diff --git a/build.rs b/build.rs index cac13b579a05e5d8a34ca7108be4e4356210e0e9..70844b045766775dfa9843e0e2aa63773dad33c1 100644 --- a/build.rs +++ b/build.rs @@ -43,15 +43,30 @@ fn main() { pkey.check_key().unwrap(); assert_eq!(pkey.group().curve_name(), Some(Nid::X9_62_PRIME256V1)); - let mut priv_key = pkey.private_key().to_vec(); - if priv_key.len() == 33 && priv_key[0] == 0 { - priv_key.remove(0); - } - assert_eq!(priv_key.len(), 32); + // Private keys generated by OpenSSL have variable size but we only handle + // constant size. Serialization is done in big endian so if the size is less + // than 32 bytes, we need to prepend with null bytes. + // If the size is 33 bytes, this means the serialized BigInt is negative. + // Any other size is invalid. + let priv_key_hex = pkey.private_key().to_hex_str().unwrap(); + let priv_key_vec = pkey.private_key().to_vec(); + let key_len = priv_key_vec.len(); + + assert!( + key_len <= 33, + "Invalid private key (too big): {} ({:#?})", + priv_key_hex, + priv_key_vec, + ); + + // Copy OpenSSL generated key to our vec, starting from the end + let mut output_vec = [0u8; 32]; + let min_key_len = std::cmp::min(key_len, 32); + output_vec[32 - min_key_len..].copy_from_slice(&priv_key_vec[key_len - min_key_len..]); // Create the raw private key out of the OpenSSL data let mut priv_key_bin_file = File::create(&priv_key_bin_path).unwrap(); - priv_key_bin_file.write_all(&priv_key).unwrap(); + priv_key_bin_file.write_all(&output_vec).unwrap(); // Convert the PEM certificate to DER and extract the serial for AAGUID let input_pem_cert = include_bytes!("crypto_data/opensk_cert.pem");