No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / hx509 / ca.c
blob3203099d0198a2c2849dbcbf2e6fe053a2c8cd60
1 /*
2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "hx_locl.h"
35 #include <pkinit_asn1.h>
36 __RCSID("$Heimdal: ca.c 22456 2008-01-15 20:22:53Z lha $"
37 "$NetBSD$");
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 } flags;
59 time_t notBefore;
60 time_t notAfter;
61 int pathLenConstraint; /* both for CA and Proxy */
62 CRLDistributionPoints crldp;
65 /**
66 * Allocate an to-be-signed certificate object that will be converted
67 * into an certificate.
69 * @param context A hx509 context.
70 * @param tbs returned to-be-signed certicate object, free with
71 * hx509_ca_tbs_free().
73 * @return An hx509 error code, see hx509_get_error_string().
75 * @ingroup hx509_ca
78 int
79 hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
81 *tbs = calloc(1, sizeof(**tbs));
82 if (*tbs == NULL)
83 return ENOMEM;
85 (*tbs)->subject = NULL;
86 (*tbs)->san.len = 0;
87 (*tbs)->san.val = NULL;
88 (*tbs)->eku.len = 0;
89 (*tbs)->eku.val = NULL;
90 (*tbs)->pathLenConstraint = 0;
91 (*tbs)->crldp.len = 0;
92 (*tbs)->crldp.val = NULL;
94 return 0;
97 /**
98 * Free an To Be Signed object.
100 * @param tbs object to free.
102 * @ingroup hx509_ca
105 void
106 hx509_ca_tbs_free(hx509_ca_tbs *tbs)
108 if (tbs == NULL || *tbs == NULL)
109 return;
111 free_SubjectPublicKeyInfo(&(*tbs)->spki);
112 free_GeneralNames(&(*tbs)->san);
113 free_ExtKeyUsage(&(*tbs)->eku);
114 der_free_heim_integer(&(*tbs)->serial);
115 free_CRLDistributionPoints(&(*tbs)->crldp);
117 hx509_name_free(&(*tbs)->subject);
119 memset(*tbs, 0, sizeof(**tbs));
120 free(*tbs);
121 *tbs = NULL;
125 * Set the absolute time when the certificate is valid from. If not
126 * set the current time will be used.
128 * @param context A hx509 context.
129 * @param tbs object to be signed.
130 * @param t time the certificated will start to be valid
132 * @return An hx509 error code, see hx509_get_error_string().
134 * @ingroup hx509_ca
138 hx509_ca_tbs_set_notBefore(hx509_context context,
139 hx509_ca_tbs tbs,
140 time_t t)
142 tbs->notBefore = t;
143 return 0;
147 * Set the absolute time when the certificate is valid to.
149 * @param context A hx509 context.
150 * @param tbs object to be signed.
151 * @param t time when the certificate will expire
153 * @return An hx509 error code, see hx509_get_error_string().
155 * @ingroup hx509_ca
159 hx509_ca_tbs_set_notAfter(hx509_context context,
160 hx509_ca_tbs tbs,
161 time_t t)
163 tbs->notAfter = t;
164 return 0;
168 * Set the relative time when the certificiate is going to expire.
170 * @param context A hx509 context.
171 * @param tbs object to be signed.
172 * @param delta seconds to the certificate is going to expire.
174 * @return An hx509 error code, see hx509_get_error_string().
176 * @ingroup hx509_ca
180 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
181 hx509_ca_tbs tbs,
182 time_t delta)
184 return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
187 static const struct units templatebits[] = {
188 { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
189 { "KeyUsage", HX509_CA_TEMPLATE_KU },
190 { "SPKI", HX509_CA_TEMPLATE_SPKI },
191 { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
192 { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
193 { "serial", HX509_CA_TEMPLATE_SERIAL },
194 { "subject", HX509_CA_TEMPLATE_SUBJECT },
195 { NULL, 0 }
199 * Make of template units, use to build flags argument to
200 * hx509_ca_tbs_set_template() with parse_units().
202 * @return an units structure.
204 * @ingroup hx509_ca
207 const struct units *
208 hx509_ca_tbs_template_units(void)
210 return templatebits;
214 * Initialize the to-be-signed certificate object from a template certifiate.
216 * @param context A hx509 context.
217 * @param tbs object to be signed.
218 * @param flags bit field selecting what to copy from the template
219 * certifiate.
220 * @param cert template certificate.
222 * @return An hx509 error code, see hx509_get_error_string().
224 * @ingroup hx509_ca
228 hx509_ca_tbs_set_template(hx509_context context,
229 hx509_ca_tbs tbs,
230 int flags,
231 hx509_cert cert)
233 int ret;
235 if (flags & HX509_CA_TEMPLATE_SUBJECT) {
236 if (tbs->subject)
237 hx509_name_free(&tbs->subject);
238 ret = hx509_cert_get_subject(cert, &tbs->subject);
239 if (ret) {
240 hx509_set_error_string(context, 0, ret,
241 "Failed to get subject from template");
242 return ret;
245 if (flags & HX509_CA_TEMPLATE_SERIAL) {
246 der_free_heim_integer(&tbs->serial);
247 ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
248 tbs->flags.serial = !ret;
249 if (ret) {
250 hx509_set_error_string(context, 0, ret,
251 "Failed to copy serial number");
252 return ret;
255 if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
256 tbs->notBefore = hx509_cert_get_notBefore(cert);
257 if (flags & HX509_CA_TEMPLATE_NOTAFTER)
258 tbs->notAfter = hx509_cert_get_notAfter(cert);
259 if (flags & HX509_CA_TEMPLATE_SPKI) {
260 free_SubjectPublicKeyInfo(&tbs->spki);
261 ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
262 tbs->flags.key = !ret;
263 if (ret)
264 return ret;
266 if (flags & HX509_CA_TEMPLATE_KU) {
267 KeyUsage ku;
268 ret = _hx509_cert_get_keyusage(context, cert, &ku);
269 if (ret)
270 return ret;
271 tbs->key_usage = KeyUsage2int(ku);
273 if (flags & HX509_CA_TEMPLATE_EKU) {
274 ExtKeyUsage eku;
275 int i;
276 ret = _hx509_cert_get_eku(context, cert, &eku);
277 if (ret)
278 return ret;
279 for (i = 0; i < eku.len; i++) {
280 ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
281 if (ret) {
282 free_ExtKeyUsage(&eku);
283 return ret;
286 free_ExtKeyUsage(&eku);
288 return 0;
292 * Make the to-be-signed certificate object a CA certificate. If the
293 * pathLenConstraint is negative path length constraint is used.
295 * @param context A hx509 context.
296 * @param tbs object to be signed.
297 * @param pathLenConstraint path length constraint, negative, no
298 * constraint.
300 * @return An hx509 error code, see hx509_get_error_string().
302 * @ingroup hx509_ca
306 hx509_ca_tbs_set_ca(hx509_context context,
307 hx509_ca_tbs tbs,
308 int pathLenConstraint)
310 tbs->flags.ca = 1;
311 tbs->pathLenConstraint = pathLenConstraint;
312 return 0;
316 * Make the to-be-signed certificate object a proxy certificate. If the
317 * pathLenConstraint is negative path length constraint is used.
319 * @param context A hx509 context.
320 * @param tbs object to be signed.
321 * @param pathLenConstraint path length constraint, negative, no
322 * constraint.
324 * @return An hx509 error code, see hx509_get_error_string().
326 * @ingroup hx509_ca
330 hx509_ca_tbs_set_proxy(hx509_context context,
331 hx509_ca_tbs tbs,
332 int pathLenConstraint)
334 tbs->flags.proxy = 1;
335 tbs->pathLenConstraint = pathLenConstraint;
336 return 0;
341 * Make the to-be-signed certificate object a windows domain controller certificate.
343 * @param context A hx509 context.
344 * @param tbs object to be signed.
346 * @return An hx509 error code, see hx509_get_error_string().
348 * @ingroup hx509_ca
352 hx509_ca_tbs_set_domaincontroller(hx509_context context,
353 hx509_ca_tbs tbs)
355 tbs->flags.domaincontroller = 1;
356 return 0;
360 * Set the subject public key info (SPKI) in the to-be-signed certificate
361 * object. SPKI is the public key and key related parameters in the
362 * certificate.
364 * @param context A hx509 context.
365 * @param tbs object to be signed.
366 * @param spki subject public key info to use for the to-be-signed certificate object.
368 * @return An hx509 error code, see hx509_get_error_string().
370 * @ingroup hx509_ca
374 hx509_ca_tbs_set_spki(hx509_context context,
375 hx509_ca_tbs tbs,
376 const SubjectPublicKeyInfo *spki)
378 int ret;
379 free_SubjectPublicKeyInfo(&tbs->spki);
380 ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
381 tbs->flags.key = !ret;
382 return ret;
386 * Set the serial number to use for to-be-signed certificate object.
388 * @param context A hx509 context.
389 * @param tbs object to be signed.
390 * @param serialNumber serial number to use for the to-be-signed
391 * certificate object.
393 * @return An hx509 error code, see hx509_get_error_string().
395 * @ingroup hx509_ca
399 hx509_ca_tbs_set_serialnumber(hx509_context context,
400 hx509_ca_tbs tbs,
401 const heim_integer *serialNumber)
403 int ret;
404 der_free_heim_integer(&tbs->serial);
405 ret = der_copy_heim_integer(serialNumber, &tbs->serial);
406 tbs->flags.serial = !ret;
407 return ret;
411 * An an extended key usage to the to-be-signed certificate object.
412 * Duplicates will detected and not added.
414 * @param context A hx509 context.
415 * @param tbs object to be signed.
416 * @param oid extended key usage to add.
418 * @return An hx509 error code, see hx509_get_error_string().
420 * @ingroup hx509_ca
424 hx509_ca_tbs_add_eku(hx509_context context,
425 hx509_ca_tbs tbs,
426 const heim_oid *oid)
428 void *ptr;
429 int ret;
430 unsigned i;
432 /* search for duplicates */
433 for (i = 0; i < tbs->eku.len; i++) {
434 if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
435 return 0;
438 ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
439 if (ptr == NULL) {
440 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
441 return ENOMEM;
443 tbs->eku.val = ptr;
444 ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
445 if (ret) {
446 hx509_set_error_string(context, 0, ret, "out of memory");
447 return ret;
449 tbs->eku.len += 1;
450 return 0;
454 * Add CRL distribution point URI to the to-be-signed certificate
455 * object.
457 * @param context A hx509 context.
458 * @param tbs object to be signed.
459 * @param uri uri to the CRL.
460 * @param issuername name of the issuer.
462 * @return An hx509 error code, see hx509_get_error_string().
464 * @ingroup hx509_ca
468 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
469 hx509_ca_tbs tbs,
470 const char *uri,
471 hx509_name issuername)
473 DistributionPoint dp;
474 int ret;
476 memset(&dp, 0, sizeof(dp));
478 dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
481 DistributionPointName name;
482 GeneralName gn;
483 size_t size;
485 name.element = choice_DistributionPointName_fullName;
486 name.u.fullName.len = 1;
487 name.u.fullName.val = &gn;
489 gn.element = choice_GeneralName_uniformResourceIdentifier;
490 gn.u.uniformResourceIdentifier = rk_UNCONST(uri);
492 ASN1_MALLOC_ENCODE(DistributionPointName,
493 dp.distributionPoint->data,
494 dp.distributionPoint->length,
495 &name, &size, ret);
496 if (ret) {
497 hx509_set_error_string(context, 0, ret,
498 "Failed to encoded DistributionPointName");
499 goto out;
501 if (dp.distributionPoint->length != size)
502 _hx509_abort("internal ASN.1 encoder error");
505 if (issuername) {
506 #if 1
508 * issuername not supported
510 hx509_set_error_string(context, 0, EINVAL,
511 "CRLDistributionPoints.name.issuername not yet supported");
512 return EINVAL;
513 #else
514 GeneralNames *crlissuer;
515 GeneralName gn;
516 Name n;
518 crlissuer = calloc(1, sizeof(*crlissuer));
519 if (crlissuer == NULL) {
520 return ENOMEM;
522 memset(&gn, 0, sizeof(gn));
524 gn.element = choice_GeneralName_directoryName;
525 ret = hx509_name_to_Name(issuername, &n);
526 if (ret) {
527 hx509_set_error_string(context, 0, ret, "out of memory");
528 goto out;
531 gn.u.directoryName.element = n.element;
532 gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
534 ret = add_GeneralNames(&crlissuer, &gn);
535 free_Name(&n);
536 if (ret) {
537 hx509_set_error_string(context, 0, ret, "out of memory");
538 goto out;
541 dp.cRLIssuer = &crlissuer;
542 #endif
545 ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
546 if (ret) {
547 hx509_set_error_string(context, 0, ret, "out of memory");
548 goto out;
551 out:
552 free_DistributionPoint(&dp);
554 return ret;
558 * Add Subject Alternative Name otherName to the to-be-signed
559 * certificate object.
561 * @param context A hx509 context.
562 * @param tbs object to be signed.
563 * @param oid the oid of the OtherName.
564 * @param os data in the other name.
566 * @return An hx509 error code, see hx509_get_error_string().
568 * @ingroup hx509_ca
572 hx509_ca_tbs_add_san_otherName(hx509_context context,
573 hx509_ca_tbs tbs,
574 const heim_oid *oid,
575 const heim_octet_string *os)
577 GeneralName gn;
579 memset(&gn, 0, sizeof(gn));
580 gn.element = choice_GeneralName_otherName;
581 gn.u.otherName.type_id = *oid;
582 gn.u.otherName.value = *os;
584 return add_GeneralNames(&tbs->san, &gn);
588 * Add Kerberos Subject Alternative Name to the to-be-signed
589 * certificate object. The principal string is a UTF8 string.
591 * @param context A hx509 context.
592 * @param tbs object to be signed.
593 * @param principal Kerberos principal to add to the certificate.
595 * @return An hx509 error code, see hx509_get_error_string().
597 * @ingroup hx509_ca
601 hx509_ca_tbs_add_san_pkinit(hx509_context context,
602 hx509_ca_tbs tbs,
603 const char *principal)
605 heim_octet_string os;
606 KRB5PrincipalName p;
607 size_t size;
608 int ret;
609 char *s = NULL;
611 memset(&p, 0, sizeof(p));
613 /* parse principal */
615 const char *str;
616 char *q;
617 int n;
619 /* count number of component */
620 n = 1;
621 for(str = principal; *str != '\0' && *str != '@'; str++){
622 if(*str=='\\'){
623 if(str[1] == '\0' || str[1] == '@') {
624 ret = HX509_PARSING_NAME_FAILED;
625 hx509_set_error_string(context, 0, ret,
626 "trailing \\ in principal name");
627 goto out;
629 str++;
630 } else if(*str == '/')
631 n++;
633 p.principalName.name_string.val =
634 calloc(n, sizeof(*p.principalName.name_string.val));
635 if (p.principalName.name_string.val == NULL) {
636 ret = ENOMEM;
637 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
638 goto out;
640 p.principalName.name_string.len = n;
642 p.principalName.name_type = KRB5_NT_PRINCIPAL;
643 q = s = strdup(principal);
644 if (q == NULL) {
645 ret = ENOMEM;
646 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
647 goto out;
649 p.realm = strrchr(q, '@');
650 if (p.realm == NULL) {
651 ret = HX509_PARSING_NAME_FAILED;
652 hx509_set_error_string(context, 0, ret, "Missing @ in principal");
653 goto out;
655 *p.realm++ = '\0';
657 n = 0;
658 while (q) {
659 p.principalName.name_string.val[n++] = q;
660 q = strchr(q, '/');
661 if (q)
662 *q++ = '\0';
666 ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
667 if (ret) {
668 hx509_set_error_string(context, 0, ret, "Out of memory");
669 goto out;
671 if (size != os.length)
672 _hx509_abort("internal ASN.1 encoder error");
674 ret = hx509_ca_tbs_add_san_otherName(context,
675 tbs,
676 oid_id_pkinit_san(),
677 &os);
678 free(os.data);
679 out:
680 if (p.principalName.name_string.val)
681 free (p.principalName.name_string.val);
682 if (s)
683 free(s);
684 return ret;
691 static int
692 add_utf8_san(hx509_context context,
693 hx509_ca_tbs tbs,
694 const heim_oid *oid,
695 const char *string)
697 const PKIXXmppAddr ustring = (const PKIXXmppAddr)string;
698 heim_octet_string os;
699 size_t size;
700 int ret;
702 os.length = 0;
703 os.data = NULL;
705 ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
706 if (ret) {
707 hx509_set_error_string(context, 0, ret, "Out of memory");
708 goto out;
710 if (size != os.length)
711 _hx509_abort("internal ASN.1 encoder error");
713 ret = hx509_ca_tbs_add_san_otherName(context,
714 tbs,
715 oid,
716 &os);
717 free(os.data);
718 out:
719 return ret;
723 * Add Microsoft UPN Subject Alternative Name to the to-be-signed
724 * certificate object. The principal string is a UTF8 string.
726 * @param context A hx509 context.
727 * @param tbs object to be signed.
728 * @param principal Microsoft UPN string.
730 * @return An hx509 error code, see hx509_get_error_string().
732 * @ingroup hx509_ca
736 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
737 hx509_ca_tbs tbs,
738 const char *principal)
740 return add_utf8_san(context, tbs, oid_id_pkinit_ms_san(), principal);
744 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
745 * certificate object. The jid is an UTF8 string.
747 * @param context A hx509 context.
748 * @param tbs object to be signed.
749 * @param jid string of an a jabber id in UTF8.
751 * @return An hx509 error code, see hx509_get_error_string().
753 * @ingroup hx509_ca
757 hx509_ca_tbs_add_san_jid(hx509_context context,
758 hx509_ca_tbs tbs,
759 const char *jid)
761 return add_utf8_san(context, tbs, oid_id_pkix_on_xmppAddr(), jid);
766 * Add a Subject Alternative Name hostname to to-be-signed certificate
767 * object. A domain match starts with ., an exact match does not.
769 * Example of a an domain match: .domain.se matches the hostname
770 * host.domain.se.
772 * @param context A hx509 context.
773 * @param tbs object to be signed.
774 * @param dnsname a hostame.
776 * @return An hx509 error code, see hx509_get_error_string().
778 * @ingroup hx509_ca
782 hx509_ca_tbs_add_san_hostname(hx509_context context,
783 hx509_ca_tbs tbs,
784 const char *dnsname)
786 GeneralName gn;
788 memset(&gn, 0, sizeof(gn));
789 gn.element = choice_GeneralName_dNSName;
790 gn.u.dNSName = rk_UNCONST(dnsname);
792 return add_GeneralNames(&tbs->san, &gn);
796 * Add a Subject Alternative Name rfc822 (email address) to
797 * to-be-signed certificate object.
799 * @param context A hx509 context.
800 * @param tbs object to be signed.
801 * @param rfc822Name a string to a email address.
803 * @return An hx509 error code, see hx509_get_error_string().
805 * @ingroup hx509_ca
809 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
810 hx509_ca_tbs tbs,
811 const char *rfc822Name)
813 GeneralName gn;
815 memset(&gn, 0, sizeof(gn));
816 gn.element = choice_GeneralName_rfc822Name;
817 gn.u.rfc822Name = rk_UNCONST(rfc822Name);
819 return add_GeneralNames(&tbs->san, &gn);
823 * Set the subject name of a to-be-signed certificate object.
825 * @param context A hx509 context.
826 * @param tbs object to be signed.
827 * @param subject the name to set a subject.
829 * @return An hx509 error code, see hx509_get_error_string().
831 * @ingroup hx509_ca
835 hx509_ca_tbs_set_subject(hx509_context context,
836 hx509_ca_tbs tbs,
837 hx509_name subject)
839 if (tbs->subject)
840 hx509_name_free(&tbs->subject);
841 return hx509_name_copy(context, subject, &tbs->subject);
845 * Expand the the subject name in the to-be-signed certificate object
846 * using hx509_name_expand().
848 * @param context A hx509 context.
849 * @param tbs object to be signed.
850 * @param env enviroment variable to expand variables in the subject
851 * name, see hx509_env_init().
853 * @return An hx509 error code, see hx509_get_error_string().
855 * @ingroup hx509_ca
859 hx509_ca_tbs_subject_expand(hx509_context context,
860 hx509_ca_tbs tbs,
861 hx509_env env)
863 return hx509_name_expand(context, tbs->subject, env);
866 static int
867 add_extension(hx509_context context,
868 TBSCertificate *tbsc,
869 int critical_flag,
870 const heim_oid *oid,
871 const heim_octet_string *data)
873 Extension ext;
874 int ret;
876 memset(&ext, 0, sizeof(ext));
878 if (critical_flag) {
879 ext.critical = malloc(sizeof(*ext.critical));
880 if (ext.critical == NULL) {
881 ret = ENOMEM;
882 hx509_set_error_string(context, 0, ret, "Out of memory");
883 goto out;
885 *ext.critical = TRUE;
888 ret = der_copy_oid(oid, &ext.extnID);
889 if (ret) {
890 hx509_set_error_string(context, 0, ret, "Out of memory");
891 goto out;
893 ret = der_copy_octet_string(data, &ext.extnValue);
894 if (ret) {
895 hx509_set_error_string(context, 0, ret, "Out of memory");
896 goto out;
898 ret = add_Extensions(tbsc->extensions, &ext);
899 if (ret) {
900 hx509_set_error_string(context, 0, ret, "Out of memory");
901 goto out;
903 out:
904 free_Extension(&ext);
905 return ret;
908 static int
909 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
911 char *tstr;
912 time_t t;
913 int ret;
915 ret = copy_Name(issuer, subject);
916 if (ret) {
917 hx509_set_error_string(context, 0, ret,
918 "Failed to copy subject name");
919 return ret;
922 t = time(NULL);
923 asprintf(&tstr, "ts-%lu", (unsigned long)t);
924 if (tstr == NULL) {
925 hx509_set_error_string(context, 0, ENOMEM,
926 "Failed to copy subject name");
927 return ENOMEM;
929 /* prefix with CN=<ts>,...*/
930 ret = _hx509_name_modify(context, subject, 1, oid_id_at_commonName(), tstr);
931 free(tstr);
932 if (ret)
933 free_Name(subject);
934 return ret;
937 static int
938 ca_sign(hx509_context context,
939 hx509_ca_tbs tbs,
940 hx509_private_key signer,
941 const AuthorityKeyIdentifier *ai,
942 const Name *issuername,
943 hx509_cert *certificate)
945 heim_octet_string data;
946 Certificate c;
947 TBSCertificate *tbsc;
948 size_t size;
949 int ret;
950 const AlgorithmIdentifier *sigalg;
951 time_t notBefore;
952 time_t notAfter;
953 unsigned key_usage;
955 sigalg = _hx509_crypto_default_sig_alg;
957 memset(&c, 0, sizeof(c));
960 * Default values are: Valid since 24h ago, valid one year into
961 * the future, KeyUsage digitalSignature and keyEncipherment set,
962 * and keyCertSign for CA certificates.
964 notBefore = tbs->notBefore;
965 if (notBefore == 0)
966 notBefore = time(NULL) - 3600 * 24;
967 notAfter = tbs->notAfter;
968 if (notAfter == 0)
969 notAfter = time(NULL) + 3600 * 24 * 365;
971 key_usage = tbs->key_usage;
972 if (key_usage == 0) {
973 KeyUsage ku;
974 memset(&ku, 0, sizeof(ku));
975 ku.digitalSignature = 1;
976 ku.keyEncipherment = 1;
977 key_usage = KeyUsage2int(ku);
980 if (tbs->flags.ca) {
981 KeyUsage ku;
982 memset(&ku, 0, sizeof(ku));
983 ku.keyCertSign = 1;
984 ku.cRLSign = 1;
985 key_usage |= KeyUsage2int(ku);
992 tbsc = &c.tbsCertificate;
994 if (tbs->flags.key == 0) {
995 ret = EINVAL;
996 hx509_set_error_string(context, 0, ret, "No public key set");
997 return ret;
1000 * Don't put restrictions on proxy certificate's subject name, it
1001 * will be generated below.
1003 if (!tbs->flags.proxy) {
1004 if (tbs->subject == NULL) {
1005 hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1006 return EINVAL;
1008 if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1009 hx509_set_error_string(context, 0, EINVAL,
1010 "NULL subject and no SubjectAltNames");
1011 return EINVAL;
1014 if (tbs->flags.ca && tbs->flags.proxy) {
1015 hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1016 "at the same time");
1017 return EINVAL;
1019 if (tbs->flags.proxy) {
1020 if (tbs->san.len > 0) {
1021 hx509_set_error_string(context, 0, EINVAL,
1022 "Proxy certificate is not allowed "
1023 "to have SubjectAltNames");
1024 return EINVAL;
1028 /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1029 tbsc->version = calloc(1, sizeof(*tbsc->version));
1030 if (tbsc->version == NULL) {
1031 ret = ENOMEM;
1032 hx509_set_error_string(context, 0, ret, "Out of memory");
1033 goto out;
1035 *tbsc->version = rfc3280_version_3;
1036 /* serialNumber CertificateSerialNumber, */
1037 if (tbs->flags.serial) {
1038 ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1039 if (ret) {
1040 hx509_set_error_string(context, 0, ret, "Out of memory");
1041 goto out;
1043 } else {
1044 tbsc->serialNumber.length = 20;
1045 tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1046 if (tbsc->serialNumber.data == NULL){
1047 ret = ENOMEM;
1048 hx509_set_error_string(context, 0, ret, "Out of memory");
1049 goto out;
1051 /* XXX diffrent */
1052 RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1053 ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1055 /* signature AlgorithmIdentifier, */
1056 ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1057 if (ret) {
1058 hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1059 goto out;
1061 /* issuer Name, */
1062 if (issuername)
1063 ret = copy_Name(issuername, &tbsc->issuer);
1064 else
1065 ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1066 if (ret) {
1067 hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1068 goto out;
1070 /* validity Validity, */
1071 tbsc->validity.notBefore.element = choice_Time_generalTime;
1072 tbsc->validity.notBefore.u.generalTime = notBefore;
1073 tbsc->validity.notAfter.element = choice_Time_generalTime;
1074 tbsc->validity.notAfter.u.generalTime = notAfter;
1075 /* subject Name, */
1076 if (tbs->flags.proxy) {
1077 ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1078 if (ret)
1079 goto out;
1080 } else {
1081 ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1082 if (ret) {
1083 hx509_set_error_string(context, 0, ret,
1084 "Failed to copy subject name");
1085 goto out;
1088 /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1089 ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1090 if (ret) {
1091 hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1092 goto out;
1094 /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1095 /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1096 /* extensions [3] EXPLICIT Extensions OPTIONAL */
1097 tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1098 if (tbsc->extensions == NULL) {
1099 ret = ENOMEM;
1100 hx509_set_error_string(context, 0, ret, "Out of memory");
1101 goto out;
1104 /* Add the text BMP string Domaincontroller to the cert */
1105 if (tbs->flags.domaincontroller) {
1106 data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1107 "\x00\x61\x00\x69\x00\x6e\x00\x43"
1108 "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1109 "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1110 "\x00\x72");
1111 data.length = 34;
1113 ret = add_extension(context, tbsc, 0,
1114 oid_id_ms_cert_enroll_domaincontroller(),
1115 &data);
1116 if (ret)
1117 goto out;
1120 /* add KeyUsage */
1122 KeyUsage ku;
1124 ku = int2KeyUsage(key_usage);
1125 ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1126 if (ret) {
1127 hx509_set_error_string(context, 0, ret, "Out of memory");
1128 goto out;
1130 if (size != data.length)
1131 _hx509_abort("internal ASN.1 encoder error");
1132 ret = add_extension(context, tbsc, 1,
1133 oid_id_x509_ce_keyUsage(), &data);
1134 free(data.data);
1135 if (ret)
1136 goto out;
1139 /* add ExtendedKeyUsage */
1140 if (tbs->eku.len > 0) {
1141 ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1142 &tbs->eku, &size, ret);
1143 if (ret) {
1144 hx509_set_error_string(context, 0, ret, "Out of memory");
1145 goto out;
1147 if (size != data.length)
1148 _hx509_abort("internal ASN.1 encoder error");
1149 ret = add_extension(context, tbsc, 0,
1150 oid_id_x509_ce_extKeyUsage(), &data);
1151 free(data.data);
1152 if (ret)
1153 goto out;
1156 /* add Subject Alternative Name */
1157 if (tbs->san.len > 0) {
1158 ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1159 &tbs->san, &size, ret);
1160 if (ret) {
1161 hx509_set_error_string(context, 0, ret, "Out of memory");
1162 goto out;
1164 if (size != data.length)
1165 _hx509_abort("internal ASN.1 encoder error");
1166 ret = add_extension(context, tbsc, 0,
1167 oid_id_x509_ce_subjectAltName(),
1168 &data);
1169 free(data.data);
1170 if (ret)
1171 goto out;
1174 /* Add Authority Key Identifier */
1175 if (ai) {
1176 ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1177 ai, &size, ret);
1178 if (ret) {
1179 hx509_set_error_string(context, 0, ret, "Out of memory");
1180 goto out;
1182 if (size != data.length)
1183 _hx509_abort("internal ASN.1 encoder error");
1184 ret = add_extension(context, tbsc, 0,
1185 oid_id_x509_ce_authorityKeyIdentifier(),
1186 &data);
1187 free(data.data);
1188 if (ret)
1189 goto out;
1192 /* Add Subject Key Identifier */
1194 SubjectKeyIdentifier si;
1195 unsigned char hash[SHA_DIGEST_LENGTH];
1198 SHA_CTX m;
1200 SHA1_Init(&m);
1201 SHA1_Update(&m, tbs->spki.subjectPublicKey.data,
1202 tbs->spki.subjectPublicKey.length / 8);
1203 SHA1_Final (hash, &m);
1206 si.data = hash;
1207 si.length = sizeof(hash);
1209 ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1210 &si, &size, ret);
1211 if (ret) {
1212 hx509_set_error_string(context, 0, ret, "Out of memory");
1213 goto out;
1215 if (size != data.length)
1216 _hx509_abort("internal ASN.1 encoder error");
1217 ret = add_extension(context, tbsc, 0,
1218 oid_id_x509_ce_subjectKeyIdentifier(),
1219 &data);
1220 free(data.data);
1221 if (ret)
1222 goto out;
1225 /* Add BasicConstraints */
1227 BasicConstraints bc;
1228 int aCA = 1;
1229 uint32_t path;
1231 memset(&bc, 0, sizeof(bc));
1233 if (tbs->flags.ca) {
1234 bc.cA = &aCA;
1235 if (tbs->pathLenConstraint >= 0) {
1236 path = tbs->pathLenConstraint;
1237 bc.pathLenConstraint = &path;
1241 ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1242 &bc, &size, ret);
1243 if (ret) {
1244 hx509_set_error_string(context, 0, ret, "Out of memory");
1245 goto out;
1247 if (size != data.length)
1248 _hx509_abort("internal ASN.1 encoder error");
1249 /* Critical if this is a CA */
1250 ret = add_extension(context, tbsc, tbs->flags.ca,
1251 oid_id_x509_ce_basicConstraints(),
1252 &data);
1253 free(data.data);
1254 if (ret)
1255 goto out;
1258 /* add Proxy */
1259 if (tbs->flags.proxy) {
1260 ProxyCertInfo info;
1262 memset(&info, 0, sizeof(info));
1264 if (tbs->pathLenConstraint >= 0) {
1265 info.pCPathLenConstraint =
1266 malloc(sizeof(*info.pCPathLenConstraint));
1267 if (info.pCPathLenConstraint == NULL) {
1268 ret = ENOMEM;
1269 hx509_set_error_string(context, 0, ret, "Out of memory");
1270 goto out;
1272 *info.pCPathLenConstraint = tbs->pathLenConstraint;
1275 ret = der_copy_oid(oid_id_pkix_ppl_inheritAll(),
1276 &info.proxyPolicy.policyLanguage);
1277 if (ret) {
1278 free_ProxyCertInfo(&info);
1279 hx509_set_error_string(context, 0, ret, "Out of memory");
1280 goto out;
1283 ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1284 &info, &size, ret);
1285 free_ProxyCertInfo(&info);
1286 if (ret) {
1287 hx509_set_error_string(context, 0, ret, "Out of memory");
1288 goto out;
1290 if (size != data.length)
1291 _hx509_abort("internal ASN.1 encoder error");
1292 ret = add_extension(context, tbsc, 0,
1293 oid_id_pkix_pe_proxyCertInfo(),
1294 &data);
1295 free(data.data);
1296 if (ret)
1297 goto out;
1300 if (tbs->crldp.len) {
1302 ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1303 &tbs->crldp, &size, ret);
1304 if (ret) {
1305 hx509_set_error_string(context, 0, ret, "Out of memory");
1306 goto out;
1308 if (size != data.length)
1309 _hx509_abort("internal ASN.1 encoder error");
1310 ret = add_extension(context, tbsc, FALSE,
1311 oid_id_x509_ce_cRLDistributionPoints(),
1312 &data);
1313 free(data.data);
1314 if (ret)
1315 goto out;
1318 ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1319 if (ret) {
1320 hx509_set_error_string(context, 0, ret, "malloc out of memory");
1321 goto out;
1323 if (data.length != size)
1324 _hx509_abort("internal ASN.1 encoder error");
1326 ret = _hx509_create_signature_bitstring(context,
1327 signer,
1328 sigalg,
1329 &data,
1330 &c.signatureAlgorithm,
1331 &c.signatureValue);
1332 free(data.data);
1333 if (ret)
1334 goto out;
1336 ret = hx509_cert_init(context, &c, certificate);
1337 if (ret)
1338 goto out;
1340 free_Certificate(&c);
1342 return 0;
1344 out:
1345 free_Certificate(&c);
1346 return ret;
1349 static int
1350 get_AuthorityKeyIdentifier(hx509_context context,
1351 const Certificate *certificate,
1352 AuthorityKeyIdentifier *ai)
1354 SubjectKeyIdentifier si;
1355 int ret;
1357 ret = _hx509_find_extension_subject_key_id(certificate, &si);
1358 if (ret == 0) {
1359 ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1360 if (ai->keyIdentifier == NULL) {
1361 free_SubjectKeyIdentifier(&si);
1362 ret = ENOMEM;
1363 hx509_set_error_string(context, 0, ret, "Out of memory");
1364 goto out;
1366 ret = der_copy_octet_string(&si, ai->keyIdentifier);
1367 free_SubjectKeyIdentifier(&si);
1368 if (ret) {
1369 hx509_set_error_string(context, 0, ret, "Out of memory");
1370 goto out;
1372 } else {
1373 GeneralNames gns;
1374 GeneralName gn;
1375 Name name;
1377 memset(&gn, 0, sizeof(gn));
1378 memset(&gns, 0, sizeof(gns));
1379 memset(&name, 0, sizeof(name));
1381 ai->authorityCertIssuer =
1382 calloc(1, sizeof(*ai->authorityCertIssuer));
1383 if (ai->authorityCertIssuer == NULL) {
1384 ret = ENOMEM;
1385 hx509_set_error_string(context, 0, ret, "Out of memory");
1386 goto out;
1388 ai->authorityCertSerialNumber =
1389 calloc(1, sizeof(*ai->authorityCertSerialNumber));
1390 if (ai->authorityCertSerialNumber == NULL) {
1391 ret = ENOMEM;
1392 hx509_set_error_string(context, 0, ret, "Out of memory");
1393 goto out;
1397 * XXX unbreak when asn1 compiler handle IMPLICIT
1399 * This is so horrible.
1402 ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1403 if (ai->authorityCertSerialNumber == NULL) {
1404 ret = ENOMEM;
1405 hx509_set_error_string(context, 0, ret, "Out of memory");
1406 goto out;
1409 memset(&gn, 0, sizeof(gn));
1410 gn.element = choice_GeneralName_directoryName;
1411 gn.u.directoryName.element =
1412 choice_GeneralName_directoryName_rdnSequence;
1413 gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1415 ret = add_GeneralNames(&gns, &gn);
1416 if (ret) {
1417 hx509_set_error_string(context, 0, ret, "Out of memory");
1418 goto out;
1421 ai->authorityCertIssuer->val = gns.val;
1422 ai->authorityCertIssuer->len = gns.len;
1424 ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1425 ai->authorityCertSerialNumber);
1426 if (ai->authorityCertSerialNumber == NULL) {
1427 ret = ENOMEM;
1428 hx509_set_error_string(context, 0, ret, "Out of memory");
1429 goto out;
1432 out:
1433 if (ret)
1434 free_AuthorityKeyIdentifier(ai);
1435 return ret;
1440 * Sign a to-be-signed certificate object with a issuer certificate.
1442 * The caller needs to at least have called the following functions on the
1443 * to-be-signed certificate object:
1444 * - hx509_ca_tbs_init()
1445 * - hx509_ca_tbs_set_subject()
1446 * - hx509_ca_tbs_set_spki()
1448 * When done the to-be-signed certificate object should be freed with
1449 * hx509_ca_tbs_free().
1451 * When creating self-signed certificate use hx509_ca_sign_self() instead.
1453 * @param context A hx509 context.
1454 * @param tbs object to be signed.
1455 * @param signer the CA certificate object to sign with (need private key).
1456 * @param certificate return cerificate, free with hx509_cert_free().
1458 * @return An hx509 error code, see hx509_get_error_string().
1460 * @ingroup hx509_ca
1464 hx509_ca_sign(hx509_context context,
1465 hx509_ca_tbs tbs,
1466 hx509_cert signer,
1467 hx509_cert *certificate)
1469 const Certificate *signer_cert;
1470 AuthorityKeyIdentifier ai;
1471 int ret;
1473 memset(&ai, 0, sizeof(ai));
1475 signer_cert = _hx509_get_cert(signer);
1477 ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1478 if (ret)
1479 goto out;
1481 ret = ca_sign(context,
1482 tbs,
1483 _hx509_cert_private_key(signer),
1484 &ai,
1485 &signer_cert->tbsCertificate.subject,
1486 certificate);
1488 out:
1489 free_AuthorityKeyIdentifier(&ai);
1491 return ret;
1495 * Work just like hx509_ca_sign() but signs it-self.
1497 * @param context A hx509 context.
1498 * @param tbs object to be signed.
1499 * @param signer private key to sign with.
1500 * @param certificate return cerificate, free with hx509_cert_free().
1502 * @return An hx509 error code, see hx509_get_error_string().
1504 * @ingroup hx509_ca
1508 hx509_ca_sign_self(hx509_context context,
1509 hx509_ca_tbs tbs,
1510 hx509_private_key signer,
1511 hx509_cert *certificate)
1513 return ca_sign(context,
1514 tbs,
1515 signer,
1516 NULL,
1517 NULL,
1518 certificate);