From 6c363981c4b8b7a09716095e2b93043ef2a35c8a Mon Sep 17 00:00:00 2001 From: Jean-Michel Picod <jmichel@google.com> Date: Thu, 20 Feb 2020 15:32:37 +0100 Subject: [PATCH] Better handling of OpenSSL generated keys. It seems that ECC keys generated by OpenSSL can be between 30 and 33 bytes long whereas OpenSK code expects a fixed size of 32 bytes. This variation could cause Travis CI to fail but also invalid ECC keys to be flashed, causing the authenticator to not work. --- build.rs | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/build.rs b/build.rs index cac13b5..dfbe063 100644 --- a/build.rs +++ b/build.rs @@ -43,15 +43,37 @@ 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 >= 30, + "Invalid private key (too small): {} ({:#?})", + priv_key_hex, + priv_key_vec, + ); + 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[32usize.saturating_sub(min_key_len)..] + .copy_from_slice(&priv_key_vec[key_len.saturating_sub(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"); -- GitLab