krb5 commit: Support PKCS11 EC client certs in PKINIT

ghudson at mit.edu ghudson at mit.edu
Mon Mar 18 21:20:14 EDT 2024


https://github.com/krb5/krb5/commit/f745c9a9bd6c0c73b944182173f1ac305d03dc3a
commit f745c9a9bd6c0c73b944182173f1ac305d03dc3a
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Feb 21 15:29:02 2024 -0500

    Support PKCS11 EC client certs in PKINIT
    
    Move the digest computation and DigestInfo encoding from
    cms_signeddata_create() to pkinit_sign_data_pkcs11(), and
    conditionalize the DigestInfo encoding on the key type.  Use CKM_ECDSA
    instead of CKM_RSA_PKCS for EC keys, and convert the resulting
    signature from the PKS11 encoding to the ASN.1 encoding required by
    CMS.
    
    Regenerate the test certificates with an additional EC client cert.
    Add test cases for EC client certs with and without PKCS11.
    
    ticket: 9112 (new)

 src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 319 +++++++++++++--------
 src/tests/pkinit-certs/ca.pem                      |  32 +--
 src/tests/pkinit-certs/eckey.pem                   |   5 +
 src/tests/pkinit-certs/ecuser.pem                  |  24 ++
 src/tests/pkinit-certs/generic.p12                 | Bin 2469 -> 2560 bytes
 src/tests/pkinit-certs/generic.pem                 |  38 +--
 src/tests/pkinit-certs/kdc.pem                     |  32 +--
 src/tests/pkinit-certs/make-certs.sh               |  11 +-
 src/tests/pkinit-certs/privkey-enc.pem             |  60 ++--
 src/tests/pkinit-certs/privkey.pem                 |  55 ++--
 src/tests/pkinit-certs/user-enc.p12                | Bin 2829 -> 2920 bytes
 src/tests/pkinit-certs/user-upn.p12                | Bin 2821 -> 2912 bytes
 src/tests/pkinit-certs/user-upn.pem                |  32 +--
 src/tests/pkinit-certs/user-upn2.p12               | Bin 2805 -> 2896 bytes
 src/tests/pkinit-certs/user-upn2.pem               |  34 +--
 src/tests/pkinit-certs/user-upn3.p12               | Bin 2821 -> 2912 bytes
 src/tests/pkinit-certs/user-upn3.pem               |  32 +--
 src/tests/pkinit-certs/user.p12                    | Bin 2829 -> 2920 bytes
 src/tests/pkinit-certs/user.pem                    |  30 +-
 src/tests/t_pkinit.py                              |  20 ++
 20 files changed, 437 insertions(+), 287 deletions(-)

diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 25796fd82..18f1ffe9f 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -93,7 +93,6 @@ struct _pkinit_identity_crypto_context {
     CK_FUNCTION_LIST_PTR p11;
     uint8_t *cert_id;
     size_t cert_id_len;
-    CK_MECHANISM_TYPE mech;
 #endif
     krb5_boolean defer_id_prompt;
     pkinit_deferred_id *deferred_ids;
@@ -283,7 +282,6 @@ compat_get0_EC(const EVP_PKEY *pkey)
 #if OPENSSL_VERSION_NUMBER < 0x30000000L
 /* OpenSSL 3.0 changes several preferred function names. */
 #define EVP_PKEY_parameters_eq EVP_PKEY_cmp_parameters
-#define EVP_MD_CTX_get0_md EVP_MD_CTX_md
 #define EVP_PKEY_get_size EVP_PKEY_size
 #define EVP_PKEY_get_bits EVP_PKEY_bits
 
@@ -1698,17 +1696,12 @@ cms_signeddata_create(krb5_context context,
     STACK_OF(X509) * cert_stack = NULL;
     ASN1_OCTET_STRING *digest_attr = NULL;
     EVP_MD_CTX *ctx;
-    const EVP_MD *md_tmp = NULL;
-    unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
-    unsigned char *digestInfo_buf = NULL, *abuf = NULL;
-    unsigned int md_len, md_len2, alen, digestInfo_len;
+    unsigned char md_data[EVP_MAX_MD_SIZE], *abuf = NULL;
+    unsigned int md_len, alen;
     STACK_OF(X509_ATTRIBUTE) * sk;
     unsigned char *sig = NULL;
     unsigned int sig_len = 0;
     X509_ALGOR *alg = NULL;
-    ASN1_OCTET_STRING *digest = NULL;
-    unsigned int alg_len = 0, digest_len = 0;
-    unsigned char *y = NULL;
     ASN1_OBJECT *oid = NULL, *oid_copy;
     int sig_alg_id;
 
@@ -1811,7 +1804,6 @@ cms_signeddata_create(krb5_context context,
             goto cleanup;
         EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
         EVP_DigestUpdate(ctx, data, data_len);
-        md_tmp = EVP_MD_CTX_get0_md(ctx);
         EVP_DigestFinal_ex(ctx, md_data, &md_len);
         EVP_MD_CTX_free(ctx);
 
@@ -1836,63 +1828,8 @@ cms_signeddata_create(krb5_context context,
         if (abuf == NULL)
             goto cleanup2;
 
-#ifndef WITHOUT_PKCS11
-        /*
-         * Some tokens can only do RSAEncryption without a hash.  To compute
-         * sha256WithRSAEncryption, encode the algorithm ID for the hash
-         * function and the hash value into an ASN.1 value of type DigestInfo:
-         * DigestInfo ::= SEQUENCE {
-         *   digestAlgorithm  AlgorithmIdentifier,
-         *   digest  OCTET STRING
-         * }
-         */
-        if (id_cryptoctx->pkcs11_method == 1 &&
-            id_cryptoctx->mech == CKM_RSA_PKCS) {
-            pkiDebug("mech = CKM_RSA_PKCS\n");
-            ctx = EVP_MD_CTX_new();
-            if (ctx == NULL)
-                goto cleanup;
-            EVP_DigestInit_ex(ctx, md_tmp, NULL);
-            EVP_DigestUpdate(ctx, abuf, alen);
-            EVP_DigestFinal_ex(ctx, md_data2, &md_len2);
-            EVP_MD_CTX_free(ctx);
-
-            alg = X509_ALGOR_new();
-            if (alg == NULL)
-                goto cleanup2;
-            X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL);
-            alg_len = i2d_X509_ALGOR(alg, NULL);
-
-            digest = ASN1_OCTET_STRING_new();
-            if (digest == NULL)
-                goto cleanup2;
-            ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
-            digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
-
-            digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
-                                              V_ASN1_SEQUENCE);
-            y = digestInfo_buf = malloc(digestInfo_len);
-            if (digestInfo_buf == NULL)
-                goto cleanup2;
-            ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
-                            V_ASN1_UNIVERSAL);
-            i2d_X509_ALGOR(alg, &y);
-            i2d_ASN1_OCTET_STRING(digest, &y);
-#ifdef DEBUG_SIG
-            pkiDebug("signing buffer\n");
-            print_buffer(digestInfo_buf, digestInfo_len);
-            print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
-#endif
-            retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
-                                      digestInfo_len, &sig, &sig_len);
-        } else
-#endif
-        {
-            pkiDebug("mech = %s\n",
-                     id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS");
-            retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
-                                      &sig, &sig_len);
-        }
+        retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
+                                  &sig, &sig_len);
 #ifdef DEBUG_SIG
         print_buffer(sig, sig_len);
 #endif
@@ -1946,14 +1883,6 @@ cms_signeddata_create(krb5_context context,
 
 cleanup2:
     if (p7si) {
-#ifndef WITHOUT_PKCS11
-        if (id_cryptoctx->pkcs11_method == 1 &&
-            id_cryptoctx->mech == CKM_RSA_PKCS) {
-            free(digestInfo_buf);
-            if (digest != NULL)
-                ASN1_OCTET_STRING_free(digest);
-        }
-#endif
         if (alg != NULL)
             X509_ALGOR_free(alg);
     }
@@ -3673,8 +3602,7 @@ cleanup:
  * Look for a key that's:
  * 1. private
  * 2. capable of the specified operation (usually signing or decrypting)
- * 3. RSA (this may be wrong but it's all we can do for now)
- * 4. matches the id of the cert we chose
+ * 3. matches the id of the cert we chose
  *
  * You must call pkinit_get_certs before calling pkinit_find_private_key
  * (that's because we need the ID of the private key)
@@ -3694,7 +3622,6 @@ pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
     CK_OBJECT_CLASS cls;
     CK_ATTRIBUTE attrs[4];
     CK_ULONG count;
-    CK_KEY_TYPE keytype;
     unsigned int nattrs = 0;
     int r;
 #ifdef PKINIT_USE_KEY_USAGE
@@ -3721,12 +3648,6 @@ pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
     nattrs++;
 #endif
 
-    keytype = CKK_RSA;
-    attrs[nattrs].type = CKA_KEY_TYPE;
-    attrs[nattrs].pValue = &keytype;
-    attrs[nattrs].ulValueLen = sizeof keytype;
-    nattrs++;
-
     attrs[nattrs].type = CKA_ID;
     attrs[nattrs].pValue = id_cryptoctx->cert_id;
     attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
@@ -3765,6 +3686,116 @@ pkinit_sign_data_fs(krb5_context context,
 }
 
 #ifndef WITHOUT_PKCS11
+/*
+ * DER-encode a DigestInfo sequence containing the algorithm md and the digest
+ * mdbytes.
+ *
+ * DigestInfo ::= SEQUENCE {
+ *   digestAlgorithm  AlgorithmIdentifier,
+ *   digest  OCTET STRING
+ * }
+ */
+static krb5_error_code
+encode_digestinfo(krb5_context context, const EVP_MD *md,
+                  const uint8_t *mdbytes, size_t mdlen,
+                  uint8_t **encoding_out, size_t *len_out)
+{
+    krb5_boolean ok = FALSE;
+    X509_ALGOR *alg = NULL;
+    ASN1_OCTET_STRING *digest = NULL;
+    uint8_t *buf, *p;
+    int alg_len, digest_len, len;
+
+    *encoding_out = NULL;
+    *len_out = 0;
+
+    alg = X509_ALGOR_new();
+    if (alg == NULL ||
+        !X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_nid(md)), V_ASN1_NULL, NULL))
+        goto cleanup;
+    alg_len = i2d_X509_ALGOR(alg, NULL);
+    if (alg_len < 0)
+        goto cleanup;
+
+    digest = ASN1_OCTET_STRING_new();
+    if (digest == NULL || !ASN1_OCTET_STRING_set(digest, mdbytes, mdlen))
+        goto cleanup;
+    digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
+    if (digest_len < 0)
+        goto cleanup;
+
+    len = ASN1_object_size(1, alg_len + digest_len, V_ASN1_SEQUENCE);
+    p = buf = malloc(len);
+    if (buf == NULL)
+        goto cleanup;
+    ASN1_put_object(&p, 1, alg_len + digest_len, V_ASN1_SEQUENCE,
+                    V_ASN1_UNIVERSAL);
+    i2d_X509_ALGOR(alg, &p);
+    i2d_ASN1_OCTET_STRING(digest, &p);
+
+    *encoding_out = buf;
+    *len_out = len;
+    ok = TRUE;
+
+cleanup:
+    X509_ALGOR_free(alg);
+    ASN1_OCTET_STRING_free(digest);
+    if (!ok)
+        return oerr(context, 0, _("Failed to DER encode DigestInfo"));
+    return 0;
+}
+
+/* Extract the r and s values from a PKCS11 ECDSA signature and re-encode them
+ * in the DER representation of an ECDSA-Sig-Value for use in CMS. */
+static krb5_error_code
+convert_pkcs11_ecdsa_sig(krb5_context context,
+                         const uint8_t *p11sig, unsigned int p11siglen,
+                         uint8_t **sig_out, unsigned int *sig_len_out)
+{
+    krb5_boolean ok = FALSE;
+    BIGNUM *r = NULL, *s = NULL;
+    ECDSA_SIG *sig = NULL;
+    int len;
+    uint8_t *p;
+
+    *sig_out = NULL;
+    *sig_len_out = 0;
+
+    if (p11siglen % 2 != 0)
+        return EINVAL;
+
+    /* Extract the r and s values from the PKCS11 signature. */
+    r = BN_bin2bn(p11sig, p11siglen / 2, NULL);
+    s = BN_bin2bn(p11sig + p11siglen / 2, p11siglen / 2, NULL);
+    if (r == NULL || s == NULL)
+        goto cleanup;
+
+    /* Create an ECDSA-Sig-Value object and transfer ownership of r and s. */
+    sig = ECDSA_SIG_new();
+    if (sig == NULL || !ECDSA_SIG_set0(sig, r, s))
+        goto cleanup;
+    r = s = NULL;
+
+    /* DER-encode the ECDSA-Sig-Value object. */
+    len = i2d_ECDSA_SIG(sig, NULL);
+    if (len < 0)
+        goto cleanup;
+    p = *sig_out = malloc(len);
+    if (*sig_out == NULL)
+        goto cleanup;
+    *sig_len_out = len;
+    i2d_ECDSA_SIG(sig, &p);
+    ok = TRUE;
+
+cleanup:
+    BN_free(r);
+    BN_free(s);
+    ECDSA_SIG_free(sig);
+    if (!ok)
+        return oerr(context, 0, _("Failed to convert PKCS11 ECDSA signature"));
+    return 0;
+}
+
 static krb5_error_code
 pkinit_sign_data_pkcs11(krb5_context context,
                         pkinit_identity_crypto_context id_cryptoctx,
@@ -3773,27 +3804,88 @@ pkinit_sign_data_pkcs11(krb5_context context,
                         unsigned char **sig,
                         unsigned int *sig_len)
 {
+    krb5_error_code ret;
     CK_OBJECT_HANDLE obj;
     CK_ULONG len;
     CK_MECHANISM mech;
-    unsigned char *cp;
+    CK_SESSION_HANDLE session;
+    CK_FUNCTION_LIST_PTR p11;
+    CK_ATTRIBUTE attr;
+    CK_KEY_TYPE keytype;
+    EVP_MD_CTX *ctx;
+    const EVP_MD *md = EVP_sha256();
+    unsigned int mdlen;
+    uint8_t mdbuf[EVP_MAX_MD_SIZE], *dinfo = NULL, *sigbuf = NULL, *input;
+    size_t dinfo_len, input_len;
     int r;
 
+    *sig = NULL;
+    *sig_len = 0;
+
     if (pkinit_open_session(context, id_cryptoctx)) {
         pkiDebug("can't open pkcs11 session\n");
         return KRB5KDC_ERR_PREAUTH_FAILED;
     }
+    p11 = id_cryptoctx->p11;
+    session = id_cryptoctx->session;
 
-    pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
+    ret = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
+    if (ret)
+        return ret;
+
+    attr.type = CKA_KEY_TYPE;
+    attr.pValue = &keytype;
+    attr.ulValueLen = sizeof(keytype);
+    r = p11->C_GetAttributeValue(session, obj, &attr, 1);
+    if (r) {
+        pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(r));
+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
+        goto cleanup;
+    }
+
+    /*
+     * We would ideally use CKM_SHA256_RSA_PKCS and CKM_ECDSA_SHA256, but
+     * historically many cards seem to be confused about whether they are
+     * capable of mechanisms or not.  To be safe we compute the digest
+     * ourselves and use CKM_RSA_PKCS and CKM_ECDSA.
+     */
+    ctx = EVP_MD_CTX_new();
+    if (ctx == NULL) {
+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
+        goto cleanup;
+    }
+    EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
+    EVP_DigestUpdate(ctx, data, data_len);
+    EVP_DigestFinal_ex(ctx, mdbuf, &mdlen);
+    EVP_MD_CTX_free(ctx);
 
-    mech.mechanism = id_cryptoctx->mech;
+    if (keytype == CKK_RSA) {
+        /* For RSA we must also encode the digest in a DigestInfo sequence. */
+        mech.mechanism = CKM_RSA_PKCS;
+        ret = encode_digestinfo(context, md, mdbuf, mdlen, &dinfo, &dinfo_len);
+        if (ret)
+            goto cleanup;
+        input = dinfo;
+        input_len = dinfo_len;
+    } else if (keytype == CKK_EC) {
+        mech.mechanism = CKM_ECDSA;
+        input = mdbuf;
+        input_len = mdlen;
+    } else {
+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
+        k5_setmsg(context, ret,
+                  _("PKCS11 certificate has unsupported key type %lu"),
+                  keytype);
+        goto cleanup;
+    }
     mech.pParameter = NULL;
     mech.ulParameterLen = 0;
 
-    if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
-                                           obj)) != CKR_OK) {
+    r = p11->C_SignInit(session, &mech, obj);
+    if (r != CKR_OK) {
         pkiDebug("C_SignInit: %s\n", pkcs11err(r));
-        return KRB5KDC_ERR_PREAUTH_FAILED;
+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
+        goto cleanup;
     }
 
     /*
@@ -3801,28 +3893,38 @@ pkinit_sign_data_pkcs11(krb5_context context,
      * get that. So guess, and if it's too small, re-malloc.
      */
     len = PK_SIGLEN_GUESS;
-    cp = malloc((size_t) len);
-    if (cp == NULL)
-        return ENOMEM;
+    sigbuf = k5alloc(len, &ret);
+    if (sigbuf == NULL)
+        goto cleanup;
 
-    r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
-                                  (CK_ULONG) data_len, cp, &len);
+    r = p11->C_Sign(session, input, input_len, sigbuf, &len);
     if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
-        free(cp);
+        free(sigbuf);
         pkiDebug("C_Sign realloc %d\n", (int) len);
-        cp = malloc((size_t) len);
-        r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
-                                      (CK_ULONG) data_len, cp, &len);
+        sigbuf = k5alloc(len, &ret);
+        if (sigbuf == NULL)
+            goto cleanup;
+        r = p11->C_Sign(session, input, input_len, sigbuf, &len);
     }
     if (r != CKR_OK) {
         pkiDebug("C_Sign: %s\n", pkcs11err(r));
-        return KRB5KDC_ERR_PREAUTH_FAILED;
+        ret = KRB5KDC_ERR_PREAUTH_FAILED;
+        goto cleanup;
     }
-    pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
-    *sig_len = len;
-    *sig = cp;
 
-    return 0;
+    if (keytype == CKK_EC) {
+        /* PKCS11 ECDSA signatures must be re-encoded for CMS. */
+        ret = convert_pkcs11_ecdsa_sig(context, sigbuf, len, sig, sig_len);
+    } else {
+        *sig_len = len;
+        *sig = sigbuf;
+        sigbuf = NULL;
+    }
+
+cleanup:
+    free(dinfo);
+    free(sigbuf);
+    return ret;
 }
 #endif
 
@@ -4404,15 +4506,6 @@ pkinit_get_certs_pkcs11(krb5_context context,
         return 0;
     }
 
-    /*
-     * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but
-     * historically many cards seem to be confused about whether they are
-     * capable of mechanisms or not. The safe thing seems to be to ignore the
-     * mechanism list, always use CKM_RSA_PKCS and calculate the sha256 digest
-     * ourselves.
-     */
-    id_cryptoctx->mech = CKM_RSA_PKCS;
-
     cls = CKO_CERTIFICATE;
     attrs[0].type = CKA_CLASS;
     attrs[0].pValue = &cls;
diff --git a/src/tests/pkinit-certs/ca.pem b/src/tests/pkinit-certs/ca.pem
index 63d31c1f5..6c782bcde 100644
--- a/src/tests/pkinit-certs/ca.pem
+++ b/src/tests/pkinit-certs/ca.pem
@@ -3,27 +3,27 @@ MIIE5TCCA82gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
 FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
 A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
 dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMFoXDTMyMDkyMDIxMTEzMFowgacxCzAJ
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owgacxCzAJ
 BgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlDYW1i
 cmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwgSW5zZWN1cmUgUEtJTklUIEtl
 cmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBk
 byBub3QgdXNlIG90aGVyd2lzZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAM+lV5iaVats0yBFN4FBe6bovloNe3d0F9qMuhKqlECv6cFra75gSGmHJz6t
-GTK8zITU7sni429azTZC9IQnUt/2lW8dWzpZD1T5Vt1DYvYFqVzjhNfzeEDK88ig
-ENfzaX/cY2P76arJr0cewGaauzaux8heYW1CjBxWmk6kWq4aD+5jggchvBeOGEE2
-NkV3MPbXut8fu+3NzuuIG7Z0ilwQv+KUvQ8QQb9VCwdsDh/ERsQ4loC9P4jtuWCJ
-ikIE78GxDcOMoC1ftJtW/mBCS2iCHipXrp2BDDJMyHxZjHpl0VoDR7koWGtD3sos
-EwUkXVvWIuKs432h2dXQ+u8HaBsCAwEAAaOCARgwggEUMB0GA1UdDgQWBBT0F6X7
-1QRftDiSeNSY3bks3nK0IzCB1AYDVR0jBIHMMIHJgBT0F6X71QRftDiSeNSY3bks
-3nK0I6GBraSBqjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0
+ggEBAJv9Sbc2QSbHWnZjk55JfeOdPGUsmKOcT/N7C0/0mOQq4tUCmha7ntpBoIJd
+UBDhMQayG3QHruQX7aogtOx8hoLoLUaNKgxzEZ0OLbDRMc2M+vTDpBROITGI1KPv
+QtthlS4ocqKvqBCze66N9LufzAju61CyKdB3pCykPrgDVVScfsZ1t2zCbK0SF2cf
+ZAdIyCLoGLeQ95/NL3SIx0CX9gU47AVmBkSQ+LExJRhbUSIg+puKbqJ0XVILR1B2
+ezgik2ObFND0hsRUS4v8pKnIDz0HXR2AneTESY+atjbzzelGA2zH86p4tLg0PanQ
+4x4+gpkQhzSr5Cmi3QX4XahSrmUCAwEAAaOCARgwggEUMB0GA1UdDgQWBBSSP/pz
+leX5zVcZ9hpI5GG2eQ+pqjCB1AYDVR0jBIHMMIHJgBSSP/pzleX5zVcZ9hpI5GG2
+eQ+pqqGBraSBqjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0
 dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoGA1UECgwDTUlUMSkwJwYDVQQLDCBJ
 bnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAwwqcGtpbml0
 IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQE
-AwIB/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBT2FJVPS+U
-0MXa1HUOETuUPrVff7VeIvyAPm9IgX1zNbCvktCc4d7ErNB3P5ng8aZz4MKqwzuX
-HVhUxbF7JKfyUI41lcixPG+k+U9mzBJaozWT+K1OhdUF//mGPxaxe5jyUhDiQArD
-/6vulX0/B+1iuIa1sCfoeelzqQcYHqhZdWn6bBdcDWNARHIXWs5zPeKA975+d5TW
-rofE7T8nNQJvcZoVjCSfcYXhP82D/0sA+wPCt3fgbBZdvJ89xwvIlzBtiwC++Zbe
-37Rt5av0+ykpR7nmh2jyG+ItzE73nYKdBrUI5J6JLSbUcQTw4jeXHwDULUHZ6fXg
-TBEM2v1VW4Df
+AwIB/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAfx04Uqh0D
+myOR1PSqEEbMWJxZXYoESnjjH4Co4doceVBTuKix/2lplD4wcvA7aMXpmkvGfP38
+dPrN1jvGd4bi/djTuxab9qB7rOeswAt+NyVHReUmuIMwgcW1UD7HXErg4EsOMjGD
+2XGhJYxGnwdURmnFwoO3yLLwo5K+C4rqPm3PbnI3W0sCA+IXepQTxuXK3dSplMMm
+0Pejw3es2s3oI9WaD2JRXvFuylw4UWYX+cyFRb+wN55Gh0rPVdxDhKCkbWNt/gTi
+/DbC+5pyQXkmy07OEGrmh4+5ae9hwejr9AukF2IZJB+oFP4i1mt9xyAOXImnWOzB
+SdHD08WHl5Gq
 -----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/eckey.pem b/src/tests/pkinit-certs/eckey.pem
new file mode 100644
index 000000000..14c2efd2a
--- /dev/null
+++ b/src/tests/pkinit-certs/eckey.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgSB3T7ihe3JUeIKZI
+PCDqATKN/dNugQsaC5AKiBPC6ymhRANCAAQy0E88e1CX16/2wL2T+nE0pmlb7wBM
+0hOh6m3m2uDbVsAIRJfhEjHWsT2ODCoBvGDV6vBeIOUjE/Ro9EwnYBW5
+-----END PRIVATE KEY-----
diff --git a/src/tests/pkinit-certs/ecuser.pem b/src/tests/pkinit-certs/ecuser.pem
new file mode 100644
index 000000000..585e53d8c
--- /dev/null
+++ b/src/tests/pkinit-certs/ecuser.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIECDCCAvCgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
+A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
+dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owSjELMAkG
+A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
+U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+MtBPPHtQl9ev9sC9k/pxNKZpW+8ATNIToept5trg21bACESX4RIx1rE9jgwqAbxg
+1erwXiDlIxP0aPRMJ2AVuaOCAWQwggFgMB0GA1UdDgQWBBR5MaRx7ub5YBwsS0CF
+Li18nsl49zCB1AYDVR0jBIHMMIHJgBSSP/pzleX5zVcZ9hpI5GG2eQ+pqqGBraSB
+qjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNV
+BAcMCUNhbWJyaWRnZTEMMAoGA1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQ
+S0lOSVQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3Vp
+dGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQEAwID6DAMBgNV
+HRMBAf8EAjAAMDkGA1UdEQQyMDCgLgYGKwYBBQICoCQwIqANGwtLUkJURVNULkNP
+TaERMA+gAwIBAaEIMAYbBHVzZXIwEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG
+9w0BAQsFAAOCAQEAfwlONLYPo0BNN2NyQZM3wkoldvFqidcoZiYALOcBcmllMP7H
+XQ/+en4TmbKR0RUJN6AjR9yEo92fHAYOB2L7AzR8AkOiRLjp/Pdg5kUHFTdKenTK
+DvpeiJELz9chk/vaMv1T9qvOwH2bVAyS8GrUc5n0ui5F61PrquLAmm+dpKyHDY60
+DdFaebS2gYsmy4bBv0mgcMZ+ZXnzXYmLNtdVQ3SgVGO7M8eyCqPbe/o0Lw4Gz+l0
+xgpFkptdlEogsOaJBzjrgWyBnWw6MkyyLiSY+iOxFpBGkwCxi1gtQwbcp4gMwaxc
+p5+JPM/JBfglBX1lpRhhxL8EGQvpryN9MT530w==
+-----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/generic.p12 b/src/tests/pkinit-certs/generic.p12
index 35c27415b..55a248137 100644
Binary files a/src/tests/pkinit-certs/generic.p12 and b/src/tests/pkinit-certs/generic.p12 differ
diff --git a/src/tests/pkinit-certs/generic.pem b/src/tests/pkinit-certs/generic.pem
index 55ebb3dbf..dde7f31a7 100644
--- a/src/tests/pkinit-certs/generic.pem
+++ b/src/tests/pkinit-certs/generic.pem
@@ -1,21 +1,21 @@
 -----BEGIN CERTIFICATE-----
-MIIDazCCAlOgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
-FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
-A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
-dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG
-A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
-U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn
-Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz
-yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y
-QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25
-YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe
-yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCS
-OTfZununxFDxuThhIFDWEZ9p2qSqTrxKtKx4CDvdckz4kaKybiNZTW7Dlh6IwWta
-60eq98WrMHXYlSaN87r95lU0ug2RFJh4uLdq3a5NM/daIIjO0Bo86oC+8EBM961Q
-mCMe7dn9ngFK92msdqO+wfpAfvhSpBPtAjQovigirheiEoER/ov9t9/3mRi5OTkY
-8YfKT/z6XJrnOUIB3AgCdGyzSRvWLqLrbh7iAFVrm6Pq6D2nNr+mE9r5u7uFl3r8
-QeDgp0Unwd1ISWTHZlrP4bq29w7y2O+/2KV04Og8z+4zoGD4nRinuJBUdNqwAXVz
-dz6pXFWgLRD+9ddI5jB0
+MIIDZjCCAk4CAQgwDQYJKoZIhvcNAQELBQAwgacxCzAJBgNVBAYTAlVTMRYwFAYD
+VQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoM
+A01JVDEpMCcGA1UECwwgSW5zZWN1cmUgUEtJTklUIEtlcmJlcm9zIHRlc3QgQ0Ex
+MzAxBgNVBAMMKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVy
+d2lzZTAeFw0yNDAyMTUwNDU5MDdaFw0zNTAxMjgwNDU5MDdaMEoxCzAJBgNVBAYT
+AlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNP
+TTENMAsGA1UEAwwEdXNlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJv9Sbc2QSbHWnZjk55JfeOdPGUsmKOcT/N7C0/0mOQq4tUCmha7ntpBoIJdUBDh
+MQayG3QHruQX7aogtOx8hoLoLUaNKgxzEZ0OLbDRMc2M+vTDpBROITGI1KPvQtth
+lS4ocqKvqBCze66N9LufzAju61CyKdB3pCykPrgDVVScfsZ1t2zCbK0SF2cfZAdI
+yCLoGLeQ95/NL3SIx0CX9gU47AVmBkSQ+LExJRhbUSIg+puKbqJ0XVILR1B2ezgi
+k2ObFND0hsRUS4v8pKnIDz0HXR2AneTESY+atjbzzelGA2zH86p4tLg0PanQ4x4+
+gpkQhzSr5Cmi3QX4XahSrmUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAau8fw4h1
+hp4/gp7l+AXvq+9E/a2y2Np+H8BmlRIg8ZLyKjRR6iPjcUwFWUteSSBsFzcc+/5V
+/Qs9gAW4nRIb9zY/sPO3KMAjJGKaP3u8xWkrfVZzaqPkfOWa5RDkh9AtvpN/fVLH
+dC+hC1xlXtjJ/YugJD6OA66sxdyTjR/v++0mqaTQyTI29HqtTc9LUcpbC1OYzxS3
+8vlZZgieRU0UlBvpsR0AqCaTZPgcrIvJ0EVIk6XzgOWJAptAe3tFEVrHtZJAQG04
+TI7NN/zw17O9Sn8NVEB4RSw6CFZeEVBBfCZL99HveEd8WPU0zgYceuVl/UCpQFNi
+Av6/+n+/6KwHXg==
 -----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/kdc.pem b/src/tests/pkinit-certs/kdc.pem
index e46afc177..4f7785854 100644
--- a/src/tests/pkinit-certs/kdc.pem
+++ b/src/tests/pkinit-certs/kdc.pem
@@ -3,27 +3,27 @@ MIIE4TCCA8mgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
 FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
 A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
 dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMFoXDTMyMDkyMDIxMTEzMFowSTELMAkG
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owSTELMAkG
 A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
 U1QuQ09NMQwwCgYDVQQDDANLREMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQDPpVeYmlWrbNMgRTeBQXum6L5aDXt3dBfajLoSqpRAr+nBa2u+YEhphyc+
-rRkyvMyE1O7J4uNvWs02QvSEJ1Lf9pVvHVs6WQ9U+VbdQ2L2Balc44TX83hAyvPI
-oBDX82l/3GNj++mqya9HHsBmmrs2rsfIXmFtQowcVppOpFquGg/uY4IHIbwXjhhB
-NjZFdzD217rfH7vtzc7riBu2dIpcEL/ilL0PEEG/VQsHbA4fxEbEOJaAvT+I7blg
-iYpCBO/BsQ3DjKAtX7SbVv5gQktogh4qV66dgQwyTMh8WYx6ZdFaA0e5KFhrQ97K
-LBMFJF1b1iLirON9odnV0PrvB2gbAgMBAAGjggFzMIIBbzAdBgNVHQ4EFgQU9Bel
-+9UEX7Q4knjUmN25LN5ytCMwgdQGA1UdIwSBzDCByYAU9Bel+9UEX7Q4knjUmN25
-LN5ytCOhga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNl
+AoIBAQCb/Um3NkEmx1p2Y5OeSX3jnTxlLJijnE/zewtP9JjkKuLVApoWu57aQaCC
+XVAQ4TEGsht0B67kF+2qILTsfIaC6C1GjSoMcxGdDi2w0THNjPr0w6QUTiExiNSj
+70LbYZUuKHKir6gQs3uujfS7n8wI7utQsinQd6QspD64A1VUnH7GdbdswmytEhdn
+H2QHSMgi6Bi3kPefzS90iMdAl/YFOOwFZgZEkPixMSUYW1EiIPqbim6idF1SC0dQ
+dns4IpNjmxTQ9IbEVEuL/KSpyA89B10dgJ3kxEmPmrY2883pRgNsx/OqeLS4ND2p
+0OMePoKZEIc0q+Qpot0F+F2oUq5lAgMBAAGjggFzMIIBbzAdBgNVHQ4EFgQUkj/6
+c5Xl+c1XGfYaSORhtnkPqaowgdQGA1UdIwSBzDCByYAUkj/6c5Xl+c1XGfYaSORh
+tnkPqaqhga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNl
 dHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwg
 SW5zZWN1cmUgUEtJTklUIEtlcmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5p
 dCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZYIBATALBgNVHQ8E
 BAMCA+gwDAYDVR0TAQH/BAIwADBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgDRsL
 S1JCVEVTVC5DT02hIDAeoAMCAQKhFzAVGwZrcmJ0Z3QbC0tSQlRFU1QuQ09NMBIG
-A1UdJQQLMAkGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggEBAJZd7v5ZOMs8Y3ht
-Kmtql8rKs0Jee73gVHYw3LXxJfHjIiNGdexxuWJ6Hy9gFnfwSco+15HP3MxMBkau
-TKo3i1+Kwf+lc7gIZ0g/CEnYOx2smHGd9yGudWypunYLjGWfH/2M8/Wu1gZDTxQ1
-pNMQZ2pPLL/C6c6vYpVQJ5cA0RSh/SC5IbOESUpZaFFMYxF5TNz+28/lDr/rN41O
-miklos6cH5EkJyI0WUqJMk04HHjREl/9RTak8mo/eaqjUMTAOyweSwpaYRCddBOo
-y1ix9yH0fSBib1+WQ3MAHZHgbgVnu7V2GnB6qMNqRLHoGa03x+5Q1X0QuKxP6iYo
-9tiGt3k=
+A1UdJQQLMAkGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggEBAHGR7TUjyGt7IbqD
+MW/MfOkLtvpv1f3MhbRSmYDweGKejh2xQIONC/BlaBA2RWmhJIYTdc8wPRlcC76D
+2HLhBmGyOSy+ZTX/txGhtXm+xzNuhLF95VKDd2Z+06CMe1CptH1fvnf5YaZsUgv4
+nXmRN2i4WWrVHoWsAFCcEM6PqT9j/2485DbjtmoS7nVNvO0UKJs2vGgZYuxgYQsl
+S387YJnSbC3/VjTHGBh+R7oRZ0cBvpviWyp5Xak0kNcWAUSu3Oa1FRYDz6Cw/r7/
+wrTWxMA9W3Ygzeh+JFpYZkj5BNrwFem8UxrM/g2ZvXVS81dKGfA5spEZ/cEsAkU1
+8mWgcJY=
 -----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/make-certs.sh b/src/tests/pkinit-certs/make-certs.sh
index 5284f4259..9fb3e4141 100755
--- a/src/tests/pkinit-certs/make-certs.sh
+++ b/src/tests/pkinit-certs/make-certs.sh
@@ -116,17 +116,21 @@ extendedKeyUsage = $CLIENT_EKU_LIST
 [exts_none]
 EOF
 
-# Generate a private key.
+# Generate an RSA private key and a password-protected PEM file for it..
 openssl genrsa $KEYSIZE > privkey.pem
 openssl rsa -in privkey.pem -out privkey-enc.pem -des3 -passout pass:encrypted
 
+# Generate an EC private key.
+openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 > eckey.pem
+
 # Generate a "CA" certificate.
 SUBJECT=ca openssl req -config openssl.cnf -new -x509 -extensions exts_ca \
     -set_serial 1 -days $DAYS -key privkey.pem -out ca.pem
 
 serial=2
 gen_cert() {
-    SUBJECT=$1 openssl req -config openssl.cnf -new -key privkey.pem -out csr
+    keyfile=${4-privkey.pem}
+    SUBJECT=$1 openssl req -config openssl.cnf -new -key $keyfile -out csr
     SUBJECT=$1 openssl x509 -extfile openssl.cnf -extensions $2 \
            -set_serial $serial -days $DAYS -req -CA ca.pem -CAkey privkey.pem \
            -in csr -out $3
@@ -152,6 +156,9 @@ gen_cert user exts_client user.pem
 gen_pkcs12 user.pem user.p12
 gen_pkcs12 user.pem user-enc.p12 encrypted
 
+# Generate an EC client certificate.
+gen_cert user exts_client ecuser.pem eckey.pem
+
 # Generate a client certificate and PKCS#12 bundle with a UPN SAN.
 gen_cert user exts_upn_client user-upn.pem
 gen_pkcs12 user-upn.pem user-upn.p12
diff --git a/src/tests/pkinit-certs/privkey-enc.pem b/src/tests/pkinit-certs/privkey-enc.pem
index 29d2f3d38..fd36246ed 100644
--- a/src/tests/pkinit-certs/privkey-enc.pem
+++ b/src/tests/pkinit-certs/privkey-enc.pem
@@ -1,30 +1,30 @@
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,5FFF1E71BFFB65E3
-
-p89x5YEL+Mb6IPZXEkkr0KC4Wj+JtgE3VKdTT0wEcRD74QVv+dbbZt62WgmpJtId
-ph0Ial2z5Mws8L/aTkPdW2H/bEroApLu4TfUV+w67KcWgrc8gOg73d6gEObqx8li
-qGbs7FC1cI1WfDfnNOnCbD66e5+bTI8fDuchaieNRqzROd9RHhmlBHgylTmf55us
-laGuwLq2cZk/+Xz0M8PPx07uauGkAK0fyfifn/JR3PsGsE9s334osVQMjbjyT0VE
-rm8HGm3PvZHHDUnkOh7AGKyEtsIa5fJAULUjugp2lQJqOigC4HVn8a33xfLI0F1+
-2nH9MZ+Ap1rtI1cJX8CDn/Ij9oFt01scLxynYekYej11zFiR6qHC0sspxu0Yi8l0
-puBPXCI0GzyF9I53ukjGeibTtssz5yw1r+2oVasR4bvfXczPjqTQCBsPSUayNNhw
-RgT7k4QTY2OlrK/5XdILBzBlsvfndXgGOwEDw4YE7PMzMmz69vPMK7CfedUqtuXq
-bGBks58tzeOa4NSfVDOuFLI+LMkoYWMSjPGD/I0trX41xCU+O6PZOnDyt5ZWl1Tm
-klJpsB7rUcwsP8d4w4QGhyyV6Mo2MTlnTILr4CwwvmDMBch3yzwbfKdeywsFQh0S
-NMrG3aYNO7csRRTD6aGvYcBCbavWq7Ujsb/fV7SOIS26f4VEqewvOFlFEXm66zaz
-GJ0IcjtNHYNIIIW4690djxPqlGgbIZTblBSBlT+iOW5HrhXvrLeMmwAPxInU5dK+
-ypk2MGc4SzemkDi8H9jDW3dwbgcvVD9wn0glhVLQKWvP6F73UUdVEXMCZ+960xnR
-gxeEwDdIpzXNadWdON1kRbqI2KesRY/XQErGHDOvf2gNSM9V2gPz+5humvcu3mXY
-r4537On4+IdzetEVtI7D0slgojs+jN8waigpkLFB5RVl8PnzblMuWOkHNA86rrp+
-h6wNqv9kHLgPjpAyB1l/7w4VqXLXeC4PdaGc2fcpdNWOncUnHROmDmYvdTocqhIF
-bAsEFV7QZoTgDB7J6vLsmbtfawtHMSb81V/wTJWRrtY/gJCrkJXR2pTYAZlPX6vK
-aK7K2NuhJFMnrQD+kxsrloSEyfsZmHtk0mAVXJw4wSxlH3eGQ+Jphb/M2wtsnWV1
-w0fehxL2Vd5SyBBctAGhUirhRngbOO/E8IioymrziQ88vJZs2DxvbuNG4WKTuTwj
-CIggXohCNKdqrwL2HAynm2FVEWhbKrQwe4kjZc64WjccR4cy9vv+dxFfrKl+vZ1o
-Wvb0WXND7fiSBrPo7OfaYM5HjrcvIRP1AtMuArhuQYVARmawUG0l7dFLN97Rh9M+
-Ud9vBIfQYlubnTGVVm/5xrUh2isQbp2vrZLfMrUNXMQm0vSxKgGkAxqNUuklJC06
-LvCtEWMYXiBmB1zP4khwCHmHB+/E1gHBAutCzhpPu86ayEtNHBHIFkqKvZSg/UuZ
-+ygDdTJV00I2neIdeQcyG+vPg6huIDIHpG5u6eQn5sLqVkhr+apeNcskMWpdkpFS
-Lo62KUZDR3yB83ne63c3IGex0hWhVojJOAxykpGp6OD9uFn6Xn7x2Q==
------END RSA PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIBw7aG13XYxwCAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECPWyEPoKz4WhBIIEyKHdx+pkDxax
+dCCUZHsJ54boZxh+7f7xmO9Rjm+6+3cE+WCjPsiGHPUDtOXLxWwcrG0RAmA1GmrE
+yZbclwEMF8LcWQ3EUDMCJXBs7CEtA4XDH+EW1KsZwP+cA53ZFFikGj3sW6Ix5GLi
+Df311Eumhp3GABU57siNn+tMZJAorInth5lXBJFQoE3KJbBrSN9iQKZTOpgr4G3B
+G+qzBwrUKnZrGIp42t8op4VkB8sA6xoHh/huJB5pNygt9OZUQ+xdxvNQq+5/kJ2I
+mP/JRPSuN4GtnNA4fBB6tPv8t0L8hActkWlQ1rSJwWnWge3t4r5/3FBcAbl+zq3k
+t8A0LWgjsiQRmlKRN7GrzorOUKFv+7YAq6rc1Ek79qitUgEiFkwZZySt5+yPstMW
+vpaq2V0yDHf5Ds9uXffprhSAjnfXdT4NTg5eMeH65OEedUpVVzHauoGfFkDGaq8L
+8XgWPZPaz6GQFpU5SGk8FZn0OLLJHnHQDYo+ViL2XSuuqY8Jd7fmpzqVoHOU8k9Q
+/ONKW+E6uvkpNH6NbknceA/ip1bcdfwA/uRBckXjCc5uR0oB18M4UQPuKlcGev39
+mcdlvzQJxl2EWbB8ULazzuzOVfCAEwKc96qOkDAY94CB69f/KhBOd2QqHzdxrQ+3
++K+YduhbfP49Vxaq4NIklS/kSSv4GEBHzEwtFxX4oqN4Er+UkBSB423nvlkSLd1g
+tR4M30lJyzmHtOEpSOZYLakviz36ZOCV/DsxrfziNG/0RB/mPLm/B5L+StqjJrTY
+Pjo3QHKb+6ShhTi+jZ8tqXa68+TZO3Q7eTgqrcn8mq9jfama0KQF/13kmUsrFXTS
+wk/nbSP10z+MhO68z7o3j+Q0Co/cXkQke4slvc3DqLNvpQdDMPLKQVxtkPBq5czr
+dbk5K2GYFLNWO5Tv2RgBGomznoAGSolz5ozIqxffVHAK4NGfhihgLO/6GujDANVz
+EX/2/IacRg0L0x7//O/GHomiFvWYnDbHhRNicERe/ji1TCxJ5glqntFjOXDumwi6
+f+mQWNWlQWtKq0IOnlHrBB+vqykAj+e+FROqJjuNI6hu4CNnrBK3Hf+NY+rXdn7l
+iCTD3ojdufqo0JDZe8dXea+B7Zu7WNAxnpW8D018DJxR2hoBvT4Po1CBaHLfxAkT
+ZGeXMjp1vZ348xBSppFpIpYjFRQBeBgSezzA66o3YIcDeHu2bTzg73DiUXNgV3RG
+OyJHmsOmN9Gax/Cx4z6/Ff7seisXpIMRU9TDrRCFKAcPHXAl3R4L6guK0I5OGwz3
+GSMxsx3PGitj0x+1ynW/Tf+EJQD33ognc+kuQfNL0XW2tNJoibZIs1WgdbDwD9RD
+X7rbb9GfSJlQUnBFG/EKU7SGmFZUVMz7we8vckZ1PfeIKfH7OWrZ2i1WxIF2WO1K
+BX4TXp0KKt+aCwf1GInQ/6aYgh5g8W2iKuz2HJeZIN+ohciNmpOynsFmHGXdbvnO
+Kw+msZEQb5AvhXf4ToiSwZLSwq3qAILN8fOQQ9ta1DjJuUtITpe6ys9xhlnriUkm
+KrY50GkimLdD6XszC2uNulAuh3o0nZplqxC9IOLh+uasEU/+xqtwTaaYBljTpH2C
+8FPAEFFUVy6lsngJEQvdjw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/src/tests/pkinit-certs/privkey.pem b/src/tests/pkinit-certs/privkey.pem
index 007b6275d..2a25dc19c 100644
--- a/src/tests/pkinit-certs/privkey.pem
+++ b/src/tests/pkinit-certs/privkey.pem
@@ -1,27 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEoAIBAAKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtr
-vmBIaYcnPq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE
-1/N4QMrzyKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOC
-ByG8F44YQTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiW
-gL0/iO25YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNH
-uShYa0PeyiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABAoIBAEpnKYMR0h6xyNjo
-VGIpT6BYB1UHPbVo0N9Ly6TCoIqpPe5DioDVyTye5A4OQlgu1G3ISqPme6478ApA
-ZZMw7/42QgdlknnOzbKaAWkZK02Sa8RP9hrXL8CvuDisOjzXCHd7RdXevzSmPfsS
-5sgdK3YFnKqMPwbCcKf61CHXvHJjWGuTIHIRh8P7gJelA4ahO0kYQ8aRXv3ldquO
-ukSI5gyk9CN+aAHqt25kEmt9oOgk+8kfKpnk+5gkOCY2YOFDDckD7nL1VIIrDxwG
-SmU598qjVwycDairWUY8uSuPCOLgbvDM9N8cERDMsyNQL63GE8ZZyHZsJ3Pbwdfs
-JVHh5ekCgYEA/CwhaT9D0WQ49GQdeI7aqazHEYDmqPdE2/qbmr67tPMZzX8AAk9j
-r4aMT+oIdtIMPdoQNNcBP6NYZLlAoMbLoAzHmWJnF5/YWLnS2Wg9OuXUOBn3jk1l
-SWelJfAKGeBld5fpSLTdHjRAwJrNCX+mc0IZIiEw2IvGUPgKGX08bX8CgYEA0swx
-xCDgvfoaKueInw/rUIcKxrSxK3pDhaR01Dg2pwSo7Vj9W01zf33qe+mjma6+U2SB
-fk+/O2VXDuEOmVDLwvp6PkmUeRE5PyH7urTMEjy5ELNGiZd9zHoG/zJnRgPwTjuW
-yguvjVGJwI1IvmODuA7Xc7iHFlvGNuxXZjPkS2UCgYA0nFxoIdvbTsaXLl/7rAow
-xixOGY+GBvil0HYwZcSxrtpeRjXRRZDtqOuTLKeRaqdFLD6fV5AaH9EsSn4STQdk
-n+XwuVf61M2FTVeRJi9IH3UUM06zsLAGDYqmDJt+5JMmzVnNYnaTe6FazbEjXy9x
-8oNd3IDdXOQGNomc4cT+rwKBgBbABOr25Wp7cJGK1XrdO/c/69DQNYLMujbVLeqt
-enCCFz0uaoGNFVcAHutqpsZyToYvha49KxVc9Y1cirfPOX58i+7nAAgk7Lm8kC9x
-Tcj2Fr8PqiA1YlVMIi8uoGi1Ch1XXwnFQxgMYcKPPPeXQ+L8bxJFKwcltnm8/h3A
-ofXlAn9AW6fYZLSzOfNQTMnuukhuAtZcEW9NlJHbej305zK89J66S8wroQs5iOla
-5GG+S4YaZh5sVGw+mnS+FCw7cQCUk40kXwX3yTrxlX1qGSCFCQnFdJow+5NVg4D+
-dzDKzniH71OZZFxTqiiz76XxiaW/rS1uOfP/WSVR9NBLpV5n
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCb/Um3NkEmx1p2
+Y5OeSX3jnTxlLJijnE/zewtP9JjkKuLVApoWu57aQaCCXVAQ4TEGsht0B67kF+2q
+ILTsfIaC6C1GjSoMcxGdDi2w0THNjPr0w6QUTiExiNSj70LbYZUuKHKir6gQs3uu
+jfS7n8wI7utQsinQd6QspD64A1VUnH7GdbdswmytEhdnH2QHSMgi6Bi3kPefzS90
+iMdAl/YFOOwFZgZEkPixMSUYW1EiIPqbim6idF1SC0dQdns4IpNjmxTQ9IbEVEuL
+/KSpyA89B10dgJ3kxEmPmrY2883pRgNsx/OqeLS4ND2p0OMePoKZEIc0q+Qpot0F
++F2oUq5lAgMBAAECggEADwzB9vY6FPa46KE01dm7VqGN+SjzVR24rQIbFkzAD4t/
+tRN6MGVLrz0TsmA0YFyJsV6vvWMcYY9Zc8eSDRr6k1i5PYxTGT5k3aVHjT6xsmY+
+tCzIANmE5FWSRnrIFYh1ry1h2gZejbXzYeT6TrvdIKOEepWl6SIR6eiy0Ggp7G7C
+SjlpT96ZtdE2RnlvcxcACtwhe3vPbkLmTCOEqeZ6LHCHIHiK4KdJgJ08OjU7Kgsr
++vmnwTJsH5s0b5IIznfWajO4JNOpqjzFDjDctGYBwp5xF4zu3u4bKe9aleM0q/jl
+ZkibxLsFAh3Xkh89nxr3E6oBLm0F8r8M7PK5wpMShQKBgQDAipf6T6XUY+ugkKw+
+301LyoAch6WV9oT6uOJsAttmcUpUr6NXhRT3OM4oqyYsAc5JW2wbz+n6lED3j6Ez
+QEKSIFrYpjrYr9D7hqvISI9JT0PhVSPXECfifEyIR9xmLvV9WQq7NRCJMi26X9ab
+Grqpw1HNlPA/rdcc/dY0p25DlwKBgQDPZqxSnwnTa6X+r0UdR8l6kc9VuESotpbE
+0ziF222bpXmZ2GKiEU1buFORHih/e3yDvKvq+p2apyUKnEEVQg/TL8/Jzya7fEOI
+lTXcNQ/f78ef+nwEAxdRVQkWXFWHvvKUHm1rGCIY7zeOLnQ9JjBQkgG8zhUamAP1
+owLBBTstYwKBgQC+yNX9Du0HvpbdfF1g0025OwekvXiDV0m/UnHxiwcxxDJeJceZ
+0mHK8nu9apGha4ynvbIrAOMdC8gwRh76NMOCHhNGt7h5vAU9Jt2S0OtCPgvJ/N5N
+nVGYJ4iCRYqLqh5QvWlXxSYEfDc5hPuWp26tBsBJEDrbLnuH27JkbD9jMwKBgQCM
+f1VFMw+I9WehvEHpr/PA4H2/5/A7ClXgR+YGZ7s8sUBLA9btSyNIevnBWNi+Y3za
+ETm1GMkjNw9UvL0qFXJ68eylHXtzjp6BK/MslZWHcfudWCYi4aUuJ5jcWPhn2Oaj
+iGk/Hz4Z/hN4cee0dOZN7lrW+BQ7y7cC88at00lfWQKBgQC7YeW02aUPw9jMJh1x
+lDfBh+E5sdRwRQIvh3BuyTd+m/LI+3b9RSy+LIL2KFJucwKm9zR9fy33tHF2S5En
+Q+inhyXfOEygal5Rzxe3Pfx+pGZbzr6IXkhquHtjuFBwJJCrSeR66V2xDmzJfCj4
+TY+CzwOJ/EltH4ZjPwEmE0S7+w==
+-----END PRIVATE KEY-----
diff --git a/src/tests/pkinit-certs/user-enc.p12 b/src/tests/pkinit-certs/user-enc.p12
index 1cc3aa3da..69780bf82 100644
Binary files a/src/tests/pkinit-certs/user-enc.p12 and b/src/tests/pkinit-certs/user-enc.p12 differ
diff --git a/src/tests/pkinit-certs/user-upn.p12 b/src/tests/pkinit-certs/user-upn.p12
index bf47384a8..e91cc8a0c 100644
Binary files a/src/tests/pkinit-certs/user-upn.p12 and b/src/tests/pkinit-certs/user-upn.p12 differ
diff --git a/src/tests/pkinit-certs/user-upn.pem b/src/tests/pkinit-certs/user-upn.pem
index 14a11831d..7dcd716cb 100644
--- a/src/tests/pkinit-certs/user-upn.pem
+++ b/src/tests/pkinit-certs/user-upn.pem
@@ -1,28 +1,28 @@
 -----BEGIN CERTIFICATE-----
-MIIExTCCA62gAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+MIIExTCCA62gAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
 FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
 A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
 dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owSjELMAkG
 A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
 U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn
-Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz
-yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y
-QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25
-YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe
-yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFPQX
-pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd
-uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+CgKCAQEAm/1JtzZBJsdadmOTnkl94508ZSyYo5xP83sLT/SY5Cri1QKaFrue2kGg
+gl1QEOExBrIbdAeu5BftqiC07HyGgugtRo0qDHMRnQ4tsNExzYz69MOkFE4hMYjU
+o+9C22GVLihyoq+oELN7ro30u5/MCO7rULIp0HekLKQ+uANVVJx+xnW3bMJsrRIX
+Zx9kB0jIIugYt5D3n80vdIjHQJf2BTjsBWYGRJD4sTElGFtRIiD6m4puonRdUgtH
+UHZ7OCKTY5sU0PSGxFRLi/ykqcgPPQddHYCd5MRJj5q2NvPN6UYDbMfzqni0uDQ9
+qdDjHj6CmRCHNKvkKaLdBfhdqFKuZQIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFJI/
++nOV5fnNVxn2GkjkYbZ5D6mqMIHUBgNVHSMEgcwwgcmAFJI/+nOV5fnNVxn2Gkjk
+YbZ5D6mqoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
 ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
 IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
 aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
 BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM
 EHVzZXJAa3JidGVzdC5jb20wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B
-AQsFAAOCAQEAYTW8tzURX2s8vuDawXEJt2as5q2MnvhUmG0YPIvK4n2fODkMW/I9
-XENFhK8wwQJNdzvBUwXUXzEGjFcGPs672ZVzykRb7sAfGlNu1f15z0KrjyUj82oz
-/gWoLwdYwZnO8jqtKjGtnLi2MeWjVCoiUW5ypUGwtEdcyZUG0PeRUrdrZu5cm+iZ
-1B1exR4lepR1iSAPYTNhp5VF6T8BSLf2BO2IKTgFnF4Xx1vyZZTsY10mruZ8S1ZR
-XiajBVdHkN1BpWWyFKt1BCt0dpRx9W7CihC3Ln9fBCsY8QA969EjRhszG2i09Xxw
-0M6/UgIQRU6hy7QTlcmehDKY0zvVJ2/RLw==
+AQsFAAOCAQEAbe5/xDlFplE/h6BSqXSftjyiPgRlmPPkuTwiKHfmHYHv+KXHBDFY
+wuGDu4Tdh/qisskXJGoKYfRsOox6AW3ZTcklkjvVw0V73nPo+98USWYTzKq7NriF
+rJ9skYALu/Yv6q8iEoziOyDG55LppWne5KH0Of5ctikZVthxDnjm/saSR1lNa+8A
+gB6x9uid73qw+seg1/DoOdb+uHGnKBeSUrJC9vtdfodYdeatNFDDNoxqjGPajDNT
+TGI2ace2yZAgD/ic1MzI/s2eTHfzzO+puJIPzLScdy80RYMeILQs9g+x5NhOUuMz
+YMVFE0PAQLshVggtJ9l8fmHmrrJXP9BAWw==
 -----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/user-upn2.p12 b/src/tests/pkinit-certs/user-upn2.p12
index 69ca648aa..e29ff5412 100644
Binary files a/src/tests/pkinit-certs/user-upn2.p12 and b/src/tests/pkinit-certs/user-upn2.p12 differ
diff --git a/src/tests/pkinit-certs/user-upn2.pem b/src/tests/pkinit-certs/user-upn2.pem
index baef41a5a..b2d8c1dd8 100644
--- a/src/tests/pkinit-certs/user-upn2.pem
+++ b/src/tests/pkinit-certs/user-upn2.pem
@@ -1,28 +1,28 @@
 -----BEGIN CERTIFICATE-----
-MIIEuTCCA6GgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+MIIEuTCCA6GgAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
 FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
 A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
 dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owSjELMAkG
 A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
 U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn
-Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz
-yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y
-QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25
-YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe
-yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBSjCCAUYwHQYDVR0OBBYEFPQX
-pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd
-uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+CgKCAQEAm/1JtzZBJsdadmOTnkl94508ZSyYo5xP83sLT/SY5Cri1QKaFrue2kGg
+gl1QEOExBrIbdAeu5BftqiC07HyGgugtRo0qDHMRnQ4tsNExzYz69MOkFE4hMYjU
+o+9C22GVLihyoq+oELN7ro30u5/MCO7rULIp0HekLKQ+uANVVJx+xnW3bMJsrRIX
+Zx9kB0jIIugYt5D3n80vdIjHQJf2BTjsBWYGRJD4sTElGFtRIiD6m4puonRdUgtH
+UHZ7OCKTY5sU0PSGxFRLi/ykqcgPPQddHYCd5MRJj5q2NvPN6UYDbMfzqni0uDQ9
+qdDjHj6CmRCHNKvkKaLdBfhdqFKuZQIDAQABo4IBSjCCAUYwHQYDVR0OBBYEFJI/
++nOV5fnNVxn2GkjkYbZ5D6mqMIHUBgNVHSMEgcwwgcmAFJI/+nOV5fnNVxn2Gkjk
+YbZ5D6mqoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
 ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
 IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
 aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
 BAQDAgPoMAwGA1UdEwEB/wQCMAAwHwYDVR0RBBgwFqAUBgorBgEEAYI3FAIDoAYM
-BHVzZXIwEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0BAQsFAAOCAQEAAsGC
-LvikD/nW3eOym4f/uuKBscOGSByP9/HoP8QwvnLYU00i5n+zXSTQctotHIifsRc4
-xHLO8xemJp7rm0h/27C1Wo5AVxJ0cmnDKQf8Ast+QXsz9ZeaeKLa5D8sDOfnZXJB
-aMTb8ChjyZz+KLjXV0VbaVkY95mfqsOoJQcl9wHhNdDOygnSucvA5Svlrbo2rlKt
-75OJZJJWrZxuaBuuSYNpCKyyg61t69hPoDKDQZ8QJZHGugWqQ2swYe9dZpUYy5xV
-CGTLCAk9ZOn8hTCC6xbNaJFjflIjcjpwabw0r986/9GeAF6KqSNbMXKaY4LLuk/8
-5FH9S8/3F56ZCNxbZQ==
+BHVzZXIwEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0BAQsFAAOCAQEAFN2R
+gVMM5HNoXuwBPcpNsP5AVSoQRTAv6UUxAjTPLGH5mE6LGW8/JxM0R5x0PdVyU3u7
+zq4qa10XdGJpSt94cD6m7R61Sw6ru9PBtHmB0oUfkWRa2+SJpjmcwyc86W0XRBhr
+OhD0QGOnF1hGyTYzPViGxRZFVMiqXsWuAJ4i6uTyyPeeN+UuehQ3SsVEA1csrKMy
+dNT7FKQBvUTBnSZ9rxphGBrw/NZQyG74KxG5W3Nsnq89VK6+ESJcsUOT55WrHRwE
+CwKoeX+otyj8ptOwKaaje0DZnSXTXqEag4G4PgH4ovd+ehad0JaE4jtQTm+Vy15W
+cwHSMGSA+Kq1Hsqhhw==
 -----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/user-upn3.p12 b/src/tests/pkinit-certs/user-upn3.p12
index 9aabc3a89..93a30422b 100644
Binary files a/src/tests/pkinit-certs/user-upn3.p12 and b/src/tests/pkinit-certs/user-upn3.p12 differ
diff --git a/src/tests/pkinit-certs/user-upn3.pem b/src/tests/pkinit-certs/user-upn3.pem
index 000d567d8..618f00526 100644
--- a/src/tests/pkinit-certs/user-upn3.pem
+++ b/src/tests/pkinit-certs/user-upn3.pem
@@ -1,28 +1,28 @@
 -----BEGIN CERTIFICATE-----
-MIIExTCCA62gAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
+MIIExTCCA62gAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
 FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
 A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
 dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owSjELMAkG
 A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
 U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn
-Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz
-yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y
-QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25
-YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe
-yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFPQX
-pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd
-uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+CgKCAQEAm/1JtzZBJsdadmOTnkl94508ZSyYo5xP83sLT/SY5Cri1QKaFrue2kGg
+gl1QEOExBrIbdAeu5BftqiC07HyGgugtRo0qDHMRnQ4tsNExzYz69MOkFE4hMYjU
+o+9C22GVLihyoq+oELN7ro30u5/MCO7rULIp0HekLKQ+uANVVJx+xnW3bMJsrRIX
+Zx9kB0jIIugYt5D3n80vdIjHQJf2BTjsBWYGRJD4sTElGFtRIiD6m4puonRdUgtH
+UHZ7OCKTY5sU0PSGxFRLi/ykqcgPPQddHYCd5MRJj5q2NvPN6UYDbMfzqni0uDQ9
+qdDjHj6CmRCHNKvkKaLdBfhdqFKuZQIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFJI/
++nOV5fnNVxn2GkjkYbZ5D6mqMIHUBgNVHSMEgcwwgcmAFJI/+nOV5fnNVxn2Gkjk
+YbZ5D6mqoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
 ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
 IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
 aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
 BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM
 EHVzZXJAS1JCVEVTVC5DT00wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B
-AQsFAAOCAQEApwXjFJ86RLM4MzbScqk0JGqm+jzaFZ6h5oyt0rlaxdhOl7kqOmIE
-sLhXtvZm75roA+UULZHumB6xg3Y0p7cc6VBAYYycWoNkhWXZMdQ8Q33vMos5cwLY
-kXjl4oTDK53goh8IlriRMV7Tv/QpJ8wh+7iqQn3lak0Tv51JexYGwp5sJREYm8q5
-rr3ChlgH7SWF8mhbu2EEiipm0whEqA4tlNKGBsTQBslnm8sK0VfVDcmLOGbMNjRs
-r+Hkd8yVvhIJ9M+WAp/OeF2vUzPBJtAfIaJBxcZmKtNI5Jk8cK/vScJZboa0qAAz
-2Y1uC9rP830mpOe0juhV2mMPron0hi1HaA==
+AQsFAAOCAQEASLN4+MiZUQwBzQ3ezt1B8Zx8jHL7a16s1H5v1J2Dwne/pM/risjg
+ZAlv65IlKEp2E6cqcmCPajlZ967vJr1qC+OSV2AZuL8HZlg+ISacoII9T97X9/UJ
+AJfOWBN6y0DQ7s6OLSunf0+mAw+LKmFoIQeO5+DvU4chEYkcs6NbbAos/He1Wgq/
+RTz9J3EhGuoDVgqq/avrTsgW9HyrHsG+Y/6n4cX2lq+VV7h8fG91hC073Rz9QMFY
+q/pBqFqIE/FrgA4YbpOrSx6m+eOyFSAWTLtmlJmROiNYo4ZuGmBtrDntet+YK75A
+8Rsfbapjn4SKJzgJseVgUbEEMOFcugQBfQ==
 -----END CERTIFICATE-----
diff --git a/src/tests/pkinit-certs/user.p12 b/src/tests/pkinit-certs/user.p12
index e55201102..0f854cae6 100644
Binary files a/src/tests/pkinit-certs/user.p12 and b/src/tests/pkinit-certs/user.p12 differ
diff --git a/src/tests/pkinit-certs/user.pem b/src/tests/pkinit-certs/user.pem
index 182ea599a..7493de52c 100644
--- a/src/tests/pkinit-certs/user.pem
+++ b/src/tests/pkinit-certs/user.pem
@@ -3,26 +3,26 @@ MIIE0zCCA7ugAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx
 FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG
 A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz
 dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug
-b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMFoXDTMyMDkyMDIxMTEzMFowSjELMAkG
+b3RoZXJ3aXNlMB4XDTI0MDIxNTA0NTkwN1oXDTM1MDEyODA0NTkwN1owSjELMAkG
 A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF
 U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn
-Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz
-yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y
-QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25
-YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe
-yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBZDCCAWAwHQYDVR0OBBYEFPQX
-pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd
-uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
+CgKCAQEAm/1JtzZBJsdadmOTnkl94508ZSyYo5xP83sLT/SY5Cri1QKaFrue2kGg
+gl1QEOExBrIbdAeu5BftqiC07HyGgugtRo0qDHMRnQ4tsNExzYz69MOkFE4hMYjU
+o+9C22GVLihyoq+oELN7ro30u5/MCO7rULIp0HekLKQ+uANVVJx+xnW3bMJsrRIX
+Zx9kB0jIIugYt5D3n80vdIjHQJf2BTjsBWYGRJD4sTElGFtRIiD6m4puonRdUgtH
+UHZ7OCKTY5sU0PSGxFRLi/ykqcgPPQddHYCd5MRJj5q2NvPN6UYDbMfzqni0uDQ9
+qdDjHj6CmRCHNKvkKaLdBfhdqFKuZQIDAQABo4IBZDCCAWAwHQYDVR0OBBYEFJI/
++nOV5fnNVxn2GkjkYbZ5D6mqMIHUBgNVHSMEgcwwgcmAFJI/+nOV5fnNVxn2Gkjk
+YbZ5D6mqoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz
 ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM
 IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu
 aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P
 BAQDAgPoMAwGA1UdEwEB/wQCMAAwOQYDVR0RBDIwMKAuBgYrBgEFAgKgJDAioA0b
 C0tSQlRFU1QuQ09NoREwD6ADAgEBoQgwBhsEdXNlcjASBgNVHSUECzAJBgcrBgEF
-AgMEMA0GCSqGSIb3DQEBCwUAA4IBAQAOBeCDK6Eg6Cu8TZ7xeAw2AbTpaW04nNSV
-Fmm0aIskMgLl2a5KEmalG7rnArRXv5IZVYFjJ6X0MzjOx+BgaGUCvN8jz1fuO3Hp
-iGhxPDzKjFMWJeY/z5bQRueSI6RCC8DzH8iPdlPUQ8ZhnukhY1Vt47wqraf197uT
-0XP21qQr1uRY+ZcLSBKZuKe9ZP3ijh57MOLvYDdAFxVp77JLznpk+oU18ujAtYgZ
-7naIGYtSQRkIi970jk82hSpc9B/KN8UcDuo+DQHWPQaDf39s30qoxooZBoue5ipp
-LQHuVaX5Hoi83cWbsVluce/JsW8GfbuC8+8CosAmzJly183f8++9
+AgMEMA0GCSqGSIb3DQEBCwUAA4IBAQBRWsxPb9miF9xf8rEIfVko0qBy8doEJsPE
+IVD9Jz/Ml/TBZRLbi1b94l15Fto/Z6XKf8jrnBs4krf6tU2D5PUZXZYZ6tr/2kkY
+IpmoOkEoQX8gtcZfaq2OJzsKHnAJT159EVydyYahHU66i4aNvho74oAafrVTyk8B
+PHCHFs0MUct8DoNwrbnfH0cjqEdVOmjjvBN0yA+RxOa543XnQqkSmCuIJKoD6pUa
+07rE372iERgIjDnzCogiEo9cCBBqDfgsbr0ah1QbWJTJvnsFuxT43tBNurRjNPoX
+Jj6xAzhQLCuvqtKtWlAUOHut18YbVGXVT+3tm7+C6iA44JvMl9m1
 -----END CERTIFICATE-----
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
index 443574642..91d4630a0 100755
--- a/src/tests/t_pkinit.py
+++ b/src/tests/t_pkinit.py
@@ -7,8 +7,10 @@ if not pkinit_enabled:
 
 # Construct a krb5.conf fragment configuring pkinit.
 user_pem = os.path.join(pkinit_certs, 'user.pem')
+ecuser_pem = os.path.join(pkinit_certs, 'ecuser.pem')
 privkey_pem = os.path.join(pkinit_certs, 'privkey.pem')
 privkey_enc_pem = os.path.join(pkinit_certs, 'privkey-enc.pem')
+privkey_ec_pem = os.path.join(pkinit_certs, 'eckey.pem')
 user_p12 = os.path.join(pkinit_certs, 'user.p12')
 user_enc_p12 = os.path.join(pkinit_certs, 'user-enc.p12')
 user_upn_p12 = os.path.join(pkinit_certs, 'user-upn.p12')
@@ -42,6 +44,7 @@ alias_kdc_conf = {'realms': {'$realm': {
 
 file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem)
 file_enc_identity = 'FILE:%s,%s' % (user_pem, privkey_enc_pem)
+ec_identity = 'FILE:%s,%s' % (ecuser_pem, privkey_ec_pem)
 dir_identity = 'DIR:%s' % path
 dir_enc_identity = 'DIR:%s' % path_enc
 dir_file_identity = 'FILE:%s,%s' % (os.path.join(path, 'user.crt'),
@@ -177,6 +180,11 @@ for g in ('4096', 'P-256', 'P-384', 'P-521'):
     realm.pkinit(realm.user_princ, expected_trace=('PKINIT using ' + g,),
                  env=group_env)
 
+# Test with an EC client cert.
+mark('EC client cert')
+realm.kinit(realm.user_princ,
+            flags=['-X', 'X509_user_identity=%s' % ec_identity])
+
 # Try using multiple configured pkinit_identities, to make sure we
 # fall back to the second one when the first one cannot be read.
 id_conf = {'realms': {'$realm': {'pkinit_identities': [file_identity + 'X',
@@ -446,4 +454,16 @@ realm.run(['./responder', '-X', p11_attr,
 realm.klist(realm.user_princ)
 realm.run([kvno, realm.host_princ])
 
+mark('PKCS11 identity, EC client cert')
+shutil.rmtree(softhsm2_tokens)
+os.mkdir(softhsm2_tokens)
+realm.run(tool_cmd + ['--init-token', '--label', 'user',
+                      '--so-pin', 'sopin', '--init-pin', '--pin', 'userpin'])
+realm.run(tool_cmd + ['-w', ecuser_pem, '-y', 'cert'])
+realm.run(tool_cmd + ['-w', privkey_ec_pem, '-y', 'privkey',
+                      '-l', '--pin', 'userpin'])
+realm.kinit(realm.user_princ, flags=['-X', p11_attr], password='userpin')
+realm.klist(realm.user_princ)
+realm.run([kvno, realm.host_princ])
+
 success('PKINIT tests')


More information about the cvs-krb5 mailing list