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