I am using OPTEE-OS and mbedTLS and want to create a CSR. I am creating my EC key using the Global Platform API:
res = TEE_AllocateTransientObject(
TEE_TYPE_ECDSA_KEYPAIR,
DSEC_ECDSA_SHA256_KEY_BITS,
&key_pair);
if (res != TEE_SUCCESS) {
return res;
}
Then extract the private key:
res = TEE_GetObjectBufferAttribute(
key_pair,
TEE_ATTR_ECC_PRIVATE_VALUE,
buffer,
&bufferlen);
if (res != TEE_SUCCESS) {
return res;
}
Then use mbedTLS to parse this value and create a to create a CSR:
mbedtls_pk_context priv_key;
mbedtls_pk_init(&priv_key);
ret = mbedtls_pk_parse_key(
&priv_key,
key,
size,
NULL ,
0
);
However, the extracted value from TEE_GetObjectBufferAttribute does not have the headers and footpage:
"-----BEGIN EC PRIVATE KEY-----"
"-----END EC PRIVATE KEY-----"
and is only a binary array (not a string). I am currently getting the following error code: "-15616: PK - Invalid key tag or value".
Is there any way to create a mbedtls_pk_context
with only the binary value of my private key?
The parsing functions in Mbed TLS's pk.h
expect DER or PEM input. If you can find ready-made code to export a key as DER (or PEM) from OPTEE, that'll be easier (but possibly marginally less efficient). On the other hand, it's easier to do the import manually than to write a DER export function.
You need to call mbedtls_pk_setup()
to declare that the context will contain an ECC key, then build the ECC key directly using the interface in ecp.h
. Convert the curve designation from the TEE encoding to the Mbed TLS encoding, and calculate the public key from the private value. (Alternatively, you could export TEE_ATTR_ECC_PUBLIC_VALUE
and set ec->Q
, but that's more work.)
mbedtls_ecp_grp_id grp_id = …; // you need to convert this from the `TEE_ATTR_ECC_CURVE`
mbedtls_pk_context pk;
mbedtls_ecp_keypair *ec = malloc(sizeof(mbedtls_ecp_keypair));
mbedtls_pk_init(&pk);
mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA));
mbedtls_ecp_keypair_init(ec);
mbedtls_ecp_group_load(&ec->grp, grp_id);
mbedtls_mpi_read_binary(&ec->d, buffer, bufferlen);
mbedtls_ecp_check_privkey(&ec->grp, &ec->d);
mbedtls_ecp_mul(&ec->grp, &ec->Q, &ec->d, &ec->grp.G, mbedtls_ctr_drbg_random, &ctr_drbg);
pk->pk_ctx = ec;
Completely untested. Error checking omitted. ctr_drbg
is a CTR_DRBG instance, used for blinding during the calculation of the public key.