svn rev #25218: trunk/src/ kdc/ lib/krb5/error_tables/ plugins/preauth/pkinit/

hartmans@MIT.EDU hartmans at MIT.EDU
Wed Sep 21 14:40:16 EDT 2011


http://src.mit.edu/fisheye/changelog/krb5/?cs=25218
Commit By: hartmans
Log Message:
pkinit:  changes to call alg-agility KDF

If the client offers the alg agility KDF, use it.

Signed-off-by: Margaret Wasserman <mrw at painless-security.com>


Changed Files:
U   trunk/src/kdc/kdc_preauth.c
U   trunk/src/lib/krb5/error_tables/krb5_err.et
U   trunk/src/plugins/preauth/pkinit/pkinit_clnt.c
U   trunk/src/plugins/preauth/pkinit/pkinit_crypto.h
U   trunk/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
U   trunk/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
U   trunk/src/plugins/preauth/pkinit/pkinit_srv.c
Modified: trunk/src/kdc/kdc_preauth.c
===================================================================
--- trunk/src/kdc/kdc_preauth.c	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/kdc/kdc_preauth.c	2011-09-21 18:40:16 UTC (rev 25218)
@@ -1104,6 +1104,8 @@
         /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */
         /* case KRB5KDC_ERR_KEY_TOO_WEAK: */
     case KRB5KDC_ERR_DISCARD:
+        /* pkinit alg-agility */
+    case KRB5KDC_ERR_NO_ACCEPTABLE_KDF:
         return retval;
     default:
         return KRB5KDC_ERR_PREAUTH_FAILED;

Modified: trunk/src/lib/krb5/error_tables/krb5_err.et
===================================================================
--- trunk/src/lib/krb5/error_tables/krb5_err.et	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/lib/krb5/error_tables/krb5_err.et	2011-09-21 18:40:16 UTC (rev 25218)
@@ -123,7 +123,7 @@
 error_code KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED,	"Checksum must be included"
 error_code KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED,	"Digest in signed-data not accepted"
 error_code KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED,	"Public key encryption not supported"
-error_code KRB5PLACEHOLD_82,	"KRB5 error code 82"
+error_code KRB5KDC_ERR_NO_ACCEPTABLE_KDF,		"No acceptable KDF offered"
 error_code KRB5PLACEHOLD_83,	"KRB5 error code 83"
 error_code KRB5PLACEHOLD_84,	"KRB5 error code 84"
 error_code KRB5KRB_AP_ERR_IAKERB_KDC_NOT_FOUND,         "The IAKERB proxy could not find a KDC"

Modified: trunk/src/plugins/preauth/pkinit/pkinit_clnt.c
===================================================================
--- trunk/src/plugins/preauth/pkinit/pkinit_clnt.c	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/plugins/preauth/pkinit/pkinit_clnt.c	2011-09-21 18:40:16 UTC (rev 25218)
@@ -684,6 +684,7 @@
     unsigned int client_key_len = 0;
     krb5_checksum cksum = {0, 0, 0, NULL};
     krb5_data k5data;
+    krb5_octet_data secret;
     int valid_san = 0;
     int valid_eku = 0;
     int need_eku_checking = 1;
@@ -794,12 +795,35 @@
             goto cleanup;
         }
 
-        retval = pkinit_octetstring2key(context, etype, client_key,
+        /* If we have a KDF algorithm ID, call the algorithm agility KDF... */
+        if (kdc_reply->u.dh_Info.kdfID) {
+            secret.length = client_key_len;
+            secret.data = client_key;
+
+            retval = pkinit_alg_agility_kdf(context, &secret,
+                                            kdc_reply->u.dh_Info.kdfID,
+                                            request->client,
+                                            request->server, etype,
+                                            (krb5_octet_data *)encoded_request,
+                                            (krb5_octet_data *)as_rep,
+                                            key_block);
+
+            if (retval) {
+                pkiDebug("failed to create key pkinit_alg_agility_kdf %s\n",
+                         error_message(retval));
+                goto cleanup;
+            }
+
+        /* ...otherwise, use the older octetstring2key function. */
+        } else {
+
+            retval = pkinit_octetstring2key(context, etype, client_key,
                                         client_key_len, key_block);
-        if (retval) {
-            pkiDebug("failed to create key pkinit_octetstring2key %s\n",
-                     error_message(retval));
-            goto cleanup;
+            if (retval) {
+                pkiDebug("failed to create key pkinit_octetstring2key %s\n",
+                         error_message(retval));
+                goto cleanup;
+            }
         }
 
         break;

Modified: trunk/src/plugins/preauth/pkinit/pkinit_crypto.h
===================================================================
--- trunk/src/plugins/preauth/pkinit/pkinit_crypto.h	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/plugins/preauth/pkinit/pkinit_crypto.h	2011-09-21 18:40:16 UTC (rev 25218)
@@ -648,5 +648,14 @@
 extern const size_t krb5_pkinit_sha256_oid_len;
 extern const krb5_octet krb5_pkinit_sha512_oid[];
 extern const size_t  krb5_pkinit_sha512_oid_len;
+/**
+ * An ordered set of OIDs, stored as krb5_octet_data of KDF algorithms
+ * supported by this implementation. The order of this array controls
+ * the order in which the server will pick.
+ */
+extern const krb5_octet_data const *supported_kdf_alg_ids[] ;
+extern const krb5_octet_data const sha1_id;
+extern const krb5_octet_data const sha256_id;
+extern const krb5_octet_data const sha512_id;
 
 #endif	/* _PKINIT_CRYPTO_H */

Modified: trunk/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
===================================================================
--- trunk/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c	2011-09-21 18:40:16 UTC (rev 25218)
@@ -2263,6 +2263,11 @@
     }
     memset (key_block->contents, 0, key_block->length);
 
+    /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
+    if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
+                                                         krb5_anonymous_principal()))
+        party_u_info = krb5_anonymous_principal();
+
     if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
         goto cleanup;
 

Modified: trunk/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
===================================================================
--- trunk/src/plugins/preauth/pkinit/pkinit_kdf_constants.c	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/plugins/preauth/pkinit/pkinit_kdf_constants.c	2011-09-21 18:40:16 UTC (rev 25218)
@@ -46,12 +46,27 @@
 #include "pkinit_crypto.h"
 
 /* statically declare OID constants for all three algorithms */
-const krb5_octet krb5_pkinit_sha1_oid[10] =
+const krb5_octet krb5_pkinit_sha1_oid[8] =
 {0x2B,0x06,0x01,0x05,0x02,0x03,0x06,0x01};
 const size_t krb5_pkinit_sha1_oid_len = 8;
-const krb5_octet krb5_pkinit_sha256_oid[10] =
+const krb5_octet krb5_pkinit_sha256_oid[8] =
 {0x2B,0x06,0x01,0x05,0x02,0x03,0x06,0x02};
 const size_t krb5_pkinit_sha256_oid_len = 8;
-const krb5_octet krb5_pkinit_sha512_oid [10] =
+const krb5_octet krb5_pkinit_sha512_oid [8] =
 {0x2B,0x06,0x01,0x05,0x02,0x03,0x06,0x03};
 const size_t krb5_pkinit_sha512_oid_len = 8;
+
+#define oid_as_data(var, oid_base) \
+    const krb5_octet_data var = \
+    {0, sizeof oid_base, (krb5_octet *) oid_base}
+oid_as_data(sha1_id, krb5_pkinit_sha1_oid);
+oid_as_data(sha256_id, krb5_pkinit_sha256_oid);
+oid_as_data(sha512_id, krb5_pkinit_sha512_oid);
+#undef oid_as_data
+
+const krb5_octet_data const *supported_kdf_alg_ids[] = {
+    &sha256_id,
+    &sha1_id,
+    &sha512_id,
+    NULL
+};

Modified: trunk/src/plugins/preauth/pkinit/pkinit_srv.c
===================================================================
--- trunk/src/plugins/preauth/pkinit/pkinit_srv.c	2011-09-21 18:40:09 UTC (rev 25217)
+++ trunk/src/plugins/preauth/pkinit/pkinit_srv.c	2011-09-21 18:40:16 UTC (rev 25218)
@@ -34,6 +34,7 @@
 #include <errno.h>
 #include <string.h>
 
+#include <k5-int.h>
 #include "pkinit.h"
 
 /* Remove when FAST PKINIT is settled. */
@@ -659,6 +660,46 @@
 }
 
 static krb5_error_code
+pkinit_pick_kdf_alg(krb5_context context,
+                    krb5_octet_data **kdf_list,
+                    krb5_octet_data **alg_oid)
+{
+    krb5_error_code retval = 0;
+    krb5_octet_data *req_oid = NULL;
+    const krb5_octet_data *supp_oid = NULL;
+    krb5_octet_data *tmp_oid = NULL;
+    int i, j = 0;
+
+    *alg_oid = NULL;
+
+    /* for each of the OIDs in the client's request... */
+    for (i = 0; NULL != (req_oid = kdf_list[i]); i++) {
+        /* if the requested OID is supported, use it. */
+        for (j = 0; NULL != (supp_oid = supported_kdf_alg_ids[j]); j++) {
+            if ((req_oid->length == supp_oid->length) &&
+                (0 == memcmp(req_oid->data, supp_oid->data, req_oid->length))) {
+                tmp_oid = k5alloc(sizeof(krb5_octet_data), &retval);
+                if (retval)
+                    goto cleanup;
+                tmp_oid->data = k5alloc(supp_oid->length, &retval);
+                if (retval)
+                    goto cleanup;
+                tmp_oid->length = supp_oid->length;
+                memcpy(tmp_oid->data, supp_oid->data, supp_oid->length);
+                *alg_oid = tmp_oid;
+                tmp_oid = NULL;
+                goto cleanup;
+            }
+        }
+        retval = KRB5KDC_ERR_NO_ACCEPTABLE_KDF;
+    }
+cleanup:
+    if (tmp_oid)
+        krb5_free_octet_data(context, tmp_oid);
+    return retval;
+}
+
+static krb5_error_code
 pkinit_server_return_padata(krb5_context context,
                             krb5_pa_data * padata,
                             struct _krb5_db_entry_new * client,
@@ -688,6 +729,7 @@
     krb5_pa_pk_as_rep *rep = NULL;
     krb5_pa_pk_as_rep_draft9 *rep9 = NULL;
     krb5_data *out_data = NULL;
+    krb5_octet_data secret;
 
     krb5_enctype enctype = -1;
 
@@ -975,6 +1017,25 @@
 #endif
     }
 
+    if ((rep != NULL && rep->choice == choice_pa_pk_as_rep_dhInfo) &&
+        ((reqctx->rcv_auth_pack != NULL &&
+          reqctx->rcv_auth_pack->supportedKDFs != NULL))) {
+
+        /* If using the alg-agility KDF, put the algorithm in the reply
+         * before encoding it.
+         */
+        if (reqctx->rcv_auth_pack != NULL &&
+            reqctx->rcv_auth_pack->supportedKDFs != NULL) {
+            retval = pkinit_pick_kdf_alg(context, reqctx->rcv_auth_pack->supportedKDFs,
+                                         &(rep->u.dh_Info.kdfID));
+            if (retval) {
+                pkiDebug("pkinit_pick_kdf_alg failed: %s\n",
+                         error_message(retval));
+                goto cleanup;
+            }
+        }
+    }
+
     switch ((int)padata->pa_type) {
     case KRB5_PADATA_PK_AS_REQ:
         retval = k5int_encode_krb5_pa_pk_as_rep(rep, &out_data);
@@ -998,12 +1059,36 @@
     if ((rep9 != NULL &&
          rep9->choice == choice_pa_pk_as_rep_draft9_dhSignedData) ||
         (rep != NULL && rep->choice == choice_pa_pk_as_rep_dhInfo)) {
-        retval = pkinit_octetstring2key(context, enctype, server_key,
-                                        server_key_len, encrypting_key);
-        if (retval) {
-            pkiDebug("pkinit_octetstring2key failed: %s\n",
-                     error_message(retval));
-            goto cleanup;
+
+        /* If supported KDFs are specified, use the alg agility KDF */
+        if ((reqctx->rcv_auth_pack != NULL &&
+             reqctx->rcv_auth_pack->supportedKDFs != NULL)) {
+
+            secret.data = server_key;
+            secret.length = server_key_len;
+
+            retval = pkinit_alg_agility_kdf(context, &secret,
+                                            rep->u.dh_Info.kdfID,
+                                            request->client, request->server,
+                                            enctype,
+                                            (krb5_octet_data *)req_pkt,
+                                            (krb5_octet_data *)out_data,
+                                            encrypting_key);
+            if (retval) {
+                pkiDebug("pkinit_alg_agility_kdf failed: %s\n",
+                         error_message(retval));
+                goto cleanup;
+            }
+
+            /* Otherwise, use the older octetstring2key() function */
+        } else {
+            retval = pkinit_octetstring2key(context, enctype, server_key,
+                                            server_key_len, encrypting_key);
+            if (retval) {
+                pkiDebug("pkinit_octetstring2key failed: %s\n",
+                         error_message(retval));
+                goto cleanup;
+            }
         }
     }
 
@@ -1028,7 +1113,6 @@
     (*send_pa)->length = out_data->length;
     (*send_pa)->contents = (krb5_octet *) out_data->data;
 
-
 cleanup:
     pkinit_fini_kdc_req_context(context, reqctx);
     free(scratch.data);




More information about the cvs-krb5 mailing list