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 :
36 : /**
37 : * @page page_ca Hx509 CA functions
38 : *
39 : * See the library functions here: @ref hx509_ca
40 : */
41 :
42 : struct hx509_ca_tbs {
43 : hx509_name subject;
44 : SubjectPublicKeyInfo spki;
45 : KeyUsage ku;
46 : ExtKeyUsage eku;
47 : GeneralNames san;
48 : CertificatePolicies cps;
49 : PolicyMappings pms;
50 : heim_integer serial;
51 : struct {
52 : unsigned int proxy:1;
53 : unsigned int ca:1;
54 : unsigned int key:1;
55 : unsigned int serial:1;
56 : unsigned int domaincontroller:1;
57 : unsigned int xUniqueID:1;
58 : } flags;
59 : time_t notBefore;
60 : time_t notAfter;
61 : HeimPkinitPrincMaxLifeSecs pkinitTicketMaxLife;
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 : HX509_LIB_FUNCTION int HX509_LIB_CALL
83 0 : hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84 : {
85 0 : *tbs = calloc(1, sizeof(**tbs));
86 0 : if (*tbs == NULL)
87 0 : return ENOMEM;
88 :
89 0 : 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 : HX509_LIB_FUNCTION void HX509_LIB_CALL
101 0 : hx509_ca_tbs_free(hx509_ca_tbs *tbs)
102 : {
103 0 : if (tbs == NULL || *tbs == NULL)
104 0 : return;
105 :
106 0 : free_SubjectPublicKeyInfo(&(*tbs)->spki);
107 0 : free_CertificatePolicies(&(*tbs)->cps);
108 0 : free_PolicyMappings(&(*tbs)->pms);
109 0 : free_GeneralNames(&(*tbs)->san);
110 0 : free_ExtKeyUsage(&(*tbs)->eku);
111 0 : der_free_heim_integer(&(*tbs)->serial);
112 0 : free_CRLDistributionPoints(&(*tbs)->crldp);
113 0 : der_free_bit_string(&(*tbs)->subjectUniqueID);
114 0 : der_free_bit_string(&(*tbs)->issuerUniqueID);
115 0 : if ((*tbs)->subject)
116 0 : hx509_name_free(&(*tbs)->subject);
117 0 : if ((*tbs)->sigalg) {
118 0 : free_AlgorithmIdentifier((*tbs)->sigalg);
119 0 : free((*tbs)->sigalg);
120 : }
121 :
122 0 : memset(*tbs, 0, sizeof(**tbs));
123 0 : free(*tbs);
124 0 : *tbs = NULL;
125 : }
126 :
127 : /**
128 : * Set the absolute time when the certificate is valid from. If not
129 : * set the current time will be used.
130 : *
131 : * @param context A hx509 context.
132 : * @param tbs object to be signed.
133 : * @param t time the certificated will start to be valid
134 : *
135 : * @return An hx509 error code, see hx509_get_error_string().
136 : *
137 : * @ingroup hx509_ca
138 : */
139 :
140 : HX509_LIB_FUNCTION int HX509_LIB_CALL
141 0 : hx509_ca_tbs_set_notBefore(hx509_context context,
142 : hx509_ca_tbs tbs,
143 : time_t t)
144 : {
145 0 : tbs->notBefore = t;
146 0 : return 0;
147 : }
148 :
149 : /**
150 : * Set the absolute time when the certificate is valid to.
151 : *
152 : * @param context A hx509 context.
153 : * @param tbs object to be signed.
154 : * @param t time when the certificate will expire
155 : *
156 : * @return An hx509 error code, see hx509_get_error_string().
157 : *
158 : * @ingroup hx509_ca
159 : */
160 :
161 : HX509_LIB_FUNCTION int HX509_LIB_CALL
162 0 : hx509_ca_tbs_set_notAfter(hx509_context context,
163 : hx509_ca_tbs tbs,
164 : time_t t)
165 : {
166 0 : tbs->notAfter = t;
167 0 : return 0;
168 : }
169 :
170 : /**
171 : * Set the relative time when the certificiate is going to expire.
172 : *
173 : * @param context A hx509 context.
174 : * @param tbs object to be signed.
175 : * @param delta seconds to the certificate is going to expire.
176 : *
177 : * @return An hx509 error code, see hx509_get_error_string().
178 : *
179 : * @ingroup hx509_ca
180 : */
181 :
182 : HX509_LIB_FUNCTION int HX509_LIB_CALL
183 0 : hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
184 : hx509_ca_tbs tbs,
185 : time_t delta)
186 : {
187 0 : return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
188 : }
189 :
190 : HX509_LIB_FUNCTION int HX509_LIB_CALL
191 0 : hx509_ca_tbs_set_pkinit_max_life(hx509_context context,
192 : hx509_ca_tbs tbs,
193 : time_t max_life)
194 : {
195 0 : tbs->pkinitTicketMaxLife = max_life;
196 0 : return 0;
197 : }
198 :
199 : static const struct units templatebits[] = {
200 : { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
201 : { "KeyUsage", HX509_CA_TEMPLATE_KU },
202 : { "SPKI", HX509_CA_TEMPLATE_SPKI },
203 : { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
204 : { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
205 : { "serial", HX509_CA_TEMPLATE_SERIAL },
206 : { "subject", HX509_CA_TEMPLATE_SUBJECT },
207 : { "pkinitMaxLife", HX509_CA_TEMPLATE_PKINIT_MAX_LIFE },
208 : { NULL, 0 }
209 : };
210 :
211 : /**
212 : * Make of template units, use to build flags argument to
213 : * hx509_ca_tbs_set_template() with parse_units().
214 : *
215 : * @return an units structure.
216 : *
217 : * @ingroup hx509_ca
218 : */
219 :
220 : HX509_LIB_FUNCTION const struct units * HX509_LIB_CALL
221 0 : hx509_ca_tbs_template_units(void)
222 : {
223 0 : return templatebits;
224 : }
225 :
226 : /**
227 : * Initialize the to-be-signed certificate object from a template certificate.
228 : *
229 : * @param context A hx509 context.
230 : * @param tbs object to be signed.
231 : * @param flags bit field selecting what to copy from the template
232 : * certificate.
233 : * @param cert template certificate.
234 : *
235 : * @return An hx509 error code, see hx509_get_error_string().
236 : *
237 : * @ingroup hx509_ca
238 : */
239 :
240 : HX509_LIB_FUNCTION int HX509_LIB_CALL
241 0 : hx509_ca_tbs_set_template(hx509_context context,
242 : hx509_ca_tbs tbs,
243 : int flags,
244 : hx509_cert cert)
245 : {
246 0 : int ret;
247 :
248 0 : if (flags & HX509_CA_TEMPLATE_SUBJECT) {
249 0 : if (tbs->subject)
250 0 : hx509_name_free(&tbs->subject);
251 0 : ret = hx509_cert_get_subject(cert, &tbs->subject);
252 0 : if (ret) {
253 0 : hx509_set_error_string(context, 0, ret,
254 : "Failed to get subject from template");
255 0 : return ret;
256 : }
257 : }
258 0 : if (flags & HX509_CA_TEMPLATE_SERIAL) {
259 0 : der_free_heim_integer(&tbs->serial);
260 0 : ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
261 0 : tbs->flags.serial = !ret;
262 0 : if (ret) {
263 0 : hx509_set_error_string(context, 0, ret,
264 : "Failed to copy serial number");
265 0 : return ret;
266 : }
267 : }
268 0 : if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
269 0 : tbs->notBefore = hx509_cert_get_notBefore(cert);
270 0 : if (flags & HX509_CA_TEMPLATE_NOTAFTER)
271 0 : tbs->notAfter = hx509_cert_get_notAfter(cert);
272 0 : if (flags & HX509_CA_TEMPLATE_SPKI) {
273 0 : free_SubjectPublicKeyInfo(&tbs->spki);
274 0 : ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
275 0 : tbs->flags.key = !ret;
276 0 : if (ret)
277 0 : return ret;
278 : }
279 0 : if (flags & HX509_CA_TEMPLATE_KU) {
280 0 : ret = _hx509_cert_get_keyusage(context, cert, &tbs->ku);
281 0 : if (ret)
282 0 : return ret;
283 : }
284 0 : if (flags & HX509_CA_TEMPLATE_EKU) {
285 0 : ExtKeyUsage eku;
286 0 : size_t i;
287 0 : ret = _hx509_cert_get_eku(context, cert, &eku);
288 0 : if (ret)
289 0 : return ret;
290 0 : for (i = 0; i < eku.len; i++) {
291 0 : ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
292 0 : if (ret) {
293 0 : free_ExtKeyUsage(&eku);
294 0 : return ret;
295 : }
296 : }
297 0 : free_ExtKeyUsage(&eku);
298 : }
299 0 : if (flags & HX509_CA_TEMPLATE_PKINIT_MAX_LIFE) {
300 0 : time_t max_life;
301 :
302 0 : if ((max_life = hx509_cert_get_pkinit_max_life(context, cert, 0)) > 0)
303 0 : hx509_ca_tbs_set_pkinit_max_life(context, tbs, max_life);
304 : }
305 0 : return 0;
306 : }
307 :
308 : /**
309 : * Make the to-be-signed certificate object a CA certificate. If the
310 : * pathLenConstraint is negative path length constraint is used.
311 : *
312 : * @param context A hx509 context.
313 : * @param tbs object to be signed.
314 : * @param pathLenConstraint path length constraint, negative, no
315 : * constraint.
316 : *
317 : * @return An hx509 error code, see hx509_get_error_string().
318 : *
319 : * @ingroup hx509_ca
320 : */
321 :
322 : HX509_LIB_FUNCTION int HX509_LIB_CALL
323 0 : hx509_ca_tbs_set_ca(hx509_context context,
324 : hx509_ca_tbs tbs,
325 : int pathLenConstraint)
326 : {
327 0 : tbs->flags.ca = 1;
328 0 : tbs->pathLenConstraint = pathLenConstraint;
329 0 : return 0;
330 : }
331 :
332 : /**
333 : * Make the to-be-signed certificate object a proxy certificate. If the
334 : * pathLenConstraint is negative path length constraint is used.
335 : *
336 : * @param context A hx509 context.
337 : * @param tbs object to be signed.
338 : * @param pathLenConstraint path length constraint, negative, no
339 : * constraint.
340 : *
341 : * @return An hx509 error code, see hx509_get_error_string().
342 : *
343 : * @ingroup hx509_ca
344 : */
345 :
346 : HX509_LIB_FUNCTION int HX509_LIB_CALL
347 0 : hx509_ca_tbs_set_proxy(hx509_context context,
348 : hx509_ca_tbs tbs,
349 : int pathLenConstraint)
350 : {
351 0 : tbs->flags.proxy = 1;
352 0 : tbs->pathLenConstraint = pathLenConstraint;
353 0 : return 0;
354 : }
355 :
356 :
357 : /**
358 : * Make the to-be-signed certificate object a windows domain controller certificate.
359 : *
360 : * @param context A hx509 context.
361 : * @param tbs object to be signed.
362 : *
363 : * @return An hx509 error code, see hx509_get_error_string().
364 : *
365 : * @ingroup hx509_ca
366 : */
367 :
368 : HX509_LIB_FUNCTION int HX509_LIB_CALL
369 0 : hx509_ca_tbs_set_domaincontroller(hx509_context context,
370 : hx509_ca_tbs tbs)
371 : {
372 0 : tbs->flags.domaincontroller = 1;
373 0 : return 0;
374 : }
375 :
376 : /**
377 : * Set the subject public key info (SPKI) in the to-be-signed certificate
378 : * object. SPKI is the public key and key related parameters in the
379 : * certificate.
380 : *
381 : * @param context A hx509 context.
382 : * @param tbs object to be signed.
383 : * @param spki subject public key info to use for the to-be-signed certificate object.
384 : *
385 : * @return An hx509 error code, see hx509_get_error_string().
386 : *
387 : * @ingroup hx509_ca
388 : */
389 :
390 : HX509_LIB_FUNCTION int HX509_LIB_CALL
391 0 : hx509_ca_tbs_set_spki(hx509_context context,
392 : hx509_ca_tbs tbs,
393 : const SubjectPublicKeyInfo *spki)
394 : {
395 0 : int ret;
396 0 : free_SubjectPublicKeyInfo(&tbs->spki);
397 0 : ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
398 0 : tbs->flags.key = !ret;
399 0 : return ret;
400 : }
401 :
402 : /**
403 : * Set the serial number to use for to-be-signed certificate object.
404 : *
405 : * @param context A hx509 context.
406 : * @param tbs object to be signed.
407 : * @param serialNumber serial number to use for the to-be-signed
408 : * certificate object.
409 : *
410 : * @return An hx509 error code, see hx509_get_error_string().
411 : *
412 : * @ingroup hx509_ca
413 : */
414 :
415 : HX509_LIB_FUNCTION int HX509_LIB_CALL
416 0 : hx509_ca_tbs_set_serialnumber(hx509_context context,
417 : hx509_ca_tbs tbs,
418 : const heim_integer *serialNumber)
419 : {
420 0 : int ret;
421 0 : der_free_heim_integer(&tbs->serial);
422 0 : ret = der_copy_heim_integer(serialNumber, &tbs->serial);
423 0 : tbs->flags.serial = !ret;
424 0 : return ret;
425 : }
426 :
427 : /**
428 : * Copy elements of a CSR into a TBS, but only if all of them are authorized.
429 : *
430 : * @param context A hx509 context.
431 : * @param tbs object to be signed.
432 : * @param req CSR
433 : *
434 : * @return An hx509 error code, see hx509_get_error_string().
435 : *
436 : * @ingroup hx509_ca
437 : */
438 :
439 : HX509_LIB_FUNCTION int HX509_LIB_CALL
440 0 : hx509_ca_tbs_set_from_csr(hx509_context context,
441 : hx509_ca_tbs tbs,
442 : hx509_request req)
443 : {
444 0 : hx509_san_type san_type;
445 0 : heim_oid oid = { 0, NULL };
446 0 : KeyUsage ku;
447 0 : size_t i;
448 0 : char *s = NULL;
449 0 : int ret;
450 :
451 0 : if (hx509_request_count_unauthorized(req)) {
452 0 : hx509_set_error_string(context, 0, EACCES,
453 : "Some certificate features requested in the CSR were not authorized");
454 0 : return EACCES;
455 : }
456 :
457 0 : ret = hx509_request_get_ku(context, req, &ku);
458 0 : if (ret == 0 && KeyUsage2int(ku))
459 0 : ret = hx509_ca_tbs_add_ku(context, tbs, ku);
460 :
461 0 : for (i = 0; ret == 0; i++) {
462 0 : free(s); s = NULL;
463 0 : der_free_oid(&oid);
464 0 : ret = hx509_request_get_eku(req, i, &s);
465 0 : if (ret == 0)
466 0 : ret = der_parse_heim_oid(s, ".", &oid);
467 0 : if (ret == 0)
468 0 : ret = hx509_ca_tbs_add_eku(context, tbs, &oid);
469 : }
470 0 : if (ret == HX509_NO_ITEM)
471 0 : ret = 0;
472 :
473 0 : for (i = 0; ret == 0; i++) {
474 0 : free(s); s = NULL;
475 0 : ret = hx509_request_get_san(req, i, &san_type, &s);
476 0 : if (ret == 0)
477 0 : ret = hx509_ca_tbs_add_san(context, tbs, san_type, s);
478 : }
479 0 : if (ret == HX509_NO_ITEM)
480 0 : ret = 0;
481 :
482 0 : der_free_oid(&oid);
483 0 : free(s);
484 0 : return ret;
485 : }
486 :
487 : /**
488 : * An an extended key usage to the to-be-signed certificate object.
489 : * Duplicates will detected and not added.
490 : *
491 : * @param context A hx509 context.
492 : * @param tbs object to be signed.
493 : * @param oid extended key usage to add.
494 : *
495 : * @return An hx509 error code, see hx509_get_error_string().
496 : *
497 : * @ingroup hx509_ca
498 : */
499 :
500 : HX509_LIB_FUNCTION int HX509_LIB_CALL
501 0 : hx509_ca_tbs_add_ku(hx509_context context,
502 : hx509_ca_tbs tbs,
503 : KeyUsage ku)
504 : {
505 0 : tbs->ku = ku;
506 0 : return 0;
507 : }
508 :
509 : /**
510 : * An an extended key usage to the to-be-signed certificate object.
511 : * Duplicates will detected and not added.
512 : *
513 : * @param context A hx509 context.
514 : * @param tbs object to be signed.
515 : * @param oid extended key usage to add.
516 : *
517 : * @return An hx509 error code, see hx509_get_error_string().
518 : *
519 : * @ingroup hx509_ca
520 : */
521 :
522 : HX509_LIB_FUNCTION int HX509_LIB_CALL
523 0 : hx509_ca_tbs_add_eku(hx509_context context,
524 : hx509_ca_tbs tbs,
525 : const heim_oid *oid)
526 : {
527 0 : void *ptr;
528 0 : int ret;
529 0 : unsigned i;
530 :
531 : /* search for duplicates */
532 0 : for (i = 0; i < tbs->eku.len; i++) {
533 0 : if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
534 0 : return 0;
535 : }
536 :
537 0 : ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
538 0 : if (ptr == NULL) {
539 0 : hx509_set_error_string(context, 0, ENOMEM, "out of memory");
540 0 : return ENOMEM;
541 : }
542 0 : tbs->eku.val = ptr;
543 0 : ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
544 0 : if (ret) {
545 0 : hx509_set_error_string(context, 0, ret, "out of memory");
546 0 : return ret;
547 : }
548 0 : tbs->eku.len += 1;
549 0 : return 0;
550 : }
551 :
552 : /**
553 : * Add a certificate policy to the to-be-signed certificate object. Duplicates
554 : * will detected and not added.
555 : *
556 : * @param context A hx509 context.
557 : * @param tbs object to be signed.
558 : * @param oid policy OID.
559 : * @param cps_uri CPS URI to qualify policy with.
560 : * @param user_notice user notice display text to qualify policy with.
561 : *
562 : * @return An hx509 error code, see hx509_get_error_string().
563 : *
564 : * @ingroup hx509_ca
565 : */
566 :
567 : HX509_LIB_FUNCTION int HX509_LIB_CALL
568 0 : hx509_ca_tbs_add_pol(hx509_context context,
569 : hx509_ca_tbs tbs,
570 : const heim_oid *oid,
571 : const char *cps_uri,
572 : const char *user_notice)
573 : {
574 0 : PolicyQualifierInfos pqis;
575 0 : PolicyQualifierInfo pqi;
576 0 : PolicyInformation pi;
577 0 : size_t i, size;
578 0 : int ret = 0;
579 :
580 : /* search for duplicates */
581 0 : for (i = 0; i < tbs->cps.len; i++) {
582 0 : if (der_heim_oid_cmp(oid, &tbs->cps.val[i].policyIdentifier) == 0)
583 0 : return 0;
584 : }
585 :
586 0 : memset(&pi, 0, sizeof(pi));
587 0 : memset(&pqi, 0, sizeof(pqi));
588 0 : memset(&pqis, 0, sizeof(pqis));
589 :
590 0 : pi.policyIdentifier = *oid;
591 0 : if (cps_uri) {
592 0 : CPSuri uri;
593 :
594 0 : uri.length = strlen(cps_uri);
595 0 : uri.data = (void *)(uintptr_t)cps_uri;
596 0 : pqi.policyQualifierId = asn1_oid_id_pkix_qt_cps;
597 :
598 0 : ASN1_MALLOC_ENCODE(CPSuri,
599 : pqi.qualifier.data,
600 : pqi.qualifier.length,
601 : &uri, &size, ret);
602 0 : if (ret == 0) {
603 0 : ret = add_PolicyQualifierInfos(&pqis, &pqi);
604 0 : free_heim_any(&pqi.qualifier);
605 : }
606 : }
607 0 : if (ret == 0 && user_notice) {
608 0 : DisplayText dt;
609 0 : UserNotice un;
610 :
611 0 : dt.element = choice_DisplayText_utf8String;
612 0 : dt.u.utf8String = (void *)(uintptr_t)user_notice;
613 0 : un.explicitText = &dt;
614 0 : un.noticeRef = 0;
615 :
616 0 : pqi.policyQualifierId = asn1_oid_id_pkix_qt_unotice;
617 0 : ASN1_MALLOC_ENCODE(UserNotice,
618 : pqi.qualifier.data,
619 : pqi.qualifier.length,
620 : &un, &size, ret);
621 0 : if (ret == 0) {
622 0 : ret = add_PolicyQualifierInfos(&pqis, &pqi);
623 0 : free_heim_any(&pqi.qualifier);
624 : }
625 : }
626 :
627 0 : pi.policyQualifiers = pqis.len ? &pqis : 0;
628 :
629 0 : if (ret == 0)
630 0 : ret = add_CertificatePolicies(&tbs->cps, &pi);
631 :
632 0 : free_PolicyQualifierInfos(&pqis);
633 0 : return ret;
634 : }
635 :
636 : /**
637 : * Add a certificate policy mapping to the to-be-signed certificate object.
638 : * Duplicates will detected and not added.
639 : *
640 : * @param context A hx509 context.
641 : * @param tbs object to be signed.
642 : * @param issuer issuerDomainPolicy policy OID.
643 : * @param subject subjectDomainPolicy policy OID.
644 : *
645 : * @return An hx509 error code, see hx509_get_error_string().
646 : *
647 : * @ingroup hx509_ca
648 : */
649 :
650 : HX509_LIB_FUNCTION int HX509_LIB_CALL
651 0 : hx509_ca_tbs_add_pol_mapping(hx509_context context,
652 : hx509_ca_tbs tbs,
653 : const heim_oid *issuer,
654 : const heim_oid *subject)
655 : {
656 0 : PolicyMapping pm;
657 0 : size_t i;
658 :
659 : /* search for duplicates */
660 0 : for (i = 0; i < tbs->pms.len; i++) {
661 0 : PolicyMapping *pmp = &tbs->pms.val[i];
662 0 : if (der_heim_oid_cmp(issuer, &pmp->issuerDomainPolicy) == 0 &&
663 0 : der_heim_oid_cmp(subject, &pmp->subjectDomainPolicy) == 0)
664 0 : return 0;
665 : }
666 :
667 0 : memset(&pm, 0, sizeof(pm));
668 0 : pm.issuerDomainPolicy = *issuer;
669 0 : pm.subjectDomainPolicy = *subject;
670 0 : return add_PolicyMappings(&tbs->pms, &pm);
671 : }
672 :
673 : /**
674 : * Add CRL distribution point URI to the to-be-signed certificate
675 : * object.
676 : *
677 : * @param context A hx509 context.
678 : * @param tbs object to be signed.
679 : * @param uri uri to the CRL.
680 : * @param issuername name of the issuer.
681 : *
682 : * @return An hx509 error code, see hx509_get_error_string().
683 : *
684 : * @ingroup hx509_ca
685 : */
686 :
687 : HX509_LIB_FUNCTION int HX509_LIB_CALL
688 0 : hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
689 : hx509_ca_tbs tbs,
690 : const char *uri,
691 : hx509_name issuername)
692 : {
693 0 : DistributionPointName dpn;
694 0 : DistributionPoint dp;
695 0 : GeneralNames crlissuer;
696 0 : GeneralName gn, ign;
697 0 : Name in;
698 0 : int ret;
699 :
700 0 : memset(&dp, 0, sizeof(dp));
701 0 : memset(&gn, 0, sizeof(gn));
702 0 : memset(&ign, 0, sizeof(ign));
703 0 : memset(&in, 0, sizeof(in));
704 0 : gn.element = choice_GeneralName_uniformResourceIdentifier;
705 0 : gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
706 0 : gn.u.uniformResourceIdentifier.length = strlen(uri);
707 0 : dpn.element = choice_DistributionPointName_fullName;
708 0 : dpn.u.fullName.len = 1;
709 0 : dpn.u.fullName.val = &gn;
710 0 : dp.distributionPoint = &dpn;
711 :
712 0 : if (issuername) {
713 0 : ign.element = choice_GeneralName_directoryName;
714 0 : ret = hx509_name_to_Name(issuername, &ign.u.directoryName);
715 0 : if (ret) {
716 0 : hx509_set_error_string(context, 0, ret, "out of memory");
717 0 : return ret;
718 : }
719 0 : crlissuer.len = 1;
720 0 : crlissuer.val = &ign;
721 0 : dp.cRLIssuer = &crlissuer;
722 : }
723 :
724 0 : ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
725 0 : if (issuername)
726 0 : free_Name(&ign.u.directoryName);
727 :
728 0 : if (ret)
729 0 : hx509_set_error_string(context, 0, ret, "out of memory");
730 0 : return ret;
731 : }
732 :
733 : /**
734 : * Add Subject Alternative Name otherName to the to-be-signed
735 : * certificate object.
736 : *
737 : * @param context A hx509 context.
738 : * @param tbs object to be signed.
739 : * @param oid the oid of the OtherName.
740 : * @param os data in the other name.
741 : *
742 : * @return An hx509 error code, see hx509_get_error_string().
743 : *
744 : * @ingroup hx509_ca
745 : */
746 :
747 : HX509_LIB_FUNCTION int HX509_LIB_CALL
748 0 : hx509_ca_tbs_add_san_otherName(hx509_context context,
749 : hx509_ca_tbs tbs,
750 : const heim_oid *oid,
751 : const heim_octet_string *os)
752 : {
753 0 : GeneralName gn;
754 :
755 0 : memset(&gn, 0, sizeof(gn));
756 0 : gn.element = choice_GeneralName_otherName;
757 0 : gn.u.otherName.type_id = *oid;
758 0 : gn.u.otherName.value = *os;
759 :
760 0 : return add_GeneralNames(&tbs->san, &gn);
761 : }
762 :
763 : static
764 : int
765 0 : dequote_strndup(hx509_context context, const char *in, size_t len, char **out)
766 : {
767 0 : size_t i, k;
768 0 : char *s;
769 :
770 0 : *out = NULL;
771 0 : if ((s = malloc(len + 1)) == NULL) {
772 0 : hx509_set_error_string(context, 0, ENOMEM, "malloc: out of memory");
773 0 : return ENOMEM;
774 : }
775 :
776 0 : for (k = i = 0; i < len; i++) {
777 0 : if (in[i] == '\\') {
778 0 : switch (in[++i]) {
779 0 : case 't': s[k++] = '\t'; break;
780 0 : case 'b': s[k++] = '\b'; break;
781 0 : case 'n': s[k++] = '\n'; break;
782 0 : case '0':
783 0 : for (i++; i < len; i++) {
784 0 : if (in[i] == '\0')
785 0 : break;
786 0 : if (in[i++] == '\\' && in[i] == '0')
787 0 : continue;
788 0 : hx509_set_error_string(context, 0,
789 : HX509_PARSING_NAME_FAILED,
790 : "embedded NULs not supported in "
791 : "PKINIT SANs");
792 0 : free(s);
793 0 : return HX509_PARSING_NAME_FAILED;
794 : }
795 0 : break;
796 0 : case '\0':
797 0 : hx509_set_error_string(context, 0,
798 : HX509_PARSING_NAME_FAILED,
799 : "trailing unquoted backslashes not "
800 : "allowed in PKINIT SANs");
801 0 : free(s);
802 0 : return HX509_PARSING_NAME_FAILED;
803 0 : default: s[k++] = in[i]; break;
804 : }
805 : } else {
806 0 : s[k++] = in[i];
807 : }
808 : }
809 0 : s[k] = '\0';
810 :
811 0 : *out = s;
812 0 : return 0;
813 : }
814 :
815 : int
816 0 : _hx509_make_pkinit_san(hx509_context context,
817 : const char *principal,
818 : heim_octet_string *os)
819 : {
820 0 : KRB5PrincipalName p;
821 0 : size_t size;
822 0 : int ret;
823 :
824 0 : os->data = NULL;
825 0 : os->length = 0;
826 0 : memset(&p, 0, sizeof(p));
827 :
828 : /* Parse principal */
829 : {
830 0 : const char *str, *str_start;
831 0 : size_t n, i;
832 :
833 : /* Count number of components */
834 0 : n = 1;
835 0 : for (str = principal; *str != '\0' && *str != '@'; str++) {
836 0 : if (*str == '\\') {
837 0 : if (str[1] == '\0') {
838 0 : ret = HX509_PARSING_NAME_FAILED;
839 0 : hx509_set_error_string(context, 0, ret,
840 : "trailing \\ in principal name");
841 0 : goto out;
842 : }
843 0 : str++;
844 0 : } else if(*str == '/') {
845 0 : n++;
846 0 : } else if(*str == '@') {
847 0 : break;
848 : }
849 : }
850 0 : if (*str != '@') {
851 : /* Note that we allow the realm to be empty */
852 0 : ret = HX509_PARSING_NAME_FAILED;
853 0 : hx509_set_error_string(context, 0, ret, "Missing @ in principal");
854 0 : goto out;
855 0 : };
856 :
857 0 : p.principalName.name_string.val =
858 0 : calloc(n, sizeof(*p.principalName.name_string.val));
859 0 : if (p.principalName.name_string.val == NULL) {
860 0 : ret = ENOMEM;
861 0 : hx509_set_error_string(context, 0, ret, "malloc: out of memory");
862 0 : goto out;
863 : }
864 0 : p.principalName.name_string.len = n;
865 0 : p.principalName.name_type = KRB5_NT_PRINCIPAL;
866 :
867 0 : for (i = 0, str_start = str = principal; *str != '\0'; str++) {
868 0 : if (*str=='\\') {
869 0 : str++;
870 0 : } else if(*str == '/') {
871 : /* Note that we allow components to be empty */
872 0 : ret = dequote_strndup(context, str_start, str - str_start,
873 0 : &p.principalName.name_string.val[i++]);
874 0 : if (ret)
875 0 : goto out;
876 0 : str_start = str + 1;
877 0 : } else if(*str == '@') {
878 0 : ret = dequote_strndup(context, str_start, str - str_start,
879 0 : &p.principalName.name_string.val[i++]);
880 0 : if (ret == 0)
881 0 : ret = dequote_strndup(context, str + 1, strlen(str + 1), &p.realm);
882 0 : if (ret)
883 0 : goto out;
884 0 : break;
885 : }
886 : }
887 : }
888 :
889 0 : ASN1_MALLOC_ENCODE(KRB5PrincipalName, os->data, os->length, &p, &size, ret);
890 0 : if (ret) {
891 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
892 0 : goto out;
893 : }
894 0 : if (size != os->length)
895 0 : _hx509_abort("internal ASN.1 encoder error");
896 :
897 0 : out:
898 0 : free_KRB5PrincipalName(&p);
899 0 : return ret;
900 : }
901 :
902 : static int
903 0 : add_ia5string_san(hx509_context context,
904 : hx509_ca_tbs tbs,
905 : const heim_oid *oid,
906 : const char *string)
907 : {
908 0 : SRVName ustring;
909 0 : heim_octet_string os;
910 0 : size_t size;
911 0 : int ret;
912 :
913 0 : ustring.data = (void *)(uintptr_t)string;
914 0 : ustring.length = strlen(string);
915 :
916 0 : os.length = 0;
917 0 : os.data = NULL;
918 :
919 0 : ASN1_MALLOC_ENCODE(SRVName, os.data, os.length, &ustring, &size, ret);
920 0 : if (ret) {
921 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
922 0 : return ret;
923 : }
924 0 : if (size != os.length)
925 0 : _hx509_abort("internal ASN.1 encoder error");
926 :
927 0 : ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os);
928 0 : free(os.data);
929 0 : return ret;
930 : }
931 :
932 : /**
933 : * Add DNSSRV Subject Alternative Name to the to-be-signed certificate object.
934 : *
935 : * @param context A hx509 context.
936 : * @param tbs object to be signed.
937 : * @param dnssrv An ASCII string of the for _Service.Name.
938 : *
939 : * @return An hx509 error code, see hx509_get_error_string().
940 : *
941 : * @ingroup hx509_ca
942 : */
943 :
944 : HX509_LIB_FUNCTION int HX509_LIB_CALL
945 0 : hx509_ca_tbs_add_san_dnssrv(hx509_context context,
946 : hx509_ca_tbs tbs,
947 : const char *dnssrv)
948 : {
949 0 : size_t i, len;
950 :
951 : /* Minimal DNSSRV input validation */
952 0 : if (dnssrv == 0 || dnssrv[0] != '_') {
953 0 : hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
954 0 : return EINVAL;
955 : }
956 0 : for (i = 1, len = strlen(dnssrv); i < len; i++) {
957 0 : if (dnssrv[i] == '.' && dnssrv[i + 1] != '\0')
958 0 : break;
959 : }
960 0 : if (i == len) {
961 0 : hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
962 0 : return EINVAL;
963 : }
964 :
965 0 : return add_ia5string_san(context, tbs,
966 : &asn1_oid_id_pkix_on_dnsSRV, dnssrv);
967 : }
968 :
969 : /**
970 : * Add Kerberos Subject Alternative Name to the to-be-signed
971 : * certificate object. The principal string is a UTF8 string.
972 : *
973 : * @param context A hx509 context.
974 : * @param tbs object to be signed.
975 : * @param principal Kerberos principal to add to the certificate.
976 : *
977 : * @return An hx509 error code, see hx509_get_error_string().
978 : *
979 : * @ingroup hx509_ca
980 : */
981 :
982 : HX509_LIB_FUNCTION int HX509_LIB_CALL
983 0 : hx509_ca_tbs_add_san_pkinit(hx509_context context,
984 : hx509_ca_tbs tbs,
985 : const char *principal)
986 : {
987 0 : heim_octet_string os;
988 0 : int ret;
989 :
990 0 : ret = _hx509_make_pkinit_san(context, principal, &os);
991 0 : if (ret == 0)
992 0 : ret = hx509_ca_tbs_add_san_otherName(context, tbs,
993 : &asn1_oid_id_pkinit_san, &os);
994 0 : free(os.data);
995 0 : return ret;
996 : }
997 :
998 : /*
999 : *
1000 : */
1001 :
1002 : static int
1003 0 : add_utf8_san(hx509_context context,
1004 : hx509_ca_tbs tbs,
1005 : const heim_oid *oid,
1006 : const char *string)
1007 : {
1008 0 : const PKIXXmppAddr ustring = (const PKIXXmppAddr)(uintptr_t)string;
1009 0 : heim_octet_string os;
1010 0 : size_t size;
1011 0 : int ret;
1012 :
1013 0 : os.length = 0;
1014 0 : os.data = NULL;
1015 :
1016 0 : ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
1017 0 : if (ret) {
1018 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1019 0 : return ret;
1020 : }
1021 0 : if (size != os.length)
1022 0 : _hx509_abort("internal ASN.1 encoder error");
1023 :
1024 0 : ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os);
1025 0 : free(os.data);
1026 0 : return ret;
1027 : }
1028 :
1029 : /**
1030 : * Add Microsoft UPN Subject Alternative Name to the to-be-signed
1031 : * certificate object. The principal string is a UTF8 string.
1032 : *
1033 : * @param context A hx509 context.
1034 : * @param tbs object to be signed.
1035 : * @param principal Microsoft UPN string.
1036 : *
1037 : * @return An hx509 error code, see hx509_get_error_string().
1038 : *
1039 : * @ingroup hx509_ca
1040 : */
1041 :
1042 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1043 0 : hx509_ca_tbs_add_san_ms_upn(hx509_context context,
1044 : hx509_ca_tbs tbs,
1045 : const char *principal)
1046 : {
1047 0 : return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
1048 : }
1049 :
1050 : /**
1051 : * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
1052 : * certificate object. The jid is an UTF8 string.
1053 : *
1054 : * @param context A hx509 context.
1055 : * @param tbs object to be signed.
1056 : * @param jid string of an a jabber id in UTF8.
1057 : *
1058 : * @return An hx509 error code, see hx509_get_error_string().
1059 : *
1060 : * @ingroup hx509_ca
1061 : */
1062 :
1063 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1064 0 : hx509_ca_tbs_add_san_jid(hx509_context context,
1065 : hx509_ca_tbs tbs,
1066 : const char *jid)
1067 : {
1068 0 : return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
1069 : }
1070 :
1071 :
1072 : /**
1073 : * Add a Subject Alternative Name hostname to to-be-signed certificate
1074 : * object. A domain match starts with ., an exact match does not.
1075 : *
1076 : * Example of a an domain match: .domain.se matches the hostname
1077 : * host.domain.se.
1078 : *
1079 : * @param context A hx509 context.
1080 : * @param tbs object to be signed.
1081 : * @param dnsname a hostame.
1082 : *
1083 : * @return An hx509 error code, see hx509_get_error_string().
1084 : *
1085 : * @ingroup hx509_ca
1086 : */
1087 :
1088 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1089 0 : hx509_ca_tbs_add_san_hostname(hx509_context context,
1090 : hx509_ca_tbs tbs,
1091 : const char *dnsname)
1092 : {
1093 0 : GeneralName gn;
1094 :
1095 0 : memset(&gn, 0, sizeof(gn));
1096 0 : gn.element = choice_GeneralName_dNSName;
1097 0 : gn.u.dNSName.data = rk_UNCONST(dnsname);
1098 0 : gn.u.dNSName.length = strlen(dnsname);
1099 :
1100 0 : return add_GeneralNames(&tbs->san, &gn);
1101 : }
1102 :
1103 : /**
1104 : * Add a Subject Alternative Name rfc822 (email address) to
1105 : * to-be-signed certificate object.
1106 : *
1107 : * @param context A hx509 context.
1108 : * @param tbs object to be signed.
1109 : * @param rfc822Name a string to a email address.
1110 : *
1111 : * @return An hx509 error code, see hx509_get_error_string().
1112 : *
1113 : * @ingroup hx509_ca
1114 : */
1115 :
1116 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1117 0 : hx509_ca_tbs_add_san_rfc822name(hx509_context context,
1118 : hx509_ca_tbs tbs,
1119 : const char *rfc822Name)
1120 : {
1121 0 : GeneralName gn;
1122 :
1123 0 : memset(&gn, 0, sizeof(gn));
1124 0 : gn.element = choice_GeneralName_rfc822Name;
1125 0 : gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
1126 0 : gn.u.rfc822Name.length = strlen(rfc822Name);
1127 :
1128 0 : return add_GeneralNames(&tbs->san, &gn);
1129 : }
1130 :
1131 : /*
1132 : * PermanentIdentifier is one SAN for naming devices with TPMs after their
1133 : * endorsement keys or EK certificates. See TPM 2.0 Keys for Device Identity
1134 : * and Attestation, Version 1.00, Revision 2, 9/17/2020 (DRAFT).
1135 : *
1136 : * The text on the form of permanent identifiers for TPM endorsement keys sans
1137 : * certificates is clearly problematic, saying: "When the TPM does not have an
1138 : * EK certificate, the identifierValue is a digest of a concatenation of the
1139 : * UTF8 string “EkPubkey” (terminating NULL not included) with the binary EK
1140 : * public key", but since arbitrary binary is not necessarily valid UTF-8...
1141 : * and since NULs embedded in UTF-8 might be OK in some contexts but really
1142 : * isn't in C (and Heimdal's ASN.1 compiler does not allow NULs in the
1143 : * middle of strings)... That just cannot be correct. Since elsewhere the TCG
1144 : * specs use the hex encoding of the SHA-256 digest of the DER encoding of
1145 : * public keys, that's what we should support in Heimdal, and maybe send in a
1146 : * comment.
1147 : *
1148 : * Also, even where one should use hex encoding of the SHA-256 digest of the
1149 : * DER encoding of public keys, how should the public keys be represented?
1150 : * Presumably as SPKIs, with all the required parameters and no more.
1151 : */
1152 :
1153 : /**
1154 : * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed
1155 : * certificate object. The permanent identifier form for TPM endorsement key
1156 : * certificates is the hex encoding of the SHA-256 digest of the DER encoding
1157 : * of the certificate. The permanent identifier form for TPM endorsement keys
1158 : * are of the form "EkPubkey<public-key>", where the form of <public-key> is
1159 : * not well specified at this point. It is the caller's responsibility to
1160 : * format the identifierValue.
1161 : *
1162 : * @param context A hx509 context.
1163 : * @param tbs object to be signed.
1164 : * @param str permanent identifier name in the form "[<assigner-oid>]:[<id>]".
1165 : * @param assigner The OID of an assigner.
1166 : *
1167 : * @return An hx509 error code, see hx509_get_error_string().
1168 : *
1169 : * @ingroup hx509_ca
1170 : */
1171 :
1172 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1173 0 : hx509_ca_tbs_add_san_permanentIdentifier_string(hx509_context context,
1174 : hx509_ca_tbs tbs,
1175 : const char *str)
1176 : {
1177 0 : const heim_oid *found = NULL;
1178 0 : heim_oid oid;
1179 0 : const char *oidstr, *id;
1180 0 : char *freeme, *p;
1181 0 : int ret;
1182 :
1183 0 : memset(&oid, 0, sizeof(oid));
1184 0 : if ((freeme = strdup(str)) == NULL)
1185 0 : return hx509_enomem(context);
1186 :
1187 0 : oidstr = freeme;
1188 0 : p = strchr(freeme, ':');
1189 0 : if (!p) {
1190 0 : hx509_set_error_string(context, 0, EINVAL,
1191 : "Invalid PermanentIdentifier string (should be \"[<oid>]:[<id>]\")");
1192 0 : free(freeme);
1193 0 : return EINVAL;
1194 : }
1195 0 : if (p) {
1196 0 : *(p++) = '\0';
1197 0 : id = p;
1198 : }
1199 0 : if (oidstr[0] != '\0') {
1200 0 : ret = der_find_heim_oid_by_name(oidstr, &found);
1201 0 : if (ret) {
1202 0 : ret = der_parse_heim_oid(oidstr, " .", &oid);
1203 0 : if (ret == 0)
1204 0 : found = &oid;
1205 : }
1206 : }
1207 0 : ret = hx509_ca_tbs_add_san_permanentIdentifier(context, tbs, id, found);
1208 0 : if (found == &oid)
1209 0 : der_free_oid(&oid);
1210 0 : free(freeme);
1211 0 : return ret;
1212 : }
1213 :
1214 : /**
1215 : * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed
1216 : * certificate object. The permanent identifier form for TPM endorsement key
1217 : * certificates is the hex encoding of the SHA-256 digest of the DER encoding
1218 : * of the certificate. The permanent identifier form for TPM endorsement keys
1219 : * are of the form "EkPubkey<public-key>", where the form of <public-key> is
1220 : * not well specified at this point. It is the caller's responsibility to
1221 : * format the identifierValue.
1222 : *
1223 : * @param context A hx509 context.
1224 : * @param tbs object to be signed.
1225 : * @param identifierValue The permanent identifier name.
1226 : * @param assigner The OID of an assigner.
1227 : *
1228 : * @return An hx509 error code, see hx509_get_error_string().
1229 : *
1230 : * @ingroup hx509_ca
1231 : */
1232 :
1233 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1234 0 : hx509_ca_tbs_add_san_permanentIdentifier(hx509_context context,
1235 : hx509_ca_tbs tbs,
1236 : const char *identifierValue,
1237 : const heim_oid *assigner)
1238 : {
1239 0 : PermanentIdentifier pi;
1240 0 : heim_utf8_string s = (void *)(uintptr_t)identifierValue;
1241 0 : heim_octet_string os;
1242 0 : size_t size;
1243 0 : int ret;
1244 :
1245 0 : pi.identifierValue = &s;
1246 0 : pi.assigner = (heim_oid*)(uintptr_t)assigner;
1247 0 : os.length = 0;
1248 0 : os.data = NULL;
1249 :
1250 0 : ASN1_MALLOC_ENCODE(PermanentIdentifier, os.data, os.length, &pi, &size,
1251 : ret);
1252 0 : if (ret) {
1253 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1254 0 : return ret;
1255 : }
1256 0 : if (size != os.length)
1257 0 : _hx509_abort("internal ASN.1 encoder error");
1258 :
1259 0 : ret = hx509_ca_tbs_add_san_otherName(context, tbs,
1260 : &asn1_oid_id_pkix_on_permanentIdentifier,
1261 : &os);
1262 0 : free(os.data);
1263 0 : return ret;
1264 : }
1265 :
1266 : /**
1267 : * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed
1268 : * certificate object.
1269 : *
1270 : * @param context A hx509 context.
1271 : * @param tbs object to be signed.
1272 : * @param str a string of the form "<oid>:<serial>".
1273 : * @param hwserial The serial number.
1274 : *
1275 : * @return An hx509 error code, see hx509_get_error_string().
1276 : *
1277 : * @ingroup hx509_ca
1278 : */
1279 :
1280 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1281 0 : hx509_ca_tbs_add_san_hardwareModuleName_string(hx509_context context,
1282 : hx509_ca_tbs tbs,
1283 : const char *str)
1284 : {
1285 0 : const heim_oid *found = NULL;
1286 0 : heim_oid oid;
1287 0 : const char *oidstr, *sno;
1288 0 : char *freeme, *p;
1289 0 : int ret;
1290 :
1291 0 : memset(&oid, 0, sizeof(oid));
1292 0 : if ((freeme = strdup(str)) == NULL)
1293 0 : return hx509_enomem(context);
1294 :
1295 0 : oidstr = freeme;
1296 0 : p = strchr(freeme, ':');
1297 0 : if (!p) {
1298 0 : hx509_set_error_string(context, 0, EINVAL,
1299 : "Invalid HardwareModuleName string (should be "
1300 : "\"<oid>:<serial>\")");
1301 0 : free(freeme);
1302 0 : return EINVAL;
1303 : }
1304 0 : if (p) {
1305 0 : *(p++) = '\0';
1306 0 : sno = p;
1307 : }
1308 0 : if (oidstr[0] == '\0') {
1309 0 : found = &asn1_oid_tcg_tpm20;
1310 : } else {
1311 0 : ret = der_find_heim_oid_by_name(oidstr, &found);
1312 0 : if (ret) {
1313 0 : ret = der_parse_heim_oid(oidstr, " .", &oid);
1314 0 : if (ret == 0)
1315 0 : found = &oid;
1316 : }
1317 : }
1318 0 : if (!found) {
1319 0 : hx509_set_error_string(context, 0, EINVAL,
1320 : "Could not resolve or parse OID \"%s\"",
1321 : oidstr);
1322 0 : free(freeme);
1323 0 : return EINVAL;
1324 : }
1325 0 : ret = hx509_ca_tbs_add_san_hardwareModuleName(context, tbs, found, sno);
1326 0 : if (found == &oid)
1327 0 : der_free_oid(&oid);
1328 0 : free(freeme);
1329 0 : return ret;
1330 : }
1331 :
1332 : /**
1333 : * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed
1334 : * certificate object.
1335 : *
1336 : * @param context A hx509 context.
1337 : * @param tbs object to be signed.
1338 : * @param hwtype The hardwar module type (e.g., `&asn1_oid_tcg_tpm20').
1339 : * @param hwserial The serial number.
1340 : *
1341 : * @return An hx509 error code, see hx509_get_error_string().
1342 : *
1343 : * @ingroup hx509_ca
1344 : */
1345 :
1346 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1347 0 : hx509_ca_tbs_add_san_hardwareModuleName(hx509_context context,
1348 : hx509_ca_tbs tbs,
1349 : const heim_oid *hwtype,
1350 : const char *hwserial)
1351 : {
1352 0 : HardwareModuleName hm;
1353 0 : heim_octet_string os;
1354 0 : size_t size;
1355 0 : int ret;
1356 :
1357 0 : hm.hwType = *hwtype;
1358 0 : hm.hwSerialNum.data = (void *)(uintptr_t)hwserial;
1359 0 : hm.hwSerialNum.length = strlen(hwserial);
1360 0 : os.length = 0;
1361 0 : os.data = NULL;
1362 :
1363 0 : ASN1_MALLOC_ENCODE(HardwareModuleName, os.data, os.length, &hm, &size,
1364 : ret);
1365 0 : if (ret) {
1366 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1367 0 : return ret;
1368 : }
1369 0 : if (size != os.length)
1370 0 : _hx509_abort("internal ASN.1 encoder error");
1371 :
1372 0 : ret = hx509_ca_tbs_add_san_otherName(context, tbs,
1373 : &asn1_oid_id_on_hardwareModuleName,
1374 : &os);
1375 0 : free(os.data);
1376 0 : return ret;
1377 : }
1378 :
1379 : /**
1380 : * Add a Subject Alternative Name of the given type to the
1381 : * to-be-signed certificate object.
1382 : *
1383 : * @param context A hx509 context.
1384 : * @param tbs object to be signed.
1385 : * @param rfc822Name a string to a email address.
1386 : *
1387 : * @return An hx509 error code, see hx509_get_error_string().
1388 : *
1389 : * @ingroup hx509_ca
1390 : */
1391 :
1392 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1393 0 : hx509_ca_tbs_add_san(hx509_context context,
1394 : hx509_ca_tbs tbs,
1395 : hx509_san_type type,
1396 : const char *s)
1397 : {
1398 0 : switch (type) {
1399 0 : case HX509_SAN_TYPE_EMAIL:
1400 0 : return hx509_ca_tbs_add_san_rfc822name(context, tbs, s);
1401 0 : case HX509_SAN_TYPE_DNSNAME:
1402 0 : return hx509_ca_tbs_add_san_hostname(context, tbs, s);
1403 0 : case HX509_SAN_TYPE_DN:
1404 0 : return ENOTSUP;
1405 0 : case HX509_SAN_TYPE_REGISTERED_ID:
1406 0 : return ENOTSUP;
1407 0 : case HX509_SAN_TYPE_XMPP:
1408 0 : return hx509_ca_tbs_add_san_jid(context, tbs, s);
1409 0 : case HX509_SAN_TYPE_PKINIT:
1410 0 : return hx509_ca_tbs_add_san_pkinit(context, tbs, s);
1411 0 : case HX509_SAN_TYPE_MS_UPN:
1412 0 : return hx509_ca_tbs_add_san_ms_upn(context, tbs, s);
1413 0 : default:
1414 0 : return ENOTSUP;
1415 : }
1416 : }
1417 :
1418 : /**
1419 : * Set the subject name of a to-be-signed certificate object.
1420 : *
1421 : * @param context A hx509 context.
1422 : * @param tbs object to be signed.
1423 : * @param subject the name to set a subject.
1424 : *
1425 : * @return An hx509 error code, see hx509_get_error_string().
1426 : *
1427 : * @ingroup hx509_ca
1428 : */
1429 :
1430 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1431 0 : hx509_ca_tbs_set_subject(hx509_context context,
1432 : hx509_ca_tbs tbs,
1433 : hx509_name subject)
1434 : {
1435 0 : if (tbs->subject)
1436 0 : hx509_name_free(&tbs->subject);
1437 0 : return hx509_name_copy(context, subject, &tbs->subject);
1438 : }
1439 :
1440 : /**
1441 : * Set the issuerUniqueID and subjectUniqueID
1442 : *
1443 : * These are only supposed to be used considered with version 2
1444 : * certificates, replaced by the two extensions SubjectKeyIdentifier
1445 : * and IssuerKeyIdentifier. This function is to allow application
1446 : * using legacy protocol to issue them.
1447 : *
1448 : * @param context A hx509 context.
1449 : * @param tbs object to be signed.
1450 : * @param issuerUniqueID to be set
1451 : * @param subjectUniqueID to be set
1452 : *
1453 : * @return An hx509 error code, see hx509_get_error_string().
1454 : *
1455 : * @ingroup hx509_ca
1456 : */
1457 :
1458 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1459 0 : hx509_ca_tbs_set_unique(hx509_context context,
1460 : hx509_ca_tbs tbs,
1461 : const heim_bit_string *subjectUniqueID,
1462 : const heim_bit_string *issuerUniqueID)
1463 : {
1464 0 : int ret;
1465 :
1466 0 : der_free_bit_string(&tbs->subjectUniqueID);
1467 0 : der_free_bit_string(&tbs->issuerUniqueID);
1468 :
1469 0 : if (subjectUniqueID) {
1470 0 : ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
1471 0 : if (ret)
1472 0 : return ret;
1473 : }
1474 :
1475 0 : if (issuerUniqueID) {
1476 0 : ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
1477 0 : if (ret)
1478 0 : return ret;
1479 : }
1480 :
1481 0 : return 0;
1482 : }
1483 :
1484 : /**
1485 : * Expand the the subject name in the to-be-signed certificate object
1486 : * using hx509_name_expand().
1487 : *
1488 : * @param context A hx509 context.
1489 : * @param tbs object to be signed.
1490 : * @param env environment variable to expand variables in the subject
1491 : * name, see hx509_env_init().
1492 : *
1493 : * @return An hx509 error code, see hx509_get_error_string().
1494 : *
1495 : * @ingroup hx509_ca
1496 : */
1497 :
1498 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1499 0 : hx509_ca_tbs_subject_expand(hx509_context context,
1500 : hx509_ca_tbs tbs,
1501 : hx509_env env)
1502 : {
1503 0 : return hx509_name_expand(context, tbs->subject, env);
1504 : }
1505 :
1506 : /**
1507 : * Get the name of a to-be-signed certificate object.
1508 : *
1509 : * @param context A hx509 context.
1510 : * @param tbs object to be signed.
1511 : *
1512 : * @return An hx509 name.
1513 : *
1514 : * @ingroup hx509_ca
1515 : */
1516 :
1517 : HX509_LIB_FUNCTION hx509_name HX509_LIB_CALL
1518 0 : hx509_ca_tbs_get_name(hx509_ca_tbs tbs)
1519 : {
1520 0 : return tbs->subject;
1521 : }
1522 :
1523 : /**
1524 : * Set signature algorithm on the to be signed certificate
1525 : *
1526 : * @param context A hx509 context.
1527 : * @param tbs object to be signed.
1528 : * @param sigalg signature algorithm to use
1529 : *
1530 : * @return An hx509 error code, see hx509_get_error_string().
1531 : *
1532 : * @ingroup hx509_ca
1533 : */
1534 :
1535 : HX509_LIB_FUNCTION int HX509_LIB_CALL
1536 0 : hx509_ca_tbs_set_signature_algorithm(hx509_context context,
1537 : hx509_ca_tbs tbs,
1538 : const AlgorithmIdentifier *sigalg)
1539 : {
1540 0 : int ret;
1541 :
1542 0 : tbs->sigalg = calloc(1, sizeof(*tbs->sigalg));
1543 0 : if (tbs->sigalg == NULL) {
1544 0 : hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
1545 0 : return ENOMEM;
1546 : }
1547 0 : ret = copy_AlgorithmIdentifier(sigalg, tbs->sigalg);
1548 0 : if (ret) {
1549 0 : free(tbs->sigalg);
1550 0 : tbs->sigalg = NULL;
1551 0 : return ret;
1552 : }
1553 0 : return 0;
1554 : }
1555 :
1556 : /*
1557 : *
1558 : */
1559 :
1560 : static int
1561 0 : add_extension(hx509_context context,
1562 : TBSCertificate *tbsc,
1563 : int critical_flag,
1564 : const heim_oid *oid,
1565 : const heim_octet_string *data)
1566 : {
1567 0 : Extension ext;
1568 0 : int ret;
1569 :
1570 0 : memset(&ext, 0, sizeof(ext));
1571 :
1572 0 : ext.critical = critical_flag;
1573 0 : ret = der_copy_oid(oid, &ext.extnID);
1574 0 : if (ret) {
1575 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1576 0 : goto out;
1577 : }
1578 0 : ret = der_copy_octet_string(data, &ext.extnValue);
1579 0 : if (ret) {
1580 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1581 0 : goto out;
1582 : }
1583 0 : ret = add_Extensions(tbsc->extensions, &ext);
1584 0 : if (ret) {
1585 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1586 0 : goto out;
1587 : }
1588 0 : out:
1589 0 : free_Extension(&ext);
1590 0 : return ret;
1591 : }
1592 :
1593 : static int
1594 0 : build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
1595 : {
1596 0 : char *tstr;
1597 0 : time_t t;
1598 0 : int ret;
1599 :
1600 0 : ret = copy_Name(issuer, subject);
1601 0 : if (ret) {
1602 0 : hx509_set_error_string(context, 0, ret,
1603 : "Failed to copy subject name");
1604 0 : return ret;
1605 : }
1606 :
1607 0 : t = time(NULL);
1608 0 : ret = asprintf(&tstr, "ts-%lu", (unsigned long)t);
1609 0 : if (ret == -1 || tstr == NULL) {
1610 0 : hx509_set_error_string(context, 0, ENOMEM,
1611 : "Failed to copy subject name");
1612 0 : return ENOMEM;
1613 : }
1614 : /* prefix with CN=<ts>,...*/
1615 0 : ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
1616 0 : free(tstr);
1617 0 : if (ret)
1618 0 : free_Name(subject);
1619 0 : return ret;
1620 : }
1621 :
1622 : static int
1623 0 : ca_sign(hx509_context context,
1624 : hx509_ca_tbs tbs,
1625 : hx509_private_key signer,
1626 : const AuthorityKeyIdentifier *ai,
1627 : const Name *issuername,
1628 : hx509_cert *certificate)
1629 : {
1630 0 : heim_error_t error = NULL;
1631 0 : heim_octet_string data;
1632 0 : Certificate c;
1633 0 : TBSCertificate *tbsc;
1634 0 : size_t size;
1635 0 : int ret;
1636 0 : const AlgorithmIdentifier *sigalg;
1637 0 : time_t notBefore;
1638 0 : time_t notAfter;
1639 :
1640 0 : sigalg = tbs->sigalg;
1641 0 : if (sigalg == NULL)
1642 0 : sigalg = _hx509_crypto_default_sig_alg;
1643 :
1644 0 : memset(&c, 0, sizeof(c));
1645 :
1646 : /*
1647 : * Default values are: Valid since 24h ago, valid one year into
1648 : * the future, KeyUsage digitalSignature and keyEncipherment set,
1649 : * and keyCertSign for CA certificates.
1650 : */
1651 0 : notBefore = tbs->notBefore;
1652 0 : if (notBefore == 0)
1653 0 : notBefore = time(NULL) - 3600 * 24;
1654 0 : notAfter = tbs->notAfter;
1655 0 : if (notAfter == 0)
1656 0 : notAfter = time(NULL) + 3600 * 24 * 365;
1657 :
1658 0 : if (tbs->flags.ca) {
1659 0 : tbs->ku.keyCertSign = 1;
1660 0 : tbs->ku.cRLSign = 1;
1661 0 : } else if (KeyUsage2int(tbs->ku) == 0) {
1662 0 : tbs->ku.digitalSignature = 1;
1663 0 : tbs->ku.keyEncipherment = 1;
1664 : }
1665 :
1666 : /*
1667 : *
1668 : */
1669 :
1670 0 : tbsc = &c.tbsCertificate;
1671 :
1672 : /* Default subject Name to empty */
1673 0 : if (tbs->subject == NULL &&
1674 0 : (ret = hx509_empty_name(context, &tbs->subject)))
1675 0 : return ret;
1676 :
1677 : /* Sanity checks */
1678 0 : if (tbs->flags.key == 0) {
1679 0 : ret = EINVAL;
1680 0 : hx509_set_error_string(context, 0, ret, "No public key set");
1681 0 : return ret;
1682 : }
1683 : /*
1684 : * Don't put restrictions on proxy certificate's subject name, it
1685 : * will be generated below.
1686 : */
1687 0 : if (!tbs->flags.proxy) {
1688 0 : if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1689 0 : hx509_set_error_string(context, 0, EINVAL,
1690 : "Empty subject and no SubjectAltNames");
1691 0 : return EINVAL;
1692 : }
1693 : }
1694 0 : if (tbs->flags.ca && tbs->flags.proxy) {
1695 0 : hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1696 : "at the same time");
1697 0 : return EINVAL;
1698 : }
1699 0 : if (tbs->flags.proxy) {
1700 0 : if (tbs->san.len > 0) {
1701 0 : hx509_set_error_string(context, 0, EINVAL,
1702 : "Proxy certificate is not allowed "
1703 : "to have SubjectAltNames");
1704 0 : return EINVAL;
1705 : }
1706 : }
1707 :
1708 : /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1709 0 : tbsc->version = calloc(1, sizeof(*tbsc->version));
1710 0 : if (tbsc->version == NULL) {
1711 0 : ret = ENOMEM;
1712 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1713 0 : goto out;
1714 : }
1715 0 : *tbsc->version = rfc3280_version_3;
1716 : /* serialNumber CertificateSerialNumber, */
1717 0 : if (tbs->flags.serial) {
1718 0 : ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1719 0 : if (ret) {
1720 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1721 0 : goto out;
1722 : }
1723 : } else {
1724 : /*
1725 : * If no explicit serial number is specified, 20 random bytes should be
1726 : * sufficiently collision resistant. Since the serial number must be a
1727 : * positive integer, ensure minimal ASN.1 DER form by forcing the high
1728 : * bit off and the next bit on (thus avoiding an all zero first octet).
1729 : */
1730 0 : tbsc->serialNumber.length = 20;
1731 0 : tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1732 0 : if (tbsc->serialNumber.data == NULL){
1733 0 : ret = ENOMEM;
1734 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1735 0 : goto out;
1736 : }
1737 0 : ret = RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1738 0 : if (ret != 1) {
1739 0 : ret = HX509_CRYPTO_INTERNAL_ERROR;
1740 0 : hx509_set_error_string(context, 0, ret, "Failed to generate random bytes");
1741 0 : goto out;
1742 : }
1743 0 : ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1744 0 : ((unsigned char *)tbsc->serialNumber.data)[0] |= 0x40;
1745 : }
1746 : /* signature AlgorithmIdentifier, */
1747 0 : ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1748 0 : if (ret) {
1749 0 : hx509_set_error_string(context, 0, ret, "Failed to copy signature alg");
1750 0 : goto out;
1751 : }
1752 : /* issuer Name, */
1753 0 : if (issuername)
1754 0 : ret = copy_Name(issuername, &tbsc->issuer);
1755 : else
1756 0 : ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1757 0 : if (ret) {
1758 0 : hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1759 0 : goto out;
1760 : }
1761 : /* validity Validity, */
1762 : {
1763 : /*
1764 : * From RFC 5280, section 4.1.2.5:
1765 : *
1766 : * CAs conforming to this profile MUST always encode certificate
1767 : * validity dates through the year 2049 as UTCTime; certificate validity
1768 : * dates in 2050 or later MUST be encoded as GeneralizedTime.
1769 : * Conforming applications MUST be able to process validity dates that
1770 : * are encoded in either UTCTime or GeneralizedTime.
1771 : *
1772 : * 2524608000 is seconds since the epoch for 2050-01-01T00:00:00Z.
1773 : *
1774 : * Both, ...u.generalTime and ...u..utcTime are time_t.
1775 : */
1776 0 : if (notBefore < 1 || (int64_t)notBefore < 2524608000)
1777 0 : tbsc->validity.notBefore.element = choice_Time_utcTime;
1778 : else
1779 0 : tbsc->validity.notBefore.element = choice_Time_generalTime;
1780 0 : tbsc->validity.notBefore.u.generalTime = notBefore;
1781 :
1782 0 : if (notAfter < 1 || (int64_t)notAfter < 2524608000)
1783 0 : tbsc->validity.notAfter.element = choice_Time_utcTime;
1784 : else
1785 0 : tbsc->validity.notAfter.element = choice_Time_generalTime;
1786 0 : tbsc->validity.notAfter.u.generalTime = notAfter;
1787 : }
1788 : /* subject Name, */
1789 0 : if (tbs->flags.proxy) {
1790 0 : ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1791 0 : if (ret)
1792 0 : goto out;
1793 : } else {
1794 0 : ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1795 0 : if (ret) {
1796 0 : hx509_set_error_string(context, 0, ret,
1797 : "Failed to copy subject name");
1798 0 : goto out;
1799 : }
1800 : }
1801 : /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1802 0 : ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1803 0 : if (ret) {
1804 0 : hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1805 0 : goto out;
1806 : }
1807 : /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1808 0 : if (tbs->issuerUniqueID.length) {
1809 0 : tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1810 0 : if (tbsc->issuerUniqueID == NULL) {
1811 0 : ret = ENOMEM;
1812 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1813 0 : goto out;
1814 : }
1815 0 : ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1816 0 : if (ret) {
1817 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1818 0 : goto out;
1819 : }
1820 : }
1821 : /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1822 0 : if (tbs->subjectUniqueID.length) {
1823 0 : tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1824 0 : if (tbsc->subjectUniqueID == NULL) {
1825 0 : ret = ENOMEM;
1826 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1827 0 : goto out;
1828 : }
1829 :
1830 0 : ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1831 0 : if (ret) {
1832 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1833 0 : goto out;
1834 : }
1835 : }
1836 :
1837 : /* extensions [3] EXPLICIT Extensions OPTIONAL */
1838 0 : tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1839 0 : if (tbsc->extensions == NULL) {
1840 0 : ret = ENOMEM;
1841 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1842 0 : goto out;
1843 : }
1844 :
1845 : /* Add the text BMP string Domaincontroller to the cert */
1846 0 : if (tbs->flags.domaincontroller) {
1847 0 : data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1848 : "\x00\x61\x00\x69\x00\x6e\x00\x43"
1849 : "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1850 : "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1851 : "\x00\x72");
1852 0 : data.length = 34;
1853 :
1854 0 : ret = add_extension(context, tbsc, 0,
1855 : &asn1_oid_id_ms_cert_enroll_domaincontroller,
1856 : &data);
1857 0 : if (ret)
1858 0 : goto out;
1859 : }
1860 :
1861 : /* Add KeyUsage */
1862 0 : if (KeyUsage2int(tbs->ku) > 0) {
1863 0 : ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length,
1864 : &tbs->ku, &size, ret);
1865 0 : if (ret) {
1866 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1867 0 : goto out;
1868 : }
1869 0 : if (size != data.length)
1870 0 : _hx509_abort("internal ASN.1 encoder error");
1871 0 : ret = add_extension(context, tbsc, 1,
1872 : &asn1_oid_id_x509_ce_keyUsage, &data);
1873 0 : free(data.data);
1874 0 : if (ret)
1875 0 : goto out;
1876 : }
1877 :
1878 : /* Add ExtendedKeyUsage */
1879 0 : if (tbs->eku.len > 0) {
1880 0 : ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1881 : &tbs->eku, &size, ret);
1882 0 : if (ret) {
1883 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1884 0 : goto out;
1885 : }
1886 0 : if (size != data.length)
1887 0 : _hx509_abort("internal ASN.1 encoder error");
1888 0 : ret = add_extension(context, tbsc, 1,
1889 : &asn1_oid_id_x509_ce_extKeyUsage, &data);
1890 0 : free(data.data);
1891 0 : if (ret)
1892 0 : goto out;
1893 : }
1894 :
1895 : /* Add Subject Alternative Name */
1896 0 : if (tbs->san.len > 0) {
1897 0 : ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1898 : &tbs->san, &size, ret);
1899 0 : if (ret) {
1900 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1901 0 : goto out;
1902 : }
1903 0 : if (size != data.length)
1904 0 : _hx509_abort("internal ASN.1 encoder error");
1905 :
1906 : /* The SAN extension is critical if the subject Name is empty */
1907 0 : ret = add_extension(context, tbsc, hx509_name_is_null_p(tbs->subject),
1908 : &asn1_oid_id_x509_ce_subjectAltName, &data);
1909 0 : free(data.data);
1910 0 : if (ret)
1911 0 : goto out;
1912 : }
1913 :
1914 : /* Add Authority Key Identifier */
1915 0 : if (ai) {
1916 0 : ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1917 : ai, &size, ret);
1918 0 : if (ret) {
1919 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1920 0 : goto out;
1921 : }
1922 0 : if (size != data.length)
1923 0 : _hx509_abort("internal ASN.1 encoder error");
1924 0 : ret = add_extension(context, tbsc, 0,
1925 : &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1926 : &data);
1927 0 : free(data.data);
1928 0 : if (ret)
1929 0 : goto out;
1930 : }
1931 :
1932 : /* Add Subject Key Identifier */
1933 : {
1934 0 : SubjectKeyIdentifier si;
1935 0 : unsigned char hash[SHA_DIGEST_LENGTH];
1936 :
1937 : {
1938 0 : EVP_MD_CTX *ctx;
1939 :
1940 0 : ctx = EVP_MD_CTX_create();
1941 0 : EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1942 0 : EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1943 0 : tbs->spki.subjectPublicKey.length / 8);
1944 0 : EVP_DigestFinal_ex(ctx, hash, NULL);
1945 0 : EVP_MD_CTX_destroy(ctx);
1946 : }
1947 :
1948 0 : si.data = hash;
1949 0 : si.length = sizeof(hash);
1950 :
1951 0 : ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1952 : &si, &size, ret);
1953 0 : if (ret) {
1954 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1955 0 : goto out;
1956 : }
1957 0 : if (size != data.length)
1958 0 : _hx509_abort("internal ASN.1 encoder error");
1959 0 : ret = add_extension(context, tbsc, 0,
1960 : &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1961 : &data);
1962 0 : free(data.data);
1963 0 : if (ret)
1964 0 : goto out;
1965 : }
1966 :
1967 : /* Add BasicConstraints */
1968 : {
1969 0 : BasicConstraints bc;
1970 0 : unsigned int path;
1971 :
1972 0 : memset(&bc, 0, sizeof(bc));
1973 :
1974 0 : if (tbs->flags.ca) {
1975 0 : bc.cA = 1;
1976 0 : if (tbs->pathLenConstraint >= 0) {
1977 0 : path = tbs->pathLenConstraint;
1978 0 : bc.pathLenConstraint = &path;
1979 : }
1980 : }
1981 :
1982 0 : ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1983 : &bc, &size, ret);
1984 0 : if (ret) {
1985 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
1986 0 : goto out;
1987 : }
1988 0 : if (size != data.length)
1989 0 : _hx509_abort("internal ASN.1 encoder error");
1990 : /* Critical if this is a CA */
1991 0 : ret = add_extension(context, tbsc, tbs->flags.ca,
1992 : &asn1_oid_id_x509_ce_basicConstraints,
1993 : &data);
1994 0 : free(data.data);
1995 0 : if (ret)
1996 0 : goto out;
1997 : }
1998 :
1999 : /* Add Proxy */
2000 0 : if (tbs->flags.proxy) {
2001 0 : ProxyCertInfo info;
2002 :
2003 0 : memset(&info, 0, sizeof(info));
2004 :
2005 0 : if (tbs->pathLenConstraint >= 0) {
2006 0 : info.pCPathLenConstraint =
2007 0 : malloc(sizeof(*info.pCPathLenConstraint));
2008 0 : if (info.pCPathLenConstraint == NULL) {
2009 0 : ret = ENOMEM;
2010 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2011 0 : goto out;
2012 : }
2013 0 : *info.pCPathLenConstraint = tbs->pathLenConstraint;
2014 : }
2015 :
2016 0 : ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
2017 : &info.proxyPolicy.policyLanguage);
2018 0 : if (ret) {
2019 0 : free_ProxyCertInfo(&info);
2020 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2021 0 : goto out;
2022 : }
2023 :
2024 0 : ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
2025 : &info, &size, ret);
2026 0 : free_ProxyCertInfo(&info);
2027 0 : if (ret) {
2028 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2029 0 : goto out;
2030 : }
2031 0 : if (size != data.length)
2032 0 : _hx509_abort("internal ASN.1 encoder error");
2033 0 : ret = add_extension(context, tbsc, 0,
2034 : &asn1_oid_id_pkix_pe_proxyCertInfo,
2035 : &data);
2036 0 : free(data.data);
2037 0 : if (ret)
2038 0 : goto out;
2039 : }
2040 :
2041 : /* Add CRL distribution point */
2042 0 : if (tbs->crldp.len) {
2043 0 : ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
2044 : &tbs->crldp, &size, ret);
2045 0 : if (ret) {
2046 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2047 0 : goto out;
2048 : }
2049 0 : if (size != data.length)
2050 0 : _hx509_abort("internal ASN.1 encoder error");
2051 0 : ret = add_extension(context, tbsc, FALSE,
2052 : &asn1_oid_id_x509_ce_cRLDistributionPoints,
2053 : &data);
2054 0 : free(data.data);
2055 0 : if (ret)
2056 0 : goto out;
2057 : }
2058 :
2059 : /* Add CertificatePolicies */
2060 0 : if (tbs->cps.len) {
2061 0 : ASN1_MALLOC_ENCODE(CertificatePolicies, data.data, data.length,
2062 : &tbs->cps, &size, ret);
2063 0 : if (ret) {
2064 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2065 0 : goto out;
2066 : }
2067 0 : if (size != data.length)
2068 0 : _hx509_abort("internal ASN.1 encoder error");
2069 0 : ret = add_extension(context, tbsc, FALSE,
2070 : &asn1_oid_id_x509_ce_certificatePolicies, &data);
2071 0 : free(data.data);
2072 0 : if (ret)
2073 0 : goto out;
2074 : }
2075 :
2076 : /* Add PolicyMappings */
2077 0 : if (tbs->cps.len) {
2078 0 : ASN1_MALLOC_ENCODE(PolicyMappings, data.data, data.length,
2079 : &tbs->pms, &size, ret);
2080 0 : if (ret) {
2081 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2082 0 : goto out;
2083 : }
2084 0 : if (size != data.length)
2085 0 : _hx509_abort("internal ASN.1 encoder error");
2086 0 : ret = add_extension(context, tbsc, FALSE,
2087 : &asn1_oid_id_x509_ce_policyMappings, &data);
2088 0 : free(data.data);
2089 0 : if (ret)
2090 0 : goto out;
2091 : }
2092 :
2093 : /* Add Heimdal PKINIT ticket max life extension */
2094 0 : if (tbs->pkinitTicketMaxLife > 0) {
2095 0 : ASN1_MALLOC_ENCODE(HeimPkinitPrincMaxLifeSecs, data.data, data.length,
2096 : &tbs->pkinitTicketMaxLife, &size, ret);
2097 0 : if (ret) {
2098 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2099 0 : goto out;
2100 : }
2101 0 : if (size != data.length)
2102 0 : _hx509_abort("internal ASN.1 encoder error");
2103 0 : ret = add_extension(context, tbsc, FALSE,
2104 : &asn1_oid_id_heim_ce_pkinit_princ_max_life, &data);
2105 0 : free(data.data);
2106 0 : if (ret)
2107 0 : goto out;
2108 : }
2109 :
2110 0 : ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
2111 0 : if (ret) {
2112 0 : hx509_set_error_string(context, 0, ret, "malloc out of memory");
2113 0 : goto out;
2114 : }
2115 0 : if (data.length != size)
2116 0 : _hx509_abort("internal ASN.1 encoder error");
2117 :
2118 0 : ret = _hx509_create_signature_bitstring(context,
2119 : signer,
2120 : sigalg,
2121 : &data,
2122 : &c.signatureAlgorithm,
2123 : &c.signatureValue);
2124 0 : free(data.data);
2125 0 : if (ret)
2126 0 : goto out;
2127 :
2128 0 : *certificate = hx509_cert_init(context, &c, &error);
2129 0 : if (*certificate == NULL) {
2130 0 : ret = heim_error_get_code(error);
2131 0 : heim_release(error);
2132 0 : goto out;
2133 : }
2134 :
2135 0 : free_Certificate(&c);
2136 :
2137 0 : return 0;
2138 :
2139 0 : out:
2140 0 : free_Certificate(&c);
2141 0 : return ret;
2142 : }
2143 :
2144 : static int
2145 0 : get_AuthorityKeyIdentifier(hx509_context context,
2146 : const Certificate *certificate,
2147 : AuthorityKeyIdentifier *ai)
2148 : {
2149 0 : SubjectKeyIdentifier si;
2150 0 : int ret;
2151 :
2152 0 : ret = _hx509_find_extension_subject_key_id(certificate, &si);
2153 0 : if (ret == 0) {
2154 0 : ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
2155 0 : if (ai->keyIdentifier == NULL) {
2156 0 : free_SubjectKeyIdentifier(&si);
2157 0 : ret = ENOMEM;
2158 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2159 0 : goto out;
2160 : }
2161 0 : ret = der_copy_octet_string(&si, ai->keyIdentifier);
2162 0 : free_SubjectKeyIdentifier(&si);
2163 0 : if (ret) {
2164 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2165 0 : goto out;
2166 : }
2167 : } else {
2168 0 : GeneralNames gns;
2169 0 : GeneralName gn;
2170 0 : Name name;
2171 :
2172 0 : memset(&gn, 0, sizeof(gn));
2173 0 : memset(&gns, 0, sizeof(gns));
2174 0 : memset(&name, 0, sizeof(name));
2175 :
2176 0 : ai->authorityCertIssuer =
2177 0 : calloc(1, sizeof(*ai->authorityCertIssuer));
2178 0 : if (ai->authorityCertIssuer == NULL) {
2179 0 : ret = ENOMEM;
2180 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2181 0 : goto out;
2182 : }
2183 0 : ai->authorityCertSerialNumber =
2184 0 : calloc(1, sizeof(*ai->authorityCertSerialNumber));
2185 0 : if (ai->authorityCertSerialNumber == NULL) {
2186 0 : ret = ENOMEM;
2187 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2188 0 : goto out;
2189 : }
2190 :
2191 : /*
2192 : * XXX unbreak when asn1 compiler handle IMPLICIT
2193 : *
2194 : * This is so horrible.
2195 : */
2196 :
2197 0 : ret = copy_Name(&certificate->tbsCertificate.subject, &name);
2198 0 : if (ret) {
2199 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2200 0 : goto out;
2201 : }
2202 :
2203 0 : memset(&gn, 0, sizeof(gn));
2204 0 : gn.element = choice_GeneralName_directoryName;
2205 0 : gn.u.directoryName.element = choice_Name_rdnSequence;
2206 0 : gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
2207 :
2208 0 : ret = add_GeneralNames(&gns, &gn);
2209 0 : if (ret) {
2210 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2211 0 : goto out;
2212 : }
2213 :
2214 0 : ai->authorityCertIssuer->val = gns.val;
2215 0 : ai->authorityCertIssuer->len = gns.len;
2216 :
2217 0 : ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
2218 : ai->authorityCertSerialNumber);
2219 0 : if (ai->authorityCertSerialNumber == NULL) {
2220 0 : ret = ENOMEM;
2221 0 : hx509_set_error_string(context, 0, ret, "Out of memory");
2222 0 : goto out;
2223 : }
2224 : }
2225 0 : out:
2226 0 : if (ret)
2227 0 : free_AuthorityKeyIdentifier(ai);
2228 0 : return ret;
2229 : }
2230 :
2231 :
2232 : /**
2233 : * Sign a to-be-signed certificate object with a issuer certificate.
2234 : *
2235 : * The caller needs to at least have called the following functions on the
2236 : * to-be-signed certificate object:
2237 : * - hx509_ca_tbs_init()
2238 : * - hx509_ca_tbs_set_subject()
2239 : * - hx509_ca_tbs_set_spki()
2240 : *
2241 : * When done the to-be-signed certificate object should be freed with
2242 : * hx509_ca_tbs_free().
2243 : *
2244 : * When creating self-signed certificate use hx509_ca_sign_self() instead.
2245 : *
2246 : * @param context A hx509 context.
2247 : * @param tbs object to be signed.
2248 : * @param signer the CA certificate object to sign with (need private key).
2249 : * @param certificate return cerificate, free with hx509_cert_free().
2250 : *
2251 : * @return An hx509 error code, see hx509_get_error_string().
2252 : *
2253 : * @ingroup hx509_ca
2254 : */
2255 :
2256 : HX509_LIB_FUNCTION int HX509_LIB_CALL
2257 0 : hx509_ca_sign(hx509_context context,
2258 : hx509_ca_tbs tbs,
2259 : hx509_cert signer,
2260 : hx509_cert *certificate)
2261 : {
2262 0 : const Certificate *signer_cert;
2263 0 : AuthorityKeyIdentifier ai;
2264 0 : int ret;
2265 :
2266 0 : memset(&ai, 0, sizeof(ai));
2267 :
2268 0 : signer_cert = _hx509_get_cert(signer);
2269 :
2270 0 : ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
2271 0 : if (ret)
2272 0 : goto out;
2273 :
2274 0 : ret = ca_sign(context,
2275 : tbs,
2276 : _hx509_cert_private_key(signer),
2277 : &ai,
2278 : &signer_cert->tbsCertificate.subject,
2279 : certificate);
2280 :
2281 0 : out:
2282 0 : free_AuthorityKeyIdentifier(&ai);
2283 :
2284 0 : return ret;
2285 : }
2286 :
2287 : /**
2288 : * Work just like hx509_ca_sign() but signs it-self.
2289 : *
2290 : * @param context A hx509 context.
2291 : * @param tbs object to be signed.
2292 : * @param signer private key to sign with.
2293 : * @param certificate return cerificate, free with hx509_cert_free().
2294 : *
2295 : * @return An hx509 error code, see hx509_get_error_string().
2296 : *
2297 : * @ingroup hx509_ca
2298 : */
2299 :
2300 : HX509_LIB_FUNCTION int HX509_LIB_CALL
2301 0 : hx509_ca_sign_self(hx509_context context,
2302 : hx509_ca_tbs tbs,
2303 : hx509_private_key signer,
2304 : hx509_cert *certificate)
2305 : {
2306 0 : return ca_sign(context,
2307 : tbs,
2308 : signer,
2309 : NULL,
2310 : NULL,
2311 : certificate);
2312 : }
2313 :
2314 : /*
2315 : * The following used to be `kdc_issue_certificate()', which was added for
2316 : * kx509 support in the kdc, then adapted for bx509d. It now has no
2317 : * kdc-specific code and very little krb5-specific code, and is named
2318 : * `hx509_ca_issue_certificate()'.
2319 : */
2320 :
2321 : /* From lib/krb5/principal.c */
2322 : #define princ_num_comp(P) ((P)->principalName.name_string.len)
2323 : #define princ_type(P) ((P)->principalName.name_type)
2324 : #define princ_comp(P) ((P)->principalName.name_string.val)
2325 : #define princ_ncomp(P, N) ((P)->principalName.name_string.val[(N)])
2326 : #define princ_realm(P) ((P)->realm)
2327 :
2328 : static const char *
2329 0 : princ_get_comp_string(KRB5PrincipalName *principal, unsigned int component)
2330 : {
2331 0 : if (component >= princ_num_comp(principal))
2332 0 : return NULL;
2333 0 : return princ_ncomp(principal, component);
2334 : }
2335 : /* XXX Add unparse_name() */
2336 :
2337 : typedef enum {
2338 : CERT_NOTSUP = 0,
2339 : CERT_CLIENT = 1,
2340 : CERT_SERVER = 2,
2341 : CERT_MIXED = 3
2342 : } cert_type;
2343 :
2344 : static void
2345 0 : frees(char **s)
2346 : {
2347 0 : free(*s);
2348 0 : *s = NULL;
2349 0 : }
2350 :
2351 : static heim_error_code
2352 0 : count_sans(hx509_request req, size_t *n)
2353 : {
2354 0 : size_t i;
2355 0 : char *s = NULL;
2356 0 : int ret = 0;
2357 :
2358 0 : *n = 0;
2359 0 : for (i = 0; ret == 0; i++) {
2360 0 : hx509_san_type san_type;
2361 :
2362 0 : ret = hx509_request_get_san(req, i, &san_type, &s);
2363 0 : if (ret)
2364 0 : break;
2365 0 : switch (san_type) {
2366 0 : case HX509_SAN_TYPE_DNSNAME:
2367 : case HX509_SAN_TYPE_EMAIL:
2368 : case HX509_SAN_TYPE_XMPP:
2369 : case HX509_SAN_TYPE_PKINIT:
2370 : case HX509_SAN_TYPE_MS_UPN:
2371 0 : (*n)++;
2372 0 : break;
2373 0 : default:
2374 0 : ret = ENOTSUP;
2375 : }
2376 0 : frees(&s);
2377 : }
2378 0 : free(s);
2379 0 : return ret == HX509_NO_ITEM ? 0 : ret;
2380 : }
2381 :
2382 : static int
2383 0 : has_sans(hx509_request req)
2384 : {
2385 0 : hx509_san_type san_type;
2386 0 : char *s = NULL;
2387 0 : int ret = hx509_request_get_san(req, 0, &san_type, &s);
2388 :
2389 0 : frees(&s);
2390 0 : return ret == HX509_NO_ITEM ? 0 : 1;
2391 : }
2392 :
2393 : static cert_type
2394 0 : characterize_cprinc(hx509_context context,
2395 : KRB5PrincipalName *cprinc)
2396 : {
2397 0 : unsigned int ncomp = princ_num_comp(cprinc);
2398 0 : const char *comp1 = princ_get_comp_string(cprinc, 1);
2399 :
2400 0 : switch (ncomp) {
2401 0 : case 1:
2402 0 : return CERT_CLIENT;
2403 0 : case 2:
2404 0 : if (strchr(comp1, '.') == NULL)
2405 0 : return CERT_CLIENT;
2406 0 : return CERT_SERVER;
2407 0 : case 3:
2408 0 : if (strchr(comp1, '.'))
2409 0 : return CERT_SERVER;
2410 0 : return CERT_NOTSUP;
2411 0 : default:
2412 0 : return CERT_NOTSUP;
2413 : }
2414 : }
2415 :
2416 : /* Characterize request as client or server cert req */
2417 : static cert_type
2418 0 : characterize(hx509_context context,
2419 : KRB5PrincipalName *cprinc,
2420 : hx509_request req)
2421 : {
2422 0 : heim_error_code ret = 0;
2423 0 : cert_type res = CERT_NOTSUP;
2424 0 : size_t i;
2425 0 : char *s = NULL;
2426 0 : int want_ekus = 0;
2427 :
2428 0 : if (!has_sans(req))
2429 0 : return characterize_cprinc(context, cprinc);
2430 :
2431 0 : for (i = 0; ret == 0; i++) {
2432 0 : heim_oid oid;
2433 :
2434 0 : frees(&s);
2435 0 : ret = hx509_request_get_eku(req, i, &s);
2436 0 : if (ret)
2437 0 : break;
2438 :
2439 0 : want_ekus = 1;
2440 0 : ret = der_parse_heim_oid(s, ".", &oid);
2441 0 : if (ret)
2442 0 : break;
2443 : /*
2444 : * If the client wants only a server certificate, then we'll be
2445 : * willing to issue one that may be longer-lived than the client's
2446 : * ticket/token.
2447 : *
2448 : * There may be other server EKUs, but these are the ones we know
2449 : * of.
2450 : */
2451 0 : if (der_heim_oid_cmp(&asn1_oid_id_pkix_kp_serverAuth, &oid) &&
2452 0 : der_heim_oid_cmp(&asn1_oid_id_pkix_kp_OCSPSigning, &oid) &&
2453 0 : der_heim_oid_cmp(&asn1_oid_id_pkix_kp_secureShellServer, &oid))
2454 0 : res |= CERT_CLIENT;
2455 : else
2456 0 : res |= CERT_SERVER;
2457 0 : der_free_oid(&oid);
2458 : }
2459 0 : frees(&s);
2460 0 : if (ret == HX509_NO_ITEM)
2461 0 : ret = 0;
2462 :
2463 0 : for (i = 0; ret == 0; i++) {
2464 0 : hx509_san_type san_type;
2465 :
2466 0 : frees(&s);
2467 0 : ret = hx509_request_get_san(req, i, &san_type, &s);
2468 0 : if (ret)
2469 0 : break;
2470 0 : switch (san_type) {
2471 0 : case HX509_SAN_TYPE_DNSNAME:
2472 0 : if (!want_ekus)
2473 0 : res |= CERT_SERVER;
2474 0 : break;
2475 0 : case HX509_SAN_TYPE_EMAIL:
2476 : case HX509_SAN_TYPE_XMPP:
2477 : case HX509_SAN_TYPE_PKINIT:
2478 : case HX509_SAN_TYPE_MS_UPN:
2479 0 : if (!want_ekus)
2480 0 : res |= CERT_CLIENT;
2481 0 : break;
2482 0 : default:
2483 0 : ret = ENOTSUP;
2484 : }
2485 0 : if (ret)
2486 0 : break;
2487 : }
2488 0 : frees(&s);
2489 0 : if (ret == HX509_NO_ITEM)
2490 0 : ret = 0;
2491 0 : return ret ? CERT_NOTSUP : res;
2492 : }
2493 :
2494 : /*
2495 : * Get a configuration sub-tree for kx509 based on what's being requested and
2496 : * by whom.
2497 : *
2498 : * We have a number of cases:
2499 : *
2500 : * - default certificate (no CSR used, or no certificate extensions requested)
2501 : * - for client principals
2502 : * - for service principals
2503 : * - client certificate requested (CSR used and client-y SANs/EKUs requested)
2504 : * - server certificate requested (CSR used and server-y SANs/EKUs requested)
2505 : * - mixed client/server certificate requested (...)
2506 : */
2507 : static heim_error_code
2508 0 : get_cf(hx509_context context,
2509 : const heim_config_binding *cf,
2510 : heim_log_facility *logf,
2511 : hx509_request req,
2512 : KRB5PrincipalName *cprinc,
2513 : const heim_config_binding **out)
2514 : {
2515 0 : heim_error_code ret;
2516 0 : unsigned int ncomp = princ_num_comp(cprinc);
2517 0 : const char *realm = princ_realm(cprinc);
2518 0 : const char *comp0 = princ_get_comp_string(cprinc, 0);
2519 0 : const char *comp1 = princ_get_comp_string(cprinc, 1);
2520 0 : const char *label = NULL;
2521 0 : const char *svc = NULL;
2522 0 : const char *def = NULL;
2523 0 : cert_type certtype = CERT_NOTSUP;
2524 0 : size_t nsans = 0;
2525 :
2526 0 : *out = NULL;
2527 0 : if (ncomp == 0) {
2528 0 : heim_log_msg(context->hcontext, logf, 5, NULL,
2529 : "Client principal has no components!");
2530 0 : hx509_set_error_string(context, 0, ret = ENOTSUP,
2531 : "Client principal has no components!");
2532 0 : return ret;
2533 : }
2534 :
2535 0 : if ((ret = count_sans(req, &nsans)) ||
2536 0 : (certtype = characterize(context, cprinc, req)) == CERT_NOTSUP) {
2537 0 : heim_log_msg(context->hcontext, logf, 5, NULL,
2538 : "Could not characterize CSR");
2539 0 : hx509_set_error_string(context, 0, ret, "Could not characterize CSR");
2540 0 : return ret;
2541 : }
2542 :
2543 0 : if (nsans) {
2544 0 : def = "custom";
2545 : /* Client requested some certificate extension, a SAN or EKU */
2546 0 : switch (certtype) {
2547 0 : case CERT_MIXED: label = "mixed"; break;
2548 0 : case CERT_CLIENT: label = "client"; break;
2549 0 : case CERT_SERVER: label = "server"; break;
2550 0 : default:
2551 0 : hx509_set_error_string(context, 0, ret = ENOTSUP,
2552 : "Requested SAN/EKU combination not "
2553 : "supported");
2554 0 : return ret;
2555 : }
2556 : } else {
2557 0 : def = "default";
2558 : /* Default certificate desired */
2559 0 : if (ncomp == 1) {
2560 0 : label = "user";
2561 0 : } else if (ncomp == 2 && strcmp(comp1, "root") == 0) {
2562 0 : label = "root_user";
2563 0 : } else if (ncomp == 2 && strcmp(comp1, "admin") == 0) {
2564 0 : label = "admin_user";
2565 0 : } else if (strchr(comp1, '.')) {
2566 0 : label = "hostbased_service";
2567 0 : svc = comp0;
2568 : } else {
2569 0 : label = "other";
2570 : }
2571 : }
2572 :
2573 0 : *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL);
2574 0 : if (*out) {
2575 0 : ret = 0;
2576 : } else {
2577 0 : heim_log_msg(context->hcontext, logf, 3, NULL,
2578 : "No configuration for %s %s certificate's realm "
2579 : "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2580 : svc ? " -> " : "", svc ? svc : "");
2581 0 : hx509_set_error_string(context, 0, EACCES,
2582 : "No configuration for %s %s certificate's realm "
2583 : "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2584 : svc ? " -> " : "", svc ? svc : "");
2585 : }
2586 0 : return ret;
2587 : }
2588 :
2589 :
2590 : /*
2591 : * Find and set a certificate template using a configuration sub-tree
2592 : * appropriate to the requesting principal.
2593 : *
2594 : * This allows for the specification of the following in configuration:
2595 : *
2596 : * - certificates as templates, with ${var} tokens in subjectName attribute
2597 : * values that will be expanded later
2598 : * - a plain string with ${var} tokens to use as the subjectName
2599 : * - EKUs
2600 : * - whether to include a PKINIT SAN
2601 : */
2602 : static heim_error_code
2603 0 : set_template(hx509_context context,
2604 : heim_log_facility *logf,
2605 : const heim_config_binding *cf,
2606 : hx509_ca_tbs tbs)
2607 : {
2608 0 : heim_error_code ret = 0;
2609 0 : const char *cert_template = NULL;
2610 0 : const char *subj_name = NULL;
2611 0 : char **ekus = NULL;
2612 :
2613 0 : if (cf == NULL)
2614 0 : return EACCES; /* Can't happen */
2615 :
2616 0 : cert_template = heim_config_get_string(context->hcontext, cf,
2617 : "template_cert", NULL);
2618 0 : subj_name = heim_config_get_string(context->hcontext, cf, "subject_name",
2619 : NULL);
2620 :
2621 0 : if (cert_template) {
2622 0 : hx509_certs certs;
2623 0 : hx509_cert template;
2624 :
2625 0 : ret = hx509_certs_init(context, cert_template, 0, NULL, &certs);
2626 0 : if (ret == 0)
2627 0 : ret = hx509_get_one_cert(context, certs, &template);
2628 0 : hx509_certs_free(&certs);
2629 0 : if (ret) {
2630 0 : heim_log_msg(context->hcontext, logf, 1, NULL,
2631 : "Failed to load certificate template from %s",
2632 : cert_template);
2633 0 : hx509_set_error_string(context, 0, EACCES,
2634 : "Failed to load certificate template from "
2635 : "%s", cert_template);
2636 0 : return ret;
2637 : }
2638 :
2639 : /*
2640 : * Only take the subjectName, the keyUsage, and EKUs from the template
2641 : * certificate.
2642 : */
2643 0 : ret = hx509_ca_tbs_set_template(context, tbs,
2644 : HX509_CA_TEMPLATE_SUBJECT |
2645 : HX509_CA_TEMPLATE_KU |
2646 : HX509_CA_TEMPLATE_EKU,
2647 : template);
2648 0 : hx509_cert_free(template);
2649 0 : if (ret)
2650 0 : return ret;
2651 : }
2652 :
2653 0 : if (subj_name) {
2654 0 : hx509_name dn = NULL;
2655 :
2656 0 : ret = hx509_parse_name(context, subj_name, &dn);
2657 0 : if (ret == 0)
2658 0 : ret = hx509_ca_tbs_set_subject(context, tbs, dn);
2659 0 : hx509_name_free(&dn);
2660 0 : if (ret)
2661 0 : return ret;
2662 : }
2663 :
2664 0 : if (cert_template == NULL && subj_name == NULL) {
2665 0 : hx509_name dn = NULL;
2666 :
2667 0 : ret = hx509_empty_name(context, &dn);
2668 0 : if (ret == 0)
2669 0 : ret = hx509_ca_tbs_set_subject(context, tbs, dn);
2670 0 : hx509_name_free(&dn);
2671 0 : if (ret)
2672 0 : return ret;
2673 : }
2674 :
2675 0 : ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL);
2676 0 : if (ekus) {
2677 : size_t i;
2678 :
2679 0 : for (i = 0; ret == 0 && ekus[i]; i++) {
2680 0 : heim_oid oid = { 0, NULL };
2681 :
2682 0 : if ((ret = der_find_or_parse_heim_oid(ekus[i], ".", &oid)) == 0)
2683 0 : ret = hx509_ca_tbs_add_eku(context, tbs, &oid);
2684 0 : der_free_oid(&oid);
2685 : }
2686 0 : heim_config_free_strings(ekus);
2687 : }
2688 :
2689 : /*
2690 : * XXX A KeyUsage template would be nice, but it needs some smarts to
2691 : * remove, e.g., encipherOnly, decipherOnly, keyEncipherment, if the SPKI
2692 : * algorithm does not support encryption. The same logic should be added
2693 : * to hx509_ca_tbs_set_template()'s HX509_CA_TEMPLATE_KU functionality.
2694 : */
2695 0 : return ret;
2696 : }
2697 :
2698 : /*
2699 : * Find and set a certificate template, set "variables" in `env', and add add
2700 : * default SANs/EKUs as appropriate.
2701 : *
2702 : * TODO:
2703 : * - lookup a template for the client principal in its HDB entry
2704 : * - lookup subjectName, SANs for a principal in its HDB entry
2705 : * - lookup a host-based client principal's HDB entry and add its canonical
2706 : * name / aliases as dNSName SANs
2707 : * (this would have to be if requested by the client, perhaps)
2708 : */
2709 : static heim_error_code
2710 0 : set_tbs(hx509_context context,
2711 : heim_log_facility *logf,
2712 : const heim_config_binding *cf,
2713 : hx509_request req,
2714 : KRB5PrincipalName *cprinc,
2715 : hx509_env *env,
2716 : hx509_ca_tbs tbs)
2717 : {
2718 0 : KRB5PrincipalName cprinc_no_realm = *cprinc;
2719 0 : heim_error_code ret;
2720 0 : unsigned int ncomp = princ_num_comp(cprinc);
2721 0 : const char *realm = princ_realm(cprinc);
2722 0 : const char *comp0 = princ_get_comp_string(cprinc, 0);
2723 0 : const char *comp1 = princ_get_comp_string(cprinc, 1);
2724 0 : const char *comp2 = princ_get_comp_string(cprinc, 2);
2725 0 : struct rk_strpool *strpool;
2726 0 : char *princ_no_realm = NULL;
2727 0 : char *princ = NULL;
2728 :
2729 0 : strpool = _hx509_unparse_kerberos_name(NULL, cprinc);
2730 0 : if (strpool)
2731 0 : princ = rk_strpoolcollect(strpool);
2732 0 : cprinc_no_realm.realm = NULL;
2733 0 : strpool = _hx509_unparse_kerberos_name(NULL, &cprinc_no_realm);
2734 0 : if (strpool)
2735 0 : princ_no_realm = rk_strpoolcollect(strpool);
2736 0 : if (princ == NULL || princ_no_realm == NULL) {
2737 0 : free(princ);
2738 0 : return hx509_enomem(context);
2739 : }
2740 0 : strpool = NULL;
2741 0 : ret = hx509_env_add(context, env, "principal-name-without-realm",
2742 : princ_no_realm);
2743 0 : if (ret == 0)
2744 0 : ret = hx509_env_add(context, env, "principal-name", princ);
2745 0 : if (ret == 0)
2746 0 : ret = hx509_env_add(context, env, "principal-name-realm",
2747 : realm);
2748 :
2749 : /* Populate requested certificate extensions from CSR/CSRPlus if allowed */
2750 0 : if (ret == 0)
2751 0 : ret = hx509_ca_tbs_set_from_csr(context, tbs, req);
2752 0 : if (ret == 0)
2753 0 : ret = set_template(context, logf, cf, tbs);
2754 :
2755 : /*
2756 : * Optionally add PKINIT SAN.
2757 : *
2758 : * Adding an id-pkinit-san means the client can use the certificate to
2759 : * initiate PKINIT. That might seem odd, but it enables a sort of PKIX
2760 : * credential delegation by allowing forwarded Kerberos tickets to be
2761 : * used to acquire PKIX credentials. Thus this can work:
2762 : *
2763 : * PKIX (w/ HW token) -> Kerberos ->
2764 : * PKIX (w/ softtoken) -> Kerberos ->
2765 : * PKIX (w/ softtoken) -> Kerberos ->
2766 : * ...
2767 : *
2768 : * Note that we may not have added the PKINIT EKU -- that depends on the
2769 : * template, and host-based service templates might well not include it.
2770 : */
2771 0 : if (ret == 0 && !has_sans(req) &&
2772 0 : heim_config_get_bool_default(context->hcontext, cf, FALSE,
2773 : "include_pkinit_san", NULL)) {
2774 0 : ret = hx509_ca_tbs_add_san_pkinit(context, tbs, princ);
2775 : }
2776 :
2777 0 : if (ret)
2778 0 : goto out;
2779 :
2780 0 : if (ncomp == 1) {
2781 0 : const char *email_domain;
2782 :
2783 0 : ret = hx509_env_add(context, env, "principal-component0",
2784 : princ_no_realm);
2785 :
2786 : /*
2787 : * If configured, include an rfc822Name that's just the client's
2788 : * principal name sans realm @ configured email domain.
2789 : */
2790 0 : if (ret == 0 && !has_sans(req) &&
2791 0 : (email_domain = heim_config_get_string(context->hcontext, cf,
2792 : "email_domain", NULL))) {
2793 0 : char *email;
2794 :
2795 0 : if (asprintf(&email, "%s@%s", princ_no_realm, email_domain) == -1 ||
2796 0 : email == NULL)
2797 0 : goto enomem;
2798 0 : ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email);
2799 0 : free(email);
2800 : }
2801 0 : } else if (ncomp == 2 || ncomp == 3) {
2802 : /*
2803 : * 2- and 3-component principal name.
2804 : *
2805 : * We do not have a reliable name-type indicator. If the second
2806 : * component has a '.' in it then we'll assume that the name is a
2807 : * host-based (2-component) or domain-based (3-component) service
2808 : * principal name. Else we'll assume it's a two-component admin-style
2809 : * username.
2810 : */
2811 :
2812 0 : ret = hx509_env_add(context, env, "principal-component0", comp0);
2813 0 : if (ret == 0)
2814 0 : ret = hx509_env_add(context, env, "principal-component1", comp1);
2815 0 : if (ret == 0 && ncomp == 3)
2816 0 : ret = hx509_env_add(context, env, "principal-component2", comp2);
2817 0 : if (ret == 0 && strchr(comp1, '.')) {
2818 : /* Looks like host-based or domain-based service */
2819 0 : ret = hx509_env_add(context, env, "principal-service-name", comp0);
2820 0 : if (ret == 0)
2821 0 : ret = hx509_env_add(context, env, "principal-host-name",
2822 : comp1);
2823 0 : if (ret == 0 && ncomp == 3)
2824 0 : ret = hx509_env_add(context, env, "principal-domain-name",
2825 : comp2);
2826 0 : if (ret == 0 && !has_sans(req) &&
2827 0 : heim_config_get_bool_default(context->hcontext, cf, FALSE,
2828 : "include_dnsname_san", NULL)) {
2829 0 : ret = hx509_ca_tbs_add_san_hostname(context, tbs, comp1);
2830 : }
2831 : }
2832 : } else {
2833 0 : heim_log_msg(context->hcontext, logf, 5, NULL,
2834 : "kx509/bx509 client %s has too many components!", princ);
2835 0 : hx509_set_error_string(context, 0, ret = EACCES,
2836 : "kx509/bx509 client %s has too many "
2837 : "components!", princ);
2838 : }
2839 :
2840 0 : out:
2841 0 : if (ret == ENOMEM)
2842 0 : goto enomem;
2843 0 : free(princ_no_realm);
2844 0 : free(princ);
2845 0 : return ret;
2846 :
2847 0 : enomem:
2848 0 : heim_log_msg(context->hcontext, logf, 0, NULL,
2849 : "Could not set up TBSCertificate: Out of memory");
2850 0 : ret = hx509_enomem(context);
2851 0 : goto out;
2852 : }
2853 :
2854 : /*
2855 : * Set the notBefore/notAfter for the certificate to be issued.
2856 : *
2857 : * Here `starttime' is the supplicant's credentials' notBefore equivalent,
2858 : * while `endtime' is the supplicant's credentials' notAfter equivalent.
2859 : *
2860 : * `req_life' is the lifetime requested by the supplicant.
2861 : *
2862 : * `endtime' must be larger than the current time.
2863 : *
2864 : * `starttime' can be zero or negative, in which case the notBefore will be the
2865 : * current time minus five minutes.
2866 : *
2867 : * `endtime', `req_life' and configuration parameters will be used to compute
2868 : * the actual notAfter.
2869 : */
2870 : static heim_error_code
2871 0 : tbs_set_times(hx509_context context,
2872 : const heim_config_binding *cf,
2873 : heim_log_facility *logf,
2874 : time_t starttime,
2875 : time_t endtime,
2876 : time_t req_life,
2877 : hx509_ca_tbs tbs)
2878 : {
2879 0 : time_t now = time(NULL);
2880 0 : time_t force = heim_config_get_time_default(context->hcontext,
2881 : cf, 5 * 24 * 3600,
2882 : "force_cert_lifetime", NULL);
2883 0 : time_t clamp = heim_config_get_time_default(context->hcontext, cf, 0,
2884 : "max_cert_lifetime", NULL);
2885 0 : int allow_more = heim_config_get_bool_default(context->hcontext, cf, FALSE,
2886 : "allow_extra_lifetime",
2887 : NULL);
2888 0 : starttime = starttime > 0 ? starttime : now - 5 * 60;
2889 :
2890 0 : if (endtime < now) {
2891 0 : heim_log_msg(context->hcontext, logf, 3, NULL,
2892 : "Endtime is in the past");
2893 0 : hx509_set_error_string(context, 0, ERANGE, "Endtime is in the past");
2894 0 : return ERANGE;
2895 : }
2896 :
2897 : /* Apply requested lifetime if shorter or if allowed more */
2898 0 : if (req_life > 0 && req_life <= endtime - now)
2899 0 : endtime = now + req_life;
2900 0 : else if (req_life > 0 && allow_more)
2901 0 : endtime = now + req_life;
2902 :
2903 : /* Apply floor */
2904 0 : if (force > 0 && force > endtime - now)
2905 0 : endtime = now + force;
2906 :
2907 : /* Apply ceiling */
2908 0 : if (clamp > 0 && clamp < endtime - now)
2909 0 : endtime = now + clamp;
2910 :
2911 0 : hx509_ca_tbs_set_notAfter(context, tbs, endtime);
2912 0 : hx509_ca_tbs_set_notBefore(context, tbs, starttime);
2913 0 : return 0;
2914 : }
2915 :
2916 : /*
2917 : * Build a certifate for `principal' and its CSR.
2918 : *
2919 : * XXX Make `cprinc' a GeneralName! That's why this is private for now.
2920 : */
2921 : heim_error_code
2922 0 : _hx509_ca_issue_certificate(hx509_context context,
2923 : const heim_config_binding *cf,
2924 : heim_log_facility *logf,
2925 : hx509_request req,
2926 : KRB5PrincipalName *cprinc,
2927 : time_t starttime,
2928 : time_t endtime,
2929 : time_t req_life,
2930 : int send_chain,
2931 : hx509_certs *out)
2932 : {
2933 0 : heim_error_code ret;
2934 0 : const char *ca;
2935 0 : hx509_ca_tbs tbs = NULL;
2936 0 : hx509_certs chain = NULL;
2937 0 : hx509_cert signer = NULL;
2938 0 : hx509_cert cert = NULL;
2939 0 : hx509_env env = NULL;
2940 0 : KeyUsage ku;
2941 :
2942 0 : *out = NULL;
2943 : /* Force KU */
2944 0 : ku = int2KeyUsage(0);
2945 0 : ku.digitalSignature = 1;
2946 0 : hx509_request_authorize_ku(req, ku);
2947 :
2948 0 : ret = get_cf(context, cf, logf, req, cprinc, &cf);
2949 0 : if (ret)
2950 0 : return ret;
2951 :
2952 0 : if ((ca = heim_config_get_string(context->hcontext, cf,
2953 : "ca", NULL)) == NULL) {
2954 0 : heim_log_msg(context->hcontext, logf, 3, NULL,
2955 : "No kx509 CA issuer credential specified");
2956 0 : hx509_set_error_string(context, 0, ret = EACCES,
2957 : "No kx509 CA issuer credential specified");
2958 0 : return ret;
2959 : }
2960 :
2961 0 : ret = hx509_ca_tbs_init(context, &tbs);
2962 0 : if (ret) {
2963 0 : heim_log_msg(context->hcontext, logf, 0, NULL,
2964 : "Failed to create certificate: Out of memory");
2965 0 : return ret;
2966 : }
2967 :
2968 : /* Lookup a template and set things in `env' and `tbs' as appropriate */
2969 0 : if (ret == 0)
2970 0 : ret = set_tbs(context, logf, cf, req, cprinc, &env, tbs);
2971 :
2972 : /* Populate generic template "env" variables */
2973 :
2974 : /*
2975 : * The `tbs' and `env' are now complete as to naming and EKUs.
2976 : *
2977 : * We check that the `tbs' is not name-less, after which all remaining
2978 : * failures here will not be policy failures. So we also log the intent to
2979 : * issue a certificate now.
2980 : */
2981 0 : if (ret == 0 && hx509_name_is_null_p(hx509_ca_tbs_get_name(tbs)) &&
2982 0 : !has_sans(req)) {
2983 0 : heim_log_msg(context->hcontext, logf, 3, NULL,
2984 : "Not issuing certificate because it would have no names");
2985 0 : hx509_set_error_string(context, 0, ret = EACCES,
2986 : "Not issuing certificate because it "
2987 : "would have no names");
2988 : }
2989 0 : if (ret)
2990 0 : goto out;
2991 :
2992 : /*
2993 : * Still to be done below:
2994 : *
2995 : * - set certificate spki
2996 : * - set certificate validity
2997 : * - expand variables in certificate subject name template
2998 : * - sign certificate
2999 : * - encode certificate and chain
3000 : */
3001 :
3002 : /* Load the issuer certificate and private key */
3003 : {
3004 0 : hx509_certs certs;
3005 0 : hx509_query *q;
3006 :
3007 0 : ret = hx509_certs_init(context, ca, 0, NULL, &certs);
3008 0 : if (ret) {
3009 0 : heim_log_msg(context->hcontext, logf, 1, NULL,
3010 : "Failed to load CA certificate and private key %s",
3011 : ca);
3012 0 : hx509_set_error_string(context, 0, ret, "Failed to load "
3013 : "CA certificate and private key %s", ca);
3014 0 : goto out;
3015 : }
3016 0 : ret = hx509_query_alloc(context, &q);
3017 0 : if (ret) {
3018 0 : hx509_certs_free(&certs);
3019 0 : goto out;
3020 : }
3021 :
3022 0 : hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
3023 0 : hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
3024 :
3025 0 : ret = hx509_certs_find(context, certs, q, &signer);
3026 0 : hx509_query_free(context, q);
3027 0 : hx509_certs_free(&certs);
3028 0 : if (ret) {
3029 0 : heim_log_msg(context->hcontext, logf, 1, NULL,
3030 : "Failed to find a CA certificate in %s", ca);
3031 0 : hx509_set_error_string(context, 0, ret,
3032 : "Failed to find a CA certificate in %s",
3033 : ca);
3034 0 : goto out;
3035 : }
3036 : }
3037 :
3038 : /* Populate the subject public key in the TBS context */
3039 : {
3040 0 : SubjectPublicKeyInfo spki;
3041 :
3042 0 : ret = hx509_request_get_SubjectPublicKeyInfo(context,
3043 : req, &spki);
3044 0 : if (ret == 0)
3045 0 : ret = hx509_ca_tbs_set_spki(context, tbs, &spki);
3046 0 : free_SubjectPublicKeyInfo(&spki);
3047 0 : if (ret)
3048 0 : goto out;
3049 : }
3050 :
3051 : /* Work out cert expiration */
3052 0 : if (ret == 0)
3053 0 : ret = tbs_set_times(context, cf, logf, starttime, endtime, req_life,
3054 : tbs);
3055 :
3056 : /* Expand the subjectName template in the TBS using the env */
3057 0 : if (ret == 0)
3058 0 : ret = hx509_ca_tbs_subject_expand(context, tbs, env);
3059 0 : hx509_env_free(&env);
3060 :
3061 : /* All done with the TBS, sign/issue the certificate */
3062 0 : if (ret == 0)
3063 0 : ret = hx509_ca_sign(context, tbs, signer, &cert);
3064 :
3065 : /*
3066 : * Gather the certificate and chain into a MEMORY store, being careful not
3067 : * to include private keys in the chain.
3068 : *
3069 : * We could have specified a separate configuration parameter for an hx509
3070 : * store meant to have only the chain and no private keys, but expecting
3071 : * the full chain in the issuer credential store and copying only the certs
3072 : * (but not the private keys) is safer and easier to configure.
3073 : */
3074 0 : if (ret == 0)
3075 0 : ret = hx509_certs_init(context, "MEMORY:certs",
3076 : HX509_CERTS_NO_PRIVATE_KEYS, NULL, out);
3077 0 : if (ret == 0)
3078 0 : ret = hx509_certs_add(context, *out, cert);
3079 0 : if (ret == 0 && send_chain) {
3080 0 : ret = hx509_certs_init(context, ca,
3081 : HX509_CERTS_NO_PRIVATE_KEYS, NULL, &chain);
3082 0 : if (ret == 0)
3083 0 : ret = hx509_certs_merge(context, *out, chain);
3084 : }
3085 :
3086 0 : out:
3087 0 : hx509_certs_free(&chain);
3088 0 : if (env)
3089 0 : hx509_env_free(&env);
3090 0 : if (tbs)
3091 0 : hx509_ca_tbs_free(&tbs);
3092 0 : if (cert)
3093 0 : hx509_cert_free(cert);
3094 0 : if (signer)
3095 0 : hx509_cert_free(signer);
3096 0 : if (ret)
3097 0 : hx509_certs_free(out);
3098 0 : return ret;
3099 : }
|