Skip to content

Commit

Permalink
ta: pkcs11: Add RSA key pair generation support
Browse files Browse the repository at this point in the history
Specified in:
PKCS #11 Cryptographic Token Interface Current Mechanisms Specification
Version 2.40 Plus Errata 01
2.1.4 PKCS #1 RSA key pair generation

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
  • Loading branch information
vesajaaskelainen authored and jforissier committed Aug 9, 2021
1 parent db28c54 commit 8692283
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 0 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 @@ -1187,6 +1187,7 @@ enum pkcs11_key_type {
* Note that this will be extended as needed.
*/
enum pkcs11_mechanism_id {
PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000,
PKCS11_CKM_MD5 = 0x00210,
PKCS11_CKM_MD5_HMAC = 0x00211,
PKCS11_CKM_SHA_1 = 0x00220,
Expand Down
28 changes: 28 additions & 0 deletions ta/pkcs11/src/pkcs11_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,10 @@ create_attributes_from_template(struct obj_attrs **out, void *template,
class = template_class;
type = PKCS11_CKK_EC;
break;
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
class = template_class;
type = PKCS11_CKK_RSA;
break;
default:
TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
}
Expand Down Expand Up @@ -879,6 +883,14 @@ create_attributes_from_template(struct obj_attrs **out, void *template,
goto out;
}
break;
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY &&
get_class(temp) != PKCS11_CKO_PRIVATE_KEY) ||
get_key_type(temp) != PKCS11_CKK_RSA) {
rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
goto out;
}
break;
default:
break;
}
Expand Down Expand Up @@ -1194,6 +1206,7 @@ enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
case PKCS11_CKM_AES_KEY_GEN:
case PKCS11_CKM_EC_KEY_PAIR_GEN:
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true));
break;
default:
Expand All @@ -1211,6 +1224,9 @@ enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
case PKCS11_CKM_EC_KEY_PAIR_GEN:
assert(get_key_type(head) == PKCS11_CKK_EC);
break;
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
assert(get_key_type(head) == PKCS11_CKK_RSA);
break;
case PKCS11_PROCESSING_IMPORT:
default:
break;
Expand Down Expand Up @@ -1254,6 +1270,9 @@ static void get_key_min_max_sizes(enum pkcs11_key_type key_type,
case PKCS11_CKK_EC:
mechanism = PKCS11_CKM_EC_KEY_PAIR_GEN;
break;
case PKCS11_CKK_RSA:
mechanism = PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN;
break;
default:
TEE_Panic(key_type);
break;
Expand Down Expand Up @@ -1333,6 +1352,14 @@ enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
}
if (public) {
switch (get_key_type(public)) {
case PKCS11_CKK_RSA:
/* Get key size */
rc = get_u32_attribute(public, PKCS11_CKA_MODULUS_BITS,
&key_length);
if (rc)
return PKCS11_CKR_TEMPLATE_INCONSISTENT;
key_length = ROUNDUP(key_length, 8) / 8;
break;
case PKCS11_CKK_EC:
break;
default:
Expand All @@ -1341,6 +1368,7 @@ enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
}
if (private) {
switch (get_key_type(private)) {
case PKCS11_CKK_RSA:
case PKCS11_CKK_EC:
break;
default:
Expand Down
3 changes: 3 additions & 0 deletions ta/pkcs11/src/processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,9 @@ enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
case PKCS11_CKM_EC_KEY_PAIR_GEN:
rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
break;
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
rc = generate_rsa_keys(proc_params, &pub_head, &priv_head);
break;
default:
rc = PKCS11_CKR_MECHANISM_INVALID;
break;
Expand Down
7 changes: 7 additions & 0 deletions ta/pkcs11/src/processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,11 @@ enum pkcs11_rc generate_ec_keys(struct pkcs11_attribute_head *proc_params,

size_t ecdsa_get_input_max_byte_size(TEE_OperationHandle op);

/*
* RSA crypto algorithm specific functions
*/
enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params,
struct obj_attrs **pub_head,
struct obj_attrs **priv_head);

#endif /*PKCS11_TA_PROCESSING_H*/
171 changes: 171 additions & 0 deletions ta/pkcs11/src/processing_rsa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2018-2021, Linaro Limited
*/

#include <assert.h>
#include <pkcs11_ta.h>
#include <tee_api_defines.h>
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>

#include "attributes.h"
#include "processing.h"

static enum pkcs11_rc tee2pkcs_rsa_attributes(struct obj_attrs **pub_head,
struct obj_attrs **priv_head,
TEE_ObjectHandle tee_obj)
{
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
void *a_ptr = NULL;

rc = tee2pkcs_add_attribute(pub_head, PKCS11_CKA_MODULUS, tee_obj,
TEE_ATTR_RSA_MODULUS);
if (rc)
goto out;

rc = get_attribute_ptr(*pub_head, PKCS11_CKA_PUBLIC_EXPONENT, &a_ptr,
NULL);
if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
goto out;

if (rc == PKCS11_CKR_OK && !a_ptr) {
rc = remove_empty_attribute(pub_head,
PKCS11_CKA_PUBLIC_EXPONENT);
if (rc)
goto out;
rc = PKCS11_RV_NOT_FOUND;
}

if (rc == PKCS11_RV_NOT_FOUND) {
rc = tee2pkcs_add_attribute(pub_head,
PKCS11_CKA_PUBLIC_EXPONENT,
tee_obj,
TEE_ATTR_RSA_PUBLIC_EXPONENT);
if (rc)
goto out;
}

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_MODULUS, tee_obj,
TEE_ATTR_RSA_MODULUS);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PUBLIC_EXPONENT,
tee_obj, TEE_ATTR_RSA_PUBLIC_EXPONENT);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIVATE_EXPONENT,
tee_obj, TEE_ATTR_RSA_PRIVATE_EXPONENT);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIME_1, tee_obj,
TEE_ATTR_RSA_PRIME1);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIME_2, tee_obj,
TEE_ATTR_RSA_PRIME2);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EXPONENT_1, tee_obj,
TEE_ATTR_RSA_EXPONENT1);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EXPONENT_2, tee_obj,
TEE_ATTR_RSA_EXPONENT2);
if (rc)
goto out;

rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_COEFFICIENT, tee_obj,
TEE_ATTR_RSA_COEFFICIENT);
out:
return rc;
}

enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params,
struct obj_attrs **pub_head,
struct obj_attrs **priv_head)
{
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
void *a_ptr = NULL;
uint32_t a_size = 0;
TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL;
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t modulus_bits = 0;
TEE_Attribute tee_attrs[1] = { };
uint32_t tee_count = 0;

if (!proc_params || !*pub_head || !*priv_head)
return PKCS11_CKR_TEMPLATE_INCONSISTENT;

rc = get_attribute_ptr(*pub_head, PKCS11_CKA_MODULUS_BITS, &a_ptr,
&a_size);
if (rc != PKCS11_CKR_OK || a_size != sizeof(uint32_t))
return PKCS11_CKR_TEMPLATE_INCONSISTENT;

TEE_MemMove(&modulus_bits, a_ptr, sizeof(uint32_t));

rc = get_attribute_ptr(*pub_head, PKCS11_CKA_PUBLIC_EXPONENT, &a_ptr,
&a_size);
if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
return rc;

if (rc == PKCS11_CKR_OK && a_ptr) {
TEE_InitRefAttribute(&tee_attrs[tee_count],
TEE_ATTR_RSA_PUBLIC_EXPONENT,
a_ptr, a_size);
tee_count++;
}

if (remove_empty_attribute(priv_head, PKCS11_CKA_MODULUS) ||
remove_empty_attribute(priv_head, PKCS11_CKA_PUBLIC_EXPONENT) ||
remove_empty_attribute(priv_head, PKCS11_CKA_PRIVATE_EXPONENT) ||
remove_empty_attribute(priv_head, PKCS11_CKA_PRIME_1) ||
remove_empty_attribute(priv_head, PKCS11_CKA_PRIME_2) ||
remove_empty_attribute(priv_head, PKCS11_CKA_EXPONENT_1) ||
remove_empty_attribute(priv_head, PKCS11_CKA_EXPONENT_2) ||
remove_empty_attribute(priv_head, PKCS11_CKA_COEFFICIENT)) {
EMSG("Unexpected attribute(s) found");
rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
goto out;
}

/* Create an RSA TEE key */
res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, modulus_bits,
&tee_obj);
if (res) {
DMSG("TEE_AllocateTransientObject failed %#"PRIx32, res);

rc = tee2pkcs_error(res);
goto out;
}

res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE);
if (res) {
DMSG("TEE_RestrictObjectUsage1 failed %#"PRIx32, res);

rc = tee2pkcs_error(res);
goto out;
}

res = TEE_GenerateKey(tee_obj, modulus_bits, tee_attrs, tee_count);
if (res) {
DMSG("TEE_GenerateKey failed %#"PRIx32, res);

rc = tee2pkcs_error(res);
goto out;
}

rc = tee2pkcs_rsa_attributes(pub_head, priv_head, tee_obj);

out:
if (tee_obj != TEE_HANDLE_NULL)
TEE_CloseObject(tee_obj);

return rc;
}
1 change: 1 addition & 0 deletions ta/pkcs11/src/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ srcs-y += processing_aes.c
srcs-y += processing_asymm.c
srcs-y += processing_digest.c
srcs-y += processing_ec.c
srcs-y += processing_rsa.c
srcs-y += processing_symm.c
srcs-y += sanitize_object.c
srcs-y += serializer.c
Expand Down
10 changes: 10 additions & 0 deletions ta/pkcs11/src/token_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ static const struct pkcs11_mechachism_modes pkcs11_modes[] = {
MECHANISM(PKCS11_CKM_ECDSA_SHA256, CKFM_AUTH_NO_RECOVER, ANY_PART),
MECHANISM(PKCS11_CKM_ECDSA_SHA384, CKFM_AUTH_NO_RECOVER, ANY_PART),
MECHANISM(PKCS11_CKM_ECDSA_SHA512, CKFM_AUTH_NO_RECOVER, ANY_PART),
/* RSA */
MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN,
PKCS11_CKFM_GENERATE_KEY_PAIR, ANY_PART),
};

#if CFG_TEE_TA_LOG_LEVEL > 0
Expand Down Expand Up @@ -212,6 +215,8 @@ const struct pkcs11_mechachism_modes token_mechanism[] = {
TA_MECHANISM(PKCS11_CKM_ECDSA_SHA256, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_ECDSA_SHA384, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_ECDSA_SHA512, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN,
PKCS11_CKFM_GENERATE_KEY_PAIR),
};

/*
Expand Down Expand Up @@ -321,6 +326,10 @@ void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id,
*min_key_size = 160; /* in bits */
*max_key_size = 521; /* in bits */
break;
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
*min_key_size = 256; /* in bits */
*max_key_size = 4096; /* in bits */
break;
default:
*min_key_size = 0;
*max_key_size = 0;
Expand All @@ -344,6 +353,7 @@ void mechanism_supported_key_sizes_bytes(uint32_t proc_id,
case PKCS11_CKM_ECDSA_SHA256:
case PKCS11_CKM_ECDSA_SHA384:
case PKCS11_CKM_ECDSA_SHA512:
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
/* Size is in bits -> convert to bytes and ceil */
*min_key_size = ROUNDUP(*min_key_size, 8) / 8;
*max_key_size = ROUNDUP(*max_key_size, 8) / 8;
Expand Down

0 comments on commit 8692283

Please sign in to comment.