]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Enable PKINIT if at least one group is available 1303/head
authorGreg Hudson <ghudson@mit.edu>
Tue, 30 May 2023 05:21:48 +0000 (01:21 -0400)
committerGreg Hudson <ghudson@mit.edu>
Fri, 2 Jun 2023 05:18:06 +0000 (01:18 -0400)
OpenSSL may no longer allow decoding of non-well-known Diffie-Hellman
group parameters as EVP_PKEY objects in FIPS mode.  However, OpenSSL
does not know about MODP group 2 (1024-bit), which is considered as a
custom group.  As a consequence, the PKINIT kdcpreauth module fails to
load in FIPS mode.

Allow initialization of PKINIT plugin if at least one of the MODP
well-known group parameters successfully decodes.

[ghudson@mit.edu: minor commit message and code edits]

ticket: 9096 (new)

src/plugins/preauth/pkinit/pkinit_clnt.c
src/plugins/preauth/pkinit/pkinit_crypto.h
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
src/plugins/preauth/pkinit/pkinit_srv.c
src/plugins/preauth/pkinit/pkinit_trace.h

index 725d5bc43863f1a9ca00f426234c1692420d4bb8..ea9ba454df17e32ee51e9a49e9af3d28d364de12 100644 (file)
@@ -1378,7 +1378,7 @@ pkinit_client_plugin_init(krb5_context context,
     if (retval)
         goto errout;
 
-    retval = pkinit_init_plg_crypto(&ctx->cryptoctx);
+    retval = pkinit_init_plg_crypto(context, &ctx->cryptoctx);
     if (retval)
         goto errout;
 
index e22798f668b66942b715397886e422454f849db3..4e9a4d40fc2821c97057e96a8552a5604f26c044 100644 (file)
@@ -103,7 +103,8 @@ typedef struct _pkinit_cert_matching_data {
 /*
  * Functions to initialize and cleanup crypto contexts
  */
-krb5_error_code pkinit_init_plg_crypto(pkinit_plg_crypto_context *);
+krb5_error_code pkinit_init_plg_crypto(krb5_context,
+                                      pkinit_plg_crypto_context *);
 void pkinit_fini_plg_crypto(pkinit_plg_crypto_context);
 
 krb5_error_code pkinit_init_req_crypto(pkinit_req_crypto_context *);
index f41328763ec6d39a0c2ffe3fbf407efc7eb260a3..d65867a5e3aa3091dcc84c0e8b3cbbd2e2df0aa1 100644 (file)
@@ -47,7 +47,8 @@
 static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
 static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
 
-static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
+static krb5_error_code pkinit_init_dh_params(krb5_context,
+                                             pkinit_plg_crypto_context);
 static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
 
 static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
@@ -951,7 +952,8 @@ oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx,
 }
 
 krb5_error_code
-pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
+pkinit_init_plg_crypto(krb5_context context,
+                       pkinit_plg_crypto_context *cryptoctx)
 {
     krb5_error_code retval = ENOMEM;
     pkinit_plg_crypto_context ctx = NULL;
@@ -969,7 +971,7 @@ pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx)
     if (retval)
         goto out;
 
-    retval = pkinit_init_dh_params(ctx);
+    retval = pkinit_init_dh_params(context, ctx);
     if (retval)
         goto out;
 
@@ -1278,30 +1280,36 @@ pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
     ASN1_OBJECT_free(ctx->id_kp_serverAuth);
 }
 
-static krb5_error_code
-pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
+static int
+try_import_group(krb5_context context, const krb5_data *params,
+                 const char *name, EVP_PKEY **pkey_out)
 {
-    krb5_error_code retval = ENOMEM;
-
-    plgctx->dh_1024 = decode_dh_params(&oakley_1024);
-    if (plgctx->dh_1024 == NULL)
-        goto cleanup;
-
-    plgctx->dh_2048 = decode_dh_params(&oakley_2048);
-    if (plgctx->dh_2048 == NULL)
-        goto cleanup;
+    *pkey_out = decode_dh_params(params);
+    if (*pkey_out == NULL)
+        TRACE_PKINIT_DH_GROUP_UNAVAILABLE(context, name);
+    return (*pkey_out != NULL) ? 1 : 0;
+}
 
-    plgctx->dh_4096 = decode_dh_params(&oakley_4096);
-    if (plgctx->dh_4096 == NULL)
-        goto cleanup;
+static krb5_error_code
+pkinit_init_dh_params(krb5_context context, pkinit_plg_crypto_context plgctx)
+{
+    int n = 0;
 
-    retval = 0;
+    n += try_import_group(context, &oakley_1024, "MODP 2 (1024-bit)",
+                          &plgctx->dh_1024);
+    n += try_import_group(context, &oakley_2048, "MODP 14 (2048-bit)",
+                          &plgctx->dh_2048);
+    n += try_import_group(context, &oakley_4096, "MODP 16 (4096-bit)",
+                          &plgctx->dh_4096);
 
-cleanup:
-    if (retval)
+    if (n == 0) {
         pkinit_fini_dh_params(plgctx);
+        k5_setmsg(context, ENOMEM,
+                  _("PKINIT cannot initialize any key exchange groups"));
+        return ENOMEM;
+    }
 
-    return retval;
+    return 0;
 }
 
 static void
@@ -2901,11 +2909,11 @@ client_create_dh(krb5_context context,
 
     if (cryptoctx->received_params != NULL)
         params = cryptoctx->received_params;
-    else if (dh_size == 1024)
+    else if (plg_cryptoctx->dh_1024 != NULL && dh_size == 1024)
         params = plg_cryptoctx->dh_1024;
-    else if (dh_size == 2048)
+    else if (plg_cryptoctx->dh_2048 != NULL && dh_size == 2048)
         params = plg_cryptoctx->dh_2048;
-    else if (dh_size == 4096)
+    else if (plg_cryptoctx->dh_4096 != NULL && dh_size == 4096)
         params = plg_cryptoctx->dh_4096;
     else
         goto cleanup;
@@ -3201,19 +3209,23 @@ pkinit_create_td_dh_parameters(krb5_context context,
     krb5_algorithm_identifier alg_4096 = { dh_oid, oakley_4096 };
     krb5_algorithm_identifier *alglist[4];
 
-    if (opts->dh_min_bits > 4096) {
-        ret = KRB5KRB_ERR_GENERIC;
-        goto cleanup;
-    }
-
     i = 0;
-    if (opts->dh_min_bits <= 2048)
+    if (plg_cryptoctx->dh_2048 != NULL && opts->dh_min_bits <= 2048)
         alglist[i++] = &alg_2048;
-    alglist[i++] = &alg_4096;
-    if (opts->dh_min_bits <= 1024)
+    if (plg_cryptoctx->dh_4096 != NULL && opts->dh_min_bits <= 4096)
+        alglist[i++] = &alg_4096;
+    if (plg_cryptoctx->dh_1024 != NULL && opts->dh_min_bits <= 1024)
         alglist[i++] = &alg_1024;
     alglist[i] = NULL;
 
+    if (i == 0) {
+        ret = KRB5KRB_ERR_GENERIC;
+        k5_setmsg(context, ret,
+                  _("OpenSSL has no supported key exchange groups for "
+                    "pkinit_dh_min_bits=%d"), opts->dh_min_bits);
+        goto cleanup;
+    }
+
     ret = k5int_encode_krb5_td_dh_parameters(alglist, &der_alglist);
     if (ret)
         goto cleanup;
index 1b3bf6d4d0eeb5a3b2098c5cdf26c49d54a93453..768a4e559f8e7f27b42ae0560d15ddcdd5a8af15 100644 (file)
@@ -1222,7 +1222,7 @@ pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
         goto errout;
     plgctx->realmname_len = strlen(plgctx->realmname);
 
-    retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
+    retval = pkinit_init_plg_crypto(context, &plgctx->cryptoctx);
     if (retval)
         goto errout;
 
index 259e95c6c2c27aabd50f4155b7f3d180acc3e0e6..5ee39c085ca8560741cf9ccca699e5b0cafc3e44 100644 (file)
@@ -90,6 +90,9 @@
 #define TRACE_PKINIT_CLIENT_TRYAGAIN(c)                                 \
     TRACE(c, "PKINIT client trying again with KDC-provided parameters")
 
+#define TRACE_PKINIT_DH_GROUP_UNAVAILABLE(c, name)                      \
+    TRACE(c, "PKINIT key exchange group {str} unsupported", name)
+
 #define TRACE_PKINIT_OPENSSL_ERROR(c, msg)              \
     TRACE(c, "PKINIT OpenSSL error: {str}", msg)