2 * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
36 RCSID("$Id: pkinit.c 21684 2007-07-23 23:09:10Z lha $");
38 struct krb5_dh_moduli {
48 #include <heim_asn1.h>
49 #include <rfc2459_asn1.h>
51 #include <pkcs8_asn1.h>
52 #include <pkcs9_asn1.h>
53 #include <pkcs12_asn1.h>
54 #include <pkinit_asn1.h>
66 struct krb5_pk_identity {
67 hx509_context hx509ctx;
68 hx509_verify_ctx verify_ctx;
72 hx509_revoke_ctx revokectx;
79 struct krb5_pk_init_ctx_data {
80 struct krb5_pk_identity *id;
82 krb5_data *clientDHNonce;
83 struct krb5_dh_moduli **m;
86 unsigned int require_binding:1;
87 unsigned int require_eku:1;
88 unsigned int require_krbtgt_otherName:1;
89 unsigned int require_hostname_match:1;
90 unsigned int trustedCertifiers:1;
94 _krb5_pk_copy_error(krb5_context context,
95 hx509_context hx509ctx,
99 __attribute__ ((format (printf, 4, 5)));
105 void KRB5_LIB_FUNCTION
106 _krb5_pk_cert_free(struct krb5_pk_cert *cert)
109 hx509_cert_free(cert->cert);
114 static krb5_error_code
115 BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
117 integer->length = BN_num_bytes(bn);
118 integer->data = malloc(integer->length);
119 if (integer->data == NULL) {
120 krb5_clear_error_string(context);
123 BN_bn2bin(bn, integer->data);
124 integer->negative = BN_is_negative(bn);
129 integer_to_BN(krb5_context context, const char *field, const heim_integer *f)
133 bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL);
135 krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field);
138 BN_set_negative(bn, f->negative);
143 static krb5_error_code
144 _krb5_pk_create_sign(krb5_context context,
145 const heim_oid *eContentType,
147 struct krb5_pk_identity *id,
148 hx509_peer_info peer,
155 ret = hx509_query_alloc(id->hx509ctx, &q);
157 _krb5_pk_copy_error(context, id->hx509ctx, ret,
158 "Allocate query to find signing certificate");
162 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
163 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
165 ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert);
166 hx509_query_free(id->hx509ctx, q);
168 _krb5_pk_copy_error(context, id->hx509ctx, ret,
169 "Find certificate to signed CMS data");
173 ret = hx509_cms_create_signed_1(id->hx509ctx,
185 _krb5_pk_copy_error(context, id->hx509ctx, ret, "create CMS signedData");
186 hx509_cert_free(cert);
192 cert2epi(hx509_context context, void *ctx, hx509_cert c)
194 ExternalPrincipalIdentifiers *ids = ctx;
195 ExternalPrincipalIdentifier id;
196 hx509_name subject = NULL;
200 memset(&id, 0, sizeof(id));
202 ret = hx509_cert_get_subject(c, &subject);
206 if (hx509_name_is_null_p(subject) != 0) {
208 id.subjectName = calloc(1, sizeof(*id.subjectName));
209 if (id.subjectName == NULL) {
210 hx509_name_free(&subject);
211 free_ExternalPrincipalIdentifier(&id);
215 ret = hx509_name_to_der_name(subject, &id.subjectName->data,
216 &id.subjectName->length);
218 hx509_name_free(&subject);
219 free_ExternalPrincipalIdentifier(&id);
223 hx509_name_free(&subject);
226 id.issuerAndSerialNumber = calloc(1, sizeof(*id.issuerAndSerialNumber));
227 if (id.issuerAndSerialNumber == NULL) {
228 free_ExternalPrincipalIdentifier(&id);
233 IssuerAndSerialNumber iasn;
237 memset(&iasn, 0, sizeof(iasn));
239 ret = hx509_cert_get_issuer(c, &issuer);
241 free_ExternalPrincipalIdentifier(&id);
245 ret = hx509_name_to_Name(issuer, &iasn.issuer);
246 hx509_name_free(&issuer);
248 free_ExternalPrincipalIdentifier(&id);
252 ret = hx509_cert_get_serialnumber(c, &iasn.serialNumber);
254 free_IssuerAndSerialNumber(&iasn);
255 free_ExternalPrincipalIdentifier(&id);
259 ASN1_MALLOC_ENCODE(IssuerAndSerialNumber,
260 id.issuerAndSerialNumber->data,
261 id.issuerAndSerialNumber->length,
263 free_IssuerAndSerialNumber(&iasn);
266 if (id.issuerAndSerialNumber->length != size)
270 id.subjectKeyIdentifier = NULL;
272 p = realloc(ids->val, sizeof(ids->val[0]) * (ids->len + 1));
274 free_ExternalPrincipalIdentifier(&id);
279 ids->val[ids->len] = id;
285 static krb5_error_code
286 build_edi(krb5_context context,
287 hx509_context hx509ctx,
289 ExternalPrincipalIdentifiers *ids)
291 return hx509_certs_iter(hx509ctx, certs, cert2epi, ids);
294 static krb5_error_code
295 build_auth_pack(krb5_context context,
297 krb5_pk_init_ctx ctx,
299 const KDC_REQ_BODY *body,
302 size_t buf_size, len;
309 krb5_clear_error_string(context);
311 memset(&checksum, 0, sizeof(checksum));
313 krb5_us_timeofday(context, &sec, &usec);
314 a->pkAuthenticator.ctime = sec;
315 a->pkAuthenticator.nonce = nonce;
317 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
321 krb5_abortx(context, "internal error in ASN.1 encoder");
323 ret = krb5_create_checksum(context,
334 ALLOC(a->pkAuthenticator.paChecksum, 1);
335 if (a->pkAuthenticator.paChecksum == NULL) {
336 krb5_set_error_string(context, "malloc: out of memory");
340 ret = krb5_data_copy(a->pkAuthenticator.paChecksum,
341 checksum.checksum.data, checksum.checksum.length);
342 free_Checksum(&checksum);
348 heim_integer dh_pub_key;
352 if (1 /* support_cached_dh */) {
353 ALLOC(a->clientDHNonce, 1);
354 if (a->clientDHNonce == NULL) {
355 krb5_clear_error_string(context);
358 ret = krb5_data_alloc(a->clientDHNonce, 40);
359 if (a->clientDHNonce == NULL) {
360 krb5_clear_error_string(context);
363 memset(a->clientDHNonce->data, 0, a->clientDHNonce->length);
364 ret = krb5_copy_data(context, a->clientDHNonce,
365 &ctx->clientDHNonce);
370 ALLOC(a->clientPublicValue, 1);
371 if (a->clientPublicValue == NULL)
373 ret = der_copy_oid(oid_id_dhpublicnumber(),
374 &a->clientPublicValue->algorithm.algorithm);
378 memset(&dp, 0, sizeof(dp));
380 ret = BN_to_integer(context, dh->p, &dp.p);
382 free_DomainParameters(&dp);
385 ret = BN_to_integer(context, dh->g, &dp.g);
387 free_DomainParameters(&dp);
390 ret = BN_to_integer(context, dh->q, &dp.q);
392 free_DomainParameters(&dp);
396 dp.validationParms = NULL;
398 a->clientPublicValue->algorithm.parameters =
399 malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
400 if (a->clientPublicValue->algorithm.parameters == NULL) {
401 free_DomainParameters(&dp);
405 ASN1_MALLOC_ENCODE(DomainParameters,
406 a->clientPublicValue->algorithm.parameters->data,
407 a->clientPublicValue->algorithm.parameters->length,
409 free_DomainParameters(&dp);
412 if (size != a->clientPublicValue->algorithm.parameters->length)
413 krb5_abortx(context, "Internal ASN1 encoder error");
415 ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
419 ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
420 &dh_pub_key, &size, ret);
421 der_free_heim_integer(&dh_pub_key);
424 if (size != dhbuf.length)
425 krb5_abortx(context, "asn1 internal error");
427 a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
428 a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
432 a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes));
433 if (a->supportedCMSTypes == NULL)
436 ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL,
437 &a->supportedCMSTypes->val,
438 &a->supportedCMSTypes->len);
446 krb5_error_code KRB5_LIB_FUNCTION
447 _krb5_pk_mk_ContentInfo(krb5_context context,
448 const krb5_data *buf,
450 struct ContentInfo *content_info)
454 ret = der_copy_oid(oid, &content_info->contentType);
457 ALLOC(content_info->content, 1);
458 if (content_info->content == NULL)
460 content_info->content->data = malloc(buf->length);
461 if (content_info->content->data == NULL)
463 memcpy(content_info->content->data, buf->data, buf->length);
464 content_info->content->length = buf->length;
468 static krb5_error_code
469 pk_mk_padata(krb5_context context,
470 krb5_pk_init_ctx ctx,
471 const KDC_REQ_BODY *req_body,
475 struct ContentInfo content_info;
479 krb5_data buf, sd_buf;
482 krb5_data_zero(&buf);
483 krb5_data_zero(&sd_buf);
484 memset(&content_info, 0, sizeof(content_info));
486 if (ctx->type == COMPAT_WIN2K) {
491 memset(&ap, 0, sizeof(ap));
493 /* fill in PKAuthenticator */
494 ret = copy_PrincipalName(req_body->sname, &ap.pkAuthenticator.kdcName);
496 free_AuthPack_Win2k(&ap);
497 krb5_clear_error_string(context);
500 ret = copy_Realm(&req_body->realm, &ap.pkAuthenticator.kdcRealm);
502 free_AuthPack_Win2k(&ap);
503 krb5_clear_error_string(context);
507 krb5_us_timeofday(context, &sec, &usec);
508 ap.pkAuthenticator.ctime = sec;
509 ap.pkAuthenticator.cusec = usec;
510 ap.pkAuthenticator.nonce = nonce;
512 ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length,
514 free_AuthPack_Win2k(&ap);
516 krb5_set_error_string(context, "AuthPack_Win2k: %d", ret);
519 if (buf.length != size)
520 krb5_abortx(context, "internal ASN1 encoder error");
522 oid = oid_id_pkcs7_data();
523 } else if (ctx->type == COMPAT_IETF) {
526 memset(&ap, 0, sizeof(ap));
528 ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap);
534 ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret);
537 krb5_set_error_string(context, "AuthPack: %d", ret);
540 if (buf.length != size)
541 krb5_abortx(context, "internal ASN1 encoder error");
543 oid = oid_id_pkauthdata();
545 krb5_abortx(context, "internal pkinit error");
547 ret = _krb5_pk_create_sign(context,
553 krb5_data_free(&buf);
557 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
558 krb5_data_free(&sd_buf);
560 krb5_set_error_string(context,
561 "ContentInfo wrapping of signedData failed");
565 if (ctx->type == COMPAT_WIN2K) {
566 PA_PK_AS_REQ_Win2k winreq;
568 pa_type = KRB5_PADATA_PK_AS_REQ_WIN;
570 memset(&winreq, 0, sizeof(winreq));
572 winreq.signed_auth_pack = buf;
574 ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length,
575 &winreq, &size, ret);
576 free_PA_PK_AS_REQ_Win2k(&winreq);
578 } else if (ctx->type == COMPAT_IETF) {
581 pa_type = KRB5_PADATA_PK_AS_REQ;
583 memset(&req, 0, sizeof(req));
584 req.signedAuthPack = buf;
586 if (ctx->trustedCertifiers) {
588 req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers));
589 if (req.trustedCertifiers == NULL) {
590 krb5_set_error_string(context, "malloc: out of memory");
591 free_PA_PK_AS_REQ(&req);
594 ret = build_edi(context, ctx->id->hx509ctx,
595 ctx->id->anchors, req.trustedCertifiers);
597 krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers");
598 free_PA_PK_AS_REQ(&req);
604 ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length,
607 free_PA_PK_AS_REQ(&req);
610 krb5_abortx(context, "internal pkinit error");
612 krb5_set_error_string(context, "PA-PK-AS-REQ %d", ret);
615 if (buf.length != size)
616 krb5_abortx(context, "Internal ASN1 encoder error");
618 ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length);
622 if (ret == 0 && ctx->type == COMPAT_WIN2K)
623 krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
626 free_ContentInfo(&content_info);
632 krb5_error_code KRB5_LIB_FUNCTION
633 _krb5_pk_mk_padata(krb5_context context,
635 const KDC_REQ_BODY *req_body,
639 krb5_pk_init_ctx ctx = c;
642 win2k_compat = krb5_config_get_bool_default(context, NULL,
650 ctx->require_binding =
651 krb5_config_get_bool_default(context, NULL,
655 "pkinit_win2k_require_binding",
657 ctx->type = COMPAT_WIN2K;
659 ctx->type = COMPAT_IETF;
662 krb5_config_get_bool_default(context, NULL,
666 "pkinit_require_eku",
668 ctx->require_krbtgt_otherName =
669 krb5_config_get_bool_default(context, NULL,
673 "pkinit_require_krbtgt_otherName",
676 ctx->require_hostname_match =
677 krb5_config_get_bool_default(context, NULL,
681 "pkinit_require_hostname_match",
684 ctx->trustedCertifiers =
685 krb5_config_get_bool_default(context, NULL,
689 "pkinit_trustedCertifiers",
692 return pk_mk_padata(context, ctx, req_body, nonce, md);
695 krb5_error_code KRB5_LIB_FUNCTION
696 _krb5_pk_verify_sign(krb5_context context,
699 struct krb5_pk_identity *id,
700 heim_oid *contentType,
702 struct krb5_pk_cert **signer)
704 hx509_certs signer_certs;
709 ret = hx509_cms_verify_signed(id->hx509ctx,
719 _krb5_pk_copy_error(context, id->hx509ctx, ret,
720 "CMS verify signed failed");
724 *signer = calloc(1, sizeof(**signer));
725 if (*signer == NULL) {
726 krb5_clear_error_string(context);
731 ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert);
733 _krb5_pk_copy_error(context, id->hx509ctx, ret,
734 "Failed to get on of the signer certs");
739 hx509_certs_free(&signer_certs);
742 hx509_cert_free((*signer)->cert);
751 static krb5_error_code
752 get_reply_key_win(krb5_context context,
753 const krb5_data *content,
757 ReplyKeyPack_Win2k key_pack;
761 ret = decode_ReplyKeyPack_Win2k(content->data,
766 krb5_set_error_string(context, "PKINIT decoding reply key failed");
767 free_ReplyKeyPack_Win2k(&key_pack);
771 if (key_pack.nonce != nonce) {
772 krb5_set_error_string(context, "PKINIT enckey nonce is wrong");
773 free_ReplyKeyPack_Win2k(&key_pack);
774 return KRB5KRB_AP_ERR_MODIFIED;
777 *key = malloc (sizeof (**key));
779 krb5_set_error_string(context, "PKINIT failed allocating reply key");
780 free_ReplyKeyPack_Win2k(&key_pack);
781 krb5_set_error_string(context, "malloc: out of memory");
785 ret = copy_EncryptionKey(&key_pack.replyKey, *key);
786 free_ReplyKeyPack_Win2k(&key_pack);
788 krb5_set_error_string(context, "PKINIT failed copying reply key");
796 static krb5_error_code
797 get_reply_key(krb5_context context,
798 const krb5_data *content,
799 const krb5_data *req_buffer,
802 ReplyKeyPack key_pack;
806 ret = decode_ReplyKeyPack(content->data,
811 krb5_set_error_string(context, "PKINIT decoding reply key failed");
812 free_ReplyKeyPack(&key_pack);
820 * XXX Verify kp.replyKey is a allowed enctype in the
824 ret = krb5_crypto_init(context, &key_pack.replyKey, 0, &crypto);
826 free_ReplyKeyPack(&key_pack);
830 ret = krb5_verify_checksum(context, crypto, 6,
831 req_buffer->data, req_buffer->length,
832 &key_pack.asChecksum);
833 krb5_crypto_destroy(context, crypto);
835 free_ReplyKeyPack(&key_pack);
840 *key = malloc (sizeof (**key));
842 krb5_set_error_string(context, "PKINIT failed allocating reply key");
843 free_ReplyKeyPack(&key_pack);
844 krb5_set_error_string(context, "malloc: out of memory");
848 ret = copy_EncryptionKey(&key_pack.replyKey, *key);
849 free_ReplyKeyPack(&key_pack);
851 krb5_set_error_string(context, "PKINIT failed copying reply key");
860 static krb5_error_code
861 pk_verify_host(krb5_context context,
863 const krb5_krbhst_info *hi,
864 struct krb5_pk_init_ctx_data *ctx,
865 struct krb5_pk_cert *host)
867 krb5_error_code ret = 0;
869 if (ctx->require_eku) {
870 ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert,
871 oid_id_pkkdcekuoid(), 0);
873 krb5_set_error_string(context, "No PK-INIT KDC EKU in kdc certificate");
877 if (ctx->require_krbtgt_otherName) {
878 hx509_octet_string_list list;
881 ret = hx509_cert_find_subjectAltName_otherName(host->cert,
885 krb5_set_error_string(context, "Failed to find the PK-INIT "
886 "subjectAltName in the KDC certificate");
891 for (i = 0; i < list.len; i++) {
894 ret = decode_KRB5PrincipalName(list.val[i].data,
899 krb5_set_error_string(context, "Failed to decode the PK-INIT "
900 "subjectAltName in the KDC certificate");
905 if (r.principalName.name_string.len != 2 ||
906 strcmp(r.principalName.name_string.val[0], KRB5_TGS_NAME) != 0 ||
907 strcmp(r.principalName.name_string.val[1], realm) != 0 ||
908 strcmp(r.realm, realm) != 0)
910 krb5_set_error_string(context, "KDC have wrong realm name in "
912 ret = KRB5_KDC_ERR_INVALID_CERTIFICATE;
915 free_KRB5PrincipalName(&r);
919 hx509_free_octet_string_list(&list);
925 ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert,
926 ctx->require_hostname_match,
929 hi->ai->ai_addr, hi->ai->ai_addrlen);
932 krb5_set_error_string(context, "Address mismatch in "
933 "the KDC certificate");
938 static krb5_error_code
939 pk_rd_pa_reply_enckey(krb5_context context,
941 const heim_octet_string *indata,
942 const heim_oid *dataType,
944 krb5_pk_init_ctx ctx,
946 const krb5_krbhst_info *hi,
948 const krb5_data *req_buffer,
953 struct krb5_pk_cert *host = NULL;
955 heim_oid contentType = { 0, NULL };
957 if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) {
958 krb5_set_error_string(context, "PKINIT: Invalid content type");
962 ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
964 HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
971 _krb5_pk_copy_error(context, ctx->id->hx509ctx, ret,
972 "Failed to unenvelope CMS data in PK-INIT reply");
975 der_free_oid(&contentType);
977 #if 0 /* windows LH with interesting CMS packets, leaks memory */
979 size_t ph = 1 + der_length_len (length);
980 unsigned char *ptr = malloc(length + ph);
983 memcpy(ptr + ph, p, length);
985 ret = der_put_length_and_tag (ptr + ph - 1, ph, length,
986 ASN1_C_UNIV, CONS, UT_Sequence, &l);
995 /* win2k uses ContentInfo */
996 if (type == COMPAT_WIN2K) {
998 heim_octet_string out;
1000 ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
1001 if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
1002 ret = EINVAL; /* XXX */
1003 krb5_set_error_string(context, "PKINIT: Invalid content type");
1004 der_free_oid(&type);
1005 der_free_octet_string(&out);
1008 der_free_oid(&type);
1009 krb5_data_free(&content);
1010 ret = krb5_data_copy(&content, out.data, out.length);
1011 der_free_octet_string(&out);
1013 krb5_set_error_string(context, "PKINIT: out of memory");
1018 ret = _krb5_pk_verify_sign(context,
1028 /* make sure that it is the kdc's certificate */
1029 ret = pk_verify_host(context, realm, hi, ctx, host);
1035 if (type == COMPAT_WIN2K) {
1036 if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
1037 krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
1038 ret = KRB5KRB_AP_ERR_MSG_TYPE;
1042 if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) {
1043 krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
1044 ret = KRB5KRB_AP_ERR_MSG_TYPE;
1052 ret = get_reply_key(context, &content, req_buffer, key);
1053 if (ret != 0 && ctx->require_binding == 0)
1054 ret = get_reply_key_win(context, &content, nonce, key);
1057 ret = get_reply_key(context, &content, req_buffer, key);
1063 /* XXX compare given etype with key->etype */
1067 _krb5_pk_cert_free(host);
1068 der_free_oid(&contentType);
1069 krb5_data_free(&content);
1074 static krb5_error_code
1075 pk_rd_pa_reply_dh(krb5_context context,
1076 const heim_octet_string *indata,
1077 const heim_oid *dataType,
1079 krb5_pk_init_ctx ctx,
1081 const krb5_krbhst_info *hi,
1086 krb5_keyblock **key)
1088 unsigned char *p, *dh_gen_key = NULL;
1089 struct krb5_pk_cert *host = NULL;
1090 BIGNUM *kdc_dh_pubkey = NULL;
1091 KDCDHKeyInfo kdc_dh_info;
1092 heim_oid contentType = { 0, NULL };
1094 krb5_error_code ret;
1098 krb5_data_zero(&content);
1099 memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
1101 if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) {
1102 krb5_set_error_string(context, "PKINIT: Invalid content type");
1106 ret = _krb5_pk_verify_sign(context,
1116 /* make sure that it is the kdc's certificate */
1117 ret = pk_verify_host(context, realm, hi, ctx, host);
1121 if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
1122 krb5_set_error_string(context, "pkinit - dh reply contains wrong oid");
1123 ret = KRB5KRB_AP_ERR_MSG_TYPE;
1127 ret = decode_KDCDHKeyInfo(content.data,
1133 krb5_set_error_string(context, "pkinit - "
1134 "failed to decode KDC DH Key Info");
1138 if (kdc_dh_info.nonce != nonce) {
1139 krb5_set_error_string(context, "PKINIT: DH nonce is wrong");
1140 ret = KRB5KRB_AP_ERR_MODIFIED;
1144 if (kdc_dh_info.dhKeyExpiration) {
1146 krb5_set_error_string(context, "pkinit; got key expiration "
1147 "without server nonce");
1148 ret = KRB5KRB_ERR_GENERIC;
1152 krb5_set_error_string(context, "pkinit; got DH reuse but no "
1154 ret = KRB5KRB_ERR_GENERIC;
1159 krb5_set_error_string(context, "pkinit: got server nonce "
1160 "without key expiration");
1161 ret = KRB5KRB_ERR_GENERIC;
1168 p = kdc_dh_info.subjectPublicKey.data;
1169 size = (kdc_dh_info.subjectPublicKey.length + 7) / 8;
1173 ret = decode_DHPublicKey(p, size, &k, NULL);
1175 krb5_set_error_string(context, "pkinit: can't decode "
1176 "without key expiration");
1180 kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k);
1181 free_DHPublicKey(&k);
1182 if (kdc_dh_pubkey == NULL) {
1183 ret = KRB5KRB_ERR_GENERIC;
1188 dh_gen_keylen = DH_size(ctx->dh);
1189 size = BN_num_bytes(ctx->dh->p);
1190 if (size < dh_gen_keylen)
1191 size = dh_gen_keylen;
1193 dh_gen_key = malloc(size);
1194 if (dh_gen_key == NULL) {
1195 krb5_set_error_string(context, "malloc: out of memory");
1199 memset(dh_gen_key, 0, size - dh_gen_keylen);
1201 dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
1202 kdc_dh_pubkey, ctx->dh);
1203 if (dh_gen_keylen == -1) {
1204 krb5_set_error_string(context,
1205 "PKINIT: Can't compute Diffie-Hellman key");
1206 ret = KRB5KRB_ERR_GENERIC;
1210 *key = malloc (sizeof (**key));
1212 krb5_set_error_string(context, "malloc: out of memory");
1217 ret = _krb5_pk_octetstring2key(context,
1219 dh_gen_key, dh_gen_keylen,
1223 krb5_set_error_string(context,
1224 "PKINIT: can't create key from DH key");
1232 BN_free(kdc_dh_pubkey);
1234 memset(dh_gen_key, 0, DH_size(ctx->dh));
1238 _krb5_pk_cert_free(host);
1240 krb5_data_free(&content);
1241 der_free_oid(&contentType);
1242 free_KDCDHKeyInfo(&kdc_dh_info);
1247 krb5_error_code KRB5_LIB_FUNCTION
1248 _krb5_pk_rd_pa_reply(krb5_context context,
1252 const krb5_krbhst_info *hi,
1254 const krb5_data *req_buffer,
1256 krb5_keyblock **key)
1258 krb5_pk_init_ctx ctx = c;
1259 krb5_error_code ret;
1262 /* Check for IETF PK-INIT first */
1263 if (ctx->type == COMPAT_IETF) {
1265 heim_octet_string os, data;
1268 if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
1269 krb5_set_error_string(context, "PKINIT: wrong padata recv");
1273 ret = decode_PA_PK_AS_REP(pa->padata_value.data,
1274 pa->padata_value.length,
1278 krb5_set_error_string(context, "Failed to decode pkinit AS rep");
1282 switch (rep.element) {
1283 case choice_PA_PK_AS_REP_dhInfo:
1284 os = rep.u.dhInfo.dhSignedData;
1286 case choice_PA_PK_AS_REP_encKeyPack:
1287 os = rep.u.encKeyPack;
1290 free_PA_PK_AS_REP(&rep);
1291 krb5_set_error_string(context, "PKINIT: -27 reply "
1292 "invalid content type");
1296 ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
1298 free_PA_PK_AS_REP(&rep);
1299 krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
1303 switch (rep.element) {
1304 case choice_PA_PK_AS_REP_dhInfo:
1305 ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi,
1307 rep.u.dhInfo.serverDHNonce,
1310 case choice_PA_PK_AS_REP_encKeyPack:
1311 ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm,
1312 ctx, etype, hi, nonce, req_buffer, pa, key);
1315 krb5_abortx(context, "pk-init as-rep case not possible to happen");
1317 der_free_octet_string(&data);
1319 free_PA_PK_AS_REP(&rep);
1321 } else if (ctx->type == COMPAT_WIN2K) {
1322 PA_PK_AS_REP_Win2k w2krep;
1324 /* Check for Windows encoding of the AS-REP pa data */
1326 #if 0 /* should this be ? */
1327 if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
1328 krb5_set_error_string(context, "PKINIT: wrong padata recv");
1333 memset(&w2krep, 0, sizeof(w2krep));
1335 ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data,
1336 pa->padata_value.length,
1340 krb5_set_error_string(context, "PKINIT: Failed decoding windows "
1341 "pkinit reply %d", ret);
1345 krb5_clear_error_string(context);
1347 switch (w2krep.element) {
1348 case choice_PA_PK_AS_REP_Win2k_encKeyPack: {
1349 heim_octet_string data;
1352 ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack,
1354 free_PA_PK_AS_REP_Win2k(&w2krep);
1356 krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
1360 ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm,
1361 ctx, etype, hi, nonce, req_buffer, pa, key);
1362 der_free_octet_string(&data);
1368 free_PA_PK_AS_REP_Win2k(&w2krep);
1369 krb5_set_error_string(context, "PKINIT: win2k reply invalid "
1376 krb5_set_error_string(context, "PKINIT: unknown reply type");
1384 krb5_context context;
1385 krb5_prompter_fct prompter;
1386 void *prompter_data;
1390 hx_pass_prompter(void *data, const hx509_prompt *prompter)
1392 krb5_error_code ret;
1394 krb5_data password_data;
1395 struct prompter *p = data;
1397 password_data.data = prompter->reply.data;
1398 password_data.length = prompter->reply.length;
1400 prompt.prompt = prompter->prompt;
1401 prompt.hidden = hx509_prompt_hidden(prompter->type);
1402 prompt.reply = &password_data;
1404 switch (prompter->type) {
1405 case HX509_PROMPT_TYPE_INFO:
1406 prompt.type = KRB5_PROMPT_TYPE_INFO;
1408 case HX509_PROMPT_TYPE_PASSWORD:
1409 case HX509_PROMPT_TYPE_QUESTION:
1411 prompt.type = KRB5_PROMPT_TYPE_PASSWORD;
1415 ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt);
1417 memset (prompter->reply.data, 0, prompter->reply.length);
1424 void KRB5_LIB_FUNCTION
1425 _krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id,
1428 hx509_verify_set_proxy_certificate(id->verify_ctx, boolean);
1432 krb5_error_code KRB5_LIB_FUNCTION
1433 _krb5_pk_load_id(krb5_context context,
1434 struct krb5_pk_identity **ret_id,
1435 const char *user_id,
1436 const char *anchor_id,
1437 char * const *chain_list,
1438 char * const *revoke_list,
1439 krb5_prompter_fct prompter,
1440 void *prompter_data,
1443 struct krb5_pk_identity *id = NULL;
1444 hx509_lock lock = NULL;
1450 if (anchor_id == NULL) {
1451 krb5_set_error_string(context, "PKINIT: No anchor given");
1452 return HEIM_PKINIT_NO_VALID_CA;
1455 if (user_id == NULL) {
1456 krb5_set_error_string(context,
1457 "PKINIT: No user certificate given");
1458 return HEIM_PKINIT_NO_PRIVATE_KEY;
1463 id = calloc(1, sizeof(*id));
1465 krb5_set_error_string(context, "malloc: out of memory");
1469 ret = hx509_context_init(&id->hx509ctx);
1473 ret = hx509_lock_init(id->hx509ctx, &lock);
1474 if (password && password[0])
1475 hx509_lock_add_password(lock, password);
1478 p.context = context;
1479 p.prompter = prompter;
1480 p.prompter_data = prompter_data;
1482 ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p);
1487 ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
1489 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1490 "Failed to init cert certs");
1494 ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors);
1496 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1497 "Failed to init anchors");
1501 ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain",
1502 0, NULL, &id->certpool);
1504 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1505 "Failed to init chain");
1509 while (chain_list && *chain_list) {
1510 ret = hx509_certs_append(id->hx509ctx, id->certpool,
1513 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1514 "Failed to laod chain %s",
1522 ret = hx509_revoke_init(id->hx509ctx, &id->revokectx);
1524 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1525 "Failed init revoke list");
1529 while (*revoke_list) {
1530 ret = hx509_revoke_add_crl(id->hx509ctx,
1534 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1535 "Failed load revoke list");
1541 hx509_context_set_missing_revoke(id->hx509ctx, 1);
1543 ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx);
1545 _krb5_pk_copy_error(context, id->hx509ctx, ret,
1546 "Failed init verify context");
1550 hx509_verify_attach_anchors(id->verify_ctx, id->anchors);
1551 hx509_verify_attach_revoke(id->verify_ctx, id->revokectx);
1555 hx509_verify_destroy_ctx(id->verify_ctx);
1556 hx509_certs_free(&id->certs);
1557 hx509_certs_free(&id->anchors);
1558 hx509_certs_free(&id->certpool);
1559 hx509_revoke_free(&id->revokectx);
1560 hx509_context_free(&id->hx509ctx);
1565 hx509_lock_free(lock);
1570 static krb5_error_code
1571 select_dh_group(krb5_context context, DH *dh, unsigned long bits,
1572 struct krb5_dh_moduli **moduli)
1574 const struct krb5_dh_moduli *m;
1577 m = moduli[1]; /* XXX */
1579 m = moduli[0]; /* XXX */
1582 for (i = 0; moduli[i] != NULL; i++) {
1583 if (bits < moduli[i]->bits)
1586 if (moduli[i] == NULL) {
1587 krb5_set_error_string(context,
1588 "Did not find a DH group parameter "
1589 "matching requirement of %lu bits",
1596 dh->p = integer_to_BN(context, "p", &m->p);
1599 dh->g = integer_to_BN(context, "g", &m->g);
1602 dh->q = integer_to_BN(context, "q", &m->q);
1612 parse_integer(krb5_context context, char **p, const char *file, int lineno,
1613 const char *name, heim_integer *integer)
1617 p1 = strsep(p, " \t");
1619 krb5_set_error_string(context, "moduli file %s missing %s on line %d",
1620 file, name, lineno);
1623 ret = der_parse_hex_heim_integer(p1, integer);
1625 krb5_set_error_string(context, "moduli file %s failed parsing %s "
1627 file, name, lineno);
1635 _krb5_parse_moduli_line(krb5_context context,
1639 struct krb5_dh_moduli **m)
1641 struct krb5_dh_moduli *m1;
1647 m1 = calloc(1, sizeof(*m1));
1649 krb5_set_error_string(context, "malloc - out of memory");
1653 while (isspace((unsigned char)*p))
1659 p1 = strsep(&p, " \t");
1661 krb5_set_error_string(context, "moduli file %s missing name "
1662 "on line %d", file, lineno);
1665 m1->name = strdup(p1);
1667 krb5_set_error_string(context, "malloc - out of memeory");
1672 p1 = strsep(&p, " \t");
1674 krb5_set_error_string(context, "moduli file %s missing bits on line %d",
1679 m1->bits = atoi(p1);
1680 if (m1->bits == 0) {
1681 krb5_set_error_string(context, "moduli file %s have un-parsable "
1682 "bits on line %d", file, lineno);
1686 ret = parse_integer(context, &p, file, lineno, "p", &m1->p);
1689 ret = parse_integer(context, &p, file, lineno, "g", &m1->g);
1692 ret = parse_integer(context, &p, file, lineno, "q", &m1->q);
1701 der_free_heim_integer(&m1->p);
1702 der_free_heim_integer(&m1->g);
1703 der_free_heim_integer(&m1->q);
1709 _krb5_free_moduli(struct krb5_dh_moduli **moduli)
1712 for (i = 0; moduli[i] != NULL; i++) {
1713 free(moduli[i]->name);
1714 der_free_heim_integer(&moduli[i]->p);
1715 der_free_heim_integer(&moduli[i]->g);
1716 der_free_heim_integer(&moduli[i]->q);
1722 static const char *default_moduli_RFC2412_MODP_group2 =
1724 "RFC2412-MODP-group2 "
1728 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
1729 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
1730 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
1731 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
1732 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
1733 "FFFFFFFF" "FFFFFFFF "
1737 "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
1738 "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
1739 "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
1740 "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
1741 "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0"
1742 "FFFFFFFF" "FFFFFFFF";
1744 static const char *default_moduli_rfc3526_MODP_group14 =
1746 "rfc3526-MODP-group14 "
1750 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
1751 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
1752 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
1753 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
1754 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
1755 "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
1756 "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
1757 "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
1758 "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
1759 "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
1760 "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF "
1764 "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
1765 "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
1766 "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
1767 "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
1768 "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F6722D9E"
1769 "E1003E5C" "50B1DF82" "CC6D241B" "0E2AE9CD" "348B1FD4" "7E9267AF"
1770 "C1B2AE91" "EE51D6CB" "0E3179AB" "1042A95D" "CF6A9483" "B84B4B36"
1771 "B3861AA7" "255E4C02" "78BA3604" "650C10BE" "19482F23" "171B671D"
1772 "F1CF3B96" "0C074301" "CD93C1D1" "7603D147" "DAE2AEF8" "37A62964"
1773 "EF15E5FB" "4AAC0B8C" "1CCAA4BE" "754AB572" "8AE9130C" "4C7D0288"
1774 "0AB9472D" "45565534" "7FFFFFFF" "FFFFFFFF";
1777 _krb5_parse_moduli(krb5_context context, const char *file,
1778 struct krb5_dh_moduli ***moduli)
1780 /* name bits P G Q */
1781 krb5_error_code ret;
1782 struct krb5_dh_moduli **m = NULL, **m2;
1785 int lineno = 0, n = 0;
1789 m = calloc(1, sizeof(m[0]) * 3);
1791 krb5_set_error_string(context, "malloc: out of memory");
1795 strlcpy(buf, default_moduli_rfc3526_MODP_group14, sizeof(buf));
1796 ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[0]);
1798 _krb5_free_moduli(m);
1803 strlcpy(buf, default_moduli_RFC2412_MODP_group2, sizeof(buf));
1804 ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[1]);
1806 _krb5_free_moduli(m);
1815 f = fopen(file, "r");
1821 while(fgets(buf, sizeof(buf), f) != NULL) {
1822 struct krb5_dh_moduli *element;
1824 buf[strcspn(buf, "\n")] = '\0';
1827 m2 = realloc(m, (n + 2) * sizeof(m[0]));
1829 krb5_set_error_string(context, "malloc: out of memory");
1830 _krb5_free_moduli(m);
1837 ret = _krb5_parse_moduli_line(context, file, lineno, buf, &element);
1839 _krb5_free_moduli(m);
1842 if (element == NULL)
1854 _krb5_dh_group_ok(krb5_context context, unsigned long bits,
1855 heim_integer *p, heim_integer *g, heim_integer *q,
1856 struct krb5_dh_moduli **moduli,
1864 for (i = 0; moduli[i] != NULL; i++) {
1865 if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 &&
1866 der_heim_integer_cmp(&moduli[i]->p, p) == 0 &&
1867 (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0))
1869 if (bits && bits > moduli[i]->bits) {
1870 krb5_set_error_string(context, "PKINIT: DH group parameter %s "
1871 "no accepted, not enough bits generated",
1873 return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
1876 *name = strdup(moduli[i]->name);
1880 krb5_set_error_string(context, "PKINIT: DH group parameter no ok");
1881 return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
1884 void KRB5_LIB_FUNCTION
1885 _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
1888 krb5_pk_init_ctx ctx;
1890 if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL)
1892 ctx = opt->opt_private->pk_init_ctx;
1897 hx509_verify_destroy_ctx(ctx->id->verify_ctx);
1898 hx509_certs_free(&ctx->id->certs);
1899 hx509_certs_free(&ctx->id->anchors);
1900 hx509_certs_free(&ctx->id->certpool);
1901 hx509_context_free(&ctx->id->hx509ctx);
1903 if (ctx->clientDHNonce) {
1904 krb5_free_data(NULL, ctx->clientDHNonce);
1905 ctx->clientDHNonce = NULL;
1908 _krb5_free_moduli(ctx->m);
1912 free(opt->opt_private->pk_init_ctx);
1913 opt->opt_private->pk_init_ctx = NULL;
1917 krb5_error_code KRB5_LIB_FUNCTION
1918 krb5_get_init_creds_opt_set_pkinit(krb5_context context,
1919 krb5_get_init_creds_opt *opt,
1920 krb5_principal principal,
1921 const char *user_id,
1922 const char *x509_anchors,
1923 char * const * pool,
1924 char * const * pki_revoke,
1926 krb5_prompter_fct prompter,
1927 void *prompter_data,
1931 krb5_error_code ret;
1932 char *anchors = NULL;
1934 if (opt->opt_private == NULL) {
1935 krb5_set_error_string(context, "PKINIT: on non extendable opt");
1939 opt->opt_private->pk_init_ctx =
1940 calloc(1, sizeof(*opt->opt_private->pk_init_ctx));
1941 if (opt->opt_private->pk_init_ctx == NULL) {
1942 krb5_set_error_string(context, "malloc: out of memory");
1945 opt->opt_private->pk_init_ctx->dh = NULL;
1946 opt->opt_private->pk_init_ctx->id = NULL;
1947 opt->opt_private->pk_init_ctx->clientDHNonce = NULL;
1948 opt->opt_private->pk_init_ctx->require_binding = 0;
1949 opt->opt_private->pk_init_ctx->require_eku = 1;
1950 opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1;
1951 opt->opt_private->pk_init_ctx->peer = NULL;
1953 /* XXX implement krb5_appdefault_strings */
1955 pool = krb5_config_get_strings(context, NULL,
1960 if (pki_revoke == NULL)
1961 pki_revoke = krb5_config_get_strings(context, NULL,
1966 if (x509_anchors == NULL) {
1967 krb5_appdefault_string(context, "kinit",
1968 krb5_principal_get_realm(context, principal),
1969 "pkinit_anchors", NULL, &anchors);
1970 x509_anchors = anchors;
1973 ret = _krb5_pk_load_id(context,
1974 &opt->opt_private->pk_init_ctx->id,
1983 free(opt->opt_private->pk_init_ctx);
1984 opt->opt_private->pk_init_ctx = NULL;
1988 if ((flags & 2) == 0) {
1989 const char *moduli_file;
1990 unsigned long dh_min_bits;
1992 moduli_file = krb5_config_get_string(context, NULL,
1998 krb5_config_get_int_default(context, NULL, 0,
2000 "pkinit_dh_min_bits",
2003 ret = _krb5_parse_moduli(context, moduli_file,
2004 &opt->opt_private->pk_init_ctx->m);
2006 _krb5_get_init_creds_opt_free_pkinit(opt);
2010 opt->opt_private->pk_init_ctx->dh = DH_new();
2011 if (opt->opt_private->pk_init_ctx->dh == NULL) {
2012 krb5_set_error_string(context, "malloc: out of memory");
2013 _krb5_get_init_creds_opt_free_pkinit(opt);
2017 ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh,
2019 opt->opt_private->pk_init_ctx->m);
2021 _krb5_get_init_creds_opt_free_pkinit(opt);
2025 if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) {
2026 krb5_set_error_string(context, "pkinit: failed to generate DH key");
2027 _krb5_get_init_creds_opt_free_pkinit(opt);
2034 krb5_set_error_string(context, "no support for PKINIT compiled in");
2044 _krb5_pk_copy_error(krb5_context context,
2045 hx509_context hx509ctx,
2054 vasprintf(&f, fmt, va);
2057 krb5_clear_error_string(context);
2061 s = hx509_get_error_string(hx509ctx, hxret);
2063 krb5_clear_error_string(context);
2067 krb5_set_error_string(context, "%s: %s", f, s);