Skip to content

Commit

Permalink
ta: pkcs11: add CKM_RSA_X_509 authentication
Browse files Browse the repository at this point in the history
Add support for CKM_RSA_X_509 mechanism for sing/verify operations.

Sign and verify operations are processed using TEE decrypt/encrypt
operation since GP TEE Internal Core API specification only allows
these modes for TEE_ALG_RSA_NOPAD algorithm. The pkcs11 TA only support
sign operation when the provided payload is exactly of the same size
as the RSA key used and checks the generate signature is of right size.

This mechanism can be needed to support CKM_RSA_X_509 for TLSv1.2
connections.

Add CFG_PKCS11_TA_RSA_X_509 to allow configuring the pkcs11 TA
with or without raw RSA crypto support. The config switch is default
enabled.

Signed-off-by: Alexandre Marechal <[email protected]>
Signed-off-by: Etienne Carriere <[email protected]>
Acked-by: Rouven Czerwinski <[email protected]>
  • Loading branch information
AMARSTM authored and jforissier committed Nov 22, 2024
1 parent b505a58 commit e02f17f
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 1 deletion.
1 change: 1 addition & 0 deletions ta/pkcs11/include/pkcs11_ta.h
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,7 @@ enum pkcs11_certificate_category {
enum pkcs11_mechanism_id {
PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000,
PKCS11_CKM_RSA_PKCS = 0x00001,
PKCS11_CKM_RSA_X_509 = 0x00003,
PKCS11_CKM_MD5_RSA_PKCS = 0x00005,
PKCS11_CKM_SHA1_RSA_PKCS = 0x00006,
PKCS11_CKM_RSA_PKCS_OAEP = 0x00009,
Expand Down
1 change: 1 addition & 0 deletions ta/pkcs11/src/pkcs11_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,7 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
case PKCS11_CKM_RSA_AES_KEY_WRAP:
case PKCS11_CKM_RSA_PKCS_OAEP:
case PKCS11_CKM_RSA_PKCS_PSS:
case PKCS11_CKM_RSA_X_509:
case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
Expand Down
1 change: 1 addition & 0 deletions ta/pkcs11/src/pkcs11_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ static const struct any_id __maybe_unused string_rc[] = {
PKCS11_ID(PKCS11_CKR_ATTRIBUTE_TYPE_INVALID),
PKCS11_ID(PKCS11_CKR_ATTRIBUTE_VALUE_INVALID),
PKCS11_ID(PKCS11_CKR_ACTION_PROHIBITED),
PKCS11_ID(PKCS11_CKR_DATA_INVALID),
PKCS11_ID(PKCS11_CKR_DATA_LEN_RANGE),
PKCS11_ID(PKCS11_CKR_DEVICE_MEMORY),
PKCS11_ID(PKCS11_CKR_ENCRYPTED_DATA_INVALID),
Expand Down
2 changes: 2 additions & 0 deletions ta/pkcs11/src/processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,6 @@ enum pkcs11_rc pkcs2tee_algo_ecdh(uint32_t *tee_id,
struct pkcs11_attribute_head *proc_params,
struct pkcs11_object *obj);

enum pkcs11_rc pkcs2tee_rsa_nopad_context(struct active_processing *proc);

#endif /*PKCS11_TA_PROCESSING_H*/
118 changes: 117 additions & 1 deletion ta/pkcs11/src/processing_asymm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <assert.h>
#include <compiler.h>
#include <mbedtls/nist_kw.h>
#include <string_ext.h>
#include <tee_api_defines.h>
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>
Expand All @@ -22,6 +23,7 @@ bool processing_is_tee_asymm(uint32_t proc_id)
/* RSA flavors */
case PKCS11_CKM_RSA_AES_KEY_WRAP:
case PKCS11_CKM_RSA_PKCS:
case PKCS11_CKM_RSA_X_509:
case PKCS11_CKM_RSA_PKCS_OAEP:
case PKCS11_CKM_RSA_PKCS_PSS:
case PKCS11_CKM_MD5_RSA_PKCS:
Expand Down Expand Up @@ -66,6 +68,7 @@ pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
{ PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 },
{ PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 },
{ PKCS11_CKM_RSA_PKCS_PSS, 1, 0 },
{ PKCS11_CKM_RSA_X_509, TEE_ALG_RSA_NOPAD, 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,
Expand Down Expand Up @@ -227,7 +230,26 @@ allocate_tee_operation(struct pkcs11_session *session,
if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj))
return PKCS11_CKR_FUNCTION_FAILED;

pkcs2tee_mode(&mode, function);
/*
* PKCS#11 allows Sign/Verify with CKM_RSA_X_509 while GP TEE API
* only permits Encrypt/Decrypt with TEE_ALG_RSA_NOPAD.
* For other algorithm, use simple 1-to-1 ID conversion pkcs2tee_mode().
*/
if (params->id == PKCS11_CKM_RSA_X_509) {
assert(!hash_algo);
switch (function) {
case PKCS11_FUNCTION_VERIFY:
mode = TEE_MODE_ENCRYPT;
break;
case PKCS11_FUNCTION_SIGN:
mode = TEE_MODE_DECRYPT;
break;
default:
TEE_Panic(0);
}
} else {
pkcs2tee_mode(&mode, function);
}

if (hash_algo) {
pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
Expand Down Expand Up @@ -385,6 +407,9 @@ init_tee_operation(struct pkcs11_session *session,
struct active_processing *proc = session->processing;

switch (proc_params->id) {
case PKCS11_CKM_RSA_X_509:
rc = pkcs2tee_rsa_nopad_context(proc);
break;
case PKCS11_CKM_RSA_PKCS_PSS:
case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
Expand Down Expand Up @@ -457,10 +482,12 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
void *in2_buf = NULL;
void *out_buf = NULL;
void *hash_buf = NULL;
void *temp_buf = NULL;
uint32_t in_size = 0;
uint32_t in2_size = 0;
size_t out_size = 0;
size_t hash_size = 0;
size_t temp_size = 0;
TEE_Attribute *tee_attrs = NULL;
size_t tee_attrs_count = 0;
bool output_data = false;
Expand Down Expand Up @@ -712,6 +739,7 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
}
break;
case PKCS11_CKM_RSA_PKCS:
case PKCS11_CKM_RSA_X_509:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_SHA224_RSA_PKCS:
Expand Down Expand Up @@ -795,6 +823,94 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
break;
}
break;

case PKCS11_CKM_RSA_X_509:
switch (function) {
case PKCS11_FUNCTION_SIGN:
/*
* GP TEE API only allows Decrypt, not Verify operation,
* on TEE_ALG_RSA_NOPAD. Be a bit strict on the size and
* content of the message and ensure the generate
* signature as the size of the modulus (@sz here).
*
* It remains the responsibility of the client to have
* a safe padding scheme for the provided message data.
*/
if (in_size != sz) {
EMSG("Invalid data size %"PRIu32" != %zu",
in_size, sz);
rc = PKCS11_CKR_DATA_LEN_RANGE;
break;
}

if (out_size < sz) {
rc = PKCS11_CKR_BUFFER_TOO_SMALL;
out_size = sz;
output_data = true;
break;
}

temp_size = sz;
temp_buf = proc->extra_ctx;
res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
tee_attrs, tee_attrs_count,
in_buf, in_size,
temp_buf, &temp_size);
if (!res && temp_size != sz) {
EMSG("CMK_RSA_X509: signature size %zu != %zu",
temp_size, sz);
rc = PKCS11_CKR_DATA_INVALID;
break;
}
if (!res) {
TEE_MemMove(out_buf, temp_buf, sz);
TEE_MemFill(temp_buf, 0xa5, sz);
}
output_data = true;
rc = tee2pkcs_error(res);
out_size = sz;
break;
case PKCS11_FUNCTION_VERIFY:
/*
* GP TEE API only allows Encrypt, not Verify operation,
* on TEE_ALG_RSA_NOPAD. Encrypt signature in
* temporary buffer preallocated to the size of the key.
*/
temp_size = sz;
temp_buf = proc->extra_ctx;
res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
tee_attrs, tee_attrs_count,
in2_buf, in2_size,
temp_buf, &temp_size);
rc = tee2pkcs_error(res);
if (rc == PKCS11_CKR_OK) {
/*
* Skip nul bytes heading message before
* comparing encrypted signature.
*/
char *ptr = in_buf;
size_t n = 0;

for (n = 0; n < in_size; n++)
if (ptr[n])
break;
in_size -= n;
ptr += n;
if (n > 1)
IMSG("Unsafe signature: skip %zu bytes",
n);

if (temp_size != in_size ||
consttime_memcmp(temp_buf, ptr, in_size))
rc = PKCS11_CKR_SIGNATURE_INVALID;
}
break;
default:
TEE_Panic(function);
break;
}
break;

case PKCS11_CKM_ECDSA_SHA1:
case PKCS11_CKM_ECDSA_SHA224:
case PKCS11_CKM_ECDSA_SHA256:
Expand Down
19 changes: 19 additions & 0 deletions ta/pkcs11/src/processing_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,3 +777,22 @@ size_t rsa_get_input_max_byte_size(TEE_OperationHandle op)

return info.maxKeySize / 8;
}

enum pkcs11_rc pkcs2tee_rsa_nopad_context(struct active_processing *proc)
{
size_t key_size = 0;

/*
* RSA no-pad (CKM_RSA_X_509) verify needs a buffer of the size
* of the key to safely run.
*/
key_size = rsa_get_input_max_byte_size(proc->tee_op_handle);
if (!key_size)
return PKCS11_CKR_GENERAL_ERROR;

proc->extra_ctx = TEE_Malloc(key_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
if (!proc->extra_ctx)
return PKCS11_CKR_DEVICE_MEMORY;

return PKCS11_CKR_OK;
}
7 changes: 7 additions & 0 deletions ta/pkcs11/src/token_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ static const struct pkcs11_mechachism_modes pkcs11_modes[] = {
CKFM_AUTH_WITH_RECOVER, SINGLE_PART_ONLY),
MECHANISM(PKCS11_CKM_RSA_PKCS_OAEP, CKFM_CIPHER_WRAP,
SINGLE_PART_ONLY),
MECHANISM(PKCS11_CKM_RSA_X_509, CKFM_CIPHER_WRAP |
CKFM_AUTH_NO_RECOVER | CKFM_AUTH_WITH_RECOVER,
SINGLE_PART_ONLY),
MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER,
SINGLE_PART_ONLY),
MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART),
Expand Down Expand Up @@ -274,6 +277,9 @@ const struct pkcs11_mechachism_modes token_mechanism[] = {
TA_MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN,
PKCS11_CKFM_GENERATE_KEY_PAIR),
TA_MECHANISM(PKCS11_CKM_RSA_PKCS, CKFM_CIPHER | CKFM_AUTH_NO_RECOVER),
#ifdef CFG_PKCS11_TA_RSA_X_509
TA_MECHANISM(PKCS11_CKM_RSA_X_509, CKFM_AUTH_NO_RECOVER),
#endif
TA_MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS, CKFM_AUTH_NO_RECOVER),
Expand Down Expand Up @@ -413,6 +419,7 @@ void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id,
break;
case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
case PKCS11_CKM_RSA_PKCS:
case PKCS11_CKM_RSA_X_509:
case PKCS11_CKM_MD5_RSA_PKCS:
case PKCS11_CKM_SHA1_RSA_PKCS:
case PKCS11_CKM_RSA_PKCS_OAEP:
Expand Down
5 changes: 5 additions & 0 deletions ta/pkcs11/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ CFG_PKCS11_TA_TOKEN_COUNT ?= 3
# When enabled, embed support for object checksum value computation
CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE ?= y

# When enabled, embed support for CKM_RSA_X_509 (a.k.a. Raw RSA) ciphering
# and authentication. The feature can be needed for some TLS v1.2 connections.
# Raw RSA can be unsafe if client uses a weak clear data padding scheme.
CFG_PKCS11_TA_RSA_X_509 ?= y

global-incdirs-y += include
global-incdirs-y += src
subdirs-y += src

0 comments on commit e02f17f

Please sign in to comment.