2 * Copyright (c) 2006 - 2010 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
37 * @page page_ca Hx509 CA functions
39 * See the library functions here: @ref hx509_ca
44 SubjectPublicKeyInfo spki;
48 CertificatePolicies cps;
55 unsigned int serial:1;
56 unsigned int domaincontroller:1;
57 unsigned int xUniqueID:1;
61 HeimPkinitPrincMaxLifeSecs pkinitTicketMaxLife;
62 int pathLenConstraint; /* both for CA and Proxy */
63 CRLDistributionPoints crldp;
64 heim_bit_string subjectUniqueID;
65 heim_bit_string issuerUniqueID;
66 AlgorithmIdentifier *sigalg;
70 * Allocate an to-be-signed certificate object that will be converted
71 * into an certificate.
73 * @param context A hx509 context.
74 * @param tbs returned to-be-signed certicate object, free with
75 * hx509_ca_tbs_free().
77 * @return An hx509 error code, see hx509_get_error_string().
82 HX509_LIB_FUNCTION int HX509_LIB_CALL
83 hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
85 *tbs = calloc(1, sizeof(**tbs));
93 * Free an To Be Signed object.
95 * @param tbs object to free.
100 HX509_LIB_FUNCTION void HX509_LIB_CALL
101 hx509_ca_tbs_free(hx509_ca_tbs *tbs)
103 if (tbs == NULL || *tbs == NULL)
106 free_SubjectPublicKeyInfo(&(*tbs)->spki);
107 free_CertificatePolicies(&(*tbs)->cps);
108 free_PolicyMappings(&(*tbs)->pms);
109 free_GeneralNames(&(*tbs)->san);
110 free_ExtKeyUsage(&(*tbs)->eku);
111 der_free_heim_integer(&(*tbs)->serial);
112 free_CRLDistributionPoints(&(*tbs)->crldp);
113 der_free_bit_string(&(*tbs)->subjectUniqueID);
114 der_free_bit_string(&(*tbs)->issuerUniqueID);
116 hx509_name_free(&(*tbs)->subject);
117 if ((*tbs)->sigalg) {
118 free_AlgorithmIdentifier((*tbs)->sigalg);
119 free((*tbs)->sigalg);
122 memset(*tbs, 0, sizeof(**tbs));
128 * Set the absolute time when the certificate is valid from. If not
129 * set the current time will be used.
131 * @param context A hx509 context.
132 * @param tbs object to be signed.
133 * @param t time the certificated will start to be valid
135 * @return An hx509 error code, see hx509_get_error_string().
140 HX509_LIB_FUNCTION int HX509_LIB_CALL
141 hx509_ca_tbs_set_notBefore(hx509_context context,
150 * Set the absolute time when the certificate is valid to.
152 * @param context A hx509 context.
153 * @param tbs object to be signed.
154 * @param t time when the certificate will expire
156 * @return An hx509 error code, see hx509_get_error_string().
161 HX509_LIB_FUNCTION int HX509_LIB_CALL
162 hx509_ca_tbs_set_notAfter(hx509_context context,
171 * Set the relative time when the certificiate is going to expire.
173 * @param context A hx509 context.
174 * @param tbs object to be signed.
175 * @param delta seconds to the certificate is going to expire.
177 * @return An hx509 error code, see hx509_get_error_string().
182 HX509_LIB_FUNCTION int HX509_LIB_CALL
183 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
187 return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
190 HX509_LIB_FUNCTION int HX509_LIB_CALL
191 hx509_ca_tbs_set_pkinit_max_life(hx509_context context,
195 tbs->pkinitTicketMaxLife = max_life;
199 static const struct units templatebits[] = {
200 { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
201 { "KeyUsage", HX509_CA_TEMPLATE_KU },
202 { "SPKI", HX509_CA_TEMPLATE_SPKI },
203 { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
204 { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
205 { "serial", HX509_CA_TEMPLATE_SERIAL },
206 { "subject", HX509_CA_TEMPLATE_SUBJECT },
207 { "pkinitMaxLife", HX509_CA_TEMPLATE_PKINIT_MAX_LIFE },
212 * Make of template units, use to build flags argument to
213 * hx509_ca_tbs_set_template() with parse_units().
215 * @return an units structure.
220 HX509_LIB_FUNCTION const struct units * HX509_LIB_CALL
221 hx509_ca_tbs_template_units(void)
227 * Initialize the to-be-signed certificate object from a template certificate.
229 * @param context A hx509 context.
230 * @param tbs object to be signed.
231 * @param flags bit field selecting what to copy from the template
233 * @param cert template certificate.
235 * @return An hx509 error code, see hx509_get_error_string().
240 HX509_LIB_FUNCTION int HX509_LIB_CALL
241 hx509_ca_tbs_set_template(hx509_context context,
248 if (flags & HX509_CA_TEMPLATE_SUBJECT) {
250 hx509_name_free(&tbs->subject);
251 ret = hx509_cert_get_subject(cert, &tbs->subject);
253 hx509_set_error_string(context, 0, ret,
254 "Failed to get subject from template");
258 if (flags & HX509_CA_TEMPLATE_SERIAL) {
259 der_free_heim_integer(&tbs->serial);
260 ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
261 tbs->flags.serial = !ret;
263 hx509_set_error_string(context, 0, ret,
264 "Failed to copy serial number");
268 if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
269 tbs->notBefore = hx509_cert_get_notBefore(cert);
270 if (flags & HX509_CA_TEMPLATE_NOTAFTER)
271 tbs->notAfter = hx509_cert_get_notAfter(cert);
272 if (flags & HX509_CA_TEMPLATE_SPKI) {
273 free_SubjectPublicKeyInfo(&tbs->spki);
274 ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
275 tbs->flags.key = !ret;
279 if (flags & HX509_CA_TEMPLATE_KU) {
280 ret = _hx509_cert_get_keyusage(context, cert, &tbs->ku);
284 if (flags & HX509_CA_TEMPLATE_EKU) {
287 ret = _hx509_cert_get_eku(context, cert, &eku);
290 for (i = 0; i < eku.len; i++) {
291 ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
293 free_ExtKeyUsage(&eku);
297 free_ExtKeyUsage(&eku);
299 if (flags & HX509_CA_TEMPLATE_PKINIT_MAX_LIFE) {
302 if ((max_life = hx509_cert_get_pkinit_max_life(context, cert, 0)) > 0)
303 hx509_ca_tbs_set_pkinit_max_life(context, tbs, max_life);
309 * Make the to-be-signed certificate object a CA certificate. If the
310 * pathLenConstraint is negative path length constraint is used.
312 * @param context A hx509 context.
313 * @param tbs object to be signed.
314 * @param pathLenConstraint path length constraint, negative, no
317 * @return An hx509 error code, see hx509_get_error_string().
322 HX509_LIB_FUNCTION int HX509_LIB_CALL
323 hx509_ca_tbs_set_ca(hx509_context context,
325 int pathLenConstraint)
328 tbs->pathLenConstraint = pathLenConstraint;
333 * Make the to-be-signed certificate object a proxy certificate. If the
334 * pathLenConstraint is negative path length constraint is used.
336 * @param context A hx509 context.
337 * @param tbs object to be signed.
338 * @param pathLenConstraint path length constraint, negative, no
341 * @return An hx509 error code, see hx509_get_error_string().
346 HX509_LIB_FUNCTION int HX509_LIB_CALL
347 hx509_ca_tbs_set_proxy(hx509_context context,
349 int pathLenConstraint)
351 tbs->flags.proxy = 1;
352 tbs->pathLenConstraint = pathLenConstraint;
358 * Make the to-be-signed certificate object a windows domain controller certificate.
360 * @param context A hx509 context.
361 * @param tbs object to be signed.
363 * @return An hx509 error code, see hx509_get_error_string().
368 HX509_LIB_FUNCTION int HX509_LIB_CALL
369 hx509_ca_tbs_set_domaincontroller(hx509_context context,
372 tbs->flags.domaincontroller = 1;
377 * Set the subject public key info (SPKI) in the to-be-signed certificate
378 * object. SPKI is the public key and key related parameters in the
381 * @param context A hx509 context.
382 * @param tbs object to be signed.
383 * @param spki subject public key info to use for the to-be-signed certificate object.
385 * @return An hx509 error code, see hx509_get_error_string().
390 HX509_LIB_FUNCTION int HX509_LIB_CALL
391 hx509_ca_tbs_set_spki(hx509_context context,
393 const SubjectPublicKeyInfo *spki)
396 free_SubjectPublicKeyInfo(&tbs->spki);
397 ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
398 tbs->flags.key = !ret;
403 * Set the serial number to use for to-be-signed certificate object.
405 * @param context A hx509 context.
406 * @param tbs object to be signed.
407 * @param serialNumber serial number to use for the to-be-signed
408 * certificate object.
410 * @return An hx509 error code, see hx509_get_error_string().
415 HX509_LIB_FUNCTION int HX509_LIB_CALL
416 hx509_ca_tbs_set_serialnumber(hx509_context context,
418 const heim_integer *serialNumber)
421 der_free_heim_integer(&tbs->serial);
422 ret = der_copy_heim_integer(serialNumber, &tbs->serial);
423 tbs->flags.serial = !ret;
428 * Copy elements of a CSR into a TBS, but only if all of them are authorized.
430 * @param context A hx509 context.
431 * @param tbs object to be signed.
434 * @return An hx509 error code, see hx509_get_error_string().
439 HX509_LIB_FUNCTION int HX509_LIB_CALL
440 hx509_ca_tbs_set_from_csr(hx509_context context,
444 hx509_san_type san_type;
445 heim_oid oid = { 0, 0 };
451 if (hx509_request_count_unauthorized(req)) {
452 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
456 ret = hx509_request_get_ku(context, req, &ku);
457 if (ret == 0 && KeyUsage2int(ku))
458 ret = hx509_ca_tbs_add_ku(context, tbs, ku);
460 for (i = 0; ret == 0; i++) {
463 ret = hx509_request_get_eku(req, i, &s);
465 ret = der_parse_heim_oid(s, ".", &oid);
467 ret = hx509_ca_tbs_add_eku(context, tbs, &oid);
469 if (ret == HX509_NO_ITEM)
472 for (i = 0; ret == 0; i++) {
474 ret = hx509_request_get_san(req, i, &san_type, &s);
476 ret = hx509_ca_tbs_add_san(context, tbs, san_type, s);
478 if (ret == HX509_NO_ITEM)
487 * An an extended key usage to the to-be-signed certificate object.
488 * Duplicates will detected and not added.
490 * @param context A hx509 context.
491 * @param tbs object to be signed.
492 * @param oid extended key usage to add.
494 * @return An hx509 error code, see hx509_get_error_string().
499 HX509_LIB_FUNCTION int HX509_LIB_CALL
500 hx509_ca_tbs_add_ku(hx509_context context,
509 * An an extended key usage to the to-be-signed certificate object.
510 * Duplicates will detected and not added.
512 * @param context A hx509 context.
513 * @param tbs object to be signed.
514 * @param oid extended key usage to add.
516 * @return An hx509 error code, see hx509_get_error_string().
521 HX509_LIB_FUNCTION int HX509_LIB_CALL
522 hx509_ca_tbs_add_eku(hx509_context context,
530 /* search for duplicates */
531 for (i = 0; i < tbs->eku.len; i++) {
532 if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
536 ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
538 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
542 ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
544 hx509_set_error_string(context, 0, ret, "out of memory");
552 * Add a certificate policy to the to-be-signed certificate object. Duplicates
553 * will detected and not added.
555 * @param context A hx509 context.
556 * @param tbs object to be signed.
557 * @param oid policy OID.
558 * @param cps_uri CPS URI to qualify policy with.
559 * @param user_notice user notice display text to qualify policy with.
561 * @return An hx509 error code, see hx509_get_error_string().
566 HX509_LIB_FUNCTION int HX509_LIB_CALL
567 hx509_ca_tbs_add_pol(hx509_context context,
571 const char *user_notice)
573 PolicyQualifierInfos pqis;
574 PolicyQualifierInfo pqi;
575 PolicyInformation pi;
579 /* search for duplicates */
580 for (i = 0; i < tbs->cps.len; i++) {
581 if (der_heim_oid_cmp(oid, &tbs->cps.val[i].policyIdentifier) == 0)
585 memset(&pi, 0, sizeof(pi));
586 memset(&pqi, 0, sizeof(pqi));
587 memset(&pqis, 0, sizeof(pqis));
589 pi.policyIdentifier = *oid;
593 uri.length = strlen(cps_uri);
594 uri.data = (void *)(uintptr_t)cps_uri;
595 pqi.policyQualifierId = asn1_oid_id_pkix_qt_cps;
597 ASN1_MALLOC_ENCODE(CPSuri,
599 pqi.qualifier.length,
602 ret = add_PolicyQualifierInfos(&pqis, &pqi);
603 free_heim_any(&pqi.qualifier);
606 if (ret == 0 && user_notice) {
610 dt.element = choice_DisplayText_utf8String;
611 dt.u.utf8String = (void *)(uintptr_t)user_notice;
612 un.explicitText = &dt;
615 pqi.policyQualifierId = asn1_oid_id_pkix_qt_unotice;
616 ASN1_MALLOC_ENCODE(UserNotice,
618 pqi.qualifier.length,
621 ret = add_PolicyQualifierInfos(&pqis, &pqi);
622 free_heim_any(&pqi.qualifier);
626 pi.policyQualifiers = pqis.len ? &pqis : 0;
629 ret = add_CertificatePolicies(&tbs->cps, &pi);
631 free_PolicyQualifierInfos(&pqis);
636 * Add a certificate policy mapping to the to-be-signed certificate object.
637 * Duplicates will detected and not added.
639 * @param context A hx509 context.
640 * @param tbs object to be signed.
641 * @param issuer issuerDomainPolicy policy OID.
642 * @param subject subjectDomainPolicy policy OID.
644 * @return An hx509 error code, see hx509_get_error_string().
649 HX509_LIB_FUNCTION int HX509_LIB_CALL
650 hx509_ca_tbs_add_pol_mapping(hx509_context context,
652 const heim_oid *issuer,
653 const heim_oid *subject)
658 /* search for duplicates */
659 for (i = 0; i < tbs->pms.len; i++) {
660 PolicyMapping *pmp = &tbs->pms.val[i];
661 if (der_heim_oid_cmp(issuer, &pmp->issuerDomainPolicy) == 0 &&
662 der_heim_oid_cmp(subject, &pmp->subjectDomainPolicy) == 0)
666 memset(&pm, 0, sizeof(pm));
667 pm.issuerDomainPolicy = *issuer;
668 pm.subjectDomainPolicy = *subject;
669 return add_PolicyMappings(&tbs->pms, &pm);
673 * Add CRL distribution point URI to the to-be-signed certificate
676 * @param context A hx509 context.
677 * @param tbs object to be signed.
678 * @param uri uri to the CRL.
679 * @param issuername name of the issuer.
681 * @return An hx509 error code, see hx509_get_error_string().
686 HX509_LIB_FUNCTION int HX509_LIB_CALL
687 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
690 hx509_name issuername)
692 DistributionPointName dpn;
693 DistributionPoint dp;
694 GeneralNames crlissuer;
699 memset(&dp, 0, sizeof(dp));
700 memset(&gn, 0, sizeof(gn));
701 memset(&ign, 0, sizeof(ign));
702 memset(&in, 0, sizeof(in));
703 gn.element = choice_GeneralName_uniformResourceIdentifier;
704 gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
705 gn.u.uniformResourceIdentifier.length = strlen(uri);
706 dpn.element = choice_DistributionPointName_fullName;
707 dpn.u.fullName.len = 1;
708 dpn.u.fullName.val = &gn;
709 dp.distributionPoint = &dpn;
712 ign.element = choice_GeneralName_directoryName;
713 ret = hx509_name_to_Name(issuername, &ign.u.directoryName);
715 hx509_set_error_string(context, 0, ret, "out of memory");
719 crlissuer.val = &ign;
720 dp.cRLIssuer = &crlissuer;
723 ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
725 free_Name(&ign.u.directoryName);
728 hx509_set_error_string(context, 0, ret, "out of memory");
733 * Add Subject Alternative Name otherName to the to-be-signed
734 * certificate object.
736 * @param context A hx509 context.
737 * @param tbs object to be signed.
738 * @param oid the oid of the OtherName.
739 * @param os data in the other name.
741 * @return An hx509 error code, see hx509_get_error_string().
746 HX509_LIB_FUNCTION int HX509_LIB_CALL
747 hx509_ca_tbs_add_san_otherName(hx509_context context,
750 const heim_octet_string *os)
754 memset(&gn, 0, sizeof(gn));
755 gn.element = choice_GeneralName_otherName;
756 gn.u.otherName.type_id = *oid;
757 gn.u.otherName.value = *os;
759 return add_GeneralNames(&tbs->san, &gn);
764 dequote_strndup(hx509_context context, const char *in, size_t len, char **out)
770 if ((s = malloc(len + 1)) == NULL) {
771 hx509_set_error_string(context, 0, ENOMEM, "malloc: out of memory");
775 for (k = i = 0; i < len; i++) {
778 case 't': s[k++] = '\t'; break;
779 case 'b': s[k++] = '\b'; break;
780 case 'n': s[k++] = '\n'; break;
782 for (i++; i < len; i++) {
785 if (in[i++] == '\\' && in[i] == '0')
787 hx509_set_error_string(context, 0,
788 HX509_PARSING_NAME_FAILED,
789 "embedded NULs not supported in "
792 return HX509_PARSING_NAME_FAILED;
796 hx509_set_error_string(context, 0,
797 HX509_PARSING_NAME_FAILED,
798 "trailing unquoted backslashes not "
799 "allowed in PKINIT SANs");
801 return HX509_PARSING_NAME_FAILED;
802 default: s[k++] = in[i]; break;
815 _hx509_make_pkinit_san(hx509_context context,
816 const char *principal,
817 heim_octet_string *os)
825 memset(&p, 0, sizeof(p));
827 /* Parse principal */
829 const char *str, *str_start;
832 /* Count number of components */
834 for (str = principal; *str != '\0' && *str != '@'; str++) {
836 if (str[1] == '\0') {
837 ret = HX509_PARSING_NAME_FAILED;
838 hx509_set_error_string(context, 0, ret,
839 "trailing \\ in principal name");
843 } else if(*str == '/') {
845 } else if(*str == '@') {
850 /* Note that we allow the realm to be empty */
851 ret = HX509_PARSING_NAME_FAILED;
852 hx509_set_error_string(context, 0, ret, "Missing @ in principal");
856 p.principalName.name_string.val =
857 calloc(n, sizeof(*p.principalName.name_string.val));
858 if (p.principalName.name_string.val == NULL) {
860 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
863 p.principalName.name_string.len = n;
864 p.principalName.name_type = KRB5_NT_PRINCIPAL;
866 for (i = 0, str_start = str = principal; *str != '\0'; str++) {
869 } else if(*str == '/') {
870 /* Note that we allow components to be empty */
871 ret = dequote_strndup(context, str_start, str - str_start,
872 &p.principalName.name_string.val[i++]);
876 } else if(*str == '@') {
877 ret = dequote_strndup(context, str_start, str - str_start,
878 &p.principalName.name_string.val[i++]);
880 ret = dequote_strndup(context, str + 1, strlen(str + 1), &p.realm);
888 ASN1_MALLOC_ENCODE(KRB5PrincipalName, os->data, os->length, &p, &size, ret);
890 hx509_set_error_string(context, 0, ret, "Out of memory");
893 if (size != os->length)
894 _hx509_abort("internal ASN.1 encoder error");
897 free_KRB5PrincipalName(&p);
902 add_ia5string_san(hx509_context context,
908 heim_octet_string os;
912 ustring.data = (void *)(uintptr_t)string;
913 ustring.length = strlen(string);
918 ASN1_MALLOC_ENCODE(SRVName, os.data, os.length, &ustring, &size, ret);
920 hx509_set_error_string(context, 0, ret, "Out of memory");
923 if (size != os.length)
924 _hx509_abort("internal ASN.1 encoder error");
926 ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os);
932 * Add DNSSRV Subject Alternative Name to the to-be-signed certificate object.
934 * @param context A hx509 context.
935 * @param tbs object to be signed.
936 * @param dnssrv An ASCII string of the for _Service.Name.
938 * @return An hx509 error code, see hx509_get_error_string().
943 HX509_LIB_FUNCTION int HX509_LIB_CALL
944 hx509_ca_tbs_add_san_dnssrv(hx509_context context,
950 /* Minimal DNSSRV input validation */
951 if (dnssrv == 0 || dnssrv[0] != '_') {
952 hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
955 for (i = 1, len = strlen(dnssrv); i < len; i++) {
956 if (dnssrv[i] == '.' && dnssrv[i + 1] != '\0')
960 hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
964 return add_ia5string_san(context, tbs,
965 &asn1_oid_id_pkix_on_dnsSRV, dnssrv);
969 * Add Kerberos Subject Alternative Name to the to-be-signed
970 * certificate object. The principal string is a UTF8 string.
972 * @param context A hx509 context.
973 * @param tbs object to be signed.
974 * @param principal Kerberos principal to add to the certificate.
976 * @return An hx509 error code, see hx509_get_error_string().
981 HX509_LIB_FUNCTION int HX509_LIB_CALL
982 hx509_ca_tbs_add_san_pkinit(hx509_context context,
984 const char *principal)
986 heim_octet_string os;
989 ret = _hx509_make_pkinit_san(context, principal, &os);
991 ret = hx509_ca_tbs_add_san_otherName(context, tbs,
992 &asn1_oid_id_pkinit_san, &os);
1002 add_utf8_san(hx509_context context,
1004 const heim_oid *oid,
1007 const PKIXXmppAddr ustring = (const PKIXXmppAddr)(uintptr_t)string;
1008 heim_octet_string os;
1015 ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
1017 hx509_set_error_string(context, 0, ret, "Out of memory");
1020 if (size != os.length)
1021 _hx509_abort("internal ASN.1 encoder error");
1023 ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os);
1029 * Add Microsoft UPN Subject Alternative Name to the to-be-signed
1030 * certificate object. The principal string is a UTF8 string.
1032 * @param context A hx509 context.
1033 * @param tbs object to be signed.
1034 * @param principal Microsoft UPN string.
1036 * @return An hx509 error code, see hx509_get_error_string().
1041 HX509_LIB_FUNCTION int HX509_LIB_CALL
1042 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
1044 const char *principal)
1046 return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
1050 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
1051 * certificate object. The jid is an UTF8 string.
1053 * @param context A hx509 context.
1054 * @param tbs object to be signed.
1055 * @param jid string of an a jabber id in UTF8.
1057 * @return An hx509 error code, see hx509_get_error_string().
1062 HX509_LIB_FUNCTION int HX509_LIB_CALL
1063 hx509_ca_tbs_add_san_jid(hx509_context context,
1067 return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
1072 * Add a Subject Alternative Name hostname to to-be-signed certificate
1073 * object. A domain match starts with ., an exact match does not.
1075 * Example of a an domain match: .domain.se matches the hostname
1078 * @param context A hx509 context.
1079 * @param tbs object to be signed.
1080 * @param dnsname a hostame.
1082 * @return An hx509 error code, see hx509_get_error_string().
1087 HX509_LIB_FUNCTION int HX509_LIB_CALL
1088 hx509_ca_tbs_add_san_hostname(hx509_context context,
1090 const char *dnsname)
1094 memset(&gn, 0, sizeof(gn));
1095 gn.element = choice_GeneralName_dNSName;
1096 gn.u.dNSName.data = rk_UNCONST(dnsname);
1097 gn.u.dNSName.length = strlen(dnsname);
1099 return add_GeneralNames(&tbs->san, &gn);
1103 * Add a Subject Alternative Name rfc822 (email address) to
1104 * to-be-signed certificate object.
1106 * @param context A hx509 context.
1107 * @param tbs object to be signed.
1108 * @param rfc822Name a string to a email address.
1110 * @return An hx509 error code, see hx509_get_error_string().
1115 HX509_LIB_FUNCTION int HX509_LIB_CALL
1116 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
1118 const char *rfc822Name)
1122 memset(&gn, 0, sizeof(gn));
1123 gn.element = choice_GeneralName_rfc822Name;
1124 gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
1125 gn.u.rfc822Name.length = strlen(rfc822Name);
1127 return add_GeneralNames(&tbs->san, &gn);
1131 * PermanentIdentifier is one SAN for naming devices with TPMs after their
1132 * endorsement keys or EK certificates. See TPM 2.0 Keys for Device Identity
1133 * and Attestation, Version 1.00, Revision 2, 9/17/2020 (DRAFT).
1135 * The text on the form of permanent identifiers for TPM endorsement keys sans
1136 * certificates is clearly problematic, saying: "When the TPM does not have an
1137 * EK certificate, the identifierValue is a digest of a concatenation of the
1138 * UTF8 string “EkPubkey” (terminating NULL not included) with the binary EK
1139 * public key", but since arbitrary binary is not necessarily valid UTF-8...
1140 * and since NULs embedded in UTF-8 might be OK in some contexts but really
1141 * isn't in C (and Heimdal's ASN.1 compiler does not allow NULs in the
1142 * middle of strings)... That just cannot be correct. Since elsewhere the TCG
1143 * specs use the hex encoding of the SHA-256 digest of the DER encoding of
1144 * public keys, that's what we should support in Heimdal, and maybe send in a
1147 * Also, even where one should use hex encoding of the SHA-256 digest of the
1148 * DER encoding of public keys, how should the public keys be represented?
1149 * Presumably as SPKIs, with all the required parameters and no more.
1153 * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed
1154 * certificate object. The permanent identifier form for TPM endorsement key
1155 * certificates is the hex encoding of the SHA-256 digest of the DER encoding
1156 * of the certificate. The permanent identifier form for TPM endorsement keys
1157 * are of the form "EkPubkey<public-key>", where the form of <public-key> is
1158 * not well specified at this point. It is the caller's responsibility to
1159 * format the identifierValue.
1161 * @param context A hx509 context.
1162 * @param tbs object to be signed.
1163 * @param str permanent identifier name in the form "[<assigner-oid>]:[<id>]".
1164 * @param assigner The OID of an assigner.
1166 * @return An hx509 error code, see hx509_get_error_string().
1171 HX509_LIB_FUNCTION int HX509_LIB_CALL
1172 hx509_ca_tbs_add_san_permanentIdentifier_string(hx509_context context,
1176 const heim_oid *found = NULL;
1178 const char *oidstr, *id;
1182 if ((freeme = strdup(str)) == NULL)
1183 return hx509_enomem(context);
1186 p = strchr(freeme, ':');
1188 hx509_set_error_string(context, 0, EINVAL,
1189 "Invalid PermanentIdentifier string (should be \"[<oid>]:[<id>]\")",
1198 if (oidstr[0] != '\0') {
1199 ret = der_find_heim_oid_by_name(oidstr, &found);
1201 ret = der_parse_heim_oid(oidstr, " .", &oid);
1206 ret = hx509_ca_tbs_add_san_permanentIdentifier(context, tbs, id, found);
1214 * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed
1215 * certificate object. The permanent identifier form for TPM endorsement key
1216 * certificates is the hex encoding of the SHA-256 digest of the DER encoding
1217 * of the certificate. The permanent identifier form for TPM endorsement keys
1218 * are of the form "EkPubkey<public-key>", where the form of <public-key> is
1219 * not well specified at this point. It is the caller's responsibility to
1220 * format the identifierValue.
1222 * @param context A hx509 context.
1223 * @param tbs object to be signed.
1224 * @param identifierValue The permanent identifier name.
1225 * @param assigner The OID of an assigner.
1227 * @return An hx509 error code, see hx509_get_error_string().
1232 HX509_LIB_FUNCTION int HX509_LIB_CALL
1233 hx509_ca_tbs_add_san_permanentIdentifier(hx509_context context,
1235 const char *identifierValue,
1236 const heim_oid *assigner)
1238 PermanentIdentifier pi;
1239 heim_utf8_string s = (void *)(uintptr_t)identifierValue;
1240 heim_octet_string os;
1244 pi.identifierValue = &s;
1245 pi.assigner = (heim_oid*)(uintptr_t)assigner;
1249 ASN1_MALLOC_ENCODE(PermanentIdentifier, os.data, os.length, &pi, &size,
1252 hx509_set_error_string(context, 0, ret, "Out of memory");
1255 if (size != os.length)
1256 _hx509_abort("internal ASN.1 encoder error");
1258 ret = hx509_ca_tbs_add_san_otherName(context, tbs,
1259 &asn1_oid_id_pkix_on_permanentIdentifier,
1266 * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed
1267 * certificate object.
1269 * @param context A hx509 context.
1270 * @param tbs object to be signed.
1271 * @param str a string of the form "<oid>:<serial>".
1272 * @param hwserial The serial number.
1274 * @return An hx509 error code, see hx509_get_error_string().
1279 HX509_LIB_FUNCTION int HX509_LIB_CALL
1280 hx509_ca_tbs_add_san_hardwareModuleName_string(hx509_context context,
1284 const heim_oid *found = NULL;
1286 const char *oidstr, *sno;
1290 if ((freeme = strdup(str)) == NULL)
1291 return hx509_enomem(context);
1294 p = strchr(freeme, ':');
1296 hx509_set_error_string(context, 0, EINVAL,
1297 "Invalid HardwareModuleName string (should be "
1298 "\"<oid>:<serial>\")",
1307 if (oidstr[0] == '\0') {
1308 found = &asn1_oid_tcg_tpm20;
1310 ret = der_find_heim_oid_by_name(oidstr, &found);
1312 ret = der_parse_heim_oid(oidstr, " .", &oid);
1318 hx509_set_error_string(context, 0, EINVAL,
1319 "Could not resolve or parse OID \"%s\"",
1324 ret = hx509_ca_tbs_add_san_hardwareModuleName(context, tbs, found, sno);
1332 * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed
1333 * certificate object.
1335 * @param context A hx509 context.
1336 * @param tbs object to be signed.
1337 * @param hwtype The hardwar module type (e.g., `&asn1_oid_tcg_tpm20').
1338 * @param hwserial The serial number.
1340 * @return An hx509 error code, see hx509_get_error_string().
1345 HX509_LIB_FUNCTION int HX509_LIB_CALL
1346 hx509_ca_tbs_add_san_hardwareModuleName(hx509_context context,
1348 const heim_oid *hwtype,
1349 const char *hwserial)
1351 HardwareModuleName hm;
1352 heim_octet_string os;
1356 hm.hwType = *hwtype;
1357 hm.hwSerialNum.data = (void *)(uintptr_t)hwserial;
1358 hm.hwSerialNum.length = strlen(hwserial);
1362 ASN1_MALLOC_ENCODE(HardwareModuleName, os.data, os.length, &hm, &size,
1365 hx509_set_error_string(context, 0, ret, "Out of memory");
1368 if (size != os.length)
1369 _hx509_abort("internal ASN.1 encoder error");
1371 ret = hx509_ca_tbs_add_san_otherName(context, tbs,
1372 &asn1_oid_id_on_hardwareModuleName,
1379 * Add a Subject Alternative Name of the given type to the
1380 * to-be-signed certificate object.
1382 * @param context A hx509 context.
1383 * @param tbs object to be signed.
1384 * @param rfc822Name a string to a email address.
1386 * @return An hx509 error code, see hx509_get_error_string().
1391 HX509_LIB_FUNCTION int HX509_LIB_CALL
1392 hx509_ca_tbs_add_san(hx509_context context,
1394 hx509_san_type type,
1398 case HX509_SAN_TYPE_EMAIL:
1399 return hx509_ca_tbs_add_san_rfc822name(context, tbs, s);
1400 case HX509_SAN_TYPE_DNSNAME:
1401 return hx509_ca_tbs_add_san_hostname(context, tbs, s);
1402 case HX509_SAN_TYPE_DN:
1404 case HX509_SAN_TYPE_REGISTERED_ID:
1406 case HX509_SAN_TYPE_XMPP:
1407 return hx509_ca_tbs_add_san_jid(context, tbs, s);
1408 case HX509_SAN_TYPE_PKINIT:
1409 return hx509_ca_tbs_add_san_pkinit(context, tbs, s);
1410 case HX509_SAN_TYPE_MS_UPN:
1411 return hx509_ca_tbs_add_san_ms_upn(context, tbs, s);
1418 * Set the subject name of a to-be-signed certificate object.
1420 * @param context A hx509 context.
1421 * @param tbs object to be signed.
1422 * @param subject the name to set a subject.
1424 * @return An hx509 error code, see hx509_get_error_string().
1429 HX509_LIB_FUNCTION int HX509_LIB_CALL
1430 hx509_ca_tbs_set_subject(hx509_context context,
1435 hx509_name_free(&tbs->subject);
1436 return hx509_name_copy(context, subject, &tbs->subject);
1440 * Set the issuerUniqueID and subjectUniqueID
1442 * These are only supposed to be used considered with version 2
1443 * certificates, replaced by the two extensions SubjectKeyIdentifier
1444 * and IssuerKeyIdentifier. This function is to allow application
1445 * using legacy protocol to issue them.
1447 * @param context A hx509 context.
1448 * @param tbs object to be signed.
1449 * @param issuerUniqueID to be set
1450 * @param subjectUniqueID to be set
1452 * @return An hx509 error code, see hx509_get_error_string().
1457 HX509_LIB_FUNCTION int HX509_LIB_CALL
1458 hx509_ca_tbs_set_unique(hx509_context context,
1460 const heim_bit_string *subjectUniqueID,
1461 const heim_bit_string *issuerUniqueID)
1465 der_free_bit_string(&tbs->subjectUniqueID);
1466 der_free_bit_string(&tbs->issuerUniqueID);
1468 if (subjectUniqueID) {
1469 ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
1474 if (issuerUniqueID) {
1475 ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
1484 * Expand the the subject name in the to-be-signed certificate object
1485 * using hx509_name_expand().
1487 * @param context A hx509 context.
1488 * @param tbs object to be signed.
1489 * @param env environment variable to expand variables in the subject
1490 * name, see hx509_env_init().
1492 * @return An hx509 error code, see hx509_get_error_string().
1497 HX509_LIB_FUNCTION int HX509_LIB_CALL
1498 hx509_ca_tbs_subject_expand(hx509_context context,
1502 return hx509_name_expand(context, tbs->subject, env);
1506 * Get the name of a to-be-signed certificate object.
1508 * @param context A hx509 context.
1509 * @param tbs object to be signed.
1511 * @return An hx509 name.
1516 HX509_LIB_FUNCTION hx509_name HX509_LIB_CALL
1517 hx509_ca_tbs_get_name(hx509_ca_tbs tbs)
1519 return tbs->subject;
1523 * Set signature algorithm on the to be signed certificate
1525 * @param context A hx509 context.
1526 * @param tbs object to be signed.
1527 * @param sigalg signature algorithm to use
1529 * @return An hx509 error code, see hx509_get_error_string().
1534 HX509_LIB_FUNCTION int HX509_LIB_CALL
1535 hx509_ca_tbs_set_signature_algorithm(hx509_context context,
1537 const AlgorithmIdentifier *sigalg)
1541 tbs->sigalg = calloc(1, sizeof(*tbs->sigalg));
1542 if (tbs->sigalg == NULL) {
1543 hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
1546 ret = copy_AlgorithmIdentifier(sigalg, tbs->sigalg);
1560 add_extension(hx509_context context,
1561 TBSCertificate *tbsc,
1563 const heim_oid *oid,
1564 const heim_octet_string *data)
1569 memset(&ext, 0, sizeof(ext));
1571 ext.critical = critical_flag;
1572 ret = der_copy_oid(oid, &ext.extnID);
1574 hx509_set_error_string(context, 0, ret, "Out of memory");
1577 ret = der_copy_octet_string(data, &ext.extnValue);
1579 hx509_set_error_string(context, 0, ret, "Out of memory");
1582 ret = add_Extensions(tbsc->extensions, &ext);
1584 hx509_set_error_string(context, 0, ret, "Out of memory");
1588 free_Extension(&ext);
1593 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
1599 ret = copy_Name(issuer, subject);
1601 hx509_set_error_string(context, 0, ret,
1602 "Failed to copy subject name");
1607 ret = asprintf(&tstr, "ts-%lu", (unsigned long)t);
1608 if (ret == -1 || tstr == NULL) {
1609 hx509_set_error_string(context, 0, ENOMEM,
1610 "Failed to copy subject name");
1613 /* prefix with CN=<ts>,...*/
1614 ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
1622 ca_sign(hx509_context context,
1624 hx509_private_key signer,
1625 const AuthorityKeyIdentifier *ai,
1626 const Name *issuername,
1627 hx509_cert *certificate)
1629 heim_error_t error = NULL;
1630 heim_octet_string data;
1632 TBSCertificate *tbsc;
1635 const AlgorithmIdentifier *sigalg;
1639 sigalg = tbs->sigalg;
1641 sigalg = _hx509_crypto_default_sig_alg;
1643 memset(&c, 0, sizeof(c));
1646 * Default values are: Valid since 24h ago, valid one year into
1647 * the future, KeyUsage digitalSignature and keyEncipherment set,
1648 * and keyCertSign for CA certificates.
1650 notBefore = tbs->notBefore;
1652 notBefore = time(NULL) - 3600 * 24;
1653 notAfter = tbs->notAfter;
1655 notAfter = time(NULL) + 3600 * 24 * 365;
1657 if (tbs->flags.ca) {
1658 tbs->ku.keyCertSign = 1;
1659 tbs->ku.cRLSign = 1;
1660 } else if (KeyUsage2int(tbs->ku) == 0) {
1661 tbs->ku.digitalSignature = 1;
1662 tbs->ku.keyEncipherment = 1;
1669 tbsc = &c.tbsCertificate;
1671 /* Default subject Name to empty */
1672 if (tbs->subject == NULL &&
1673 (ret = hx509_empty_name(context, &tbs->subject)))
1677 if (tbs->flags.key == 0) {
1679 hx509_set_error_string(context, 0, ret, "No public key set");
1683 * Don't put restrictions on proxy certificate's subject name, it
1684 * will be generated below.
1686 if (!tbs->flags.proxy) {
1687 if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1688 hx509_set_error_string(context, 0, EINVAL,
1689 "Empty subject and no SubjectAltNames");
1693 if (tbs->flags.ca && tbs->flags.proxy) {
1694 hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1695 "at the same time");
1698 if (tbs->flags.proxy) {
1699 if (tbs->san.len > 0) {
1700 hx509_set_error_string(context, 0, EINVAL,
1701 "Proxy certificate is not allowed "
1702 "to have SubjectAltNames");
1707 /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1708 tbsc->version = calloc(1, sizeof(*tbsc->version));
1709 if (tbsc->version == NULL) {
1711 hx509_set_error_string(context, 0, ret, "Out of memory");
1714 *tbsc->version = rfc3280_version_3;
1715 /* serialNumber CertificateSerialNumber, */
1716 if (tbs->flags.serial) {
1717 ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1719 hx509_set_error_string(context, 0, ret, "Out of memory");
1724 * If no explicit serial number is specified, 20 random bytes should be
1725 * sufficiently collision resistant. Since the serial number must be a
1726 * positive integer, ensure minimal ASN.1 DER form by forcing the high
1727 * bit off and the next bit on (thus avoiding an all zero first octet).
1729 tbsc->serialNumber.length = 20;
1730 tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1731 if (tbsc->serialNumber.data == NULL){
1733 hx509_set_error_string(context, 0, ret, "Out of memory");
1736 RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1737 ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1738 ((unsigned char *)tbsc->serialNumber.data)[0] |= 0x40;
1740 /* signature AlgorithmIdentifier, */
1741 ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1743 hx509_set_error_string(context, 0, ret, "Failed to copy signature alg");
1748 ret = copy_Name(issuername, &tbsc->issuer);
1750 ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1752 hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1755 /* validity Validity, */
1758 * From RFC 5280, section 4.1.2.5:
1760 * CAs conforming to this profile MUST always encode certificate
1761 * validity dates through the year 2049 as UTCTime; certificate validity
1762 * dates in 2050 or later MUST be encoded as GeneralizedTime.
1763 * Conforming applications MUST be able to process validity dates that
1764 * are encoded in either UTCTime or GeneralizedTime.
1766 * 2524608000 is seconds since the epoch for 2050-01-01T00:00:00Z.
1768 * Both, ...u.generalTime and ...u..utcTime are time_t.
1770 if (notBefore < 1 || (int64_t)notBefore < 2524608000)
1771 tbsc->validity.notBefore.element = choice_Time_utcTime;
1773 tbsc->validity.notBefore.element = choice_Time_generalTime;
1774 tbsc->validity.notBefore.u.generalTime = notBefore;
1776 if (notAfter < 1 || (int64_t)notAfter < 2524608000)
1777 tbsc->validity.notAfter.element = choice_Time_utcTime;
1779 tbsc->validity.notAfter.element = choice_Time_generalTime;
1780 tbsc->validity.notAfter.u.generalTime = notAfter;
1783 if (tbs->flags.proxy) {
1784 ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1788 ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1790 hx509_set_error_string(context, 0, ret,
1791 "Failed to copy subject name");
1795 /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1796 ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1798 hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1801 /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1802 if (tbs->issuerUniqueID.length) {
1803 tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1804 if (tbsc->issuerUniqueID == NULL) {
1806 hx509_set_error_string(context, 0, ret, "Out of memory");
1809 ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1811 hx509_set_error_string(context, 0, ret, "Out of memory");
1815 /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1816 if (tbs->subjectUniqueID.length) {
1817 tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1818 if (tbsc->subjectUniqueID == NULL) {
1820 hx509_set_error_string(context, 0, ret, "Out of memory");
1824 ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1826 hx509_set_error_string(context, 0, ret, "Out of memory");
1831 /* extensions [3] EXPLICIT Extensions OPTIONAL */
1832 tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1833 if (tbsc->extensions == NULL) {
1835 hx509_set_error_string(context, 0, ret, "Out of memory");
1839 /* Add the text BMP string Domaincontroller to the cert */
1840 if (tbs->flags.domaincontroller) {
1841 data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1842 "\x00\x61\x00\x69\x00\x6e\x00\x43"
1843 "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1844 "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1848 ret = add_extension(context, tbsc, 0,
1849 &asn1_oid_id_ms_cert_enroll_domaincontroller,
1856 if (KeyUsage2int(tbs->ku) > 0) {
1857 ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length,
1858 &tbs->ku, &size, ret);
1860 hx509_set_error_string(context, 0, ret, "Out of memory");
1863 if (size != data.length)
1864 _hx509_abort("internal ASN.1 encoder error");
1865 ret = add_extension(context, tbsc, 1,
1866 &asn1_oid_id_x509_ce_keyUsage, &data);
1872 /* Add ExtendedKeyUsage */
1873 if (tbs->eku.len > 0) {
1874 ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1875 &tbs->eku, &size, ret);
1877 hx509_set_error_string(context, 0, ret, "Out of memory");
1880 if (size != data.length)
1881 _hx509_abort("internal ASN.1 encoder error");
1882 ret = add_extension(context, tbsc, 1,
1883 &asn1_oid_id_x509_ce_extKeyUsage, &data);
1889 /* Add Subject Alternative Name */
1890 if (tbs->san.len > 0) {
1891 ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1892 &tbs->san, &size, ret);
1894 hx509_set_error_string(context, 0, ret, "Out of memory");
1897 if (size != data.length)
1898 _hx509_abort("internal ASN.1 encoder error");
1900 /* The SAN extension is critical if the subject Name is empty */
1901 ret = add_extension(context, tbsc, hx509_name_is_null_p(tbs->subject),
1902 &asn1_oid_id_x509_ce_subjectAltName, &data);
1908 /* Add Authority Key Identifier */
1910 ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1913 hx509_set_error_string(context, 0, ret, "Out of memory");
1916 if (size != data.length)
1917 _hx509_abort("internal ASN.1 encoder error");
1918 ret = add_extension(context, tbsc, 0,
1919 &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1926 /* Add Subject Key Identifier */
1928 SubjectKeyIdentifier si;
1929 unsigned char hash[SHA_DIGEST_LENGTH];
1934 ctx = EVP_MD_CTX_create();
1935 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1936 EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1937 tbs->spki.subjectPublicKey.length / 8);
1938 EVP_DigestFinal_ex(ctx, hash, NULL);
1939 EVP_MD_CTX_destroy(ctx);
1943 si.length = sizeof(hash);
1945 ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1948 hx509_set_error_string(context, 0, ret, "Out of memory");
1951 if (size != data.length)
1952 _hx509_abort("internal ASN.1 encoder error");
1953 ret = add_extension(context, tbsc, 0,
1954 &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1961 /* Add BasicConstraints */
1963 BasicConstraints bc;
1966 memset(&bc, 0, sizeof(bc));
1968 if (tbs->flags.ca) {
1970 if (tbs->pathLenConstraint >= 0) {
1971 path = tbs->pathLenConstraint;
1972 bc.pathLenConstraint = &path;
1976 ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1979 hx509_set_error_string(context, 0, ret, "Out of memory");
1982 if (size != data.length)
1983 _hx509_abort("internal ASN.1 encoder error");
1984 /* Critical if this is a CA */
1985 ret = add_extension(context, tbsc, tbs->flags.ca,
1986 &asn1_oid_id_x509_ce_basicConstraints,
1994 if (tbs->flags.proxy) {
1997 memset(&info, 0, sizeof(info));
1999 if (tbs->pathLenConstraint >= 0) {
2000 info.pCPathLenConstraint =
2001 malloc(sizeof(*info.pCPathLenConstraint));
2002 if (info.pCPathLenConstraint == NULL) {
2004 hx509_set_error_string(context, 0, ret, "Out of memory");
2007 *info.pCPathLenConstraint = tbs->pathLenConstraint;
2010 ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
2011 &info.proxyPolicy.policyLanguage);
2013 free_ProxyCertInfo(&info);
2014 hx509_set_error_string(context, 0, ret, "Out of memory");
2018 ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
2020 free_ProxyCertInfo(&info);
2022 hx509_set_error_string(context, 0, ret, "Out of memory");
2025 if (size != data.length)
2026 _hx509_abort("internal ASN.1 encoder error");
2027 ret = add_extension(context, tbsc, 0,
2028 &asn1_oid_id_pkix_pe_proxyCertInfo,
2035 /* Add CRL distribution point */
2036 if (tbs->crldp.len) {
2037 ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
2038 &tbs->crldp, &size, ret);
2040 hx509_set_error_string(context, 0, ret, "Out of memory");
2043 if (size != data.length)
2044 _hx509_abort("internal ASN.1 encoder error");
2045 ret = add_extension(context, tbsc, FALSE,
2046 &asn1_oid_id_x509_ce_cRLDistributionPoints,
2053 /* Add CertificatePolicies */
2055 ASN1_MALLOC_ENCODE(CertificatePolicies, data.data, data.length,
2056 &tbs->cps, &size, ret);
2058 hx509_set_error_string(context, 0, ret, "Out of memory");
2061 if (size != data.length)
2062 _hx509_abort("internal ASN.1 encoder error");
2063 ret = add_extension(context, tbsc, FALSE,
2064 &asn1_oid_id_x509_ce_certificatePolicies, &data);
2070 /* Add PolicyMappings */
2072 ASN1_MALLOC_ENCODE(PolicyMappings, data.data, data.length,
2073 &tbs->pms, &size, ret);
2075 hx509_set_error_string(context, 0, ret, "Out of memory");
2078 if (size != data.length)
2079 _hx509_abort("internal ASN.1 encoder error");
2080 ret = add_extension(context, tbsc, FALSE,
2081 &asn1_oid_id_x509_ce_policyMappings, &data);
2087 /* Add Heimdal PKINIT ticket max life extension */
2088 if (tbs->pkinitTicketMaxLife > 0) {
2089 ASN1_MALLOC_ENCODE(HeimPkinitPrincMaxLifeSecs, data.data, data.length,
2090 &tbs->pkinitTicketMaxLife, &size, ret);
2092 hx509_set_error_string(context, 0, ret, "Out of memory");
2095 if (size != data.length)
2096 _hx509_abort("internal ASN.1 encoder error");
2097 ret = add_extension(context, tbsc, FALSE,
2098 &asn1_oid_id_heim_ce_pkinit_princ_max_life, &data);
2104 ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
2106 hx509_set_error_string(context, 0, ret, "malloc out of memory");
2109 if (data.length != size)
2110 _hx509_abort("internal ASN.1 encoder error");
2112 ret = _hx509_create_signature_bitstring(context,
2116 &c.signatureAlgorithm,
2122 *certificate = hx509_cert_init(context, &c, &error);
2123 if (*certificate == NULL) {
2124 ret = heim_error_get_code(error);
2125 heim_release(error);
2129 free_Certificate(&c);
2134 free_Certificate(&c);
2139 get_AuthorityKeyIdentifier(hx509_context context,
2140 const Certificate *certificate,
2141 AuthorityKeyIdentifier *ai)
2143 SubjectKeyIdentifier si;
2146 ret = _hx509_find_extension_subject_key_id(certificate, &si);
2148 ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
2149 if (ai->keyIdentifier == NULL) {
2150 free_SubjectKeyIdentifier(&si);
2152 hx509_set_error_string(context, 0, ret, "Out of memory");
2155 ret = der_copy_octet_string(&si, ai->keyIdentifier);
2156 free_SubjectKeyIdentifier(&si);
2158 hx509_set_error_string(context, 0, ret, "Out of memory");
2166 memset(&gn, 0, sizeof(gn));
2167 memset(&gns, 0, sizeof(gns));
2168 memset(&name, 0, sizeof(name));
2170 ai->authorityCertIssuer =
2171 calloc(1, sizeof(*ai->authorityCertIssuer));
2172 if (ai->authorityCertIssuer == NULL) {
2174 hx509_set_error_string(context, 0, ret, "Out of memory");
2177 ai->authorityCertSerialNumber =
2178 calloc(1, sizeof(*ai->authorityCertSerialNumber));
2179 if (ai->authorityCertSerialNumber == NULL) {
2181 hx509_set_error_string(context, 0, ret, "Out of memory");
2186 * XXX unbreak when asn1 compiler handle IMPLICIT
2188 * This is so horrible.
2191 ret = copy_Name(&certificate->tbsCertificate.subject, &name);
2193 hx509_set_error_string(context, 0, ret, "Out of memory");
2197 memset(&gn, 0, sizeof(gn));
2198 gn.element = choice_GeneralName_directoryName;
2199 gn.u.directoryName.element = choice_Name_rdnSequence;
2200 gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
2202 ret = add_GeneralNames(&gns, &gn);
2204 hx509_set_error_string(context, 0, ret, "Out of memory");
2208 ai->authorityCertIssuer->val = gns.val;
2209 ai->authorityCertIssuer->len = gns.len;
2211 ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
2212 ai->authorityCertSerialNumber);
2213 if (ai->authorityCertSerialNumber == NULL) {
2215 hx509_set_error_string(context, 0, ret, "Out of memory");
2221 free_AuthorityKeyIdentifier(ai);
2227 * Sign a to-be-signed certificate object with a issuer certificate.
2229 * The caller needs to at least have called the following functions on the
2230 * to-be-signed certificate object:
2231 * - hx509_ca_tbs_init()
2232 * - hx509_ca_tbs_set_subject()
2233 * - hx509_ca_tbs_set_spki()
2235 * When done the to-be-signed certificate object should be freed with
2236 * hx509_ca_tbs_free().
2238 * When creating self-signed certificate use hx509_ca_sign_self() instead.
2240 * @param context A hx509 context.
2241 * @param tbs object to be signed.
2242 * @param signer the CA certificate object to sign with (need private key).
2243 * @param certificate return cerificate, free with hx509_cert_free().
2245 * @return An hx509 error code, see hx509_get_error_string().
2250 HX509_LIB_FUNCTION int HX509_LIB_CALL
2251 hx509_ca_sign(hx509_context context,
2254 hx509_cert *certificate)
2256 const Certificate *signer_cert;
2257 AuthorityKeyIdentifier ai;
2260 memset(&ai, 0, sizeof(ai));
2262 signer_cert = _hx509_get_cert(signer);
2264 ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
2268 ret = ca_sign(context,
2270 _hx509_cert_private_key(signer),
2272 &signer_cert->tbsCertificate.subject,
2276 free_AuthorityKeyIdentifier(&ai);
2282 * Work just like hx509_ca_sign() but signs it-self.
2284 * @param context A hx509 context.
2285 * @param tbs object to be signed.
2286 * @param signer private key to sign with.
2287 * @param certificate return cerificate, free with hx509_cert_free().
2289 * @return An hx509 error code, see hx509_get_error_string().
2294 HX509_LIB_FUNCTION int HX509_LIB_CALL
2295 hx509_ca_sign_self(hx509_context context,
2297 hx509_private_key signer,
2298 hx509_cert *certificate)
2300 return ca_sign(context,
2309 * The following used to be `kdc_issue_certificate()', which was added for
2310 * kx509 support in the kdc, then adapted for bx509d. It now has no
2311 * kdc-specific code and very little krb5-specific code, and is named
2312 * `hx509_ca_issue_certificate()'.
2315 /* From lib/krb5/principal.c */
2316 #define princ_num_comp(P) ((P)->principalName.name_string.len)
2317 #define princ_type(P) ((P)->principalName.name_type)
2318 #define princ_comp(P) ((P)->principalName.name_string.val)
2319 #define princ_ncomp(P, N) ((P)->principalName.name_string.val[(N)])
2320 #define princ_realm(P) ((P)->realm)
2323 princ_get_comp_string(KRB5PrincipalName *principal, unsigned int component)
2325 if (component >= princ_num_comp(principal))
2327 return princ_ncomp(principal, component);
2329 /* XXX Add unparse_name() */
2345 static heim_error_code
2346 count_sans(hx509_request req, size_t *n)
2353 for (i = 0; ret == 0; i++) {
2354 hx509_san_type san_type;
2357 ret = hx509_request_get_san(req, i, &san_type, &s);
2361 case HX509_SAN_TYPE_DNSNAME:
2362 case HX509_SAN_TYPE_EMAIL:
2363 case HX509_SAN_TYPE_XMPP:
2364 case HX509_SAN_TYPE_PKINIT:
2365 case HX509_SAN_TYPE_MS_UPN:
2373 return ret == HX509_NO_ITEM ? 0 : ret;
2377 has_sans(hx509_request req)
2379 hx509_san_type san_type;
2381 int ret = hx509_request_get_san(req, 0, &san_type, &s);
2384 return ret == HX509_NO_ITEM ? 0 : 1;
2388 characterize_cprinc(hx509_context context,
2389 KRB5PrincipalName *cprinc)
2391 unsigned int ncomp = princ_num_comp(cprinc);
2392 const char *comp1 = princ_get_comp_string(cprinc, 1);
2398 if (strchr(comp1, '.') == NULL)
2402 if (strchr(comp1, '.'))
2410 /* Characterize request as client or server cert req */
2412 characterize(hx509_context context,
2413 KRB5PrincipalName *cprinc,
2416 heim_error_code ret = 0;
2417 cert_type res = CERT_NOTSUP;
2423 return characterize_cprinc(context, cprinc);
2425 for (i = 0; ret == 0; i++) {
2429 ret = hx509_request_get_eku(req, i, &s);
2434 ret = der_parse_heim_oid(s, ".", &oid);
2438 * If the client wants only a server certificate, then we'll be
2439 * willing to issue one that may be longer-lived than the client's
2442 * There may be other server EKUs, but these are the ones we know
2445 if (der_heim_oid_cmp(&asn1_oid_id_pkix_kp_serverAuth, &oid) &&
2446 der_heim_oid_cmp(&asn1_oid_id_pkix_kp_OCSPSigning, &oid) &&
2447 der_heim_oid_cmp(&asn1_oid_id_pkix_kp_secureShellServer, &oid))
2454 if (ret == HX509_NO_ITEM)
2457 for (i = 0; ret == 0; i++) {
2458 hx509_san_type san_type;
2461 ret = hx509_request_get_san(req, i, &san_type, &s);
2465 case HX509_SAN_TYPE_DNSNAME:
2469 case HX509_SAN_TYPE_EMAIL:
2470 case HX509_SAN_TYPE_XMPP:
2471 case HX509_SAN_TYPE_PKINIT:
2472 case HX509_SAN_TYPE_MS_UPN:
2483 if (ret == HX509_NO_ITEM)
2485 return ret ? CERT_NOTSUP : res;
2489 * Get a configuration sub-tree for kx509 based on what's being requested and
2492 * We have a number of cases:
2494 * - default certificate (no CSR used, or no certificate extensions requested)
2495 * - for client principals
2496 * - for service principals
2497 * - client certificate requested (CSR used and client-y SANs/EKUs requested)
2498 * - server certificate requested (CSR used and server-y SANs/EKUs requested)
2499 * - mixed client/server certificate requested (...)
2501 static heim_error_code
2502 get_cf(hx509_context context,
2503 const heim_config_binding *cf,
2504 heim_log_facility *logf,
2506 KRB5PrincipalName *cprinc,
2507 const heim_config_binding **out)
2509 heim_error_code ret;
2510 unsigned int ncomp = princ_num_comp(cprinc);
2511 const char *realm = princ_realm(cprinc);
2512 const char *comp0 = princ_get_comp_string(cprinc, 0);
2513 const char *comp1 = princ_get_comp_string(cprinc, 1);
2514 const char *label = NULL;
2515 const char *svc = NULL;
2516 const char *def = NULL;
2517 cert_type certtype = CERT_NOTSUP;
2522 heim_log_msg(context->hcontext, logf, 5, NULL,
2523 "Client principal has no components!");
2524 hx509_set_error_string(context, 0, ret = ENOTSUP,
2525 "Client principal has no components!");
2529 if ((ret = count_sans(req, &nsans)) ||
2530 (certtype = characterize(context, cprinc, req)) == CERT_NOTSUP) {
2531 heim_log_msg(context->hcontext, logf, 5, NULL,
2532 "Could not characterize CSR");
2533 hx509_set_error_string(context, 0, ret, "Could not characterize CSR");
2539 /* Client requested some certificate extension, a SAN or EKU */
2541 case CERT_MIXED: label = "mixed"; break;
2542 case CERT_CLIENT: label = "client"; break;
2543 case CERT_SERVER: label = "server"; break;
2545 hx509_set_error_string(context, 0, ret = ENOTSUP,
2546 "Requested SAN/EKU combination not "
2552 /* Default certificate desired */
2555 } else if (ncomp == 2 && strcmp(comp1, "root") == 0) {
2556 label = "root_user";
2557 } else if (ncomp == 2 && strcmp(comp1, "admin") == 0) {
2558 label = "admin_user";
2559 } else if (strchr(comp1, '.')) {
2560 label = "hostbased_service";
2567 *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL);
2571 heim_log_msg(context->hcontext, logf, 3, NULL,
2572 "No configuration for %s %s certificate's realm "
2573 "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2574 svc ? " -> " : "", svc ? svc : "");
2575 hx509_set_error_string(context, 0, EACCES,
2576 "No configuration for %s %s certificate's realm "
2577 "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2578 svc ? " -> " : "", svc ? svc : "");
2585 * Find and set a certificate template using a configuration sub-tree
2586 * appropriate to the requesting principal.
2588 * This allows for the specification of the following in configuration:
2590 * - certificates as templates, with ${var} tokens in subjectName attribute
2591 * values that will be expanded later
2592 * - a plain string with ${var} tokens to use as the subjectName
2594 * - whether to include a PKINIT SAN
2596 static heim_error_code
2597 set_template(hx509_context context,
2598 heim_log_facility *logf,
2599 const heim_config_binding *cf,
2602 heim_error_code ret = 0;
2603 const char *cert_template = NULL;
2604 const char *subj_name = NULL;
2608 return EACCES; /* Can't happen */
2610 cert_template = heim_config_get_string(context->hcontext, cf,
2611 "template_cert", NULL);
2612 subj_name = heim_config_get_string(context->hcontext, cf, "subject_name",
2614 ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL);
2616 if (cert_template) {
2618 hx509_cert template;
2620 ret = hx509_certs_init(context, cert_template, 0, NULL, &certs);
2622 ret = hx509_get_one_cert(context, certs, &template);
2623 hx509_certs_free(&certs);
2625 heim_log_msg(context->hcontext, logf, 1, NULL,
2626 "Failed to load certificate template from %s",
2628 hx509_set_error_string(context, 0, EACCES,
2629 "Failed to load certificate template from "
2630 "%s", cert_template);
2635 * Only take the subjectName, the keyUsage, and EKUs from the template
2638 ret = hx509_ca_tbs_set_template(context, tbs,
2639 HX509_CA_TEMPLATE_SUBJECT |
2640 HX509_CA_TEMPLATE_KU |
2641 HX509_CA_TEMPLATE_EKU,
2643 hx509_cert_free(template);
2649 hx509_name dn = NULL;
2651 ret = hx509_parse_name(context, subj_name, &dn);
2653 ret = hx509_ca_tbs_set_subject(context, tbs, dn);
2654 hx509_name_free(&dn);
2659 if (cert_template == NULL && subj_name == NULL) {
2660 hx509_name dn = NULL;
2662 ret = hx509_empty_name(context, &dn);
2664 ret = hx509_ca_tbs_set_subject(context, tbs, dn);
2665 hx509_name_free(&dn);
2673 for (i = 0; ret == 0 && ekus[i]; i++) {
2674 heim_oid oid = { 0, 0 };
2676 if ((ret = der_find_or_parse_heim_oid(ekus[i], ".", &oid)) == 0)
2677 ret = hx509_ca_tbs_add_eku(context, tbs, &oid);
2680 heim_config_free_strings(ekus);
2684 * XXX A KeyUsage template would be nice, but it needs some smarts to
2685 * remove, e.g., encipherOnly, decipherOnly, keyEncipherment, if the SPKI
2686 * algorithm does not support encryption. The same logic should be added
2687 * to hx509_ca_tbs_set_template()'s HX509_CA_TEMPLATE_KU functionality.
2693 * Find and set a certificate template, set "variables" in `env', and add add
2694 * default SANs/EKUs as appropriate.
2697 * - lookup a template for the client principal in its HDB entry
2698 * - lookup subjectName, SANs for a principal in its HDB entry
2699 * - lookup a host-based client principal's HDB entry and add its canonical
2700 * name / aliases as dNSName SANs
2701 * (this would have to be if requested by the client, perhaps)
2703 static heim_error_code
2704 set_tbs(hx509_context context,
2705 heim_log_facility *logf,
2706 const heim_config_binding *cf,
2708 KRB5PrincipalName *cprinc,
2712 KRB5PrincipalName cprinc_no_realm = *cprinc;
2713 heim_error_code ret;
2714 unsigned int ncomp = princ_num_comp(cprinc);
2715 const char *realm = princ_realm(cprinc);
2716 const char *comp0 = princ_get_comp_string(cprinc, 0);
2717 const char *comp1 = princ_get_comp_string(cprinc, 1);
2718 const char *comp2 = princ_get_comp_string(cprinc, 2);
2719 struct rk_strpool *strpool;
2720 char *princ_no_realm = NULL;
2723 strpool = _hx509_unparse_kerberos_name(NULL, cprinc);
2725 princ = rk_strpoolcollect(strpool);
2726 cprinc_no_realm.realm = NULL;
2727 strpool = _hx509_unparse_kerberos_name(NULL, &cprinc_no_realm);
2729 princ_no_realm = rk_strpoolcollect(strpool);
2730 if (princ == NULL || princ_no_realm == NULL) {
2732 return hx509_enomem(context);
2735 ret = hx509_env_add(context, env, "principal-name-without-realm",
2738 ret = hx509_env_add(context, env, "principal-name", princ);
2740 ret = hx509_env_add(context, env, "principal-name-realm",
2743 /* Populate requested certificate extensions from CSR/CSRPlus if allowed */
2744 ret = hx509_ca_tbs_set_from_csr(context, tbs, req);
2746 ret = set_template(context, logf, cf, tbs);
2749 * Optionally add PKINIT SAN.
2751 * Adding an id-pkinit-san means the client can use the certificate to
2752 * initiate PKINIT. That might seem odd, but it enables a sort of PKIX
2753 * credential delegation by allowing forwarded Kerberos tickets to be
2754 * used to acquire PKIX credentials. Thus this can work:
2756 * PKIX (w/ HW token) -> Kerberos ->
2757 * PKIX (w/ softtoken) -> Kerberos ->
2758 * PKIX (w/ softtoken) -> Kerberos ->
2761 * Note that we may not have added the PKINIT EKU -- that depends on the
2762 * template, and host-based service templates might well not include it.
2764 if (ret == 0 && !has_sans(req) &&
2765 heim_config_get_bool_default(context->hcontext, cf, FALSE,
2766 "include_pkinit_san", NULL)) {
2767 ret = hx509_ca_tbs_add_san_pkinit(context, tbs, princ);
2774 const char *email_domain;
2776 ret = hx509_env_add(context, env, "principal-component0",
2780 * If configured, include an rfc822Name that's just the client's
2781 * principal name sans realm @ configured email domain.
2783 if (ret == 0 && !has_sans(req) &&
2784 (email_domain = heim_config_get_string(context->hcontext, cf,
2785 "email_domain", NULL))) {
2788 if (asprintf(&email, "%s@%s", princ_no_realm, email_domain) == -1 ||
2791 ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email);
2794 } else if (ncomp == 2 || ncomp == 3) {
2796 * 2- and 3-component principal name.
2798 * We do not have a reliable name-type indicator. If the second
2799 * component has a '.' in it then we'll assume that the name is a
2800 * host-based (2-component) or domain-based (3-component) service
2801 * principal name. Else we'll assume it's a two-component admin-style
2805 ret = hx509_env_add(context, env, "principal-component0", comp0);
2807 ret = hx509_env_add(context, env, "principal-component1", comp1);
2808 if (ret == 0 && ncomp == 3)
2809 ret = hx509_env_add(context, env, "principal-component2", comp2);
2810 if (ret == 0 && strchr(comp1, '.')) {
2811 /* Looks like host-based or domain-based service */
2812 ret = hx509_env_add(context, env, "principal-service-name", comp0);
2814 ret = hx509_env_add(context, env, "principal-host-name",
2816 if (ret == 0 && ncomp == 3)
2817 ret = hx509_env_add(context, env, "principal-domain-name",
2819 if (ret == 0 && !has_sans(req) &&
2820 heim_config_get_bool_default(context->hcontext, cf, FALSE,
2821 "include_dnsname_san", NULL)) {
2822 ret = hx509_ca_tbs_add_san_hostname(context, tbs, comp1);
2826 heim_log_msg(context->hcontext, logf, 5, NULL,
2827 "kx509/bx509 client %s has too many components!", princ);
2828 hx509_set_error_string(context, 0, ret = EACCES,
2829 "kx509/bx509 client %s has too many "
2830 "components!", princ);
2836 free(princ_no_realm);
2841 heim_log_msg(context->hcontext, logf, 0, NULL,
2842 "Could not set up TBSCertificate: Out of memory");
2843 ret = hx509_enomem(context);
2848 * Set the notBefore/notAfter for the certificate to be issued.
2850 * Here `starttime' is the supplicant's credentials' notBefore equivalent,
2851 * while `endtime' is the supplicant's credentials' notAfter equivalent.
2853 * `req_life' is the lifetime requested by the supplicant.
2855 * `endtime' must be larger than the current time.
2857 * `starttime' can be zero or negative, in which case the notBefore will be the
2858 * current time minus five minutes.
2860 * `endtime', `req_life' and configuration parameters will be used to compute
2861 * the actual notAfter.
2863 static heim_error_code
2864 tbs_set_times(hx509_context context,
2865 const heim_config_binding *cf,
2866 heim_log_facility *logf,
2872 time_t now = time(NULL);
2873 time_t force = heim_config_get_time_default(context->hcontext,
2875 "force_cert_lifetime", NULL);
2876 time_t clamp = heim_config_get_time_default(context->hcontext, cf, 0,
2877 "max_cert_lifetime", NULL);
2878 int allow_more = heim_config_get_bool_default(context->hcontext, cf, FALSE,
2879 "allow_extra_lifetime",
2881 starttime = starttime > 0 ? starttime : now - 5 * 60;
2883 if (endtime < now) {
2884 heim_log_msg(context->hcontext, logf, 3, NULL,
2885 "Endtime is in the past");
2886 hx509_set_error_string(context, 0, ERANGE, "Endtime is in the past");
2890 /* Apply requested lifetime if shorter or if allowed more */
2891 if (req_life > 0 && req_life <= endtime - now)
2892 endtime = now + req_life;
2893 else if (req_life > 0 && allow_more)
2894 endtime = now + req_life;
2897 if (force > 0 && force > endtime - now)
2898 endtime = now + force;
2901 if (clamp > 0 && clamp < endtime - now)
2902 endtime = now + clamp;
2904 hx509_ca_tbs_set_notAfter(context, tbs, endtime);
2905 hx509_ca_tbs_set_notBefore(context, tbs, starttime);
2910 * Build a certifate for `principal' and its CSR.
2912 * XXX Make `cprinc' a GeneralName! That's why this is private for now.
2915 _hx509_ca_issue_certificate(hx509_context context,
2916 const heim_config_binding *cf,
2917 heim_log_facility *logf,
2919 KRB5PrincipalName *cprinc,
2926 heim_error_code ret;
2928 hx509_ca_tbs tbs = NULL;
2929 hx509_certs chain = NULL;
2930 hx509_cert signer = NULL;
2931 hx509_cert cert = NULL;
2932 hx509_env env = NULL;
2937 ku = int2KeyUsage(0);
2938 ku.digitalSignature = 1;
2939 hx509_request_authorize_ku(req, ku);
2941 ret = get_cf(context, cf, logf, req, cprinc, &cf);
2943 if ((ca = heim_config_get_string(context->hcontext, cf,
2944 "ca", NULL)) == NULL) {
2945 heim_log_msg(context->hcontext, logf, 3, NULL,
2946 "No kx509 CA issuer credential specified");
2947 hx509_set_error_string(context, 0, ret = EACCES,
2948 "No kx509 CA issuer credential specified");
2952 ret = hx509_ca_tbs_init(context, &tbs);
2954 heim_log_msg(context->hcontext, logf, 0, NULL,
2955 "Failed to create certificate: Out of memory");
2959 /* Lookup a template and set things in `env' and `tbs' as appropriate */
2961 ret = set_tbs(context, logf, cf, req, cprinc, &env, tbs);
2963 /* Populate generic template "env" variables */
2966 * The `tbs' and `env' are now complete as to naming and EKUs.
2968 * We check that the `tbs' is not name-less, after which all remaining
2969 * failures here will not be policy failures. So we also log the intent to
2970 * issue a certificate now.
2972 if (ret == 0 && hx509_name_is_null_p(hx509_ca_tbs_get_name(tbs)) &&
2974 heim_log_msg(context->hcontext, logf, 3, NULL,
2975 "Not issuing certificate because it would have no names");
2976 hx509_set_error_string(context, 0, ret = EACCES,
2977 "Not issuing certificate because it "
2978 "would have no names");
2984 * Still to be done below:
2986 * - set certificate spki
2987 * - set certificate validity
2988 * - expand variables in certificate subject name template
2989 * - sign certificate
2990 * - encode certificate and chain
2993 /* Load the issuer certificate and private key */
2998 ret = hx509_certs_init(context, ca, 0, NULL, &certs);
3000 heim_log_msg(context->hcontext, logf, 1, NULL,
3001 "Failed to load CA certificate and private key %s",
3003 hx509_set_error_string(context, 0, ret, "Failed to load "
3004 "CA certificate and private key %s", ca);
3007 ret = hx509_query_alloc(context, &q);
3009 hx509_certs_free(&certs);
3013 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
3014 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
3016 ret = hx509_certs_find(context, certs, q, &signer);
3017 hx509_query_free(context, q);
3018 hx509_certs_free(&certs);
3020 heim_log_msg(context->hcontext, logf, 1, NULL,
3021 "Failed to find a CA certificate in %s", ca);
3022 hx509_set_error_string(context, 0, ret,
3023 "Failed to find a CA certificate in %s",
3029 /* Populate the subject public key in the TBS context */
3031 SubjectPublicKeyInfo spki;
3033 ret = hx509_request_get_SubjectPublicKeyInfo(context,
3036 ret = hx509_ca_tbs_set_spki(context, tbs, &spki);
3037 free_SubjectPublicKeyInfo(&spki);
3042 /* Work out cert expiration */
3044 ret = tbs_set_times(context, cf, logf, starttime, endtime, req_life,
3047 /* Expand the subjectName template in the TBS using the env */
3049 ret = hx509_ca_tbs_subject_expand(context, tbs, env);
3050 hx509_env_free(&env);
3052 /* All done with the TBS, sign/issue the certificate */
3053 ret = hx509_ca_sign(context, tbs, signer, &cert);
3058 * Gather the certificate and chain into a MEMORY store, being careful not
3059 * to include private keys in the chain.
3061 * We could have specified a separate configuration parameter for an hx509
3062 * store meant to have only the chain and no private keys, but expecting
3063 * the full chain in the issuer credential store and copying only the certs
3064 * (but not the private keys) is safer and easier to configure.
3066 ret = hx509_certs_init(context, "MEMORY:certs",
3067 HX509_CERTS_NO_PRIVATE_KEYS, NULL, out);
3069 ret = hx509_certs_add(context, *out, cert);
3070 if (ret == 0 && send_chain) {
3071 ret = hx509_certs_init(context, ca,
3072 HX509_CERTS_NO_PRIVATE_KEYS, NULL, &chain);
3074 ret = hx509_certs_merge(context, *out, chain);
3078 hx509_certs_free(&chain);
3080 hx509_env_free(&env);
3082 hx509_ca_tbs_free(&tbs);
3084 hx509_cert_free(cert);
3086 hx509_cert_free(signer);
3088 hx509_certs_free(out);