~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/hx509/ca.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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