xref: /minix/crypto/external/bsd/heimdal/dist/lib/hx509/ca.c (revision 0a6a1f1d)
1 /*	$NetBSD: ca.c,v 1.1.1.2 2014/04/24 12:45:41 pettai Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
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.
18  *
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.
22  *
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.
34  */
35 
36 #include "hx_locl.h"
37 #include <krb5/pkinit_asn1.h>
38 
39 /**
40  * @page page_ca Hx509 CA functions
41  *
42  * See the library functions here: @ref hx509_ca
43  */
44 
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;
66 
67 };
68 
69 /**
70  * Allocate an to-be-signed certificate object that will be converted
71  * into an certificate.
72  *
73  * @param context A hx509 context.
74  * @param tbs returned to-be-signed certicate object, free with
75  * hx509_ca_tbs_free().
76  *
77  * @return An hx509 error code, see hx509_get_error_string().
78  *
79  * @ingroup hx509_ca
80  */
81 
82 int
hx509_ca_tbs_init(hx509_context context,hx509_ca_tbs * tbs)83 hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84 {
85     *tbs = calloc(1, sizeof(**tbs));
86     if (*tbs == NULL)
87 	return ENOMEM;
88 
89     return 0;
90 }
91 
92 /**
93  * Free an To Be Signed object.
94  *
95  * @param tbs object to free.
96  *
97  * @ingroup hx509_ca
98  */
99 
100 void
hx509_ca_tbs_free(hx509_ca_tbs * tbs)101 hx509_ca_tbs_free(hx509_ca_tbs *tbs)
102 {
103     if (tbs == NULL || *tbs == NULL)
104 	return;
105 
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);
114 
115     memset(*tbs, 0, sizeof(**tbs));
116     free(*tbs);
117     *tbs = NULL;
118 }
119 
120 /**
121  * Set the absolute time when the certificate is valid from. If not
122  * set the current time will be used.
123  *
124  * @param context A hx509 context.
125  * @param tbs object to be signed.
126  * @param t time the certificated will start to be valid
127  *
128  * @return An hx509 error code, see hx509_get_error_string().
129  *
130  * @ingroup hx509_ca
131  */
132 
133 int
hx509_ca_tbs_set_notBefore(hx509_context context,hx509_ca_tbs tbs,time_t t)134 hx509_ca_tbs_set_notBefore(hx509_context context,
135 			   hx509_ca_tbs tbs,
136 			   time_t t)
137 {
138     tbs->notBefore = t;
139     return 0;
140 }
141 
142 /**
143  * Set the absolute time when the certificate is valid to.
144  *
145  * @param context A hx509 context.
146  * @param tbs object to be signed.
147  * @param t time when the certificate will expire
148  *
149  * @return An hx509 error code, see hx509_get_error_string().
150  *
151  * @ingroup hx509_ca
152  */
153 
154 int
hx509_ca_tbs_set_notAfter(hx509_context context,hx509_ca_tbs tbs,time_t t)155 hx509_ca_tbs_set_notAfter(hx509_context context,
156 			   hx509_ca_tbs tbs,
157 			   time_t t)
158 {
159     tbs->notAfter = t;
160     return 0;
161 }
162 
163 /**
164  * Set the relative time when the certificiate is going to expire.
165  *
166  * @param context A hx509 context.
167  * @param tbs object to be signed.
168  * @param delta seconds to the certificate is going to expire.
169  *
170  * @return An hx509 error code, see hx509_get_error_string().
171  *
172  * @ingroup hx509_ca
173  */
174 
175 int
hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,hx509_ca_tbs tbs,time_t delta)176 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
177 				   hx509_ca_tbs tbs,
178 				   time_t delta)
179 {
180     return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
181 }
182 
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 }
192 };
193 
194 /**
195  * Make of template units, use to build flags argument to
196  * hx509_ca_tbs_set_template() with parse_units().
197  *
198  * @return an units structure.
199  *
200  * @ingroup hx509_ca
201  */
202 
203 const struct units *
hx509_ca_tbs_template_units(void)204 hx509_ca_tbs_template_units(void)
205 {
206     return templatebits;
207 }
208 
209 /**
210  * Initialize the to-be-signed certificate object from a template certifiate.
211  *
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.
217  *
218  * @return An hx509 error code, see hx509_get_error_string().
219  *
220  * @ingroup hx509_ca
221  */
222 
223 int
hx509_ca_tbs_set_template(hx509_context context,hx509_ca_tbs tbs,int flags,hx509_cert cert)224 hx509_ca_tbs_set_template(hx509_context context,
225 			  hx509_ca_tbs tbs,
226 			  int flags,
227 			  hx509_cert cert)
228 {
229     int ret;
230 
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;
239 	}
240     }
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;
249 	}
250     }
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;
261     }
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);
268     }
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;
280 	    }
281 	}
282 	free_ExtKeyUsage(&eku);
283     }
284     return 0;
285 }
286 
287 /**
288  * Make the to-be-signed certificate object a CA certificate. If the
289  * pathLenConstraint is negative path length constraint is used.
290  *
291  * @param context A hx509 context.
292  * @param tbs object to be signed.
293  * @param pathLenConstraint path length constraint, negative, no
294  * constraint.
295  *
296  * @return An hx509 error code, see hx509_get_error_string().
297  *
298  * @ingroup hx509_ca
299  */
300 
301 int
hx509_ca_tbs_set_ca(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)302 hx509_ca_tbs_set_ca(hx509_context context,
303 		    hx509_ca_tbs tbs,
304 		    int pathLenConstraint)
305 {
306     tbs->flags.ca = 1;
307     tbs->pathLenConstraint = pathLenConstraint;
308     return 0;
309 }
310 
311 /**
312  * Make the to-be-signed certificate object a proxy certificate. If the
313  * pathLenConstraint is negative path length constraint is used.
314  *
315  * @param context A hx509 context.
316  * @param tbs object to be signed.
317  * @param pathLenConstraint path length constraint, negative, no
318  * constraint.
319  *
320  * @return An hx509 error code, see hx509_get_error_string().
321  *
322  * @ingroup hx509_ca
323  */
324 
325 int
hx509_ca_tbs_set_proxy(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)326 hx509_ca_tbs_set_proxy(hx509_context context,
327 		       hx509_ca_tbs tbs,
328 		       int pathLenConstraint)
329 {
330     tbs->flags.proxy = 1;
331     tbs->pathLenConstraint = pathLenConstraint;
332     return 0;
333 }
334 
335 
336 /**
337  * Make the to-be-signed certificate object a windows domain controller certificate.
338  *
339  * @param context A hx509 context.
340  * @param tbs object to be signed.
341  *
342  * @return An hx509 error code, see hx509_get_error_string().
343  *
344  * @ingroup hx509_ca
345  */
346 
347 int
hx509_ca_tbs_set_domaincontroller(hx509_context context,hx509_ca_tbs tbs)348 hx509_ca_tbs_set_domaincontroller(hx509_context context,
349 				  hx509_ca_tbs tbs)
350 {
351     tbs->flags.domaincontroller = 1;
352     return 0;
353 }
354 
355 /**
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.
359  *
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.
363  *
364  * @return An hx509 error code, see hx509_get_error_string().
365  *
366  * @ingroup hx509_ca
367  */
368 
369 int
hx509_ca_tbs_set_spki(hx509_context context,hx509_ca_tbs tbs,const SubjectPublicKeyInfo * spki)370 hx509_ca_tbs_set_spki(hx509_context context,
371 		      hx509_ca_tbs tbs,
372 		      const SubjectPublicKeyInfo *spki)
373 {
374     int ret;
375     free_SubjectPublicKeyInfo(&tbs->spki);
376     ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
377     tbs->flags.key = !ret;
378     return ret;
379 }
380 
381 /**
382  * Set the serial number to use for to-be-signed certificate object.
383  *
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.
388  *
389  * @return An hx509 error code, see hx509_get_error_string().
390  *
391  * @ingroup hx509_ca
392  */
393 
394 int
hx509_ca_tbs_set_serialnumber(hx509_context context,hx509_ca_tbs tbs,const heim_integer * serialNumber)395 hx509_ca_tbs_set_serialnumber(hx509_context context,
396 			      hx509_ca_tbs tbs,
397 			      const heim_integer *serialNumber)
398 {
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;
404 }
405 
406 /**
407  * An an extended key usage to the to-be-signed certificate object.
408  * Duplicates will detected and not added.
409  *
410  * @param context A hx509 context.
411  * @param tbs object to be signed.
412  * @param oid extended key usage to add.
413  *
414  * @return An hx509 error code, see hx509_get_error_string().
415  *
416  * @ingroup hx509_ca
417  */
418 
419 int
hx509_ca_tbs_add_eku(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid)420 hx509_ca_tbs_add_eku(hx509_context context,
421 		     hx509_ca_tbs tbs,
422 		     const heim_oid *oid)
423 {
424     void *ptr;
425     int ret;
426     unsigned i;
427 
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;
432     }
433 
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;
438     }
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;
444     }
445     tbs->eku.len += 1;
446     return 0;
447 }
448 
449 /**
450  * Add CRL distribution point URI to the to-be-signed certificate
451  * object.
452  *
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.
457  *
458  * @return An hx509 error code, see hx509_get_error_string().
459  *
460  * @ingroup hx509_ca
461  */
462 
463 int
hx509_ca_tbs_add_crl_dp_uri(hx509_context context,hx509_ca_tbs tbs,const char * uri,hx509_name issuername)464 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
465 			    hx509_ca_tbs tbs,
466 			    const char *uri,
467 			    hx509_name issuername)
468 {
469     DistributionPoint dp;
470     int ret;
471 
472     memset(&dp, 0, sizeof(dp));
473 
474     dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
475 
476     {
477 	DistributionPointName name;
478 	GeneralName gn;
479 	size_t size;
480 
481 	name.element = choice_DistributionPointName_fullName;
482 	name.u.fullName.len = 1;
483 	name.u.fullName.val = &gn;
484 
485 	gn.element = choice_GeneralName_uniformResourceIdentifier;
486 	gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
487 	gn.u.uniformResourceIdentifier.length = strlen(uri);
488 
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;
497 	}
498 	if (dp.distributionPoint->length != size)
499 	    _hx509_abort("internal ASN.1 encoder error");
500     }
501 
502     if (issuername) {
503 #if 1
504 	/**
505 	 * issuername not supported
506 	 */
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;
514 
515 	crlissuer = calloc(1, sizeof(*crlissuer));
516 	if (crlissuer == NULL) {
517 	    return ENOMEM;
518 	}
519 	memset(&gn, 0, sizeof(gn));
520 
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;
526 	}
527 
528 	gn.u.directoryName.element = n.element;
529 	gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
530 
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;
536 	}
537 
538 	dp.cRLIssuer = &crlissuer;
539 #endif
540     }
541 
542     ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
543     if (ret) {
544 	hx509_set_error_string(context, 0, ret, "out of memory");
545 	goto out;
546     }
547 
548 out:
549     free_DistributionPoint(&dp);
550 
551     return ret;
552 }
553 
554 /**
555  * Add Subject Alternative Name otherName to the to-be-signed
556  * certificate object.
557  *
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.
562  *
563  * @return An hx509 error code, see hx509_get_error_string().
564  *
565  * @ingroup hx509_ca
566  */
567 
568 int
hx509_ca_tbs_add_san_otherName(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const heim_octet_string * os)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)
573 {
574     GeneralName gn;
575 
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;
580 
581     return add_GeneralNames(&tbs->san, &gn);
582 }
583 
584 /**
585  * Add Kerberos Subject Alternative Name to the to-be-signed
586  * certificate object. The principal string is a UTF8 string.
587  *
588  * @param context A hx509 context.
589  * @param tbs object to be signed.
590  * @param principal Kerberos principal to add to the certificate.
591  *
592  * @return An hx509 error code, see hx509_get_error_string().
593  *
594  * @ingroup hx509_ca
595  */
596 
597 int
hx509_ca_tbs_add_san_pkinit(hx509_context context,hx509_ca_tbs tbs,const char * principal)598 hx509_ca_tbs_add_san_pkinit(hx509_context context,
599 			    hx509_ca_tbs tbs,
600 			    const char *principal)
601 {
602     heim_octet_string os;
603     KRB5PrincipalName p;
604     size_t size;
605     int ret;
606     char *s = NULL;
607 
608     memset(&p, 0, sizeof(p));
609 
610     /* parse principal */
611     {
612 	const char *str;
613 	char *q;
614 	int n;
615 
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;
625 		}
626 		str++;
627 	    } else if(*str == '/')
628 		n++;
629 	}
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;
636 	}
637 	p.principalName.name_string.len = n;
638 
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;
645 	}
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;
651 	};
652 	*p.realm++ = '\0';
653 
654 	n = 0;
655 	while (q) {
656 	    p.principalName.name_string.val[n++] = q;
657 	    q = strchr(q, '/');
658 	    if (q)
659 		*q++ = '\0';
660 	}
661     }
662 
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;
667     }
668     if (size != os.length)
669 	_hx509_abort("internal ASN.1 encoder error");
670 
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;
682 }
683 
684 /*
685  *
686  */
687 
688 static int
add_utf8_san(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const char * string)689 add_utf8_san(hx509_context context,
690 	     hx509_ca_tbs tbs,
691 	     const heim_oid *oid,
692 	     const char *string)
693 {
694     const PKIXXmppAddr ustring = (const PKIXXmppAddr)(intptr_t)string;
695     heim_octet_string os;
696     size_t size;
697     int ret;
698 
699     os.length = 0;
700     os.data = NULL;
701 
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;
706     }
707     if (size != os.length)
708 	_hx509_abort("internal ASN.1 encoder error");
709 
710     ret = hx509_ca_tbs_add_san_otherName(context,
711 					 tbs,
712 					 oid,
713 					 &os);
714     free(os.data);
715 out:
716     return ret;
717 }
718 
719 /**
720  * Add Microsoft UPN Subject Alternative Name to the to-be-signed
721  * certificate object. The principal string is a UTF8 string.
722  *
723  * @param context A hx509 context.
724  * @param tbs object to be signed.
725  * @param principal Microsoft UPN string.
726  *
727  * @return An hx509 error code, see hx509_get_error_string().
728  *
729  * @ingroup hx509_ca
730  */
731 
732 int
hx509_ca_tbs_add_san_ms_upn(hx509_context context,hx509_ca_tbs tbs,const char * principal)733 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
734 			    hx509_ca_tbs tbs,
735 			    const char *principal)
736 {
737     return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
738 }
739 
740 /**
741  * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
742  * certificate object. The jid is an UTF8 string.
743  *
744  * @param context A hx509 context.
745  * @param tbs object to be signed.
746  * @param jid string of an a jabber id in UTF8.
747  *
748  * @return An hx509 error code, see hx509_get_error_string().
749  *
750  * @ingroup hx509_ca
751  */
752 
753 int
hx509_ca_tbs_add_san_jid(hx509_context context,hx509_ca_tbs tbs,const char * jid)754 hx509_ca_tbs_add_san_jid(hx509_context context,
755 			 hx509_ca_tbs tbs,
756 			 const char *jid)
757 {
758     return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
759 }
760 
761 
762 /**
763  * Add a Subject Alternative Name hostname to to-be-signed certificate
764  * object. A domain match starts with ., an exact match does not.
765  *
766  * Example of a an domain match: .domain.se matches the hostname
767  * host.domain.se.
768  *
769  * @param context A hx509 context.
770  * @param tbs object to be signed.
771  * @param dnsname a hostame.
772  *
773  * @return An hx509 error code, see hx509_get_error_string().
774  *
775  * @ingroup hx509_ca
776  */
777 
778 int
hx509_ca_tbs_add_san_hostname(hx509_context context,hx509_ca_tbs tbs,const char * dnsname)779 hx509_ca_tbs_add_san_hostname(hx509_context context,
780 			      hx509_ca_tbs tbs,
781 			      const char *dnsname)
782 {
783     GeneralName gn;
784 
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);
789 
790     return add_GeneralNames(&tbs->san, &gn);
791 }
792 
793 /**
794  * Add a Subject Alternative Name rfc822 (email address) to
795  * to-be-signed certificate object.
796  *
797  * @param context A hx509 context.
798  * @param tbs object to be signed.
799  * @param rfc822Name a string to a email address.
800  *
801  * @return An hx509 error code, see hx509_get_error_string().
802  *
803  * @ingroup hx509_ca
804  */
805 
806 int
hx509_ca_tbs_add_san_rfc822name(hx509_context context,hx509_ca_tbs tbs,const char * rfc822Name)807 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
808 				hx509_ca_tbs tbs,
809 				const char *rfc822Name)
810 {
811     GeneralName gn;
812 
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);
817 
818     return add_GeneralNames(&tbs->san, &gn);
819 }
820 
821 /**
822  * Set the subject name of a to-be-signed certificate object.
823  *
824  * @param context A hx509 context.
825  * @param tbs object to be signed.
826  * @param subject the name to set a subject.
827  *
828  * @return An hx509 error code, see hx509_get_error_string().
829  *
830  * @ingroup hx509_ca
831  */
832 
833 int
hx509_ca_tbs_set_subject(hx509_context context,hx509_ca_tbs tbs,hx509_name subject)834 hx509_ca_tbs_set_subject(hx509_context context,
835 			 hx509_ca_tbs tbs,
836 			 hx509_name subject)
837 {
838     if (tbs->subject)
839 	hx509_name_free(&tbs->subject);
840     return hx509_name_copy(context, subject, &tbs->subject);
841 }
842 
843 /**
844  * Set the issuerUniqueID and subjectUniqueID
845  *
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.
850  *
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
855  *
856  * @return An hx509 error code, see hx509_get_error_string().
857  *
858  * @ingroup hx509_ca
859  */
860 
861 int
hx509_ca_tbs_set_unique(hx509_context context,hx509_ca_tbs tbs,const heim_bit_string * subjectUniqueID,const heim_bit_string * issuerUniqueID)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)
866 {
867     int ret;
868 
869     der_free_bit_string(&tbs->subjectUniqueID);
870     der_free_bit_string(&tbs->issuerUniqueID);
871 
872     if (subjectUniqueID) {
873 	ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
874 	if (ret)
875 	    return ret;
876     }
877 
878     if (issuerUniqueID) {
879 	ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
880 	if (ret)
881 	    return ret;
882     }
883 
884     return 0;
885 }
886 
887 /**
888  * Expand the the subject name in the to-be-signed certificate object
889  * using hx509_name_expand().
890  *
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().
895  *
896  * @return An hx509 error code, see hx509_get_error_string().
897  *
898  * @ingroup hx509_ca
899  */
900 
901 int
hx509_ca_tbs_subject_expand(hx509_context context,hx509_ca_tbs tbs,hx509_env env)902 hx509_ca_tbs_subject_expand(hx509_context context,
903 			    hx509_ca_tbs tbs,
904 			    hx509_env env)
905 {
906     return hx509_name_expand(context, tbs->subject, env);
907 }
908 
909 /*
910  *
911  */
912 
913 static int
add_extension(hx509_context context,TBSCertificate * tbsc,int critical_flag,const heim_oid * oid,const heim_octet_string * data)914 add_extension(hx509_context context,
915 	      TBSCertificate *tbsc,
916 	      int critical_flag,
917 	      const heim_oid *oid,
918 	      const heim_octet_string *data)
919 {
920     Extension ext;
921     int ret;
922 
923     memset(&ext, 0, sizeof(ext));
924 
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;
931 	}
932 	*ext.critical = TRUE;
933     }
934 
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;
939     }
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;
944     }
945     ret = add_Extensions(tbsc->extensions, &ext);
946     if (ret) {
947 	hx509_set_error_string(context, 0, ret, "Out of memory");
948 	goto out;
949     }
950 out:
951     free_Extension(&ext);
952     return ret;
953 }
954 
955 static int
build_proxy_prefix(hx509_context context,const Name * issuer,Name * subject)956 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
957 {
958     char *tstr;
959     time_t t;
960     int ret;
961 
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;
967     }
968 
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;
975     }
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;
982 }
983 
984 static int
ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,const AuthorityKeyIdentifier * ai,const Name * issuername,hx509_cert * certificate)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)
991 {
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;
1001 
1002     sigalg = _hx509_crypto_default_sig_alg;
1003 
1004     memset(&c, 0, sizeof(c));
1005 
1006     /*
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.
1010      */
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;
1017 
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);
1025     }
1026 
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);
1033     }
1034 
1035     /*
1036      *
1037      */
1038 
1039     tbsc = &c.tbsCertificate;
1040 
1041     if (tbs->flags.key == 0) {
1042 	ret = EINVAL;
1043 	hx509_set_error_string(context, 0, ret, "No public key set");
1044 	return ret;
1045     }
1046     /*
1047      * Don't put restrictions on proxy certificate's subject name, it
1048      * will be generated below.
1049      */
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;
1054 	}
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;
1059 	}
1060     }
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;
1065     }
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;
1072 	}
1073     }
1074 
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;
1081     }
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;
1089 	}
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;
1097 	}
1098 	/* XXX diffrent */
1099 	RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1100 	((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1101     }
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;
1107     }
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;
1116     }
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;
1133 	}
1134     }
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;
1140     }
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;
1148 	}
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;
1153 	}
1154     }
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;
1162 	}
1163 
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;
1168 	}
1169     }
1170 
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;
1177     }
1178 
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;
1187 
1188 	ret = add_extension(context, tbsc, 0,
1189 			    &asn1_oid_id_ms_cert_enroll_domaincontroller,
1190 			    &data);
1191 	if (ret)
1192 	    goto out;
1193     }
1194 
1195     /* add KeyUsage */
1196     {
1197 	KeyUsage ku;
1198 
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;
1204 	}
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;
1212     }
1213 
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;
1221 	}
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;
1229     }
1230 
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;
1238 	}
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;
1247     }
1248 
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;
1256 	}
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;
1265     }
1266 
1267     /* Add Subject Key Identifier */
1268     {
1269 	SubjectKeyIdentifier si;
1270 	unsigned char hash[SHA_DIGEST_LENGTH];
1271 
1272 	{
1273 	    EVP_MD_CTX *ctx;
1274 
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);
1281 	}
1282 
1283 	si.data = hash;
1284 	si.length = sizeof(hash);
1285 
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;
1291 	}
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;
1300     }
1301 
1302     /* Add BasicConstraints */
1303     {
1304 	BasicConstraints bc;
1305 	int aCA = 1;
1306 	unsigned int path;
1307 
1308 	memset(&bc, 0, sizeof(bc));
1309 
1310 	if (tbs->flags.ca) {
1311 	    bc.cA = &aCA;
1312 	    if (tbs->pathLenConstraint >= 0) {
1313 		path = tbs->pathLenConstraint;
1314 		bc.pathLenConstraint = &path;
1315 	    }
1316 	}
1317 
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;
1323 	}
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;
1333     }
1334 
1335     /* add Proxy */
1336     if (tbs->flags.proxy) {
1337 	ProxyCertInfo info;
1338 
1339 	memset(&info, 0, sizeof(info));
1340 
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;
1348 	    }
1349 	    *info.pCPathLenConstraint = tbs->pathLenConstraint;
1350 	}
1351 
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;
1358 	}
1359 
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;
1366 	}
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;
1375     }
1376 
1377     if (tbs->crldp.len) {
1378 
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;
1384 	}
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;
1393     }
1394 
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;
1399     }
1400     if (data.length != size)
1401 	_hx509_abort("internal ASN.1 encoder error");
1402 
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;
1412 
1413     ret = hx509_cert_init(context, &c, certificate);
1414     if (ret)
1415 	goto out;
1416 
1417     free_Certificate(&c);
1418 
1419     return 0;
1420 
1421 out:
1422     free_Certificate(&c);
1423     return ret;
1424 }
1425 
1426 static int
get_AuthorityKeyIdentifier(hx509_context context,const Certificate * certificate,AuthorityKeyIdentifier * ai)1427 get_AuthorityKeyIdentifier(hx509_context context,
1428 			   const Certificate *certificate,
1429 			   AuthorityKeyIdentifier *ai)
1430 {
1431     SubjectKeyIdentifier si;
1432     int ret;
1433 
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;
1442 	}
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;
1448 	}
1449     } else {
1450 	GeneralNames gns;
1451 	GeneralName gn;
1452 	Name name;
1453 
1454 	memset(&gn, 0, sizeof(gn));
1455 	memset(&gns, 0, sizeof(gns));
1456 	memset(&name, 0, sizeof(name));
1457 
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;
1464 	}
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;
1471 	}
1472 
1473 	/*
1474 	 * XXX unbreak when asn1 compiler handle IMPLICIT
1475 	 *
1476 	 * This is so horrible.
1477 	 */
1478 
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;
1483 	}
1484 
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;
1490 
1491 	ret = add_GeneralNames(&gns, &gn);
1492 	if (ret) {
1493 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1494 	    goto out;
1495 	}
1496 
1497 	ai->authorityCertIssuer->val = gns.val;
1498 	ai->authorityCertIssuer->len = gns.len;
1499 
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;
1506 	}
1507     }
1508 out:
1509     if (ret)
1510 	free_AuthorityKeyIdentifier(ai);
1511     return ret;
1512 }
1513 
1514 
1515 /**
1516  * Sign a to-be-signed certificate object with a issuer certificate.
1517  *
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()
1523  *
1524  * When done the to-be-signed certificate object should be freed with
1525  * hx509_ca_tbs_free().
1526  *
1527  * When creating self-signed certificate use hx509_ca_sign_self() instead.
1528  *
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().
1533  *
1534  * @return An hx509 error code, see hx509_get_error_string().
1535  *
1536  * @ingroup hx509_ca
1537  */
1538 
1539 int
hx509_ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_cert signer,hx509_cert * certificate)1540 hx509_ca_sign(hx509_context context,
1541 	      hx509_ca_tbs tbs,
1542 	      hx509_cert signer,
1543 	      hx509_cert *certificate)
1544 {
1545     const Certificate *signer_cert;
1546     AuthorityKeyIdentifier ai;
1547     int ret;
1548 
1549     memset(&ai, 0, sizeof(ai));
1550 
1551     signer_cert = _hx509_get_cert(signer);
1552 
1553     ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1554     if (ret)
1555 	goto out;
1556 
1557     ret = ca_sign(context,
1558 		  tbs,
1559 		  _hx509_cert_private_key(signer),
1560 		  &ai,
1561 		  &signer_cert->tbsCertificate.subject,
1562 		  certificate);
1563 
1564 out:
1565     free_AuthorityKeyIdentifier(&ai);
1566 
1567     return ret;
1568 }
1569 
1570 /**
1571  * Work just like hx509_ca_sign() but signs it-self.
1572  *
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().
1577  *
1578  * @return An hx509 error code, see hx509_get_error_string().
1579  *
1580  * @ingroup hx509_ca
1581  */
1582 
1583 int
hx509_ca_sign_self(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,hx509_cert * certificate)1584 hx509_ca_sign_self(hx509_context context,
1585 		   hx509_ca_tbs tbs,
1586 		   hx509_private_key signer,
1587 		   hx509_cert *certificate)
1588 {
1589     return ca_sign(context,
1590 		   tbs,
1591 		   signer,
1592 		   NULL,
1593 		   NULL,
1594 		   certificate);
1595 }
1596