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,7 +6,8 @@ edition = "2018"
[dependencies]
hkdf = "0.9.0"
sha2 = { version = "0.9.1", default-features = false }
sha-1 = { version = "0.9.1", default-features = false }
sha2 = { version = "0.9.1", default-features = false }
byteorder = { version = "1.3.4", default-features = false }
num_enum = { version = "0.5.1", default-features = false }
log = "0.4.11"

View File

@ -1,13 +1,21 @@
use num_enum::IntoPrimitive;
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;
#[derive(Debug, Clone)]
pub struct Certificate<'a> {
pub tbs_certificate: TBSCertificate<'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)]
@ -129,3 +137,60 @@ pub struct AlgorithmIdentifier<'a> {
pub algorithm: &'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]
#[macro_use]
extern crate alloc;
pub mod tls;
@ -15,10 +14,12 @@ use nom::error::ParseError;
// TODO: Implement errors
// Details: Encapsulate smoltcp & nom errors
#[derive(Debug, Clone)]
pub enum Error {
PropagatedError(smoltcp::Error),
ParsingError(nom::error::ErrorKind),
ParsingError,
EncryptionError,
DecryptionError,
CapacityError,
SignatureValidationError,
}

View File

@ -97,15 +97,45 @@ fn main() {
).unwrap();
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);
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_256));
println!("Sig Verify: {:?}", public_key.verify(padding, &hash, &SIGNATURE));
let padding = PaddingScheme::new_pss::<sha2::Sha256, OsRng>(rng);
println!("Sig Verify: {:?}", public_key.verify(padding, &hash, &VERIFY_SIGNATURE));
}
const CERTIFICATE: [u8; 0x325] = [
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
const CLIENT_HELLO: [u8; 0xCA] = [
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] = [

View File

@ -78,7 +78,8 @@ pub(crate) fn parse_tls_repr(bytes: &[u8]) -> IResult<&[u8], TlsRepr> {
// Diff from regular handshake:
// 1. Handshake can coalesced into a larger TLS record
// 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 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)
)
)(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)?;
@ -154,7 +165,18 @@ pub(crate) fn parse_handshake(bytes: &[u8]) -> IResult<&[u8], HandshakeRepr> {
);
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!()
}
}
@ -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> {
let extension_type = 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
let (rest, tag) = take(1_usize)(bytes)?;
// Parse length
let (rest, length_byte) = take(1_usize)(rest)?;
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 {
if length_byte[0] & 0x7F > core::mem::size_of::<usize>().try_into().unwrap() {
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];
}
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
// It is quite useless when the value slice of the exact same length is returned
// i.e. `length` can be replaced by `value.len()`
// Length: (return param) returns the length of the entire asn1_der_object
// Length of the value within the ASN.1 DER object = value.len()
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)?;
Ok((rest, (tag, length, value)))
Ok((rest, (tag, length + header_size, value)))
}
pub fn parse_asn1_der_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerCertificate> {
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(
tuple((
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
))
)(rest)?;
let (_, (_, tbs_certificate_length, _)) =
parse_asn1_der_object(tbs_certificate_encoded)?;
Ok((
excluded,
Asn1DerCertificate {
tbs_certificate,
signature_algorithm: sig_alg,
signature_value: sig_value,
tbs_certificate_encoded: &tbs_certificate_encoded[0..tbs_certificate_length]
}
))
}
// Parser for TBSCertificate (Sequence: 0x30)
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
if tag_val != 0x30 {
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
// i.e. context-specific, constructed, type [0] -> tag: A0
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
if tag_val != 0xA0 {
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
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
if tag_val != 0x02 {
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
// Public keys are always represented in bytes
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
if tag_val != 0x03 {
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
// 0x00 -> false; 0xFF -> true
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
// 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)));
}
Ok((rest, value[0] == 0xFF))
@ -620,7 +693,7 @@ pub fn parse_asn1_der_boolean(bytes: &[u8]) -> IResult<&[u8], bool> {
// SEQUENCE: tag: 0x30
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
if tag_val != 0x30 {
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)
// Encapsulates OID (alg) and optional params (params)
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
if tag_val != 0x30 {
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)
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
if tag_val != 0x06 {
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)
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
if tag_val != 0x30 {
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)
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
match tag_val {
0x17 => {
@ -712,7 +785,7 @@ pub fn parse_ans1_der_time(bytes: &[u8]) -> IResult<&[u8], Asn1DerTime> {
// Parser for SubjectKeyPublicInfo (Sequence: 0x30)
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
if tag_val != 0x30 {
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)
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
if tag_val != 0xA3 {
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
}
let (_, (tag_val, length, mut value)) = complete(
let (_, (tag_val, _, mut value)) = complete(
parse_asn1_der_object
)(value)?;
// 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)
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
if tag_val != 0x30 {
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
// 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> {
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
// 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)));
}
// Erase the padded bits
let padding = value[0];
let usage_array: [u8; 2] = if length == 2 {
let usage_array: [u8; 2] = if value.len() == 2 {
[value[1], 0]
} else {
[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)
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
if tag_val != 0x30 {
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)
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
if tag_val != 0x30 {
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)
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
if tag_val != 0x30 {
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)
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
if tag_val != 0x30 {
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)
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
if tag_val != 0x04 {
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))
}
// 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 {
// Extensions
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 generic_array::GenericArray;
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
use rsa::RSAPublicKey;
use core::convert::AsRef;
use core::cell::RefCell;
@ -50,6 +51,9 @@ pub(crate) struct Session {
// Reset to 0 on rekey AND key exchange
// TODO: Force rekey if sequence_number need to wrap
sequence_number: u64,
// Certificate public key
// For Handling CertificateVerify
cert_rsa_public_key: Option<RSAPublicKey>,
}
impl Session {
@ -73,6 +77,7 @@ impl Session {
client_nonce: None,
server_nonce: None,
sequence_number: 0,
cert_rsa_public_key: None
}
}
@ -425,11 +430,18 @@ impl Session {
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;
}
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;
}

View File

@ -30,6 +30,11 @@ use aes_gcm::aes::Aes128;
use aes_gcm::{AeadInPlace, NewAead};
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 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::buffer::TlsBuffer;
use crate::session::{Session, TlsRole};
use crate::certificate::validate_root_certificate;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(non_camel_case_types)]
@ -166,7 +172,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
// TLS Client wait for server's certificate cerify
// No need to send anything
TlsState::WAIT_CV=> {},
TlsState::WAIT_CV => {},
_ => todo!()
}
@ -359,8 +365,8 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
}
let parse_result = parse_inner_plaintext_for_handshake(&payload);
let (_, mut handshake_vec) = parse_result
.map_err(|_| Error::Unrecognized)?;
let (_, (mut handshake_slice, mut handshake_vec)) =
parse_result.map_err(|_| Error::Unrecognized)?;
// Verify that it is indeed an EE
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
// 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
// Ideas: 1. Split off WAIT_CERT_CR handling into a separate function
@ -392,7 +409,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
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();
// Instantiate associated data and decrypt
@ -408,28 +425,78 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
&mut payload
);
}
// log::info!("Decrypted payload {:?}", payload);
// Parse the certificate from TLS payload
let parse_result = parse_inner_plaintext_for_handshake(&payload);
let (_, mut handshake_vec) = parse_result
let (_, (handshake_slice, mut handshake_vec)) = parse_result
.map_err(|_| Error::Unrecognized)?;
log::info!("Decrypted certificate {:X?}", handshake_vec);
// Verify that it is indeed an Certificate
let might_be_ee = handshake_vec.remove(0);
if might_be_ee.get_msg_type() != HandshakeType::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
self.session.borrow_mut().client_update_for_wait_cert_cr();
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
let parse_result = parse_inner_plaintext_for_handshake(&payload);
let (_, mut handshake_vec) = parse_result
.map_err(|_| Error::Unrecognized)?;
// Get hash from session, validate signature
}
_ => {},
}

View File

@ -12,6 +12,8 @@ use core::convert::TryInto;
use alloc::vec::Vec;
use crate::certificate::Certificate as Asn1DerCertificate;
pub(crate) const HRR_RANDOM: [u8; 32] = [
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
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 {
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)]
@ -196,6 +211,7 @@ pub(crate) enum HandshakeData<'a> {
ServerHello(ServerHello<'a>),
EncryptedExtensions(EncryptedExtensions),
Certificate(Certificate<'a>),
CertificateVerify(CertificateVerify<'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)]
pub(crate) struct CertificateEntry<'a> {
pub(crate) certificate_entry_info: CertificateEntryInfo<'a>,
@ -675,6 +705,12 @@ pub(crate) struct CertificateEntry<'a> {
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)]
pub(crate) struct Certificate<'a> {
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: 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],
}