Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hx509/ks_p12.c
34878 views
1
/*
2
* Copyright (c) 2004 - 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
36
struct ks_pkcs12 {
37
hx509_certs certs;
38
char *fn;
39
};
40
41
typedef int (*collector_func)(hx509_context,
42
struct hx509_collector *,
43
const void *, size_t,
44
const PKCS12_Attributes *);
45
46
struct type {
47
const heim_oid *oid;
48
collector_func func;
49
};
50
51
static void
52
parse_pkcs12_type(hx509_context, struct hx509_collector *, const heim_oid *,
53
const void *, size_t, const PKCS12_Attributes *);
54
55
56
static const PKCS12_Attribute *
57
find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid)
58
{
59
size_t i;
60
if (attrs == NULL)
61
return NULL;
62
for (i = 0; i < attrs->len; i++)
63
if (der_heim_oid_cmp(oid, &attrs->val[i].attrId) == 0)
64
return &attrs->val[i];
65
return NULL;
66
}
67
68
static int
69
keyBag_parser(hx509_context context,
70
struct hx509_collector *c,
71
const void *data, size_t length,
72
const PKCS12_Attributes *attrs)
73
{
74
const PKCS12_Attribute *attr;
75
PKCS8PrivateKeyInfo ki;
76
const heim_octet_string *os = NULL;
77
int ret;
78
79
attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId);
80
if (attr)
81
os = &attr->attrValues;
82
83
ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
84
if (ret)
85
return ret;
86
87
_hx509_collector_private_key_add(context,
88
c,
89
&ki.privateKeyAlgorithm,
90
NULL,
91
&ki.privateKey,
92
os);
93
free_PKCS8PrivateKeyInfo(&ki);
94
return 0;
95
}
96
97
static int
98
ShroudedKeyBag_parser(hx509_context context,
99
struct hx509_collector *c,
100
const void *data, size_t length,
101
const PKCS12_Attributes *attrs)
102
{
103
PKCS8EncryptedPrivateKeyInfo pk;
104
heim_octet_string content;
105
int ret;
106
107
memset(&pk, 0, sizeof(pk));
108
109
ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL);
110
if (ret)
111
return ret;
112
113
ret = _hx509_pbe_decrypt(context,
114
_hx509_collector_get_lock(c),
115
&pk.encryptionAlgorithm,
116
&pk.encryptedData,
117
&content);
118
free_PKCS8EncryptedPrivateKeyInfo(&pk);
119
if (ret)
120
return ret;
121
122
ret = keyBag_parser(context, c, content.data, content.length, attrs);
123
der_free_octet_string(&content);
124
return ret;
125
}
126
127
static int
128
certBag_parser(hx509_context context,
129
struct hx509_collector *c,
130
const void *data, size_t length,
131
const PKCS12_Attributes *attrs)
132
{
133
heim_octet_string os;
134
hx509_cert cert;
135
PKCS12_CertBag cb;
136
int ret;
137
138
ret = decode_PKCS12_CertBag(data, length, &cb, NULL);
139
if (ret)
140
return ret;
141
142
if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) {
143
free_PKCS12_CertBag(&cb);
144
return 0;
145
}
146
147
ret = decode_PKCS12_OctetString(cb.certValue.data,
148
cb.certValue.length,
149
&os,
150
NULL);
151
free_PKCS12_CertBag(&cb);
152
if (ret)
153
return ret;
154
155
ret = hx509_cert_init_data(context, os.data, os.length, &cert);
156
der_free_octet_string(&os);
157
if (ret)
158
return ret;
159
160
ret = _hx509_collector_certs_add(context, c, cert);
161
if (ret) {
162
hx509_cert_free(cert);
163
return ret;
164
}
165
166
{
167
const PKCS12_Attribute *attr;
168
const heim_oid *oids[] = {
169
&asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName
170
};
171
size_t i;
172
173
for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) {
174
const heim_oid *oid = oids[i];
175
attr = find_attribute(attrs, oid);
176
if (attr)
177
_hx509_set_cert_attribute(context, cert, oid,
178
&attr->attrValues);
179
}
180
}
181
182
hx509_cert_free(cert);
183
184
return 0;
185
}
186
187
static int
188
parse_safe_content(hx509_context context,
189
struct hx509_collector *c,
190
const unsigned char *p, size_t len)
191
{
192
PKCS12_SafeContents sc;
193
int ret;
194
size_t i;
195
196
memset(&sc, 0, sizeof(sc));
197
198
ret = decode_PKCS12_SafeContents(p, len, &sc, NULL);
199
if (ret)
200
return ret;
201
202
for (i = 0; i < sc.len ; i++)
203
parse_pkcs12_type(context,
204
c,
205
&sc.val[i].bagId,
206
sc.val[i].bagValue.data,
207
sc.val[i].bagValue.length,
208
sc.val[i].bagAttributes);
209
210
free_PKCS12_SafeContents(&sc);
211
return 0;
212
}
213
214
static int
215
safeContent_parser(hx509_context context,
216
struct hx509_collector *c,
217
const void *data, size_t length,
218
const PKCS12_Attributes *attrs)
219
{
220
heim_octet_string os;
221
int ret;
222
223
ret = decode_PKCS12_OctetString(data, length, &os, NULL);
224
if (ret)
225
return ret;
226
ret = parse_safe_content(context, c, os.data, os.length);
227
der_free_octet_string(&os);
228
return ret;
229
}
230
231
static int
232
encryptedData_parser(hx509_context context,
233
struct hx509_collector *c,
234
const void *data, size_t length,
235
const PKCS12_Attributes *attrs)
236
{
237
heim_octet_string content;
238
heim_oid contentType;
239
int ret;
240
241
memset(&contentType, 0, sizeof(contentType));
242
243
ret = hx509_cms_decrypt_encrypted(context,
244
_hx509_collector_get_lock(c),
245
data, length,
246
&contentType,
247
&content);
248
if (ret)
249
return ret;
250
251
if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
252
ret = parse_safe_content(context, c, content.data, content.length);
253
254
der_free_octet_string(&content);
255
der_free_oid(&contentType);
256
return ret;
257
}
258
259
static int
260
envelopedData_parser(hx509_context context,
261
struct hx509_collector *c,
262
const void *data, size_t length,
263
const PKCS12_Attributes *attrs)
264
{
265
heim_octet_string content;
266
heim_oid contentType;
267
hx509_lock lock;
268
int ret;
269
270
memset(&contentType, 0, sizeof(contentType));
271
272
lock = _hx509_collector_get_lock(c);
273
274
ret = hx509_cms_unenvelope(context,
275
_hx509_lock_unlock_certs(lock),
276
0,
277
data, length,
278
NULL,
279
0,
280
&contentType,
281
&content);
282
if (ret) {
283
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
284
"PKCS12 failed to unenvelope");
285
return ret;
286
}
287
288
if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
289
ret = parse_safe_content(context, c, content.data, content.length);
290
291
der_free_octet_string(&content);
292
der_free_oid(&contentType);
293
294
return ret;
295
}
296
297
298
struct type bagtypes[] = {
299
{ &asn1_oid_id_pkcs12_keyBag, keyBag_parser },
300
{ &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
301
{ &asn1_oid_id_pkcs12_certBag, certBag_parser },
302
{ &asn1_oid_id_pkcs7_data, safeContent_parser },
303
{ &asn1_oid_id_pkcs7_encryptedData, encryptedData_parser },
304
{ &asn1_oid_id_pkcs7_envelopedData, envelopedData_parser }
305
};
306
307
static void
308
parse_pkcs12_type(hx509_context context,
309
struct hx509_collector *c,
310
const heim_oid *oid,
311
const void *data, size_t length,
312
const PKCS12_Attributes *attrs)
313
{
314
size_t i;
315
316
for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++)
317
if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0)
318
(*bagtypes[i].func)(context, c, data, length, attrs);
319
}
320
321
static int
322
p12_init(hx509_context context,
323
hx509_certs certs, void **data, int flags,
324
const char *residue, hx509_lock lock)
325
{
326
struct ks_pkcs12 *p12;
327
size_t len;
328
void *buf;
329
PKCS12_PFX pfx;
330
PKCS12_AuthenticatedSafe as;
331
int ret;
332
size_t i;
333
struct hx509_collector *c;
334
335
*data = NULL;
336
337
if (lock == NULL)
338
lock = _hx509_empty_lock;
339
340
ret = _hx509_collector_alloc(context, lock, &c);
341
if (ret)
342
return ret;
343
344
p12 = calloc(1, sizeof(*p12));
345
if (p12 == NULL) {
346
ret = ENOMEM;
347
hx509_set_error_string(context, 0, ret, "out of memory");
348
goto out;
349
}
350
351
p12->fn = strdup(residue);
352
if (p12->fn == NULL) {
353
ret = ENOMEM;
354
hx509_set_error_string(context, 0, ret, "out of memory");
355
goto out;
356
}
357
358
if (flags & HX509_CERTS_CREATE) {
359
ret = hx509_certs_init(context, "MEMORY:ks-file-create",
360
0, lock, &p12->certs);
361
if (ret == 0)
362
*data = p12;
363
goto out;
364
}
365
366
ret = rk_undumpdata(residue, &buf, &len);
367
if (ret) {
368
hx509_clear_error_string(context);
369
goto out;
370
}
371
372
ret = decode_PKCS12_PFX(buf, len, &pfx, NULL);
373
rk_xfree(buf);
374
if (ret) {
375
hx509_set_error_string(context, 0, ret,
376
"Failed to decode the PFX in %s", residue);
377
goto out;
378
}
379
380
if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) {
381
free_PKCS12_PFX(&pfx);
382
ret = EINVAL;
383
hx509_set_error_string(context, 0, ret,
384
"PKCS PFX isn't a pkcs7-data container");
385
goto out;
386
}
387
388
if (pfx.authSafe.content == NULL) {
389
free_PKCS12_PFX(&pfx);
390
ret = EINVAL;
391
hx509_set_error_string(context, 0, ret,
392
"PKCS PFX missing data");
393
goto out;
394
}
395
396
{
397
heim_octet_string asdata;
398
399
ret = decode_PKCS12_OctetString(pfx.authSafe.content->data,
400
pfx.authSafe.content->length,
401
&asdata,
402
NULL);
403
free_PKCS12_PFX(&pfx);
404
if (ret) {
405
hx509_clear_error_string(context);
406
goto out;
407
}
408
ret = decode_PKCS12_AuthenticatedSafe(asdata.data,
409
asdata.length,
410
&as,
411
NULL);
412
der_free_octet_string(&asdata);
413
if (ret) {
414
hx509_clear_error_string(context);
415
goto out;
416
}
417
}
418
419
for (i = 0; i < as.len; i++)
420
parse_pkcs12_type(context,
421
c,
422
&as.val[i].contentType,
423
as.val[i].content->data,
424
as.val[i].content->length,
425
NULL);
426
427
free_PKCS12_AuthenticatedSafe(&as);
428
429
ret = _hx509_collector_collect_certs(context, c, &p12->certs);
430
if (ret == 0)
431
*data = p12;
432
433
out:
434
_hx509_collector_free(c);
435
436
if (ret && p12) {
437
if (p12->fn)
438
free(p12->fn);
439
if (p12->certs)
440
hx509_certs_free(&p12->certs);
441
free(p12);
442
}
443
444
return ret;
445
}
446
447
static int
448
addBag(hx509_context context,
449
PKCS12_AuthenticatedSafe *as,
450
const heim_oid *oid,
451
void *data,
452
size_t length)
453
{
454
void *ptr;
455
int ret;
456
457
ptr = realloc(as->val, sizeof(as->val[0]) * (as->len + 1));
458
if (ptr == NULL) {
459
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
460
return ENOMEM;
461
}
462
as->val = ptr;
463
464
ret = der_copy_oid(oid, &as->val[as->len].contentType);
465
if (ret) {
466
hx509_set_error_string(context, 0, ret, "out of memory");
467
return ret;
468
}
469
470
as->val[as->len].content = calloc(1, sizeof(*as->val[0].content));
471
if (as->val[as->len].content == NULL) {
472
der_free_oid(&as->val[as->len].contentType);
473
hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory");
474
return ENOMEM;
475
}
476
477
as->val[as->len].content->data = data;
478
as->val[as->len].content->length = length;
479
480
as->len++;
481
482
return 0;
483
}
484
485
static int
486
store_func(hx509_context context, void *ctx, hx509_cert c)
487
{
488
PKCS12_AuthenticatedSafe *as = ctx;
489
PKCS12_OctetString os;
490
PKCS12_CertBag cb;
491
size_t size;
492
int ret;
493
494
memset(&os, 0, sizeof(os));
495
memset(&cb, 0, sizeof(cb));
496
497
os.data = NULL;
498
os.length = 0;
499
500
ret = hx509_cert_binary(context, c, &os);
501
if (ret)
502
return ret;
503
504
ASN1_MALLOC_ENCODE(PKCS12_OctetString,
505
cb.certValue.data,cb.certValue.length,
506
&os, &size, ret);
507
free(os.data);
508
if (ret)
509
goto out;
510
ret = der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType);
511
if (ret) {
512
free_PKCS12_CertBag(&cb);
513
goto out;
514
}
515
ASN1_MALLOC_ENCODE(PKCS12_CertBag, os.data, os.length,
516
&cb, &size, ret);
517
free_PKCS12_CertBag(&cb);
518
if (ret)
519
goto out;
520
521
ret = addBag(context, as, &asn1_oid_id_pkcs12_certBag, os.data, os.length);
522
523
if (_hx509_cert_private_key_exportable(c)) {
524
hx509_private_key key = _hx509_cert_private_key(c);
525
PKCS8PrivateKeyInfo pki;
526
527
memset(&pki, 0, sizeof(pki));
528
529
ret = der_parse_hex_heim_integer("00", &pki.version);
530
if (ret)
531
return ret;
532
ret = _hx509_private_key_oid(context, key,
533
&pki.privateKeyAlgorithm.algorithm);
534
if (ret) {
535
free_PKCS8PrivateKeyInfo(&pki);
536
return ret;
537
}
538
ret = _hx509_private_key_export(context,
539
_hx509_cert_private_key(c),
540
HX509_KEY_FORMAT_DER,
541
&pki.privateKey);
542
if (ret) {
543
free_PKCS8PrivateKeyInfo(&pki);
544
return ret;
545
}
546
/* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */
547
548
ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length,
549
&pki, &size, ret);
550
free_PKCS8PrivateKeyInfo(&pki);
551
if (ret)
552
return ret;
553
554
ret = addBag(context, as, &asn1_oid_id_pkcs12_keyBag, os.data, os.length);
555
if (ret)
556
return ret;
557
}
558
559
out:
560
return ret;
561
}
562
563
static int
564
p12_store(hx509_context context,
565
hx509_certs certs, void *data, int flags, hx509_lock lock)
566
{
567
struct ks_pkcs12 *p12 = data;
568
PKCS12_PFX pfx;
569
PKCS12_AuthenticatedSafe as;
570
PKCS12_OctetString asdata;
571
size_t size;
572
int ret;
573
574
memset(&as, 0, sizeof(as));
575
memset(&pfx, 0, sizeof(pfx));
576
577
ret = hx509_certs_iter_f(context, p12->certs, store_func, &as);
578
if (ret)
579
goto out;
580
581
ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length,
582
&as, &size, ret);
583
free_PKCS12_AuthenticatedSafe(&as);
584
if (ret)
585
return ret;
586
587
ret = der_parse_hex_heim_integer("03", &pfx.version);
588
if (ret) {
589
free(asdata.data);
590
goto out;
591
}
592
593
pfx.authSafe.content = calloc(1, sizeof(*pfx.authSafe.content));
594
595
ASN1_MALLOC_ENCODE(PKCS12_OctetString,
596
pfx.authSafe.content->data,
597
pfx.authSafe.content->length,
598
&asdata, &size, ret);
599
free(asdata.data);
600
if (ret)
601
goto out;
602
603
ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType);
604
if (ret)
605
goto out;
606
607
ASN1_MALLOC_ENCODE(PKCS12_PFX, asdata.data, asdata.length,
608
&pfx, &size, ret);
609
if (ret)
610
goto out;
611
612
#if 0
613
const struct _hx509_password *pw;
614
615
pw = _hx509_lock_get_passwords(lock);
616
if (pw != NULL) {
617
pfx.macData = calloc(1, sizeof(*pfx.macData));
618
if (pfx.macData == NULL) {
619
ret = ENOMEM;
620
hx509_set_error_string(context, 0, ret, "malloc out of memory");
621
return ret;
622
}
623
if (pfx.macData == NULL) {
624
free(asdata.data);
625
goto out;
626
}
627
}
628
ret = calculate_hash(&aspath, pw, pfx.macData);
629
#endif
630
631
rk_dumpdata(p12->fn, asdata.data, asdata.length);
632
free(asdata.data);
633
634
out:
635
free_PKCS12_AuthenticatedSafe(&as);
636
free_PKCS12_PFX(&pfx);
637
638
return ret;
639
}
640
641
642
static int
643
p12_free(hx509_certs certs, void *data)
644
{
645
struct ks_pkcs12 *p12 = data;
646
hx509_certs_free(&p12->certs);
647
free(p12->fn);
648
free(p12);
649
return 0;
650
}
651
652
static int
653
p12_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
654
{
655
struct ks_pkcs12 *p12 = data;
656
return hx509_certs_add(context, p12->certs, c);
657
}
658
659
static int
660
p12_iter_start(hx509_context context,
661
hx509_certs certs,
662
void *data,
663
void **cursor)
664
{
665
struct ks_pkcs12 *p12 = data;
666
return hx509_certs_start_seq(context, p12->certs, cursor);
667
}
668
669
static int
670
p12_iter(hx509_context context,
671
hx509_certs certs,
672
void *data,
673
void *cursor,
674
hx509_cert *cert)
675
{
676
struct ks_pkcs12 *p12 = data;
677
return hx509_certs_next_cert(context, p12->certs, cursor, cert);
678
}
679
680
static int
681
p12_iter_end(hx509_context context,
682
hx509_certs certs,
683
void *data,
684
void *cursor)
685
{
686
struct ks_pkcs12 *p12 = data;
687
return hx509_certs_end_seq(context, p12->certs, cursor);
688
}
689
690
static struct hx509_keyset_ops keyset_pkcs12 = {
691
"PKCS12",
692
0,
693
p12_init,
694
p12_store,
695
p12_free,
696
p12_add,
697
NULL,
698
p12_iter_start,
699
p12_iter,
700
p12_iter_end
701
};
702
703
void
704
_hx509_ks_pkcs12_register(hx509_context context)
705
{
706
_hx509_ks_register(context, &keyset_pkcs12);
707
}
708
709