Coverage Report

Created: 2025-12-31 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/third_party/heimdal/lib/hx509/ca.c
Line
Count
Source
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
hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84
0
{
85
0
    *tbs = calloc(1, sizeof(**tbs));
86
0
    if (*tbs == NULL)
87
0
  return ENOMEM;
88
89
0
    return 0;
90
0
}
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
hx509_ca_tbs_free(hx509_ca_tbs *tbs)
102
0
{
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
0
    }
121
122
0
    memset(*tbs, 0, sizeof(**tbs));
123
0
    free(*tbs);
124
0
    *tbs = NULL;
125
0
}
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
hx509_ca_tbs_set_notBefore(hx509_context context,
142
         hx509_ca_tbs tbs,
143
         time_t t)
144
0
{
145
0
    tbs->notBefore = t;
146
0
    return 0;
147
0
}
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
hx509_ca_tbs_set_notAfter(hx509_context context,
163
         hx509_ca_tbs tbs,
164
         time_t t)
165
0
{
166
0
    tbs->notAfter = t;
167
0
    return 0;
168
0
}
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
hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
184
           hx509_ca_tbs tbs,
185
           time_t delta)
186
0
{
187
0
    return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
188
0
}
189
190
HX509_LIB_FUNCTION int HX509_LIB_CALL
191
hx509_ca_tbs_set_pkinit_max_life(hx509_context context,
192
                                 hx509_ca_tbs tbs,
193
                                 time_t max_life)
194
0
{
195
0
    tbs->pkinitTicketMaxLife = max_life;
196
0
    return 0;
197
0
}
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
hx509_ca_tbs_template_units(void)
222
0
{
223
0
    return templatebits;
224
0
}
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
hx509_ca_tbs_set_template(hx509_context context,
242
        hx509_ca_tbs tbs,
243
        int flags,
244
        hx509_cert cert)
245
0
{
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
0
           "Failed to get subject from template");
255
0
      return ret;
256
0
  }
257
0
    }
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
0
           "Failed to copy serial number");
265
0
      return ret;
266
0
  }
267
0
    }
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
0
    }
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
0
    }
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
0
      }
296
0
  }
297
0
  free_ExtKeyUsage(&eku);
298
0
    }
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
0
    }
305
0
    return 0;
306
0
}
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
hx509_ca_tbs_set_ca(hx509_context context,
324
        hx509_ca_tbs tbs,
325
        int pathLenConstraint)
326
0
{
327
0
    tbs->flags.ca = 1;
328
0
    tbs->pathLenConstraint = pathLenConstraint;
329
0
    return 0;
330
0
}
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
hx509_ca_tbs_set_proxy(hx509_context context,
348
           hx509_ca_tbs tbs,
349
           int pathLenConstraint)
350
0
{
351
0
    tbs->flags.proxy = 1;
352
0
    tbs->pathLenConstraint = pathLenConstraint;
353
0
    return 0;
354
0
}
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
hx509_ca_tbs_set_domaincontroller(hx509_context context,
370
          hx509_ca_tbs tbs)
371
0
{
372
0
    tbs->flags.domaincontroller = 1;
373
0
    return 0;
374
0
}
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
hx509_ca_tbs_set_spki(hx509_context context,
392
          hx509_ca_tbs tbs,
393
          const SubjectPublicKeyInfo *spki)
394
0
{
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
0
}
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
hx509_ca_tbs_set_serialnumber(hx509_context context,
417
            hx509_ca_tbs tbs,
418
            const heim_integer *serialNumber)
419
0
{
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
0
}
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
hx509_ca_tbs_set_from_csr(hx509_context context,
441
                    hx509_ca_tbs tbs,
442
                    hx509_request req)
443
0
{
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
0
                               "Some certificate features requested in the CSR were not authorized");
454
0
        return EACCES;
455
0
    }
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
0
    }
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
0
    }
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
0
}
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
hx509_ca_tbs_add_ku(hx509_context context,
502
        hx509_ca_tbs tbs,
503
        KeyUsage ku)
504
0
{
505
0
    tbs->ku = ku;
506
0
    return 0;
507
0
}
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
hx509_ca_tbs_add_eku(hx509_context context,
524
         hx509_ca_tbs tbs,
525
         const heim_oid *oid)
526
0
{
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
0
    }
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
0
    }
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
0
    }
548
0
    tbs->eku.len += 1;
549
0
    return 0;
550
0
}
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
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
0
{
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
0
    }
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
0
         pqi.qualifier.data,
600
0
         pqi.qualifier.length,
601
0
         &uri, &size, ret);
602
0
        if (ret == 0) {
603
0
            ret = add_PolicyQualifierInfos(&pqis, &pqi);
604
0
            free_heim_any(&pqi.qualifier);
605
0
        }
606
0
    }
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
0
         pqi.qualifier.data,
619
0
         pqi.qualifier.length,
620
0
         &un, &size, ret);
621
0
        if (ret == 0) {
622
0
            ret = add_PolicyQualifierInfos(&pqis, &pqi);
623
0
            free_heim_any(&pqi.qualifier);
624
0
        }
625
0
    }
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
0
}
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
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
0
{
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
0
    }
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
0
}
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
hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
689
          hx509_ca_tbs tbs,
690
          const char *uri,
691
          hx509_name issuername)
692
0
{
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
0
  }
719
0
        crlissuer.len = 1;
720
0
        crlissuer.val = &ign;
721
0
  dp.cRLIssuer = &crlissuer;
722
0
    }
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
0
}
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
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
0
{
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
0
}
762
763
static
764
int
765
dequote_strndup(hx509_context context, const char *in, size_t len, char **out)
766
0
{
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
0
    }
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
0
                                           HX509_PARSING_NAME_FAILED,
790
0
                                           "embedded NULs not supported in "
791
0
                                           "PKINIT SANs");
792
0
                    free(s);
793
0
                    return HX509_PARSING_NAME_FAILED;
794
0
                }
795
0
                break;
796
0
            case '\0':
797
0
                hx509_set_error_string(context, 0,
798
0
                                       HX509_PARSING_NAME_FAILED,
799
0
                                       "trailing unquoted backslashes not "
800
0
                                       "allowed in PKINIT SANs");
801
0
                free(s);
802
0
                return HX509_PARSING_NAME_FAILED;
803
0
            default:  s[k++] = in[i]; break;
804
0
            }
805
0
        } else {
806
0
            s[k++] = in[i];
807
0
        }
808
0
    }
809
0
    s[k] = '\0';
810
811
0
    *out = s;
812
0
    return 0;
813
0
}
814
815
int
816
_hx509_make_pkinit_san(hx509_context context,
817
                       const char *principal,
818
                       heim_octet_string *os)
819
0
{
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
0
    {
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
0
             "trailing \\ in principal name");
841
0
        goto out;
842
0
    }
843
0
    str++;
844
0
      } else if(*str == '/') {
845
0
    n++;
846
0
      } else if(*str == '@') {
847
0
    break;
848
0
            }
849
0
  }
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
0
  }
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
0
            }
886
0
  }
887
0
    }
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
0
    }
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
0
}
901
902
static int
903
add_ia5string_san(hx509_context context,
904
                  hx509_ca_tbs tbs,
905
                  const heim_oid *oid,
906
                  const char *string)
907
0
{
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
0
    }
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
0
}
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
hx509_ca_tbs_add_san_dnssrv(hx509_context context,
946
          hx509_ca_tbs tbs,
947
          const char *dnssrv)
948
0
{
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
0
    }
956
0
    for (i = 1, len = strlen(dnssrv); i < len; i++) {
957
0
        if (dnssrv[i] == '.' && dnssrv[i + 1] != '\0')
958
0
            break;
959
0
    }
960
0
    if (i == len) {
961
0
        hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
962
0
        return EINVAL;
963
0
    }
964
965
0
    return add_ia5string_san(context, tbs,
966
0
                             &asn1_oid_id_pkix_on_dnsSRV, dnssrv);
967
0
}
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
hx509_ca_tbs_add_san_pkinit(hx509_context context,
984
          hx509_ca_tbs tbs,
985
          const char *principal)
986
0
{
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
0
                                             &asn1_oid_id_pkinit_san, &os);
994
0
    free(os.data);
995
0
    return ret;
996
0
}
997
998
/*
999
 *
1000
 */
1001
1002
static int
1003
add_utf8_san(hx509_context context,
1004
       hx509_ca_tbs tbs,
1005
       const heim_oid *oid,
1006
       const char *string)
1007
0
{
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
0
    }
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
0
}
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
hx509_ca_tbs_add_san_ms_upn(hx509_context context,
1044
          hx509_ca_tbs tbs,
1045
          const char *principal)
1046
0
{
1047
0
    return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
1048
0
}
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
hx509_ca_tbs_add_san_jid(hx509_context context,
1065
       hx509_ca_tbs tbs,
1066
       const char *jid)
1067
0
{
1068
0
    return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
1069
0
}
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
hx509_ca_tbs_add_san_hostname(hx509_context context,
1090
            hx509_ca_tbs tbs,
1091
            const char *dnsname)
1092
0
{
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
0
}
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
hx509_ca_tbs_add_san_rfc822name(hx509_context context,
1118
        hx509_ca_tbs tbs,
1119
        const char *rfc822Name)
1120
0
{
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
0
}
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
hx509_ca_tbs_add_san_permanentIdentifier_string(hx509_context context,
1174
                                                hx509_ca_tbs tbs,
1175
                                                const char *str)
1176
0
{
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
0
                               "Invalid PermanentIdentifier string (should be \"[<oid>]:[<id>]\")");
1192
0
        free(freeme);
1193
0
        return EINVAL;
1194
0
    }
1195
0
    if (p) {
1196
0
        *(p++) = '\0';
1197
0
        id = p;
1198
0
    }
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
0
        }
1206
0
    }
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
0
}
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
hx509_ca_tbs_add_san_permanentIdentifier(hx509_context context,
1235
                                         hx509_ca_tbs tbs,
1236
                                         const char *identifierValue,
1237
                                         const heim_oid *assigner)
1238
0
{
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
0
                       ret);
1252
0
    if (ret) {
1253
0
  hx509_set_error_string(context, 0, ret, "Out of memory");
1254
0
  return ret;
1255
0
    }
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
0
                                         &asn1_oid_id_pkix_on_permanentIdentifier,
1261
0
                                         &os);
1262
0
    free(os.data);
1263
0
    return ret;
1264
0
}
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
hx509_ca_tbs_add_san_hardwareModuleName_string(hx509_context context,
1282
                                               hx509_ca_tbs tbs,
1283
                                               const char *str)
1284
0
{
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
0
                               "Invalid HardwareModuleName string (should be "
1300
0
                               "\"<oid>:<serial>\")");
1301
0
        free(freeme);
1302
0
        return EINVAL;
1303
0
    }
1304
0
    if (p) {
1305
0
        *(p++) = '\0';
1306
0
        sno = p;
1307
0
    }
1308
0
    if (oidstr[0] == '\0') {
1309
0
        found = &asn1_oid_tcg_tpm20;
1310
0
    } 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
0
        }
1317
0
    }
1318
0
    if (!found) {
1319
0
        hx509_set_error_string(context, 0, EINVAL,
1320
0
                               "Could not resolve or parse OID \"%s\"",
1321
0
                               oidstr);
1322
0
        free(freeme);
1323
0
        return EINVAL;
1324
0
    }
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
0
}
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
hx509_ca_tbs_add_san_hardwareModuleName(hx509_context context,
1348
                                        hx509_ca_tbs tbs,
1349
                                        const heim_oid *hwtype,
1350
                                        const char *hwserial)
1351
0
{
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
0
                       ret);
1365
0
    if (ret) {
1366
0
  hx509_set_error_string(context, 0, ret, "Out of memory");
1367
0
  return ret;
1368
0
    }
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
0
                                         &asn1_oid_id_on_hardwareModuleName,
1374
0
                                         &os);
1375
0
    free(os.data);
1376
0
    return ret;
1377
0
}
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
hx509_ca_tbs_add_san(hx509_context context,
1394
                     hx509_ca_tbs tbs,
1395
                     hx509_san_type type,
1396
                     const char *s)
1397
0
{
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
0
    }
1416
0
}
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
hx509_ca_tbs_set_subject(hx509_context context,
1432
       hx509_ca_tbs tbs,
1433
       hx509_name subject)
1434
0
{
1435
0
    if (tbs->subject)
1436
0
  hx509_name_free(&tbs->subject);
1437
0
    return hx509_name_copy(context, subject, &tbs->subject);
1438
0
}
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
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
0
{
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
0
    }
1474
1475
0
    if (issuerUniqueID) {
1476
0
  ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
1477
0
  if (ret)
1478
0
      return ret;
1479
0
    }
1480
1481
0
    return 0;
1482
0
}
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
hx509_ca_tbs_subject_expand(hx509_context context,
1500
          hx509_ca_tbs tbs,
1501
          hx509_env env)
1502
0
{
1503
0
    return hx509_name_expand(context, tbs->subject, env);
1504
0
}
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
hx509_ca_tbs_get_name(hx509_ca_tbs tbs)
1519
0
{
1520
0
    return tbs->subject;
1521
0
}
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
hx509_ca_tbs_set_signature_algorithm(hx509_context context,
1537
             hx509_ca_tbs tbs,
1538
             const AlgorithmIdentifier *sigalg)
1539
0
{
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
0
    }
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
0
    }
1553
0
    return 0;
1554
0
}
1555
1556
/*
1557
 *
1558
 */
1559
1560
static int
1561
add_extension(hx509_context context,
1562
        TBSCertificate *tbsc,
1563
        int critical_flag,
1564
        const heim_oid *oid,
1565
        const heim_octet_string *data)
1566
0
{
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
0
    }
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
0
    }
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
0
    }
1588
0
out:
1589
0
    free_Extension(&ext);
1590
0
    return ret;
1591
0
}
1592
1593
static int
1594
build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
1595
0
{
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
0
             "Failed to copy subject name");
1604
0
  return ret;
1605
0
    }
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
0
             "Failed to copy subject name");
1612
0
  return ENOMEM;
1613
0
    }
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
0
}
1621
1622
static int
1623
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
0
{
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
0
    }
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
0
    }
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
0
           "Empty subject and no SubjectAltNames");
1691
0
      return EINVAL;
1692
0
  }
1693
0
    }
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
0
             "at the same time");
1697
0
  return EINVAL;
1698
0
    }
1699
0
    if (tbs->flags.proxy) {
1700
0
  if (tbs->san.len > 0) {
1701
0
      hx509_set_error_string(context, 0, EINVAL,
1702
0
           "Proxy certificate is not allowed "
1703
0
           "to have SubjectAltNames");
1704
0
      return EINVAL;
1705
0
  }
1706
0
    }
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
0
    }
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
0
  }
1723
0
    } 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
0
  }
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
0
  }
1743
0
  ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1744
0
  ((unsigned char *)tbsc->serialNumber.data)[0] |= 0x40;
1745
0
    }
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
0
    }
1752
    /* issuer               Name, */
1753
0
    if (issuername)
1754
0
  ret = copy_Name(issuername, &tbsc->issuer);
1755
0
    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
0
    }
1761
    /* validity             Validity, */
1762
0
    {
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
0
        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
0
        else
1785
0
            tbsc->validity.notAfter.element = choice_Time_generalTime;
1786
0
        tbsc->validity.notAfter.u.generalTime = notAfter;
1787
0
    }
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
0
    } 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
0
           "Failed to copy subject name");
1798
0
      goto out;
1799
0
  }
1800
0
    }
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
0
    }
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
0
  }
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
0
  }
1820
0
    }
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
0
  }
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
0
  }
1835
0
    }
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
0
    }
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
0
             "\x00\x61\x00\x69\x00\x6e\x00\x43"
1849
0
             "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1850
0
             "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1851
0
             "\x00\x72");
1852
0
  data.length = 34;
1853
1854
0
  ret = add_extension(context, tbsc, 0,
1855
0
          &asn1_oid_id_ms_cert_enroll_domaincontroller,
1856
0
          &data);
1857
0
  if (ret)
1858
0
      goto out;
1859
0
    }
1860
1861
    /* Add KeyUsage */
1862
0
    if (KeyUsage2int(tbs->ku) > 0) {
1863
0
        ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length,
1864
0
                           &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
0
  }
1869
0
  if (size != data.length)
1870
0
      _hx509_abort("internal ASN.1 encoder error");
1871
0
  ret = add_extension(context, tbsc, 1,
1872
0
          &asn1_oid_id_x509_ce_keyUsage, &data);
1873
0
  free(data.data);
1874
0
  if (ret)
1875
0
      goto out;
1876
0
    }
1877
1878
    /* Add ExtendedKeyUsage */
1879
0
    if (tbs->eku.len > 0) {
1880
0
  ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1881
0
         &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
0
  }
1886
0
  if (size != data.length)
1887
0
      _hx509_abort("internal ASN.1 encoder error");
1888
0
  ret = add_extension(context, tbsc, 1,
1889
0
          &asn1_oid_id_x509_ce_extKeyUsage, &data);
1890
0
  free(data.data);
1891
0
  if (ret)
1892
0
      goto out;
1893
0
    }
1894
1895
    /* Add Subject Alternative Name */
1896
0
    if (tbs->san.len > 0) {
1897
0
  ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1898
0
         &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
0
  }
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
0
                            &asn1_oid_id_x509_ce_subjectAltName, &data);
1909
0
  free(data.data);
1910
0
  if (ret)
1911
0
      goto out;
1912
0
    }
1913
1914
    /* Add Authority Key Identifier */
1915
0
    if (ai) {
1916
0
  ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1917
0
         ai, &size, ret);
1918
0
  if (ret) {
1919
0
      hx509_set_error_string(context, 0, ret, "Out of memory");
1920
0
      goto out;
1921
0
  }
1922
0
  if (size != data.length)
1923
0
      _hx509_abort("internal ASN.1 encoder error");
1924
0
  ret = add_extension(context, tbsc, 0,
1925
0
          &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1926
0
          &data);
1927
0
  free(data.data);
1928
0
  if (ret)
1929
0
      goto out;
1930
0
    }
1931
1932
    /* Add Subject Key Identifier */
1933
0
    {
1934
0
  SubjectKeyIdentifier si;
1935
0
  unsigned char hash[SHA_DIGEST_LENGTH];
1936
1937
0
  {
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
0
  }
1947
1948
0
  si.data = hash;
1949
0
  si.length = sizeof(hash);
1950
1951
0
  ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1952
0
         &si, &size, ret);
1953
0
  if (ret) {
1954
0
      hx509_set_error_string(context, 0, ret, "Out of memory");
1955
0
      goto out;
1956
0
  }
1957
0
  if (size != data.length)
1958
0
      _hx509_abort("internal ASN.1 encoder error");
1959
0
  ret = add_extension(context, tbsc, 0,
1960
0
          &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1961
0
          &data);
1962
0
  free(data.data);
1963
0
  if (ret)
1964
0
      goto out;
1965
0
    }
1966
1967
    /* Add BasicConstraints */
1968
0
    {
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
0
      }
1980
0
  }
1981
1982
0
  ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1983
0
         &bc, &size, ret);
1984
0
  if (ret) {
1985
0
      hx509_set_error_string(context, 0, ret, "Out of memory");
1986
0
      goto out;
1987
0
  }
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
0
          &asn1_oid_id_x509_ce_basicConstraints,
1993
0
          &data);
1994
0
  free(data.data);
1995
0
  if (ret)
1996
0
      goto out;
1997
0
    }
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
0
      }
2013
0
      *info.pCPathLenConstraint = tbs->pathLenConstraint;
2014
0
  }
2015
2016
0
  ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
2017
0
         &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
0
  }
2023
2024
0
  ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
2025
0
         &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
0
  }
2031
0
  if (size != data.length)
2032
0
      _hx509_abort("internal ASN.1 encoder error");
2033
0
  ret = add_extension(context, tbsc, 0,
2034
0
          &asn1_oid_id_pkix_pe_proxyCertInfo,
2035
0
          &data);
2036
0
  free(data.data);
2037
0
  if (ret)
2038
0
      goto out;
2039
0
    }
2040
2041
    /* Add CRL distribution point */
2042
0
    if (tbs->crldp.len) {
2043
0
  ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
2044
0
         &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
0
  }
2049
0
  if (size != data.length)
2050
0
      _hx509_abort("internal ASN.1 encoder error");
2051
0
  ret = add_extension(context, tbsc, FALSE,
2052
0
          &asn1_oid_id_x509_ce_cRLDistributionPoints,
2053
0
          &data);
2054
0
  free(data.data);
2055
0
  if (ret)
2056
0
      goto out;
2057
0
    }
2058
2059
    /* Add CertificatePolicies */
2060
0
    if (tbs->cps.len) {
2061
0
  ASN1_MALLOC_ENCODE(CertificatePolicies, data.data, data.length,
2062
0
         &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
0
  }
2067
0
  if (size != data.length)
2068
0
      _hx509_abort("internal ASN.1 encoder error");
2069
0
        ret = add_extension(context, tbsc, FALSE,
2070
0
                            &asn1_oid_id_x509_ce_certificatePolicies, &data);
2071
0
        free(data.data);
2072
0
  if (ret)
2073
0
      goto out;
2074
0
    }
2075
2076
    /* Add PolicyMappings */
2077
0
    if (tbs->cps.len) {
2078
0
  ASN1_MALLOC_ENCODE(PolicyMappings, data.data, data.length,
2079
0
         &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
0
  }
2084
0
  if (size != data.length)
2085
0
      _hx509_abort("internal ASN.1 encoder error");
2086
0
        ret = add_extension(context, tbsc, FALSE,
2087
0
                            &asn1_oid_id_x509_ce_policyMappings, &data);
2088
0
        free(data.data);
2089
0
  if (ret)
2090
0
      goto out;
2091
0
    }
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
0
                           &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
0
  }
2101
0
  if (size != data.length)
2102
0
      _hx509_abort("internal ASN.1 encoder error");
2103
0
        ret = add_extension(context, tbsc, FALSE,
2104
0
                            &asn1_oid_id_heim_ce_pkinit_princ_max_life, &data);
2105
0
        free(data.data);
2106
0
  if (ret)
2107
0
      goto out;
2108
0
    }
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
0
    }
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
0
              signer,
2120
0
              sigalg,
2121
0
              &data,
2122
0
              &c.signatureAlgorithm,
2123
0
              &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
0
    }
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
0
}
2143
2144
static int
2145
get_AuthorityKeyIdentifier(hx509_context context,
2146
         const Certificate *certificate,
2147
         AuthorityKeyIdentifier *ai)
2148
0
{
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
0
  }
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
0
  }
2167
0
    } 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
0
  }
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
0
  }
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
0
  }
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
0
  }
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
0
            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
0
  }
2224
0
    }
2225
0
out:
2226
0
    if (ret)
2227
0
  free_AuthorityKeyIdentifier(ai);
2228
0
    return ret;
2229
0
}
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
hx509_ca_sign(hx509_context context,
2258
        hx509_ca_tbs tbs,
2259
        hx509_cert signer,
2260
        hx509_cert *certificate)
2261
0
{
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
0
      tbs,
2276
0
      _hx509_cert_private_key(signer),
2277
0
      &ai,
2278
0
      &signer_cert->tbsCertificate.subject,
2279
0
      certificate);
2280
2281
0
out:
2282
0
    free_AuthorityKeyIdentifier(&ai);
2283
2284
0
    return ret;
2285
0
}
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
hx509_ca_sign_self(hx509_context context,
2302
       hx509_ca_tbs tbs,
2303
       hx509_private_key signer,
2304
       hx509_cert *certificate)
2305
0
{
2306
0
    return ca_sign(context,
2307
0
       tbs,
2308
0
       signer,
2309
0
       NULL,
2310
0
       NULL,
2311
0
       certificate);
2312
0
}
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
0
#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
0
#define princ_ncomp(P, N) ((P)->principalName.name_string.val[(N)])
2326
0
#define princ_realm(P) ((P)->realm)
2327
2328
static const char *
2329
princ_get_comp_string(KRB5PrincipalName *principal, unsigned int component)
2330
0
{
2331
0
    if (component >= princ_num_comp(principal))
2332
0
       return NULL;
2333
0
    return princ_ncomp(principal, component);
2334
0
}
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
frees(char **s)
2346
0
{
2347
0
    free(*s);
2348
0
    *s = NULL;
2349
0
}
2350
2351
static heim_error_code
2352
count_sans(hx509_request req, size_t *n)
2353
0
{
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
0
        case HX509_SAN_TYPE_EMAIL:
2368
0
        case HX509_SAN_TYPE_XMPP:
2369
0
        case HX509_SAN_TYPE_PKINIT:
2370
0
        case HX509_SAN_TYPE_MS_UPN:
2371
0
            (*n)++;
2372
0
            break;
2373
0
        default:
2374
0
            ret = ENOTSUP;
2375
0
        }
2376
0
        frees(&s);
2377
0
    }
2378
0
    free(s);
2379
0
    return ret == HX509_NO_ITEM ? 0 : ret;
2380
0
}
2381
2382
static int
2383
has_sans(hx509_request req)
2384
0
{
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
0
}
2392
2393
static cert_type
2394
characterize_cprinc(hx509_context context,
2395
                    KRB5PrincipalName *cprinc)
2396
0
{
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
0
    }
2414
0
}
2415
2416
/* Characterize request as client or server cert req */
2417
static cert_type
2418
characterize(hx509_context context,
2419
             KRB5PrincipalName *cprinc,
2420
             hx509_request req)
2421
0
{
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
0
        else
2456
0
            res |= CERT_SERVER;
2457
0
        der_free_oid(&oid);
2458
0
    }
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
0
        case HX509_SAN_TYPE_XMPP:
2477
0
        case HX509_SAN_TYPE_PKINIT:
2478
0
        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
0
        }
2485
0
        if (ret)
2486
0
            break;
2487
0
    }
2488
0
    frees(&s);
2489
0
    if (ret == HX509_NO_ITEM)
2490
0
        ret = 0;
2491
0
    return ret ? CERT_NOTSUP : res;
2492
0
}
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
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
0
{
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
0
                     "Client principal has no components!");
2530
0
        hx509_set_error_string(context, 0, ret = ENOTSUP,
2531
0
                               "Client principal has no components!");
2532
0
        return ret;
2533
0
    }
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
0
                     "Could not characterize CSR");
2539
0
        hx509_set_error_string(context, 0, ret, "Could not characterize CSR");
2540
0
        return ret;
2541
0
    }
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
0
                                   "Requested SAN/EKU combination not "
2553
0
                                   "supported");
2554
0
            return ret;
2555
0
        }
2556
0
    } 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
0
        } else {
2569
0
            label = "other";
2570
0
        }
2571
0
    }
2572
2573
0
    *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL);
2574
0
    if (*out) {
2575
0
        ret = 0;
2576
0
    } else {
2577
0
        heim_log_msg(context->hcontext, logf, 3, NULL,
2578
0
                     "No configuration for %s %s certificate's realm "
2579
0
                     "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2580
0
                     svc ? " -> " : "", svc ? svc : "");
2581
0
        hx509_set_error_string(context, 0, EACCES,
2582
0
                "No configuration for %s %s certificate's realm "
2583
0
                "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2584
0
                svc ? " -> " : "", svc ? svc : "");
2585
0
    }
2586
0
    return ret;
2587
0
}
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
set_template(hx509_context context,
2604
             heim_log_facility *logf,
2605
             const heim_config_binding *cf,
2606
             hx509_ca_tbs tbs)
2607
0
{
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
0
                                           "template_cert", NULL);
2618
0
    subj_name = heim_config_get_string(context->hcontext, cf, "subject_name",
2619
0
                                       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
0
                         "Failed to load certificate template from %s",
2632
0
                         cert_template);
2633
0
            hx509_set_error_string(context, 0, EACCES,
2634
0
                                   "Failed to load certificate template from "
2635
0
                                   "%s", cert_template);
2636
0
            return ret;
2637
0
        }
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
0
                                        HX509_CA_TEMPLATE_SUBJECT |
2645
0
                                        HX509_CA_TEMPLATE_KU |
2646
0
                                        HX509_CA_TEMPLATE_EKU,
2647
0
                                        template);
2648
0
        hx509_cert_free(template);
2649
0
        if (ret)
2650
0
            return ret;
2651
0
    }
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
0
    }
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
0
    }
2674
2675
0
    ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL);
2676
0
    if (ekus) {
2677
0
        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
0
        }
2686
0
        heim_config_free_strings(ekus);
2687
0
    }
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
0
}
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
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
0
{
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
0
    }
2740
0
    strpool = NULL;
2741
0
    ret = hx509_env_add(context, env, "principal-name-without-realm",
2742
0
                        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
0
                            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
0
                                     "include_pkinit_san", NULL)) {
2774
0
        ret = hx509_ca_tbs_add_san_pkinit(context, tbs, princ);
2775
0
    }
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
0
                            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
0
                                                   "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
0
        }
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
0
                                    comp1);
2823
0
            if (ret == 0 && ncomp == 3)
2824
0
                ret = hx509_env_add(context, env, "principal-domain-name",
2825
0
                                    comp2);
2826
0
            if (ret == 0 && !has_sans(req) &&
2827
0
                heim_config_get_bool_default(context->hcontext, cf, FALSE,
2828
0
                                             "include_dnsname_san", NULL)) {
2829
0
                ret = hx509_ca_tbs_add_san_hostname(context, tbs, comp1);
2830
0
            }
2831
0
        }
2832
0
    } else {
2833
0
        heim_log_msg(context->hcontext, logf, 5, NULL,
2834
0
                     "kx509/bx509 client %s has too many components!", princ);
2835
0
        hx509_set_error_string(context, 0, ret = EACCES,
2836
0
                               "kx509/bx509 client %s has too many "
2837
0
                               "components!", princ);
2838
0
    }
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
0
                 "Could not set up TBSCertificate: Out of memory");
2850
0
    ret = hx509_enomem(context);
2851
0
    goto out;
2852
0
}
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
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
0
{
2879
0
    time_t now = time(NULL);
2880
0
    time_t force = heim_config_get_time_default(context->hcontext,
2881
0
                                                cf, 5 * 24 * 3600,
2882
0
                                                "force_cert_lifetime", NULL);
2883
0
    time_t clamp = heim_config_get_time_default(context->hcontext, cf, 0,
2884
0
                                                "max_cert_lifetime", NULL);
2885
0
    int allow_more = heim_config_get_bool_default(context->hcontext, cf, FALSE,
2886
0
                                                  "allow_extra_lifetime",
2887
0
                                                  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
0
                     "Endtime is in the past");
2893
0
        hx509_set_error_string(context, 0, ERANGE, "Endtime is in the past");
2894
0
        return ERANGE;
2895
0
    }
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
0
}
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
_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
0
{
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
0
                                     "ca", NULL)) == NULL) {
2954
0
        heim_log_msg(context->hcontext, logf, 3, NULL,
2955
0
                     "No kx509 CA issuer credential specified");
2956
0
        hx509_set_error_string(context, 0, ret = EACCES,
2957
0
                               "No kx509 CA issuer credential specified");
2958
0
        return ret;
2959
0
    }
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
0
                     "Failed to create certificate: Out of memory");
2965
0
        return ret;
2966
0
    }
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
0
                     "Not issuing certificate because it would have no names");
2985
0
        hx509_set_error_string(context, 0, ret = EACCES,
2986
0
                               "Not issuing certificate because it "
2987
0
                               "would have no names");
2988
0
    }
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
0
    {
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
0
                         "Failed to load CA certificate and private key %s",
3011
0
                         ca);
3012
0
            hx509_set_error_string(context, 0, ret, "Failed to load "
3013
0
                                   "CA certificate and private key %s", ca);
3014
0
            goto out;
3015
0
        }
3016
0
        ret = hx509_query_alloc(context, &q);
3017
0
        if (ret) {
3018
0
            hx509_certs_free(&certs);
3019
0
            goto out;
3020
0
        }
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
0
                         "Failed to find a CA certificate in %s", ca);
3031
0
            hx509_set_error_string(context, 0, ret,
3032
0
                                   "Failed to find a CA certificate in %s",
3033
0
                                   ca);
3034
0
            goto out;
3035
0
        }
3036
0
    }
3037
3038
    /* Populate the subject public key in the TBS context */
3039
0
    {
3040
0
        SubjectPublicKeyInfo spki;
3041
3042
0
        ret = hx509_request_get_SubjectPublicKeyInfo(context,
3043
0
                                                     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
0
    }
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
0
                            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
0
                               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
0
                               HX509_CERTS_NO_PRIVATE_KEYS, NULL, &chain);
3082
0
        if (ret == 0)
3083
0
            ret = hx509_certs_merge(context, *out, chain);
3084
0
    }
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
0
}