1 /* $NetBSD: ca.c,v 1.2 2017/01/28 21:31:48 christos 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 AlgorithmIdentifier *sigalg;
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 if ((*tbs)->sigalg) {
115 free_AlgorithmIdentifier((*tbs)->sigalg);
116 free((*tbs)->sigalg);
117 }
118
119 memset(*tbs, 0, sizeof(**tbs));
120 free(*tbs);
121 *tbs = NULL;
122 }
123
124 /**
125 * Set the absolute time when the certificate is valid from. If not
126 * set the current time will be used.
127 *
128 * @param context A hx509 context.
129 * @param tbs object to be signed.
130 * @param t time the certificated will start to be valid
131 *
132 * @return An hx509 error code, see hx509_get_error_string().
133 *
134 * @ingroup hx509_ca
135 */
136
137 int
hx509_ca_tbs_set_notBefore(hx509_context context,hx509_ca_tbs tbs,time_t t)138 hx509_ca_tbs_set_notBefore(hx509_context context,
139 hx509_ca_tbs tbs,
140 time_t t)
141 {
142 tbs->notBefore = t;
143 return 0;
144 }
145
146 /**
147 * Set the absolute time when the certificate is valid to.
148 *
149 * @param context A hx509 context.
150 * @param tbs object to be signed.
151 * @param t time when the certificate will expire
152 *
153 * @return An hx509 error code, see hx509_get_error_string().
154 *
155 * @ingroup hx509_ca
156 */
157
158 int
hx509_ca_tbs_set_notAfter(hx509_context context,hx509_ca_tbs tbs,time_t t)159 hx509_ca_tbs_set_notAfter(hx509_context context,
160 hx509_ca_tbs tbs,
161 time_t t)
162 {
163 tbs->notAfter = t;
164 return 0;
165 }
166
167 /**
168 * Set the relative time when the certificiate is going to expire.
169 *
170 * @param context A hx509 context.
171 * @param tbs object to be signed.
172 * @param delta seconds to the certificate is going to expire.
173 *
174 * @return An hx509 error code, see hx509_get_error_string().
175 *
176 * @ingroup hx509_ca
177 */
178
179 int
hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,hx509_ca_tbs tbs,time_t delta)180 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
181 hx509_ca_tbs tbs,
182 time_t delta)
183 {
184 return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
185 }
186
187 static const struct units templatebits[] = {
188 { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
189 { "KeyUsage", HX509_CA_TEMPLATE_KU },
190 { "SPKI", HX509_CA_TEMPLATE_SPKI },
191 { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
192 { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
193 { "serial", HX509_CA_TEMPLATE_SERIAL },
194 { "subject", HX509_CA_TEMPLATE_SUBJECT },
195 { NULL, 0 }
196 };
197
198 /**
199 * Make of template units, use to build flags argument to
200 * hx509_ca_tbs_set_template() with parse_units().
201 *
202 * @return an units structure.
203 *
204 * @ingroup hx509_ca
205 */
206
207 const struct units *
hx509_ca_tbs_template_units(void)208 hx509_ca_tbs_template_units(void)
209 {
210 return templatebits;
211 }
212
213 /**
214 * Initialize the to-be-signed certificate object from a template certifiate.
215 *
216 * @param context A hx509 context.
217 * @param tbs object to be signed.
218 * @param flags bit field selecting what to copy from the template
219 * certifiate.
220 * @param cert template certificate.
221 *
222 * @return An hx509 error code, see hx509_get_error_string().
223 *
224 * @ingroup hx509_ca
225 */
226
227 int
hx509_ca_tbs_set_template(hx509_context context,hx509_ca_tbs tbs,int flags,hx509_cert cert)228 hx509_ca_tbs_set_template(hx509_context context,
229 hx509_ca_tbs tbs,
230 int flags,
231 hx509_cert cert)
232 {
233 int ret;
234
235 if (flags & HX509_CA_TEMPLATE_SUBJECT) {
236 if (tbs->subject)
237 hx509_name_free(&tbs->subject);
238 ret = hx509_cert_get_subject(cert, &tbs->subject);
239 if (ret) {
240 hx509_set_error_string(context, 0, ret,
241 "Failed to get subject from template");
242 return ret;
243 }
244 }
245 if (flags & HX509_CA_TEMPLATE_SERIAL) {
246 der_free_heim_integer(&tbs->serial);
247 ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
248 tbs->flags.serial = !ret;
249 if (ret) {
250 hx509_set_error_string(context, 0, ret,
251 "Failed to copy serial number");
252 return ret;
253 }
254 }
255 if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
256 tbs->notBefore = hx509_cert_get_notBefore(cert);
257 if (flags & HX509_CA_TEMPLATE_NOTAFTER)
258 tbs->notAfter = hx509_cert_get_notAfter(cert);
259 if (flags & HX509_CA_TEMPLATE_SPKI) {
260 free_SubjectPublicKeyInfo(&tbs->spki);
261 ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
262 tbs->flags.key = !ret;
263 if (ret)
264 return ret;
265 }
266 if (flags & HX509_CA_TEMPLATE_KU) {
267 KeyUsage ku;
268 ret = _hx509_cert_get_keyusage(context, cert, &ku);
269 if (ret)
270 return ret;
271 tbs->key_usage = KeyUsage2int(ku);
272 }
273 if (flags & HX509_CA_TEMPLATE_EKU) {
274 ExtKeyUsage eku;
275 size_t i;
276 ret = _hx509_cert_get_eku(context, cert, &eku);
277 if (ret)
278 return ret;
279 for (i = 0; i < eku.len; i++) {
280 ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
281 if (ret) {
282 free_ExtKeyUsage(&eku);
283 return ret;
284 }
285 }
286 free_ExtKeyUsage(&eku);
287 }
288 return 0;
289 }
290
291 /**
292 * Make the to-be-signed certificate object a CA certificate. If the
293 * pathLenConstraint is negative path length constraint is used.
294 *
295 * @param context A hx509 context.
296 * @param tbs object to be signed.
297 * @param pathLenConstraint path length constraint, negative, no
298 * constraint.
299 *
300 * @return An hx509 error code, see hx509_get_error_string().
301 *
302 * @ingroup hx509_ca
303 */
304
305 int
hx509_ca_tbs_set_ca(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)306 hx509_ca_tbs_set_ca(hx509_context context,
307 hx509_ca_tbs tbs,
308 int pathLenConstraint)
309 {
310 tbs->flags.ca = 1;
311 tbs->pathLenConstraint = pathLenConstraint;
312 return 0;
313 }
314
315 /**
316 * Make the to-be-signed certificate object a proxy certificate. If the
317 * pathLenConstraint is negative path length constraint is used.
318 *
319 * @param context A hx509 context.
320 * @param tbs object to be signed.
321 * @param pathLenConstraint path length constraint, negative, no
322 * constraint.
323 *
324 * @return An hx509 error code, see hx509_get_error_string().
325 *
326 * @ingroup hx509_ca
327 */
328
329 int
hx509_ca_tbs_set_proxy(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)330 hx509_ca_tbs_set_proxy(hx509_context context,
331 hx509_ca_tbs tbs,
332 int pathLenConstraint)
333 {
334 tbs->flags.proxy = 1;
335 tbs->pathLenConstraint = pathLenConstraint;
336 return 0;
337 }
338
339
340 /**
341 * Make the to-be-signed certificate object a windows domain controller certificate.
342 *
343 * @param context A hx509 context.
344 * @param tbs object to be signed.
345 *
346 * @return An hx509 error code, see hx509_get_error_string().
347 *
348 * @ingroup hx509_ca
349 */
350
351 int
hx509_ca_tbs_set_domaincontroller(hx509_context context,hx509_ca_tbs tbs)352 hx509_ca_tbs_set_domaincontroller(hx509_context context,
353 hx509_ca_tbs tbs)
354 {
355 tbs->flags.domaincontroller = 1;
356 return 0;
357 }
358
359 /**
360 * Set the subject public key info (SPKI) in the to-be-signed certificate
361 * object. SPKI is the public key and key related parameters in the
362 * certificate.
363 *
364 * @param context A hx509 context.
365 * @param tbs object to be signed.
366 * @param spki subject public key info to use for the to-be-signed certificate object.
367 *
368 * @return An hx509 error code, see hx509_get_error_string().
369 *
370 * @ingroup hx509_ca
371 */
372
373 int
hx509_ca_tbs_set_spki(hx509_context context,hx509_ca_tbs tbs,const SubjectPublicKeyInfo * spki)374 hx509_ca_tbs_set_spki(hx509_context context,
375 hx509_ca_tbs tbs,
376 const SubjectPublicKeyInfo *spki)
377 {
378 int ret;
379 free_SubjectPublicKeyInfo(&tbs->spki);
380 ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
381 tbs->flags.key = !ret;
382 return ret;
383 }
384
385 /**
386 * Set the serial number to use for to-be-signed certificate object.
387 *
388 * @param context A hx509 context.
389 * @param tbs object to be signed.
390 * @param serialNumber serial number to use for the to-be-signed
391 * certificate object.
392 *
393 * @return An hx509 error code, see hx509_get_error_string().
394 *
395 * @ingroup hx509_ca
396 */
397
398 int
hx509_ca_tbs_set_serialnumber(hx509_context context,hx509_ca_tbs tbs,const heim_integer * serialNumber)399 hx509_ca_tbs_set_serialnumber(hx509_context context,
400 hx509_ca_tbs tbs,
401 const heim_integer *serialNumber)
402 {
403 int ret;
404 der_free_heim_integer(&tbs->serial);
405 ret = der_copy_heim_integer(serialNumber, &tbs->serial);
406 tbs->flags.serial = !ret;
407 return ret;
408 }
409
410 /**
411 * An an extended key usage to the to-be-signed certificate object.
412 * Duplicates will detected and not added.
413 *
414 * @param context A hx509 context.
415 * @param tbs object to be signed.
416 * @param oid extended key usage to add.
417 *
418 * @return An hx509 error code, see hx509_get_error_string().
419 *
420 * @ingroup hx509_ca
421 */
422
423 int
hx509_ca_tbs_add_eku(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid)424 hx509_ca_tbs_add_eku(hx509_context context,
425 hx509_ca_tbs tbs,
426 const heim_oid *oid)
427 {
428 void *ptr;
429 int ret;
430 unsigned i;
431
432 /* search for duplicates */
433 for (i = 0; i < tbs->eku.len; i++) {
434 if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
435 return 0;
436 }
437
438 ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
439 if (ptr == NULL) {
440 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
441 return ENOMEM;
442 }
443 tbs->eku.val = ptr;
444 ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
445 if (ret) {
446 hx509_set_error_string(context, 0, ret, "out of memory");
447 return ret;
448 }
449 tbs->eku.len += 1;
450 return 0;
451 }
452
453 /**
454 * Add CRL distribution point URI to the to-be-signed certificate
455 * object.
456 *
457 * @param context A hx509 context.
458 * @param tbs object to be signed.
459 * @param uri uri to the CRL.
460 * @param issuername name of the issuer.
461 *
462 * @return An hx509 error code, see hx509_get_error_string().
463 *
464 * @ingroup hx509_ca
465 */
466
467 int
hx509_ca_tbs_add_crl_dp_uri(hx509_context context,hx509_ca_tbs tbs,const char * uri,hx509_name issuername)468 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
469 hx509_ca_tbs tbs,
470 const char *uri,
471 hx509_name issuername)
472 {
473 DistributionPoint dp;
474 int ret;
475
476 memset(&dp, 0, sizeof(dp));
477
478 dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
479
480 {
481 DistributionPointName name;
482 GeneralName gn;
483 size_t size;
484
485 name.element = choice_DistributionPointName_fullName;
486 name.u.fullName.len = 1;
487 name.u.fullName.val = &gn;
488
489 gn.element = choice_GeneralName_uniformResourceIdentifier;
490 gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
491 gn.u.uniformResourceIdentifier.length = strlen(uri);
492
493 ASN1_MALLOC_ENCODE(DistributionPointName,
494 dp.distributionPoint->data,
495 dp.distributionPoint->length,
496 &name, &size, ret);
497 if (ret) {
498 hx509_set_error_string(context, 0, ret,
499 "Failed to encoded DistributionPointName");
500 goto out;
501 }
502 if (dp.distributionPoint->length != size)
503 _hx509_abort("internal ASN.1 encoder error");
504 }
505
506 if (issuername) {
507 #if 1
508 /**
509 * issuername not supported
510 */
511 hx509_set_error_string(context, 0, EINVAL,
512 "CRLDistributionPoints.name.issuername not yet supported");
513 return EINVAL;
514 #else
515 GeneralNames *crlissuer;
516 GeneralName gn;
517 Name n;
518
519 crlissuer = calloc(1, sizeof(*crlissuer));
520 if (crlissuer == NULL) {
521 return ENOMEM;
522 }
523 memset(&gn, 0, sizeof(gn));
524
525 gn.element = choice_GeneralName_directoryName;
526 ret = hx509_name_to_Name(issuername, &n);
527 if (ret) {
528 hx509_set_error_string(context, 0, ret, "out of memory");
529 goto out;
530 }
531
532 gn.u.directoryName.element = n.element;
533 gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
534
535 ret = add_GeneralNames(&crlissuer, &gn);
536 free_Name(&n);
537 if (ret) {
538 hx509_set_error_string(context, 0, ret, "out of memory");
539 goto out;
540 }
541
542 dp.cRLIssuer = &crlissuer;
543 #endif
544 }
545
546 ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
547 if (ret) {
548 hx509_set_error_string(context, 0, ret, "out of memory");
549 goto out;
550 }
551
552 out:
553 free_DistributionPoint(&dp);
554
555 return ret;
556 }
557
558 /**
559 * Add Subject Alternative Name otherName to the to-be-signed
560 * certificate object.
561 *
562 * @param context A hx509 context.
563 * @param tbs object to be signed.
564 * @param oid the oid of the OtherName.
565 * @param os data in the other name.
566 *
567 * @return An hx509 error code, see hx509_get_error_string().
568 *
569 * @ingroup hx509_ca
570 */
571
572 int
hx509_ca_tbs_add_san_otherName(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const heim_octet_string * os)573 hx509_ca_tbs_add_san_otherName(hx509_context context,
574 hx509_ca_tbs tbs,
575 const heim_oid *oid,
576 const heim_octet_string *os)
577 {
578 GeneralName gn;
579
580 memset(&gn, 0, sizeof(gn));
581 gn.element = choice_GeneralName_otherName;
582 gn.u.otherName.type_id = *oid;
583 gn.u.otherName.value = *os;
584
585 return add_GeneralNames(&tbs->san, &gn);
586 }
587
588 /**
589 * Add Kerberos Subject Alternative Name to the to-be-signed
590 * certificate object. The principal string is a UTF8 string.
591 *
592 * @param context A hx509 context.
593 * @param tbs object to be signed.
594 * @param principal Kerberos principal to add to the certificate.
595 *
596 * @return An hx509 error code, see hx509_get_error_string().
597 *
598 * @ingroup hx509_ca
599 */
600
601 int
hx509_ca_tbs_add_san_pkinit(hx509_context context,hx509_ca_tbs tbs,const char * principal)602 hx509_ca_tbs_add_san_pkinit(hx509_context context,
603 hx509_ca_tbs tbs,
604 const char *principal)
605 {
606 heim_octet_string os;
607 KRB5PrincipalName p;
608 size_t size;
609 int ret;
610 char *s = NULL;
611
612 memset(&p, 0, sizeof(p));
613
614 /* parse principal */
615 {
616 const char *str;
617 char *q;
618 int n;
619
620 /* count number of component */
621 n = 1;
622 for(str = principal; *str != '\0' && *str != '@'; str++){
623 if(*str=='\\'){
624 if(str[1] == '\0' || str[1] == '@') {
625 ret = HX509_PARSING_NAME_FAILED;
626 hx509_set_error_string(context, 0, ret,
627 "trailing \\ in principal name");
628 goto out;
629 }
630 str++;
631 } else if(*str == '/')
632 n++;
633 }
634 p.principalName.name_string.val =
635 calloc(n, sizeof(*p.principalName.name_string.val));
636 if (p.principalName.name_string.val == NULL) {
637 ret = ENOMEM;
638 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
639 goto out;
640 }
641 p.principalName.name_string.len = n;
642
643 p.principalName.name_type = KRB5_NT_PRINCIPAL;
644 q = s = strdup(principal);
645 if (q == NULL) {
646 ret = ENOMEM;
647 hx509_set_error_string(context, 0, ret, "malloc: out of memory");
648 goto out;
649 }
650 p.realm = strrchr(q, '@');
651 if (p.realm == NULL) {
652 ret = HX509_PARSING_NAME_FAILED;
653 hx509_set_error_string(context, 0, ret, "Missing @ in principal");
654 goto out;
655 };
656 *p.realm++ = '\0';
657
658 n = 0;
659 while (q) {
660 p.principalName.name_string.val[n++] = q;
661 q = strchr(q, '/');
662 if (q)
663 *q++ = '\0';
664 }
665 }
666
667 ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
668 if (ret) {
669 hx509_set_error_string(context, 0, ret, "Out of memory");
670 goto out;
671 }
672 if (size != os.length)
673 _hx509_abort("internal ASN.1 encoder error");
674
675 ret = hx509_ca_tbs_add_san_otherName(context,
676 tbs,
677 &asn1_oid_id_pkinit_san,
678 &os);
679 free(os.data);
680 out:
681 if (p.principalName.name_string.val)
682 free (p.principalName.name_string.val);
683 if (s)
684 free(s);
685 return ret;
686 }
687
688 /*
689 *
690 */
691
692 static int
add_utf8_san(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const char * string)693 add_utf8_san(hx509_context context,
694 hx509_ca_tbs tbs,
695 const heim_oid *oid,
696 const char *string)
697 {
698 const PKIXXmppAddr ustring = (const PKIXXmppAddr)(intptr_t)string;
699 heim_octet_string os;
700 size_t size;
701 int ret;
702
703 os.length = 0;
704 os.data = NULL;
705
706 ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
707 if (ret) {
708 hx509_set_error_string(context, 0, ret, "Out of memory");
709 goto out;
710 }
711 if (size != os.length)
712 _hx509_abort("internal ASN.1 encoder error");
713
714 ret = hx509_ca_tbs_add_san_otherName(context,
715 tbs,
716 oid,
717 &os);
718 free(os.data);
719 out:
720 return ret;
721 }
722
723 /**
724 * Add Microsoft UPN Subject Alternative Name to the to-be-signed
725 * certificate object. The principal string is a UTF8 string.
726 *
727 * @param context A hx509 context.
728 * @param tbs object to be signed.
729 * @param principal Microsoft UPN string.
730 *
731 * @return An hx509 error code, see hx509_get_error_string().
732 *
733 * @ingroup hx509_ca
734 */
735
736 int
hx509_ca_tbs_add_san_ms_upn(hx509_context context,hx509_ca_tbs tbs,const char * principal)737 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
738 hx509_ca_tbs tbs,
739 const char *principal)
740 {
741 return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
742 }
743
744 /**
745 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
746 * certificate object. The jid is an UTF8 string.
747 *
748 * @param context A hx509 context.
749 * @param tbs object to be signed.
750 * @param jid string of an a jabber id in UTF8.
751 *
752 * @return An hx509 error code, see hx509_get_error_string().
753 *
754 * @ingroup hx509_ca
755 */
756
757 int
hx509_ca_tbs_add_san_jid(hx509_context context,hx509_ca_tbs tbs,const char * jid)758 hx509_ca_tbs_add_san_jid(hx509_context context,
759 hx509_ca_tbs tbs,
760 const char *jid)
761 {
762 return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
763 }
764
765
766 /**
767 * Add a Subject Alternative Name hostname to to-be-signed certificate
768 * object. A domain match starts with ., an exact match does not.
769 *
770 * Example of a an domain match: .domain.se matches the hostname
771 * host.domain.se.
772 *
773 * @param context A hx509 context.
774 * @param tbs object to be signed.
775 * @param dnsname a hostame.
776 *
777 * @return An hx509 error code, see hx509_get_error_string().
778 *
779 * @ingroup hx509_ca
780 */
781
782 int
hx509_ca_tbs_add_san_hostname(hx509_context context,hx509_ca_tbs tbs,const char * dnsname)783 hx509_ca_tbs_add_san_hostname(hx509_context context,
784 hx509_ca_tbs tbs,
785 const char *dnsname)
786 {
787 GeneralName gn;
788
789 memset(&gn, 0, sizeof(gn));
790 gn.element = choice_GeneralName_dNSName;
791 gn.u.dNSName.data = rk_UNCONST(dnsname);
792 gn.u.dNSName.length = strlen(dnsname);
793
794 return add_GeneralNames(&tbs->san, &gn);
795 }
796
797 /**
798 * Add a Subject Alternative Name rfc822 (email address) to
799 * to-be-signed certificate object.
800 *
801 * @param context A hx509 context.
802 * @param tbs object to be signed.
803 * @param rfc822Name a string to a email address.
804 *
805 * @return An hx509 error code, see hx509_get_error_string().
806 *
807 * @ingroup hx509_ca
808 */
809
810 int
hx509_ca_tbs_add_san_rfc822name(hx509_context context,hx509_ca_tbs tbs,const char * rfc822Name)811 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
812 hx509_ca_tbs tbs,
813 const char *rfc822Name)
814 {
815 GeneralName gn;
816
817 memset(&gn, 0, sizeof(gn));
818 gn.element = choice_GeneralName_rfc822Name;
819 gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
820 gn.u.rfc822Name.length = strlen(rfc822Name);
821
822 return add_GeneralNames(&tbs->san, &gn);
823 }
824
825 /**
826 * Set the subject name of a to-be-signed certificate object.
827 *
828 * @param context A hx509 context.
829 * @param tbs object to be signed.
830 * @param subject the name to set a subject.
831 *
832 * @return An hx509 error code, see hx509_get_error_string().
833 *
834 * @ingroup hx509_ca
835 */
836
837 int
hx509_ca_tbs_set_subject(hx509_context context,hx509_ca_tbs tbs,hx509_name subject)838 hx509_ca_tbs_set_subject(hx509_context context,
839 hx509_ca_tbs tbs,
840 hx509_name subject)
841 {
842 if (tbs->subject)
843 hx509_name_free(&tbs->subject);
844 return hx509_name_copy(context, subject, &tbs->subject);
845 }
846
847 /**
848 * Set the issuerUniqueID and subjectUniqueID
849 *
850 * These are only supposed to be used considered with version 2
851 * certificates, replaced by the two extensions SubjectKeyIdentifier
852 * and IssuerKeyIdentifier. This function is to allow application
853 * using legacy protocol to issue them.
854 *
855 * @param context A hx509 context.
856 * @param tbs object to be signed.
857 * @param issuerUniqueID to be set
858 * @param subjectUniqueID to be set
859 *
860 * @return An hx509 error code, see hx509_get_error_string().
861 *
862 * @ingroup hx509_ca
863 */
864
865 int
hx509_ca_tbs_set_unique(hx509_context context,hx509_ca_tbs tbs,const heim_bit_string * subjectUniqueID,const heim_bit_string * issuerUniqueID)866 hx509_ca_tbs_set_unique(hx509_context context,
867 hx509_ca_tbs tbs,
868 const heim_bit_string *subjectUniqueID,
869 const heim_bit_string *issuerUniqueID)
870 {
871 int ret;
872
873 der_free_bit_string(&tbs->subjectUniqueID);
874 der_free_bit_string(&tbs->issuerUniqueID);
875
876 if (subjectUniqueID) {
877 ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
878 if (ret)
879 return ret;
880 }
881
882 if (issuerUniqueID) {
883 ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
884 if (ret)
885 return ret;
886 }
887
888 return 0;
889 }
890
891 /**
892 * Expand the the subject name in the to-be-signed certificate object
893 * using hx509_name_expand().
894 *
895 * @param context A hx509 context.
896 * @param tbs object to be signed.
897 * @param env environment variable to expand variables in the subject
898 * name, see hx509_env_init().
899 *
900 * @return An hx509 error code, see hx509_get_error_string().
901 *
902 * @ingroup hx509_ca
903 */
904
905 int
hx509_ca_tbs_subject_expand(hx509_context context,hx509_ca_tbs tbs,hx509_env env)906 hx509_ca_tbs_subject_expand(hx509_context context,
907 hx509_ca_tbs tbs,
908 hx509_env env)
909 {
910 return hx509_name_expand(context, tbs->subject, env);
911 }
912
913 /**
914 * Set signature algorithm on the to be signed certificate
915 *
916 * @param context A hx509 context.
917 * @param tbs object to be signed.
918 * @param sigalg signature algorithm to use
919 *
920 * @return An hx509 error code, see hx509_get_error_string().
921 *
922 * @ingroup hx509_ca
923 */
924
925 int
hx509_ca_tbs_set_signature_algorithm(hx509_context context,hx509_ca_tbs tbs,const AlgorithmIdentifier * sigalg)926 hx509_ca_tbs_set_signature_algorithm(hx509_context context,
927 hx509_ca_tbs tbs,
928 const AlgorithmIdentifier *sigalg)
929 {
930 int ret;
931
932 tbs->sigalg = calloc(1, sizeof(*tbs->sigalg));
933 if (tbs->sigalg == NULL) {
934 hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
935 return ENOMEM;
936 }
937 ret = copy_AlgorithmIdentifier(sigalg, tbs->sigalg);
938 if (ret) {
939 free(tbs->sigalg);
940 tbs->sigalg = NULL;
941 return ret;
942 }
943 return 0;
944 }
945
946 /*
947 *
948 */
949
950 static int
add_extension(hx509_context context,TBSCertificate * tbsc,int critical_flag,const heim_oid * oid,const heim_octet_string * data)951 add_extension(hx509_context context,
952 TBSCertificate *tbsc,
953 int critical_flag,
954 const heim_oid *oid,
955 const heim_octet_string *data)
956 {
957 Extension ext;
958 int ret;
959
960 memset(&ext, 0, sizeof(ext));
961
962 if (critical_flag) {
963 ext.critical = malloc(sizeof(*ext.critical));
964 if (ext.critical == NULL) {
965 ret = ENOMEM;
966 hx509_set_error_string(context, 0, ret, "Out of memory");
967 goto out;
968 }
969 *ext.critical = TRUE;
970 }
971
972 ret = der_copy_oid(oid, &ext.extnID);
973 if (ret) {
974 hx509_set_error_string(context, 0, ret, "Out of memory");
975 goto out;
976 }
977 ret = der_copy_octet_string(data, &ext.extnValue);
978 if (ret) {
979 hx509_set_error_string(context, 0, ret, "Out of memory");
980 goto out;
981 }
982 ret = add_Extensions(tbsc->extensions, &ext);
983 if (ret) {
984 hx509_set_error_string(context, 0, ret, "Out of memory");
985 goto out;
986 }
987 out:
988 free_Extension(&ext);
989 return ret;
990 }
991
992 static int
build_proxy_prefix(hx509_context context,const Name * issuer,Name * subject)993 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
994 {
995 char *tstr;
996 time_t t;
997 int ret;
998
999 ret = copy_Name(issuer, subject);
1000 if (ret) {
1001 hx509_set_error_string(context, 0, ret,
1002 "Failed to copy subject name");
1003 return ret;
1004 }
1005
1006 t = time(NULL);
1007 ret = asprintf(&tstr, "ts-%lu", (unsigned long)t);
1008 if (ret == -1 || tstr == NULL) {
1009 hx509_set_error_string(context, 0, ENOMEM,
1010 "Failed to copy subject name");
1011 return ENOMEM;
1012 }
1013 /* prefix with CN=<ts>,...*/
1014 ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
1015 free(tstr);
1016 if (ret)
1017 free_Name(subject);
1018 return ret;
1019 }
1020
1021 static int
ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,const AuthorityKeyIdentifier * ai,const Name * issuername,hx509_cert * certificate)1022 ca_sign(hx509_context context,
1023 hx509_ca_tbs tbs,
1024 hx509_private_key signer,
1025 const AuthorityKeyIdentifier *ai,
1026 const Name *issuername,
1027 hx509_cert *certificate)
1028 {
1029 heim_error_t error = NULL;
1030 heim_octet_string data;
1031 Certificate c;
1032 TBSCertificate *tbsc;
1033 size_t size;
1034 int ret;
1035 const AlgorithmIdentifier *sigalg;
1036 time_t notBefore;
1037 time_t notAfter;
1038 unsigned key_usage;
1039
1040 sigalg = tbs->sigalg;
1041 if (sigalg == NULL)
1042 sigalg = _hx509_crypto_default_sig_alg;
1043
1044 memset(&c, 0, sizeof(c));
1045
1046 /*
1047 * Default values are: Valid since 24h ago, valid one year into
1048 * the future, KeyUsage digitalSignature and keyEncipherment set,
1049 * and keyCertSign for CA certificates.
1050 */
1051 notBefore = tbs->notBefore;
1052 if (notBefore == 0)
1053 notBefore = time(NULL) - 3600 * 24;
1054 notAfter = tbs->notAfter;
1055 if (notAfter == 0)
1056 notAfter = time(NULL) + 3600 * 24 * 365;
1057
1058 key_usage = tbs->key_usage;
1059 if (key_usage == 0) {
1060 KeyUsage ku;
1061 memset(&ku, 0, sizeof(ku));
1062 ku.digitalSignature = 1;
1063 ku.keyEncipherment = 1;
1064 key_usage = KeyUsage2int(ku);
1065 }
1066
1067 if (tbs->flags.ca) {
1068 KeyUsage ku;
1069 memset(&ku, 0, sizeof(ku));
1070 ku.keyCertSign = 1;
1071 ku.cRLSign = 1;
1072 key_usage |= KeyUsage2int(ku);
1073 }
1074
1075 /*
1076 *
1077 */
1078
1079 tbsc = &c.tbsCertificate;
1080
1081 if (tbs->flags.key == 0) {
1082 ret = EINVAL;
1083 hx509_set_error_string(context, 0, ret, "No public key set");
1084 return ret;
1085 }
1086 /*
1087 * Don't put restrictions on proxy certificate's subject name, it
1088 * will be generated below.
1089 */
1090 if (!tbs->flags.proxy) {
1091 if (tbs->subject == NULL) {
1092 hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1093 return EINVAL;
1094 }
1095 if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1096 hx509_set_error_string(context, 0, EINVAL,
1097 "NULL subject and no SubjectAltNames");
1098 return EINVAL;
1099 }
1100 }
1101 if (tbs->flags.ca && tbs->flags.proxy) {
1102 hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1103 "at the same time");
1104 return EINVAL;
1105 }
1106 if (tbs->flags.proxy) {
1107 if (tbs->san.len > 0) {
1108 hx509_set_error_string(context, 0, EINVAL,
1109 "Proxy certificate is not allowed "
1110 "to have SubjectAltNames");
1111 return EINVAL;
1112 }
1113 }
1114
1115 /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1116 tbsc->version = calloc(1, sizeof(*tbsc->version));
1117 if (tbsc->version == NULL) {
1118 ret = ENOMEM;
1119 hx509_set_error_string(context, 0, ret, "Out of memory");
1120 goto out;
1121 }
1122 *tbsc->version = rfc3280_version_3;
1123 /* serialNumber CertificateSerialNumber, */
1124 if (tbs->flags.serial) {
1125 ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1126 if (ret) {
1127 hx509_set_error_string(context, 0, ret, "Out of memory");
1128 goto out;
1129 }
1130 } else {
1131 /*
1132 * If no explicit serial number is specified, 20 random bytes should be
1133 * sufficiently collision resistant. Since the serial number must be a
1134 * positive integer, ensure minimal ASN.1 DER form by forcing the high
1135 * bit off and the next bit on (thus avoiding an all zero first octet).
1136 */
1137 tbsc->serialNumber.length = 20;
1138 tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1139 if (tbsc->serialNumber.data == NULL){
1140 ret = ENOMEM;
1141 hx509_set_error_string(context, 0, ret, "Out of memory");
1142 goto out;
1143 }
1144 RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1145 ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1146 ((unsigned char *)tbsc->serialNumber.data)[0] |= 0x40;
1147 }
1148 /* signature AlgorithmIdentifier, */
1149 ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1150 if (ret) {
1151 hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1152 goto out;
1153 }
1154 /* issuer Name, */
1155 if (issuername)
1156 ret = copy_Name(issuername, &tbsc->issuer);
1157 else
1158 ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1159 if (ret) {
1160 hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1161 goto out;
1162 }
1163 /* validity Validity, */
1164 tbsc->validity.notBefore.element = choice_Time_generalTime;
1165 tbsc->validity.notBefore.u.generalTime = notBefore;
1166 tbsc->validity.notAfter.element = choice_Time_generalTime;
1167 tbsc->validity.notAfter.u.generalTime = notAfter;
1168 /* subject Name, */
1169 if (tbs->flags.proxy) {
1170 ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1171 if (ret)
1172 goto out;
1173 } else {
1174 ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1175 if (ret) {
1176 hx509_set_error_string(context, 0, ret,
1177 "Failed to copy subject name");
1178 goto out;
1179 }
1180 }
1181 /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1182 ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1183 if (ret) {
1184 hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1185 goto out;
1186 }
1187 /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1188 if (tbs->issuerUniqueID.length) {
1189 tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1190 if (tbsc->issuerUniqueID == NULL) {
1191 ret = ENOMEM;
1192 hx509_set_error_string(context, 0, ret, "Out of memory");
1193 goto out;
1194 }
1195 ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1196 if (ret) {
1197 hx509_set_error_string(context, 0, ret, "Out of memory");
1198 goto out;
1199 }
1200 }
1201 /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1202 if (tbs->subjectUniqueID.length) {
1203 tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1204 if (tbsc->subjectUniqueID == NULL) {
1205 ret = ENOMEM;
1206 hx509_set_error_string(context, 0, ret, "Out of memory");
1207 goto out;
1208 }
1209
1210 ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1211 if (ret) {
1212 hx509_set_error_string(context, 0, ret, "Out of memory");
1213 goto out;
1214 }
1215 }
1216
1217 /* extensions [3] EXPLICIT Extensions OPTIONAL */
1218 tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1219 if (tbsc->extensions == NULL) {
1220 ret = ENOMEM;
1221 hx509_set_error_string(context, 0, ret, "Out of memory");
1222 goto out;
1223 }
1224
1225 /* Add the text BMP string Domaincontroller to the cert */
1226 if (tbs->flags.domaincontroller) {
1227 data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1228 "\x00\x61\x00\x69\x00\x6e\x00\x43"
1229 "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1230 "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1231 "\x00\x72");
1232 data.length = 34;
1233
1234 ret = add_extension(context, tbsc, 0,
1235 &asn1_oid_id_ms_cert_enroll_domaincontroller,
1236 &data);
1237 if (ret)
1238 goto out;
1239 }
1240
1241 /* add KeyUsage */
1242 {
1243 KeyUsage ku;
1244
1245 ku = int2KeyUsage(key_usage);
1246 ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1247 if (ret) {
1248 hx509_set_error_string(context, 0, ret, "Out of memory");
1249 goto out;
1250 }
1251 if (size != data.length)
1252 _hx509_abort("internal ASN.1 encoder error");
1253 ret = add_extension(context, tbsc, 1,
1254 &asn1_oid_id_x509_ce_keyUsage, &data);
1255 free(data.data);
1256 if (ret)
1257 goto out;
1258 }
1259
1260 /* add ExtendedKeyUsage */
1261 if (tbs->eku.len > 0) {
1262 ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1263 &tbs->eku, &size, ret);
1264 if (ret) {
1265 hx509_set_error_string(context, 0, ret, "Out of memory");
1266 goto out;
1267 }
1268 if (size != data.length)
1269 _hx509_abort("internal ASN.1 encoder error");
1270 ret = add_extension(context, tbsc, 0,
1271 &asn1_oid_id_x509_ce_extKeyUsage, &data);
1272 free(data.data);
1273 if (ret)
1274 goto out;
1275 }
1276
1277 /* add Subject Alternative Name */
1278 if (tbs->san.len > 0) {
1279 ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1280 &tbs->san, &size, ret);
1281 if (ret) {
1282 hx509_set_error_string(context, 0, ret, "Out of memory");
1283 goto out;
1284 }
1285 if (size != data.length)
1286 _hx509_abort("internal ASN.1 encoder error");
1287 ret = add_extension(context, tbsc, 0,
1288 &asn1_oid_id_x509_ce_subjectAltName,
1289 &data);
1290 free(data.data);
1291 if (ret)
1292 goto out;
1293 }
1294
1295 /* Add Authority Key Identifier */
1296 if (ai) {
1297 ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1298 ai, &size, ret);
1299 if (ret) {
1300 hx509_set_error_string(context, 0, ret, "Out of memory");
1301 goto out;
1302 }
1303 if (size != data.length)
1304 _hx509_abort("internal ASN.1 encoder error");
1305 ret = add_extension(context, tbsc, 0,
1306 &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1307 &data);
1308 free(data.data);
1309 if (ret)
1310 goto out;
1311 }
1312
1313 /* Add Subject Key Identifier */
1314 {
1315 SubjectKeyIdentifier si;
1316 unsigned char hash[SHA_DIGEST_LENGTH];
1317
1318 {
1319 EVP_MD_CTX *ctx;
1320
1321 ctx = EVP_MD_CTX_create();
1322 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1323 EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1324 tbs->spki.subjectPublicKey.length / 8);
1325 EVP_DigestFinal_ex(ctx, hash, NULL);
1326 EVP_MD_CTX_destroy(ctx);
1327 }
1328
1329 si.data = hash;
1330 si.length = sizeof(hash);
1331
1332 ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1333 &si, &size, ret);
1334 if (ret) {
1335 hx509_set_error_string(context, 0, ret, "Out of memory");
1336 goto out;
1337 }
1338 if (size != data.length)
1339 _hx509_abort("internal ASN.1 encoder error");
1340 ret = add_extension(context, tbsc, 0,
1341 &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1342 &data);
1343 free(data.data);
1344 if (ret)
1345 goto out;
1346 }
1347
1348 /* Add BasicConstraints */
1349 {
1350 BasicConstraints bc;
1351 int aCA = 1;
1352 unsigned int path;
1353
1354 memset(&bc, 0, sizeof(bc));
1355
1356 if (tbs->flags.ca) {
1357 bc.cA = &aCA;
1358 if (tbs->pathLenConstraint >= 0) {
1359 path = tbs->pathLenConstraint;
1360 bc.pathLenConstraint = &path;
1361 }
1362 }
1363
1364 ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1365 &bc, &size, ret);
1366 if (ret) {
1367 hx509_set_error_string(context, 0, ret, "Out of memory");
1368 goto out;
1369 }
1370 if (size != data.length)
1371 _hx509_abort("internal ASN.1 encoder error");
1372 /* Critical if this is a CA */
1373 ret = add_extension(context, tbsc, tbs->flags.ca,
1374 &asn1_oid_id_x509_ce_basicConstraints,
1375 &data);
1376 free(data.data);
1377 if (ret)
1378 goto out;
1379 }
1380
1381 /* add Proxy */
1382 if (tbs->flags.proxy) {
1383 ProxyCertInfo info;
1384
1385 memset(&info, 0, sizeof(info));
1386
1387 if (tbs->pathLenConstraint >= 0) {
1388 info.pCPathLenConstraint =
1389 malloc(sizeof(*info.pCPathLenConstraint));
1390 if (info.pCPathLenConstraint == NULL) {
1391 ret = ENOMEM;
1392 hx509_set_error_string(context, 0, ret, "Out of memory");
1393 goto out;
1394 }
1395 *info.pCPathLenConstraint = tbs->pathLenConstraint;
1396 }
1397
1398 ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
1399 &info.proxyPolicy.policyLanguage);
1400 if (ret) {
1401 free_ProxyCertInfo(&info);
1402 hx509_set_error_string(context, 0, ret, "Out of memory");
1403 goto out;
1404 }
1405
1406 ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1407 &info, &size, ret);
1408 free_ProxyCertInfo(&info);
1409 if (ret) {
1410 hx509_set_error_string(context, 0, ret, "Out of memory");
1411 goto out;
1412 }
1413 if (size != data.length)
1414 _hx509_abort("internal ASN.1 encoder error");
1415 ret = add_extension(context, tbsc, 0,
1416 &asn1_oid_id_pkix_pe_proxyCertInfo,
1417 &data);
1418 free(data.data);
1419 if (ret)
1420 goto out;
1421 }
1422
1423 if (tbs->crldp.len) {
1424
1425 ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1426 &tbs->crldp, &size, ret);
1427 if (ret) {
1428 hx509_set_error_string(context, 0, ret, "Out of memory");
1429 goto out;
1430 }
1431 if (size != data.length)
1432 _hx509_abort("internal ASN.1 encoder error");
1433 ret = add_extension(context, tbsc, FALSE,
1434 &asn1_oid_id_x509_ce_cRLDistributionPoints,
1435 &data);
1436 free(data.data);
1437 if (ret)
1438 goto out;
1439 }
1440
1441 ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1442 if (ret) {
1443 hx509_set_error_string(context, 0, ret, "malloc out of memory");
1444 goto out;
1445 }
1446 if (data.length != size)
1447 _hx509_abort("internal ASN.1 encoder error");
1448
1449 ret = _hx509_create_signature_bitstring(context,
1450 signer,
1451 sigalg,
1452 &data,
1453 &c.signatureAlgorithm,
1454 &c.signatureValue);
1455 free(data.data);
1456 if (ret)
1457 goto out;
1458
1459 *certificate = hx509_cert_init(context, &c, &error);
1460 if (*certificate == NULL) {
1461 ret = heim_error_get_code(error);
1462 heim_release(error);
1463 goto out;
1464 }
1465
1466 free_Certificate(&c);
1467
1468 return 0;
1469
1470 out:
1471 free_Certificate(&c);
1472 return ret;
1473 }
1474
1475 static int
get_AuthorityKeyIdentifier(hx509_context context,const Certificate * certificate,AuthorityKeyIdentifier * ai)1476 get_AuthorityKeyIdentifier(hx509_context context,
1477 const Certificate *certificate,
1478 AuthorityKeyIdentifier *ai)
1479 {
1480 SubjectKeyIdentifier si;
1481 int ret;
1482
1483 ret = _hx509_find_extension_subject_key_id(certificate, &si);
1484 if (ret == 0) {
1485 ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1486 if (ai->keyIdentifier == NULL) {
1487 free_SubjectKeyIdentifier(&si);
1488 ret = ENOMEM;
1489 hx509_set_error_string(context, 0, ret, "Out of memory");
1490 goto out;
1491 }
1492 ret = der_copy_octet_string(&si, ai->keyIdentifier);
1493 free_SubjectKeyIdentifier(&si);
1494 if (ret) {
1495 hx509_set_error_string(context, 0, ret, "Out of memory");
1496 goto out;
1497 }
1498 } else {
1499 GeneralNames gns;
1500 GeneralName gn;
1501 Name name;
1502
1503 memset(&gn, 0, sizeof(gn));
1504 memset(&gns, 0, sizeof(gns));
1505 memset(&name, 0, sizeof(name));
1506
1507 ai->authorityCertIssuer =
1508 calloc(1, sizeof(*ai->authorityCertIssuer));
1509 if (ai->authorityCertIssuer == NULL) {
1510 ret = ENOMEM;
1511 hx509_set_error_string(context, 0, ret, "Out of memory");
1512 goto out;
1513 }
1514 ai->authorityCertSerialNumber =
1515 calloc(1, sizeof(*ai->authorityCertSerialNumber));
1516 if (ai->authorityCertSerialNumber == NULL) {
1517 ret = ENOMEM;
1518 hx509_set_error_string(context, 0, ret, "Out of memory");
1519 goto out;
1520 }
1521
1522 /*
1523 * XXX unbreak when asn1 compiler handle IMPLICIT
1524 *
1525 * This is so horrible.
1526 */
1527
1528 ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1529 if (ret) {
1530 hx509_set_error_string(context, 0, ret, "Out of memory");
1531 goto out;
1532 }
1533
1534 memset(&gn, 0, sizeof(gn));
1535 gn.element = choice_GeneralName_directoryName;
1536 gn.u.directoryName.element =
1537 choice_GeneralName_directoryName_rdnSequence;
1538 gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1539
1540 ret = add_GeneralNames(&gns, &gn);
1541 if (ret) {
1542 hx509_set_error_string(context, 0, ret, "Out of memory");
1543 goto out;
1544 }
1545
1546 ai->authorityCertIssuer->val = gns.val;
1547 ai->authorityCertIssuer->len = gns.len;
1548
1549 ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1550 ai->authorityCertSerialNumber);
1551 if (ai->authorityCertSerialNumber == NULL) {
1552 ret = ENOMEM;
1553 hx509_set_error_string(context, 0, ret, "Out of memory");
1554 goto out;
1555 }
1556 }
1557 out:
1558 if (ret)
1559 free_AuthorityKeyIdentifier(ai);
1560 return ret;
1561 }
1562
1563
1564 /**
1565 * Sign a to-be-signed certificate object with a issuer certificate.
1566 *
1567 * The caller needs to at least have called the following functions on the
1568 * to-be-signed certificate object:
1569 * - hx509_ca_tbs_init()
1570 * - hx509_ca_tbs_set_subject()
1571 * - hx509_ca_tbs_set_spki()
1572 *
1573 * When done the to-be-signed certificate object should be freed with
1574 * hx509_ca_tbs_free().
1575 *
1576 * When creating self-signed certificate use hx509_ca_sign_self() instead.
1577 *
1578 * @param context A hx509 context.
1579 * @param tbs object to be signed.
1580 * @param signer the CA certificate object to sign with (need private key).
1581 * @param certificate return cerificate, free with hx509_cert_free().
1582 *
1583 * @return An hx509 error code, see hx509_get_error_string().
1584 *
1585 * @ingroup hx509_ca
1586 */
1587
1588 int
hx509_ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_cert signer,hx509_cert * certificate)1589 hx509_ca_sign(hx509_context context,
1590 hx509_ca_tbs tbs,
1591 hx509_cert signer,
1592 hx509_cert *certificate)
1593 {
1594 const Certificate *signer_cert;
1595 AuthorityKeyIdentifier ai;
1596 int ret;
1597
1598 memset(&ai, 0, sizeof(ai));
1599
1600 signer_cert = _hx509_get_cert(signer);
1601
1602 ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1603 if (ret)
1604 goto out;
1605
1606 ret = ca_sign(context,
1607 tbs,
1608 _hx509_cert_private_key(signer),
1609 &ai,
1610 &signer_cert->tbsCertificate.subject,
1611 certificate);
1612
1613 out:
1614 free_AuthorityKeyIdentifier(&ai);
1615
1616 return ret;
1617 }
1618
1619 /**
1620 * Work just like hx509_ca_sign() but signs it-self.
1621 *
1622 * @param context A hx509 context.
1623 * @param tbs object to be signed.
1624 * @param signer private key to sign with.
1625 * @param certificate return cerificate, free with hx509_cert_free().
1626 *
1627 * @return An hx509 error code, see hx509_get_error_string().
1628 *
1629 * @ingroup hx509_ca
1630 */
1631
1632 int
hx509_ca_sign_self(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,hx509_cert * certificate)1633 hx509_ca_sign_self(hx509_context context,
1634 hx509_ca_tbs tbs,
1635 hx509_private_key signer,
1636 hx509_cert *certificate)
1637 {
1638 return ca_sign(context,
1639 tbs,
1640 signer,
1641 NULL,
1642 NULL,
1643 certificate);
1644 }
1645