cert: add key verify

This commit is contained in:
occheung 2020-10-28 17:33:00 +08:00
parent 1261b36b8f
commit 0042fea902
8 changed files with 378 additions and 57 deletions

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
hkdf = "0.9.0" hkdf = "0.9.0"
sha-1 = { version = "0.9.1", default-features = false }
sha2 = { version = "0.9.1", default-features = false } sha2 = { version = "0.9.1", default-features = false }
byteorder = { version = "1.3.4", default-features = false } byteorder = { version = "1.3.4", default-features = false }
num_enum = { version = "0.5.1", default-features = false } num_enum = { version = "0.5.1", default-features = false }

View File

@ -1,13 +1,21 @@
use num_enum::IntoPrimitive; use num_enum::IntoPrimitive;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use crate::parse::parse_asn1_der_object;
use crate::parse::parse_asn1_der_rsa_public_key;
use crate::Error as TlsError;
use sha1::{Sha1, Digest};
use rsa::{PublicKey, RSAPublicKey, PaddingScheme, BigUint, Hash};
use alloc::vec::Vec; use alloc::vec::Vec;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Certificate<'a> { pub struct Certificate<'a> {
pub tbs_certificate: TBSCertificate<'a>, pub tbs_certificate: TBSCertificate<'a>,
pub signature_algorithm: AlgorithmIdentifier<'a>, pub signature_algorithm: AlgorithmIdentifier<'a>,
pub signature_value: &'a [u8] pub signature_value: &'a [u8],
pub tbs_certificate_encoded: &'a [u8],
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -129,3 +137,60 @@ pub struct AlgorithmIdentifier<'a> {
pub algorithm: &'a [u8], pub algorithm: &'a [u8],
pub parameters: &'a [u8], pub parameters: &'a [u8],
} }
// TODO: MOve this to impl block of Certificate
// Verify self-signed root certificate parsed certificate
pub fn validate_root_certificate(cert: &Certificate) -> Result<bool, TlsError> {
// Verify Signature
match cert.signature_algorithm.algorithm {
SHA1_WITH_RSA_ENCRYPTION => {
let mut hasher = Sha1::new();
hasher.update(cert.tbs_certificate_encoded);
// TODO: invoke method to get public key
let (_, (modulus, exponent)) = parse_asn1_der_rsa_public_key(
cert.tbs_certificate.subject_public_key_info.subject_public_key
).map_err(|_| TlsError::ParsingError)?;
let rsa_public_key = RSAPublicKey::new(
BigUint::from_bytes_be(modulus),
BigUint::from_bytes_be(exponent)
).map_err(|_| TlsError::SignatureValidationError)?;
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1));
let verify_result = rsa_public_key.verify(
padding,
&hasher.finalize(),
cert.signature_value
);
log::info!("Verification result: {:?}", verify_result);
Ok(verify_result.is_ok())
}
_ => {
todo!()
}
}
}
impl<'a> Certificate<'a> {
// Return the public key, if used for RSA
pub fn return_rsa_public_key(&self) -> Result<RSAPublicKey, ()> {
if self.signature_algorithm.algorithm != oid::SHA1_WITH_RSA_ENCRYPTION {
return Err(());
}
let (_, (modulus, exponent)) = parse_asn1_der_rsa_public_key(
self.tbs_certificate.subject_public_key_info.subject_public_key
).map_err(|_| ())?;
RSAPublicKey::new(
BigUint::from_bytes_be(modulus),
BigUint::from_bytes_be(exponent)
).map_err(|_| ())
}
}
mod oid {
// ECDSA signature algorithms
pub const SHA1_WITH_RSA_ENCRYPTION: &'static [u8] = &[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05];
}

View File

@ -1,6 +1,5 @@
#![no_std] #![no_std]
#[macro_use]
extern crate alloc; extern crate alloc;
pub mod tls; pub mod tls;
@ -15,10 +14,12 @@ use nom::error::ParseError;
// TODO: Implement errors // TODO: Implement errors
// Details: Encapsulate smoltcp & nom errors // Details: Encapsulate smoltcp & nom errors
#[derive(Debug, Clone)]
pub enum Error { pub enum Error {
PropagatedError(smoltcp::Error), PropagatedError(smoltcp::Error),
ParsingError(nom::error::ErrorKind), ParsingError,
EncryptionError, EncryptionError,
DecryptionError, DecryptionError,
CapacityError, CapacityError,
SignatureValidationError,
} }

View File

@ -97,15 +97,45 @@ fn main() {
).unwrap(); ).unwrap();
println!("{:X?}", public_key); println!("{:X?}", public_key);
let hash = sha2::Sha256::new().chain(&CERTIFICATE[4..(0x209+8)]).finalize(); let transcript_hash = sha2::Sha256::new()
.chain(&CLIENT_HELLO)
.chain(&SERVER_HELLO)
.chain(&ENCRYPTED_EXTENSION)
.chain(&CERTIFICATE)
.finalize();
println!("Transcript: {:X?}", transcript_hash);
let hash = sha2::Sha256::new()
.chain(&MANY20)
.chain(&CONTEXT_STRING)
.chain(&SINGLE_ZERO_BYTE)
.chain(&transcript_hash)
.finalize();
println!("Hash: {:X?}", hash); println!("Hash: {:X?}", hash);
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_256)); let padding = PaddingScheme::new_pss::<sha2::Sha256, OsRng>(rng);
println!("Sig Verify: {:?}", public_key.verify(padding, &hash, &SIGNATURE)); println!("Sig Verify: {:?}", public_key.verify(padding, &hash, &VERIFY_SIGNATURE));
} }
const CERTIFICATE: [u8; 0x325] = [ const CLIENT_HELLO: [u8; 0xCA] = [
0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x15, 0x5a, 0x92, 0xad, 0xc2, 0x04, 0x8f, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x80, 0x36, 0x06, 0xba, 0xe7, 0x47, 0x6b, 0x08, 0x94, 0x04, 0xec, 0xa7, 0xb6, 0x91, 0x04, 0x3f, 0xf7, 0x92, 0xbc, 0x19, 0xee, 0xfb, 0x7d, 0x74, 0xd7, 0xa8, 0x0d, 0x00, 0x1e, 0x7b, 0x4b, 0x3a, 0x4a, 0xe6, 0x0f, 0xe8, 0xc0, 0x71, 0xfc, 0x73, 0xe7, 0x02, 0x4c, 0x0d, 0xbc, 0xf4, 0xbd, 0xd1, 0x1d, 0x39, 0x6b, 0xba, 0x70, 0x46, 0x4a, 0x13, 0xe9, 0x4a, 0xf8, 0x3d, 0xf3, 0xe1, 0x09, 0x59, 0x54, 0x7b, 0xc9, 0x55, 0xfb, 0x41, 0x2d, 0xa3, 0x76, 0x52, 0x11, 0xe1, 0xf3, 0xdc, 0x77, 0x6c, 0xaa, 0x53, 0x37, 0x6e, 0xca, 0x3a, 0xec, 0xbe, 0xc3, 0xaa, 0xb7, 0x3b, 0x31, 0xd5, 0x6c, 0xb6, 0x52, 0x9c, 0x80, 0x98, 0xbc, 0xc9, 0xe0, 0x28, 0x18, 0xe2, 0x0b, 0xf7, 0xf8, 0xa0, 0x3a, 0xfd, 0x17, 0x04, 0x50, 0x9e, 0xce, 0x79, 0xbd, 0x9f, 0x39, 0xf1, 0xea, 0x69, 0xec, 0x47, 0x97, 0x2e, 0x83, 0x0f, 0xb5, 0xca, 0x95, 0xde, 0x95, 0xa1, 0xe6, 0x04, 0x22, 0xd5, 0xee, 0xbe, 0x52, 0x79, 0x54, 0xa1, 0xe7, 0xbf, 0x8a, 0x86, 0xf6, 0x46, 0x6d, 0x0d, 0x9f, 0x16, 0x95, 0x1a, 0x4c, 0xf7, 0xa0, 0x46, 0x92, 0x59, 0x5c, 0x13, 0x52, 0xf2, 0x54, 0x9e, 0x5a, 0xfb, 0x4e, 0xbf, 0xd7, 0x7a, 0x37, 0x95, 0x01, 0x44, 0xe4, 0xc0, 0x26, 0x87, 0x4c, 0x65, 0x3e, 0x40, 0x7d, 0x7d, 0x23, 0x07, 0x44, 0x01, 0xf4, 0x84, 0xff, 0xd0, 0x8f, 0x7a, 0x1f, 0xa0, 0x52, 0x10, 0xd1, 0xf4, 0xf0, 0xd5, 0xce, 0x79, 0x70, 0x29, 0x32, 0xe2, 0xca, 0xbe, 0x70, 0x1f, 0xdf, 0xad, 0x6b, 0x4b, 0xb7, 0x11, 0x01, 0xf4, 0x4b, 0xad, 0x66, 0x6a, 0x11, 0x13, 0x0f, 0xe2, 0xee, 0x82, 0x9e, 0x4d, 0x02, 0x9d, 0xc9, 0x1c, 0xdd, 0x67, 0x16, 0xdb, 0xb9, 0x06, 0x18, 0x86, 0xed, 0xc1, 0xba, 0x94, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x89, 0x4f, 0xde, 0x5b, 0xcc, 0x69, 0xe2, 0x52, 0xcf, 0x3e, 0xa3, 0x00, 0xdf, 0xb1, 0x97, 0xb8, 0x1d, 0xe1, 0xc1, 0x46, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0x16, 0x45, 0xa6, 0x9a, 0x2e, 0x37, 0x79, 0xe4, 0xf6, 0xdd, 0x27, 0x1a, 0xba, 0x1c, 0x0b, 0xfd, 0x6c, 0xd7, 0x55, 0x99, 0xb5, 0xe7, 0xc3, 0x6e, 0x53, 0x3e, 0xff, 0x36, 0x59, 0x08, 0x43, 0x24, 0xc9, 0xe7, 0xa5, 0x04, 0x07, 0x9d, 0x39, 0xe0, 0xd4, 0x29, 0x87, 0xff, 0xe3, 0xeb, 0xdd, 0x09, 0xc1, 0xcf, 0x1d, 0x91, 0x44, 0x55, 0x87, 0x0b, 0x57, 0x1d, 0xd1, 0x9b, 0xdf, 0x1d, 0x24, 0xf8, 0xbb, 0x9a, 0x11, 0xfe, 0x80, 0xfd, 0x59, 0x2b, 0xa0, 0x39, 0x8c, 0xde, 0x11, 0xe2, 0x65, 0x1e, 0x61, 0x8c, 0xe5, 0x98, 0xfa, 0x96, 0xe5, 0x37, 0x2e, 0xef, 0x3d, 0x24, 0x8a, 0xfd, 0xe1, 0x74, 0x63, 0xeb, 0xbf, 0xab, 0xb8, 0xe4, 0xd1, 0xab, 0x50, 0x2a, 0x54, 0xec, 0x00, 0x64, 0xe9, 0x2f, 0x78, 0x19, 0x66, 0x0d, 0x3f, 0x27, 0xcf, 0x20, 0x9e, 0x66, 0x7f, 0xce, 0x5a, 0xe2, 0xe4, 0xac, 0x99, 0xc7, 0xc9, 0x38, 0x18, 0xf8, 0xb2, 0x51, 0x07, 0x22, 0xdf, 0xed, 0x97, 0xf3, 0x2e, 0x3e, 0x93, 0x49, 0xd4, 0xc6, 0x6c, 0x9e, 0xa6, 0x39, 0x6d, 0x74, 0x44, 0x62, 0xa0, 0x6b, 0x42, 0xc6, 0xd5, 0xba, 0x68, 0x8e, 0xac, 0x3a, 0x01, 0x7b, 0xdd, 0xfc, 0x8e, 0x2c, 0xfc, 0xad, 0x27, 0xcb, 0x69, 0xd3, 0xcc, 0xdc, 0xa2, 0x80, 0x41, 0x44, 0x65, 0xd3, 0xae, 0x34, 0x8c, 0xe0, 0xf3, 0x4a, 0xb2, 0xfb, 0x9c, 0x61, 0x83, 0x71, 0x31, 0x2b, 0x19, 0x10, 0x41, 0x64, 0x1c, 0x23, 0x7f, 0x11, 0xa5, 0xd6, 0x5c, 0x84, 0x4f, 0x04, 0x04, 0x84, 0x99, 0x38, 0x71, 0x2b, 0x95, 0x9e, 0xd6, 0x85, 0xbc, 0x5c, 0x5d, 0xd6, 0x45, 0xed, 0x19, 0x90, 0x94, 0x73, 0x40, 0x29, 0x26, 0xdc, 0xb4, 0x0e, 0x34, 0x69, 0xa1, 0x59, 0x41, 0xe8, 0xe2, 0xcc, 0xa8, 0x4b, 0xb6, 0x08, 0x46, 0x36, 0xa0 0x01, 0x00, 0x00, 0xc6, 0x03, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x06, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0x01, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x18, 0x00, 0x16, 0x00, 0x00, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x35, 0x80, 0x72, 0xd6, 0x36, 0x58, 0x80, 0xd1, 0xae, 0xea, 0x32, 0x9a, 0xdf, 0x91, 0x21, 0x38, 0x38, 0x51, 0xed, 0x21, 0xa2, 0x8e, 0x3b, 0x75, 0xe9, 0x65, 0xd0, 0xd2, 0xcd, 0x16, 0x62, 0x54, 0x00, 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04
];
const SERVER_HELLO: [u8; 0x7A] = [
0x02, 0x00, 0x00, 0x76, 0x03, 0x03, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x20, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04
];
const ENCRYPTED_EXTENSION: [u8; 6] = [0x08, 0x00, 0x00, 0x02, 0x00, 0x00];
const MANY20: [u8; 64] = [0x20; 64];
const CONTEXT_STRING: &'static str = "TLS 1.3, server CertificateVerify";
const SINGLE_ZERO_BYTE: [u8; 1] = [0];
const CERTIFICATE: [u8; 818] = [
0x0b, 0x00, 0x03, 0x2e, 0x00, 0x00, 0x03, 0x2a, 0x00, 0x03, 0x25, 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x09, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x15, 0x5a, 0x92, 0xad, 0xc2, 0x04, 0x8f, 0x90, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x30, 0x30, 0x35, 0x30, 0x31, 0x33, 0x38, 0x31, 0x37, 0x5a, 0x30, 0x2b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69, 0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0x80, 0x36, 0x06, 0xba, 0xe7, 0x47, 0x6b, 0x08, 0x94, 0x04, 0xec, 0xa7, 0xb6, 0x91, 0x04, 0x3f, 0xf7, 0x92, 0xbc, 0x19, 0xee, 0xfb, 0x7d, 0x74, 0xd7, 0xa8, 0x0d, 0x00, 0x1e, 0x7b, 0x4b, 0x3a, 0x4a, 0xe6, 0x0f, 0xe8, 0xc0, 0x71, 0xfc, 0x73, 0xe7, 0x02, 0x4c, 0x0d, 0xbc, 0xf4, 0xbd, 0xd1, 0x1d, 0x39, 0x6b, 0xba, 0x70, 0x46, 0x4a, 0x13, 0xe9, 0x4a, 0xf8, 0x3d, 0xf3, 0xe1, 0x09, 0x59, 0x54, 0x7b, 0xc9, 0x55, 0xfb, 0x41, 0x2d, 0xa3, 0x76, 0x52, 0x11, 0xe1, 0xf3, 0xdc, 0x77, 0x6c, 0xaa, 0x53, 0x37, 0x6e, 0xca, 0x3a, 0xec, 0xbe, 0xc3, 0xaa, 0xb7, 0x3b, 0x31, 0xd5, 0x6c, 0xb6, 0x52, 0x9c, 0x80, 0x98, 0xbc, 0xc9, 0xe0, 0x28, 0x18, 0xe2, 0x0b, 0xf7, 0xf8, 0xa0, 0x3a, 0xfd, 0x17, 0x04, 0x50, 0x9e, 0xce, 0x79, 0xbd, 0x9f, 0x39, 0xf1, 0xea, 0x69, 0xec, 0x47, 0x97, 0x2e, 0x83, 0x0f, 0xb5, 0xca, 0x95, 0xde, 0x95, 0xa1, 0xe6, 0x04, 0x22, 0xd5, 0xee, 0xbe, 0x52, 0x79, 0x54, 0xa1, 0xe7, 0xbf, 0x8a, 0x86, 0xf6, 0x46, 0x6d, 0x0d, 0x9f, 0x16, 0x95, 0x1a, 0x4c, 0xf7, 0xa0, 0x46, 0x92, 0x59, 0x5c, 0x13, 0x52, 0xf2, 0x54, 0x9e, 0x5a, 0xfb, 0x4e, 0xbf, 0xd7, 0x7a, 0x37, 0x95, 0x01, 0x44, 0xe4, 0xc0, 0x26, 0x87, 0x4c, 0x65, 0x3e, 0x40, 0x7d, 0x7d, 0x23, 0x07, 0x44, 0x01, 0xf4, 0x84, 0xff, 0xd0, 0x8f, 0x7a, 0x1f, 0xa0, 0x52, 0x10, 0xd1, 0xf4, 0xf0, 0xd5, 0xce, 0x79, 0x70, 0x29, 0x32, 0xe2, 0xca, 0xbe, 0x70, 0x1f, 0xdf, 0xad, 0x6b, 0x4b, 0xb7, 0x11, 0x01, 0xf4, 0x4b, 0xad, 0x66, 0x6a, 0x11, 0x13, 0x0f, 0xe2, 0xee, 0x82, 0x9e, 0x4d, 0x02, 0x9d, 0xc9, 0x1c, 0xdd, 0x67, 0x16, 0xdb, 0xb9, 0x06, 0x18, 0x86, 0xed, 0xc1, 0xba, 0x94, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x52, 0x30, 0x50, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x89, 0x4f, 0xde, 0x5b, 0xcc, 0x69, 0xe2, 0x52, 0xcf, 0x3e, 0xa3, 0x00, 0xdf, 0xb1, 0x97, 0xb8, 0x1d, 0xe1, 0xc1, 0x46, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x59, 0x16, 0x45, 0xa6, 0x9a, 0x2e, 0x37, 0x79, 0xe4, 0xf6, 0xdd, 0x27, 0x1a, 0xba, 0x1c, 0x0b, 0xfd, 0x6c, 0xd7, 0x55, 0x99, 0xb5, 0xe7, 0xc3, 0x6e, 0x53, 0x3e, 0xff, 0x36, 0x59, 0x08, 0x43, 0x24, 0xc9, 0xe7, 0xa5, 0x04, 0x07, 0x9d, 0x39, 0xe0, 0xd4, 0x29, 0x87, 0xff, 0xe3, 0xeb, 0xdd, 0x09, 0xc1, 0xcf, 0x1d, 0x91, 0x44, 0x55, 0x87, 0x0b, 0x57, 0x1d, 0xd1, 0x9b, 0xdf, 0x1d, 0x24, 0xf8, 0xbb, 0x9a, 0x11, 0xfe, 0x80, 0xfd, 0x59, 0x2b, 0xa0, 0x39, 0x8c, 0xde, 0x11, 0xe2, 0x65, 0x1e, 0x61, 0x8c, 0xe5, 0x98, 0xfa, 0x96, 0xe5, 0x37, 0x2e, 0xef, 0x3d, 0x24, 0x8a, 0xfd, 0xe1, 0x74, 0x63, 0xeb, 0xbf, 0xab, 0xb8, 0xe4, 0xd1, 0xab, 0x50, 0x2a, 0x54, 0xec, 0x00, 0x64, 0xe9, 0x2f, 0x78, 0x19, 0x66, 0x0d, 0x3f, 0x27, 0xcf, 0x20, 0x9e, 0x66, 0x7f, 0xce, 0x5a, 0xe2, 0xe4, 0xac, 0x99, 0xc7, 0xc9, 0x38, 0x18, 0xf8, 0xb2, 0x51, 0x07, 0x22, 0xdf, 0xed, 0x97, 0xf3, 0x2e, 0x3e, 0x93, 0x49, 0xd4, 0xc6, 0x6c, 0x9e, 0xa6, 0x39, 0x6d, 0x74, 0x44, 0x62, 0xa0, 0x6b, 0x42, 0xc6, 0xd5, 0xba, 0x68, 0x8e, 0xac, 0x3a, 0x01, 0x7b, 0xdd, 0xfc, 0x8e, 0x2c, 0xfc, 0xad, 0x27, 0xcb, 0x69, 0xd3, 0xcc, 0xdc, 0xa2, 0x80, 0x41, 0x44, 0x65, 0xd3, 0xae, 0x34, 0x8c, 0xe0, 0xf3, 0x4a, 0xb2, 0xfb, 0x9c, 0x61, 0x83, 0x71, 0x31, 0x2b, 0x19, 0x10, 0x41, 0x64, 0x1c, 0x23, 0x7f, 0x11, 0xa5, 0xd6, 0x5c, 0x84, 0x4f, 0x04, 0x04, 0x84, 0x99, 0x38, 0x71, 0x2b, 0x95, 0x9e, 0xd6, 0x85, 0xbc, 0x5c, 0x5d, 0xd6, 0x45, 0xed, 0x19, 0x90, 0x94, 0x73, 0x40, 0x29, 0x26, 0xdc, 0xb4, 0x0e, 0x34, 0x69, 0xa1, 0x59, 0x41, 0xe8, 0xe2, 0xcc, 0xa8, 0x4b, 0xb6, 0x08, 0x46, 0x36, 0xa0, 0x00, 0x00
]; ];
const PUBLIC_KEY: [u8; 256] = [ const PUBLIC_KEY: [u8; 256] = [

View File

@ -78,7 +78,8 @@ pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], TlsRepr> {
// Diff from regular handshake: // Diff from regular handshake:
// 1. Handshake can coalesced into a larger TLS record // 1. Handshake can coalesced into a larger TLS record
// 2. Content type and zero paddings at the end // 2. Content type and zero paddings at the end
pub(crate) fn parse_inner_plaintext_for_handshake(bytes: &[u8]) -> IResult<&[u8], Vec<HandshakeRepr>> { // Return handshake slice for hashing
pub(crate) fn parse_inner_plaintext_for_handshake(bytes: &[u8]) -> IResult<&[u8], (&[u8], Vec<HandshakeRepr>)> {
let mut remaining_bytes = bytes; let mut remaining_bytes = bytes;
let mut handshake_vec: Vec<HandshakeRepr> = Vec::new(); let mut handshake_vec: Vec<HandshakeRepr> = Vec::new();
@ -97,7 +98,17 @@ pub(crate) fn parse_inner_plaintext_for_handshake(bytes: &[u8]) -> IResult<&[u8]
take_till(|byte| byte != 0x00) take_till(|byte| byte != 0x00)
) )
)(remaining_bytes)?; )(remaining_bytes)?;
return Ok((&[], handshake_vec)); return Ok((
&[],
(
// A concatenation of all handshakes received
// The remaining content_type byte and zero paddings are stripped
&bytes[
..(bytes.len()-remaining_bytes.len())
],
handshake_vec
)
));
} }
let (rem, handshake_repr) = parse_handshake(remaining_bytes)?; let (rem, handshake_repr) = parse_handshake(remaining_bytes)?;
@ -154,7 +165,18 @@ pub(crate) fn parse_handshake(bytes: &[u8]) -> IResult<&[u8], HandshakeRepr> {
); );
Ok((rest, repr)) Ok((rest, repr))
} },
CertificateVerify => {
// Parse CertificateVerify
let (rest, handshake_data) = parse_certificate_verify(
rest
)?;
repr.handshake_data = HandshakeData::CertificateVerify(
handshake_data
);
Ok((rest, repr))
},
_ => todo!() _ => todo!()
} }
} }
@ -351,6 +373,33 @@ fn parse_handshake_certificate_entry_info(bytes: &[u8]) -> IResult<&[u8], (u32,
)) ))
} }
fn parse_certificate_verify(bytes: &[u8]) -> IResult<&[u8], CertificateVerify> {
let signature_scheme = take(2_usize);
let signature_length = take(2_usize);
let (rest, (signature_scheme, signature_length)) = tuple((
signature_scheme,
signature_length
))(bytes)?;
let signature_scheme = SignatureScheme::try_from(
NetworkEndian::read_u16(signature_scheme)
).unwrap();
let signature_length = NetworkEndian::read_u16(signature_length);
let (_, signature) = complete(
take(signature_length)
)(rest)?;
Ok((
&[],
CertificateVerify {
algorithm: signature_scheme,
signature_length,
signature
}
))
}
fn parse_extension(bytes: &[u8], handshake_type: HandshakeType) -> IResult<&[u8], Extension> { fn parse_extension(bytes: &[u8], handshake_type: HandshakeType) -> IResult<&[u8], Extension> {
let extension_type = take(2_usize); let extension_type = take(2_usize);
let length = take(2_usize); let length = take(2_usize);
@ -468,13 +517,18 @@ fn parse_extension(bytes: &[u8], handshake_type: HandshakeType) -> IResult<&[u8]
)) ))
} }
pub fn parse_asn1_der_header(bytes: &[u8]) -> IResult<&[u8], (u8, usize)> { // Parse tag and length
// Return remaining bytes, tag (as byte), indicated length,
// and header (tag + length field) length
pub fn parse_asn1_der_header(bytes: &[u8]) -> IResult<&[u8], (u8, usize, usize)> {
// Parse tag // Parse tag
let (rest, tag) = take(1_usize)(bytes)?; let (rest, tag) = take(1_usize)(bytes)?;
// Parse length // Parse length
let (rest, length_byte) = take(1_usize)(rest)?; let (rest, length_byte) = take(1_usize)(rest)?;
if length_byte[0] <= 0x7F { if length_byte[0] <= 0x7F {
Ok((rest, (tag[0], length_byte[0].into()))) // Header length is 2 bytes
// Tag: 1; Length: 1
Ok((rest, (tag[0], length_byte[0].into(), 2)))
} else { } else {
if length_byte[0] & 0x7F > core::mem::size_of::<usize>().try_into().unwrap() { if length_byte[0] & 0x7F > core::mem::size_of::<usize>().try_into().unwrap() {
return Err(nom::Err::Failure((length_byte, ErrorKind::TooLarge))); return Err(nom::Err::Failure((length_byte, ErrorKind::TooLarge)));
@ -487,21 +541,35 @@ pub fn parse_asn1_der_header(bytes: &[u8]) -> IResult<&[u8], (u8, usize)> {
length_array[array_index + 8 - length_slice.len()] = length_slice[array_index]; length_array[array_index + 8 - length_slice.len()] = length_slice[array_index];
} }
let (_, length_array) = length_array.split_at(8 - core::mem::size_of::<usize>()); let (_, length_array) = length_array.split_at(8 - core::mem::size_of::<usize>());
Ok((rem, (tag[0], usize::from_be_bytes((*length_array).try_into().unwrap()))))
// Header length:
// Tag: 1; Length: long_form_indic (1) + size of length (length_size)
Ok((
rem,
(
tag[0],
usize::from_be_bytes((*length_array).try_into().unwrap()),
1 + 1 + usize::try_from(length_size).unwrap()
)
))
} }
} }
// TODO: Not return length // Length: (return param) returns the length of the entire asn1_der_object
// It is quite useless when the value slice of the exact same length is returned // Length of the value within the ASN.1 DER object = value.len()
// i.e. `length` can be replaced by `value.len()`
pub fn parse_asn1_der_object(bytes: &[u8]) -> IResult<&[u8], (u8, usize, &[u8])> { pub fn parse_asn1_der_object(bytes: &[u8]) -> IResult<&[u8], (u8, usize, &[u8])> {
let (rest, (tag, length)) = parse_asn1_der_header(bytes)?; let (rest, (tag, length, header_size)) = parse_asn1_der_header(bytes)?;
let (rest, value) = take(length)(rest)?; let (rest, value) = take(length)(rest)?;
Ok((rest, (tag, length, value))) Ok((rest, (tag, length + header_size, value)))
} }
pub fn parse_asn1_der_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerCertificate> { pub fn parse_asn1_der_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerCertificate> {
let (excluded, (_, _, rest)) = parse_asn1_der_object(bytes)?; let (excluded, (_, _, rest)) = parse_asn1_der_object(bytes)?;
// Return encoded TBS certificate in ASN1 DER
// For convenience of validation
let tbs_certificate_encoded = rest;
let (_, (tbs_certificate, sig_alg, sig_value)) = complete( let (_, (tbs_certificate, sig_alg, sig_value)) = complete(
tuple(( tuple((
parse_asn1_der_tbs_certificate, parse_asn1_der_tbs_certificate,
@ -509,19 +577,24 @@ pub fn parse_asn1_der_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerCertifi
parse_asn1_der_bit_string parse_asn1_der_bit_string
)) ))
)(rest)?; )(rest)?;
let (_, (_, tbs_certificate_length, _)) =
parse_asn1_der_object(tbs_certificate_encoded)?;
Ok(( Ok((
excluded, excluded,
Asn1DerCertificate { Asn1DerCertificate {
tbs_certificate, tbs_certificate,
signature_algorithm: sig_alg, signature_algorithm: sig_alg,
signature_value: sig_value, signature_value: sig_value,
tbs_certificate_encoded: &tbs_certificate_encoded[0..tbs_certificate_length]
} }
)) ))
} }
// Parser for TBSCertificate (Sequence: 0x30) // Parser for TBSCertificate (Sequence: 0x30)
pub fn parse_asn1_der_tbs_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerTBSCertificate> { pub fn parse_asn1_der_tbs_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerTBSCertificate> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag is indeed 0x30 // Verify the tag is indeed 0x30
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -566,7 +639,7 @@ pub fn parse_asn1_der_tbs_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerTBS
// Version encapsulates an Integer // Version encapsulates an Integer
// i.e. context-specific, constructed, type [0] -> tag: A0 // i.e. context-specific, constructed, type [0] -> tag: A0
pub fn parse_asn1_der_version(bytes: &[u8]) -> IResult<&[u8], Asn1DerVersion> { pub fn parse_asn1_der_version(bytes: &[u8]) -> IResult<&[u8], Asn1DerVersion> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag is indeed 0xA0 // Verify the tag is indeed 0xA0
if tag_val != 0xA0 { if tag_val != 0xA0 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -579,7 +652,7 @@ pub fn parse_asn1_der_version(bytes: &[u8]) -> IResult<&[u8], Asn1DerVersion> {
// INTEGER: tag: 0x02 // INTEGER: tag: 0x02
pub fn parse_asn1_der_integer(bytes: &[u8]) -> IResult<&[u8], &[u8]> { pub fn parse_asn1_der_integer(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag is indeed 0x02 // Verify the tag is indeed 0x02
if tag_val != 0x02 { if tag_val != 0x02 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -591,7 +664,7 @@ pub fn parse_asn1_der_integer(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
// Assumption: No unused bits at the last byte // Assumption: No unused bits at the last byte
// Public keys are always represented in bytes // Public keys are always represented in bytes
pub fn parse_asn1_der_bit_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> { pub fn parse_asn1_der_bit_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag is indeed 0x03 // Verify the tag is indeed 0x03
if tag_val != 0x03 { if tag_val != 0x03 {
return Err(nom::Err::Error((bytes, ErrorKind::Verify))); return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
@ -609,10 +682,10 @@ pub fn parse_asn1_der_bit_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
// Length should be 1 // Length should be 1
// 0x00 -> false; 0xFF -> true // 0x00 -> false; 0xFF -> true
pub fn parse_asn1_der_boolean(bytes: &[u8]) -> IResult<&[u8], bool> { pub fn parse_asn1_der_boolean(bytes: &[u8]) -> IResult<&[u8], bool> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag is indeed 0x01 and the length is 1 // Verify the tag is indeed 0x01 and the length is 1
// The value should be 0x00 or 0xFF // The value should be 0x00 or 0xFF
if tag_val != 0x01 || length != 1 || (value[0] != 0x00 && value[0] != 0xFF) { if tag_val != 0x01 || value.len() != 1 || (value[0] != 0x00 && value[0] != 0xFF) {
return Err(nom::Err::Error((bytes, ErrorKind::Verify))); return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
} }
Ok((rest, value[0] == 0xFF)) Ok((rest, value[0] == 0xFF))
@ -620,7 +693,7 @@ pub fn parse_asn1_der_boolean(bytes: &[u8]) -> IResult<&[u8], bool> {
// SEQUENCE: tag: 0x30 // SEQUENCE: tag: 0x30
pub fn parse_asn1_der_sequence(bytes: &[u8]) -> IResult<&[u8], &[u8]> { pub fn parse_asn1_der_sequence(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag is indeed 0x03 // Verify the tag is indeed 0x03
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -636,7 +709,7 @@ pub fn parse_asn1_der_serial_number(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
// Algorithm Identifier: Sequence -> universal, constructed, 0 (0x30) // Algorithm Identifier: Sequence -> universal, constructed, 0 (0x30)
// Encapsulates OID (alg) and optional params (params) // Encapsulates OID (alg) and optional params (params)
pub fn parse_asn1_der_algorithm_identifier(bytes: &[u8]) -> IResult<&[u8], Asn1DerAlgId> { pub fn parse_asn1_der_algorithm_identifier(bytes: &[u8]) -> IResult<&[u8], Asn1DerAlgId> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val is indeed 0x30 // Verify the tag_val is indeed 0x30
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -659,7 +732,7 @@ pub fn parse_asn1_der_algorithm_identifier(bytes: &[u8]) -> IResult<&[u8], Asn1D
// Parser for Universal OID type (0x06) // Parser for Universal OID type (0x06)
pub fn parse_asn1_der_oid(bytes: &[u8]) -> IResult<&[u8], &[u8]> { pub fn parse_asn1_der_oid(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val is indeed 0x06 // Verify the tag_val is indeed 0x06
if tag_val != 0x06 { if tag_val != 0x06 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -669,7 +742,7 @@ pub fn parse_asn1_der_oid(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
// Parser for Time Validity Sequence Structure (0x30) // Parser for Time Validity Sequence Structure (0x30)
pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], Asn1DerValidity> { pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], Asn1DerValidity> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val is indeed 0x30 // Verify the tag_val is indeed 0x30
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -691,7 +764,7 @@ pub fn parse_asn1_der_validity(bytes: &[u8]) -> IResult<&[u8], Asn1DerValidity>
// Parser for Time Representation (0x17: UTCTime, 0x18: GeneralizedTime) // Parser for Time Representation (0x17: UTCTime, 0x18: GeneralizedTime)
pub fn parse_ans1_der_time(bytes: &[u8]) -> IResult<&[u8], Asn1DerTime> { pub fn parse_ans1_der_time(bytes: &[u8]) -> IResult<&[u8], Asn1DerTime> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Handle UTCTime, Gen.Time and Invalid Tag values // Handle UTCTime, Gen.Time and Invalid Tag values
match tag_val { match tag_val {
0x17 => { 0x17 => {
@ -712,7 +785,7 @@ pub fn parse_ans1_der_time(bytes: &[u8]) -> IResult<&[u8], Asn1DerTime> {
// Parser for SubjectKeyPublicInfo (Sequence: 0x30) // Parser for SubjectKeyPublicInfo (Sequence: 0x30)
pub fn parse_asn1_der_subject_key_public_info(bytes: &[u8]) -> IResult<&[u8], Asn1DerSubjectPublicKeyInfo> { pub fn parse_asn1_der_subject_key_public_info(bytes: &[u8]) -> IResult<&[u8], Asn1DerSubjectPublicKeyInfo> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val is indeed 0x30 // Verify the tag_val is indeed 0x30
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -734,13 +807,13 @@ pub fn parse_asn1_der_subject_key_public_info(bytes: &[u8]) -> IResult<&[u8], As
// Parser for extensions (Context-specific Sequence: 0xA3, then universal Sequence: 0x30) // Parser for extensions (Context-specific Sequence: 0xA3, then universal Sequence: 0x30)
pub fn parse_asn1_der_extensions(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensions> { pub fn parse_asn1_der_extensions(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensions> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val is indeed 0xA3 // Verify the tag_val is indeed 0xA3
if tag_val != 0xA3 { if tag_val != 0xA3 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
} }
let (_, (tag_val, length, mut value)) = complete( let (_, (tag_val, _, mut value)) = complete(
parse_asn1_der_object parse_asn1_der_object
)(value)?; )(value)?;
// Verify the tag_val is indeed 0x30 // Verify the tag_val is indeed 0x30
@ -763,7 +836,7 @@ pub fn parse_asn1_der_extensions(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensio
// Parser for an extension (Sequence: 0x30) // Parser for an extension (Sequence: 0x30)
pub fn parse_asn1_der_extension(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtension> { pub fn parse_asn1_der_extension(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtension> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val is indeed 0x30 // Verify the tag_val is indeed 0x30
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -825,15 +898,15 @@ pub fn parse_asn1_der_extension(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtension
// Parser for KeyUsage Extension, may have bit padding // Parser for KeyUsage Extension, may have bit padding
// Do not use parse_asn1_der_bit_string, that assumes no bit padding // Do not use parse_asn1_der_bit_string, that assumes no bit padding
pub fn parse_asn1_der_key_usage(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> { pub fn parse_asn1_der_key_usage(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify the tag_val represents a bitstring, and it must have length 2 // Verify the tag_val represents a bitstring, and it must have length 2
// i.e. bit-padding | bit-string // i.e. bit-padding | bit-string
if tag_val != 0x03 || (length != 2 && length != 3) { if tag_val != 0x03 || (value.len() != 2 && value.len() != 3) {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
} }
// Erase the padded bits // Erase the padded bits
let padding = value[0]; let padding = value[0];
let usage_array: [u8; 2] = if length == 2 { let usage_array: [u8; 2] = if value.len() == 2 {
[value[1], 0] [value[1], 0]
} else { } else {
[value[1], value[2]] [value[1], value[2]]
@ -849,7 +922,7 @@ pub fn parse_asn1_der_key_usage(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtension
// Parser for CertificatePolicies Extension (sequence: 0x30) // Parser for CertificatePolicies Extension (sequence: 0x30)
pub fn parse_asn1_der_certificate_policies(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> { pub fn parse_asn1_der_certificate_policies(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> {
let (rest, (tag_val, length, mut value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, mut value)) = parse_asn1_der_object(bytes)?;
// Verify tag value // Verify tag value
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -873,7 +946,7 @@ pub fn parse_asn1_der_certificate_policies(bytes: &[u8]) -> IResult<&[u8], Asn1D
// Parser for PolicyInformation (Sequence: 0x30) // Parser for PolicyInformation (Sequence: 0x30)
pub fn parse_asn1_der_policy_information(bytes: &[u8]) -> IResult<&[u8], Asn1DerPolicyInformation> { pub fn parse_asn1_der_policy_information(bytes: &[u8]) -> IResult<&[u8], Asn1DerPolicyInformation> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify tag value // Verify tag value
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -897,7 +970,7 @@ pub fn parse_asn1_der_policy_information(bytes: &[u8]) -> IResult<&[u8], Asn1Der
// Parser for BasicConstraints (Sequence: 0x30) // Parser for BasicConstraints (Sequence: 0x30)
pub fn parse_asn1_der_basic_constraints(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> { pub fn parse_asn1_der_basic_constraints(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify tag value // Verify tag value
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -929,7 +1002,7 @@ pub fn parse_asn1_der_basic_constraints(bytes: &[u8]) -> IResult<&[u8], Asn1DerE
// Parser for Extended Key Usage Extension (Sequence: 0x30) // Parser for Extended Key Usage Extension (Sequence: 0x30)
pub fn parse_asn1_der_extended_key_usage(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> { pub fn parse_asn1_der_extended_key_usage(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtensionValue> {
let (rest, (tag_val, length, mut value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, mut value)) = parse_asn1_der_object(bytes)?;
// Verify tag value // Verify tag value
if tag_val != 0x30 { if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -986,7 +1059,7 @@ pub fn parse_inhibit_any_policy(bytes: &[u8]) -> IResult<&[u8], Asn1DerExtension
// Parser for octet string (tag: 0x04) // Parser for octet string (tag: 0x04)
pub fn parse_asn1_der_octet_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> { pub fn parse_asn1_der_octet_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
let (rest, (tag_val, length, value)) = parse_asn1_der_object(bytes)?; let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
// Verify tag value // Verify tag value
if tag_val != 0x04 { if tag_val != 0x04 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify))); return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
@ -994,6 +1067,29 @@ pub fn parse_asn1_der_octet_string(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
Ok((rest, value)) Ok((rest, value))
} }
// Take ASN.1 DER encoded public key
// Return a slice of modulus, and a slice of exponent
// Construct numeric value by wrapping rsa::BigUint with the return values
pub fn parse_asn1_der_rsa_public_key(bytes: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
// RSA Public key is a sequence of 2 integers
let (_, (tag_val, _, value)) = complete(parse_asn1_der_object)(bytes)?;
// Verify tag value
if tag_val != 0x30 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
}
let (_, (modulus, exponent)) = complete(
tuple((
parse_asn1_der_integer,
parse_asn1_der_integer
))
)(value)?;
Ok((
&[],
(modulus, exponent)
))
}
mod oid { mod oid {
// Extensions // Extensions
pub const CERT_KEY_USAGE: &'static [u8] = &[85, 29, 15]; // 2.5.29.15 pub const CERT_KEY_USAGE: &'static [u8] = &[85, 29, 15]; // 2.5.29.15

View File

@ -8,6 +8,7 @@ use ccm::Ccm;
use hkdf::Hkdf; use hkdf::Hkdf;
use generic_array::GenericArray; use generic_array::GenericArray;
use byteorder::{ByteOrder, NetworkEndian, BigEndian}; use byteorder::{ByteOrder, NetworkEndian, BigEndian};
use rsa::RSAPublicKey;
use core::convert::AsRef; use core::convert::AsRef;
use core::cell::RefCell; use core::cell::RefCell;
@ -50,6 +51,9 @@ pub(crate) struct Session {
// 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
sequence_number: u64, sequence_number: u64,
// Certificate public key
// For Handling CertificateVerify
cert_rsa_public_key: Option<RSAPublicKey>,
} }
impl Session { impl Session {
@ -73,6 +77,7 @@ impl Session {
client_nonce: None, client_nonce: None,
server_nonce: None, server_nonce: None,
sequence_number: 0, sequence_number: 0,
cert_rsa_public_key: None
} }
} }
@ -425,11 +430,18 @@ impl Session {
self.sequence_number = 0; self.sequence_number = 0;
} }
pub(crate) fn client_update_for_ee(&mut self) { pub(crate) fn client_update_for_ee(&mut self, ee_slice: &[u8]) {
self.hash.update(ee_slice);
self.state = TlsState::WAIT_CERT_CR; self.state = TlsState::WAIT_CERT_CR;
} }
pub(crate) fn client_update_for_wait_cert_cr(&mut self) { pub(crate) fn client_update_for_wait_cert_cr(
&mut self,
cert_slice: &[u8],
cert_rsa_public_key: RSAPublicKey
) {
self.hash.update(cert_slice);
self.cert_rsa_public_key.replace(cert_rsa_public_key);
self.state = TlsState::WAIT_CV; self.state = TlsState::WAIT_CV;
} }

View File

@ -30,6 +30,11 @@ use aes_gcm::aes::Aes128;
use aes_gcm::{AeadInPlace, NewAead}; use aes_gcm::{AeadInPlace, NewAead};
use sha2::{Sha256, Sha384, Sha512, Digest}; use sha2::{Sha256, Sha384, Sha512, Digest};
use nom::bytes::complete::take;
use nom::IResult;
use nom::error::make_error;
use nom::error::ErrorKind;
use alloc::vec::{ self, Vec }; use alloc::vec::{ self, Vec };
use crate::Error as TlsError; use crate::Error as TlsError;
@ -37,6 +42,7 @@ use crate::tls_packet::*;
use crate::parse::{ parse_tls_repr, parse_handshake, parse_inner_plaintext_for_handshake }; use crate::parse::{ parse_tls_repr, parse_handshake, parse_inner_plaintext_for_handshake };
use crate::buffer::TlsBuffer; use crate::buffer::TlsBuffer;
use crate::session::{Session, TlsRole}; use crate::session::{Session, TlsRole};
use crate::certificate::validate_root_certificate;
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -359,8 +365,8 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
} }
let parse_result = parse_inner_plaintext_for_handshake(&payload); let parse_result = parse_inner_plaintext_for_handshake(&payload);
let (_, mut handshake_vec) = parse_result let (_, (mut handshake_slice, mut handshake_vec)) =
.map_err(|_| Error::Unrecognized)?; parse_result.map_err(|_| Error::Unrecognized)?;
// Verify that it is indeed an EE // Verify that it is indeed an EE
let might_be_ee = handshake_vec.remove(0); let might_be_ee = handshake_vec.remove(0);
@ -373,7 +379,18 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
// Practically, nothing will be done about cookies/server name // Practically, nothing will be done about cookies/server name
// Extension processing is therefore skipped // Extension processing is therefore skipped
self.session.borrow_mut().client_update_for_ee(); // Update hash of the session, get EE by taking appropriate length of data
let (handshake_slice, ee_slice) =
take::<_, _, (&[u8], ErrorKind)>(
might_be_ee.length + 4
)(handshake_slice)
.map_err(|_| Error::Unrecognized)?;
self.session.borrow_mut()
.client_update_for_ee(
&ee_slice
);
// TODO: Handle in WAIT_CERT_CR if there are still unprocessed handshakes // TODO: Handle in WAIT_CERT_CR if there are still unprocessed handshakes
// Ideas: 1. Split off WAIT_CERT_CR handling into a separate function // Ideas: 1. Split off WAIT_CERT_CR handling into a separate function
@ -392,7 +409,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
todo!() todo!()
} }
// Pull out the `payload` from TlsRepr, decrypt as EE // Pull out the `payload` from TlsRepr, decrypt as CERT
let mut payload = repr.payload.take().unwrap(); let mut payload = repr.payload.take().unwrap();
// Instantiate associated data and decrypt // Instantiate associated data and decrypt
@ -408,28 +425,78 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
&mut payload &mut payload
); );
} }
// log::info!("Decrypted payload {:?}", payload);
// Parse the certificate from TLS payload
let parse_result = parse_inner_plaintext_for_handshake(&payload);
let (_, (handshake_slice, mut handshake_vec)) = parse_result
.map_err(|_| Error::Unrecognized)?;
// Verify that it is indeed an Certificate
let might_be_cert = handshake_vec.remove(0);
if might_be_cert.get_msg_type() != HandshakeType::Certificate {
// Process the other handshakes in "handshake_vec"
todo!()
}
// TODO: Process Certificate
let cert = might_be_cert.get_asn1_der_certificate().unwrap();
log::info!("Certificate Acquisition");
log::info!("Validation {:?}",
validate_root_certificate(cert)
);
// Update session TLS state to WAIT_CV
let (handshake_slice, cert_slice) =
take::<_, _, (&[u8], ErrorKind)>(
might_be_cert.length + 4
)(handshake_slice)
.map_err(|_| Error::Unrecognized)?;
self.session.borrow_mut()
.client_update_for_wait_cert_cr(
&cert_slice,
cert.return_rsa_public_key().unwrap()
);
},
// In this stage, server will eventually send a CertificateVerify
// Verify that the signature is indeed correct
TlsState::WAIT_CV => {
// CertificateVerify is disguised as Application Data
if !repr.is_application_data() {
// Abort communication, this affect IV calculation
todo!()
}
// Pull out the `payload` from TlsRepr, decrypt as CV
// Keep 1 copy to update hash
let mut payload = repr.payload.take().unwrap();
let cert_slice = payload.clone();
// Instantiate associated data and decrypt
let mut array: [u8; 5] = [0; 5];
let mut buffer = TlsBuffer::new(&mut array);
buffer.write_u8(repr.content_type.into())?;
buffer.write_u16(repr.version.into())?;
buffer.write_u16(repr.length)?;
let associated_data: &[u8] = buffer.into();
{
self.session.borrow_mut().decrypt_in_place(
associated_data,
&mut payload
);
}
// Parse the certificate from TLS payload // Parse the certificate from TLS payload
let parse_result = parse_inner_plaintext_for_handshake(&payload); let parse_result = parse_inner_plaintext_for_handshake(&payload);
let (_, mut handshake_vec) = parse_result let (_, mut handshake_vec) = parse_result
.map_err(|_| Error::Unrecognized)?; .map_err(|_| Error::Unrecognized)?;
log::info!("Decrypted certificate {:X?}", handshake_vec); // Get hash from session, validate signature
// Verify that it is indeed an Certificate
let might_be_ee = handshake_vec.remove(0);
if might_be_ee.get_msg_type() != HandshakeType::Certificate {
// Process the other handshakes in "handshake_vec"
todo!()
} }
// TODO: Process Certificate
// Update session TLS state to WAIT_CV
self.session.borrow_mut().client_update_for_wait_cert_cr();
},
_ => {}, _ => {},
} }

View File

@ -12,6 +12,8 @@ use core::convert::TryInto;
use alloc::vec::Vec; use alloc::vec::Vec;
use crate::certificate::Certificate as Asn1DerCertificate;
pub(crate) const HRR_RANDOM: [u8; 32] = [ pub(crate) const HRR_RANDOM: [u8; 32] = [
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
@ -162,6 +164,19 @@ impl<'a, 'b> HandshakeRepr<'a> {
pub(crate) fn get_msg_type(&self) -> HandshakeType { pub(crate) fn get_msg_type(&self) -> HandshakeType {
self.msg_type self.msg_type
} }
pub(crate) fn get_asn1_der_certificate(&self) -> Result<&Asn1DerCertificate, ()> {
if self.msg_type != HandshakeType::Certificate {
return Err(())
};
if let HandshakeData::Certificate(
cert
) = &self.handshake_data {
Ok(cert.get_certificate(0))
} else {
Err(())
}
}
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)] #[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
@ -196,6 +211,7 @@ pub(crate) enum HandshakeData<'a> {
ServerHello(ServerHello<'a>), ServerHello(ServerHello<'a>),
EncryptedExtensions(EncryptedExtensions), EncryptedExtensions(EncryptedExtensions),
Certificate(Certificate<'a>), Certificate(Certificate<'a>),
CertificateVerify(CertificateVerify<'a>),
} }
impl<'a> HandshakeData<'a> { impl<'a> HandshakeData<'a> {
@ -668,6 +684,20 @@ pub(crate) enum CertificateEntryInfo<'a> {
} }
} }
impl<'a> CertificateEntryInfo<'a> {
pub(crate) fn get_certificate(&self) -> &Asn1DerCertificate {
match self {
CertificateEntryInfo::RawPublicKey {
ASN1_subjectPublicKeyInfo_length,
ASN1_subjectPublicKeyInfo
} => todo!(),
CertificateEntryInfo::X509 {
cert_data_length, cert_data
} => &cert_data
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct CertificateEntry<'a> { pub(crate) struct CertificateEntry<'a> {
pub(crate) certificate_entry_info: CertificateEntryInfo<'a>, pub(crate) certificate_entry_info: CertificateEntryInfo<'a>,
@ -675,6 +705,12 @@ pub(crate) struct CertificateEntry<'a> {
pub(crate) extensions: Vec<Extension>, pub(crate) extensions: Vec<Extension>,
} }
impl<'a> CertificateEntry<'a> {
pub(crate) fn get_certificate(&self) -> &Asn1DerCertificate {
self.certificate_entry_info.get_certificate()
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct Certificate<'a> { pub(crate) struct Certificate<'a> {
pub(crate) certificate_request_context_length: u8, // 0 length unless responding to CERT_REQUEST pub(crate) certificate_request_context_length: u8, // 0 length unless responding to CERT_REQUEST
@ -682,3 +718,16 @@ pub(crate) struct Certificate<'a> {
pub(crate) certificate_list_length: u32, // Only 24 bits pub(crate) certificate_list_length: u32, // Only 24 bits
pub(crate) certificate_list: Vec<CertificateEntry<'a>>, pub(crate) certificate_list: Vec<CertificateEntry<'a>>,
} }
impl<'a> Certificate<'a> {
pub(crate) fn get_certificate(&self, index: usize) -> &Asn1DerCertificate {
self.certificate_list[index].get_certificate()
}
}
#[derive(Debug, Clone)]
pub(crate) struct CertificateVerify<'a> {
pub(crate) algorithm: SignatureScheme,
pub(crate) signature_length: u16,
pub(crate) signature: &'a [u8],
}