diff --git a/common/attrs.c b/common/attrs.c index cbe09531..c10cb3c6 100644 --- a/common/attrs.c +++ b/common/attrs.c @@ -779,9 +779,13 @@ attribute_is_sensitive (const CK_ATTRIBUTE *attr, X (CKA_IBM_PROTKEY_EXTRACTABLE) X (CKA_IBM_PROTKEY_NEVER_EXTRACTABLE) X (CKA_IBM_OPAQUE_PKEY) + X (CKA_IBM_DILITHIUM_MODE) X (CKA_IBM_DILITHIUM_KEYFORM) X (CKA_IBM_DILITHIUM_RHO) X (CKA_IBM_DILITHIUM_T1) + X (CKA_IBM_KYBER_MODE) + X (CKA_IBM_KYBER_PK) + X (CKA_IBM_KYBER_KEYFORM) case CKA_VALUE: return (klass != CKO_CERTIFICATE && klass != CKO_X_CERTIFICATE_EXTENSION); diff --git a/common/constants.c b/common/constants.c index e2c3cb37..31e1ce01 100644 --- a/common/constants.c +++ b/common/constants.c @@ -145,6 +145,10 @@ const p11_constant p11_constant_types[] = { CT (CKA_UNWRAP_TEMPLATE, "unwrap-template") CT (CKA_ALLOWED_MECHANISMS, "allowed-mechanisms") CT (CKA_IBM_OPAQUE, "ibm-opaque") + CT (CKA_IBM_OPAQUE_REENC, "ibm-opaque-reenc") + CT (CKA_IBM_OPAQUE_OLD, "ibm-opaque-old") + CT (CKA_IBM_KYBER_MODE, "ibm-kyber-mode") + CT (CKA_IBM_DILITHIUM_MODE, "ibm-dilithium-mode") CT (CKA_IBM_RESTRICTABLE, "ibm-restrictable") CT (CKA_IBM_NEVER_MODIFIABLE, "ibm-never-modifiable") CT (CKA_IBM_RETAINKEY, "ibm-retainkey") @@ -165,7 +169,11 @@ const p11_constant p11_constant_types[] = { CT (CKA_IBM_DILITHIUM_S2, "ibm-dilithium-s2") CT (CKA_IBM_DILITHIUM_T0, "ibm-dilithium-t0") CT (CKA_IBM_DILITHIUM_T1, "ibm-dilithium-t1") + CT (CKA_IBM_KYBER_KEYFORM, "ibm-kyber-keyform") + CT (CKA_IBM_KYBER_PK, "ibm-kyber-pk") + CT (CKA_IBM_KYBER_SK, "ibm-kyber-sk") CT (CKA_IBM_OPAQUE_PKEY, "ibm-opaque-pkey") + CT (CKA_IBM_CCA_AES_KEY_MODE, "ibm-cca-aes-key-mode") CT (CKA_NSS_URL, "nss-url") CT (CKA_NSS_EMAIL, "nss-email") CT (CKA_NSS_SMIME_INFO, "nss-smime-constant") @@ -632,11 +640,14 @@ const p11_constant p11_constant_mechanisms[] = { CT (CKM_IBM_EC_X448, "ibm-ec-x448") CT (CKM_IBM_ED448_SHA3, "ibm-ed448-sha3") CT (CKM_IBM_DILITHIUM, "ibm-dilithium") + CT (CKM_IBM_KYBER, "ibm-kyber") CT (CKM_IBM_SHA3_224_HMAC, "ibm-sha3-224-hmac") CT (CKM_IBM_SHA3_256_HMAC, "ibm-sha3-256-hmac") CT (CKM_IBM_SHA3_384_HMAC, "ibm-sha3-384-hmac") CT (CKM_IBM_SHA3_512_HMAC, "ibm-sha3-512-hmac") + CT (CKM_IBM_ECDSA_OTHER, "ibm-ecdsa-other") CT (CKM_IBM_ATTRIBUTEBOUND_WRAP, "ibm-attributebound-wrap") + CT (CKM_IBM_BTC_DERIVE, "ibm-btc-derive") { CKA_INVALID }, }; diff --git a/common/pkcs11x.h b/common/pkcs11x.h index a0e44416..12e57007 100644 --- a/common/pkcs11x.h +++ b/common/pkcs11x.h @@ -187,7 +187,19 @@ typedef CK_ULONG CK_TRUST; #define CKK_IBM_PQC_DILITHIUM CKK_VENDOR_DEFINED + 0x10023 +/* Secure key tokens store the secure key blob in attribute CKA_IBM_OPAQUE +in their key object. During an HSM master key change, the secure key blob +is being re-enciphered with the new master key. This re-enciphered secure +key blob is stored in attribute CKA_IBM_OPAQUE_REENC while the HSM master +key change operation is active. + +When a HSM master key change operation is finalized, the secure key blob +enciphered with the old master key is backed up into attribute CKA_IBM_OPAQUE_OLD, +and the re-enciphered secure key blob from CKA_IBM_OPAQUE_REENC becomes +the current one in CKA_IBM_OPAQUE. */ #define CKA_IBM_OPAQUE (CKA_VENDOR_DEFINED + 1) +#define CKA_IBM_OPAQUE_REENC (CKA_VENDOR_DEFINED + 3) +#define CKA_IBM_OPAQUE_OLD (CKA_VENDOR_DEFINED + 4) #define CKA_IBM_RESTRICTABLE (CKA_VENDOR_DEFINED + 0x10001) #define CKA_IBM_NEVER_MODIFIABLE (CKA_VENDOR_DEFINED + 0x10002) #define CKA_IBM_RETAINKEY (CKA_VENDOR_DEFINED + 0x10003) @@ -208,7 +220,13 @@ typedef CK_ULONG CK_TRUST; #define CKA_IBM_DILITHIUM_S2 (CKA_VENDOR_DEFINED + 0xd0006) #define CKA_IBM_DILITHIUM_T0 (CKA_VENDOR_DEFINED + 0xd0007) #define CKA_IBM_DILITHIUM_T1 (CKA_VENDOR_DEFINED + 0xd0008) +#define CKA_IBM_DILITHIUM_MODE (CKA_VENDOR_DEFINED + 0x00010) +#define CKA_IBM_CCA_AES_KEY_MODE (CKA_VENDOR_DEFINED + 0xd0101) #define CKA_IBM_OPAQUE_PKEY (CKA_VENDOR_DEFINED + 0xd0100) +#define CKA_IBM_KYBER_MODE (CKA_VENDOR_DEFINED + 0x0000E) +#define CKA_IBM_KYBER_KEYFORM (CKA_VENDOR_DEFINED + 0xd0009) +#define CKA_IBM_KYBER_PK (CKA_VENDOR_DEFINED + 0xd000A) +#define CKA_IBM_KYBER_SK (CKA_VENDOR_DEFINED + 0xd000B) #define CKM_IBM_SHA3_224 (CKM_VENDOR_DEFINED + 0x10001) #define CKM_IBM_SHA3_256 (CKM_VENDOR_DEFINED + 0x10002) @@ -220,20 +238,96 @@ typedef CK_ULONG CK_TRUST; #define CKM_IBM_EC_X448 (CKM_VENDOR_DEFINED + 0x1001e) #define CKM_IBM_ED448_SHA3 (CKM_VENDOR_DEFINED + 0x1001f) #define CKM_IBM_DILITHIUM (CKM_VENDOR_DEFINED + 0x10023) +#define CKM_IBM_KYBER (CKM_VENDOR_DEFINED + 0x10024) #define CKM_IBM_SHA3_224_HMAC (CKM_VENDOR_DEFINED + 0x10025) #define CKM_IBM_SHA3_256_HMAC (CKM_VENDOR_DEFINED + 0x10026) #define CKM_IBM_SHA3_384_HMAC (CKM_VENDOR_DEFINED + 0x10027) #define CKM_IBM_SHA3_512_HMAC (CKM_VENDOR_DEFINED + 0x10028) +#define CKM_IBM_ECDSA_OTHER (CKM_VENDOR_DEFINED + 0x10031) #define CKM_IBM_ATTRIBUTEBOUND_WRAP (CKM_VENDOR_DEFINED + 0x20004) +#define CKM_IBM_BTC_DERIVE (CKM_VENDOR_DEFINED + 0x70001) /* * If the caller is using the PKCS#11 GNU calling convention, then we cater * to that here. */ #ifdef CRYPTOKI_GNU +#define CK_BYTE_PTR unsigned char * +#define CK_BYTE unsigned char + +#define childKeyIndex child_key_index +#define pChainCode p_chain_code +#define ulChainCodeLen ul_cahin_code_len + +#define ulVersion ul_version +#define bPrepend b_prepend +#define pCipher p_cipher +#define ulCipherLen ul_cipher_len +#define pSharedData p_shared_data +#define hSecret h_secret + #define hSignVerifyKey h_sign_verify_key #endif +#define CKM_IBM_ECSDSA_RAND 3 +#define CKM_IBM_ECSDSA_COMPR_MULTI 5 + +struct ck_ibm_ecdsa_other { + CK_ULONG submechanism; +}; + +typedef struct ck_ibm_ecdsa_other CK_IBM_ECDSA_OTHER_PARAMS; + +struct ck_ibm_btc_derive_params { + CK_ULONG type; + CK_ULONG childKeyIndex; + CK_BYTE_PTR pChainCode; + CK_ULONG ulChainCodeLen; + CK_ULONG version; +}; + +typedef struct ck_ibm_btc_derive_params CK_IBM_BTC_DERIVE_PARAMS; + +#define CK_IBM_BIP0032_HARDENED 0x80000000 // key index flag + +#define CK_IBM_BIP0032_PRV2PRV 1 +#define CK_IBM_BIP0032_PRV2PUB 2 +#define CK_IBM_BIP0032_PUB2PUB 3 +#define CK_IBM_BIP0032_MASTERK 4 +#define CK_IBM_SLIP0010_PRV2PRV 5 +#define CK_IBM_SLIP0010_PRV2PUB 6 +#define CK_IBM_SLIP0010_PUB2PUB 7 +#define CK_IBM_SLIP0010_MASTERK 8 + +#define CK_IBM_BTC_CHAINCODE_LENGTH 32 + +#define CK_IBM_BTC_DERIVE_PARAMS_VERSION_1 1 + +#define CK_IBM_KYBER_KEYFORM_ROUND2_768 1 +#define CK_IBM_KYBER_KEYFORM_ROUND2_1024 2 + +#define CK_IBM_KYBER_KEM_VERSION 0 + +typedef CK_ULONG CK_IBM_KYBER_KDF_TYPE; +typedef CK_ULONG CK_IBM_KYBER_KEM_MODE; + +#define CK_IBM_KYBER_KEM_ENCAPSULATE 1 +#define CK_IBM_KYBER_KEM_DECAPSULATE 2 + +struct ck_ibm_kyber_params { + CK_ULONG ulVersion; + CK_IBM_KYBER_KEM_MODE mode; + CK_IBM_KYBER_KDF_TYPE kdf; + CK_BBOOL bPrepend; + CK_BYTE *pCipher; + CK_ULONG ulCipherLen; + CK_BYTE *pSharedData; + CK_ULONG ulSharedDataLen; + CK_OBJECT_HANDLE hSecret; +}; + +typedef struct ck_ibm_kyber_params CK_IBM_KYBER_PARAMS; + struct ck_ibm_attributebound_wrap { CK_OBJECT_HANDLE hSignVerifyKey; }; @@ -241,6 +335,20 @@ struct ck_ibm_attributebound_wrap { typedef struct ck_ibm_attributebound_wrap CK_IBM_ATTRIBUTEBOUND_WRAP_PARAMS; #ifdef CRYPTOKI_GNU +#undef CK_BYTE_PTR +#undef CK_BYTE + +#undef childKeyIndex +#undef pChainCode +#undef ulChainCodeLen + +#undef ulVersion +#undef bPrepend +#undef pCipher +#undef ulCipherLen +#undef pSharedData +#undef hSecret + #undef hSignVerifyKey #endif diff --git a/configure.ac b/configure.ac index a21d7509..a5eb7791 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ P11KIT_AGE=4 # ------------------------------------------------------------------------------ # p11-kit RPC protocol versions P11KIT_RPC_MIN=0 -P11KIT_RPC_MAX=1 +P11KIT_RPC_MAX=2 # ------------------------------------------------------------------------------ diff --git a/meson_options.txt b/meson_options.txt index 34d6f61d..5c49e4a2 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -83,5 +83,5 @@ option('rpc_min', type : 'integer', description : 'Minimum RPC protocol version we support') option('rpc_max', type : 'integer', - min : 0, max : 1, value : 1, + min : 0, max : 2, value : 2, description : 'Maximum RPC protocol version we support') diff --git a/p11-kit/rpc-client.c b/p11-kit/rpc-client.c index b335d915..f59cf56b 100644 --- a/p11-kit/rpc-client.c +++ b/p11-kit/rpc-client.c @@ -457,6 +457,55 @@ proto_write_mechanism (p11_rpc_message *msg, return p11_buffer_failed (msg->output) ? CKR_HOST_MEMORY : CKR_OK; } +static CK_RV +proto_read_error (p11_rpc_message *msg, CK_RV *error) +{ + if (!p11_rpc_message_read_ulong(msg, error)) + return PARSE_ERROR; + + return CKR_OK; +} + +static CK_RV +proto_read_mech_param_update (p11_rpc_message *msg, + CK_MECHANISM_PTR *mech) +{ + size_t offset; + CK_MECHANISM temp; + + assert (msg != NULL); + assert (mech != NULL); + assert (msg->input != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || p11_rpc_message_verify_part (msg, "P")); + + /* Check the length needed to store the parameter */ + memset (&temp, 0, sizeof (temp)); + temp.mechanism = (*mech)->mechanism; + offset = msg->parsed; + if (!p11_rpc_buffer_get_mech_param_update (msg->input, &offset, &temp)) { + msg->parsed = offset; + return PARSE_ERROR; + } + + /* The mechanism doesn't require parameter */ + if (temp.ulParameterLen == 0) { + msg->parsed = offset; + return CKR_OK; + } + + /* Actually retrieve the parameter */ + if ((*mech)->ulParameterLen != temp.ulParameterLen) + return CKR_MECHANISM_PARAM_INVALID; + if (!p11_rpc_buffer_get_mech_param_update (msg->input, &msg->parsed, *mech)) + return PARSE_ERROR; + + assert (msg->parsed == offset); + + return CKR_OK; +} + static CK_RV proto_read_info (p11_rpc_message *msg, CK_INFO_PTR info) @@ -652,6 +701,16 @@ proto_read_sesssion_info (p11_rpc_message *msg, if (_ret == CKR_OK && !p11_rpc_message_read_ulong (&_msg, val)) \ _ret = PARSE_ERROR; +#define OUT_MECH_PARAM_UPDATE(mech) \ + if (_ret != CKR_OK) goto _cleanup; \ + _ret = proto_read_mech_param_update (&_msg, &mech); \ + if (_ret != CKR_OK) goto _cleanup; + +#define OUT_ERROR(err) \ + if (_ret != CKR_OK) goto _cleanup; \ + _ret = proto_read_error (&_msg, &err); + + #define OUT_BYTE_ARRAY(arr, len) \ if (len == NULL) \ _ret = CKR_ARGUMENTS_BAD; \ @@ -706,6 +765,17 @@ proto_read_sesssion_info (p11_rpc_message *msg, if (_ret == CKR_OK) \ _ret = proto_read_mechanism_info (&_msg, info); +// EARLY_EXIT_ON_FAIL +#define PREP_EEOF \ + CK_RV err; + +#define PROCESS_CALL_NO_CHECK \ + _ret = call_run (_mod, &_msg); + +#define CHECK_EEOF \ + if(err != CKR_OK) \ + _ret = err; + /* ------------------------------------------------------------------- * INITIALIZATION and 'GLOBAL' CALLS @@ -1874,13 +1944,13 @@ rpc_C_UnwrapKey (CK_X_FUNCTION_LIST *self, } static CK_RV -rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self, - CK_SESSION_HANDLE session, - CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE base_key, - CK_ATTRIBUTE_PTR template, - CK_ULONG count, - CK_OBJECT_HANDLE_PTR key) +C_DeriveKey1 (CK_X_FUNCTION_LIST *self, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) { BEGIN_CALL_OR (C_DeriveKey, self, CKR_SESSION_HANDLE_INVALID); IN_ULONG (session); @@ -1892,6 +1962,46 @@ rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self, END_CALL; } +static CK_RV +C_DeriveKey2 (CK_X_FUNCTION_LIST *self, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + PREP_EEOF; + BEGIN_CALL_OR (C_DeriveKey2, self, CKR_SESSION_HANDLE_INVALID); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (base_key); + IN_ATTRIBUTE_ARRAY (template, count); + PROCESS_CALL_NO_CHECK; + OUT_ERROR (err); + OUT_MECH_PARAM_UPDATE (mechanism); + CHECK_EEOF; + OUT_ULONG (key); + END_CALL; +} + +static CK_RV +rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self, + CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + uint8_t version = RPC_VERSION; + + if (version <= 1) + return C_DeriveKey1 (self, session, mechanism, base_key, template, count, key); + else + return C_DeriveKey2 (self, session, mechanism, base_key, template, count, key); +} + static CK_RV rpc_C_SeedRandom (CK_X_FUNCTION_LIST *self, CK_SESSION_HANDLE session, diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c index ea902553..049417f6 100644 --- a/p11-kit/rpc-message.c +++ b/p11-kit/rpc-message.c @@ -850,8 +850,10 @@ map_attribute_to_value_type (CK_ATTRIBUTE_TYPE type) case CKA_BITS_PER_PIXEL: case CKA_MECHANISM_TYPE: case CKA_IBM_DILITHIUM_KEYFORM: + case CKA_IBM_CCA_AES_KEY_MODE: case CKA_IBM_STD_COMPLIANCE1: case CKA_IBM_KEYTYPE: + case CKA_IBM_KYBER_KEYFORM: return P11_RPC_VALUE_ULONG; case CKA_WRAP_TEMPLATE: case CKA_UNWRAP_TEMPLATE: @@ -902,10 +904,13 @@ map_attribute_to_value_type (CK_ATTRIBUTE_TYPE type) case CKA_DEFAULT_CMS_ATTRIBUTES: case CKA_SUPPORTED_CMS_ATTRIBUTES: case CKA_IBM_OPAQUE: + case CKA_IBM_OPAQUE_REENC: + case CKA_IBM_OPAQUE_OLD: case CKA_IBM_CV: case CKA_IBM_MACKEY: case CKA_IBM_STRUCT_PARAMS: case CKA_IBM_OPAQUE_PKEY: + case CKA_IBM_DILITHIUM_MODE: case CKA_IBM_DILITHIUM_RHO: case CKA_IBM_DILITHIUM_SEED: case CKA_IBM_DILITHIUM_TR: @@ -913,6 +918,9 @@ map_attribute_to_value_type (CK_ATTRIBUTE_TYPE type) case CKA_IBM_DILITHIUM_S2: case CKA_IBM_DILITHIUM_T0: case CKA_IBM_DILITHIUM_T1: + case CKA_IBM_KYBER_MODE: + case CKA_IBM_KYBER_PK: + case CKA_IBM_KYBER_SK: return P11_RPC_VALUE_BYTE_ARRAY; } } @@ -1660,6 +1668,368 @@ p11_rpc_buffer_get_ibm_attrbound_wrap_mechanism_value (p11_buffer *buffer, return true; } +void +p11_rpc_buffer_add_ibm_kyber_mech_param_update (p11_buffer *buffer, + const void *value, + CK_ULONG value_length) +{ + CK_IBM_KYBER_PARAMS params; + + if (value_length != sizeof (CK_IBM_KYBER_PARAMS)) { + p11_buffer_fail (buffer); + return; + } + + memcpy (¶ms, value, value_length); + + if (params.mode == CK_IBM_KYBER_KEM_ENCAPSULATE) { + p11_rpc_buffer_add_byte(buffer, CK_IBM_KYBER_KEM_ENCAPSULATE); + + if (params.pCipher == NULL) { + p11_rpc_buffer_add_byte(buffer, 0); + p11_rpc_buffer_add_uint32(buffer, params.ulCipherLen); + } else { + p11_rpc_buffer_add_byte(buffer, 1); + p11_rpc_buffer_add_byte_array(buffer, (unsigned char *)params.pCipher, params.ulCipherLen); + } + } else { + p11_rpc_buffer_add_byte(buffer, CK_IBM_KYBER_KEM_DECAPSULATE); + } +} + +bool +p11_rpc_buffer_get_ibm_kyber_mech_param_update (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length) +{ + const unsigned char *data; + size_t len; + unsigned char has_data; + unsigned char capsulation; + uint32_t length; + + if (!p11_rpc_buffer_get_byte(buffer, offset, &capsulation)) + return false; + + if (capsulation == CK_IBM_KYBER_KEM_ENCAPSULATE) { + if (!p11_rpc_buffer_get_byte(buffer, offset, &has_data)) + return false; + + if (has_data == 0) { + if (!p11_rpc_buffer_get_uint32(buffer, offset, &length)) + return false; + len = length; + } else { + if (!p11_rpc_buffer_get_byte_array(buffer, offset, &data, &len)) + return false; + } + + if (value) { + CK_IBM_KYBER_PARAMS *params = (CK_IBM_KYBER_PARAMS *) value; + + if (params->pCipher && params->ulCipherLen == len) { + memcpy(params->pCipher, data, len); + params->ulCipherLen = len; + } else { + params->pCipher = (void *) data; + params->ulCipherLen = len; + } + } + } + + if (value_length) + *value_length = sizeof (CK_IBM_KYBER_PARAMS); + + return true; +} + +void +p11_rpc_buffer_add_ibm_btc_derive_mech_param_update (p11_buffer *buffer, + const void *value, + CK_ULONG value_length) +{ + CK_IBM_BTC_DERIVE_PARAMS params; + + if (value_length != sizeof (CK_IBM_BTC_DERIVE_PARAMS)) { + p11_buffer_fail (buffer); + return; + } + + memcpy (¶ms, value, value_length); + + if (params.pChainCode == NULL) { + p11_rpc_buffer_add_byte(buffer, 0); + p11_rpc_buffer_add_uint32(buffer, params.ulChainCodeLen); + } else { + p11_rpc_buffer_add_byte(buffer, 1); + p11_rpc_buffer_add_byte_array(buffer, (unsigned char *)params.pChainCode, params.ulChainCodeLen); + } +} + +bool +p11_rpc_buffer_get_ibm_btc_derive_mech_param_update (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length) +{ + const unsigned char *data; + unsigned char has_data; + size_t len; + uint32_t length; + + if (!p11_rpc_buffer_get_byte(buffer, offset, &has_data)) + return false; + + if (has_data == 0) { + if (!p11_rpc_buffer_get_uint32(buffer, offset, &length)) + return false; + len = length; + } else { + if (!p11_rpc_buffer_get_byte_array(buffer, offset, &data, &len)) + return false; + } + + if (value) { + CK_IBM_BTC_DERIVE_PARAMS *params = (CK_IBM_BTC_DERIVE_PARAMS *) value; + + if (params->pChainCode && params->ulChainCodeLen == len) { + memcpy(params->pChainCode, data, len); + params->ulChainCodeLen = len; + } else { + params->pChainCode = (void *) data; + params->ulChainCodeLen = len; + } + } + + if (value_length) + *value_length = sizeof (CK_IBM_BTC_DERIVE_PARAMS); + + return true; +} + +void +p11_rpc_buffer_add_ibm_ecdsa_other_mechanism_value (p11_buffer *buffer, + const void *value, + CK_ULONG value_length) +{ + CK_IBM_ECDSA_OTHER_PARAMS params; + + if (value_length != sizeof (CK_IBM_ECDSA_OTHER_PARAMS)) { + p11_buffer_fail (buffer); + return; + } + + memcpy (¶ms, value, value_length); + + if (params.submechanism > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + + p11_rpc_buffer_add_uint64 (buffer, params.submechanism); +} + +bool +p11_rpc_buffer_get_ibm_ecdsa_other_mechanism_value (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length) +{ + uint64_t val1; + + if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val1)) + return false; + + if (value) { + CK_IBM_ECDSA_OTHER_PARAMS params; + + params.submechanism = val1; + + memcpy (value, ¶ms, sizeof (CK_IBM_ECDSA_OTHER_PARAMS)); + } + + if (value_length) + *value_length = sizeof (CK_IBM_ECDSA_OTHER_PARAMS); + + return true; +} + +void +p11_rpc_buffer_add_ibm_btc_derive_mechanism_value (p11_buffer *buffer, + const void *value, + CK_ULONG value_length) +{ + CK_IBM_BTC_DERIVE_PARAMS params; + + if (value_length != sizeof (CK_IBM_BTC_DERIVE_PARAMS)) { + p11_buffer_fail (buffer); + return; + } + + memcpy (¶ms, value, value_length); + + if (params.type > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.type); + + if (params.childKeyIndex > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.childKeyIndex); + + p11_rpc_buffer_add_byte_array(buffer, (unsigned char *)params.pChainCode, params.ulChainCodeLen); + + if (params.version > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.version); +} + +bool +p11_rpc_buffer_get_ibm_btc_derive_mechanism_value (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length) +{ + uint64_t val1; + uint64_t val2; + size_t len; + const unsigned char *data; + uint64_t val3; + + if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val1) || + !p11_rpc_buffer_get_uint64 (buffer, offset, &val2) || + !p11_rpc_buffer_get_byte_array (buffer, offset, &data, &len) || + !p11_rpc_buffer_get_uint64 (buffer, offset, &val3)) + return false; + + if (value) { + CK_IBM_BTC_DERIVE_PARAMS params = { 0 }; + + params.type = val1; + params.childKeyIndex = val2; + params.ulChainCodeLen = len; + params.pChainCode = (void *) data; + params.version = val3; + + memcpy (value, ¶ms, sizeof (CK_IBM_BTC_DERIVE_PARAMS)); + } + + if (value_length) + *value_length = sizeof (CK_IBM_BTC_DERIVE_PARAMS); + + return true; +} + +void +p11_rpc_buffer_add_ibm_kyber_mechanism_value (p11_buffer *buffer, + const void *value, + CK_ULONG value_length) +{ + CK_IBM_KYBER_PARAMS params; + + if (value_length != sizeof (CK_IBM_KYBER_PARAMS)) { + p11_buffer_fail (buffer); + return; + } + + memcpy (¶ms, value, value_length); + + if (params.ulVersion > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.ulVersion); + + if (params.mode > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.mode); + + if (params.kdf > UINT64_MAX) { + p11_buffer_fail (buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.kdf); + + if (params.bPrepend > sizeof(CK_BBOOL)) { + p11_buffer_fail(buffer); + return; + } + p11_rpc_buffer_add_byte(buffer, (unsigned char) params.bPrepend); + + p11_rpc_buffer_add_byte_array(buffer, (unsigned char *)params.pCipher, params.ulCipherLen); + + p11_rpc_buffer_add_byte_array(buffer, (unsigned char *)params.pSharedData, params.ulSharedDataLen); + + if (params.hSecret > sizeof(CK_OBJECT_HANDLE)) { + p11_buffer_fail(buffer); + return; + } + p11_rpc_buffer_add_uint64(buffer, params.hSecret); +} + +bool +p11_rpc_buffer_get_ibm_kyber_mechanism_value (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length) +{ + uint64_t val1; + uint64_t val2; + uint64_t val3; + unsigned char byte; + const unsigned char *data1; + size_t len1; + const unsigned char *data2; + size_t len2; + uint64_t val4; + + if (!p11_rpc_buffer_get_uint64(buffer, offset, &val1) || + !p11_rpc_buffer_get_uint64(buffer, offset, &val2) || + !p11_rpc_buffer_get_uint64(buffer, offset, &val3) || + !p11_rpc_buffer_get_byte(buffer, offset, &byte) || + !p11_rpc_buffer_get_byte_array(buffer, offset, &data1, &len1) || + !p11_rpc_buffer_get_byte_array(buffer, offset, &data2, &len2) || + !p11_rpc_buffer_get_uint64(buffer, offset, &val4)) + return false; + + if (value) { + CK_IBM_KYBER_PARAMS *params = (CK_IBM_KYBER_PARAMS *) value; + + params->ulVersion = val1; + params->mode = val2; + params->kdf = val3; + params->bPrepend = byte; + if (params->pCipher && params->ulCipherLen == len1) { + memcpy(params->pCipher, data1, len1); + params->ulCipherLen = len1; + } else { + params->pCipher = (void *) data1; + params->ulCipherLen = len1; + } + if (params->pSharedData && params->ulSharedDataLen == len2) { + memcpy(params->pSharedData, data2, len2); + params->ulSharedDataLen = len2; + } else { + params->pSharedData = (void *) data2; + params->ulSharedDataLen = len2; + } + params->hSecret = val4; + } + + if (value_length) + *value_length = sizeof (CK_IBM_KYBER_PARAMS); + + return true; +} + void p11_rpc_buffer_add_aes_iv_mechanism_value (p11_buffer *buffer, const void *value, @@ -1956,7 +2326,15 @@ p11_rpc_buffer_get_dh_pkcs_derive_mechanism_value (p11_buffer *buffer, return true; } +static p11_rpc_mechanism_serializer p11_rpc_mech_param_update_serializers[] = { + { CKM_IBM_BTC_DERIVE, p11_rpc_buffer_add_ibm_btc_derive_mech_param_update, p11_rpc_buffer_get_ibm_btc_derive_mech_param_update }, + { CKM_IBM_KYBER, p11_rpc_buffer_add_ibm_kyber_mech_param_update, p11_rpc_buffer_get_ibm_kyber_mech_param_update }, +}; + static p11_rpc_mechanism_serializer p11_rpc_mechanism_serializers[] = { + { CKM_IBM_ECDSA_OTHER, p11_rpc_buffer_add_ibm_ecdsa_other_mechanism_value, p11_rpc_buffer_get_ibm_ecdsa_other_mechanism_value }, + { CKM_IBM_BTC_DERIVE, p11_rpc_buffer_add_ibm_btc_derive_mechanism_value, p11_rpc_buffer_get_ibm_btc_derive_mechanism_value }, + { CKM_IBM_KYBER, p11_rpc_buffer_add_ibm_kyber_mechanism_value, p11_rpc_buffer_get_ibm_kyber_mechanism_value }, { CKM_RSA_PKCS_PSS, p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value, p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value }, { CKM_SHA1_RSA_PKCS_PSS, p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value, p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value }, { CKM_SHA224_RSA_PKCS_PSS, p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value, p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value }, @@ -2181,12 +2559,18 @@ p11_rpc_buffer_add_mechanism (p11_buffer *buffer, const CK_MECHANISM *mech) p11_rpc_buffer_add_uint32 (buffer, mech->mechanism); if (mechanism_has_no_parameters (mech->mechanism)) { - p11_rpc_buffer_add_byte_array (buffer, NULL, 0); return; } assert (mechanism_has_sane_parameters (mech->mechanism)); + if (mech->pParameter == NULL && mech->ulParameterLen == 0) { + p11_rpc_buffer_add_byte (buffer, 0); + return; + } else { + p11_rpc_buffer_add_byte (buffer, 1); + } + for (i = 0; i < ELEMS (p11_rpc_mechanism_serializers); i++) { if (p11_rpc_mechanism_serializers[i].type == mech->mechanism) { serializer = &p11_rpc_mechanism_serializers[i]; @@ -2208,6 +2592,7 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer, uint32_t mechanism; p11_rpc_mechanism_serializer *serializer = NULL; size_t i; + unsigned char has_param; /* The mechanism type */ if (!p11_rpc_buffer_get_uint32 (buffer, offset, &mechanism)) @@ -2224,6 +2609,17 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer, mech->ulParameterLen = 0; mech->pParameter = NULL; return true; + } else if (mechanism_has_no_parameters (mech->mechanism)) { + return true; + } + + if (!p11_rpc_buffer_get_byte(buffer, offset, &has_param)) + return false; + + if (has_param == 0) { + mech->ulParameterLen = 0; + mech->pParameter = NULL; + return true; } for (i = 0; i < ELEMS (p11_rpc_mechanism_serializers); i++) { @@ -2242,3 +2638,74 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer, return true; } + +void +p11_rpc_buffer_add_mech_param_update (p11_buffer *buffer, const CK_MECHANISM *mech) +{ + p11_rpc_mechanism_serializer *serializer = NULL; + size_t i; + + if (mechanism_has_no_parameters (mech->mechanism)) { + return; + } + + if (mech->pParameter == NULL && mech->ulParameterLen == 0) { + p11_rpc_buffer_add_byte (buffer, 0); + return; + } else { + p11_rpc_buffer_add_byte (buffer, 1); + } + + for (i = 0; i < ELEMS (p11_rpc_mech_param_update_serializers); i++) { + if (p11_rpc_mech_param_update_serializers[i].type == mech->mechanism) { + serializer = &p11_rpc_mech_param_update_serializers[i]; + break; + } + } + + if (serializer == NULL) + return; + + serializer->encode (buffer, mech->pParameter, mech->ulParameterLen); +} + +bool +p11_rpc_buffer_get_mech_param_update (p11_buffer *buffer, + size_t *offset, + CK_MECHANISM *mech) +{ + p11_rpc_mechanism_serializer *serializer = NULL; + size_t i; + unsigned char has_param; + + if (mechanism_has_no_parameters (mech->mechanism)) { + mech->ulParameterLen = 0; + mech->pParameter = NULL; + return true; + } + + if (!p11_rpc_buffer_get_byte(buffer, offset, &has_param)) + return false; + + if (has_param == 0) { + mech->ulParameterLen = 0; + mech->pParameter = NULL; + return true; + } + + for (i = 0; i < ELEMS (p11_rpc_mech_param_update_serializers); i++) { + if (p11_rpc_mech_param_update_serializers[i].type == mech->mechanism) { + serializer = &p11_rpc_mech_param_update_serializers[i]; + break; + } + } + + if (serializer == NULL) + return true; + + if (!serializer->decode (buffer, offset, + mech->pParameter, &mech->ulParameterLen)) + return false; + + return true; +} diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h index e59562de..405e477e 100644 --- a/p11-kit/rpc-message.h +++ b/p11-kit/rpc-message.h @@ -138,6 +138,7 @@ enum { P11_RPC_CALL_C_MessageVerifyFinal, P11_RPC_CALL_C_InitToken2, + P11_RPC_CALL_C_DeriveKey2, P11_RPC_CALL_MAX }; @@ -159,6 +160,7 @@ typedef struct { * v = CK_VERSION * y = CK_BYTE * z = null terminated string + * P = mechanism parameter */ static const p11_rpc_call p11_rpc_calls[] = { @@ -253,6 +255,7 @@ static const p11_rpc_call p11_rpc_calls[] = { { P11_RPC_CALL_C_MessageVerifyFinal, "C_MessageVerifyFinal", "u", "" }, { P11_RPC_CALL_C_InitToken2, "C_InitToken2", "uays", "" }, + { P11_RPC_CALL_C_DeriveKey2, "C_DeriveKey2", "uMuaA", "uPu" }, }; #ifdef _DEBUG @@ -514,6 +517,31 @@ bool p11_rpc_buffer_get_mechanism (p11_buffer *buffer, size_t *offset, CK_MECHANISM *mech); +void p11_rpc_buffer_add_ibm_kyber_mech_param_update (p11_buffer *buffer, + const void *value, + CK_ULONG value_length); + +bool p11_rpc_buffer_get_ibm_kyber_mech_param_update (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length); + +void p11_rpc_buffer_add_ibm_btc_derive_mech_param_update (p11_buffer *buffer, + const void *value, + CK_ULONG value_length); + +bool p11_rpc_buffer_get_ibm_btc_derive_mech_param_update (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length); + +void p11_rpc_buffer_add_mech_param_update (p11_buffer *buffer, + const CK_MECHANISM *mech); + +bool p11_rpc_buffer_get_mech_param_update (p11_buffer *buffer, + size_t *offset, + CK_MECHANISM *mech); + void p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value (p11_buffer *buffer, const void *value, @@ -558,6 +586,39 @@ bool p11_rpc_buffer_get_ibm_attrbound_wrap_mechanism_value void *value, CK_ULONG *value_length); +void p11_rpc_buffer_add_ibm_ecdsa_other_mechanism_value + (p11_buffer *buffer, + const void *value, + CK_ULONG value_length); + +bool p11_rpc_buffer_get_ibm_ecdsa_other_mechanism_value + (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length); + +void p11_rpc_buffer_add_ibm_btc_derive_mechanism_value + (p11_buffer *buffer, + const void *value, + CK_ULONG value_length); + +bool p11_rpc_buffer_get_ibm_btc_derive_mechanism_value + (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length); + +void p11_rpc_buffer_add_ibm_kyber_mechanism_value + (p11_buffer *buffer, + const void *value, + CK_ULONG value_length); + +bool p11_rpc_buffer_get_ibm_kyber_mechanism_value + (p11_buffer *buffer, + size_t *offset, + void *value, + CK_ULONG *value_length); + void p11_rpc_buffer_add_aes_iv_mechanism_value (p11_buffer *buffer, const void *value, CK_ULONG value_length); diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c index ef3b3836..fc052ba3 100644 --- a/p11-kit/rpc-server.c +++ b/p11-kit/rpc-server.c @@ -580,6 +580,30 @@ proto_write_mechanism_info (p11_rpc_message *msg, return CKR_OK; } +static CK_RV +proto_write_error (p11_rpc_message *msg, CK_RV err) +{ + if(!p11_rpc_message_write_ulong(msg, err)) + return CKR_HOST_MEMORY; + + return p11_buffer_failed (msg->output) ? CKR_HOST_MEMORY : CKR_OK; +} + +static CK_RV +proto_write_mech_param_update (p11_rpc_message *msg, + CK_MECHANISM_PTR *mech) +{ + assert (msg != NULL); + assert (msg->output != NULL); + + /* Make sure this is in the right order */ + assert (!msg->signature || p11_rpc_message_verify_part (msg, "P")); + + p11_rpc_buffer_add_mech_param_update (msg->output, *mech); + + return p11_buffer_failed (msg->output) ? CKR_HOST_MEMORY : CKR_OK; +} + static CK_RV proto_write_session_info (p11_rpc_message *msg, CK_SESSION_INFO_PTR info) @@ -693,6 +717,24 @@ call_ready (p11_rpc_message *msg) if (_ret == CKR_OK && !p11_rpc_message_write_ulong (msg, val)) \ _ret = PREP_ERROR; +#define OUT_MECH_PARAM_UPDATE(mech) \ + _ret2 = proto_write_mech_param_update (msg, &mech); \ + if (_ret2 != CKR_OK) { \ + _ret = _ret2; \ + goto _cleanup; \ + } + +#define CHECK_ERROR \ + if (_ret != CKR_OK && _ret != CKR_BUFFER_TOO_SMALL) \ + goto _cleanup; + +#define OUT_ERROR \ + _ret2 = proto_write_error (msg, _ret); \ + if (_ret2 != CKR_OK) { \ + _ret = _ret2; \ + goto _cleanup; \ + } + #define OUT_BYTE_ARRAY(array, len) \ /* Note how we filter return codes */ \ _ret = proto_write_byte_array (msg, array, len, _ret); @@ -1851,6 +1893,32 @@ rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self, END_CALL; } +static CK_RV +rpc_C_DeriveKey2 (CK_X_FUNCTION_LIST *self, + p11_rpc_message *msg) +{ + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism_; + CK_MECHANISM_PTR mechanism = &mechanism_; + CK_OBJECT_HANDLE base_key; + CK_ATTRIBUTE_PTR template; + CK_ULONG attribute_count; + CK_OBJECT_HANDLE key; + CK_RV _ret2; + + BEGIN_CALL (DeriveKey); + IN_ULONG (session); + IN_MECHANISM (mechanism); + IN_ULONG (base_key); + IN_ATTRIBUTE_ARRAY (template, attribute_count); + PROCESS_CALL ((self, session, mechanism, base_key, template, attribute_count, &key)); + CHECK_ERROR; + OUT_ERROR; + OUT_MECH_PARAM_UPDATE (mechanism); + OUT_ULONG (key); + END_CALL; +} + static CK_RV rpc_C_SeedRandom (CK_X_FUNCTION_LIST *self, p11_rpc_message *msg) @@ -2415,6 +2483,7 @@ p11_rpc_server_handle (CK_X_FUNCTION_LIST *self, CASE_CALL (C_MessageVerifyFinal) CASE_CALL (C_InitToken2) + CASE_CALL (C_DeriveKey2) #undef CASE_CALL default: /* This should have been caught by the parse code */ @@ -2429,14 +2498,16 @@ p11_rpc_server_handle (CK_X_FUNCTION_LIST *self, } /* A filled in response */ - if (ret == CKR_OK) { + if (ret == CKR_OK || ret == CKR_BUFFER_TOO_SMALL) { /* * Since we're dealing with many many functions above generating * these messages we want to make sure each of them actually * does what it's supposed to. */ - assert (p11_rpc_message_is_verified (&msg)); + if (ret == CKR_OK) + assert (p11_rpc_message_is_verified (&msg)); + assert (msg.call_type == P11_RPC_RESPONSE); assert (msg.call_id == req_id); assert (p11_rpc_calls[msg.call_id].response);