On the bright side, it passes my one test cases. On the down side, I think it's possibly deeply flawed.

This commit is contained in:
2017-12-27 15:25:18 -08:00
parent 1b32487511
commit 8e83ed65d4
2 changed files with 61 additions and 47 deletions

View File

@@ -8,7 +8,14 @@ chrono = "^0.4.0"
num = "^0.1.40" num = "^0.1.40"
sha-1 = "^0.7.0" sha-1 = "^0.7.0"
sha2 = "^0.7.0" sha2 = "^0.7.0"
simple_asn1 = { path = "../simple_asn1" } simple_asn1 = "^0.1.0"
simple_rsa = { path = "../simple_rsa" }
[dev-dependencies] [dev-dependencies]
quickcheck = "^0.4.1" quickcheck = "^0.4.1"
[profile.dev]
opt-level = 1
[profile.test]
opt-level = 1

View File

@@ -5,11 +5,15 @@ extern crate num;
extern crate quickcheck; extern crate quickcheck;
#[macro_use] #[macro_use]
extern crate simple_asn1; extern crate simple_asn1;
extern crate simple_rsa;
use chrono::{DateTime,Utc}; use chrono::{DateTime,Utc};
use num::{BigUint,ToPrimitive}; use num::{BigUint,ToPrimitive};
use simple_asn1::{ASN1Block,ASN1Class,FromASN1,FromASN1WithBody,OID,ToASN1}; use simple_asn1::{ASN1Block,ASN1Class,FromASN1,FromASN1WithBody,OID,ToASN1};
use simple_asn1::{ASN1DecodeErr,ASN1EncodeErr,der_decode}; use simple_asn1::{ASN1DecodeErr,ASN1EncodeErr,der_decode};
use simple_rsa::{RSAPublicKey,RSAError,SigningHash,
SIGNING_HASH_SHA1, SIGNING_HASH_SHA224, SIGNING_HASH_SHA256,
SIGNING_HASH_SHA384, SIGNING_HASH_SHA512};
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
enum HashAlgorithm { None, MD2, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 } enum HashAlgorithm { None, MD2, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }
@@ -17,16 +21,16 @@ enum HashAlgorithm { None, MD2, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
enum PubKeyAlgorithm { RSA, RSAPSS, DSA, EC, DH, Unknown(OID) } enum PubKeyAlgorithm { RSA, RSAPSS, DSA, EC, DH, Unknown(OID) }
#[derive(Clone,Debug,PartialEq)] #[derive(Debug)]
enum X509ParseError { enum X509ParseError {
ASN1DecodeError(ASN1DecodeErr), ASN1DecodeError(ASN1DecodeErr), RSAError(RSAError),
NotEnoughData, ItemNotFound, IllegalFormat, NoSerialNumber, NotEnoughData, ItemNotFound, IllegalFormat, NoSerialNumber,
NoSignatureAlgorithm, NoNameInformation, IllFormedNameInformation, NoSignatureAlgorithm, NoNameInformation, IllFormedNameInformation,
NoValueForName, UnknownAttrTypeValue, IllegalStringValue, NoValidityInfo, NoValueForName, UnknownAttrTypeValue, IllegalStringValue, NoValidityInfo,
ImproperValidityInfo, NoSubjectPublicKeyInfo, ImproperSubjectPublicKeyInfo, ImproperValidityInfo, NoSubjectPublicKeyInfo, ImproperSubjectPublicKeyInfo,
BadPublicKeyAlgorithm, UnsupportedPublicKey, InvalidRSAKey, BadPublicKeyAlgorithm, UnsupportedPublicKey, InvalidRSAKey,
UnsupportedExtension, UnexpectedNegativeNumber, MissingNumber, UnsupportedExtension, UnexpectedNegativeNumber, MissingNumber,
NoSignatureFound NoSignatureFound, UnsupportedSignature, SignatureFailed
} }
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
@@ -34,50 +38,18 @@ enum X509PublicKey {
RSA(RSAPublicKey) RSA(RSAPublicKey)
} }
#[derive(Clone,Debug,PartialEq)]
struct RSAPublicKey {
bit_size: usize,
n: BigUint,
e: BigUint
}
impl FromASN1 for RSAPublicKey {
type Error = X509ParseError;
fn from_asn1(bs: &[ASN1Block])
-> Result<(RSAPublicKey,&[ASN1Block]),X509ParseError>
{
match bs.split_first() {
None =>
Err(X509ParseError::ItemNotFound),
Some((&ASN1Block::Sequence(_, _, ref items), rest))
if items.len() == 2 =>
{
let n = decode_biguint(&items[0])?;
let e = decode_biguint(&items[1])?;
let nsize = n.bits();
let mut rsa_size = 256;
while rsa_size < nsize {
rsa_size = rsa_size * 2;
}
let res = RSAPublicKey{ bit_size: rsa_size, n: n, e: e };
Ok((res, rest))
}
Some(_) =>
Err(X509ParseError::InvalidRSAKey)
}
}
}
impl From<ASN1DecodeErr> for X509ParseError { impl From<ASN1DecodeErr> for X509ParseError {
fn from(e: ASN1DecodeErr) -> X509ParseError { fn from(e: ASN1DecodeErr) -> X509ParseError {
X509ParseError::ASN1DecodeError(e) X509ParseError::ASN1DecodeError(e)
} }
} }
impl From<RSAError> for X509ParseError {
fn from(e: RSAError) -> X509ParseError {
X509ParseError::RSAError(e)
}
}
impl FromASN1 for PubKeyAlgorithm { impl FromASN1 for PubKeyAlgorithm {
type Error = X509ParseError; type Error = X509ParseError;
@@ -401,7 +373,7 @@ struct Certificate {
impl FromASN1WithBody for Certificate { impl FromASN1WithBody for Certificate {
type Error = X509ParseError; type Error = X509ParseError;
fn from_asn1_with_body<'a>(bs: &'a[ASN1Block], v: &[u8]) fn from_asn1_with_body<'a>(bs: &'a[ASN1Block], raw_input: &[u8])
-> Result<(Certificate,&'a[ASN1Block]),X509ParseError> -> Result<(Certificate,&'a[ASN1Block]),X509ParseError>
{ {
match bs.split_first() { match bs.split_first() {
@@ -419,8 +391,11 @@ impl FromASN1WithBody for Certificate {
ASN1Block::BitString(_, _, size, ref sig) ASN1Block::BitString(_, _, size, ref sig)
if size % 8 == 0 => if size % 8 == 0 =>
{ {
println!("Offset: {}", hashend); let signed_block: &[u8] = &raw_input[0..hashend];
println!("Algblock: {:?}", algblock); check_signature(algblock,
&certblock.subject_key,
signed_block,
sig.to_vec());
Ok((certblock, rest)) Ok((certblock, rest))
} }
_ => _ =>
@@ -433,6 +408,39 @@ impl FromASN1WithBody for Certificate {
} }
} }
fn check_signature(alg: SignatureAlgorithm,
key: &X509PublicKey,
block: &[u8],
sig: Vec<u8>)
-> Result<(),X509ParseError>
{
match (alg.key_alg, key) {
(PubKeyAlgorithm::RSA, &X509PublicKey::RSA(ref key)) => {
let shash = signing_hash(alg.hash_alg)?;
if !key.verify(shash, block, sig) {
return Err(X509ParseError::SignatureFailed);
}
Ok(())
}
_ => {
Err(X509ParseError::UnsupportedSignature)
}
}
}
fn signing_hash(a: HashAlgorithm)
-> Result<&'static SigningHash,X509ParseError>
{
match a {
HashAlgorithm::SHA1 => Ok(&SIGNING_HASH_SHA1),
HashAlgorithm::SHA224 => Ok(&SIGNING_HASH_SHA224),
HashAlgorithm::SHA256 => Ok(&SIGNING_HASH_SHA256),
HashAlgorithm::SHA384 => Ok(&SIGNING_HASH_SHA384),
HashAlgorithm::SHA512 => Ok(&SIGNING_HASH_SHA512),
_ => Err(X509ParseError::UnsupportedSignature)
}
}
fn get_tbs_certificate(x: &ASN1Block) fn get_tbs_certificate(x: &ASN1Block)
-> Result<Certificate,X509ParseError> -> Result<Certificate,X509ParseError>
{ {
@@ -913,7 +921,7 @@ fn get_rsa_public_key(b: &ASN1Block)
{ {
match b { match b {
&ASN1Block::BitString(_, _, size, ref vec) if size % 8 == 0 => { &ASN1Block::BitString(_, _, size, ref vec) if size % 8 == 0 => {
der_decode(vec) der_decode(vec).map_err(|x| X509ParseError::RSAError(x))
} }
_ => _ =>
Err(X509ParseError::InvalidRSAKey) Err(X509ParseError::InvalidRSAKey)
@@ -1087,6 +1095,5 @@ mod tests {
#[test] #[test]
fn x509_tests() { fn x509_tests() {
assert!(can_parse("test/server.bin").is_ok()); assert!(can_parse("test/server.bin").is_ok());
assert!(can_parse("test/key.bin").is_ok());
} }
} }