count number of enctypes too
[heimdal.git] / lib / hx509 / ca.c
blobcb5a7be62cc30626a062a4c62dcc89492d3db791
1 /*
2 * Copyright (c) 2006 - 2010 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>
37 /**
38 * @page page_ca Hx509 CA functions
40 * See the library functions here: @ref hx509_ca
43 struct hx509_ca_tbs {
44 hx509_name subject;
45 SubjectPublicKeyInfo spki;
46 ExtKeyUsage eku;
47 GeneralNames san;
48 unsigned key_usage;
49 heim_integer serial;
50 struct {
51 unsigned int proxy:1;
52 unsigned int ca:1;
53 unsigned int key:1;
54 unsigned int serial:1;
55 unsigned int domaincontroller:1;
56 unsigned int xUniqueID:1;
57 } flags;
58 time_t notBefore;
59 time_t notAfter;
60 int pathLenConstraint; /* both for CA and Proxy */
61 CRLDistributionPoints crldp;
62 heim_bit_string subjectUniqueID;
63 heim_bit_string issuerUniqueID;
67 /**
68 * Allocate an to-be-signed certificate object that will be converted
69 * into an certificate.
71 * @param context A hx509 context.
72 * @param tbs returned to-be-signed certicate object, free with
73 * hx509_ca_tbs_free().
75 * @return An hx509 error code, see hx509_get_error_string().
77 * @ingroup hx509_ca
80 int
81 hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
83 *tbs = calloc(1, sizeof(**tbs));
84 if (*tbs == NULL)
85 return ENOMEM;
87 return 0;
90 /**
91 * Free an To Be Signed object.
93 * @param tbs object to free.
95 * @ingroup hx509_ca
98 void
99 hx509_ca_tbs_free(hx509_ca_tbs *tbs)
101 if (tbs == NULL || *tbs == NULL)
102 return;
104 free_SubjectPublicKeyInfo(&(*tbs)->spki);
105 free_GeneralNames(&(*tbs)->san);
106 free_ExtKeyUsage(&(*tbs)->eku);
107 der_free_heim_integer(&(*tbs)->serial);
108 free_CRLDistributionPoints(&(*tbs)->crldp);
109 der_free_bit_string(&(*tbs)->subjectUniqueID);
110 der_free_bit_string(&(*tbs)->issuerUniqueID);
111 hx509_name_free(&(*tbs)->subject);
113 memset(*tbs, 0, sizeof(**tbs));
114 free(*tbs);
115 *tbs = NULL;
119 * Set the absolute time when the certificate is valid from. If not
120 * set the current time will be used.
122 * @param context A hx509 context.
123 * @param tbs object to be signed.
124 * @param t time the certificated will start to be valid
126 * @return An hx509 error code, see hx509_get_error_string().
128 * @ingroup hx509_ca
132 hx509_ca_tbs_set_notBefore(hx509_context context,
133 hx509_ca_tbs tbs,
134 time_t t)
136 tbs->notBefore = t;
137 return 0;
141 * Set the absolute time when the certificate is valid to.
143 * @param context A hx509 context.
144 * @param tbs object to be signed.
145 * @param t time when the certificate will expire
147 * @return An hx509 error code, see hx509_get_error_string().
149 * @ingroup hx509_ca
153 hx509_ca_tbs_set_notAfter(hx509_context context,
154 hx509_ca_tbs tbs,
155 time_t t)
157 tbs->notAfter = t;
158 return 0;
162 * Set the relative time when the certificiate is going to expire.
164 * @param context A hx509 context.
165 * @param tbs object to be signed.
166 * @param delta seconds to the certificate is going to expire.
168 * @return An hx509 error code, see hx509_get_error_string().
170 * @ingroup hx509_ca
174 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
175 hx509_ca_tbs tbs,
176 time_t delta)
178 return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
181 static const struct units templatebits[] = {
182 { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
183 { "KeyUsage", HX509_CA_TEMPLATE_KU },
184 { "SPKI", HX509_CA_TEMPLATE_SPKI },
185 { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
186 { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
187 { "serial", HX509_CA_TEMPLATE_SERIAL },
188 { "subject", HX509_CA_TEMPLATE_SUBJECT },
189 { NULL, 0 }
193 * Make of template units, use to build flags argument to
194 * hx509_ca_tbs_set_template() with parse_units().
196 * @return an units structure.
198 * @ingroup hx509_ca
201 const struct units *
202 hx509_ca_tbs_template_units(void)
204 return templatebits;
208 * Initialize the to-be-signed certificate object from a template certifiate.
210 * @param context A hx509 context.
211 * @param tbs object to be signed.
212 * @param flags bit field selecting what to copy from the template
213 * certifiate.
214 * @param cert template certificate.
216 * @return An hx509 error code, see hx509_get_error_string().
218 * @ingroup hx509_ca
222 hx509_ca_tbs_set_template(hx509_context context,
223 hx509_ca_tbs tbs,
224 int flags,
225 hx509_cert cert)
227 int ret;
229 if (flags & HX509_CA_TEMPLATE_SUBJECT) {
230 if (tbs->subject)
231 hx509_name_free(&tbs->subject);
232 ret = hx509_cert_get_subject(cert, &tbs->subject);
233 if (ret) {
234 hx509_set_error_string(context, 0, ret,
235 "Failed to get subject from template");
236 return ret;
239 if (flags & HX509_CA_TEMPLATE_SERIAL) {
240 der_free_heim_integer(&tbs->serial);
241 ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
242 tbs->flags.serial = !ret;
243 if (ret) {
244 hx509_set_error_string(context, 0, ret,
245 "Failed to copy serial number");
246 return ret;
249 if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
250 tbs->notBefore = hx509_cert_get_notBefore(cert);
251 if (flags & HX509_CA_TEMPLATE_NOTAFTER)
252 tbs->notAfter = hx509_cert_get_notAfter(cert);
253 if (flags & HX509_CA_TEMPLATE_SPKI) {
254 free_SubjectPublicKeyInfo(&tbs->spki);
255 ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
256 tbs->flags.key = !ret;
257 if (ret)
258 return ret;
260 if (flags & HX509_CA_TEMPLATE_KU) {
261 KeyUsage ku;
262 ret = _hx509_cert_get_keyusage(context, cert, &ku);
263 if (ret)
264 return ret;
265 tbs->key_usage = KeyUsage2int(ku);
267 if (flags & HX509_CA_TEMPLATE_EKU) {
268 ExtKeyUsage eku;
269 size_t i;
270 ret = _hx509_cert_get_eku(context, cert, &eku);
271 if (ret)
272 return ret;
273 for (i = 0; i < eku.len; i++) {
274 ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
275 if (ret) {
276 free_ExtKeyUsage(&eku);
277 return ret;
280 free_ExtKeyUsage(&eku);
282 return 0;
286 * Make the to-be-signed certificate object a CA certificate. If the
287 * pathLenConstraint is negative path length constraint is used.
289 * @param context A hx509 context.
290 * @param tbs object to be signed.
291 * @param pathLenConstraint path length constraint, negative, no
292 * constraint.
294 * @return An hx509 error code, see hx509_get_error_string().
296 * @ingroup hx509_ca
300 hx509_ca_tbs_set_ca(hx509_context context,
301 hx509_ca_tbs tbs,
302 int pathLenConstraint)
304 tbs->flags.ca = 1;
305 tbs->pathLenConstraint = pathLenConstraint;
306 return 0;
310 * Make the to-be-signed certificate object a proxy certificate. If the
311 * pathLenConstraint is negative path length constraint is used.
313 * @param context A hx509 context.
314 * @param tbs object to be signed.
315 * @param pathLenConstraint path length constraint, negative, no
316 * constraint.
318 * @return An hx509 error code, see hx509_get_error_string().
320 * @ingroup hx509_ca
324 hx509_ca_tbs_set_proxy(hx509_context context,
325 hx509_ca_tbs tbs,
326 int pathLenConstraint)
328 tbs->flags.proxy = 1;
329 tbs->pathLenConstraint = pathLenConstraint;
330 return 0;
335 * Make the to-be-signed certificate object a windows domain controller certificate.
337 * @param context A hx509 context.
338 * @param tbs object to be signed.
340 * @return An hx509 error code, see hx509_get_error_string().
342 * @ingroup hx509_ca
346 hx509_ca_tbs_set_domaincontroller(hx509_context context,
347 hx509_ca_tbs tbs)
349 tbs->flags.domaincontroller = 1;
350 return 0;
354 * Set the subject public key info (SPKI) in the to-be-signed certificate
355 * object. SPKI is the public key and key related parameters in the
356 * certificate.
358 * @param context A hx509 context.
359 * @param tbs object to be signed.
360 * @param spki subject public key info to use for the to-be-signed certificate object.
362 * @return An hx509 error code, see hx509_get_error_string().
364 * @ingroup hx509_ca
368 hx509_ca_tbs_set_spki(hx509_context context,
369 hx509_ca_tbs tbs,
370 const SubjectPublicKeyInfo *spki)
372 int ret;
373 free_SubjectPublicKeyInfo(&tbs->spki);
374 ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
375 tbs->flags.key = !ret;
376 return ret;
380 * Set the serial number to use for to-be-signed certificate object.
382 * @param context A hx509 context.
383 * @param tbs object to be signed.
384 * @param serialNumber serial number to use for the to-be-signed
385 * certificate object.
387 * @return An hx509 error code, see hx509_get_error_string().
389 * @ingroup hx509_ca
393 hx509_ca_tbs_set_serialnumber(hx509_context context,
394 hx509_ca_tbs tbs,
395 const heim_integer *serialNumber)
397 int ret;
398 der_free_heim_integer(&tbs->serial);
399 ret = der_copy_heim_integer(serialNumber, &tbs->serial);
400 tbs->flags.serial = !ret;
401 return ret;
405 * An an extended key usage to the to-be-signed certificate object.
406 * Duplicates will detected and not added.
408 * @param context A hx509 context.
409 * @param tbs object to be signed.
410 * @param oid extended key usage to add.
412 * @return An hx509 error code, see hx509_get_error_string().
414 * @ingroup hx509_ca
418 hx509_ca_tbs_add_eku(hx509_context context,
419 hx509_ca_tbs tbs,
420 const heim_oid *oid)
422 void *ptr;
423 int ret;
424 unsigned i;
426 /* search for duplicates */
427 for (i = 0; i < tbs->eku.len; i++) {
428 if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
429 return 0;
432 ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
433 if (ptr == NULL) {
434 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
435 return ENOMEM;
437 tbs->eku.val = ptr;
438 ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
439 if (ret) {
440 hx509_set_error_string(context, 0, ret, "out of memory");
441 return ret;
443 tbs->eku.len += 1;
444 return 0;
448 * Add CRL distribution point URI to the to-be-signed certificate
449 * object.
451 * @param context A hx509 context.
452 * @param tbs object to be signed.
453 * @param uri uri to the CRL.
454 * @param issuername name of the issuer.
456 * @return An hx509 error code, see hx509_get_error_string().
458 * @ingroup hx509_ca
462 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
463 hx509_ca_tbs tbs,
464 const char *uri,
465 hx509_name issuername)
467 DistributionPoint dp;
468 int ret;
470 memset(&dp, 0, sizeof(dp));
472 dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
475 DistributionPointName name;
476 GeneralName gn;
477 size_t size;
479 name.element = choice_DistributionPointName_fullName;
480 name.u.fullName.len = 1;
481 name.u.fullName.val = &gn;
483 gn.element = choice_GeneralName_uniformResourceIdentifier;
484 gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
485 gn.u.uniformResourceIdentifier.length = strlen(uri);
487 ASN1_MALLOC_ENCODE(DistributionPointName,
488 dp.distributionPoint->data,
489 dp.distributionPoint->length,
490 &name, &size, ret);
491 if (ret) {
492 hx509_set_error_string(context, 0, ret,
493 "Failed to encoded DistributionPointName");
494 goto out;
496 if (dp.distributionPoint->length != size)
497 _hx509_abort("internal ASN.1 encoder error");
500 if (issuername) {
501 #if 1
503 * issuername not supported
505 hx509_set_error_string(context, 0, EINVAL,
506 "CRLDistributionPoints.name.issuername not yet supported");
507 return EINVAL;
508 #else
509 GeneralNames *crlissuer;
510 GeneralName gn;
511 Name n;
513 crlissuer = calloc(1, sizeof(*crlissuer));
514 if (crlissuer == NULL) {
515 return ENOMEM;
517 memset(&gn, 0, sizeof(gn));
519 gn.element = choice_GeneralName_directoryName;
520 ret = hx509_name_to_Name(issuername, &n);
521 if (ret) {
522 hx509_set_error_string(context, 0, ret, "out of memory");
523 goto out;
526 gn.u.directoryName.element = n.element;
527 gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
529 ret = add_GeneralNames(&crlissuer, &gn);
530 free_Name(&n);
531 if (ret) {
532 hx509_set_error_string(context, 0, ret, "out of memory");
533 goto out;
536 dp.cRLIssuer = &crlissuer;
537 #endif
540 ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
541 if (ret) {
542 hx509_set_error_string(context, 0, ret, "out of memory");
543 goto out;
546 out:
547 free_DistributionPoint(&dp);
549 return ret;
553 * Add Subject Alternative Name otherName to the to-be-signed
554 * certificate object.
556 * @param context A hx509 context.
557 * @param tbs object to be signed.
558 * @param oid the oid of the OtherName.
559 * @param os data in the other name.
561 * @return An hx509 error code, see hx509_get_error_string().
563 * @ingroup hx509_ca
567 hx509_ca_tbs_add_san_otherName(hx509_context context,
568 hx509_ca_tbs tbs,
569 const heim_oid *oid,
570 const heim_octet_string *os)
572 GeneralName gn;
574 memset(&gn, 0, sizeof(gn));
575 gn.element = choice_GeneralName_otherName;
576 gn.u.otherName.type_id = *oid;
577 gn.u.otherName.value = *os;
579 return add_GeneralNames(&tbs->san, &gn);
583 * Add Kerberos Subject Alternative Name to the to-be-signed
584 * certificate object. The principal string is a UTF8 string.
586 * @param context A hx509 context.
587 * @param tbs object to be signed.
588 * @param principal Kerberos principal to add to the certificate.
590 * @return An hx509 error code, see hx509_get_error_string().
592 * @ingroup hx509_ca
596 hx509_ca_tbs_add_san_pkinit(hx509_context context,
597 hx509_ca_tbs tbs,
598 const char *principal)
600 heim_octet_string os;
601 KRB5PrincipalName p;
602 size_t size;
603 int ret;
604 char *s = NULL;
606 memset(&p, 0, sizeof(p));
608 /* parse principal */
610 const char *str;
611 char *q;
612 int n;
614 /* count number of component */
615 n = 1;
616 for(str = principal; *str != '\0' && *str != '@'; str++){
617 if(*str=='\\'){
618 if(str[1] == '\0' || str[1] == '@') {
619 ret = HX509_PARSING_NAME_FAILED;
620 hx509_set_error_string(context, 0, ret,
621 "trailing \\ in principal name");
622 goto out;
624 str++;
625 } else if(*str == '/')
626 n++;
628 p.principalName.name_string.val =
629 calloc(n, sizeof(*p.principalName.name_string.val));
630 if (p.principalName.name_string.val == NULL) {
631 ret = ENOMEM;
632 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
633 goto out;
635 p.principalName.name_string.len = n;
637 p.principalName.name_type = KRB5_NT_PRINCIPAL;
638 q = s = strdup(principal);
639 if (q == NULL) {
640 ret = ENOMEM;
641 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
642 goto out;
644 p.realm = strrchr(q, '@');
645 if (p.realm == NULL) {
646 ret = HX509_PARSING_NAME_FAILED;
647 hx509_set_error_string(context, 0, ret, "Missing @ in principal");
648 goto out;
650 *p.realm++ = '\0';
652 n = 0;
653 while (q) {
654 p.principalName.name_string.val[n++] = q;
655 q = strchr(q, '/');
656 if (q)
657 *q++ = '\0';
661 ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
662 if (ret) {
663 hx509_set_error_string(context, 0, ret, "Out of memory");
664 goto out;
666 if (size != os.length)
667 _hx509_abort("internal ASN.1 encoder error");
669 ret = hx509_ca_tbs_add_san_otherName(context,
670 tbs,
671 &asn1_oid_id_pkinit_san,
672 &os);
673 free(os.data);
674 out:
675 if (p.principalName.name_string.val)
676 free (p.principalName.name_string.val);
677 if (s)
678 free(s);
679 return ret;
686 static int
687 add_utf8_san(hx509_context context,
688 hx509_ca_tbs tbs,
689 const heim_oid *oid,
690 const char *string)
692 const PKIXXmppAddr ustring = (const PKIXXmppAddr)(intptr_t)string;
693 heim_octet_string os;
694 size_t size;
695 int ret;
697 os.length = 0;
698 os.data = NULL;
700 ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
701 if (ret) {
702 hx509_set_error_string(context, 0, ret, "Out of memory");
703 goto out;
705 if (size != os.length)
706 _hx509_abort("internal ASN.1 encoder error");
708 ret = hx509_ca_tbs_add_san_otherName(context,
709 tbs,
710 oid,
711 &os);
712 free(os.data);
713 out:
714 return ret;
718 * Add Microsoft UPN Subject Alternative Name to the to-be-signed
719 * certificate object. The principal string is a UTF8 string.
721 * @param context A hx509 context.
722 * @param tbs object to be signed.
723 * @param principal Microsoft UPN string.
725 * @return An hx509 error code, see hx509_get_error_string().
727 * @ingroup hx509_ca
731 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
732 hx509_ca_tbs tbs,
733 const char *principal)
735 return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
739 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
740 * certificate object. The jid is an UTF8 string.
742 * @param context A hx509 context.
743 * @param tbs object to be signed.
744 * @param jid string of an a jabber id in UTF8.
746 * @return An hx509 error code, see hx509_get_error_string().
748 * @ingroup hx509_ca
752 hx509_ca_tbs_add_san_jid(hx509_context context,
753 hx509_ca_tbs tbs,
754 const char *jid)
756 return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
761 * Add a Subject Alternative Name hostname to to-be-signed certificate
762 * object. A domain match starts with ., an exact match does not.
764 * Example of a an domain match: .domain.se matches the hostname
765 * host.domain.se.
767 * @param context A hx509 context.
768 * @param tbs object to be signed.
769 * @param dnsname a hostame.
771 * @return An hx509 error code, see hx509_get_error_string().
773 * @ingroup hx509_ca
777 hx509_ca_tbs_add_san_hostname(hx509_context context,
778 hx509_ca_tbs tbs,
779 const char *dnsname)
781 GeneralName gn;
783 memset(&gn, 0, sizeof(gn));
784 gn.element = choice_GeneralName_dNSName;
785 gn.u.dNSName.data = rk_UNCONST(dnsname);
786 gn.u.dNSName.length = strlen(dnsname);
788 return add_GeneralNames(&tbs->san, &gn);
792 * Add a Subject Alternative Name rfc822 (email address) to
793 * to-be-signed certificate object.
795 * @param context A hx509 context.
796 * @param tbs object to be signed.
797 * @param rfc822Name a string to a email address.
799 * @return An hx509 error code, see hx509_get_error_string().
801 * @ingroup hx509_ca
805 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
806 hx509_ca_tbs tbs,
807 const char *rfc822Name)
809 GeneralName gn;
811 memset(&gn, 0, sizeof(gn));
812 gn.element = choice_GeneralName_rfc822Name;
813 gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
814 gn.u.rfc822Name.length = strlen(rfc822Name);
816 return add_GeneralNames(&tbs->san, &gn);
820 * Set the subject name of a to-be-signed certificate object.
822 * @param context A hx509 context.
823 * @param tbs object to be signed.
824 * @param subject the name to set a subject.
826 * @return An hx509 error code, see hx509_get_error_string().
828 * @ingroup hx509_ca
832 hx509_ca_tbs_set_subject(hx509_context context,
833 hx509_ca_tbs tbs,
834 hx509_name subject)
836 if (tbs->subject)
837 hx509_name_free(&tbs->subject);
838 return hx509_name_copy(context, subject, &tbs->subject);
842 * Set the issuerUniqueID and subjectUniqueID
844 * These are only supposed to be used considered with version 2
845 * certificates, replaced by the two extensions SubjectKeyIdentifier
846 * and IssuerKeyIdentifier. This function is to allow application
847 * using legacy protocol to issue them.
849 * @param context A hx509 context.
850 * @param tbs object to be signed.
851 * @param issuerUniqueID to be set
852 * @param subjectUniqueID to be set
854 * @return An hx509 error code, see hx509_get_error_string().
856 * @ingroup hx509_ca
860 hx509_ca_tbs_set_unique(hx509_context context,
861 hx509_ca_tbs tbs,
862 const heim_bit_string *subjectUniqueID,
863 const heim_bit_string *issuerUniqueID)
865 int ret;
867 der_free_bit_string(&tbs->subjectUniqueID);
868 der_free_bit_string(&tbs->issuerUniqueID);
870 if (subjectUniqueID) {
871 ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
872 if (ret)
873 return ret;
876 if (issuerUniqueID) {
877 ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
878 if (ret)
879 return ret;
882 return 0;
886 * Expand the the subject name in the to-be-signed certificate object
887 * using hx509_name_expand().
889 * @param context A hx509 context.
890 * @param tbs object to be signed.
891 * @param env enviroment variable to expand variables in the subject
892 * name, see hx509_env_init().
894 * @return An hx509 error code, see hx509_get_error_string().
896 * @ingroup hx509_ca
900 hx509_ca_tbs_subject_expand(hx509_context context,
901 hx509_ca_tbs tbs,
902 hx509_env env)
904 return hx509_name_expand(context, tbs->subject, env);
911 static int
912 add_extension(hx509_context context,
913 TBSCertificate *tbsc,
914 int critical_flag,
915 const heim_oid *oid,
916 const heim_octet_string *data)
918 Extension ext;
919 int ret;
921 memset(&ext, 0, sizeof(ext));
923 if (critical_flag) {
924 ext.critical = malloc(sizeof(*ext.critical));
925 if (ext.critical == NULL) {
926 ret = ENOMEM;
927 hx509_set_error_string(context, 0, ret, "Out of memory");
928 goto out;
930 *ext.critical = TRUE;
933 ret = der_copy_oid(oid, &ext.extnID);
934 if (ret) {
935 hx509_set_error_string(context, 0, ret, "Out of memory");
936 goto out;
938 ret = der_copy_octet_string(data, &ext.extnValue);
939 if (ret) {
940 hx509_set_error_string(context, 0, ret, "Out of memory");
941 goto out;
943 ret = add_Extensions(tbsc->extensions, &ext);
944 if (ret) {
945 hx509_set_error_string(context, 0, ret, "Out of memory");
946 goto out;
948 out:
949 free_Extension(&ext);
950 return ret;
953 static int
954 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
956 char *tstr;
957 time_t t;
958 int ret;
960 ret = copy_Name(issuer, subject);
961 if (ret) {
962 hx509_set_error_string(context, 0, ret,
963 "Failed to copy subject name");
964 return ret;
967 t = time(NULL);
968 asprintf(&tstr, "ts-%lu", (unsigned long)t);
969 if (tstr == NULL) {
970 hx509_set_error_string(context, 0, ENOMEM,
971 "Failed to copy subject name");
972 return ENOMEM;
974 /* prefix with CN=<ts>,...*/
975 ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
976 free(tstr);
977 if (ret)
978 free_Name(subject);
979 return ret;
982 static int
983 ca_sign(hx509_context context,
984 hx509_ca_tbs tbs,
985 hx509_private_key signer,
986 const AuthorityKeyIdentifier *ai,
987 const Name *issuername,
988 hx509_cert *certificate)
990 heim_octet_string data;
991 Certificate c;
992 TBSCertificate *tbsc;
993 size_t size;
994 int ret;
995 const AlgorithmIdentifier *sigalg;
996 time_t notBefore;
997 time_t notAfter;
998 unsigned key_usage;
1000 sigalg = _hx509_crypto_default_sig_alg;
1002 memset(&c, 0, sizeof(c));
1005 * Default values are: Valid since 24h ago, valid one year into
1006 * the future, KeyUsage digitalSignature and keyEncipherment set,
1007 * and keyCertSign for CA certificates.
1009 notBefore = tbs->notBefore;
1010 if (notBefore == 0)
1011 notBefore = time(NULL) - 3600 * 24;
1012 notAfter = tbs->notAfter;
1013 if (notAfter == 0)
1014 notAfter = time(NULL) + 3600 * 24 * 365;
1016 key_usage = tbs->key_usage;
1017 if (key_usage == 0) {
1018 KeyUsage ku;
1019 memset(&ku, 0, sizeof(ku));
1020 ku.digitalSignature = 1;
1021 ku.keyEncipherment = 1;
1022 key_usage = KeyUsage2int(ku);
1025 if (tbs->flags.ca) {
1026 KeyUsage ku;
1027 memset(&ku, 0, sizeof(ku));
1028 ku.keyCertSign = 1;
1029 ku.cRLSign = 1;
1030 key_usage |= KeyUsage2int(ku);
1037 tbsc = &c.tbsCertificate;
1039 if (tbs->flags.key == 0) {
1040 ret = EINVAL;
1041 hx509_set_error_string(context, 0, ret, "No public key set");
1042 return ret;
1045 * Don't put restrictions on proxy certificate's subject name, it
1046 * will be generated below.
1048 if (!tbs->flags.proxy) {
1049 if (tbs->subject == NULL) {
1050 hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1051 return EINVAL;
1053 if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1054 hx509_set_error_string(context, 0, EINVAL,
1055 "NULL subject and no SubjectAltNames");
1056 return EINVAL;
1059 if (tbs->flags.ca && tbs->flags.proxy) {
1060 hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1061 "at the same time");
1062 return EINVAL;
1064 if (tbs->flags.proxy) {
1065 if (tbs->san.len > 0) {
1066 hx509_set_error_string(context, 0, EINVAL,
1067 "Proxy certificate is not allowed "
1068 "to have SubjectAltNames");
1069 return EINVAL;
1073 /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1074 tbsc->version = calloc(1, sizeof(*tbsc->version));
1075 if (tbsc->version == NULL) {
1076 ret = ENOMEM;
1077 hx509_set_error_string(context, 0, ret, "Out of memory");
1078 goto out;
1080 *tbsc->version = rfc3280_version_3;
1081 /* serialNumber CertificateSerialNumber, */
1082 if (tbs->flags.serial) {
1083 ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1084 if (ret) {
1085 hx509_set_error_string(context, 0, ret, "Out of memory");
1086 goto out;
1088 } else {
1089 tbsc->serialNumber.length = 20;
1090 tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1091 if (tbsc->serialNumber.data == NULL){
1092 ret = ENOMEM;
1093 hx509_set_error_string(context, 0, ret, "Out of memory");
1094 goto out;
1096 /* XXX diffrent */
1097 RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1098 ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1100 /* signature AlgorithmIdentifier, */
1101 ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1102 if (ret) {
1103 hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1104 goto out;
1106 /* issuer Name, */
1107 if (issuername)
1108 ret = copy_Name(issuername, &tbsc->issuer);
1109 else
1110 ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1111 if (ret) {
1112 hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1113 goto out;
1115 /* validity Validity, */
1116 tbsc->validity.notBefore.element = choice_Time_generalTime;
1117 tbsc->validity.notBefore.u.generalTime = notBefore;
1118 tbsc->validity.notAfter.element = choice_Time_generalTime;
1119 tbsc->validity.notAfter.u.generalTime = notAfter;
1120 /* subject Name, */
1121 if (tbs->flags.proxy) {
1122 ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1123 if (ret)
1124 goto out;
1125 } else {
1126 ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1127 if (ret) {
1128 hx509_set_error_string(context, 0, ret,
1129 "Failed to copy subject name");
1130 goto out;
1133 /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1134 ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1135 if (ret) {
1136 hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1137 goto out;
1139 /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1140 if (tbs->issuerUniqueID.length) {
1141 tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1142 if (tbsc->issuerUniqueID == NULL) {
1143 ret = ENOMEM;
1144 hx509_set_error_string(context, 0, ret, "Out of memory");
1145 goto out;
1147 ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1148 if (ret) {
1149 hx509_set_error_string(context, 0, ret, "Out of memory");
1150 goto out;
1153 /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1154 if (tbs->subjectUniqueID.length) {
1155 tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1156 if (tbsc->subjectUniqueID == NULL) {
1157 ret = ENOMEM;
1158 hx509_set_error_string(context, 0, ret, "Out of memory");
1159 goto out;
1162 ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1163 if (ret) {
1164 hx509_set_error_string(context, 0, ret, "Out of memory");
1165 goto out;
1169 /* extensions [3] EXPLICIT Extensions OPTIONAL */
1170 tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1171 if (tbsc->extensions == NULL) {
1172 ret = ENOMEM;
1173 hx509_set_error_string(context, 0, ret, "Out of memory");
1174 goto out;
1177 /* Add the text BMP string Domaincontroller to the cert */
1178 if (tbs->flags.domaincontroller) {
1179 data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1180 "\x00\x61\x00\x69\x00\x6e\x00\x43"
1181 "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1182 "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1183 "\x00\x72");
1184 data.length = 34;
1186 ret = add_extension(context, tbsc, 0,
1187 &asn1_oid_id_ms_cert_enroll_domaincontroller,
1188 &data);
1189 if (ret)
1190 goto out;
1193 /* add KeyUsage */
1195 KeyUsage ku;
1197 ku = int2KeyUsage(key_usage);
1198 ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1199 if (ret) {
1200 hx509_set_error_string(context, 0, ret, "Out of memory");
1201 goto out;
1203 if (size != data.length)
1204 _hx509_abort("internal ASN.1 encoder error");
1205 ret = add_extension(context, tbsc, 1,
1206 &asn1_oid_id_x509_ce_keyUsage, &data);
1207 free(data.data);
1208 if (ret)
1209 goto out;
1212 /* add ExtendedKeyUsage */
1213 if (tbs->eku.len > 0) {
1214 ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1215 &tbs->eku, &size, ret);
1216 if (ret) {
1217 hx509_set_error_string(context, 0, ret, "Out of memory");
1218 goto out;
1220 if (size != data.length)
1221 _hx509_abort("internal ASN.1 encoder error");
1222 ret = add_extension(context, tbsc, 0,
1223 &asn1_oid_id_x509_ce_extKeyUsage, &data);
1224 free(data.data);
1225 if (ret)
1226 goto out;
1229 /* add Subject Alternative Name */
1230 if (tbs->san.len > 0) {
1231 ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1232 &tbs->san, &size, ret);
1233 if (ret) {
1234 hx509_set_error_string(context, 0, ret, "Out of memory");
1235 goto out;
1237 if (size != data.length)
1238 _hx509_abort("internal ASN.1 encoder error");
1239 ret = add_extension(context, tbsc, 0,
1240 &asn1_oid_id_x509_ce_subjectAltName,
1241 &data);
1242 free(data.data);
1243 if (ret)
1244 goto out;
1247 /* Add Authority Key Identifier */
1248 if (ai) {
1249 ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1250 ai, &size, ret);
1251 if (ret) {
1252 hx509_set_error_string(context, 0, ret, "Out of memory");
1253 goto out;
1255 if (size != data.length)
1256 _hx509_abort("internal ASN.1 encoder error");
1257 ret = add_extension(context, tbsc, 0,
1258 &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1259 &data);
1260 free(data.data);
1261 if (ret)
1262 goto out;
1265 /* Add Subject Key Identifier */
1267 SubjectKeyIdentifier si;
1268 unsigned char hash[SHA_DIGEST_LENGTH];
1271 EVP_MD_CTX *ctx;
1273 ctx = EVP_MD_CTX_create();
1274 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1275 EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1276 tbs->spki.subjectPublicKey.length / 8);
1277 EVP_DigestFinal_ex(ctx, hash, NULL);
1278 EVP_MD_CTX_destroy(ctx);
1281 si.data = hash;
1282 si.length = sizeof(hash);
1284 ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1285 &si, &size, ret);
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 &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1294 &data);
1295 free(data.data);
1296 if (ret)
1297 goto out;
1300 /* Add BasicConstraints */
1302 BasicConstraints bc;
1303 int aCA = 1;
1304 unsigned int path;
1306 memset(&bc, 0, sizeof(bc));
1308 if (tbs->flags.ca) {
1309 bc.cA = &aCA;
1310 if (tbs->pathLenConstraint >= 0) {
1311 path = tbs->pathLenConstraint;
1312 bc.pathLenConstraint = &path;
1316 ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1317 &bc, &size, ret);
1318 if (ret) {
1319 hx509_set_error_string(context, 0, ret, "Out of memory");
1320 goto out;
1322 if (size != data.length)
1323 _hx509_abort("internal ASN.1 encoder error");
1324 /* Critical if this is a CA */
1325 ret = add_extension(context, tbsc, tbs->flags.ca,
1326 &asn1_oid_id_x509_ce_basicConstraints,
1327 &data);
1328 free(data.data);
1329 if (ret)
1330 goto out;
1333 /* add Proxy */
1334 if (tbs->flags.proxy) {
1335 ProxyCertInfo info;
1337 memset(&info, 0, sizeof(info));
1339 if (tbs->pathLenConstraint >= 0) {
1340 info.pCPathLenConstraint =
1341 malloc(sizeof(*info.pCPathLenConstraint));
1342 if (info.pCPathLenConstraint == NULL) {
1343 ret = ENOMEM;
1344 hx509_set_error_string(context, 0, ret, "Out of memory");
1345 goto out;
1347 *info.pCPathLenConstraint = tbs->pathLenConstraint;
1350 ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
1351 &info.proxyPolicy.policyLanguage);
1352 if (ret) {
1353 free_ProxyCertInfo(&info);
1354 hx509_set_error_string(context, 0, ret, "Out of memory");
1355 goto out;
1358 ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1359 &info, &size, ret);
1360 free_ProxyCertInfo(&info);
1361 if (ret) {
1362 hx509_set_error_string(context, 0, ret, "Out of memory");
1363 goto out;
1365 if (size != data.length)
1366 _hx509_abort("internal ASN.1 encoder error");
1367 ret = add_extension(context, tbsc, 0,
1368 &asn1_oid_id_pkix_pe_proxyCertInfo,
1369 &data);
1370 free(data.data);
1371 if (ret)
1372 goto out;
1375 if (tbs->crldp.len) {
1377 ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1378 &tbs->crldp, &size, ret);
1379 if (ret) {
1380 hx509_set_error_string(context, 0, ret, "Out of memory");
1381 goto out;
1383 if (size != data.length)
1384 _hx509_abort("internal ASN.1 encoder error");
1385 ret = add_extension(context, tbsc, FALSE,
1386 &asn1_oid_id_x509_ce_cRLDistributionPoints,
1387 &data);
1388 free(data.data);
1389 if (ret)
1390 goto out;
1393 ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1394 if (ret) {
1395 hx509_set_error_string(context, 0, ret, "malloc out of memory");
1396 goto out;
1398 if (data.length != size)
1399 _hx509_abort("internal ASN.1 encoder error");
1401 ret = _hx509_create_signature_bitstring(context,
1402 signer,
1403 sigalg,
1404 &data,
1405 &c.signatureAlgorithm,
1406 &c.signatureValue);
1407 free(data.data);
1408 if (ret)
1409 goto out;
1411 ret = hx509_cert_init(context, &c, certificate);
1412 if (ret)
1413 goto out;
1415 free_Certificate(&c);
1417 return 0;
1419 out:
1420 free_Certificate(&c);
1421 return ret;
1424 static int
1425 get_AuthorityKeyIdentifier(hx509_context context,
1426 const Certificate *certificate,
1427 AuthorityKeyIdentifier *ai)
1429 SubjectKeyIdentifier si;
1430 int ret;
1432 ret = _hx509_find_extension_subject_key_id(certificate, &si);
1433 if (ret == 0) {
1434 ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1435 if (ai->keyIdentifier == NULL) {
1436 free_SubjectKeyIdentifier(&si);
1437 ret = ENOMEM;
1438 hx509_set_error_string(context, 0, ret, "Out of memory");
1439 goto out;
1441 ret = der_copy_octet_string(&si, ai->keyIdentifier);
1442 free_SubjectKeyIdentifier(&si);
1443 if (ret) {
1444 hx509_set_error_string(context, 0, ret, "Out of memory");
1445 goto out;
1447 } else {
1448 GeneralNames gns;
1449 GeneralName gn;
1450 Name name;
1452 memset(&gn, 0, sizeof(gn));
1453 memset(&gns, 0, sizeof(gns));
1454 memset(&name, 0, sizeof(name));
1456 ai->authorityCertIssuer =
1457 calloc(1, sizeof(*ai->authorityCertIssuer));
1458 if (ai->authorityCertIssuer == NULL) {
1459 ret = ENOMEM;
1460 hx509_set_error_string(context, 0, ret, "Out of memory");
1461 goto out;
1463 ai->authorityCertSerialNumber =
1464 calloc(1, sizeof(*ai->authorityCertSerialNumber));
1465 if (ai->authorityCertSerialNumber == NULL) {
1466 ret = ENOMEM;
1467 hx509_set_error_string(context, 0, ret, "Out of memory");
1468 goto out;
1472 * XXX unbreak when asn1 compiler handle IMPLICIT
1474 * This is so horrible.
1477 ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1478 if (ret) {
1479 hx509_set_error_string(context, 0, ret, "Out of memory");
1480 goto out;
1483 memset(&gn, 0, sizeof(gn));
1484 gn.element = choice_GeneralName_directoryName;
1485 gn.u.directoryName.element =
1486 choice_GeneralName_directoryName_rdnSequence;
1487 gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1489 ret = add_GeneralNames(&gns, &gn);
1490 if (ret) {
1491 hx509_set_error_string(context, 0, ret, "Out of memory");
1492 goto out;
1495 ai->authorityCertIssuer->val = gns.val;
1496 ai->authorityCertIssuer->len = gns.len;
1498 ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1499 ai->authorityCertSerialNumber);
1500 if (ai->authorityCertSerialNumber == NULL) {
1501 ret = ENOMEM;
1502 hx509_set_error_string(context, 0, ret, "Out of memory");
1503 goto out;
1506 out:
1507 if (ret)
1508 free_AuthorityKeyIdentifier(ai);
1509 return ret;
1514 * Sign a to-be-signed certificate object with a issuer certificate.
1516 * The caller needs to at least have called the following functions on the
1517 * to-be-signed certificate object:
1518 * - hx509_ca_tbs_init()
1519 * - hx509_ca_tbs_set_subject()
1520 * - hx509_ca_tbs_set_spki()
1522 * When done the to-be-signed certificate object should be freed with
1523 * hx509_ca_tbs_free().
1525 * When creating self-signed certificate use hx509_ca_sign_self() instead.
1527 * @param context A hx509 context.
1528 * @param tbs object to be signed.
1529 * @param signer the CA certificate object to sign with (need private key).
1530 * @param certificate return cerificate, free with hx509_cert_free().
1532 * @return An hx509 error code, see hx509_get_error_string().
1534 * @ingroup hx509_ca
1538 hx509_ca_sign(hx509_context context,
1539 hx509_ca_tbs tbs,
1540 hx509_cert signer,
1541 hx509_cert *certificate)
1543 const Certificate *signer_cert;
1544 AuthorityKeyIdentifier ai;
1545 int ret;
1547 memset(&ai, 0, sizeof(ai));
1549 signer_cert = _hx509_get_cert(signer);
1551 ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1552 if (ret)
1553 goto out;
1555 ret = ca_sign(context,
1556 tbs,
1557 _hx509_cert_private_key(signer),
1558 &ai,
1559 &signer_cert->tbsCertificate.subject,
1560 certificate);
1562 out:
1563 free_AuthorityKeyIdentifier(&ai);
1565 return ret;
1569 * Work just like hx509_ca_sign() but signs it-self.
1571 * @param context A hx509 context.
1572 * @param tbs object to be signed.
1573 * @param signer private key to sign with.
1574 * @param certificate return cerificate, free with hx509_cert_free().
1576 * @return An hx509 error code, see hx509_get_error_string().
1578 * @ingroup hx509_ca
1582 hx509_ca_sign_self(hx509_context context,
1583 hx509_ca_tbs tbs,
1584 hx509_private_key signer,
1585 hx509_cert *certificate)
1587 return ca_sign(context,
1588 tbs,
1589 signer,
1590 NULL,
1591 NULL,
1592 certificate);