cert: rewrite key handling

This commit is contained in:
occheung 2020-11-03 17:02:26 +08:00
parent c57fc79f6b
commit bfc13dcebc
3 changed files with 130 additions and 18 deletions

View File

@ -1,8 +1,11 @@
use num_enum::IntoPrimitive;
use num_enum::TryFromPrimitive;
use generic_array::GenericArray;
use crate::parse::parse_asn1_der_rsa_public_key;
use crate::Error as TlsError;
use crate::session::CertificatePublicKey;
use sha1::{Sha1, Digest};
use rsa::{PublicKey, RSAPublicKey, PaddingScheme, BigUint, Hash};
@ -182,10 +185,112 @@ impl<'a> Certificate<'a> {
BigUint::from_bytes_be(exponent)
).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 {
// ECDSA signature algorithms
pub const SHA1_WITH_RSA_ENCRYPTION: &'static [u8] = &[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05];
// RSA public key
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];
}

View File

@ -57,12 +57,13 @@ pub(crate) struct Session {
// Sequence number: Start from 0, 64 bits
// Increment by one per record processed (read OR write)
// 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,
server_sequence_number: u64,
// Certificate public key
// 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 {
@ -93,7 +94,8 @@ impl Session {
server_application_nonce: None,
client_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
// These 2 algorithms have a mandated hash function
if signature_algorithm == SignatureScheme::ecdsa_secp256r1_sha256
{
if signature_algorithm == SignatureScheme::ecdsa_secp256r1_sha256 {
todo!()
}
@ -1441,4 +1442,16 @@ 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
}
}

View File

@ -286,8 +286,8 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
// Process TLS ingress during handshake
// The slice should ONLY include handshake overhead
// i.e. No 5 bytes of TLS Record
// YES 4 bytes of HandshakeRepr, everything within the same handshake
// i.e. Exclude 5 bytes of TLS Record
// Include 4 bytes of HandshakeRepr, everything within the same handshake
fn process(&self, handshake_slice: &[u8], mut repr: TlsRepr) -> Result<()> {
// Change_cipher_spec check:
// Must receive CCS before recv peer's FINISH message
@ -409,18 +409,12 @@ impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
todo!()
}
// This is indeed a desirable ServerHello TLS repr
// 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();
// Get slice without reserialization
let mut session = self.session.borrow_mut();
session.client_update_for_sh(
selected_cipher.unwrap(),
server_public.unwrap(),
&slice[5..]
handshake_slice
);
// Key exchange occurred, seq_num is set to 0
// Do NOT update seq_num again. Early return.