URL: https://github.com/SSSD/sssd/pull/5855
Author: alexey-tikhonov
 Title: #5855: CKM_RSA_PKCS support.
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5855/head:pr5855
git checkout pr5855
From 820a328ea37c5d99721fcc37486a05b984ac331e Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Thu, 28 Oct 2021 13:49:11 +0200
Subject: [PATCH 1/3] P11: refactoring of get_preferred_rsa_mechanism()

Flattened code structure and more accurate errors handling.
---
 src/p11_child/p11_child_openssl.c | 75 +++++++++++++++++--------------
 1 file changed, 41 insertions(+), 34 deletions(-)

diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index 27ee18bba6..3bceae651b 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -1313,7 +1313,7 @@ static CK_RV get_preferred_rsa_mechanism(TALLOC_CTX *mem_ctx,
     CK_RV rv;
     size_t c;
     size_t m;
-    struct prefs {
+    const struct prefs {
         CK_MECHANISM_TYPE mech;
         const char *mech_name;
         const EVP_MD *evp_md;
@@ -1327,44 +1327,51 @@ static CK_RV get_preferred_rsa_mechanism(TALLOC_CTX *mem_ctx,
         { 0, NULL, NULL, NULL }
     };
 
-    *preferred_mechanism = CKM_SHA1_RSA_PKCS;
-    *preferred_evp_md = EVP_sha1();
-
     rv = module->C_GetMechanismList(slot_id, NULL, &count);
-    if (rv == CKR_OK && count > 0) {
-        mechanism_list = talloc_size(mem_ctx,
-                                     count * sizeof(CK_MECHANISM_TYPE));
-        if (mechanism_list != NULL) {
-            rv = module->C_GetMechanismList(slot_id, mechanism_list, &count);
-            if (rv == CKR_OK) {
-                for (m = 0; m < count; m++) {
-                    DEBUG(SSSDBG_TRACE_ALL, "Found mechanism [%lu].\n",
-                                            mechanism_list[m]);
-                }
-                for (c = 0; prefs[c].mech != 0; c++) {
-                    for (m = 0; m < count; m++) {
-                        if (prefs[c].mech == mechanism_list[m]) {
-                            *preferred_mechanism = prefs[c].mech;
-                            *preferred_evp_md = prefs[c].evp_md;
-                            DEBUG(SSSDBG_FUNC_DATA,
-                                  "Using PKCS#11 mechanism [%lu][%s] and "
-                                  "local message digest [%s].\n",
-                                  *preferred_mechanism, prefs[c].mech_name,
-                                  prefs[c].md_name);
-                            break;
-                        }
-                    }
-                    if (m != count) {
-                        break;
-                    }
-                }
+    if (rv != CKR_OK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "C_GetMechanismList failed: [%lu][%s]\n",
+              rv, p11_kit_strerror(rv));
+        return rv;
+    }
+    if (count == 0) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "No mechanism found\n");
+        return CKR_GENERAL_ERROR;
+    }
+
+    mechanism_list = talloc_size(mem_ctx, count * sizeof(CK_MECHANISM_TYPE));
+    if (mechanism_list == NULL) {
+        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to allocate memory\n");
+        return CKR_GENERAL_ERROR;
+    }
+
+    rv = module->C_GetMechanismList(slot_id, mechanism_list, &count);
+    if (rv != CKR_OK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "2nd C_GetMechanismList failed: [%lu][%s]\n",
+              rv, p11_kit_strerror(rv));
+        return rv;
+    }
+
+    for (m = 0; m < count; m++) {
+        DEBUG(SSSDBG_TRACE_ALL, "Found mechanism [%lu].\n", mechanism_list[m]);
+    }
+    for (c = 0; prefs[c].mech != 0; c++) {
+        for (m = 0; m < count; m++) {
+            if (prefs[c].mech == mechanism_list[m]) {
+                *preferred_mechanism = prefs[c].mech;
+                *preferred_evp_md = prefs[c].evp_md;
+                DEBUG(SSSDBG_FUNC_DATA,
+                      "Using PKCS#11 mechanism [%lu][%s] and "
+                      "local message digest [%s].\n",
+                      *preferred_mechanism, prefs[c].mech_name,
+                      prefs[c].md_name);
+                talloc_free(mechanism_list);
+                return CKR_OK;
             }
         }
     }
 
-    talloc_free(mechanism_list);
-
-    return rv;
+    DEBUG(SSSDBG_MINOR_FAILURE, "No match found\n");
+    return CKR_GENERAL_ERROR;
 }
 
 static int sign_data(CK_FUNCTION_LIST *module, CK_SESSION_HANDLE session,

From f8572b87a0acc7451282b973da80c8e9421c04cf Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Thu, 28 Oct 2021 14:05:58 +0200
Subject: [PATCH 2/3] P11: add support of 'CKM_RSA_PKCS' mechanism

Resolves: https://github.com/SSSD/sssd/issues/5854
---
 src/p11_child/p11_child_openssl.c | 51 ++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
index 3bceae651b..be9bc42421 100644
--- a/src/p11_child/p11_child_openssl.c
+++ b/src/p11_child/p11_child_openssl.c
@@ -1137,24 +1137,29 @@ static CK_KEY_TYPE get_key_type(CK_FUNCTION_LIST *module,
     return type;
 }
 
-static int do_hash(TALLOC_CTX *mem_ctx, const EVP_MD *evp_md,
-                   CK_BYTE *in, size_t in_len,
-                   CK_BYTE **hash, size_t *hash_len)
+static int do_sha512(TALLOC_CTX *mem_ctx, CK_BYTE *in, size_t in_len,
+                     bool add_info, CK_BYTE **_hash, size_t *_hash_len)
 {
     EVP_MD_CTX *md_ctx = NULL;
     int ret;
     unsigned char md_value[EVP_MAX_MD_SIZE];
     unsigned int md_len;
     CK_BYTE *out = NULL;
+    const CK_BYTE info[] =
+        {   /* https://datatracker.ietf.org/doc/html/rfc3447#page-43 :
+               the DER encoding T of the DigestInfo value for SHA-512 */
+            0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+            0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
+        };
+    const unsigned int info_len = add_info ? sizeof(info) : 0;
 
     md_ctx = EVP_MD_CTX_create();
     if (md_ctx == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "EVP_MD_CTX_create failed.\n");
-        ret = ENOMEM;
-        goto done;
+        return ENOMEM;
     }
 
-    ret = EVP_DigestInit(md_ctx, evp_md);
+    ret = EVP_DigestInit(md_ctx, EVP_sha512());
     if (ret != 1) {
         DEBUG(SSSDBG_OP_FAILURE, "EVP_DigestInit failed.\n");
         ret = EINVAL;
@@ -1175,27 +1180,26 @@ static int do_hash(TALLOC_CTX *mem_ctx, const EVP_MD *evp_md,
         goto done;
     }
 
-    out = talloc_size(mem_ctx, md_len * sizeof(CK_BYTE));
+    out = talloc_size(mem_ctx, info_len + md_len * sizeof(CK_BYTE));
     if (out == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
         ret = ENOMEM;
         goto done;
     }
 
-    memcpy(out, md_value, md_len);
+    if (add_info) {
+        memcpy(out, info, info_len);
+    }
+
+    memcpy(out + info_len, md_value, md_len);
 
-    *hash = out;
-    *hash_len = md_len;
+    *_hash = out;
+    *_hash_len = info_len + md_len;
 
     ret = EOK;
 
 done:
-
     EVP_MD_CTX_free(md_ctx);
-    if (ret != EOK) {
-        free(out);
-    }
-
     return ret;
 }
 
@@ -1323,6 +1327,7 @@ static CK_RV get_preferred_rsa_mechanism(TALLOC_CTX *mem_ctx,
         { CKM_SHA384_RSA_PKCS, "CKM_SHA384_RSA_PKCS", EVP_sha384(), "sha384" },
         { CKM_SHA256_RSA_PKCS, "CKM_SHA256_RSA_PKCS", EVP_sha256(), "sha256" },
         { CKM_SHA224_RSA_PKCS, "CKM_SHA224_RSA_PKCS", EVP_sha224(), "sha224" },
+        { CKM_RSA_PKCS,        "CKM_RSA_PKCS",        NULL,         "-none-" },
         { CKM_SHA1_RSA_PKCS,   "CKM_SHA1_RSA_PKCS",   EVP_sha1(),   "sha1" },
         { 0, NULL, NULL, NULL }
     };
@@ -1360,8 +1365,8 @@ static CK_RV get_preferred_rsa_mechanism(TALLOC_CTX *mem_ctx,
                 *preferred_mechanism = prefs[c].mech;
                 *preferred_evp_md = prefs[c].evp_md;
                 DEBUG(SSSDBG_FUNC_DATA,
-                      "Using PKCS#11 mechanism [%lu][%s] and "
-                      "local message digest [%s].\n",
+                      "Using PKCS#11 mechanism [%lu][%s] with "
+                      "message digest [%s].\n",
                       *preferred_mechanism, prefs[c].mech_name,
                       prefs[c].md_name);
                 talloc_free(mechanism_list);
@@ -1447,12 +1452,11 @@ static int sign_data(CK_FUNCTION_LIST *module, CK_SESSION_HANDLE session,
         DEBUG(SSSDBG_TRACE_ALL, "Found RSA key using mechanism [%lu].\n",
                                 preferred_mechanism);
         mechanism.mechanism = preferred_mechanism;
-        card_does_hash = true;
+        card_does_hash = (evp_md != NULL);
         break;
     case CKK_EC:
         DEBUG(SSSDBG_TRACE_ALL, "Found ECC key using CKM_ECDSA.\n");
         mechanism.mechanism = CKM_ECDSA;
-        evp_md = EVP_sha512();
         card_does_hash = false;
         break;
     case CK_UNAVAILABLE_INFORMATION:
@@ -1482,8 +1486,10 @@ static int sign_data(CK_FUNCTION_LIST *module, CK_SESSION_HANDLE session,
         val_to_sign = random_value;
         val_to_sign_len = sizeof(random_value);
     } else {
-        ret = do_hash(cert, evp_md, random_value, sizeof(random_value),
-                      &hash_val, &hash_len);
+        evp_md = EVP_sha512();
+        ret = do_sha512(cert, random_value, sizeof(random_value),
+                        (mechanism.mechanism == CKM_RSA_PKCS), /* add_info */
+                        &hash_val, &hash_len);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE, "do_hash failed.\n");
             return ret;
@@ -1559,7 +1565,8 @@ static int sign_data(CK_FUNCTION_LIST *module, CK_SESSION_HANDLE session,
     } else {
         ret = EVP_VerifyFinal(md_ctx, signature, signature_size, cert_pub_key);
         if (ret != 1) {
-            DEBUG(SSSDBG_OP_FAILURE, "EVP_VerifyFinal failed.\n");
+            DEBUG(SSSDBG_OP_FAILURE, "EVP_VerifyFinal failed: '%s'\n",
+                  ERR_reason_error_string(ERR_peek_last_error()));
             ret = EINVAL;
             goto done;
         }

From 0822cb0a27cff128cc6e8e6561ec6b475019837a Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Thu, 4 Nov 2021 22:17:45 +0100
Subject: [PATCH 3/3] TESTS: added two tests to check cert auth with specific
 RSA mechanisms: CKM_RSA_PKCS and CKM_SHA384_RSA_PKCS. (CKM_SHA384_RSA_PKCS is
 arbitrary chosen as one of CKM_SHA*_RSA_PKCS family)

---
 src/tests/cmocka/test_pam_srv.c | 24 ++++++++++++++++++++++++
 src/tests/test_CA/Makefile.am   | 26 +++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
index e00b585c13..c86c32a907 100644
--- a/src/tests/cmocka/test_pam_srv.c
+++ b/src/tests/cmocka/test_pam_srv.c
@@ -329,6 +329,24 @@ static int pam_test_setup_no_verification(void **state)
     pam_test_setup_common();
     return 0;
 }
+
+static int pam_test_setup_mech_rsa_pkcs(void **state)
+{
+    int rc = pam_test_setup_no_verification(state);
+    if (rc != 0) {
+        return rc;
+    }
+    return putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_mech_rsa_pkcs.conf"));
+}
+
+static int pam_test_setup_mech_rsa_sha384_pkcs(void **state)
+{
+    int rc = pam_test_setup_no_verification(state);
+    if (rc != 0) {
+        return rc;
+    }
+    return putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_mech_rsa_sha384_pkcs.conf"));
+}
 #endif /* HAVE_TEST_CA */
 
 static int pam_cached_test_setup(void **state)
@@ -3663,6 +3681,12 @@ int main(int argc, const char *argv[])
         cmocka_unit_test_setup_teardown(test_pam_cert_auth,
                                         pam_test_setup_no_verification,
                                         pam_test_teardown),
+        cmocka_unit_test_setup_teardown(test_pam_cert_auth,
+                                        pam_test_setup_mech_rsa_pkcs,
+                                        pam_test_teardown),
+        cmocka_unit_test_setup_teardown(test_pam_cert_auth,
+                                        pam_test_setup_mech_rsa_sha384_pkcs,
+                                        pam_test_teardown),
         cmocka_unit_test_setup_teardown(test_pam_pss_cert_auth,
                                         pam_test_setup, pam_test_teardown),
         cmocka_unit_test_setup_teardown(test_pam_ecc_cert_auth,
diff --git a/src/tests/test_CA/Makefile.am b/src/tests/test_CA/Makefile.am
index fdef3ab40f..59048214b1 100644
--- a/src/tests/test_CA/Makefile.am
+++ b/src/tests/test_CA/Makefile.am
@@ -29,7 +29,7 @@ pubkeys_h = $(addprefix SSSD_test_cert_pubsshkey_,$(addsuffix .h,$(ids)))
 pkcs12 = $(addprefix SSSD_test_cert_pkcs12_,$(addsuffix .pem,$(ids)))
 
 
-extra = softhsm2_none softhsm2_one softhsm2_two softhsm2_2tokens softhsm2_ocsp softhsm2_2certs_same_id softhsm2_pss_one SSSD_test_cert_x509_0001.der SSSD_test_cert_x509_0007.der
+extra = softhsm2_none softhsm2_one softhsm2_mech_rsa_pkcs softhsm2_mech_rsa_sha384_pkcs softhsm2_two softhsm2_2tokens softhsm2_ocsp softhsm2_2certs_same_id softhsm2_pss_one SSSD_test_cert_x509_0001.der SSSD_test_cert_x509_0007.der
 if HAVE_FAKETIME
 extra += SSSD_test_CA_expired_crl.pem
 endif
@@ -119,6 +119,30 @@ softhsm2_one.conf:
 	@echo "objectstore.backend = file" >> $@
 	@echo "slots.removable = true" >> $@
 
+softhsm2_mech_rsa_pkcs: softhsm2_mech_rsa_pkcs.conf
+	mkdir $@
+	SOFTHSM2_CONF=./$< $(SOFTHSM2_UTIL) --init-token  --label "SSSD Test Token" --pin 123456 --so-pin 123456 --free
+	GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --no-mark-private --load-certificate=SSSD_test_cert_x509_0001.pem --login  --label 'SSSD test cert 0001' --id 'C554C9F82C2A9D58B70921C143304153A8A42F17'
+	GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --load-privkey=$(srcdir)/SSSD_test_cert_key_0001.pem --login  --label 'SSSD test cert 0001' --id 'C554C9F82C2A9D58B70921C143304153A8A42F17'
+
+softhsm2_mech_rsa_pkcs.conf:
+	@echo "directories.tokendir = "$(abs_top_builddir)"/src/tests/test_CA/softhsm2_mech_rsa_pkcs" > $@
+	@echo "objectstore.backend = file" >> $@
+	@echo "slots.removable = true" >> $@
+	@echo "slots.mechanisms = CKM_RSA_PKCS" >> $@
+
+softhsm2_mech_rsa_sha384_pkcs: softhsm2_mech_rsa_sha384_pkcs.conf
+	mkdir $@
+	SOFTHSM2_CONF=./$< $(SOFTHSM2_UTIL) --init-token  --label "SSSD Test Token" --pin 123456 --so-pin 123456 --free
+	GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --no-mark-private --load-certificate=SSSD_test_cert_x509_0001.pem --login  --label 'SSSD test cert 0001' --id 'C554C9F82C2A9D58B70921C143304153A8A42F17'
+	GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --load-privkey=$(srcdir)/SSSD_test_cert_key_0001.pem --login  --label 'SSSD test cert 0001' --id 'C554C9F82C2A9D58B70921C143304153A8A42F17'
+
+softhsm2_mech_rsa_sha384_pkcs.conf:
+	@echo "directories.tokendir = "$(abs_top_builddir)"/src/tests/test_CA/softhsm2_mech_rsa_sha384_pkcs" > $@
+	@echo "objectstore.backend = file" >> $@
+	@echo "slots.removable = true" >> $@
+	@echo "slots.mechanisms = CKM_SHA384_RSA_PKCS" >> $@
+
 #Export cert from softhsm2 via p11tool, should produce the same as openssl
 SSSD_test_cert_x509_0001.der: softhsm2_one.conf
 	$(eval ID_VAR = $(shell GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --info|cut -d' ' -f2|grep ^pkcs11))
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to