Skip to content

Commit

Permalink
ta: pkcs11: Add RSA AES key wrap
Browse files Browse the repository at this point in the history
The PKCS#11 Specification:
https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/cs01/
pkcs11-spec-v3.1-cs01.pdf

6.1.23 RSA AES KEY WRAP

The mechanism requires AES KWP mechanism CKM_AES_KEY_WRAP_KWP
which is not currently implemented in OP-TEE nor mentioned in
Global Platform specification.

Use the MBedTLS to wrap/unwrap the target key.

Signed-off-by: Valerii Chubar <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
  • Loading branch information
Valerii Chubar authored and jforissier committed Dec 9, 2022
1 parent a9aa45d commit 45d40bd
Show file tree
Hide file tree
Showing 7 changed files with 695 additions and 16 deletions.
1 change: 1 addition & 0 deletions ta/pkcs11/include/pkcs11_ta.h
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,7 @@ enum pkcs11_mechanism_id {
PKCS11_CKM_ECDSA_SHA384 = 0x01045,
PKCS11_CKM_ECDSA_SHA512 = 0x01046,
PKCS11_CKM_ECDH1_DERIVE = 0x01050,
PKCS11_CKM_RSA_AES_KEY_WRAP = 0x01054,
PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN = 0x01055,
PKCS11_CKM_EDDSA = 0x01057,
PKCS11_CKM_AES_KEY_GEN = 0x01080,
Expand Down
265 changes: 262 additions & 3 deletions ta/pkcs11/src/pkcs11_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <assert.h>
#include <inttypes.h>
#include <mbedtls/pk.h>
#include <pkcs11_ta.h>
#include <stdlib.h>
#include <string_ext.h>
Expand Down Expand Up @@ -1403,6 +1404,7 @@ enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
case PKCS11_CKM_AES_CBC:
case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
case PKCS11_CKM_RSA_AES_KEY_WRAP:
assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
break;
case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
Expand Down Expand Up @@ -1822,6 +1824,7 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
case PKCS11_CKM_RSA_AES_KEY_WRAP:
case PKCS11_CKM_RSA_PKCS_OAEP:
case PKCS11_CKM_RSA_PKCS_PSS:
case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
Expand Down Expand Up @@ -2226,15 +2229,166 @@ static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data,
return add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
}

static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
void *data,
size_t key_size)
{
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
int mbedtls_rc = 0;
uint32_t key_bits = 0;
uint32_t size = 0;
uint32_t buffer_size = 0;
void *buffer = NULL;
mbedtls_pk_context pk = { };
mbedtls_rsa_context *rsa = NULL;
mbedtls_mpi n = { };
mbedtls_mpi e = { };
mbedtls_mpi d = { };
mbedtls_mpi p = { };
mbedtls_mpi q = { };

rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits);
if (rc && rc != PKCS11_RV_NOT_FOUND)
return rc;

if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) ||
remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) ||
remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) ||
remove_empty_attribute(head, PKCS11_CKA_PRIME_1) ||
remove_empty_attribute(head, PKCS11_CKA_PRIME_2))
return PKCS11_CKR_GENERAL_ERROR;

mbedtls_pk_init(&pk);
mbedtls_mpi_init(&n);
mbedtls_mpi_init(&e);
mbedtls_mpi_init(&d);
mbedtls_mpi_init(&p);
mbedtls_mpi_init(&q);

mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size, NULL, 0);
if (mbedtls_rc) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

rsa = mbedtls_pk_rsa(pk);
mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e);
if (mbedtls_rc) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) {
rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
goto out;
}

size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8);
buffer_size = size;
buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
if (!buffer) {
rc = PKCS11_CKR_DEVICE_MEMORY;
goto out;
}

mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size);
if (mbedtls_rc) {
rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
goto out;
}

rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size);
if (rc)
goto out;

size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8);
if (buffer_size < size) {
rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
goto out;
}

mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size);
if (mbedtls_rc) {
rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
goto out;
}

rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size);
if (rc)
goto out;

size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8);
if (buffer_size < size) {
rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
goto out;
}

mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size);
if (mbedtls_rc) {
rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
goto out;
}

rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size);
if (rc)
goto out;

size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8);
if (buffer_size < size) {
rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
goto out;
}

mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size);
if (mbedtls_rc) {
rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
goto out;
}

rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size);
if (rc)
goto out;

size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8);
if (buffer_size < size) {
rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE;
goto out;
}

mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size);
if (mbedtls_rc) {
rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
goto out;
}

rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size);

out:
mbedtls_pk_free(&pk);
mbedtls_mpi_free(&n);
mbedtls_mpi_free(&e);
mbedtls_mpi_free(&d);
mbedtls_mpi_free(&p);
mbedtls_mpi_free(&q);
TEE_Free(buffer);
return rc;
}

enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data,
size_t key_size)
{
switch (get_class(*head)) {
case PKCS11_CKO_SECRET_KEY:
return set_secret_key_data(head, data, key_size);
case PKCS11_CKO_PRIVATE_KEY:
if (get_key_type(*head) == PKCS11_CKK_RSA)
return set_private_key_data_rsa(head, data, key_size);
break;
default:
return PKCS11_CKR_GENERAL_ERROR;
}

return PKCS11_CKR_GENERAL_ERROR;
}

static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head,
Expand All @@ -2258,17 +2412,122 @@ static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head,
return PKCS11_CKR_OK;
}

static enum pkcs11_rc
encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz)
{
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
int i = 0;
int mbedtls_rc = 0;
int start = 0;
int der_size = 0;
void *n = NULL;
void *p = NULL;
void *q = NULL;
void *d = NULL;
void *e = NULL;
uint32_t n_len = 0;
uint32_t p_len = 0;
uint32_t q_len = 0;
uint32_t d_len = 0;
uint32_t e_len = 0;
uint8_t *buffer = NULL;
mbedtls_pk_context pk = { };
mbedtls_rsa_context *rsa = NULL;
const mbedtls_pk_info_t *pk_info = NULL;

mbedtls_pk_init(&pk);
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (mbedtls_pk_setup(&pk, pk_info)) {
rc = PKCS11_CKR_GENERAL_ERROR;
goto out;
}

rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len);
if (rc)
goto out;

rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len);
if (rc)
goto out;

rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len);
if (rc)
goto out;

rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len);
if (rc)
goto out;

rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len);
if (rc)
goto out;

rsa = mbedtls_pk_rsa(pk);
mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len,
q, q_len, d, d_len, e, e_len);
if (mbedtls_rc) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

if (mbedtls_rsa_complete(rsa)) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

if (mbedtls_rsa_check_privkey(rsa)) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

der_size = n_len * 8;
buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
if (!buffer) {
rc = PKCS11_CKR_DEVICE_MEMORY;
goto out;
}

mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size);
if (mbedtls_rc < 0) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

start = der_size - mbedtls_rc;
for (i = 0; i < mbedtls_rc; i++) {
buffer[i] = buffer[i + start];
buffer[i + start] = 0;
}

*data = buffer;
*sz = mbedtls_rc;
out:
mbedtls_pk_free(&pk);

if (rc)
TEE_Free(buffer);

return rc;
}

enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data,
uint32_t *sz)
{
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;

switch (get_class(head)) {
case PKCS11_CKO_SECRET_KEY:
return alloc_copy_attribute_value(head, data, sz);
rc = alloc_copy_attribute_value(head, data, sz);
break;
case PKCS11_CKO_PRIVATE_KEY:
if (get_key_type(head) == PKCS11_CKK_RSA)
rc = encode_rsa_private_key_der(head, data, sz);
break;
default:
return PKCS11_CKR_GENERAL_ERROR;
break;
}

return PKCS11_CKR_OK;
return rc;
}

enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
Expand Down
Loading

0 comments on commit 45d40bd

Please sign in to comment.