cert: add more sig alg
This commit is contained in:
parent
bfc13dcebc
commit
7231438269
@ -69,6 +69,10 @@ optional = true
|
||||
version = "0.7.3"
|
||||
optional = true
|
||||
|
||||
[dependencies.hex-literal]
|
||||
version = "0.3.1"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
std = [ "simple_logger", "rand" ]
|
||||
std = [ "simple_logger", "rand", "hex-literal" ]
|
@ -4,13 +4,19 @@ use num_enum::TryFromPrimitive;
|
||||
use generic_array::GenericArray;
|
||||
|
||||
use crate::parse::parse_asn1_der_rsa_public_key;
|
||||
use crate::parse::parse_rsa_ssa_pss_parameters;
|
||||
|
||||
use crate::Error as TlsError;
|
||||
use crate::session::CertificatePublicKey;
|
||||
use crate::oid::*;
|
||||
use crate::fake_rng::FakeRandom;
|
||||
|
||||
use sha1::{Sha1, Digest};
|
||||
use sha2::{Sha224, Sha256, Sha384, Sha512};
|
||||
use rsa::{PublicKey, RSAPublicKey, PaddingScheme, BigUint, Hash};
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use heapless::{ Vec as HeaplessVec, consts::* };
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Certificate<'a> {
|
||||
@ -143,6 +149,7 @@ pub struct AlgorithmIdentifier<'a> {
|
||||
|
||||
// TODO: MOve this to impl block of Certificate
|
||||
// Verify self-signed root certificate parsed certificate
|
||||
// TODO: Remove this method, it will be replaced
|
||||
pub fn validate_root_certificate(cert: &Certificate) -> Result<bool, TlsError> {
|
||||
// Verify Signature
|
||||
match cert.signature_algorithm.algorithm {
|
||||
@ -150,10 +157,15 @@ pub fn validate_root_certificate(cert: &Certificate) -> Result<bool, TlsError> {
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(cert.tbs_certificate_encoded);
|
||||
|
||||
log::info!("Created hashed");
|
||||
|
||||
let (_, (modulus, exponent)) = parse_asn1_der_rsa_public_key(
|
||||
cert.tbs_certificate.subject_public_key_info.subject_public_key
|
||||
).map_err(|_| TlsError::ParsingError)?;
|
||||
|
||||
log::info!("Modulus: {:?}", modulus);
|
||||
log::info!("Exponent: {:?}", exponent);
|
||||
|
||||
let rsa_public_key = RSAPublicKey::new(
|
||||
BigUint::from_bytes_be(modulus),
|
||||
BigUint::from_bytes_be(exponent)
|
||||
@ -164,16 +176,17 @@ pub fn validate_root_certificate(cert: &Certificate) -> Result<bool, TlsError> {
|
||||
padding,
|
||||
&hasher.finalize(),
|
||||
cert.signature_value
|
||||
);
|
||||
Ok(verify_result.is_ok())
|
||||
}
|
||||
).unwrap();
|
||||
Ok(true)
|
||||
},
|
||||
_ => Err(TlsError::SignatureValidationError)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if self.signature_algorithm.algorithm != SHA1_WITH_RSA_ENCRYPTION {
|
||||
return Err(());
|
||||
}
|
||||
let (_, (modulus, exponent)) = parse_asn1_der_rsa_public_key(
|
||||
@ -195,25 +208,31 @@ impl<'a> Certificate<'a> {
|
||||
|
||||
// 3 possibilities: RSA_ENCRYPTION, ID_EC_PUBLIC_KEY, and EdDSA25519
|
||||
match algorithm_identifier.algorithm {
|
||||
oid::RSA_ENCRYPTION => {
|
||||
RSA_ENCRYPTION => {
|
||||
log::info!("Chose rsa encryption");
|
||||
log::info!("Entire key: {:X?}", self.tbs_certificate.subject_public_key_info.subject_public_key);
|
||||
let (_, (modulus, exponent)) = parse_asn1_der_rsa_public_key(
|
||||
self.tbs_certificate.subject_public_key_info.subject_public_key
|
||||
).map_err(|_| ())?;
|
||||
log::info!("Modulus: {:X?}\n, Exponent: {:X?}", modulus, exponent);
|
||||
|
||||
log::info!("Big int modulus: {:?}", BigUint::from_bytes_be(modulus));
|
||||
|
||||
let public_key = RSAPublicKey::new(
|
||||
BigUint::from_bytes_be(modulus),
|
||||
BigUint::from_bytes_be(exponent)
|
||||
).map_err(|_| ())?;
|
||||
log::info!("Got rsa key parts");
|
||||
Ok(
|
||||
CertificatePublicKey::RSA {
|
||||
cert_rsa_public_key: public_key
|
||||
}
|
||||
)
|
||||
},
|
||||
oid::ID_EC_PUBLIC_KEY => {
|
||||
ID_EC_PUBLIC_KEY => {
|
||||
// Check the type of EC, only support secp256r1
|
||||
// Will definitely NOT support custom curve
|
||||
if algorithm_identifier.parameters != oid::PRIME256V1 {
|
||||
if algorithm_identifier.parameters != PRIME256V1 {
|
||||
return Err(());
|
||||
}
|
||||
let p256_verify_key = p256::ecdsa::VerifyKey::from_encoded_point(
|
||||
@ -229,7 +248,7 @@ impl<'a> Certificate<'a> {
|
||||
}
|
||||
)
|
||||
},
|
||||
oid::ID_EDDSA_25519 => {
|
||||
ID_EDDSA_25519 => {
|
||||
let ed25519_public_key = ed25519_dalek::PublicKey::from_bytes(
|
||||
public_key_info.subject_public_key
|
||||
).map_err(|_| ())?;
|
||||
@ -242,55 +261,159 @@ impl<'a> Certificate<'a> {
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
// Validate certificate's signature
|
||||
// Do not be confused with TLS Certificate Verify
|
||||
pub fn validate_signature(&self) -> Result<(), TlsError> {
|
||||
let sig_alg = self.signature_algorithm.algorithm;
|
||||
|
||||
// Prepare hash value
|
||||
match sig_alg {
|
||||
SHA1_WITH_RSA_ENCRYPTION => {
|
||||
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1));
|
||||
let hashed = Sha1::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
SHA224_WITH_RSA_ENCRYPTION => {
|
||||
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_224));
|
||||
let hashed = Sha224::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
SHA256_WITH_RSA_ENCRYPTION => {
|
||||
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_256));
|
||||
let hashed = Sha256::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
SHA384_WITH_RSA_ENCRYPTION => {
|
||||
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_384));
|
||||
let hashed = Sha384::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
SHA512_WITH_RSA_ENCRYPTION => {
|
||||
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_512));
|
||||
let hashed = Sha512::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
// Further process the signature algorithm before creating digests
|
||||
// i.e. PSS, OAEP
|
||||
ID_RSASSA_PSS => {
|
||||
let (_, (hash_alg, salt_len)) = parse_rsa_ssa_pss_parameters(
|
||||
self.signature_algorithm.parameters
|
||||
).unwrap();
|
||||
match hash_alg {
|
||||
ID_SHA1 => {
|
||||
let padding = PaddingScheme::new_pss_with_salt::<Sha1, FakeRandom>(
|
||||
FakeRandom {},
|
||||
salt_len
|
||||
);
|
||||
let hashed = Sha1::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
ID_SHA224 => {
|
||||
let padding = PaddingScheme::new_pss_with_salt::<Sha224, FakeRandom>(
|
||||
FakeRandom {},
|
||||
salt_len
|
||||
);
|
||||
let hashed = Sha224::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
ID_SHA256 => {
|
||||
let padding = PaddingScheme::new_pss_with_salt::<Sha256, FakeRandom>(
|
||||
FakeRandom {},
|
||||
salt_len
|
||||
);
|
||||
let hashed = Sha256::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
ID_SHA384 => {
|
||||
let padding = PaddingScheme::new_pss_with_salt::<Sha384, FakeRandom>(
|
||||
FakeRandom {},
|
||||
salt_len
|
||||
);
|
||||
let hashed = Sha384::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
|
||||
ID_SHA512 => {
|
||||
let padding = PaddingScheme::new_pss_with_salt::<Sha512, FakeRandom>(
|
||||
FakeRandom {},
|
||||
salt_len
|
||||
);
|
||||
let hashed = Sha512::digest(self.tbs_certificate_encoded);
|
||||
let sig = self.signature_value;
|
||||
self.get_cert_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.get_rsa_public_key()
|
||||
.map_err(|_| TlsError::SignatureValidationError)?
|
||||
.verify(padding, &hashed, sig)
|
||||
.map_err(|_| TlsError::SignatureValidationError)
|
||||
},
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
_ => todo!()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Centralize OID, another OID module can be found in `parse.rs`
|
||||
mod oid {
|
||||
// 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];
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ pub mod key;
|
||||
pub mod session;
|
||||
pub mod certificate;
|
||||
pub mod fake_rng;
|
||||
pub mod oid;
|
||||
|
||||
// TODO: Implement errors
|
||||
// Details: Encapsulate smoltcp & nom errors
|
||||
|
44
src/main.rs
44
src/main.rs
@ -78,44 +78,10 @@ fn main() {
|
||||
// tls_socket.tls_connect(&mut sockets).unwrap();
|
||||
simple_logger::SimpleLogger::new().init().unwrap();
|
||||
|
||||
// let (rest, result) = parse_asn1_der_certificate(&CERTIFICATE).unwrap();
|
||||
// println!(
|
||||
// "{:X?}\n{:X?}",
|
||||
// rest,
|
||||
// result
|
||||
// );
|
||||
use rsa::RSAPublicKey;
|
||||
use rsa::BigUint;
|
||||
use rsa::PaddingScheme;
|
||||
use rsa::Hash;
|
||||
use rsa::PublicKey;
|
||||
let (_, certificate) = parse_asn1_der_certificate(&RSA_PSS_CERT).unwrap();
|
||||
|
||||
let mut rng = OsRng;
|
||||
let public_key = RSAPublicKey::new(
|
||||
BigUint::from_bytes_be(&PUBLIC_KEY),
|
||||
BigUint::from_bytes_be(&[01, 00 ,01])
|
||||
).unwrap();
|
||||
println!("{:X?}", public_key);
|
||||
certificate.validate_signature().unwrap();
|
||||
|
||||
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_pss::<sha2::Sha256, OsRng>(rng);
|
||||
println!("Sig Verify: {:?}", public_key.verify(padding, &hash, &VERIFY_SIGNATURE));
|
||||
}
|
||||
|
||||
const CLIENT_HELLO: [u8; 0xCA] = [
|
||||
@ -149,3 +115,9 @@ const SIGNATURE: [u8; 256] = [
|
||||
const VERIFY_SIGNATURE: [u8; 256] = [
|
||||
0x17, 0xfe, 0xb5, 0x33, 0xca, 0x6d, 0x00, 0x7d, 0x00, 0x58, 0x25, 0x79, 0x68, 0x42, 0x4b, 0xbc, 0x3a, 0xa6, 0x90, 0x9e, 0x9d, 0x49, 0x55, 0x75, 0x76, 0xa5, 0x20, 0xe0, 0x4a, 0x5e, 0xf0, 0x5f, 0x0e, 0x86, 0xd2, 0x4f, 0xf4, 0x3f, 0x8e, 0xb8, 0x61, 0xee, 0xf5, 0x95, 0x22, 0x8d, 0x70, 0x32, 0xaa, 0x36, 0x0f, 0x71, 0x4e, 0x66, 0x74, 0x13, 0x92, 0x6e, 0xf4, 0xf8, 0xb5, 0x80, 0x3b, 0x69, 0xe3, 0x55, 0x19, 0xe3, 0xb2, 0x3f, 0x43, 0x73, 0xdf, 0xac, 0x67, 0x87, 0x06, 0x6d, 0xcb, 0x47, 0x56, 0xb5, 0x45, 0x60, 0xe0, 0x88, 0x6e, 0x9b, 0x96, 0x2c, 0x4a, 0xd2, 0x8d, 0xab, 0x26, 0xba, 0xd1, 0xab, 0xc2, 0x59, 0x16, 0xb0, 0x9a, 0xf2, 0x86, 0x53, 0x7f, 0x68, 0x4f, 0x80, 0x8a, 0xef, 0xee, 0x73, 0x04, 0x6c, 0xb7, 0xdf, 0x0a, 0x84, 0xfb, 0xb5, 0x96, 0x7a, 0xca, 0x13, 0x1f, 0x4b, 0x1c, 0xf3, 0x89, 0x79, 0x94, 0x03, 0xa3, 0x0c, 0x02, 0xd2, 0x9c, 0xbd, 0xad, 0xb7, 0x25, 0x12, 0xdb, 0x9c, 0xec, 0x2e, 0x5e, 0x1d, 0x00, 0xe5, 0x0c, 0xaf, 0xcf, 0x6f, 0x21, 0x09, 0x1e, 0xbc, 0x4f, 0x25, 0x3c, 0x5e, 0xab, 0x01, 0xa6, 0x79, 0xba, 0xea, 0xbe, 0xed, 0xb9, 0xc9, 0x61, 0x8f, 0x66, 0x00, 0x6b, 0x82, 0x44, 0xd6, 0x62, 0x2a, 0xaa, 0x56, 0x88, 0x7c, 0xcf, 0xc6, 0x6a, 0x0f, 0x38, 0x51, 0xdf, 0xa1, 0x3a, 0x78, 0xcf, 0xf7, 0x99, 0x1e, 0x03, 0xcb, 0x2c, 0x3a, 0x0e, 0xd8, 0x7d, 0x73, 0x67, 0x36, 0x2e, 0xb7, 0x80, 0x5b, 0x00, 0xb2, 0x52, 0x4f, 0xf2, 0x98, 0xa4, 0xda, 0x48, 0x7c, 0xac, 0xde, 0xaf, 0x8a, 0x23, 0x36, 0xc5, 0x63, 0x1b, 0x3e, 0xfa, 0x93, 0x5b, 0xb4, 0x11, 0xe7, 0x53, 0xca, 0x13, 0xb0, 0x15, 0xfe, 0xc7, 0xe4, 0xa7, 0x30, 0xf1, 0x36, 0x9f, 0x9e
|
||||
];
|
||||
|
||||
const RSA_PSS_CERT: [u8; 0x3AB] =
|
||||
hex_literal::hex!("308203a73082028fa00302010202146642be8f709457f9cd6eed72051c240a5565138c300d06092a864886f70d01010a30003063310b30090603550406130255533113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464311c301a06035504030c136578616d706c652e756c666865696d2e6e6574301e170d3230313130343039313535325a170d3231313130343039313535325a3063310b30090603550406130255533113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464311c301a06035504030c136578616d706c652e756c666865696d2e6e657430820122300d06092a864886f70d01010105000382010f003082010a0282010100b5a347b654ca0bad8d56990e70aa7411b78dedc9fd9a6760ee936ea01486238538dbc4d0bc95a1a5f060b6296ba67001f103cfd918ad1ec33a1a680d4e8283a24300391e9a53cd6641fc51f0a984c3cd16542b934a0ec8c3447782542628320d6c24988cf0b7b19bbaba91f1999968def724d8e65b624fbb9826208aece1ee90badda7c6b8a97fc4085299f9d32661a06bc67d2d662e0efcee1df5b6dc1d02e56929d8976441456d0fe50314c9861e9845f75f5dc2ca9828089b5d4bd109d1e8ada8986c5bd68ee004a7bfcb932768023e11fe8e299b25b8774ed8bdbb0f644ddaa83df1ff4e84bfc18d3b815decb5ca4f1db1125df98dba94e4ef5570ec5a510203010001a3533051301d0603551d0e04160414050928eff30f3094f01ddb09f1d7a9193addf854301f0603551d23041830168014050928eff30f3094f01ddb09f1d7a9193addf854300f0603551d130101ff040530030101ff300d06092a864886f70d01010a300003820101002d14281587dc33d4559e77852d17fade1a9f3f0e5af847bde80c921be360d6e3b598dfb50aad706de3832841798b66736b9296a83c06e0078dceabc39760a5bf5eb7a7287859b22e9beb7ebb928b99034d155fd12307ee541ea53979bb8afb62db233dfcf1e16afea5eac33817b8cbb13841cb89e9b65a5a4b08a6c6e3d1e0036bc9576b90cf62437e3ef985f02b88be4e6863068c9bc45dd473763f4cdcfc3bfb8a90d7b3225b67a3a39c6ac446de55596dc135221b4383773ddd9efdcca48f389af9c1c0547e0ada1c14153fc38e02c95e4c37da45af1e6d3b0a6cafb603d95a1c887384b476caf60783835a150ee7fd22b6838ce19adcb2e59572c6349703");
|
||||
|
||||
const RSA_PKCS_CERT: [u8; 0x03AB] =
|
||||
hex_literal::hex!("308203a73082028fa00302010202144a5a52142c495ec189e661457ba0330809c9dede300d06092a864886f70d01010b05003063310b30090603550406130255533113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464311c301a06035504030c13746573742e68656c6c6f776f726c642e636f6d301e170d3230313130343038353031325a170d3231313130343038353031325a3063310b30090603550406130255533113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464311c301a06035504030c13746573742e68656c6c6f776f726c642e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100a665127e115e41937b51f87fa44d9894e52a45479a234110037f8c8ce2de6d263e12e3824d57a39d7386afe35cb926af1d6f593673eae31f1e27b8914895006fc7e5fdac11f369b73741a97663f2bb08edb7ab7c1ccc8be9259ce2c1b9d04ba066e05fd6a440ca99b148ddc95a23432228f5172b32939921f70f4f632691ee19a50d7deffb50cb9f018562c803065ca1f1817f1f93c25b3aa0ef91b2f91ef1c86fd346bc00ac165fbd5abf04d944a58e48fd24959133637a949cb85d498063aa4ed0927327591d125500430fa91782af806d46fe330251103c8139b3bf35034b009748324a0fffac2474eed6f04e8d90582dc6125cce0274305f28e82b5409170203010001a3533051301d0603551d0e04160414a36633b9660897096d8138d4f0281a3b76e6696c301f0603551d23041830168014a36633b9660897096d8138d4f0281a3b76e6696c300f0603551d130101ff040530030101ff300d06092a864886f70d01010b0500038201010090631de179bf4940e636e0e7142d9feb440d818c9ea095b6ae31a4ad9876fbd1c2b6808d2edc60e20b107daaf592d14bb9f1ca37c9d975b0c463478dbac8cb183b90bbaecdb1ad5541674f3ba957f2837e57480c445328f917c8a358fc5465c1f838108f60b59327cd1fba59e1635276372bdb17557b636b59be60b4c6b6cf3ecb9fd40b9469d7bfa4f2053be4c08e2e350453050a076d923923588c7f839c709d31c2296dfd837b850f0ba4b44a36c112b9a6ef7186b090162628367a95fa1673e4362d7a23aebd46a85c69eac76f7194d166c89ce6103c508eb970f35bf0b241cbbae5ddffc5ea6515e5f36a8645dc0c8a48798199f65f01b811bec2f287d5");
|
81
src/oid.rs
Normal file
81
src/oid.rs
Normal file
@ -0,0 +1,81 @@
|
||||
// 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];
|
||||
|
||||
// Hash OIDs
|
||||
pub const ID_SHA1: &'static [u8] =
|
||||
&[0x2B, 0x0E, 0x03, 0x02, 0x1A];
|
||||
pub const ID_SHA224: &'static [u8] =
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04];
|
||||
pub const ID_SHA256: &'static [u8] =
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01];
|
||||
pub const ID_SHA384: &'static [u8] =
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02];
|
||||
pub const ID_SHA512: &'static [u8] =
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03];
|
||||
|
||||
// Mask Generation Function (mgf1)
|
||||
pub const ID_MGF1: &'static [u8] =
|
||||
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08];
|
||||
|
||||
// Algorithm Identifier with specific parameters
|
||||
pub const ID_P_SPECIFIED: &'static [u8] =
|
||||
&[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x09];
|
||||
|
||||
// Extensions
|
||||
pub const CERT_KEY_USAGE: &'static [u8] = &[85, 29, 15]; // 2.5.29.15
|
||||
pub const CERT_POLICIES: &'static [u8] = &[85, 29, 32]; // 2.5.29.32
|
||||
pub const CERT_BASIC_CONSTRAINTS: &'static [u8] = &[85, 29, 19]; // 2.5.29.19
|
||||
pub const CERT_EXT_KEY_USAGE: &'static [u8] = &[85, 29, 37]; // 2.5.29.37
|
||||
pub const CERT_INHIBIT_ANY_POLICY: &'static [u8] = &[85, 29, 54]; // 2.5.29.54
|
||||
// Extended Key Extensions
|
||||
pub const ANY_EXTENDED_KEY_USAGE: &'static [u8] = &[85, 29, 37, 0]; // 2.5.29.37.0
|
||||
pub const ID_KP_SERVER_AUTH: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 1]; // 1.3.6.1.5.5.7.3.1
|
||||
pub const ID_KP_CLIENT_AUTH: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 2]; // 1.3.6.1.5.5.7.3.2
|
||||
pub const ID_KP_CODE_SIGNING: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 3]; // 1.3.6.1.5.5.7.3.3
|
||||
pub const ID_KP_EMAIL_PROTECTION: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 4]; // 1.3.6.1.5.5.7.3.4
|
||||
pub const ID_KP_TIME_STAMPING: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 8]; // 1.3.6.1.5.5.7.3.8
|
||||
pub const ID_KP_OCSP_SIGNING: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 9];
|
229
src/parse.rs
229
src/parse.rs
@ -26,6 +26,9 @@ use crate::certificate::{
|
||||
TBSCertificate as Asn1DerTBSCertificate,
|
||||
};
|
||||
|
||||
use crate::oid;
|
||||
use crate::oid::*;
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use core::convert::TryInto;
|
||||
|
||||
@ -650,7 +653,7 @@ pub fn parse_asn1_der_tbs_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerTBS
|
||||
subject_public_key_info, issuer_unique_id, subject_unique_id, extensions
|
||||
)) = complete(
|
||||
tuple((
|
||||
parse_asn1_der_version,
|
||||
opt(parse_asn1_der_version),
|
||||
parse_asn1_der_serial_number,
|
||||
parse_asn1_der_algorithm_identifier,
|
||||
parse_asn1_der_sequence,
|
||||
@ -659,10 +662,16 @@ pub fn parse_asn1_der_tbs_certificate(bytes: &[u8]) -> IResult<&[u8], Asn1DerTBS
|
||||
parse_asn1_der_subject_key_public_info,
|
||||
opt(parse_asn1_der_bit_string),
|
||||
opt(parse_asn1_der_bit_string),
|
||||
parse_asn1_der_extensions
|
||||
opt(parse_asn1_der_extensions)
|
||||
))
|
||||
)(value)?;
|
||||
|
||||
log::info!("Parsed tbscert");
|
||||
let version = version.unwrap_or(Asn1DerVersion::v1);
|
||||
let extensions = extensions.unwrap_or(
|
||||
Asn1DerExtensions { extensions: Vec::new() }
|
||||
);
|
||||
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerTBSCertificate {
|
||||
@ -687,7 +696,7 @@ pub fn parse_asn1_der_version(bytes: &[u8]) -> IResult<&[u8], Asn1DerVersion> {
|
||||
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)));
|
||||
return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
|
||||
}
|
||||
// Parse the encapsulated INTEGER, force completeness
|
||||
let (_, integer) = complete(parse_asn1_der_integer)(value)?;
|
||||
@ -759,13 +768,11 @@ pub fn parse_asn1_der_algorithm_identifier(bytes: &[u8]) -> IResult<&[u8], Asn1D
|
||||
if tag_val != 0x30 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
// Parse OID and then optionl parameters
|
||||
let (_, (oid, (_, _, optional_param))) = complete(
|
||||
tuple((
|
||||
parse_asn1_der_oid,
|
||||
parse_asn1_der_object
|
||||
))
|
||||
)(value)?;
|
||||
// Parse OID, leave the rest as optionl parameters
|
||||
let (optional_param, oid) = parse_asn1_der_oid(value)?;
|
||||
log::info!("OID: {:X?}", oid);
|
||||
log::info!("Optional parameter: {:X?}", optional_param);
|
||||
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerAlgId {
|
||||
@ -841,6 +848,8 @@ pub fn parse_asn1_der_subject_key_public_info(bytes: &[u8]) -> IResult<&[u8], As
|
||||
parse_asn1_der_bit_string,
|
||||
))
|
||||
)(value)?;
|
||||
log::info!("Parsed subject key alg ident: {:?}", algorithm);
|
||||
log::info!("Parsed key: {:X?}", subject_public_key);
|
||||
Ok((
|
||||
rest,
|
||||
Asn1DerSubjectPublicKeyInfo {
|
||||
@ -852,6 +861,7 @@ 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> {
|
||||
log::info!("Invoked extension parsing");
|
||||
let (rest, (tag_val, _, value)) = parse_asn1_der_object(bytes)?;
|
||||
// Verify the tag_val is indeed 0xA3
|
||||
if tag_val != 0xA3 {
|
||||
@ -1135,19 +1145,188 @@ pub fn parse_asn1_der_rsa_public_key(bytes: &[u8]) -> IResult<&[u8], (&[u8], &[u
|
||||
))
|
||||
}
|
||||
|
||||
mod oid {
|
||||
// Extensions
|
||||
pub const CERT_KEY_USAGE: &'static [u8] = &[85, 29, 15]; // 2.5.29.15
|
||||
pub const CERT_POLICIES: &'static [u8] = &[85, 29, 32]; // 2.5.29.32
|
||||
pub const CERT_BASIC_CONSTRAINTS: &'static [u8] = &[85, 29, 19]; // 2.5.29.19
|
||||
pub const CERT_EXT_KEY_USAGE: &'static [u8] = &[85, 29, 37]; // 2.5.29.37
|
||||
pub const CERT_INHIBIT_ANY_POLICY: &'static [u8] = &[85, 29, 54]; // 2.5.29.54
|
||||
// Extended Key Extensions
|
||||
pub const ANY_EXTENDED_KEY_USAGE: &'static [u8] = &[85, 29, 37, 0]; // 2.5.29.37.0
|
||||
pub const ID_KP_SERVER_AUTH: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 1]; // 1.3.6.1.5.5.7.3.1
|
||||
pub const ID_KP_CLIENT_AUTH: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 2]; // 1.3.6.1.5.5.7.3.2
|
||||
pub const ID_KP_CODE_SIGNING: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 3]; // 1.3.6.1.5.5.7.3.3
|
||||
pub const ID_KP_EMAIL_PROTECTION: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 4]; // 1.3.6.1.5.5.7.3.4
|
||||
pub const ID_KP_TIME_STAMPING: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 8]; // 1.3.6.1.5.5.7.3.8
|
||||
pub const ID_KP_OCSP_SIGNING: &'static [u8] = &[43, 6, 1, 5, 5, 7, 3, 9]; // 1.3.6.1.5.5.7.3.9
|
||||
/*
|
||||
* Prasers for PSS/OAEP signature algorithms parameters in certificate
|
||||
*/
|
||||
|
||||
// Take addition parameter of PSS algorithm idenfier
|
||||
// Return hash function OID
|
||||
pub fn parse_rsa_ssa_pss_parameters(params: &[u8]) -> IResult<&[u8], (&[u8], usize)> {
|
||||
// Handle the case where there is literally no optional parameter
|
||||
// Return default SHA1 OID and 20 salt length
|
||||
if params.len() == 0 {
|
||||
return Ok((&[], (ID_SHA1, 20)))
|
||||
}
|
||||
|
||||
// Parse as RSASSA-PSS-params (Sequence: 0x30)
|
||||
let (_, rsa_ssa_params) = complete(
|
||||
parse_asn1_der_sequence
|
||||
)(params)?;
|
||||
|
||||
let (_, (hash_alg, mgf_hash_alg, salt_len, _)) = complete(
|
||||
tuple((
|
||||
opt(parse_hash_algorithm),
|
||||
opt(parse_mask_gen_algorithm),
|
||||
opt(parse_salt_length),
|
||||
opt(parse_trailer_field)
|
||||
))
|
||||
)(params)?;
|
||||
|
||||
let hash_alg = hash_alg.unwrap_or(
|
||||
Asn1DerAlgId { algorithm: ID_SHA1, parameters: &[] }
|
||||
);
|
||||
let mgf_hash_alg = mgf_hash_alg.unwrap_or(
|
||||
Asn1DerAlgId { algorithm: ID_SHA1, parameters: &[] }
|
||||
);
|
||||
let salt_len = salt_len.unwrap_or(&[0x14]);
|
||||
|
||||
// // Parse HashAlgorithm [0]
|
||||
// let (rest, (tag_val, _, hash_alg)) = parse_asn1_der_object(rsa_ssa_params)?;
|
||||
// // Verify the tag is indeed 0xA0
|
||||
// if tag_val != 0xA0 {
|
||||
// return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
// }
|
||||
// // Parse the encapsulated algorithm identifier, force completeness
|
||||
// let (_, hash_alg) = complete(parse_asn1_der_algorithm_identifier)(hash_alg)?;
|
||||
|
||||
// // Parse MaskGenAlgorithm [1]
|
||||
// let (rest, (tag_val, _, mask_gen_alg)) = parse_asn1_der_object(rest)?;
|
||||
// // Verify the tag is indeed 0xA1
|
||||
// if tag_val != 0xA1 {
|
||||
// return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
// }
|
||||
// // Parse the encapsulated algorithm identifier, force completeness
|
||||
// let (_, mgf) = complete(parse_asn1_der_algorithm_identifier)(mask_gen_alg)?;
|
||||
// // Algorithm field of mgf should always be mgf1
|
||||
// if mgf.algorithm != ID_MGF1 {
|
||||
// todo!()
|
||||
// }
|
||||
// // Parse the parameters of MGF Alg. Ident. to get hash algorithm under MGF
|
||||
// let (_, mgf_hash_alg) = complete(parse_asn1_der_algorithm_identifier)(
|
||||
// mgf.parameters
|
||||
// )?;
|
||||
|
||||
// // Parse salt length [2]
|
||||
// let (rest, (tag_val, _, salt_len)) = parse_asn1_der_object(rest)?;
|
||||
// if tag_val != 0xA2 {
|
||||
// return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
// }
|
||||
// // Parse the encapsulated integer, force completeness
|
||||
// let (_, salt_len) = complete(
|
||||
// parse_asn1_der_integer
|
||||
// )(salt_len)?;
|
||||
|
||||
// // If there are still unprocessed data left, parse for trailer field
|
||||
// if rest.len() != 0 {
|
||||
// // Parse trailer field [3]
|
||||
// let (_, (tag_val, _, trailer_field)) = complete(
|
||||
// parse_asn1_der_object
|
||||
// )(rest)?;
|
||||
// if tag_val != 0xA3 {
|
||||
// return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
// }
|
||||
// // Parse the encapsulated integer, force completeness
|
||||
// let (_, trailer_field) = complete(
|
||||
// parse_asn1_der_integer
|
||||
// )(trailer_field)?;
|
||||
// // The value must be 1 stated in RFC 4055
|
||||
// if trailer_field.len() < 1 || trailer_field[trailer_field.len() - 1] != 1 {
|
||||
// return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
// }
|
||||
// }
|
||||
|
||||
// Verify that the hash functions listed in HashFunc and MGF are consistent
|
||||
if hash_alg.algorithm != mgf_hash_alg.algorithm {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Parse encoded salt length integer into usize
|
||||
if salt_len.len() > core::mem::size_of::<usize>() {
|
||||
todo!()
|
||||
}
|
||||
let mut array_buffer: [u8; core::mem::size_of::<usize>()] = [0; core::mem::size_of::<usize>()];
|
||||
array_buffer[(8-salt_len.len())..].clone_from_slice(salt_len);
|
||||
let salt_len = usize::from_be_bytes(array_buffer);
|
||||
|
||||
Ok((
|
||||
&[],
|
||||
(
|
||||
hash_alg.algorithm,
|
||||
salt_len
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_hash_algorithm(bytes: &[u8]) -> IResult<&[u8], Asn1DerAlgId> {
|
||||
// Parse HashAlgorithm [0]
|
||||
let (rest, (tag_val, _, hash_alg)) = parse_asn1_der_object(bytes)?;
|
||||
// Verify the tag is indeed 0xA0
|
||||
if tag_val != 0xA0 {
|
||||
return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
|
||||
}
|
||||
// Parse the encapsulated algorithm identifier, force completeness
|
||||
let (_, hash_alg) = complete(parse_asn1_der_algorithm_identifier)(hash_alg)?;
|
||||
Ok((
|
||||
rest, hash_alg
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_mask_gen_algorithm(bytes: &[u8]) -> IResult<&[u8], Asn1DerAlgId> {
|
||||
// Parse MaskGenAlgorithm [1]
|
||||
let (rest, (tag_val, _, mask_gen_alg)) = parse_asn1_der_object(bytes)?;
|
||||
// Verify the tag is indeed 0xA1
|
||||
if tag_val != 0xA1 {
|
||||
return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
|
||||
}
|
||||
// Parse the encapsulated algorithm identifier, force completeness
|
||||
let (_, mgf) = complete(parse_asn1_der_algorithm_identifier)(mask_gen_alg)?;
|
||||
// Algorithm field of mgf should always be mgf1
|
||||
if mgf.algorithm != ID_MGF1 {
|
||||
todo!()
|
||||
}
|
||||
// Parse the parameters of MGF Alg. Ident. to get hash algorithm under MGF
|
||||
let (_, mgf_hash_alg) = complete(parse_asn1_der_algorithm_identifier)(
|
||||
mgf.parameters
|
||||
)?;
|
||||
Ok((
|
||||
rest, mgf_hash_alg
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_salt_length(bytes: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
// Parse salt length [2]
|
||||
let (rest, (tag_val, _, salt_len)) = parse_asn1_der_object(bytes)?;
|
||||
if tag_val != 0xA2 {
|
||||
return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
|
||||
}
|
||||
// Parse the encapsulated integer, force completeness
|
||||
let (_, salt_len) = complete(
|
||||
parse_asn1_der_integer
|
||||
)(salt_len)?;
|
||||
|
||||
Ok((
|
||||
rest, salt_len
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_trailer_field(bytes: &[u8]) -> IResult<&[u8], ()> {
|
||||
// Parse trailer field [3]
|
||||
let (_, (tag_val, _, trailer_field)) = complete(
|
||||
parse_asn1_der_object
|
||||
)(bytes)?;
|
||||
if tag_val != 0xA3 {
|
||||
return Err(nom::Err::Error((bytes, ErrorKind::Verify)));
|
||||
}
|
||||
// Parse the encapsulated integer, force completeness
|
||||
let (_, trailer_field) = complete(
|
||||
parse_asn1_der_integer
|
||||
)(trailer_field)?;
|
||||
// The value must be 1 stated in RFC 4055
|
||||
if trailer_field.len() < 1 || trailer_field[trailer_field.len() - 1] != 1 {
|
||||
return Err(nom::Err::Failure((&[], ErrorKind::Verify)));
|
||||
}
|
||||
|
||||
Ok((
|
||||
&[], ()
|
||||
))
|
||||
}
|
||||
|
@ -1455,3 +1455,29 @@ pub(crate) enum CertificatePublicKey {
|
||||
cert_eddsa_key: ed25519_dalek::PublicKey
|
||||
}
|
||||
}
|
||||
|
||||
impl CertificatePublicKey {
|
||||
pub(crate) fn get_rsa_public_key(&self) -> Result<&RSAPublicKey, ()> {
|
||||
if let CertificatePublicKey::RSA { cert_rsa_public_key } = self {
|
||||
Ok(&cert_rsa_public_key)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
pub(crate) fn get_ecdsa_secp256r1_sha256_verify_key(&self) -> Result<&p256::ecdsa::VerifyKey, ()> {
|
||||
if let CertificatePublicKey::ECDSA_SECP256R1_SHA256 {
|
||||
cert_verify_key
|
||||
} = self {
|
||||
Ok(&cert_verify_key)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
pub(crate) fn get_ed25519_public_key(&self) -> Result<&ed25519_dalek::PublicKey, ()> {
|
||||
if let CertificatePublicKey::ED25519 { cert_eddsa_key } = self {
|
||||
Ok(&cert_eddsa_key)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user