Skip to content

Commit

Permalink
ta: pkcs11: Add support for RSA signing & verification
Browse files Browse the repository at this point in the history
Add support for performing RSA signing & verification operations for:

- PKCS #1 v1.5 RSA with supplied hash value
- Multi stage MD5
- Multi stage SHA-1
- Multi stage SHA-224
- Multi stage SHA-256
- Multi stage SHA-384
- Multi stage SHA-512

Specified in:
PKCS #11 Cryptographic Token Interface Current Mechanisms Specification
Version 2.40 Plus Errata 01
2.1 RSA

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 8692283 commit 0442c95
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 0 deletions.
7 changes: 7 additions & 0 deletions ta/pkcs11/include/pkcs11_ta.h
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,13 @@ enum pkcs11_key_type {
*/
enum pkcs11_mechanism_id {
PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000,
PKCS11_CKM_RSA_PKCS = 0x00001,
PKCS11_CKM_MD5_RSA_PKCS = 0x00005,
PKCS11_CKM_SHA1_RSA_PKCS = 0x00006,
PKCS11_CKM_SHA256_RSA_PKCS = 0x00040,
PKCS11_CKM_SHA384_RSA_PKCS = 0x00041,
PKCS11_CKM_SHA512_RSA_PKCS = 0x00042,
PKCS11_CKM_SHA224_RSA_PKCS = 0x00046,
PKCS11_CKM_MD5 = 0x00210,
PKCS11_CKM_MD5_HMAC = 0x00211,
PKCS11_CKM_SHA_1 = 0x00220,
Expand Down
22 changes: 22 additions & 0 deletions ta/pkcs11/src/pkcs11_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,28 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
}
break;
case PKCS11_CKM_RSA_PKCS:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
if (key_type != PKCS11_CKK_RSA) {
EMSG("Invalid key %s for mechanism %s",
id2str_type(key_type, key_class),
id2str_proc(proc_id));

return PKCS11_CKR_KEY_TYPE_INCONSISTENT;
}
if (key_class != PKCS11_CKO_PUBLIC_KEY &&
key_class != PKCS11_CKO_PRIVATE_KEY) {
EMSG("Invalid key class for mechanism %s",
id2str_proc(proc_id));

return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
}
break;
default:
DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
id2str_proc(proc_id));
Expand Down
5 changes: 5 additions & 0 deletions ta/pkcs11/src/processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ size_t get_object_key_bit_size(struct pkcs11_object *obj)
if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
return 0;

return a_size * 8;
case PKCS11_CKK_RSA:
if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size))
return 0;

return a_size * 8;
case PKCS11_CKK_EC:
if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS,
Expand Down
6 changes: 6 additions & 0 deletions ta/pkcs11/src/processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,14 @@ size_t ecdsa_get_input_max_byte_size(TEE_OperationHandle op);
/*
* RSA crypto algorithm specific functions
*/
enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs,
size_t *tee_count,
struct pkcs11_object *obj);

enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params,
struct obj_attrs **pub_head,
struct obj_attrs **priv_head);

size_t rsa_get_input_max_byte_size(TEE_OperationHandle op);

#endif /*PKCS11_TA_PROCESSING_H*/
86 changes: 86 additions & 0 deletions ta/pkcs11/src/processing_asymm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
bool processing_is_tee_asymm(uint32_t proc_id)
{
switch (proc_id) {
/* RSA flavors */
case PKCS11_CKM_RSA_PKCS:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
/* EC flavors */
case PKCS11_CKM_ECDSA:
case PKCS11_CKM_ECDSA_SHA1:
Expand All @@ -42,6 +50,20 @@ pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
uint32_t tee_id;
uint32_t tee_hash_id;
} pkcs2tee_algo[] = {
/* RSA flavors */
{ PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 },
{ PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5,
TEE_ALG_MD5 },
{ PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1,
TEE_ALG_SHA1 },
{ PKCS11_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224,
TEE_ALG_SHA224 },
{ PKCS11_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256,
TEE_ALG_SHA256 },
{ PKCS11_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384,
TEE_ALG_SHA384 },
{ PKCS11_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512,
TEE_ALG_SHA512 },
/* EC flavors (Must find key size from the object) */
{ PKCS11_CKM_ECDSA, 1, 0 },
{ PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 },
Expand Down Expand Up @@ -78,6 +100,16 @@ pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
break;
}

/*
* PKCS#11 uses single mechanism CKM_RSA_PKCS for both ciphering and
* authentication whereas GPD TEE expects TEE_ALG_RSAES_PKCS1_V1_5 for
* ciphering and TEE_ALG_RSASSA_PKCS1_V1_5 for authentication.
*/
if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 &&
(function == PKCS11_FUNCTION_SIGN ||
function == PKCS11_FUNCTION_VERIFY))
*tee_id = TEE_ALG_RSASSA_PKCS1_V1_5;

return rc;
}

Expand Down Expand Up @@ -106,6 +138,12 @@ static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
else
*tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY;
break;
case PKCS11_CKK_RSA:
if (class == PKCS11_CKO_PRIVATE_KEY)
*tee_type = TEE_TYPE_RSA_KEYPAIR;
else
*tee_type = TEE_TYPE_RSA_PUBLIC_KEY;
break;
default:
TEE_Panic(type);
break;
Expand Down Expand Up @@ -188,6 +226,13 @@ static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,

if (obj->key_handle != TEE_HANDLE_NULL) {
switch (type) {
case PKCS11_CKK_RSA:
/* RSA loaded keys can be reused */
assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY &&
class == PKCS11_CKO_PUBLIC_KEY) ||
(obj->key_type == TEE_TYPE_RSA_KEYPAIR &&
class == PKCS11_CKO_PRIVATE_KEY));
goto key_ready;
case PKCS11_CKK_EC:
/* Reuse EC TEE key only if already DSA or DH */
switch (obj->key_type) {
Expand Down Expand Up @@ -219,6 +264,9 @@ static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
return PKCS11_CKR_GENERAL_ERROR;

switch (type) {
case PKCS11_CKK_RSA:
rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj);
break;
case PKCS11_CKK_EC:
rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
break;
Expand Down Expand Up @@ -362,6 +410,12 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
case PKCS11_CKM_ECDSA_SHA256:
case PKCS11_CKM_ECDSA_SHA384:
case PKCS11_CKM_ECDSA_SHA512:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);

TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf,
Expand Down Expand Up @@ -389,6 +443,12 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
case PKCS11_CKM_ECDSA_SHA256:
case PKCS11_CKM_ECDSA_SHA384:
case PKCS11_CKM_ECDSA_SHA512:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);

hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
Expand Down Expand Up @@ -453,13 +513,33 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
goto out;
}
break;
case PKCS11_CKM_RSA_PKCS:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
/* Get key size in bytes */
sz = rsa_get_input_max_byte_size(proc->tee_op_handle);
if (!sz) {
rc = PKCS11_CKR_FUNCTION_FAILED;
goto out;
}

if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) {
rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
goto out;
}
break;
default:
break;
}

/* Next perform actual signing operation */
switch (proc->mecha_type) {
case PKCS11_CKM_ECDSA:
case PKCS11_CKM_RSA_PKCS:
/* For operations using provided input data */
switch (function) {
case PKCS11_FUNCTION_ENCRYPT:
Expand Down Expand Up @@ -509,6 +589,12 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
case PKCS11_CKM_ECDSA_SHA256:
case PKCS11_CKM_ECDSA_SHA384:
case PKCS11_CKM_ECDSA_SHA512:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
case PKCS11_CKM_SHA256_RSA_PKCS:
case PKCS11_CKM_SHA384_RSA_PKCS:
case PKCS11_CKM_SHA512_RSA_PKCS:
/* For operations having hash operation use calculated hash */
switch (function) {
case PKCS11_FUNCTION_SIGN:
Expand Down
115 changes: 115 additions & 0 deletions ta/pkcs11/src/processing_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,114 @@
#include <tee_internal_api_extensions.h>

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

enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs,
size_t *tee_count,
struct pkcs11_object *obj)
{
TEE_Attribute *attrs = NULL;
size_t count = 0;
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
void *a_ptr = NULL;

assert(get_key_type(obj->attributes) == PKCS11_CKK_RSA);

switch (get_class(obj->attributes)) {
case PKCS11_CKO_PUBLIC_KEY:
attrs = TEE_Malloc(2 * sizeof(TEE_Attribute),
TEE_USER_MEM_HINT_NO_FILL_ZERO);
if (!attrs)
return PKCS11_CKR_DEVICE_MEMORY;

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS,
obj, PKCS11_CKA_MODULUS))
count++;

if (pkcs2tee_load_attr(&attrs[count],
TEE_ATTR_RSA_PUBLIC_EXPONENT, obj,
PKCS11_CKA_PUBLIC_EXPONENT))
count++;

if (count == 2)
rc = PKCS11_CKR_OK;

break;

case PKCS11_CKO_PRIVATE_KEY:
attrs = TEE_Malloc(8 * sizeof(TEE_Attribute),
TEE_USER_MEM_HINT_NO_FILL_ZERO);
if (!attrs)
return PKCS11_CKR_DEVICE_MEMORY;

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS,
obj, PKCS11_CKA_MODULUS))
count++;

if (pkcs2tee_load_attr(&attrs[count],
TEE_ATTR_RSA_PUBLIC_EXPONENT, obj,
PKCS11_CKA_PUBLIC_EXPONENT))
count++;

if (pkcs2tee_load_attr(&attrs[count],
TEE_ATTR_RSA_PRIVATE_EXPONENT, obj,
PKCS11_CKA_PRIVATE_EXPONENT))
count++;

if (count != 3)
break;

/* If pre-computed values are present load those */
rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_PRIME_1,
&a_ptr, NULL);
if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
break;
if (rc == PKCS11_RV_NOT_FOUND || !a_ptr) {
rc = PKCS11_CKR_OK;
break;
}

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME1, obj,
PKCS11_CKA_PRIME_1))
count++;

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME2, obj,
PKCS11_CKA_PRIME_2))
count++;

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_EXPONENT1,
obj, PKCS11_CKA_EXPONENT_1))
count++;

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_EXPONENT2,
obj, PKCS11_CKA_EXPONENT_2))
count++;

if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_COEFFICIENT,
obj, PKCS11_CKA_COEFFICIENT))
count++;

if (count == 8)
rc = PKCS11_CKR_OK;

break;

default:
assert(0);
break;
}

if (rc == PKCS11_CKR_OK) {
*tee_attrs = attrs;
*tee_count = count;
} else {
TEE_Free(attrs);
}

return rc;
}

static enum pkcs11_rc tee2pkcs_rsa_attributes(struct obj_attrs **pub_head,
struct obj_attrs **priv_head,
TEE_ObjectHandle tee_obj)
Expand Down Expand Up @@ -169,3 +275,12 @@ enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params,

return rc;
}

size_t rsa_get_input_max_byte_size(TEE_OperationHandle op)
{
TEE_OperationInfo info = { };

TEE_GetOperationInfo(op, &info);

return info.maxKeySize / 8;
}

0 comments on commit 0442c95

Please sign in to comment.