Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ta: pkcs11: CKM_RSA_X_509 ("raw RSA") support #7030

Merged
merged 2 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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*/
161 changes: 160 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,28 @@ 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_ENCRYPT:
case PKCS11_FUNCTION_VERIFY:
mode = TEE_MODE_ENCRYPT;
break;
case PKCS11_FUNCTION_DECRYPT:
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 +409,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 +484,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 +741,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 +825,135 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
break;
}
break;

case PKCS11_CKM_RSA_X_509:
switch (function) {
case PKCS11_FUNCTION_ENCRYPT:
/*
* Input message size shall be at most the key size
* As encrypting with raw RSA can be unsafe, it
* remains the responsibility of the client to
* prolerly pad the message for safe usage.
*/
if (in_size > sz) {
rc = PKCS11_CKR_DATA_LEN_RANGE;
break;
}
res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
tee_attrs, tee_attrs_count,
in_buf, in_size,
out_buf, &out_size);
output_data = true;
rc = tee2pkcs_error(res);
if (rc == PKCS11_CKR_ARGUMENTS_BAD)
rc = PKCS11_CKR_DATA_LEN_RANGE;
break;
case PKCS11_FUNCTION_DECRYPT:
/*
* Input message size shall be at most the key size
* As decrypting with raw RSA can be unsafe, it
* remains the responsibility of the encryption
* instance to have prolerly padded its message.
*/
if (in_size > sz) {
rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
break;
}

res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
tee_attrs, tee_attrs_count,
in_buf, in_size,
out_buf, &out_size);
output_data = true;
rc = tee2pkcs_error(res);
if (rc == PKCS11_CKR_ARGUMENTS_BAD)
rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
break;
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 @@ -775,3 +775,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_CIPHER | 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