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 22433 2008-01-13 14:11:46Z 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_binary(subject, id.subjectName);
217 hx509_name_free(&subject);
218 free_ExternalPrincipalIdentifier(&id);
222 hx509_name_free(&subject);
225 id.issuerAndSerialNumber = calloc(1, sizeof(*id.issuerAndSerialNumber));
226 if (id.issuerAndSerialNumber == NULL) {
227 free_ExternalPrincipalIdentifier(&id);
232 IssuerAndSerialNumber iasn;
236 memset(&iasn, 0, sizeof(iasn));
238 ret = hx509_cert_get_issuer(c, &issuer);
240 free_ExternalPrincipalIdentifier(&id);
244 ret = hx509_name_to_Name(issuer, &iasn.issuer);
245 hx509_name_free(&issuer);
247 free_ExternalPrincipalIdentifier(&id);
251 ret = hx509_cert_get_serialnumber(c, &iasn.serialNumber);
253 free_IssuerAndSerialNumber(&iasn);
254 free_ExternalPrincipalIdentifier(&id);
258 ASN1_MALLOC_ENCODE(IssuerAndSerialNumber,
259 id.issuerAndSerialNumber->data,
260 id.issuerAndSerialNumber->length,
262 free_IssuerAndSerialNumber(&iasn);
265 if (id.issuerAndSerialNumber->length != size)
269 id.subjectKeyIdentifier = NULL;
271 p = realloc(ids->val, sizeof(ids->val[0]) * (ids->len + 1));
273 free_ExternalPrincipalIdentifier(&id);
278 ids->val[ids->len] = id;
284 static krb5_error_code
285 build_edi(krb5_context context,
286 hx509_context hx509ctx,
288 ExternalPrincipalIdentifiers *ids)
290 return hx509_certs_iter(hx509ctx, certs, cert2epi, ids);
293 static krb5_error_code
294 build_auth_pack(krb5_context context,
296 krb5_pk_init_ctx ctx,
298 const KDC_REQ_BODY *body,
301 size_t buf_size, len;
308 krb5_clear_error_string(context);
310 memset(&checksum, 0, sizeof(checksum));
312 krb5_us_timeofday(context, &sec, &usec);
313 a->pkAuthenticator.ctime = sec;
314 a->pkAuthenticator.nonce = nonce;
316 ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
320 krb5_abortx(context, "internal error in ASN.1 encoder");
322 ret = krb5_create_checksum(context,
333 ALLOC(a->pkAuthenticator.paChecksum, 1);
334 if (a->pkAuthenticator.paChecksum == NULL) {
335 krb5_set_error_string(context, "malloc: out of memory");
339 ret = krb5_data_copy(a->pkAuthenticator.paChecksum,
340 checksum.checksum.data, checksum.checksum.length);
341 free_Checksum(&checksum);
347 heim_integer dh_pub_key;
351 if (1 /* support_cached_dh */) {
352 ALLOC(a->clientDHNonce, 1);
353 if (a->clientDHNonce == NULL) {
354 krb5_clear_error_string(context);
357 ret = krb5_data_alloc(a->clientDHNonce, 40);
358 if (a->clientDHNonce == NULL) {
359 krb5_clear_error_string(context);
362 memset(a->clientDHNonce->data, 0, a->clientDHNonce->length);
363 ret = krb5_copy_data(context, a->clientDHNonce,
364 &ctx->clientDHNonce);
369 ALLOC(a->clientPublicValue, 1);
370 if (a->clientPublicValue == NULL)
372 ret = der_copy_oid(oid_id_dhpublicnumber(),
373 &a->clientPublicValue->algorithm.algorithm);
377 memset(&dp, 0, sizeof(dp));
379 ret = BN_to_integer(context, dh->p, &dp.p);
381 free_DomainParameters(&dp);
384 ret = BN_to_integer(context, dh->g, &dp.g);
386 free_DomainParameters(&dp);
389 ret = BN_to_integer(context, dh->q, &dp.q);
391 free_DomainParameters(&dp);
395 dp.validationParms = NULL;
397 a->clientPublicValue->algorithm.parameters =
398 malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
399 if (a->clientPublicValue->algorithm.parameters == NULL) {
400 free_DomainParameters(&dp);
404 ASN1_MALLOC_ENCODE(DomainParameters,
405 a->clientPublicValue->algorithm.parameters->data,
406 a->clientPublicValue->algorithm.parameters->length,
408 free_DomainParameters(&dp);
411 if (size != a->clientPublicValue->algorithm.parameters->length)
412 krb5_abortx(context, "Internal ASN1 encoder error");
414 ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
418 ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
419 &dh_pub_key, &size, ret);
420 der_free_heim_integer(&dh_pub_key);
423 if (size != dhbuf.length)
424 krb5_abortx(context, "asn1 internal error");
426 a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
427 a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
431 a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes));
432 if (a->supportedCMSTypes == NULL)
435 ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL,
436 &a->supportedCMSTypes->val,
437 &a->supportedCMSTypes->len);
445 krb5_error_code KRB5_LIB_FUNCTION
446 _krb5_pk_mk_ContentInfo(krb5_context context,
447 const krb5_data *buf,
449 struct ContentInfo *content_info)
453 ret = der_copy_oid(oid, &content_info->contentType);
456 ALLOC(content_info->content, 1);
457 if (content_info->content == NULL)
459 content_info->content->data = malloc(buf->length);
460 if (content_info->content->data == NULL)
462 memcpy(content_info->content->data, buf->data, buf->length);
463 content_info->content->length = buf->length;
467 static krb5_error_code
468 pk_mk_padata(krb5_context context,
469 krb5_pk_init_ctx ctx,
470 const KDC_REQ_BODY *req_body,
474 struct ContentInfo content_info;
478 krb5_data buf, sd_buf;
481 krb5_data_zero(&buf);
482 krb5_data_zero(&sd_buf);
483 memset(&content_info, 0, sizeof(content_info));
485 if (ctx->type == COMPAT_WIN2K) {
490 memset(&ap, 0, sizeof(ap));
492 /* fill in PKAuthenticator */
493 ret = copy_PrincipalName(req_body->sname, &ap.pkAuthenticator.kdcName);
495 free_AuthPack_Win2k(&ap);
496 krb5_clear_error_string(context);
499 ret = copy_Realm(&req_body->realm, &ap.pkAuthenticator.kdcRealm);
501 free_AuthPack_Win2k(&ap);
502 krb5_clear_error_string(context);
506 krb5_us_timeofday(context, &sec, &usec);
507 ap.pkAuthenticator.ctime = sec;
508 ap.pkAuthenticator.cusec = usec;
509 ap.pkAuthenticator.nonce = nonce;
511 ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length,
513 free_AuthPack_Win2k(&ap);
515 krb5_set_error_string(context, "AuthPack_Win2k: %d", ret);
518 if (buf.length != size)
519 krb5_abortx(context, "internal ASN1 encoder error");
521 oid = oid_id_pkcs7_data();
522 } else if (ctx->type == COMPAT_IETF) {
525 memset(&ap, 0, sizeof(ap));
527 ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap);
533 ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret);
536 krb5_set_error_string(context, "AuthPack: %d", ret);
539 if (buf.length != size)
540 krb5_abortx(context, "internal ASN1 encoder error");
542 oid = oid_id_pkauthdata();
544 krb5_abortx(context, "internal pkinit error");
546 ret = _krb5_pk_create_sign(context,
552 krb5_data_free(&buf);
556 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
557 krb5_data_free(&sd_buf);
559 krb5_set_error_string(context,
560 "ContentInfo wrapping of signedData failed");
564 if (ctx->type == COMPAT_WIN2K) {
565 PA_PK_AS_REQ_Win2k winreq;
567 pa_type = KRB5_PADATA_PK_AS_REQ_WIN;
569 memset(&winreq, 0, sizeof(winreq));
571 winreq.signed_auth_pack = buf;
573 ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length,
574 &winreq, &size, ret);
575 free_PA_PK_AS_REQ_Win2k(&winreq);
577 } else if (ctx->type == COMPAT_IETF) {
580 pa_type = KRB5_PADATA_PK_AS_REQ;
582 memset(&req, 0, sizeof(req));
583 req.signedAuthPack = buf;
585 if (ctx->trustedCertifiers) {
587 req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers));
588 if (req.trustedCertifiers == NULL) {
589 krb5_set_error_string(context, "malloc: out of memory");
590 free_PA_PK_AS_REQ(&req);
593 ret = build_edi(context, ctx->id->hx509ctx,
594 ctx->id->anchors, req.trustedCertifiers);
596 krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers");
597 free_PA_PK_AS_REQ(&req);
603 ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length,
606 free_PA_PK_AS_REQ(&req);
609 krb5_abortx(context, "internal pkinit error");
611 krb5_set_error_string(context, "PA-PK-AS-REQ %d", ret);
614 if (buf.length != size)
615 krb5_abortx(context, "Internal ASN1 encoder error");
617 ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length);
621 if (ret == 0 && ctx->type == COMPAT_WIN2K)
622 krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
625 free_ContentInfo(&content_info);
631 krb5_error_code KRB5_LIB_FUNCTION
632 _krb5_pk_mk_padata(krb5_context context,
634 const KDC_REQ_BODY *req_body,
638 krb5_pk_init_ctx ctx = c;
641 win2k_compat = krb5_config_get_bool_default(context, NULL,
649 ctx->require_binding =
650 krb5_config_get_bool_default(context, NULL,
654 "pkinit_win2k_require_binding",
656 ctx->type = COMPAT_WIN2K;
658 ctx->type = COMPAT_IETF;
661 krb5_config_get_bool_default(context, NULL,
665 "pkinit_require_eku",
667 ctx->require_krbtgt_otherName =
668 krb5_config_get_bool_default(context, NULL,
672 "pkinit_require_krbtgt_otherName",
675 ctx->require_hostname_match =
676 krb5_config_get_bool_default(context, NULL,
680 "pkinit_require_hostname_match",
683 ctx->trustedCertifiers =
684 krb5_config_get_bool_default(context, NULL,
688 "pkinit_trustedCertifiers",
691 return pk_mk_padata(context, ctx, req_body, nonce, md);
694 krb5_error_code KRB5_LIB_FUNCTION
695 _krb5_pk_verify_sign(krb5_context context,
698 struct krb5_pk_identity *id,
699 heim_oid *contentType,
701 struct krb5_pk_cert **signer)
703 hx509_certs signer_certs;
708 ret = hx509_cms_verify_signed(id->hx509ctx,
718 _krb5_pk_copy_error(context, id->hx509ctx, ret,
719 "CMS verify signed failed");
723 *signer = calloc(1, sizeof(**signer));
724 if (*signer == NULL) {
725 krb5_clear_error_string(context);
730 ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert);
732 _krb5_pk_copy_error(context, id->hx509ctx, ret,
733 "Failed to get on of the signer certs");
738 hx509_certs_free(&signer_certs);
741 hx509_cert_free((*signer)->cert);
750 static krb5_error_code
751 get_reply_key_win(krb5_context context,
752 const krb5_data *content,
756 ReplyKeyPack_Win2k key_pack;
760 ret = decode_ReplyKeyPack_Win2k(content->data,
765 krb5_set_error_string(context, "PKINIT decoding reply key failed");
766 free_ReplyKeyPack_Win2k(&key_pack);
770 if (key_pack.nonce != nonce) {
771 krb5_set_error_string(context, "PKINIT enckey nonce is wrong");
772 free_ReplyKeyPack_Win2k(&key_pack);
773 return KRB5KRB_AP_ERR_MODIFIED;
776 *key = malloc (sizeof (**key));
778 krb5_set_error_string(context, "PKINIT failed allocating reply key");
779 free_ReplyKeyPack_Win2k(&key_pack);
780 krb5_set_error_string(context, "malloc: out of memory");
784 ret = copy_EncryptionKey(&key_pack.replyKey, *key);
785 free_ReplyKeyPack_Win2k(&key_pack);
787 krb5_set_error_string(context, "PKINIT failed copying reply key");
795 static krb5_error_code
796 get_reply_key(krb5_context context,
797 const krb5_data *content,
798 const krb5_data *req_buffer,
801 ReplyKeyPack key_pack;
805 ret = decode_ReplyKeyPack(content->data,
810 krb5_set_error_string(context, "PKINIT decoding reply key failed");
811 free_ReplyKeyPack(&key_pack);
819 * XXX Verify kp.replyKey is a allowed enctype in the
823 ret = krb5_crypto_init(context, &key_pack.replyKey, 0, &crypto);
825 free_ReplyKeyPack(&key_pack);
829 ret = krb5_verify_checksum(context, crypto, 6,
830 req_buffer->data, req_buffer->length,
831 &key_pack.asChecksum);
832 krb5_crypto_destroy(context, crypto);
834 free_ReplyKeyPack(&key_pack);
839 *key = malloc (sizeof (**key));
841 krb5_set_error_string(context, "PKINIT failed allocating reply key");
842 free_ReplyKeyPack(&key_pack);
843 krb5_set_error_string(context, "malloc: out of memory");
847 ret = copy_EncryptionKey(&key_pack.replyKey, *key);
848 free_ReplyKeyPack(&key_pack);
850 krb5_set_error_string(context, "PKINIT failed copying reply key");
859 static krb5_error_code
860 pk_verify_host(krb5_context context,
862 const krb5_krbhst_info *hi,
863 struct krb5_pk_init_ctx_data *ctx,
864 struct krb5_pk_cert *host)
866 krb5_error_code ret = 0;
868 if (ctx->require_eku) {
869 ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert,
870 oid_id_pkkdcekuoid(), 0);
872 krb5_set_error_string(context, "No PK-INIT KDC EKU in kdc certificate");
876 if (ctx->require_krbtgt_otherName) {
877 hx509_octet_string_list list;
880 ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx,
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);