use cryptonum::unsigned::{U3072,U2048,U1024,U256,U192}; use dsa::{DSAPublic,DSAPublicKey,DSAParameters}; use dsa::{L3072N256,L2048N256,L2048N224,L1024N160}; use ecdsa::{ECDSAEncodeErr,ECDSAPublic,ECCPublicKey}; use ecdsa::{P192,P224,P256,P384,P521}; use num::BigUint; use rsa::RSAPublic; use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,OID,ToASN1, der_decode,der_encode,from_der}; use utils::TranslateNums; use x509::error::X509ParseError; pub enum X509PublicKey { DSA(DSAPublic), RSA(RSAPublic), ECDSA(ECDSAPublic) } impl From for Option { fn from(x: X509PublicKey) -> Option { match x { X509PublicKey::DSA(x) => Some(x), _ => None } } } impl From for Option { fn from(x: X509PublicKey) -> Option { match x { X509PublicKey::RSA(x) => Some(x), _ => None } } } impl From for Option { fn from(x: X509PublicKey) -> Option { match x { X509PublicKey::ECDSA(x) => Some(x), _ => None } } } pub enum X509EncodeErr { ASN1EncodeErr(ASN1EncodeErr), ECDSAEncodeErr(ECDSAEncodeErr) } impl From for X509EncodeErr { fn from(x: ASN1EncodeErr) -> X509EncodeErr { X509EncodeErr::ASN1EncodeErr(x) } } impl From for X509EncodeErr { fn from(x: ECDSAEncodeErr) -> X509EncodeErr { X509EncodeErr::ECDSAEncodeErr(x) } } impl ToASN1 for X509PublicKey { type Error = X509EncodeErr; fn to_asn1_class(&self, c: ASN1Class) -> Result,X509EncodeErr> { let block = match self { X509PublicKey::RSA(x) => encode_rsa_key(c, x)?, X509PublicKey::DSA(x) => encode_dsa_key(c, x)?, X509PublicKey::ECDSA(x) => encode_ecdsa_key(c, x)?, }; Ok(vec![block]) } } impl FromASN1 for X509PublicKey { type Error = X509ParseError; fn from_asn1(v: &[ASN1Block]) -> Result<(X509PublicKey, &[ASN1Block]), Self::Error> { let (block, rest) = v.split_first().ok_or(X509ParseError::NotEnoughData)?; // SubjectPublicKeyInfo ::= SEQUENCE { // algorithm AlgorithmIdentifier, // subjectPublicKey BIT STRING } if let &ASN1Block::Sequence(_, _, ref info) = block { let (id, malginfo) = strip_algident(&info[0])?; if id == oid!(1,2,840,113549,1,1,1) { let key = decode_rsa_key(&info[1])?; return Ok((X509PublicKey::RSA(key), rest)); } if id == oid!(1,2,840,10040,4,1) { if let Some(alginfo) = malginfo { let key = decode_dsa_key(alginfo, &info[1])?; return Ok((X509PublicKey::DSA(key), rest)); } } if id == oid!(1,2,840,10045,2,1) { if let Some(alginfo) = malginfo { let key = decode_ecdsa_key(alginfo, &info[1..])?; return Ok((X509PublicKey::ECDSA(key), rest)); } } } Err(X509ParseError::IllFormedKey) } } //------------------------------------------------------------------------------ // // RSA Public Key encoding / decoding // //------------------------------------------------------------------------------ fn encode_rsa_key(c: ASN1Class, x: &RSAPublic) -> Result { let objoid = ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,113549,1,1,1)); let bstr = der_encode(x)?; let objkey = ASN1Block::BitString(c, 0, bstr.len() * 8, bstr); Ok(ASN1Block::Sequence(c, 0, vec![objoid, objkey])) } fn decode_rsa_key(x: &ASN1Block) -> Result { if let &ASN1Block::BitString(_, _, _, ref bstr) = x { der_decode(bstr).map_err(|x| X509ParseError::RSAError(x)) } else { Err(X509ParseError::NotEnoughData) } } //------------------------------------------------------------------------------ // // DSA Public Key encoding / decoding // //------------------------------------------------------------------------------ fn encode_dsa_key(c: ASN1Class, x: &DSAPublic) -> Result { let objoid = ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10040,4,1)); let (mut objparams, bstr) = match x { DSAPublic::DSAPublicL1024N160(x) => (x.params.to_asn1_class(c)?, der_encode(x)?), DSAPublic::DSAPublicL2048N224(x) => (x.params.to_asn1_class(c)?, der_encode(x)?), DSAPublic::DSAPublicL2048N256(x) => (x.params.to_asn1_class(c)?, der_encode(x)?), DSAPublic::DSAPublicL3072N256(x) => (x.params.to_asn1_class(c)?, der_encode(x)?) }; objparams.insert(0, objoid); let headinfo = ASN1Block::Sequence(c, 0, objparams); let objkey = ASN1Block::BitString(c, 0, bstr.len() * 8, bstr); Ok(ASN1Block::Sequence(c, 0, vec![headinfo, objkey])) } fn decode_dsa_key(info: ASN1Block, key: &ASN1Block) -> Result { if let ASN1Block::Sequence(_, _, pqg) = info { if pqg.len() != 3 { return Err(X509ParseError::InvalidDSAInfo); } let puint = decode_biguint(&pqg[0])?; let guint = decode_biguint(&pqg[1])?; let quint = decode_biguint(&pqg[2])?; if puint.bits() > 2048 { let p = U3072::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?; let q = U3072::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?; let g = U256::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?; let params = L3072N256::new(p, q, g); if let ASN1Block::BitString(_, _, _, ybstr) = key { let blocks = from_der(ybstr)?; let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?; if let ASN1Block::Integer(_,_,ynum) = iblk { let y = U3072::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?; let key = DSAPublicKey::::new(params, y); let reskey = DSAPublic::DSAPublicL3072N256(key); return Ok(reskey); } } return Err(X509ParseError::InvalidDSAKey) } if puint.bits() > 1024 { if guint.bits() > 224 { let p = U2048::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?; let q = U2048::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?; let g = U256::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?; let params = L2048N256::new(p, q, g); if let ASN1Block::BitString(_, _, _, ybstr) = key { let blocks = from_der(ybstr)?; let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?; if let ASN1Block::Integer(_,_,ynum) = iblk { let y = U2048::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?; let key = DSAPublicKey::::new(params, y); let reskey = DSAPublic::DSAPublicL2048N256(key); return Ok(reskey); } } return Err(X509ParseError::InvalidDSAKey) } else { let p = U2048::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?; let q = U2048::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?; let g = U256::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?; let params = L2048N224::new(p, q, g); if let ASN1Block::BitString(_, _, _, ybstr) = key { let blocks = from_der(ybstr)?; let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?; if let ASN1Block::Integer(_,_,ynum) = iblk { let y = U2048::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?; let key = DSAPublicKey::::new(params, y); let reskey = DSAPublic::DSAPublicL2048N224(key); return Ok(reskey); } } return Err(X509ParseError::InvalidDSAKey) } } let p = U1024::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?; let q = U1024::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?; let g = U192::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?; let params = L1024N160::new(p, q, g); if let ASN1Block::BitString(_, _, _, ybstr) = key { let blocks = from_der(ybstr)?; let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?; if let ASN1Block::Integer(_,_,ynum) = iblk { let y = U1024::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?; let key = DSAPublicKey::::new(params, y); let reskey = DSAPublic::DSAPublicL1024N160(key); return Ok(reskey); } } return Err(X509ParseError::InvalidDSAKey) } Err(X509ParseError::InvalidDSAInfo) } //------------------------------------------------------------------------------ // // ECDSA Public Key encoding // //------------------------------------------------------------------------------ fn encode_ecdsa_key(c: ASN1Class, x: &ECDSAPublic) -> Result { let objoid = ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10045,2,1)); let (base_curve_oid, mut keyvec) = match x { ECDSAPublic::P192(k) => (oid!(1,2,840,10045,3,1,1), k.to_asn1_class(c)?), ECDSAPublic::P224(k) => (oid!(1,3,132,0,33), k.to_asn1_class(c)?), ECDSAPublic::P256(k) => (oid!(1,2,840,10045,3,1,7), k.to_asn1_class(c)?), ECDSAPublic::P384(k) => (oid!(1,3,132,0,34), k.to_asn1_class(c)?), ECDSAPublic::P521(k) => (oid!(1,3,132,0,35), k.to_asn1_class(c)?), }; let curve_oid = ASN1Block::ObjectIdentifier(c, 0, base_curve_oid); let header = ASN1Block::Sequence(c, 0, vec![objoid, curve_oid]); keyvec.insert(0, header); Ok(ASN1Block::Sequence(c, 0, keyvec)) } fn decode_ecdsa_key(info: ASN1Block, keybls: &[ASN1Block]) -> Result { if let ASN1Block::ObjectIdentifier(_, _, oid) = info { if oid == oid!(1,2,840,10045,3,1,1) { let (res, _) = ECCPublicKey::::from_asn1(keybls)?; return Ok(ECDSAPublic::P192(res)); } if oid == oid!(1,3,132,0,33) { let (res, _) = ECCPublicKey::::from_asn1(keybls)?; return Ok(ECDSAPublic::P224(res)); } if oid == oid!(1,2,840,10045,3,1,7) { let (res, _) = ECCPublicKey::::from_asn1(keybls)?; return Ok(ECDSAPublic::P256(res)); } if oid == oid!(1,3,132,0,34) { let (res, _) = ECCPublicKey::::from_asn1(keybls)?; return Ok(ECDSAPublic::P384(res)); } if oid == oid!(1,3,132,0,35) { let (res, _) = ECCPublicKey::::from_asn1(keybls)?; return Ok(ECDSAPublic::P521(res)); } } Err(X509ParseError::UnknownEllipticCurve) } fn strip_algident(block: &ASN1Block) -> Result<(OID, Option),X509ParseError> { match block { &ASN1Block::ObjectIdentifier(_, _, ref oid) => { Ok((oid.clone(), None)) } &ASN1Block::Sequence(_, _, ref items) => { let (oid, _) = strip_algident(&items[0])?; Ok((oid, Some(items[1].clone()))) } _ => Err(X509ParseError::IllFormedAlgoInfo) } } fn decode_biguint(b: &ASN1Block) -> Result { match b { &ASN1Block::Integer(_, _, ref v) => { match v.to_biguint() { Some(sn) => Ok(sn), _ => Err(X509ParseError::InvalidDSAInfo) } } _ => Err(X509ParseError::InvalidDSAInfo) } }