[bssl] Support conversion from COSE_Key to EVP_PKEY
The subject public key in DICE chain will be encoded as EVP_PKEY
in a subsequent cl to verify the DICE chain signatures.
Bug: 314266221
Test: atest libbssl_avf_nostd.test
Change-Id: I489876025d431a794f08cb12999b34e4920d3507
diff --git a/libs/bssl/src/evp.rs b/libs/bssl/src/evp.rs
index 330f317..86f99a8 100644
--- a/libs/bssl/src/evp.rs
+++ b/libs/bssl/src/evp.rs
@@ -17,15 +17,23 @@
use crate::cbb::CbbFixed;
use crate::digest::{Digester, DigesterContext};
use crate::ec_key::EcKey;
-use crate::util::{check_int_result, to_call_failed_error};
+use crate::util::{
+ check_int_result, get_label_value, get_label_value_as_bytes, to_call_failed_error,
+};
use alloc::vec::Vec;
-use bssl_avf_error::{ApiName, Result};
+use bssl_avf_error::{ApiName, Error, Result};
use bssl_ffi::{
CBB_flush, CBB_len, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_free, EVP_PKEY_new,
EVP_PKEY_new_raw_public_key, EVP_PKEY_set1_EC_KEY, EVP_marshal_public_key, EVP_PKEY,
EVP_PKEY_ED25519, EVP_PKEY_X25519,
};
+use ciborium::Value;
use core::ptr::{self, NonNull};
+use coset::{
+ iana::{self, EnumI64},
+ CoseKey, KeyType, Label,
+};
+use log::error;
/// Wrapper of an `EVP_PKEY` object, representing a public or private key.
pub struct PKey {
@@ -116,6 +124,43 @@
Ok(Self { pkey, _inner_ec_key: None })
}
+ /// Creates a `PKey` from the given `cose_key`.
+ ///
+ /// The lifetime of the returned instance is not tied to the lifetime of the `cose_key` as the
+ /// data of `cose_key` is copied into the `EVP_PKEY` or `EC_KEY` object.
+ pub fn from_cose_public_key(cose_key: &CoseKey) -> Result<Self> {
+ match &cose_key.kty {
+ KeyType::Assigned(iana::KeyType::EC2) => {
+ EcKey::from_cose_public_key(cose_key)?.try_into()
+ }
+ KeyType::Assigned(iana::KeyType::OKP) => {
+ let curve_type =
+ get_label_value(cose_key, Label::Int(iana::OkpKeyParameter::Crv.to_i64()))?;
+ let curve_type = match curve_type {
+ crv if crv == &Value::from(iana::EllipticCurve::Ed25519.to_i64()) => {
+ PKeyType::ED25519
+ }
+ crv if crv == &Value::from(iana::EllipticCurve::X25519.to_i64()) => {
+ PKeyType::X25519
+ }
+ crv => {
+ error!("Unsupported curve type in OKP COSE key: {:?}", crv);
+ return Err(Error::Unimplemented);
+ }
+ };
+ let x = get_label_value_as_bytes(
+ cose_key,
+ Label::Int(iana::OkpKeyParameter::X.to_i64()),
+ )?;
+ Self::new_raw_public_key(x, curve_type)
+ }
+ kty => {
+ error!("Unsupported key type in COSE key: {:?}", kty);
+ Err(Error::Unimplemented)
+ }
+ }
+ }
+
/// Verifies the given `signature` of the `message` using the current public key.
///
/// The `message` will be hashed using the given `digester` before verification.