backend.rs (8325B)
1 /* -*- Mode: rust; rust-indent-offset: 4 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 use pkcs11_bindings::*; 7 use rsclientcerts::cryptoki::*; 8 use rsclientcerts::manager::{ClientCertsBackend, CryptokiObject, Sign}; 9 use rsclientcerts_util::error::Error; 10 use rsclientcerts_util::*; 11 12 use base64::prelude::*; 13 use libcrux_p256::{ecdsa_sign_p256_without_hash, validate_private_key}; 14 use num_bigint::BigUint; 15 use rand::{thread_rng, RngCore}; 16 17 #[derive(Clone)] 18 struct RSAKey { 19 modulus: BigUint, 20 private_exponent: BigUint, 21 } 22 23 #[derive(Clone)] 24 struct ECKey { 25 private_key: Vec<u8>, 26 } 27 28 #[derive(Clone)] 29 enum PrivateKey { 30 RSA(RSAKey), 31 EC(ECKey), 32 } 33 34 #[derive(Clone)] 35 pub struct Key { 36 cryptoki_key: CryptokiKey, 37 private_key: PrivateKey, 38 } 39 40 impl Key { 41 fn new(private_key_info: Vec<u8>, cert: Vec<u8>) -> Result<Key, Error> { 42 let private_key_info = read_private_key_info(&private_key_info).unwrap(); 43 let (cryptoki_key, private_key) = match private_key_info { 44 PrivateKeyInfo::RSA(rsa_private_key) => ( 45 CryptokiKey::new(Some(rsa_private_key.modulus.clone()), None, &cert).unwrap(), 46 PrivateKey::RSA(RSAKey { 47 modulus: BigUint::from_bytes_be(rsa_private_key.modulus.as_ref()), 48 private_exponent: BigUint::from_bytes_be( 49 rsa_private_key.private_exponent.as_ref(), 50 ), 51 }), 52 ), 53 PrivateKeyInfo::EC(ec_private_key) => ( 54 CryptokiKey::new(None, Some(ENCODED_OID_BYTES_SECP256R1.to_vec()), &cert).unwrap(), 55 PrivateKey::EC(ECKey { 56 private_key: ec_private_key.private_key, 57 }), 58 ), 59 }; 60 Ok(Key { 61 cryptoki_key, 62 private_key, 63 }) 64 } 65 } 66 67 impl CryptokiObject for Key { 68 fn matches(&self, attrs: &[(CK_ATTRIBUTE_TYPE, Vec<u8>)]) -> bool { 69 self.cryptoki_key.matches(attrs) 70 } 71 72 fn get_attribute(&self, attribute: CK_ATTRIBUTE_TYPE) -> Option<&[u8]> { 73 self.cryptoki_key.get_attribute(attribute) 74 } 75 } 76 77 // Implements EMSA-PKCS1-v1_5-ENCODE as per RFC 8017 section 9.2, except that the message `M` has 78 // already been hashed and encoded into a `DigestInfo` with the appropriate digest algorithm. 79 fn emsa_pkcs1v1_5_encode(digest_info: &[u8], em_len: usize) -> Vec<u8> { 80 assert!(em_len >= digest_info.len() + 11); 81 let mut ps = vec![0xff; em_len - digest_info.len() - 3]; 82 let mut em = vec![0x00, 0x01]; 83 em.append(&mut ps); 84 em.push(0x00); 85 em.extend_from_slice(digest_info); 86 em 87 } 88 89 impl Sign for Key { 90 fn get_signature_length( 91 &mut self, 92 _data: &[u8], 93 _params: &Option<CK_RSA_PKCS_PSS_PARAMS>, 94 ) -> Result<usize, Error> { 95 match &self.private_key { 96 PrivateKey::RSA(rsa_private_key) => Ok(((rsa_private_key.modulus.bits() + 7) / 8) 97 .try_into() 98 .unwrap()), 99 PrivateKey::EC(_) => Ok(64), // currently, only secp256r1 is supported 100 } 101 } 102 103 fn sign( 104 &mut self, 105 data: &[u8], 106 params: &Option<CK_RSA_PKCS_PSS_PARAMS>, 107 ) -> Result<Vec<u8>, Error> { 108 match &self.private_key { 109 PrivateKey::RSA(rsa_private_key) => { 110 let encoded = if let Some(params) = params.as_ref() { 111 let em_bits = rsa_private_key.modulus.bits() - 1; 112 emsa_pss_encode(data, em_bits.try_into().unwrap(), params).unwrap() 113 } else { 114 let em_len = ((rsa_private_key.modulus.bits() + 7) / 8) 115 .try_into() 116 .unwrap(); 117 emsa_pkcs1v1_5_encode(data, em_len) 118 }; 119 let message = BigUint::from_bytes_be(&encoded); 120 // NB: Do not use this implementation where maintaining the secrecy of the private key is 121 // important. In particular, the underlying exponentiation implementation may not be 122 // constant-time and could leak information. This is intended to only be used in tests. 123 // Additionally, the "private" key in use is already not at all a secret. 124 let signature = 125 message.modpow(&rsa_private_key.private_exponent, &rsa_private_key.modulus); 126 Ok(signature.to_bytes_be()) 127 } 128 PrivateKey::EC(ec_private_key) => { 129 Ok(ecdsa(data, ec_private_key.private_key.as_slice())) 130 } 131 } 132 } 133 } 134 135 fn ecdsa(hash: &[u8], private_key: &[u8]) -> Vec<u8> { 136 assert_eq!(hash.len(), 32); 137 assert_eq!(private_key.len(), 32); 138 assert!(validate_private_key(private_key)); 139 let mut signature = vec![0; 64]; 140 let nonce = loop { 141 let mut nonce = [0u8; 32]; 142 thread_rng().fill_bytes(&mut nonce); 143 if validate_private_key(&nonce) { 144 break nonce; 145 } 146 }; 147 assert!(ecdsa_sign_p256_without_hash( 148 signature.as_mut_slice(), 149 hash.len().try_into().unwrap(), 150 hash, 151 private_key, 152 nonce.as_slice(), 153 )); 154 signature 155 } 156 157 pub struct Backend { 158 slot_description: &'static [u8; 64], 159 token_label: &'static [u8; 32], 160 slot_flags: CK_FLAGS, 161 token_flags: CK_FLAGS, 162 logged_in: bool, 163 certs: Vec<CryptokiCert>, 164 keys: Vec<Key>, 165 } 166 167 const TOKEN_MODEL_BYTES: &[u8; 16] = b"Test Model "; 168 const TOKEN_SERIAL_NUMBER_BYTES: &[u8; 16] = b"0000000000000000"; 169 170 impl Backend { 171 pub fn new( 172 slot_description: &'static [u8; 64], 173 token_label: &'static [u8; 32], 174 slot_flags: CK_FLAGS, 175 token_flags: CK_FLAGS, 176 certs_pem: Vec<&'static str>, 177 keys_pem: Vec<&'static str>, 178 ) -> Backend { 179 let certs_der = certs_pem 180 .into_iter() 181 .map(pem_to_base64) 182 .map(|base64| BASE64_STANDARD.decode(base64).unwrap()); 183 let keys_der = keys_pem 184 .into_iter() 185 .map(pem_to_base64) 186 .map(|base64| BASE64_STANDARD.decode(base64).unwrap()); 187 let mut certs = Vec::new(); 188 let mut keys = Vec::new(); 189 for (cert_der, key_der) in std::iter::zip(certs_der, keys_der) { 190 let cert = CryptokiCert::new(cert_der.to_vec(), b"test certificate".to_vec()).unwrap(); 191 certs.push(cert); 192 let key = Key::new(key_der.to_vec(), cert_der.to_vec()).unwrap(); 193 keys.push(key); 194 } 195 Backend { 196 slot_description, 197 token_label, 198 slot_flags, 199 token_flags, 200 logged_in: false, 201 certs, 202 keys, 203 } 204 } 205 } 206 207 fn pem_to_base64(pem: &str) -> String { 208 let lines = pem.split('\n'); 209 let line_count = lines.clone().count(); 210 // Strip off "-----BEGIN CERTIFICATE-----" / "-----END CERTIFICATE-----" 211 lines 212 .skip(1) 213 .take(line_count - 3) 214 .collect::<Vec<&str>>() 215 .join("") 216 } 217 218 impl ClientCertsBackend for Backend { 219 type Key = Key; 220 221 fn find_objects(&mut self) -> Result<(Vec<CryptokiCert>, Vec<Key>), Error> { 222 Ok((self.certs.clone(), self.keys.clone())) 223 } 224 225 fn get_slot_info(&self) -> CK_SLOT_INFO { 226 CK_SLOT_INFO { 227 slotDescription: *self.slot_description, 228 manufacturerID: *crate::MANUFACTURER_ID_BYTES, 229 flags: self.slot_flags, 230 ..Default::default() 231 } 232 } 233 234 fn get_token_info(&self) -> CK_TOKEN_INFO { 235 CK_TOKEN_INFO { 236 label: *self.token_label, 237 manufacturerID: *crate::MANUFACTURER_ID_BYTES, 238 model: *TOKEN_MODEL_BYTES, 239 serialNumber: *TOKEN_SERIAL_NUMBER_BYTES, 240 flags: self.token_flags, 241 ..Default::default() 242 } 243 } 244 245 fn get_mechanism_list(&self) -> Vec<CK_MECHANISM_TYPE> { 246 vec![CKM_ECDSA, CKM_RSA_PKCS, CKM_RSA_PKCS_PSS] 247 } 248 249 fn login(&mut self) { 250 self.logged_in = true; 251 } 252 253 fn logout(&mut self) { 254 self.logged_in = false; 255 } 256 257 fn is_logged_in(&self) -> bool { 258 self.logged_in 259 } 260 }