diff --git a/examples/example_keys.c b/examples/example_keys.c index e39add26..cff77a99 100644 --- a/examples/example_keys.c +++ b/examples/example_keys.c @@ -264,6 +264,29 @@ const unsigned char cose_ex_P_256_pub_der[91] = { }; +const unsigned char cose_ex_P_256_pair_cbor[] = { + 0xa6, 0x01, 0x02, 0x02, 0x58, 0x24, 0x6d, 0x65, + 0x72, 0x69, 0x61, 0x64, 0x6f, 0x63, 0x2e, 0x62, + 0x72, 0x61, 0x6e, 0x64, 0x79, 0x62, 0x75, 0x63, + 0x6b, 0x40, 0x62, 0x75, 0x63, 0x6b, 0x6c, 0x61, + 0x6e, 0x64, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x20, 0x01, 0x21, 0x58, 0x20, 0x65, + 0xed, 0xa5, 0xa1, 0x25, 0x77, 0xc2, 0xba, 0xe8, + 0x29, 0x43, 0x7f, 0xe3, 0x38, 0x70, 0x1a, 0x10, + 0xaa, 0xa3, 0x75, 0xe1, 0xbb, 0x5b, 0x5d, 0xe1, + 0x08, 0xde, 0x43, 0x9c, 0x08, 0x55, 0x1d, 0x22, + 0x58, 0x20, 0x1e, 0x52, 0xed, 0x75, 0x70, 0x11, + 0x63, 0xf7, 0xf9, 0xe4, 0x0d, 0xdf, 0x9f, 0x34, + 0x1b, 0x3d, 0xc9, 0xba, 0x86, 0x0a, 0xf7, 0xe0, + 0xca, 0x7c, 0xa7, 0xe9, 0xee, 0xcd, 0x00, 0x84, + 0xd1, 0x9c, 0x23, 0x58, 0x20, 0xaf, 0xf9, 0x07, + 0xc9, 0x9f, 0x9a, 0xd3, 0xaa, 0xe6, 0xc4, 0xcd, + 0xf2, 0x11, 0x22, 0xbc, 0xe2, 0xbd, 0x68, 0xb5, + 0x28, 0x3e, 0x69, 0x07, 0x15, 0x4a, 0xd9, 0x11, + 0x84, 0x0f, 0xa2, 0x08, 0xcf +}; + + const unsigned char cose_ex_P_521_priv_sec1[66] = { 0x00, 0x08, 0x51, 0x38, 0xdd, 0xab, 0xf5, 0xca, 0x97, 0x5f, 0x58, 0x60, 0xf9, 0x1a, 0x08, 0xe9, diff --git a/examples/example_keys.h b/examples/example_keys.h index 3fe20d94..02fbd4ce 100644 --- a/examples/example_keys.h +++ b/examples/example_keys.h @@ -201,6 +201,8 @@ extern const unsigned char cose_ex_P_256_priv_sec1[32]; extern const unsigned char cose_ex_P_256_pub_sec1[65]; extern const unsigned char cose_ex_P_256_pair_der[121]; extern const unsigned char cose_ex_P_256_pub_der[91]; +extern const unsigned char cose_ex_P_256_pair_cbor[149]; + // KID: bilbo.baggins@hobbiton.example extern const unsigned char cose_ex_P_521_priv_sec1[66]; diff --git a/examples/init_keys_psa.c b/examples/init_keys_psa.c index 225da040..8f145fd3 100644 --- a/examples/init_keys_psa.c +++ b/examples/init_keys_psa.c @@ -240,7 +240,7 @@ init_fixed_test_ec_encryption_key(uint32_t cose_ec_curve_id, priv_key_bytes.ptr, priv_key_bytes.len, (mbedtls_svc_key_id_t *)(&private_key->key.handle)); - +#if 0 /* Import the public key from the SEC1 representation. It is * the only format supported by psa_import_key(). ASN.1/DER/PEM * formats are not supported. @@ -253,6 +253,14 @@ init_fixed_test_ec_encryption_key(uint32_t cose_ec_curve_id, status = psa_import_key(&attributes, pub_key_bytes.ptr, pub_key_bytes.len, (mbedtls_svc_key_id_t *)(&public_key->key.handle)); +#else + + t_cose_key_decode(Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(cose_ex_P_256_pair_cbor), public_key); + + + + +#endif /* * With PSA, it is also possible to import the private key as diff --git a/inc/t_cose/t_cose_key.h b/inc/t_cose/t_cose_key.h index a757e9ee..da646999 100644 --- a/inc/t_cose/t_cose_key.h +++ b/inc/t_cose/t_cose_key.h @@ -228,6 +228,10 @@ void t_cose_key_free_symmetric(struct t_cose_key key); +enum t_cose_err_t +t_cose_key_decode(struct q_useful_buf_c cbor_encoded, + struct t_cose_key *key); + #ifdef __cplusplus } #endif diff --git a/src/t_cose_key.c b/src/t_cose_key.c index 0ce88f5a..3a968dfd 100644 --- a/src/t_cose_key.c +++ b/src/t_cose_key.c @@ -10,6 +10,8 @@ */ #include "t_cose/t_cose_key.h" #include "t_cose_crypto.h" +#include "qcbor/qcbor_spiffy_decode.h" +#include "t_cose_crypto.h" /* @@ -35,3 +37,74 @@ t_cose_key_free_symmetric(struct t_cose_key key) t_cose_crypto_free_symmetric_key(key); } + + +enum t_cose_err_t +t_cose_key_decode(struct q_useful_buf_c cbor_encoded, + struct t_cose_key *key) +{ + QCBORDecodeContext cbor_decoder; + int64_t kty; + int64_t curve; + struct q_useful_buf_c x; + struct q_useful_buf_c y_string; + bool y_bool; + QCBORItem y; + enum t_cose_err_t result; + + + QCBORDecode_Init(&cbor_decoder, cbor_encoded, 0); + + + QCBORDecode_EnterMap(&cbor_decoder, NULL); + + QCBORDecode_GetInt64InMapN(&cbor_decoder, T_COSE_KEY_COMMON_KTY, &kty); + QCBORDecode_GetInt64InMapN(&cbor_decoder, T_COSE_KEY_PARAM_CRV, &curve); + QCBORDecode_GetByteStringInMapN(&cbor_decoder, T_COSE_KEY_PARAM_X_COORDINATE, &x); + QCBORDecode_GetItemInMapN(&cbor_decoder, T_COSE_KEY_PARAM_Y_COORDINATE, QCBOR_TYPE_ANY, &y); + + QCBORDecode_ExitMap(&cbor_decoder); + if(QCBORDecode_GetError(&cbor_decoder)) { + return T_COSE_ERR_FAIL; // TODO: is this right? + } + + // TODO: check kty + + /* If y is a bool, then point compression is used and y is a boolean + * indicating the sign. If not then it is a byte string with the y. + * Anything else is an error. See RFC 9053 7.1.1. + */ + switch(y.uDataType) { + case QCBOR_TYPE_BYTE_STRING: + y_string = y.val.string; + y_bool = true; /* Unused. Only here to avoid compiler warning */ + break; + + case QCBOR_TYPE_TRUE: + y_bool = true; + y_string = NULL_Q_USEFUL_BUF_C; + break; + + case QCBOR_TYPE_FALSE: + y_bool = true; + y_string = NULL_Q_USEFUL_BUF_C; + break; + + default: + return 77; // TODO: error code + } + + /* Turn it into a t_cose_key that is imported into the library */ + + if(curve > INT32_MAX || curve < INT32_MIN) { + // Make sure cast is safe + return T_COSE_ERR_FAIL; // TODO: error + } + result = t_cose_crypto_import_ec2_pubkey((int32_t)curve, + x, + y_string, + y_bool, + key); + + return result; +}