Public Key plain byte encoding (#540)

* public key is encoded in bytes

* ECDSA pubkey in uncompressed format
This commit is contained in:
kaczmarczyck
2022-08-31 15:51:40 +02:00
committed by GitHub
parent 598c21071e
commit 1b360662ee
6 changed files with 18 additions and 50 deletions

View File

@@ -15,7 +15,6 @@
extern crate alloc;
use openssl::{bn, ec, nid};
use sk_cbor::cbor_map;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
@@ -52,25 +51,7 @@ fn main() {
.public_key()
.to_bytes(&group, conversion_form, &mut ctx)
.unwrap();
const POINT_LEN: usize = 32;
assert_eq!(raw_bytes.len(), 1 + 2 * POINT_LEN);
assert_eq!(raw_bytes[0], 0x04);
let x_bytes = &raw_bytes[1..][..POINT_LEN];
let y_bytes = &raw_bytes[1 + POINT_LEN..][..POINT_LEN];
const EC2_KEY_TYPE: i64 = 2;
const P_256_CURVE: i64 = 1;
const ES256_ALGORITHM: i64 = -7;
let pub_key_cbor = sk_cbor::cbor_map! {
1 => EC2_KEY_TYPE,
3 => ES256_ALGORITHM,
-1 => P_256_CURVE,
-2 => x_bytes,
-3 => y_bytes,
};
let mut cbor_bytes = vec![];
sk_cbor::writer::write(pub_key_cbor, &mut cbor_bytes).unwrap();
let upgrade_pubkey_path = Path::new(&out_dir).join("opensk_upgrade_pubkey_cbor.bin");
let upgrade_pubkey_path = Path::new(&out_dir).join("opensk_upgrade_pubkey.bin");
let mut upgrade_pub_bin_file = File::create(&upgrade_pubkey_path).unwrap();
upgrade_pub_bin_file.write_all(&cbor_bytes).unwrap();
upgrade_pub_bin_file.write_all(&raw_bytes).unwrap();
}

View File

@@ -16,9 +16,8 @@ use super::exponent256::ExponentP256;
use super::gfp256::GFP256;
use super::int256::Int256;
use super::montgomery::Montgomery;
#[cfg(test)]
use arrayref::array_mut_ref;
#[cfg(feature = "std")]
use arrayref::array_mut_ref;
use arrayref::array_ref;
use core::ops::Add;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
@@ -45,7 +44,6 @@ impl PointP256 {
/** Serialization **/
// This uses uncompressed point format from "SEC 1: Elliptic Curve Cryptography" ("Standards for
// Efficient Cryptography").
#[cfg(feature = "std")]
pub fn from_bytes_uncompressed_vartime(bytes: &[u8]) -> Option<PointP256> {
if bytes.len() != 65 || bytes[0] != 0x04 {
None
@@ -57,7 +55,7 @@ impl PointP256 {
}
}
#[cfg(test)]
#[cfg(feature = "std")]
pub fn to_bytes_uncompressed(&self, bytes: &mut [u8; 65]) {
bytes[0] = 0x04;
self.x.to_int().to_bin(array_mut_ref![bytes, 1, 32]);

View File

@@ -231,13 +231,12 @@ impl PubKey {
.map(|p| PubKey { p })
}
#[cfg(feature = "std")]
pub fn from_bytes_uncompressed(bytes: &[u8]) -> Option<PubKey> {
PointP256::from_bytes_uncompressed_vartime(bytes).map(|p| PubKey { p })
}
#[cfg(test)]
fn to_bytes_uncompressed(&self, bytes: &mut [u8; 65]) {
#[cfg(feature = "std")]
pub fn to_bytes_uncompressed(&self, bytes: &mut [u8; 65]) {
self.p.to_bytes_uncompressed(bytes);
}

View File

@@ -836,8 +836,8 @@ impl From<ecdh::PubKey> for CoseKey {
impl From<ecdsa::PubKey> for CoseKey {
fn from(pk: ecdsa::PubKey) -> Self {
let mut x_bytes = [0; ecdh::NBYTES];
let mut y_bytes = [0; ecdh::NBYTES];
let mut x_bytes = [0; ecdsa::NBYTES];
let mut y_bytes = [0; ecdsa::NBYTES];
pk.to_coordinates(&mut x_bytes, &mut y_bytes);
CoseKey {
x_bytes,

View File

@@ -14,9 +14,9 @@
pub const ATTESTATION_PRIVATE_KEY_LENGTH: usize = 32;
pub const AAGUID_LENGTH: usize = 16;
pub const UPGRADE_PUBLIC_KEY_LENGTH: usize = 77;
pub const UPGRADE_PUBLIC_KEY_LENGTH: usize = 65;
pub const AAGUID: &[u8; AAGUID_LENGTH] =
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_aaguid.bin"));
pub const UPGRADE_PUBLIC_KEY: &[u8; UPGRADE_PUBLIC_KEY_LENGTH] =
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_upgrade_pubkey_cbor.bin"));
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_upgrade_pubkey.bin"));

View File

@@ -47,7 +47,7 @@ use self::credential_id::{
use self::credential_management::process_credential_management;
use self::crypto_wrapper::PrivateKey;
use self::data_formats::{
AuthenticatorTransport, CoseKey, CredentialProtectionPolicy, EnterpriseAttestationMode,
AuthenticatorTransport, CredentialProtectionPolicy, EnterpriseAttestationMode,
GetAssertionExtensions, PackedAttestationStatement, PinUvAuthProtocol,
PublicKeyCredentialDescriptor, PublicKeyCredentialParameter, PublicKeyCredentialSource,
PublicKeyCredentialType, PublicKeyCredentialUserEntity, SignatureAlgorithm,
@@ -266,9 +266,8 @@ fn verify_signature(
) -> Result<(), Ctap2StatusCode> {
let signature = ecdsa::Signature::from_bytes(signature_bytes)
.ok_or(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER)?;
let cbor_public_key = cbor_read(public_key_bytes)?;
let cose_key = CoseKey::try_from(cbor_public_key)?;
let public_key = ecdsa::PubKey::try_from(cose_key)?;
let public_key = ecdsa::PubKey::from_bytes_uncompressed(public_key_bytes)
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
if !public_key.verify_hash_vartime(signed_hash, &signature) {
return Err(Ctap2StatusCode::CTAP2_ERR_INTEGRITY_FAILURE);
}
@@ -3492,18 +3491,13 @@ mod test {
metadata[32..96].copy_from_slice(&signature_bytes);
let public_key = private_key.genpk();
let mut public_key_bytes = vec![];
cbor_write(
cbor::Value::from(CoseKey::from(public_key)),
&mut public_key_bytes,
)
.unwrap();
let mut public_key_bytes = [0; 65];
public_key.to_bytes_uncompressed(&mut public_key_bytes);
assert_eq!(
parse_metadata(upgrade_locations, &public_key_bytes, &metadata),
Ok(())
);
// Any manipulation of data fails.
metadata[METADATA_SIGN_OFFSET] = 0x88;
assert_eq!(
@@ -3542,12 +3536,8 @@ mod test {
signature.to_bytes(&mut signature_bytes);
let public_key = private_key.genpk();
let mut public_key_bytes = vec![];
cbor_write(
cbor::Value::from(CoseKey::from(public_key)),
&mut public_key_bytes,
)
.unwrap();
let mut public_key_bytes = [0; 65];
public_key.to_bytes_uncompressed(&mut public_key_bytes);
assert_eq!(
verify_signature(&signature_bytes, &public_key_bytes, &signed_hash),
@@ -3560,7 +3550,7 @@ mod test {
public_key_bytes[0] ^= 0x01;
assert_eq!(
verify_signature(&signature_bytes, &public_key_bytes, &signed_hash),
Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)
Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)
);
public_key_bytes[0] ^= 0x01;
signature_bytes[0] ^= 0x01;