aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2024-02-21 15:29:02 -0500
committerGreg Hudson <ghudson@mit.edu>2024-03-18 21:05:44 -0400
commitf745c9a9bd6c0c73b944182173f1ac305d03dc3a (patch)
tree489707dc889ee1fa48b08ac17c8227f574be181c
parentbdcd6075bd4593c8f67722ce075c9519faec58b7 (diff)
downloadkrb5-f745c9a9bd6c0c73b944182173f1ac305d03dc3a.zip
krb5-f745c9a9bd6c0c73b944182173f1ac305d03dc3a.tar.gz
krb5-f745c9a9bd6c0c73b944182173f1ac305d03dc3a.tar.bz2
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)
-rw-r--r--src/plugins/preauth/pkinit/pkinit_crypto_openssl.c319
-rw-r--r--src/tests/pkinit-certs/ca.pem32
-rw-r--r--src/tests/pkinit-certs/eckey.pem5
-rw-r--r--src/tests/pkinit-certs/ecuser.pem24
-rw-r--r--src/tests/pkinit-certs/generic.p12bin2469 -> 2560 bytes
-rw-r--r--src/tests/pkinit-certs/generic.pem38
-rw-r--r--src/tests/pkinit-certs/kdc.pem32
-rwxr-xr-xsrc/tests/pkinit-certs/make-certs.sh11
-rw-r--r--src/tests/pkinit-certs/privkey-enc.pem60
-rw-r--r--src/tests/pkinit-certs/privkey.pem55
-rw-r--r--src/tests/pkinit-certs/user-enc.p12bin2829 -> 2920 bytes
-rw-r--r--src/tests/pkinit-certs/user-upn.p12bin2821 -> 2912 bytes
-rw-r--r--src/tests/pkinit-certs/user-upn.pem32
-rw-r--r--src/tests/pkinit-certs/user-upn2.p12bin2805 -> 2896 bytes
-rw-r--r--src/tests/pkinit-certs/user-upn2.pem34
-rw-r--r--src/tests/pkinit-certs/user-upn3.p12bin2821 -> 2912 bytes
-rw-r--r--src/tests/pkinit-certs/user-upn3.pem32
-rw-r--r--src/tests/pkinit-certs/user.p12bin2829 -> 2920 bytes
-rw-r--r--src/tests/pkinit-certs/user.pem30
-rwxr-xr-xsrc/tests/t_pkinit.py20
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 25796fd..18f1ffe 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 63d31c1..6c782bc 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 0000000..14c2efd
--- /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 0000000..585e53d
--- /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 35c2741..55a2481 100644
--- a/src/tests/pkinit-certs/generic.p12
+++ b/src/tests/pkinit-certs/generic.p12
Binary files differ
diff --git a/src/tests/pkinit-certs/generic.pem b/src/tests/pkinit-certs/generic.pem
index 55ebb3d..dde7f31 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 e46afc1..4f77858 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 5284f42..9fb3e41 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 29d2f3d..fd36246 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 007b627..2a25dc1 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 1cc3aa3..69780bf 100644
--- a/src/tests/pkinit-certs/user-enc.p12
+++ b/src/tests/pkinit-certs/user-enc.p12
Binary files differ
diff --git a/src/tests/pkinit-certs/user-upn.p12 b/src/tests/pkinit-certs/user-upn.p12
index bf47384..e91cc8a 100644
--- a/src/tests/pkinit-certs/user-upn.p12
+++ b/src/tests/pkinit-certs/user-upn.p12
Binary files differ
diff --git a/src/tests/pkinit-certs/user-upn.pem b/src/tests/pkinit-certs/user-upn.pem
index 14a1183..7dcd716 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 69ca648..e29ff54 100644
--- a/src/tests/pkinit-certs/user-upn2.p12
+++ b/src/tests/pkinit-certs/user-upn2.p12
Binary files differ
diff --git a/src/tests/pkinit-certs/user-upn2.pem b/src/tests/pkinit-certs/user-upn2.pem
index baef41a..b2d8c1d 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 9aabc3a..93a3042 100644
--- a/src/tests/pkinit-certs/user-upn3.p12
+++ b/src/tests/pkinit-certs/user-upn3.p12
Binary files differ
diff --git a/src/tests/pkinit-certs/user-upn3.pem b/src/tests/pkinit-certs/user-upn3.pem
index 000d567..618f005 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 e552011..0f854ca 100644
--- a/src/tests/pkinit-certs/user.p12
+++ b/src/tests/pkinit-certs/user.p12
Binary files differ
diff --git a/src/tests/pkinit-certs/user.pem b/src/tests/pkinit-certs/user.pem
index 182ea59..7493de5 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 4435746..91d4630 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')