1use crate::Error;
8use crate::Result;
9use crate::common_name_to_subject;
10use mbedtls::hash;
11use mbedtls::pk::{Pk, Type as PkType};
12pub use mbedtls::rng::Rdrand as FtxRng;
13use pkix;
14use pkix::bit_vec::BitVec;
15use pkix::pem::{der_to_pem, PEM_CERTIFICATE_REQUEST};
16use pkix::pkcs10::{CertificationRequest, CertificationRequestInfo};
17use pkix::types::{
18 Attribute, DerSequence, EcdsaX962, Extension, Name, ObjectIdentifier, RsaPkcs15, Sha256,
19};
20use pkix::DerWrite;
21
22#[derive(Clone, Copy, Debug)]
23pub enum SignatureAlgorithm {
24 EcdsaX962,
25 RsaPkcs15,
26}
27
28pub trait ExternalKey {
30 fn get_public_key_der(&mut self) -> Result<Vec<u8>>;
31 fn sign_sha256(&mut self, input: &[u8]) -> Result<(Vec<u8>, SignatureAlgorithm)>;
32}
33
34pub trait CsrSigner {
35 fn get_public_key_der(&mut self) -> Result<Vec<u8>>;
36 fn sign_csr(&mut self, csr: &CertificationRequestInfo<DerSequence>) -> Result<String>;
37}
38
39impl<T> CsrSigner for T
40where
41 T: ExternalKey
42{
43 fn get_public_key_der(&mut self) -> Result<Vec<u8>> {
44 ExternalKey::get_public_key_der(self)
45 }
46
47 fn sign_csr(&mut self, csr: &CertificationRequestInfo<DerSequence>) -> Result<String>
48 {
49 let reqinfo = DerSequence::from(pkix::yasna::construct_der(|writer| {
50 csr.write(writer)
51 }));
52
53 let (sig, sigalg) = self.sign_sha256(reqinfo.as_ref())?;
54
55 let csr = match sigalg {
56 SignatureAlgorithm::EcdsaX962 => pkix::yasna::construct_der(|writer| {
57 CertificationRequest {
58 reqinfo,
59 sigalg: EcdsaX962(Sha256),
60 sig: BitVec::from_bytes(&sig),
61 }.write(writer)
62 }),
63 SignatureAlgorithm::RsaPkcs15 => pkix::yasna::construct_der(|writer| {
64 CertificationRequest {
65 reqinfo,
66 sigalg: RsaPkcs15(Sha256),
67 sig: BitVec::from_bytes(&sig),
68 }.write(writer)
69 })
70 };
71
72 Ok(der_to_pem(&csr, PEM_CERTIFICATE_REQUEST))
73 }
74}
75
76impl ExternalKey for Pk {
77 fn get_public_key_der(&mut self) -> Result<Vec<u8>> {
78 Ok(self.write_public_der_vec().map_err(|e| Error::ExternalKey(Box::new(e)))?)
79 }
80
81 fn sign_sha256(&mut self, input: &[u8]) -> Result<(Vec<u8>, SignatureAlgorithm)> {
82 let mut hash = [0u8; 32];
83 hash::Md::hash(hash::Type::Sha256, &input, &mut hash).map_err(|e| Error::ExternalKey(Box::new(e)))?;
84
85 let mut sig = vec![0u8; (self.len()+7)/8];
86 self.sign(hash::Type::Sha256, &hash, &mut sig, &mut FtxRng).map_err(|e| Error::ExternalKey(Box::new(e)))?;
87
88 let sigalg = match self.pk_type() {
89 PkType::Rsa | PkType::RsaAlt | PkType::RsassaPss => Ok(SignatureAlgorithm::RsaPkcs15),
90 PkType::Eckey | PkType::Ecdsa => Ok(SignatureAlgorithm::EcdsaX962),
91 _ => Err(Error::ExternalKeyString(format!("Invalid key type: {:?}", self.pk_type()))),
92 }?;
93
94 Ok((sig, sigalg))
95 }
96}
97
98pub fn get_csr(
99 signer: &mut dyn CsrSigner,
100 subject: &Name,
101 attributes: Vec<(ObjectIdentifier, Vec<Vec<u8>>)>,
102 extensions: &Option<Vec<(ObjectIdentifier, bool, Vec<u8>)>>,
103) -> Result<String> {
104
105 let pub_key_der = signer.get_public_key_der()?;
106
107 let mut attributes = attributes.iter().map(|&(ref oid,ref elems)| {
108 Attribute {
109 oid: oid.clone(),
110 value: elems.iter().map(|e| e[..].into()).collect(),
111 }
112 }).collect::<Vec<_>>();
113
114 let extension_bytes = extensions.as_ref().and_then(|ext| {
115 Some(pkix::yasna::construct_der(|w|w.write_sequence(|w|{
116 for &(ref oid, critical, ref value) in ext {
117 Extension {
118 oid: oid.clone(),
119 critical: critical,
120 value: value[..].to_owned(),
121 }.write(w.next())
122 }
123 })))
124 });
125
126 if let Some(bytes) = &extension_bytes {
127 attributes.push(Attribute{
128 oid: pkix::oid::extensionRequest.clone(),
129 value: vec![bytes[..].into()],
130 });
131 }
132
133 let csr = CertificationRequestInfo {
134 subject: subject.to_owned(),
135 spki: DerSequence::from(&pub_key_der[..]),
136 attributes: attributes,
137 };
138
139 signer.sign_csr(&csr)
140}
141
142pub fn get_csr_common_name(
143 signer: &mut dyn CsrSigner,
144 common_name: &str,
145 attributes: Vec<(ObjectIdentifier, Vec<Vec<u8>>)>,
146 extensions: &Option<Vec<(ObjectIdentifier, bool, Vec<u8>)>>,
147) -> Result<String> {
148 let subject = common_name_to_subject(common_name);
149 get_csr(signer, &subject, attributes, extensions)
150}