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