etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / hx509 / ca.c
blobf2e455b8576d1e5aa1e984a2a51064c9562d4ded
1 /* $NetBSD: ca.c,v 1.1.1.2 2014/04/24 12:45:41 pettai Exp $ */
3 /*
4 * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "hx_locl.h"
37 #include <krb5/pkinit_asn1.h>
39 /**
40 * @page page_ca Hx509 CA functions
42 * See the library functions here: @ref hx509_ca
45 struct hx509_ca_tbs {
46 hx509_name subject;
47 SubjectPublicKeyInfo spki;
48 ExtKeyUsage eku;
49 GeneralNames san;
50 unsigned key_usage;
51 heim_integer serial;
52 struct {
53 unsigned int proxy:1;
54 unsigned int ca:1;
55 unsigned int key:1;
56 unsigned int serial:1;
57 unsigned int domaincontroller:1;
58 unsigned int xUniqueID:1;
59 } flags;
60 time_t notBefore;
61 time_t notAfter;
62 int pathLenConstraint; /* both for CA and Proxy */
63 CRLDistributionPoints crldp;
64 heim_bit_string subjectUniqueID;
65 heim_bit_string issuerUniqueID;
69 /**
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().
79 * @ingroup hx509_ca
82 int
83 hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
85 *tbs = calloc(1, sizeof(**tbs));
86 if (*tbs == NULL)
87 return ENOMEM;
89 return 0;
92 /**
93 * Free an To Be Signed object.
95 * @param tbs object to free.
97 * @ingroup hx509_ca
100 void
101 hx509_ca_tbs_free(hx509_ca_tbs *tbs)
103 if (tbs == NULL || *tbs == NULL)
104 return;
106 free_SubjectPublicKeyInfo(&(*tbs)->spki);
107 free_GeneralNames(&(*tbs)->san);
108 free_ExtKeyUsage(&(*tbs)->eku);
109 der_free_heim_integer(&(*tbs)->serial);
110 free_CRLDistributionPoints(&(*tbs)->crldp);
111 der_free_bit_string(&(*tbs)->subjectUniqueID);
112 der_free_bit_string(&(*tbs)->issuerUniqueID);
113 hx509_name_free(&(*tbs)->subject);
115 memset(*tbs, 0, sizeof(**tbs));
116 free(*tbs);
117 *tbs = NULL;
121 * Set the absolute time when the certificate is valid from. If not
122 * set the current time will be used.
124 * @param context A hx509 context.
125 * @param tbs object to be signed.
126 * @param t time the certificated will start to be valid
128 * @return An hx509 error code, see hx509_get_error_string().
130 * @ingroup hx509_ca
134 hx509_ca_tbs_set_notBefore(hx509_context context,
135 hx509_ca_tbs tbs,
136 time_t t)
138 tbs->notBefore = t;
139 return 0;
143 * Set the absolute time when the certificate is valid to.
145 * @param context A hx509 context.
146 * @param tbs object to be signed.
147 * @param t time when the certificate will expire
149 * @return An hx509 error code, see hx509_get_error_string().
151 * @ingroup hx509_ca
155 hx509_ca_tbs_set_notAfter(hx509_context context,
156 hx509_ca_tbs tbs,
157 time_t t)
159 tbs->notAfter = t;
160 return 0;
164 * Set the relative time when the certificiate is going to expire.
166 * @param context A hx509 context.
167 * @param tbs object to be signed.
168 * @param delta seconds to the certificate is going to expire.
170 * @return An hx509 error code, see hx509_get_error_string().
172 * @ingroup hx509_ca
176 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
177 hx509_ca_tbs tbs,
178 time_t delta)
180 return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
183 static const struct units templatebits[] = {
184 { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
185 { "KeyUsage", HX509_CA_TEMPLATE_KU },
186 { "SPKI", HX509_CA_TEMPLATE_SPKI },
187 { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
188 { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
189 { "serial", HX509_CA_TEMPLATE_SERIAL },
190 { "subject", HX509_CA_TEMPLATE_SUBJECT },
191 { NULL, 0 }
195 * Make of template units, use to build flags argument to
196 * hx509_ca_tbs_set_template() with parse_units().
198 * @return an units structure.
200 * @ingroup hx509_ca
203 const struct units *
204 hx509_ca_tbs_template_units(void)
206 return templatebits;
210 * Initialize the to-be-signed certificate object from a template certifiate.
212 * @param context A hx509 context.
213 * @param tbs object to be signed.
214 * @param flags bit field selecting what to copy from the template
215 * certifiate.
216 * @param cert template certificate.
218 * @return An hx509 error code, see hx509_get_error_string().
220 * @ingroup hx509_ca
224 hx509_ca_tbs_set_template(hx509_context context,
225 hx509_ca_tbs tbs,
226 int flags,
227 hx509_cert cert)
229 int ret;
231 if (flags & HX509_CA_TEMPLATE_SUBJECT) {
232 if (tbs->subject)
233 hx509_name_free(&tbs->subject);
234 ret = hx509_cert_get_subject(cert, &tbs->subject);
235 if (ret) {
236 hx509_set_error_string(context, 0, ret,
237 "Failed to get subject from template");
238 return ret;
241 if (flags & HX509_CA_TEMPLATE_SERIAL) {
242 der_free_heim_integer(&tbs->serial);
243 ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
244 tbs->flags.serial = !ret;
245 if (ret) {
246 hx509_set_error_string(context, 0, ret,
247 "Failed to copy serial number");
248 return ret;
251 if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
252 tbs->notBefore = hx509_cert_get_notBefore(cert);
253 if (flags & HX509_CA_TEMPLATE_NOTAFTER)
254 tbs->notAfter = hx509_cert_get_notAfter(cert);
255 if (flags & HX509_CA_TEMPLATE_SPKI) {
256 free_SubjectPublicKeyInfo(&tbs->spki);
257 ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
258 tbs->flags.key = !ret;
259 if (ret)
260 return ret;
262 if (flags & HX509_CA_TEMPLATE_KU) {
263 KeyUsage ku;
264 ret = _hx509_cert_get_keyusage(context, cert, &ku);
265 if (ret)
266 return ret;
267 tbs->key_usage = KeyUsage2int(ku);
269 if (flags & HX509_CA_TEMPLATE_EKU) {
270 ExtKeyUsage eku;
271 size_t i;
272 ret = _hx509_cert_get_eku(context, cert, &eku);
273 if (ret)
274 return ret;
275 for (i = 0; i < eku.len; i++) {
276 ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
277 if (ret) {
278 free_ExtKeyUsage(&eku);
279 return ret;
282 free_ExtKeyUsage(&eku);
284 return 0;
288 * Make the to-be-signed certificate object a CA certificate. If the
289 * pathLenConstraint is negative path length constraint is used.
291 * @param context A hx509 context.
292 * @param tbs object to be signed.
293 * @param pathLenConstraint path length constraint, negative, no
294 * constraint.
296 * @return An hx509 error code, see hx509_get_error_string().
298 * @ingroup hx509_ca
302 hx509_ca_tbs_set_ca(hx509_context context,
303 hx509_ca_tbs tbs,
304 int pathLenConstraint)
306 tbs->flags.ca = 1;
307 tbs->pathLenConstraint = pathLenConstraint;
308 return 0;
312 * Make the to-be-signed certificate object a proxy certificate. If the
313 * pathLenConstraint is negative path length constraint is used.
315 * @param context A hx509 context.
316 * @param tbs object to be signed.
317 * @param pathLenConstraint path length constraint, negative, no
318 * constraint.
320 * @return An hx509 error code, see hx509_get_error_string().
322 * @ingroup hx509_ca
326 hx509_ca_tbs_set_proxy(hx509_context context,
327 hx509_ca_tbs tbs,
328 int pathLenConstraint)
330 tbs->flags.proxy = 1;
331 tbs->pathLenConstraint = pathLenConstraint;
332 return 0;
337 * Make the to-be-signed certificate object a windows domain controller certificate.
339 * @param context A hx509 context.
340 * @param tbs object to be signed.
342 * @return An hx509 error code, see hx509_get_error_string().
344 * @ingroup hx509_ca
348 hx509_ca_tbs_set_domaincontroller(hx509_context context,
349 hx509_ca_tbs tbs)
351 tbs->flags.domaincontroller = 1;
352 return 0;
356 * Set the subject public key info (SPKI) in the to-be-signed certificate
357 * object. SPKI is the public key and key related parameters in the
358 * certificate.
360 * @param context A hx509 context.
361 * @param tbs object to be signed.
362 * @param spki subject public key info to use for the to-be-signed certificate object.
364 * @return An hx509 error code, see hx509_get_error_string().
366 * @ingroup hx509_ca
370 hx509_ca_tbs_set_spki(hx509_context context,
371 hx509_ca_tbs tbs,
372 const SubjectPublicKeyInfo *spki)
374 int ret;
375 free_SubjectPublicKeyInfo(&tbs->spki);
376 ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
377 tbs->flags.key = !ret;
378 return ret;
382 * Set the serial number to use for to-be-signed certificate object.
384 * @param context A hx509 context.
385 * @param tbs object to be signed.
386 * @param serialNumber serial number to use for the to-be-signed
387 * certificate object.
389 * @return An hx509 error code, see hx509_get_error_string().
391 * @ingroup hx509_ca
395 hx509_ca_tbs_set_serialnumber(hx509_context context,
396 hx509_ca_tbs tbs,
397 const heim_integer *serialNumber)
399 int ret;
400 der_free_heim_integer(&tbs->serial);
401 ret = der_copy_heim_integer(serialNumber, &tbs->serial);
402 tbs->flags.serial = !ret;
403 return ret;
407 * An an extended key usage to the to-be-signed certificate object.
408 * Duplicates will detected and not added.
410 * @param context A hx509 context.
411 * @param tbs object to be signed.
412 * @param oid extended key usage to add.
414 * @return An hx509 error code, see hx509_get_error_string().
416 * @ingroup hx509_ca
420 hx509_ca_tbs_add_eku(hx509_context context,
421 hx509_ca_tbs tbs,
422 const heim_oid *oid)
424 void *ptr;
425 int ret;
426 unsigned i;
428 /* search for duplicates */
429 for (i = 0; i < tbs->eku.len; i++) {
430 if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
431 return 0;
434 ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
435 if (ptr == NULL) {
436 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
437 return ENOMEM;
439 tbs->eku.val = ptr;
440 ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
441 if (ret) {
442 hx509_set_error_string(context, 0, ret, "out of memory");
443 return ret;
445 tbs->eku.len += 1;
446 return 0;
450 * Add CRL distribution point URI to the to-be-signed certificate
451 * object.
453 * @param context A hx509 context.
454 * @param tbs object to be signed.
455 * @param uri uri to the CRL.
456 * @param issuername name of the issuer.
458 * @return An hx509 error code, see hx509_get_error_string().
460 * @ingroup hx509_ca
464 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
465 hx509_ca_tbs tbs,
466 const char *uri,
467 hx509_name issuername)
469 DistributionPoint dp;
470 int ret;
472 memset(&dp, 0, sizeof(dp));
474 dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
477 DistributionPointName name;
478 GeneralName gn;
479 size_t size;
481 name.element = choice_DistributionPointName_fullName;
482 name.u.fullName.len = 1;
483 name.u.fullName.val = &gn;
485 gn.element = choice_GeneralName_uniformResourceIdentifier;
486 gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
487 gn.u.uniformResourceIdentifier.length = strlen(uri);
489 ASN1_MALLOC_ENCODE(DistributionPointName,
490 dp.distributionPoint->data,
491 dp.distributionPoint->length,
492 &name, &size, ret);
493 if (ret) {
494 hx509_set_error_string(context, 0, ret,
495 "Failed to encoded DistributionPointName");
496 goto out;
498 if (dp.distributionPoint->length != size)
499 _hx509_abort("internal ASN.1 encoder error");
502 if (issuername) {
503 #if 1
505 * issuername not supported
507 hx509_set_error_string(context, 0, EINVAL,
508 "CRLDistributionPoints.name.issuername not yet supported");
509 return EINVAL;
510 #else
511 GeneralNames *crlissuer;
512 GeneralName gn;
513 Name n;
515 crlissuer = calloc(1, sizeof(*crlissuer));
516 if (crlissuer == NULL) {
517 return ENOMEM;
519 memset(&gn, 0, sizeof(gn));
521 gn.element = choice_GeneralName_directoryName;
522 ret = hx509_name_to_Name(issuername, &n);
523 if (ret) {
524 hx509_set_error_string(context, 0, ret, "out of memory");
525 goto out;
528 gn.u.directoryName.element = n.element;
529 gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
531 ret = add_GeneralNames(&crlissuer, &gn);
532 free_Name(&n);
533 if (ret) {
534 hx509_set_error_string(context, 0, ret, "out of memory");
535 goto out;
538 dp.cRLIssuer = &crlissuer;
539 #endif
542 ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
543 if (ret) {
544 hx509_set_error_string(context, 0, ret, "out of memory");
545 goto out;
548 out:
549 free_DistributionPoint(&dp);
551 return ret;
555 * Add Subject Alternative Name otherName to the to-be-signed
556 * certificate object.
558 * @param context A hx509 context.
559 * @param tbs object to be signed.
560 * @param oid the oid of the OtherName.
561 * @param os data in the other name.
563 * @return An hx509 error code, see hx509_get_error_string().
565 * @ingroup hx509_ca
569 hx509_ca_tbs_add_san_otherName(hx509_context context,
570 hx509_ca_tbs tbs,
571 const heim_oid *oid,
572 const heim_octet_string *os)
574 GeneralName gn;
576 memset(&gn, 0, sizeof(gn));
577 gn.element = choice_GeneralName_otherName;
578 gn.u.otherName.type_id = *oid;
579 gn.u.otherName.value = *os;
581 return add_GeneralNames(&tbs->san, &gn);
585 * Add Kerberos Subject Alternative Name to the to-be-signed
586 * certificate object. The principal string is a UTF8 string.
588 * @param context A hx509 context.
589 * @param tbs object to be signed.
590 * @param principal Kerberos principal to add to the certificate.
592 * @return An hx509 error code, see hx509_get_error_string().
594 * @ingroup hx509_ca
598 hx509_ca_tbs_add_san_pkinit(hx509_context context,
599 hx509_ca_tbs tbs,
600 const char *principal)
602 heim_octet_string os;
603 KRB5PrincipalName p;
604 size_t size;
605 int ret;
606 char *s = NULL;
608 memset(&p, 0, sizeof(p));
610 /* parse principal */
612 const char *str;
613 char *q;
614 int n;
616 /* count number of component */
617 n = 1;
618 for(str = principal; *str != '\0' && *str != '@'; str++){
619 if(*str=='\\'){
620 if(str[1] == '\0' || str[1] == '@') {
621 ret = HX509_PARSING_NAME_FAILED;
622 hx509_set_error_string(context, 0, ret,
623 "trailing \\ in principal name");
624 goto out;
626 str++;
627 } else if(*str == '/')
628 n++;
630 p.principalName.name_string.val =
631 calloc(n, sizeof(*p.principalName.name_string.val));
632 if (p.principalName.name_string.val == NULL) {
633 ret = ENOMEM;
634 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
635 goto out;
637 p.principalName.name_string.len = n;
639 p.principalName.name_type = KRB5_NT_PRINCIPAL;
640 q = s = strdup(principal);
641 if (q == NULL) {
642 ret = ENOMEM;
643 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
644 goto out;
646 p.realm = strrchr(q, '@');
647 if (p.realm == NULL) {
648 ret = HX509_PARSING_NAME_FAILED;
649 hx509_set_error_string(context, 0, ret, "Missing @ in principal");
650 goto out;
652 *p.realm++ = '\0';
654 n = 0;
655 while (q) {
656 p.principalName.name_string.val[n++] = q;
657 q = strchr(q, '/');
658 if (q)
659 *q++ = '\0';
663 ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
664 if (ret) {
665 hx509_set_error_string(context, 0, ret, "Out of memory");
666 goto out;
668 if (size != os.length)
669 _hx509_abort("internal ASN.1 encoder error");
671 ret = hx509_ca_tbs_add_san_otherName(context,
672 tbs,
673 &asn1_oid_id_pkinit_san,
674 &os);
675 free(os.data);
676 out:
677 if (p.principalName.name_string.val)
678 free (p.principalName.name_string.val);
679 if (s)
680 free(s);
681 return ret;
688 static int
689 add_utf8_san(hx509_context context,
690 hx509_ca_tbs tbs,
691 const heim_oid *oid,
692 const char *string)
694 const PKIXXmppAddr ustring = (const PKIXXmppAddr)(intptr_t)string;
695 heim_octet_string os;
696 size_t size;
697 int ret;
699 os.length = 0;
700 os.data = NULL;
702 ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
703 if (ret) {
704 hx509_set_error_string(context, 0, ret, "Out of memory");
705 goto out;
707 if (size != os.length)
708 _hx509_abort("internal ASN.1 encoder error");
710 ret = hx509_ca_tbs_add_san_otherName(context,
711 tbs,
712 oid,
713 &os);
714 free(os.data);
715 out:
716 return ret;
720 * Add Microsoft UPN Subject Alternative Name to the to-be-signed
721 * certificate object. The principal string is a UTF8 string.
723 * @param context A hx509 context.
724 * @param tbs object to be signed.
725 * @param principal Microsoft UPN string.
727 * @return An hx509 error code, see hx509_get_error_string().
729 * @ingroup hx509_ca
733 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
734 hx509_ca_tbs tbs,
735 const char *principal)
737 return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
741 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
742 * certificate object. The jid is an UTF8 string.
744 * @param context A hx509 context.
745 * @param tbs object to be signed.
746 * @param jid string of an a jabber id in UTF8.
748 * @return An hx509 error code, see hx509_get_error_string().
750 * @ingroup hx509_ca
754 hx509_ca_tbs_add_san_jid(hx509_context context,
755 hx509_ca_tbs tbs,
756 const char *jid)
758 return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
763 * Add a Subject Alternative Name hostname to to-be-signed certificate
764 * object. A domain match starts with ., an exact match does not.
766 * Example of a an domain match: .domain.se matches the hostname
767 * host.domain.se.
769 * @param context A hx509 context.
770 * @param tbs object to be signed.
771 * @param dnsname a hostame.
773 * @return An hx509 error code, see hx509_get_error_string().
775 * @ingroup hx509_ca
779 hx509_ca_tbs_add_san_hostname(hx509_context context,
780 hx509_ca_tbs tbs,
781 const char *dnsname)
783 GeneralName gn;
785 memset(&gn, 0, sizeof(gn));
786 gn.element = choice_GeneralName_dNSName;
787 gn.u.dNSName.data = rk_UNCONST(dnsname);
788 gn.u.dNSName.length = strlen(dnsname);
790 return add_GeneralNames(&tbs->san, &gn);
794 * Add a Subject Alternative Name rfc822 (email address) to
795 * to-be-signed certificate object.
797 * @param context A hx509 context.
798 * @param tbs object to be signed.
799 * @param rfc822Name a string to a email address.
801 * @return An hx509 error code, see hx509_get_error_string().
803 * @ingroup hx509_ca
807 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
808 hx509_ca_tbs tbs,
809 const char *rfc822Name)
811 GeneralName gn;
813 memset(&gn, 0, sizeof(gn));
814 gn.element = choice_GeneralName_rfc822Name;
815 gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
816 gn.u.rfc822Name.length = strlen(rfc822Name);
818 return add_GeneralNames(&tbs->san, &gn);
822 * Set the subject name of a to-be-signed certificate object.
824 * @param context A hx509 context.
825 * @param tbs object to be signed.
826 * @param subject the name to set a subject.
828 * @return An hx509 error code, see hx509_get_error_string().
830 * @ingroup hx509_ca
834 hx509_ca_tbs_set_subject(hx509_context context,
835 hx509_ca_tbs tbs,
836 hx509_name subject)
838 if (tbs->subject)
839 hx509_name_free(&tbs->subject);
840 return hx509_name_copy(context, subject, &tbs->subject);
844 * Set the issuerUniqueID and subjectUniqueID
846 * These are only supposed to be used considered with version 2
847 * certificates, replaced by the two extensions SubjectKeyIdentifier
848 * and IssuerKeyIdentifier. This function is to allow application
849 * using legacy protocol to issue them.
851 * @param context A hx509 context.
852 * @param tbs object to be signed.
853 * @param issuerUniqueID to be set
854 * @param subjectUniqueID to be set
856 * @return An hx509 error code, see hx509_get_error_string().
858 * @ingroup hx509_ca
862 hx509_ca_tbs_set_unique(hx509_context context,
863 hx509_ca_tbs tbs,
864 const heim_bit_string *subjectUniqueID,
865 const heim_bit_string *issuerUniqueID)
867 int ret;
869 der_free_bit_string(&tbs->subjectUniqueID);
870 der_free_bit_string(&tbs->issuerUniqueID);
872 if (subjectUniqueID) {
873 ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
874 if (ret)
875 return ret;
878 if (issuerUniqueID) {
879 ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
880 if (ret)
881 return ret;
884 return 0;
888 * Expand the the subject name in the to-be-signed certificate object
889 * using hx509_name_expand().
891 * @param context A hx509 context.
892 * @param tbs object to be signed.
893 * @param env enviroment variable to expand variables in the subject
894 * name, see hx509_env_init().
896 * @return An hx509 error code, see hx509_get_error_string().
898 * @ingroup hx509_ca
902 hx509_ca_tbs_subject_expand(hx509_context context,
903 hx509_ca_tbs tbs,
904 hx509_env env)
906 return hx509_name_expand(context, tbs->subject, env);
913 static int
914 add_extension(hx509_context context,
915 TBSCertificate *tbsc,
916 int critical_flag,
917 const heim_oid *oid,
918 const heim_octet_string *data)
920 Extension ext;
921 int ret;
923 memset(&ext, 0, sizeof(ext));
925 if (critical_flag) {
926 ext.critical = malloc(sizeof(*ext.critical));
927 if (ext.critical == NULL) {
928 ret = ENOMEM;
929 hx509_set_error_string(context, 0, ret, "Out of memory");
930 goto out;
932 *ext.critical = TRUE;
935 ret = der_copy_oid(oid, &ext.extnID);
936 if (ret) {
937 hx509_set_error_string(context, 0, ret, "Out of memory");
938 goto out;
940 ret = der_copy_octet_string(data, &ext.extnValue);
941 if (ret) {
942 hx509_set_error_string(context, 0, ret, "Out of memory");
943 goto out;
945 ret = add_Extensions(tbsc->extensions, &ext);
946 if (ret) {
947 hx509_set_error_string(context, 0, ret, "Out of memory");
948 goto out;
950 out:
951 free_Extension(&ext);
952 return ret;
955 static int
956 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
958 char *tstr;
959 time_t t;
960 int ret;
962 ret = copy_Name(issuer, subject);
963 if (ret) {
964 hx509_set_error_string(context, 0, ret,
965 "Failed to copy subject name");
966 return ret;
969 t = time(NULL);
970 asprintf(&tstr, "ts-%lu", (unsigned long)t);
971 if (tstr == NULL) {
972 hx509_set_error_string(context, 0, ENOMEM,
973 "Failed to copy subject name");
974 return ENOMEM;
976 /* prefix with CN=<ts>,...*/
977 ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
978 free(tstr);
979 if (ret)
980 free_Name(subject);
981 return ret;
984 static int
985 ca_sign(hx509_context context,
986 hx509_ca_tbs tbs,
987 hx509_private_key signer,
988 const AuthorityKeyIdentifier *ai,
989 const Name *issuername,
990 hx509_cert *certificate)
992 heim_octet_string data;
993 Certificate c;
994 TBSCertificate *tbsc;
995 size_t size;
996 int ret;
997 const AlgorithmIdentifier *sigalg;
998 time_t notBefore;
999 time_t notAfter;
1000 unsigned key_usage;
1002 sigalg = _hx509_crypto_default_sig_alg;
1004 memset(&c, 0, sizeof(c));
1007 * Default values are: Valid since 24h ago, valid one year into
1008 * the future, KeyUsage digitalSignature and keyEncipherment set,
1009 * and keyCertSign for CA certificates.
1011 notBefore = tbs->notBefore;
1012 if (notBefore == 0)
1013 notBefore = time(NULL) - 3600 * 24;
1014 notAfter = tbs->notAfter;
1015 if (notAfter == 0)
1016 notAfter = time(NULL) + 3600 * 24 * 365;
1018 key_usage = tbs->key_usage;
1019 if (key_usage == 0) {
1020 KeyUsage ku;
1021 memset(&ku, 0, sizeof(ku));
1022 ku.digitalSignature = 1;
1023 ku.keyEncipherment = 1;
1024 key_usage = KeyUsage2int(ku);
1027 if (tbs->flags.ca) {
1028 KeyUsage ku;
1029 memset(&ku, 0, sizeof(ku));
1030 ku.keyCertSign = 1;
1031 ku.cRLSign = 1;
1032 key_usage |= KeyUsage2int(ku);
1039 tbsc = &c.tbsCertificate;
1041 if (tbs->flags.key == 0) {
1042 ret = EINVAL;
1043 hx509_set_error_string(context, 0, ret, "No public key set");
1044 return ret;
1047 * Don't put restrictions on proxy certificate's subject name, it
1048 * will be generated below.
1050 if (!tbs->flags.proxy) {
1051 if (tbs->subject == NULL) {
1052 hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1053 return EINVAL;
1055 if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1056 hx509_set_error_string(context, 0, EINVAL,
1057 "NULL subject and no SubjectAltNames");
1058 return EINVAL;
1061 if (tbs->flags.ca && tbs->flags.proxy) {
1062 hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1063 "at the same time");
1064 return EINVAL;
1066 if (tbs->flags.proxy) {
1067 if (tbs->san.len > 0) {
1068 hx509_set_error_string(context, 0, EINVAL,
1069 "Proxy certificate is not allowed "
1070 "to have SubjectAltNames");
1071 return EINVAL;
1075 /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1076 tbsc->version = calloc(1, sizeof(*tbsc->version));
1077 if (tbsc->version == NULL) {
1078 ret = ENOMEM;
1079 hx509_set_error_string(context, 0, ret, "Out of memory");
1080 goto out;
1082 *tbsc->version = rfc3280_version_3;
1083 /* serialNumber CertificateSerialNumber, */
1084 if (tbs->flags.serial) {
1085 ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1086 if (ret) {
1087 hx509_set_error_string(context, 0, ret, "Out of memory");
1088 goto out;
1090 } else {
1091 tbsc->serialNumber.length = 20;
1092 tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1093 if (tbsc->serialNumber.data == NULL){
1094 ret = ENOMEM;
1095 hx509_set_error_string(context, 0, ret, "Out of memory");
1096 goto out;
1098 /* XXX diffrent */
1099 RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1100 ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1102 /* signature AlgorithmIdentifier, */
1103 ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1104 if (ret) {
1105 hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1106 goto out;
1108 /* issuer Name, */
1109 if (issuername)
1110 ret = copy_Name(issuername, &tbsc->issuer);
1111 else
1112 ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1113 if (ret) {
1114 hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1115 goto out;
1117 /* validity Validity, */
1118 tbsc->validity.notBefore.element = choice_Time_generalTime;
1119 tbsc->validity.notBefore.u.generalTime = notBefore;
1120 tbsc->validity.notAfter.element = choice_Time_generalTime;
1121 tbsc->validity.notAfter.u.generalTime = notAfter;
1122 /* subject Name, */
1123 if (tbs->flags.proxy) {
1124 ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1125 if (ret)
1126 goto out;
1127 } else {
1128 ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1129 if (ret) {
1130 hx509_set_error_string(context, 0, ret,
1131 "Failed to copy subject name");
1132 goto out;
1135 /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1136 ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1137 if (ret) {
1138 hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1139 goto out;
1141 /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1142 if (tbs->issuerUniqueID.length) {
1143 tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1144 if (tbsc->issuerUniqueID == NULL) {
1145 ret = ENOMEM;
1146 hx509_set_error_string(context, 0, ret, "Out of memory");
1147 goto out;
1149 ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1150 if (ret) {
1151 hx509_set_error_string(context, 0, ret, "Out of memory");
1152 goto out;
1155 /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1156 if (tbs->subjectUniqueID.length) {
1157 tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1158 if (tbsc->subjectUniqueID == NULL) {
1159 ret = ENOMEM;
1160 hx509_set_error_string(context, 0, ret, "Out of memory");
1161 goto out;
1164 ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1165 if (ret) {
1166 hx509_set_error_string(context, 0, ret, "Out of memory");
1167 goto out;
1171 /* extensions [3] EXPLICIT Extensions OPTIONAL */
1172 tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1173 if (tbsc->extensions == NULL) {
1174 ret = ENOMEM;
1175 hx509_set_error_string(context, 0, ret, "Out of memory");
1176 goto out;
1179 /* Add the text BMP string Domaincontroller to the cert */
1180 if (tbs->flags.domaincontroller) {
1181 data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1182 "\x00\x61\x00\x69\x00\x6e\x00\x43"
1183 "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1184 "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1185 "\x00\x72");
1186 data.length = 34;
1188 ret = add_extension(context, tbsc, 0,
1189 &asn1_oid_id_ms_cert_enroll_domaincontroller,
1190 &data);
1191 if (ret)
1192 goto out;
1195 /* add KeyUsage */
1197 KeyUsage ku;
1199 ku = int2KeyUsage(key_usage);
1200 ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1201 if (ret) {
1202 hx509_set_error_string(context, 0, ret, "Out of memory");
1203 goto out;
1205 if (size != data.length)
1206 _hx509_abort("internal ASN.1 encoder error");
1207 ret = add_extension(context, tbsc, 1,
1208 &asn1_oid_id_x509_ce_keyUsage, &data);
1209 free(data.data);
1210 if (ret)
1211 goto out;
1214 /* add ExtendedKeyUsage */
1215 if (tbs->eku.len > 0) {
1216 ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1217 &tbs->eku, &size, ret);
1218 if (ret) {
1219 hx509_set_error_string(context, 0, ret, "Out of memory");
1220 goto out;
1222 if (size != data.length)
1223 _hx509_abort("internal ASN.1 encoder error");
1224 ret = add_extension(context, tbsc, 0,
1225 &asn1_oid_id_x509_ce_extKeyUsage, &data);
1226 free(data.data);
1227 if (ret)
1228 goto out;
1231 /* add Subject Alternative Name */
1232 if (tbs->san.len > 0) {
1233 ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1234 &tbs->san, &size, ret);
1235 if (ret) {
1236 hx509_set_error_string(context, 0, ret, "Out of memory");
1237 goto out;
1239 if (size != data.length)
1240 _hx509_abort("internal ASN.1 encoder error");
1241 ret = add_extension(context, tbsc, 0,
1242 &asn1_oid_id_x509_ce_subjectAltName,
1243 &data);
1244 free(data.data);
1245 if (ret)
1246 goto out;
1249 /* Add Authority Key Identifier */
1250 if (ai) {
1251 ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1252 ai, &size, ret);
1253 if (ret) {
1254 hx509_set_error_string(context, 0, ret, "Out of memory");
1255 goto out;
1257 if (size != data.length)
1258 _hx509_abort("internal ASN.1 encoder error");
1259 ret = add_extension(context, tbsc, 0,
1260 &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1261 &data);
1262 free(data.data);
1263 if (ret)
1264 goto out;
1267 /* Add Subject Key Identifier */
1269 SubjectKeyIdentifier si;
1270 unsigned char hash[SHA_DIGEST_LENGTH];
1273 EVP_MD_CTX *ctx;
1275 ctx = EVP_MD_CTX_create();
1276 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1277 EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1278 tbs->spki.subjectPublicKey.length / 8);
1279 EVP_DigestFinal_ex(ctx, hash, NULL);
1280 EVP_MD_CTX_destroy(ctx);
1283 si.data = hash;
1284 si.length = sizeof(hash);
1286 ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1287 &si, &size, ret);
1288 if (ret) {
1289 hx509_set_error_string(context, 0, ret, "Out of memory");
1290 goto out;
1292 if (size != data.length)
1293 _hx509_abort("internal ASN.1 encoder error");
1294 ret = add_extension(context, tbsc, 0,
1295 &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1296 &data);
1297 free(data.data);
1298 if (ret)
1299 goto out;
1302 /* Add BasicConstraints */
1304 BasicConstraints bc;
1305 int aCA = 1;
1306 unsigned int path;
1308 memset(&bc, 0, sizeof(bc));
1310 if (tbs->flags.ca) {
1311 bc.cA = &aCA;
1312 if (tbs->pathLenConstraint >= 0) {
1313 path = tbs->pathLenConstraint;
1314 bc.pathLenConstraint = &path;
1318 ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1319 &bc, &size, ret);
1320 if (ret) {
1321 hx509_set_error_string(context, 0, ret, "Out of memory");
1322 goto out;
1324 if (size != data.length)
1325 _hx509_abort("internal ASN.1 encoder error");
1326 /* Critical if this is a CA */
1327 ret = add_extension(context, tbsc, tbs->flags.ca,
1328 &asn1_oid_id_x509_ce_basicConstraints,
1329 &data);
1330 free(data.data);
1331 if (ret)
1332 goto out;
1335 /* add Proxy */
1336 if (tbs->flags.proxy) {
1337 ProxyCertInfo info;
1339 memset(&info, 0, sizeof(info));
1341 if (tbs->pathLenConstraint >= 0) {
1342 info.pCPathLenConstraint =
1343 malloc(sizeof(*info.pCPathLenConstraint));
1344 if (info.pCPathLenConstraint == NULL) {
1345 ret = ENOMEM;
1346 hx509_set_error_string(context, 0, ret, "Out of memory");
1347 goto out;
1349 *info.pCPathLenConstraint = tbs->pathLenConstraint;
1352 ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
1353 &info.proxyPolicy.policyLanguage);
1354 if (ret) {
1355 free_ProxyCertInfo(&info);
1356 hx509_set_error_string(context, 0, ret, "Out of memory");
1357 goto out;
1360 ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1361 &info, &size, ret);
1362 free_ProxyCertInfo(&info);
1363 if (ret) {
1364 hx509_set_error_string(context, 0, ret, "Out of memory");
1365 goto out;
1367 if (size != data.length)
1368 _hx509_abort("internal ASN.1 encoder error");
1369 ret = add_extension(context, tbsc, 0,
1370 &asn1_oid_id_pkix_pe_proxyCertInfo,
1371 &data);
1372 free(data.data);
1373 if (ret)
1374 goto out;
1377 if (tbs->crldp.len) {
1379 ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1380 &tbs->crldp, &size, ret);
1381 if (ret) {
1382 hx509_set_error_string(context, 0, ret, "Out of memory");
1383 goto out;
1385 if (size != data.length)
1386 _hx509_abort("internal ASN.1 encoder error");
1387 ret = add_extension(context, tbsc, FALSE,
1388 &asn1_oid_id_x509_ce_cRLDistributionPoints,
1389 &data);
1390 free(data.data);
1391 if (ret)
1392 goto out;
1395 ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1396 if (ret) {
1397 hx509_set_error_string(context, 0, ret, "malloc out of memory");
1398 goto out;
1400 if (data.length != size)
1401 _hx509_abort("internal ASN.1 encoder error");
1403 ret = _hx509_create_signature_bitstring(context,
1404 signer,
1405 sigalg,
1406 &data,
1407 &c.signatureAlgorithm,
1408 &c.signatureValue);
1409 free(data.data);
1410 if (ret)
1411 goto out;
1413 ret = hx509_cert_init(context, &c, certificate);
1414 if (ret)
1415 goto out;
1417 free_Certificate(&c);
1419 return 0;
1421 out:
1422 free_Certificate(&c);
1423 return ret;
1426 static int
1427 get_AuthorityKeyIdentifier(hx509_context context,
1428 const Certificate *certificate,
1429 AuthorityKeyIdentifier *ai)
1431 SubjectKeyIdentifier si;
1432 int ret;
1434 ret = _hx509_find_extension_subject_key_id(certificate, &si);
1435 if (ret == 0) {
1436 ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1437 if (ai->keyIdentifier == NULL) {
1438 free_SubjectKeyIdentifier(&si);
1439 ret = ENOMEM;
1440 hx509_set_error_string(context, 0, ret, "Out of memory");
1441 goto out;
1443 ret = der_copy_octet_string(&si, ai->keyIdentifier);
1444 free_SubjectKeyIdentifier(&si);
1445 if (ret) {
1446 hx509_set_error_string(context, 0, ret, "Out of memory");
1447 goto out;
1449 } else {
1450 GeneralNames gns;
1451 GeneralName gn;
1452 Name name;
1454 memset(&gn, 0, sizeof(gn));
1455 memset(&gns, 0, sizeof(gns));
1456 memset(&name, 0, sizeof(name));
1458 ai->authorityCertIssuer =
1459 calloc(1, sizeof(*ai->authorityCertIssuer));
1460 if (ai->authorityCertIssuer == NULL) {
1461 ret = ENOMEM;
1462 hx509_set_error_string(context, 0, ret, "Out of memory");
1463 goto out;
1465 ai->authorityCertSerialNumber =
1466 calloc(1, sizeof(*ai->authorityCertSerialNumber));
1467 if (ai->authorityCertSerialNumber == NULL) {
1468 ret = ENOMEM;
1469 hx509_set_error_string(context, 0, ret, "Out of memory");
1470 goto out;
1474 * XXX unbreak when asn1 compiler handle IMPLICIT
1476 * This is so horrible.
1479 ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1480 if (ret) {
1481 hx509_set_error_string(context, 0, ret, "Out of memory");
1482 goto out;
1485 memset(&gn, 0, sizeof(gn));
1486 gn.element = choice_GeneralName_directoryName;
1487 gn.u.directoryName.element =
1488 choice_GeneralName_directoryName_rdnSequence;
1489 gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1491 ret = add_GeneralNames(&gns, &gn);
1492 if (ret) {
1493 hx509_set_error_string(context, 0, ret, "Out of memory");
1494 goto out;
1497 ai->authorityCertIssuer->val = gns.val;
1498 ai->authorityCertIssuer->len = gns.len;
1500 ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1501 ai->authorityCertSerialNumber);
1502 if (ai->authorityCertSerialNumber == NULL) {
1503 ret = ENOMEM;
1504 hx509_set_error_string(context, 0, ret, "Out of memory");
1505 goto out;
1508 out:
1509 if (ret)
1510 free_AuthorityKeyIdentifier(ai);
1511 return ret;
1516 * Sign a to-be-signed certificate object with a issuer certificate.
1518 * The caller needs to at least have called the following functions on the
1519 * to-be-signed certificate object:
1520 * - hx509_ca_tbs_init()
1521 * - hx509_ca_tbs_set_subject()
1522 * - hx509_ca_tbs_set_spki()
1524 * When done the to-be-signed certificate object should be freed with
1525 * hx509_ca_tbs_free().
1527 * When creating self-signed certificate use hx509_ca_sign_self() instead.
1529 * @param context A hx509 context.
1530 * @param tbs object to be signed.
1531 * @param signer the CA certificate object to sign with (need private key).
1532 * @param certificate return cerificate, free with hx509_cert_free().
1534 * @return An hx509 error code, see hx509_get_error_string().
1536 * @ingroup hx509_ca
1540 hx509_ca_sign(hx509_context context,
1541 hx509_ca_tbs tbs,
1542 hx509_cert signer,
1543 hx509_cert *certificate)
1545 const Certificate *signer_cert;
1546 AuthorityKeyIdentifier ai;
1547 int ret;
1549 memset(&ai, 0, sizeof(ai));
1551 signer_cert = _hx509_get_cert(signer);
1553 ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1554 if (ret)
1555 goto out;
1557 ret = ca_sign(context,
1558 tbs,
1559 _hx509_cert_private_key(signer),
1560 &ai,
1561 &signer_cert->tbsCertificate.subject,
1562 certificate);
1564 out:
1565 free_AuthorityKeyIdentifier(&ai);
1567 return ret;
1571 * Work just like hx509_ca_sign() but signs it-self.
1573 * @param context A hx509 context.
1574 * @param tbs object to be signed.
1575 * @param signer private key to sign with.
1576 * @param certificate return cerificate, free with hx509_cert_free().
1578 * @return An hx509 error code, see hx509_get_error_string().
1580 * @ingroup hx509_ca
1584 hx509_ca_sign_self(hx509_context context,
1585 hx509_ca_tbs tbs,
1586 hx509_private_key signer,
1587 hx509_cert *certificate)
1589 return ca_sign(context,
1590 tbs,
1591 signer,
1592 NULL,
1593 NULL,
1594 certificate);