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