From 115001db63deaea37eb27089174ceb72c5a12444 Mon Sep 17 00:00:00 2001 From: istepic Date: Wed, 29 Mar 2023 13:56:02 +0200 Subject: [PATCH] hsm: update libp11 patch Some PKCS#11 implementations don't support all the features libp11 is using. Some of them are removed. Object attributes for RSA and ECC keypair were modified: - Removed CKA_WRAP from pub/priv RSA keys since it's unclear if RSA keys are used for wrapping in any cryptographic algorithm. - Changed RSA public exponent from 0x101 to 0x10001 - Removed CKA_DERIVE from ECC public key since only private key is used for derivation along with public key from the other party - Removed CKA_WRAP from ECC public keys since algorithm that uses ECC public keys for key wrapping doesn't exist - Removed CKA_VERIFY_RECOVER from ECC public key since this is only supported for RSA based DSAs - Removed CKA_ENCRYPT from ECC public keys since they are never used for encryption - Removed CKA_UNWRAP from ECC private keys since algorithm that uses ECC private keys for key unwrapping doesn't exist --- README.md | 6 +- ...c-keypair-generation-interface-and-e.patch | 95 ++++++++++++++----- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 56349eb0..e2444bad 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,9 @@ build/$ cmake -DBUILD_TESTING=True -DMOCOCRW_DILITHIUM_ENABLED=ON .. ### Build with HSM support HSM support is an **optional** feature for MoCOCrW. This allows for loading and storing keys on HSM -and using those keys in various cryptographic algorithms without having keys in memory. To build -MoCOCrW with HSM support, a patched version of libp11 is necessary since upstream libp11 does not -support key generation through OpenSSL's ENGINE API. +and using those keys in various cryptographic algorithms without having keys in memory. Thread safety +is not guaranteed. To build MoCOCrW with HSM support, a patched version of libp11 is necessary since +upstream libp11 does not support key generation through OpenSSL's ENGINE API. [libp11 release 0.4.12](https://github.com/OpenSC/libp11/releases/tag/libp11-0.4.12) patched with [patch for key generation](https://github.com/bmwcarit/MoCOCrW/blob/openssl1.1/dockerfiles/feature-support/hsm-patches/0001-Introduce-generic-keypair-generation-interface-and-e.patch) is required for building MoCOCrW with diff --git a/dockerfiles/feature-support/hsm-patches/0001-Introduce-generic-keypair-generation-interface-and-e.patch b/dockerfiles/feature-support/hsm-patches/0001-Introduce-generic-keypair-generation-interface-and-e.patch index c741c99f..14bd4a17 100644 --- a/dockerfiles/feature-support/hsm-patches/0001-Introduce-generic-keypair-generation-interface-and-e.patch +++ b/dockerfiles/feature-support/hsm-patches/0001-Introduce-generic-keypair-generation-interface-and-e.patch @@ -1,4 +1,4 @@ -From 828282b17f40237bb875e93df0e216e12c4f2504 Mon Sep 17 00:00:00 2001 +From 8468ecc844664c2f066492ed08569d5b7db37756 Mon Sep 17 00:00:00 2001 From: istepic Date: Mon, 5 Dec 2022 22:44:25 +0100 Subject: [PATCH] Introduce generic keypair generation interface and engine @@ -46,13 +46,14 @@ Signed-off-by: istepic src/libp11-int.h | 15 ++- src/libp11.h | 48 +++++++--- src/p11_front.c | 32 +++++-- - src/p11_key.c | 119 +++++++++++++++++++++++- + src/p11_key.c | 133 +++++++++++++++++++++++--- + src/p11_load.c | 1 - src/p11_misc.c | 75 +++++++++++++++ src/p11_slot.c | 1 + tests/Makefile.am | 6 +- tests/keygen.c | 215 +++++++++++++++++++++++++++++++++++++++++++ tests/keygen.softhsm | 39 ++++++++ - 12 files changed, 587 insertions(+), 33 deletions(-) + 13 files changed, 595 insertions(+), 40 deletions(-) create mode 100644 tests/keygen.c create mode 100755 tests/keygen.softhsm @@ -330,7 +331,7 @@ index f74f209..f82c9a3 100644 { PKCS11_OBJECT_private *key = PRIVKEY(pkey); diff --git a/src/p11_key.c b/src/p11_key.c -index ec7f279..57cba43 100644 +index ec7f279..5a30e79 100644 --- a/src/p11_key.c +++ b/src/p11_key.c @@ -252,8 +252,8 @@ int pkcs11_reload_object(PKCS11_OBJECT_private *obj) @@ -344,7 +345,12 @@ index ec7f279..57cba43 100644 PKCS11_CTX_private *ctx = slot->ctx; CK_SESSION_HANDLE session; -@@ -266,10 +266,20 @@ int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int b +@@ -262,36 +262,45 @@ int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int b + CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 + }; + CK_ULONG num_bits = bits; +- CK_BYTE public_exponent[] = { 1, 0, 1 }; ++ CK_BYTE public_exponent[] = { 1, 0, 0, 0, 1 }; CK_OBJECT_HANDLE pub_key_obj, priv_key_obj; int rv; @@ -353,7 +359,7 @@ index ec7f279..57cba43 100644 - if (pkcs11_get_session(slot, 1, &session)) + // R/W session is mandatory for key generation. + if (pkcs11_open_session(slot, 1)) { -+ return -1; + return -1; + } + // open_session might call C_CloseAllSessions if current session is not R/W. + // C_CloseAllSessions logs everyone out @@ -363,12 +369,38 @@ index ec7f279..57cba43 100644 + } + } + if (pkcs11_get_session(slot, 1, &session)) { - return -1; ++ return -1; + } ++ /* The following attributes are necessary for RSA encryption and DSA */ /* pubkey attributes */ pkcs11_addattr(&pubtmpl, CKA_ID, id, id_len); -@@ -310,6 +320,105 @@ int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int b + if (label) + pkcs11_addattr_s(&pubtmpl, CKA_LABEL, label); + pkcs11_addattr_bool(&pubtmpl, CKA_TOKEN, TRUE); +- pkcs11_addattr_bool(&pubtmpl, CKA_ENCRYPT, TRUE); + pkcs11_addattr_bool(&pubtmpl, CKA_VERIFY, TRUE); +- pkcs11_addattr_bool(&pubtmpl, CKA_WRAP, TRUE); ++ pkcs11_addattr_bool(&pubtmpl, CKA_ENCRYPT, TRUE); + pkcs11_addattr_var(&pubtmpl, CKA_MODULUS_BITS, num_bits); +- pkcs11_addattr(&pubtmpl, CKA_PUBLIC_EXPONENT, public_exponent, 3); ++ pkcs11_addattr(&pubtmpl, CKA_PUBLIC_EXPONENT, public_exponent, 5); + + /* privkey attributes */ + pkcs11_addattr(&privtmpl, CKA_ID, id, id_len); + if (label) + pkcs11_addattr_s(&privtmpl, CKA_LABEL, label); +- pkcs11_addattr_bool(&privtmpl, CKA_TOKEN, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_PRIVATE, TRUE); ++ pkcs11_addattr_bool(&privtmpl, CKA_TOKEN, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_SENSITIVE, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_DECRYPT, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_SIGN, TRUE); +- pkcs11_addattr_bool(&privtmpl, CKA_UNWRAP, TRUE); + + /* call the pkcs11 module to create the key pair */ + rv = CRYPTOKI_call(ctx, C_GenerateKeyPair( +@@ -310,6 +319,108 @@ int pkcs11_generate_key(PKCS11_SLOT_private *slot, int algorithm, unsigned int b return 0; } @@ -385,8 +417,8 @@ index ec7f279..57cba43 100644 + CK_OBJECT_HANDLE pub_key_obj, priv_key_obj; + int rv; + -+ unsigned char *ecdsa_params = NULL; -+ int ecdsa_params_len = 0; ++ unsigned char *ec_params = NULL; ++ int ec_params_len = 0; + unsigned char *tmp = NULL; + ASN1_OBJECT *curve_obj = NULL; + int curve_nid = NID_undef; @@ -417,36 +449,39 @@ index ec7f279..57cba43 100644 + curve_obj = OBJ_nid2obj(curve_nid); + if (!curve_obj) + return -1; -+ ecdsa_params_len = i2d_ASN1_OBJECT(curve_obj, NULL); -+ ecdsa_params = (unsigned char *)OPENSSL_malloc(ecdsa_params_len); -+ if (!ecdsa_params) ++ // convert to DER format and take just the length ++ ec_params_len = i2d_ASN1_OBJECT(curve_obj, NULL); ++ if (ec_params_len < 0) ++ return -1; ++ ec_params = OPENSSL_malloc(ec_params_len); ++ if (!ec_params) ++ return -1; ++ // ec_params points to begining of DER encoded object. Since we need this ++ // location later and OpenSSL changes it in i2d_ASN1_OBJECT to point to 1 byte ++ // after DER encoded object, we assign the pointer to temporary throw-away ++ // pointer tmp ++ tmp = ec_params; ++ if (i2d_ASN1_OBJECT(curve_obj, &tmp) < 0) + return -1; -+ tmp = ecdsa_params; -+ i2d_ASN1_OBJECT(curve_obj, &tmp); + ++ /* The following attributes are necessary for ECDSA and ECDH mechanisms */ + /* pubkey attributes */ + pkcs11_addattr(&pubtmpl, CKA_ID, id, id_len); + if (label) + pkcs11_addattr_s(&pubtmpl, CKA_LABEL, label); + pkcs11_addattr_bool(&pubtmpl, CKA_TOKEN, TRUE); -+ pkcs11_addattr_bool(&pubtmpl, CKA_DERIVE, FALSE); -+ pkcs11_addattr_bool(&pubtmpl, CKA_WRAP, FALSE); + pkcs11_addattr_bool(&pubtmpl, CKA_VERIFY, TRUE); -+ pkcs11_addattr_bool(&pubtmpl, CKA_VERIFY_RECOVER, FALSE); -+ pkcs11_addattr_bool(&pubtmpl, CKA_ENCRYPT, FALSE); -+ pkcs11_addattr(&pubtmpl, CKA_ECDSA_PARAMS, ecdsa_params, ecdsa_params_len); ++ pkcs11_addattr(&pubtmpl, CKA_EC_PARAMS, ec_params, ec_params_len); + + /* privkey attributes */ + pkcs11_addattr(&privtmpl, CKA_ID, id, id_len); + if (label) + pkcs11_addattr_s(&privtmpl, CKA_LABEL, label); -+ pkcs11_addattr_bool(&privtmpl, CKA_TOKEN, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_PRIVATE, TRUE); ++ pkcs11_addattr_bool(&privtmpl, CKA_TOKEN, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_SENSITIVE, TRUE); + pkcs11_addattr_bool(&privtmpl, CKA_DERIVE, TRUE); -+ pkcs11_addattr_bool(&privtmpl, CKA_UNWRAP, FALSE); + pkcs11_addattr_bool(&privtmpl, CKA_SIGN, TRUE); -+ pkcs11_addattr_bool(&privtmpl, CKA_DECRYPT, FALSE); + + /* call the pkcs11 module to create the key pair */ + rv = CRYPTOKI_call(ctx, C_GenerateKeyPair( @@ -465,7 +500,7 @@ index ec7f279..57cba43 100644 + /* zap all memory allocated when building the template */ + pkcs11_zap_attrs(&privtmpl); + pkcs11_zap_attrs(&pubtmpl); -+ OPENSSL_free(ecdsa_params); ++ OPENSSL_free(ec_params); + + CRYPTOKI_checkerr(CKR_F_PKCS11_GENERATE_KEY, rv); + return 0; @@ -474,6 +509,18 @@ index ec7f279..57cba43 100644 /* * Store a private key on the token */ +diff --git a/src/p11_load.c b/src/p11_load.c +index e89b0c7..330dc91 100644 +--- a/src/p11_load.c ++++ b/src/p11_load.c +@@ -81,7 +81,6 @@ int pkcs11_CTX_load(PKCS11_CTX *ctx, const char *name) + /* Tell the PKCS11 to initialize itself */ + memset(&args, 0, sizeof(args)); + /* Unconditionally say using OS locking primitives is OK */ +- args.flags |= CKF_OS_LOCKING_OK; + args.pReserved = cpriv->init_args; + rv = cpriv->method->C_Initialize(&args); + if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { diff --git a/src/p11_misc.c b/src/p11_misc.c index 1b0e64d..1d9a845 100644 --- a/src/p11_misc.c