d738b9
From 73c156f998e848c5e383ddd715193d84d95e5c39 Mon Sep 17 00:00:00 2001
d738b9
From: Sumit Bose <sbose@redhat.com>
d738b9
Date: Fri, 26 Jan 2018 11:47:50 -0500
d738b9
Subject: [PATCH] Fix hex conversion of PKINIT certid strings
d738b9
d738b9
When parsing a PKCS11 token specification, correctly convert from hex
d738b9
to binary instead of using OpenSSL bignum functions (which would strip
d738b9
leading zeros).
d738b9
d738b9
[ghudson@mit.edu: made hex_string_to_bin() a bit less verbose; wrote
d738b9
commit message]
d738b9
d738b9
ticket: 8636
d738b9
(cherry picked from commit 63e8b8142fd7b3931a7bf2d6448978ca536bafc0)
d738b9
---
d738b9
 .../preauth/pkinit/pkinit_crypto_openssl.c    | 55 +++++++++++++++----
d738b9
 1 file changed, 44 insertions(+), 11 deletions(-)
d738b9
d738b9
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
d738b9
index 85ca8885d..6098acc6a 100644
d738b9
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
d738b9
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
d738b9
@@ -4640,6 +4640,43 @@ reassemble_pkcs11_name(pkinit_identity_opts *idopts)
d738b9
     return ret;
d738b9
 }
d738b9
 
d738b9
+static int
d738b9
+hex_string_to_bin(const char *str, int *bin_len_out, CK_BYTE **bin_out)
d738b9
+{
d738b9
+    size_t str_len, i;
d738b9
+    CK_BYTE *bin;
d738b9
+    char *endptr, tmp[3] = { '\0', '\0', '\0' };
d738b9
+    long val;
d738b9
+
d738b9
+    *bin_len_out = 0;
d738b9
+    *bin_out = NULL;
d738b9
+
d738b9
+    str_len = strlen(str);
d738b9
+    if (str_len % 2 != 0)
d738b9
+        return EINVAL;
d738b9
+    bin = malloc(str_len / 2);
d738b9
+    if (bin == NULL)
d738b9
+        return ENOMEM;
d738b9
+
d738b9
+    errno = 0;
d738b9
+    for (i = 0; i < str_len / 2; i++) {
d738b9
+        tmp[0] = str[i * 2];
d738b9
+        tmp[1] = str[i * 2 + 1];
d738b9
+
d738b9
+        val = strtol(tmp, &endptr, 16);
d738b9
+        if (val < 0 || val > 255 || errno != 0 || endptr != &tmp[2]) {
d738b9
+            free(bin);
d738b9
+            return EINVAL;
d738b9
+        }
d738b9
+
d738b9
+        bin[i] = (CK_BYTE)val;
d738b9
+    }
d738b9
+
d738b9
+    *bin_len_out = str_len / 2;
d738b9
+    *bin_out = bin;
d738b9
+    return 0;
d738b9
+}
d738b9
+
d738b9
 static krb5_error_code
d738b9
 pkinit_get_certs_pkcs11(krb5_context context,
d738b9
                         pkinit_plg_crypto_context plg_cryptoctx,
d738b9
@@ -4682,18 +4719,14 @@ pkinit_get_certs_pkcs11(krb5_context context,
d738b9
     }
d738b9
     /* Convert the ascii cert_id string into a binary blob */
d738b9
     if (idopts->cert_id_string != NULL) {
d738b9
-        BIGNUM *bn = NULL;
d738b9
-        BN_hex2bn(&bn, idopts->cert_id_string);
d738b9
-        if (bn == NULL)
d738b9
-            return ENOMEM;
d738b9
-        id_cryptoctx->cert_id_len = BN_num_bytes(bn);
d738b9
-        id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
d738b9
-        if (id_cryptoctx->cert_id == NULL) {
d738b9
-            BN_free(bn);
d738b9
-            return ENOMEM;
d738b9
+        r = hex_string_to_bin(idopts->cert_id_string,
d738b9
+                              &id_cryptoctx->cert_id_len,
d738b9
+                              &id_cryptoctx->cert_id);
d738b9
+        if (r != 0) {
d738b9
+            pkiDebug("Failed to convert certid string [%s]\n",
d738b9
+                     idopts->cert_id_string);
d738b9
+            return r;
d738b9
         }
d738b9
-        BN_bn2bin(bn, id_cryptoctx->cert_id);
d738b9
-        BN_free(bn);
d738b9
     }
d738b9
     id_cryptoctx->slotid = idopts->slotid;
d738b9
     id_cryptoctx->pkcs11_method = 1;