cert: rewrite key handling
This commit is contained in:
parent
c57fc79f6b
commit
bfc13dcebc
@ -1,8 +1,11 @@
|
|||||||
use num_enum::IntoPrimitive;
|
use num_enum::IntoPrimitive;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
|
||||||
|
use generic_array::GenericArray;
|
||||||
|
|
||||||
use crate::parse::parse_asn1_der_rsa_public_key;
|
use crate::parse::parse_asn1_der_rsa_public_key;
|
||||||
use crate::Error as TlsError;
|
use crate::Error as TlsError;
|
||||||
|
use crate::session::CertificatePublicKey;
|
||||||
|
|
||||||
use sha1::{Sha1, Digest};
|
use sha1::{Sha1, Digest};
|
||||||
use rsa::{PublicKey, RSAPublicKey, PaddingScheme, BigUint, Hash};
|
use rsa::{PublicKey, RSAPublicKey, PaddingScheme, BigUint, Hash};
|
||||||
@ -182,10 +185,112 @@ impl<'a> Certificate<'a> {
|
|||||||
BigUint::from_bytes_be(exponent)
|
BigUint::from_bytes_be(exponent)
|
||||||
).map_err(|_| ())
|
).map_err(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// General return public key method
|
||||||
|
// TODO: Replace return_rsa_public_key() with this method
|
||||||
|
// Things to change: session.rs: client_update_for_wait_cert_cr
|
||||||
|
pub(crate) fn get_cert_public_key(&self) -> Result<CertificatePublicKey, ()> {
|
||||||
|
let public_key_info = &self.tbs_certificate.subject_public_key_info;
|
||||||
|
let algorithm_identifier = &public_key_info.algorithm;
|
||||||
|
|
||||||
|
// 3 possibilities: RSA_ENCRYPTION, ID_EC_PUBLIC_KEY, and EdDSA25519
|
||||||
|
match algorithm_identifier.algorithm {
|
||||||
|
oid::RSA_ENCRYPTION => {
|
||||||
|
let (_, (modulus, exponent)) = parse_asn1_der_rsa_public_key(
|
||||||
|
self.tbs_certificate.subject_public_key_info.subject_public_key
|
||||||
|
).map_err(|_| ())?;
|
||||||
|
|
||||||
|
let public_key = RSAPublicKey::new(
|
||||||
|
BigUint::from_bytes_be(modulus),
|
||||||
|
BigUint::from_bytes_be(exponent)
|
||||||
|
).map_err(|_| ())?;
|
||||||
|
Ok(
|
||||||
|
CertificatePublicKey::RSA {
|
||||||
|
cert_rsa_public_key: public_key
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
oid::ID_EC_PUBLIC_KEY => {
|
||||||
|
// Check the type of EC, only support secp256r1
|
||||||
|
// Will definitely NOT support custom curve
|
||||||
|
if algorithm_identifier.parameters != oid::PRIME256V1 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let p256_verify_key = p256::ecdsa::VerifyKey::from_encoded_point(
|
||||||
|
&p256::EncodedPoint::from_untagged_bytes(
|
||||||
|
GenericArray::from_slice(
|
||||||
|
&public_key_info.subject_public_key[1..]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).map_err(|_| ())?;
|
||||||
|
Ok(
|
||||||
|
CertificatePublicKey::ECDSA_SECP256R1_SHA256 {
|
||||||
|
cert_verify_key: p256_verify_key
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
oid::ID_EDDSA_25519 => {
|
||||||
|
let ed25519_public_key = ed25519_dalek::PublicKey::from_bytes(
|
||||||
|
public_key_info.subject_public_key
|
||||||
|
).map_err(|_| ())?;
|
||||||
|
Ok(
|
||||||
|
CertificatePublicKey::ED25519 {
|
||||||
|
cert_eddsa_key: ed25519_public_key
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Centralize OID, another OID module can be found in `parse.rs`
|
||||||
mod oid {
|
mod oid {
|
||||||
// ECDSA signature algorithms
|
// RSA public key
|
||||||
pub const SHA1_WITH_RSA_ENCRYPTION: &'static [u8] = &[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05];
|
pub const RSA_ENCRYPTION: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01];
|
||||||
|
|
||||||
|
// EC public key for secp256r1
|
||||||
|
pub const ID_EC_PUBLIC_KEY: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01];
|
||||||
|
pub const PRIME256V1: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
|
||||||
|
|
||||||
|
// EDDSA25519 public key, signature algorithm
|
||||||
|
pub const ID_EDDSA_25519: &'static [u8] =
|
||||||
|
&[0x2B, 0x65, 0x70];
|
||||||
|
|
||||||
|
// Supported Signature Algorithm (RFC 4055, RFC 3279)
|
||||||
|
// PKCS #1 v1.5
|
||||||
|
pub const SHA1_WITH_RSA_ENCRYPTION: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05];
|
||||||
|
pub const SHA224_WITH_RSA_ENCRYPTION: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E];
|
||||||
|
pub const SHA256_WITH_RSA_ENCRYPTION: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B];
|
||||||
|
pub const SHA384_WITH_RSA_ENCRYPTION: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C];
|
||||||
|
pub const SHA512_WITH_RSA_ENCRYPTION: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D];
|
||||||
|
|
||||||
|
// RSASSA_PSS
|
||||||
|
pub const ID_RSASSA_PSS: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0A];
|
||||||
|
|
||||||
|
// RSAES_OAEP
|
||||||
|
pub const ID_RSAES_OAEP: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x07];
|
||||||
|
|
||||||
|
// ECDSA signature algorithms, from OID repo
|
||||||
|
pub const ECDSA_WITH_SHA1: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01];
|
||||||
|
pub const ECDSA_WITH_SHA224: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01];
|
||||||
|
pub const ECDSA_WITH_SHA256: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02];
|
||||||
|
pub const ECDSA_WITH_SHA384: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03];
|
||||||
|
pub const ECDSA_WITH_SHA512: &'static [u8] =
|
||||||
|
&[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +57,13 @@ pub(crate) struct Session {
|
|||||||
// Sequence number: Start from 0, 64 bits
|
// Sequence number: Start from 0, 64 bits
|
||||||
// Increment by one per record processed (read OR write)
|
// Increment by one per record processed (read OR write)
|
||||||
// Reset to 0 on rekey AND key exchange
|
// Reset to 0 on rekey AND key exchange
|
||||||
// TODO: Force rekey if sequence number need to wrap
|
// TODO: Force rekey if sequence number need to wrap (very low priority)
|
||||||
client_sequence_number: u64,
|
client_sequence_number: u64,
|
||||||
server_sequence_number: u64,
|
server_sequence_number: u64,
|
||||||
// Certificate public key
|
// Certificate public key
|
||||||
// For Handling CertificateVerify
|
// For Handling CertificateVerify
|
||||||
cert_rsa_public_key: Option<RSAPublicKey>,
|
cert_rsa_public_key: Option<RSAPublicKey>, // TODO: Replace and remove
|
||||||
|
cert_public_key: Option<CertificatePublicKey>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
@ -93,7 +94,8 @@ impl Session {
|
|||||||
server_application_nonce: None,
|
server_application_nonce: None,
|
||||||
client_sequence_number: 0,
|
client_sequence_number: 0,
|
||||||
server_sequence_number: 0,
|
server_sequence_number: 0,
|
||||||
cert_rsa_public_key: None
|
cert_rsa_public_key: None, // TODO: Remove over-specific public key
|
||||||
|
cert_public_key: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,8 +502,7 @@ impl Session {
|
|||||||
|
|
||||||
// Handle Ed25519 and p256 separately
|
// Handle Ed25519 and p256 separately
|
||||||
// These 2 algorithms have a mandated hash function
|
// These 2 algorithms have a mandated hash function
|
||||||
if signature_algorithm == SignatureScheme::ecdsa_secp256r1_sha256
|
if signature_algorithm == SignatureScheme::ecdsa_secp256r1_sha256 {
|
||||||
{
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1442,3 +1443,15 @@ impl Cipher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) enum CertificatePublicKey {
|
||||||
|
RSA {
|
||||||
|
cert_rsa_public_key: RSAPublicKey
|
||||||
|
},
|
||||||
|
ECDSA_SECP256R1_SHA256 {
|
||||||
|
cert_verify_key: p256::ecdsa::VerifyKey
|
||||||
|
},
|
||||||
|
ED25519 {
|
||||||
|
cert_eddsa_key: ed25519_dalek::PublicKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
14
src/tls.rs
14
src/tls.rs
@ -286,8 +286,8 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
|||||||
|
|
||||||
// Process TLS ingress during handshake
|
// Process TLS ingress during handshake
|
||||||
// The slice should ONLY include handshake overhead
|
// The slice should ONLY include handshake overhead
|
||||||
// i.e. No 5 bytes of TLS Record
|
// i.e. Exclude 5 bytes of TLS Record
|
||||||
// YES 4 bytes of HandshakeRepr, everything within the same handshake
|
// Include 4 bytes of HandshakeRepr, everything within the same handshake
|
||||||
fn process(&self, handshake_slice: &[u8], mut repr: TlsRepr) -> Result<()> {
|
fn process(&self, handshake_slice: &[u8], mut repr: TlsRepr) -> Result<()> {
|
||||||
// Change_cipher_spec check:
|
// Change_cipher_spec check:
|
||||||
// Must receive CCS before recv peer's FINISH message
|
// Must receive CCS before recv peer's FINISH message
|
||||||
@ -409,18 +409,12 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is indeed a desirable ServerHello TLS repr
|
// Get slice without reserialization
|
||||||
// Reprocess ServerHello into a slice
|
|
||||||
// Update session with required parameter
|
|
||||||
let mut array = [0; 512];
|
|
||||||
let mut buffer = TlsBuffer::new(&mut array);
|
|
||||||
buffer.enqueue_tls_repr(repr)?;
|
|
||||||
let slice: &[u8] = buffer.into();
|
|
||||||
let mut session = self.session.borrow_mut();
|
let mut session = self.session.borrow_mut();
|
||||||
session.client_update_for_sh(
|
session.client_update_for_sh(
|
||||||
selected_cipher.unwrap(),
|
selected_cipher.unwrap(),
|
||||||
server_public.unwrap(),
|
server_public.unwrap(),
|
||||||
&slice[5..]
|
handshake_slice
|
||||||
);
|
);
|
||||||
// Key exchange occurred, seq_num is set to 0
|
// Key exchange occurred, seq_num is set to 0
|
||||||
// Do NOT update seq_num again. Early return.
|
// Do NOT update seq_num again. Early return.
|
||||||
|
Loading…
Reference in New Issue
Block a user