aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/https/x509/pkcs12.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/https/x509/pkcs12.c')
-rw-r--r--src/daemon/https/x509/pkcs12.c1309
1 files changed, 0 insertions, 1309 deletions
diff --git a/src/daemon/https/x509/pkcs12.c b/src/daemon/https/x509/pkcs12.c
deleted file mode 100644
index af069e0d..00000000
--- a/src/daemon/https/x509/pkcs12.c
+++ /dev/null
@@ -1,1309 +0,0 @@
1/*
2 * Copyright (C) 2003, 2004, 2005 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS.
7 *
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
22 *
23 */
24
25/* Functions that relate on PKCS12 packet parsing.
26 */
27
28#include <gnutls_int.h>
29#include <libtasn1.h>
30
31#ifdef ENABLE_PKI
32
33#include <gnutls_datum.h>
34#include <gnutls_global.h>
35#include <gnutls_errors.h>
36#include <gnutls_num.h>
37#include <common.h>
38#include <x509_b64.h>
39#include <pkcs12.h>
40#include <dn.h>
41#include <mpi.h>
42#include <gc.h>
43
44
45/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
46 * which holds them. Returns an ASN1_TYPE of authenticatedSafe.
47 */
48static int
49_decodeMHD_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
50 MHD_gnutls_datum_t * raw)
51{
52 char oid[128];
53 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
54 MHD_gnutls_datum_t auth_safe = { NULL, 0 };
55 int tmp_size, len, result;
56
57 len = sizeof (oid) - 1;
58 result = MHD__asn1_read_value (pkcs12, "authSafe.contentType", oid, &len);
59 if (result != ASN1_SUCCESS)
60 {
61 MHD_gnutls_assert ();
62 return MHD_gtls_asn2err (result);
63 }
64
65 if (strcmp (oid, DATA_OID) != 0)
66 {
67 MHD_gnutls_assert ();
68 MHD__gnutls_x509_log ("Unknown PKCS12 Content OID '%s'\n", oid);
69 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
70 }
71
72 /* Step 1. Read the content data
73 */
74
75 tmp_size = 0;
76 result =
77 MHD__gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1);
78 if (result < 0)
79 {
80 MHD_gnutls_assert ();
81 goto cleanup;
82 }
83
84 /* Step 2. Extract the authenticatedSafe.
85 */
86
87 if ((result = MHD__asn1_create_element
88 (MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
89 &c2)) != ASN1_SUCCESS)
90 {
91 MHD_gnutls_assert ();
92 result = MHD_gtls_asn2err (result);
93 goto cleanup;
94 }
95
96 result = MHD__asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, NULL);
97 if (result != ASN1_SUCCESS)
98 {
99 MHD_gnutls_assert ();
100 result = MHD_gtls_asn2err (result);
101 goto cleanup;
102 }
103
104 if (raw == NULL)
105 {
106 MHD__gnutls_free_datum (&auth_safe);
107 }
108 else
109 {
110 raw->data = auth_safe.data;
111 raw->size = auth_safe.size;
112 }
113
114 if (authen_safe)
115 *authen_safe = c2;
116 else
117 MHD__asn1_delete_structure (&c2);
118
119 return 0;
120
121cleanup:
122 if (c2)
123 MHD__asn1_delete_structure (&c2);
124 MHD__gnutls_free_datum (&auth_safe);
125 return result;
126}
127
128/**
129 * MHD_gnutlsMHD_pkcs12_init - This function initializes a MHD_gnutlsMHD_pkcs12_t structure
130 * @pkcs12: The structure to be initialized
131 *
132 * This function will initialize a PKCS12 structure. PKCS12 structures
133 * usually contain lists of X.509 Certificates and X.509 Certificate
134 * revocation lists.
135 *
136 * Returns 0 on success.
137 *
138 **/
139int
140MHD_gnutlsMHD_pkcs12_init (MHD_gnutlsMHD_pkcs12_t * pkcs12)
141{
142 *pkcs12 = MHD_gnutls_calloc (1, sizeof (MHD_gnutlsMHD_pkcs12_int));
143
144 if (*pkcs12)
145 {
146 int result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
147 "PKIX1.pkcs-12-PFX",
148 &(*pkcs12)->pkcs12);
149 if (result != ASN1_SUCCESS)
150 {
151 MHD_gnutls_assert ();
152 MHD_gnutls_free (*pkcs12);
153 return MHD_gtls_asn2err (result);
154 }
155 return 0; /* success */
156 }
157 return GNUTLS_E_MEMORY_ERROR;
158}
159
160/**
161 * MHD_gnutlsMHD_pkcs12_deinit - This function deinitializes memory used by a MHD_gnutlsMHD_pkcs12_t structure
162 * @pkcs12: The structure to be initialized
163 *
164 * This function will deinitialize a PKCS12 structure.
165 *
166 **/
167void
168MHD_gnutlsMHD_pkcs12_deinit (MHD_gnutlsMHD_pkcs12_t pkcs12)
169{
170 if (!pkcs12)
171 return;
172
173 if (pkcs12->pkcs12)
174 MHD__asn1_delete_structure (&pkcs12->pkcs12);
175
176 MHD_gnutls_free (pkcs12);
177}
178
179/**
180 * MHD_gnutlsMHD_pkcs12_import - This function will import a DER or PEM encoded PKCS12 structure
181 * @pkcs12: The structure to store the parsed PKCS12.
182 * @data: The DER or PEM encoded PKCS12.
183 * @format: One of DER or PEM
184 * @flags: an ORed sequence of MHD_gnutls_privkey_pkcs8_flags
185 *
186 * This function will convert the given DER or PEM encoded PKCS12
187 * to the native MHD_gnutlsMHD_pkcs12_t format. The output will be stored in 'pkcs12'.
188 *
189 * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
190 *
191 * Returns 0 on success.
192 *
193 **/
194int
195MHD_gnutlsMHD_pkcs12_import (MHD_gnutlsMHD_pkcs12_t pkcs12,
196 const MHD_gnutls_datum_t * data,
197 MHD_gnutls_x509_crt_fmt_t format, unsigned int flags)
198{
199 int result = 0, need_free = 0;
200 MHD_gnutls_datum_t _data;
201
202 _data.data = data->data;
203 _data.size = data->size;
204
205 if (pkcs12 == NULL)
206 {
207 MHD_gnutls_assert ();
208 return GNUTLS_E_INVALID_REQUEST;
209 }
210
211 /* If the PKCS12 is in PEM format then decode it
212 */
213 if (format == GNUTLS_X509_FMT_PEM)
214 {
215 opaque *out;
216
217 result = MHD__gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
218 &out);
219
220 if (result <= 0)
221 {
222 if (result == 0)
223 result = GNUTLS_E_INTERNAL_ERROR;
224 MHD_gnutls_assert ();
225 return result;
226 }
227
228 _data.data = out;
229 _data.size = result;
230
231 need_free = 1;
232 }
233
234 result = MHD__asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, NULL);
235 if (result != ASN1_SUCCESS)
236 {
237 result = MHD_gtls_asn2err (result);
238 MHD_gnutls_assert ();
239 goto cleanup;
240 }
241
242 if (need_free)
243 MHD__gnutls_free_datum (&_data);
244
245 return 0;
246
247cleanup:
248 if (need_free)
249 MHD__gnutls_free_datum (&_data);
250 return result;
251}
252
253
254/**
255 * MHD_gnutlsMHD_pkcs12_export - This function will export the pkcs12 structure
256 * @pkcs12: Holds the pkcs12 structure
257 * @format: the format of output params. One of PEM or DER.
258 * @output_data: will contain a structure PEM or DER encoded
259 * @output_data_size: holds the size of output_data (and will be
260 * replaced by the actual size of parameters)
261 *
262 * This function will export the pkcs12 structure to DER or PEM format.
263 *
264 * If the buffer provided is not long enough to hold the output, then
265 * *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
266 * will be returned.
267 *
268 * If the structure is PEM encoded, it will have a header
269 * of "BEGIN PKCS12".
270 *
271 * Return value: In case of failure a negative value will be
272 * returned, and 0 on success.
273 *
274 **/
275int
276MHD_gnutlsMHD_pkcs12_export (MHD_gnutlsMHD_pkcs12_t pkcs12,
277 MHD_gnutls_x509_crt_fmt_t format, void *output_data,
278 size_t * output_data_size)
279{
280 if (pkcs12 == NULL)
281 {
282 MHD_gnutls_assert ();
283 return GNUTLS_E_INVALID_REQUEST;
284 }
285
286 return MHD__gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12,
287 output_data, output_data_size);
288}
289
290static int
291oid2bag (const char *oid)
292{
293 if (strcmp (oid, BAG_PKCS8_KEY) == 0)
294 return GNUTLS_BAG_PKCS8_KEY;
295 if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
296 return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
297 if (strcmp (oid, BAG_CERTIFICATE) == 0)
298 return GNUTLS_BAG_CERTIFICATE;
299 if (strcmp (oid, BAG_CRL) == 0)
300 return GNUTLS_BAG_CRL;
301
302 return GNUTLS_BAG_UNKNOWN;
303}
304
305static const char *
306bag_to_oid (int bag)
307{
308 switch (bag)
309 {
310 case GNUTLS_BAG_PKCS8_KEY:
311 return BAG_PKCS8_KEY;
312 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
313 return BAG_PKCS8_ENCRYPTED_KEY;
314 case GNUTLS_BAG_CERTIFICATE:
315 return BAG_CERTIFICATE;
316 case GNUTLS_BAG_CRL:
317 return BAG_CRL;
318 }
319 return NULL;
320}
321
322static inline char *
323ucs2_to_ascii (char *data, int size)
324{
325 int i, j;
326
327 for (i = 0; i < size / 2; i++)
328 {
329 j = 2 * i + 1;
330 if (isascii (data[j]))
331 data[i] = data[i * 2 + 1];
332 else
333 data[i] = '?';
334 }
335 data[i] = 0;
336
337 return data;
338}
339
340/* Decodes the SafeContents, and puts the output in
341 * the given bag.
342 */
343int
344MHD_pkcs12_decode_safe_contents (const MHD_gnutls_datum_t * content,
345 MHD_gnutlsMHD_pkcs12_bag_t bag)
346{
347 char oid[128], root[MAX_NAME_SIZE];
348 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
349 int len, result;
350 int bag_type;
351 MHD_gnutls_datum_t attr_val;
352 int count = 0, i, attributes, j;
353 size_t size;
354
355 /* Step 1. Extract the SEQUENCE.
356 */
357
358 if ((result = MHD__asn1_create_element
359 (MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
360 &c2)) != ASN1_SUCCESS)
361 {
362 MHD_gnutls_assert ();
363 result = MHD_gtls_asn2err (result);
364 goto cleanup;
365 }
366
367 result = MHD__asn1_der_decoding (&c2, content->data, content->size, NULL);
368 if (result != ASN1_SUCCESS)
369 {
370 MHD_gnutls_assert ();
371 result = MHD_gtls_asn2err (result);
372 goto cleanup;
373 }
374
375 /* Count the number of bags
376 */
377 result = MHD__asn1_number_of_elements (c2, "", &count);
378 if (result != ASN1_SUCCESS)
379 {
380 MHD_gnutls_assert ();
381 result = MHD_gtls_asn2err (result);
382 goto cleanup;
383 }
384
385 bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);
386
387 for (i = 0; i < bag->bag_elements; i++)
388 {
389
390 snprintf (root, sizeof (root), "?%u.bagId", i + 1);
391
392 len = sizeof (oid);
393 result = MHD__asn1_read_value (c2, root, oid, &len);
394 if (result != ASN1_SUCCESS)
395 {
396 MHD_gnutls_assert ();
397 result = MHD_gtls_asn2err (result);
398 goto cleanup;
399 }
400
401 /* Read the Bag type
402 */
403 bag_type = oid2bag (oid);
404
405 if (bag_type < 0)
406 {
407 MHD_gnutls_assert ();
408 goto cleanup;
409 }
410
411 /* Read the Bag Value
412 */
413
414 snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
415
416 result = MHD__gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
417 if (result < 0)
418 {
419 MHD_gnutls_assert ();
420 goto cleanup;
421 }
422
423 if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL)
424 {
425 MHD_gnutls_datum_t tmp = bag->element[i].data;
426
427 result =
428 MHD_pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
429 if (result < 0)
430 {
431 MHD_gnutls_assert ();
432 goto cleanup;
433 }
434
435 MHD__gnutls_free_datum (&tmp);
436 }
437
438 /* read the bag attributes
439 */
440 snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);
441
442 result = MHD__asn1_number_of_elements (c2, root, &attributes);
443 if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
444 {
445 MHD_gnutls_assert ();
446 result = MHD_gtls_asn2err (result);
447 goto cleanup;
448 }
449
450 if (attributes < 0)
451 attributes = 1;
452
453 if (result != ASN1_ELEMENT_NOT_FOUND)
454 for (j = 0; j < attributes; j++)
455 {
456
457 snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
458 j + 1);
459
460 result =
461 MHD__gnutls_x509_decode_and_read_attribute (c2, root, oid,
462 sizeof (oid), &attr_val,
463 1, 0);
464
465 if (result < 0)
466 {
467 MHD_gnutls_assert ();
468 continue; /* continue in case we find some known attributes */
469 }
470
471 if (strcmp (oid, KEY_ID_OID) == 0)
472 {
473 size = attr_val.size;
474
475 result =
476 MHD__gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
477 attr_val.data, &size);
478 attr_val.size = size;
479 if (result < 0)
480 {
481 MHD__gnutls_free_datum (&attr_val);
482 MHD_gnutls_assert ();
483 MHD__gnutls_x509_log
484 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
485 continue;
486 }
487 bag->element[i].local_key_id = attr_val;
488 }
489 else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
490 {
491 size = attr_val.size;
492 result =
493 MHD__gnutls_x509_decode_octet_string ("BMPString",
494 attr_val.data, size,
495 attr_val.data, &size);
496 attr_val.size = size;
497 if (result < 0)
498 {
499 MHD__gnutls_free_datum (&attr_val);
500 MHD_gnutls_assert ();
501 MHD__gnutls_x509_log
502 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
503 continue;
504 }
505 bag->element[i].friendly_name =
506 ucs2_to_ascii (attr_val.data, attr_val.size);
507 }
508 else
509 {
510 MHD__gnutls_free_datum (&attr_val);
511 MHD__gnutls_x509_log
512 ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
513 }
514 }
515
516
517 bag->element[i].type = bag_type;
518
519 }
520
521 MHD__asn1_delete_structure (&c2);
522
523
524 return 0;
525
526cleanup:
527 if (c2)
528 MHD__asn1_delete_structure (&c2);
529 return result;
530
531}
532
533
534static int
535_parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
536 MHD_gnutlsMHD_pkcs12_bag_t bag)
537{
538 MHD_gnutls_datum_t content = { NULL, 0 };
539 int result;
540
541 /* Step 1. Extract the content.
542 */
543
544 result = MHD__gnutls_x509_read_value (sc, sc_name, &content, 1);
545 if (result < 0)
546 {
547 MHD_gnutls_assert ();
548 goto cleanup;
549 }
550
551 result = MHD_pkcs12_decode_safe_contents (&content, bag);
552 if (result < 0)
553 {
554 MHD_gnutls_assert ();
555 goto cleanup;
556 }
557
558 MHD__gnutls_free_datum (&content);
559
560 return 0;
561
562cleanup:
563 MHD__gnutls_free_datum (&content);
564 return result;
565}
566
567
568/**
569 * MHD_gnutlsMHD_pkcs12_get_bag - This function returns a Bag from a PKCS12 structure
570 * @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
571 * @indx: contains the index of the bag to extract
572 * @bag: An initialized bag, where the contents of the bag will be copied
573 *
574 * This function will return a Bag from the PKCS12 structure.
575 * Returns 0 on success.
576 *
577 * After the last Bag has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
578 * will be returned.
579 *
580 **/
581int
582MHD_gnutlsMHD_pkcs12_get_bag (MHD_gnutlsMHD_pkcs12_t pkcs12,
583 int indx, MHD_gnutlsMHD_pkcs12_bag_t bag)
584{
585 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
586 int result, len;
587 char root2[MAX_NAME_SIZE];
588 char oid[128];
589
590 if (pkcs12 == NULL)
591 {
592 MHD_gnutls_assert ();
593 return GNUTLS_E_INVALID_REQUEST;
594 }
595
596 /* Step 1. decode the data.
597 */
598 result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
599 if (result < 0)
600 {
601 MHD_gnutls_assert ();
602 return result;
603 }
604
605 /* Step 2. Parse the AuthenticatedSafe
606 */
607
608 snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
609
610 len = sizeof (oid) - 1;
611 result = MHD__asn1_read_value (c2, root2, oid, &len);
612
613 if (result == ASN1_ELEMENT_NOT_FOUND)
614 {
615 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
616 goto cleanup;
617 }
618
619 if (result != ASN1_SUCCESS)
620 {
621 MHD_gnutls_assert ();
622 result = MHD_gtls_asn2err (result);
623 goto cleanup;
624 }
625
626 /* Not encrypted Bag
627 */
628
629 snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
630
631 if (strcmp (oid, DATA_OID) == 0)
632 {
633 result = _parse_safe_contents (c2, root2, bag);
634 goto cleanup;
635 }
636
637 /* ENC_DATA_OID needs decryption */
638
639 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
640 bag->bag_elements = 1;
641
642 result = MHD__gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
643 if (result < 0)
644 {
645 MHD_gnutls_assert ();
646 goto cleanup;
647 }
648
649 result = 0;
650
651cleanup:
652 if (c2)
653 MHD__asn1_delete_structure (&c2);
654 return result;
655}
656
657/* Creates an empty PFX structure for the PKCS12 structure.
658 */
659static int
660create_empty_pfx (ASN1_TYPE pkcs12)
661{
662 uint8_t three = 3;
663 int result;
664 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
665
666 /* Use version 3
667 */
668 result = MHD__asn1_write_value (pkcs12, "version", &three, 1);
669 if (result != ASN1_SUCCESS)
670 {
671 MHD_gnutls_assert ();
672 result = MHD_gtls_asn2err (result);
673 goto cleanup;
674 }
675
676 /* Write the content type of the data
677 */
678 result = MHD__asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
679 if (result != ASN1_SUCCESS)
680 {
681 MHD_gnutls_assert ();
682 result = MHD_gtls_asn2err (result);
683 goto cleanup;
684 }
685
686 /* Check if the authenticatedSafe content is empty, and encode a
687 * null one in that case.
688 */
689
690 if ((result = MHD__asn1_create_element
691 (MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
692 &c2)) != ASN1_SUCCESS)
693 {
694 MHD_gnutls_assert ();
695 result = MHD_gtls_asn2err (result);
696 goto cleanup;
697 }
698
699 result =
700 MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
701 if (result < 0)
702 {
703 MHD_gnutls_assert ();
704 goto cleanup;
705 }
706 MHD__asn1_delete_structure (&c2);
707
708 return 0;
709
710cleanup:
711 MHD__asn1_delete_structure (&c2);
712 return result;
713
714}
715
716/**
717 * MHD_gnutlsMHD_pkcs12_set_bag - This function inserts a Bag into a PKCS12 structure
718 * @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
719 * @bag: An initialized bag
720 *
721 * This function will insert a Bag into the PKCS12 structure.
722 * Returns 0 on success.
723 *
724 **/
725int
726MHD_gnutlsMHD_pkcs12_set_bag (MHD_gnutlsMHD_pkcs12_t pkcs12, MHD_gnutlsMHD_pkcs12_bag_t bag)
727{
728 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
729 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
730 int result;
731 int enc = 0, dum = 1;
732 char null;
733
734 if (pkcs12 == NULL)
735 {
736 MHD_gnutls_assert ();
737 return GNUTLS_E_INVALID_REQUEST;
738 }
739
740 /* Step 1. Check if the pkcs12 structure is empty. In that
741 * case generate an empty PFX.
742 */
743 result = MHD__asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
744 if (result == ASN1_VALUE_NOT_FOUND)
745 {
746 result = create_empty_pfx (pkcs12->pkcs12);
747 if (result < 0)
748 {
749 MHD_gnutls_assert ();
750 return result;
751 }
752 }
753
754 /* Step 2. decode the authenticatedSafe.
755 */
756 result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
757 if (result < 0)
758 {
759 MHD_gnutls_assert ();
760 return result;
761 }
762
763 /* Step 3. Encode the bag elements into a SafeContents
764 * structure.
765 */
766 result = MHD_pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
767 if (result < 0)
768 {
769 MHD_gnutls_assert ();
770 return result;
771 }
772
773 /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
774 * structure.
775 */
776 result = MHD__asn1_write_value (c2, "", "NEW", 1);
777 if (result != ASN1_SUCCESS)
778 {
779 MHD_gnutls_assert ();
780 result = MHD_gtls_asn2err (result);
781 goto cleanup;
782 }
783
784 if (enc)
785 result = MHD__asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
786 else
787 result = MHD__asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
788 if (result != ASN1_SUCCESS)
789 {
790 MHD_gnutls_assert ();
791 result = MHD_gtls_asn2err (result);
792 goto cleanup;
793 }
794
795 if (enc)
796 {
797 /* Encrypted packets are written directly.
798 */
799 result =
800 MHD__asn1_write_value (c2, "?LAST.content",
801 bag->element[0].data.data,
802 bag->element[0].data.size);
803 if (result != ASN1_SUCCESS)
804 {
805 MHD_gnutls_assert ();
806 result = MHD_gtls_asn2err (result);
807 goto cleanup;
808 }
809 }
810 else
811 {
812 result =
813 MHD__gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
814 "?LAST.content", 1);
815 if (result < 0)
816 {
817 MHD_gnutls_assert ();
818 goto cleanup;
819 }
820 }
821
822 MHD__asn1_delete_structure (&safe_cont);
823
824
825 /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
826 * structure.
827 */
828 result =
829 MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
830 "authSafe.content", 1);
831 if (result < 0)
832 {
833 MHD_gnutls_assert ();
834 goto cleanup;
835 }
836
837 MHD__asn1_delete_structure (&c2);
838
839 return 0;
840
841cleanup:
842 MHD__asn1_delete_structure (&c2);
843 MHD__asn1_delete_structure (&safe_cont);
844 return result;
845}
846
847/**
848 * MHD_gnutlsMHD_pkcs12_generate_mac - This function generates the MAC of the PKCS12 structure
849 * @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
850 * @pass: The password for the MAC
851 *
852 * This function will generate a MAC for the PKCS12 structure.
853 * Returns 0 on success.
854 *
855 **/
856int
857MHD_gnutlsMHD_pkcs12_generate_mac (MHD_gnutlsMHD_pkcs12_t pkcs12, const char *pass)
858{
859 opaque salt[8], key[20];
860 int result;
861 mac_hd_t td1 = NULL;
862 MHD_gnutls_datum_t tmp = { NULL, 0 };
863 opaque sha_mac[20];
864
865 if (pkcs12 == NULL)
866 {
867 MHD_gnutls_assert ();
868 return GNUTLS_E_INVALID_REQUEST;
869 }
870
871 /* Generate the salt.
872 */
873 if (MHD_gc_nonce (salt, sizeof (salt)) != GC_OK)
874 {
875 MHD_gnutls_assert ();
876 return GNUTLS_E_RANDOM_FAILED;
877 }
878
879 /* Write the salt into the structure.
880 */
881 result =
882 MHD__asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
883 if (result != ASN1_SUCCESS)
884 {
885 MHD_gnutls_assert ();
886 result = MHD_gtls_asn2err (result);
887 goto cleanup;
888 }
889
890 /* Generate the key.
891 */
892 result = MHD_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
893 1, pass, sizeof (key), key);
894 if (result < 0)
895 {
896 MHD_gnutls_assert ();
897 goto cleanup;
898 }
899
900 /* Get the data to be MACed
901 */
902 result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
903 if (result < 0)
904 {
905 MHD_gnutls_assert ();
906 goto cleanup;
907 }
908
909 /* MAC the data
910 */
911 td1 = MHD_gtls_MHD_hmac_init (MHD_GNUTLS_MAC_SHA1, key, sizeof (key));
912 if (td1 == GNUTLS_MAC_FAILED)
913 {
914 MHD_gnutls_assert ();
915 result = GNUTLS_E_INTERNAL_ERROR;
916 goto cleanup;
917 }
918
919 MHD_gnutls_hash (td1, tmp.data, tmp.size);
920 MHD__gnutls_free_datum (&tmp);
921
922 MHD_gnutls_MHD_hmac_deinit (td1, sha_mac);
923
924
925 result =
926 MHD__asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
927 sizeof (sha_mac));
928 if (result != ASN1_SUCCESS)
929 {
930 MHD_gnutls_assert ();
931 result = MHD_gtls_asn2err (result);
932 goto cleanup;
933 }
934
935 result =
936 MHD__asn1_write_value (pkcs12->pkcs12,
937 "macData.mac.digestAlgorithm.parameters", NULL, 0);
938 if (result != ASN1_SUCCESS)
939 {
940 MHD_gnutls_assert ();
941 result = MHD_gtls_asn2err (result);
942 goto cleanup;
943 }
944
945 result =
946 MHD__asn1_write_value (pkcs12->pkcs12,
947 "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
948 1);
949 if (result != ASN1_SUCCESS)
950 {
951 MHD_gnutls_assert ();
952 result = MHD_gtls_asn2err (result);
953 goto cleanup;
954 }
955
956 return 0;
957
958cleanup:
959 MHD__gnutls_free_datum (&tmp);
960 return result;
961}
962
963/**
964 * MHD_gnutlsMHD_pkcs12_verify_mac - This function verifies the MAC of the PKCS12 structure
965 * @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
966 * @pass: The password for the MAC
967 *
968 * This function will verify the MAC for the PKCS12 structure.
969 * Returns 0 on success.
970 *
971 **/
972int
973MHD_gnutlsMHD_pkcs12_verify_mac (MHD_gnutlsMHD_pkcs12_t pkcs12, const char *pass)
974{
975 opaque key[20];
976 int result;
977 unsigned int iter;
978 int len;
979 mac_hd_t td1 = NULL;
980 MHD_gnutls_datum_t tmp = { NULL, 0 }, salt =
981 {
982 NULL, 0};
983 opaque sha_mac[20];
984 opaque sha_mac_orig[20];
985
986 if (pkcs12 == NULL)
987 {
988 MHD_gnutls_assert ();
989 return GNUTLS_E_INVALID_REQUEST;
990 }
991
992 /* read the iterations
993 */
994
995 result =
996 MHD__gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
997 if (result < 0)
998 {
999 iter = 1; /* the default */
1000 }
1001
1002
1003 /* Read the salt from the structure.
1004 */
1005 result =
1006 MHD__gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
1007 if (result != ASN1_SUCCESS)
1008 {
1009 MHD_gnutls_assert ();
1010 result = MHD_gtls_asn2err (result);
1011 goto cleanup;
1012 }
1013
1014 /* Generate the key.
1015 */
1016 result = MHD_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
1017 iter, pass, sizeof (key), key);
1018 if (result < 0)
1019 {
1020 MHD_gnutls_assert ();
1021 goto cleanup;
1022 }
1023
1024 MHD__gnutls_free_datum (&salt);
1025
1026 /* Get the data to be MACed
1027 */
1028 result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
1029 if (result < 0)
1030 {
1031 MHD_gnutls_assert ();
1032 goto cleanup;
1033 }
1034
1035 /* MAC the data
1036 */
1037 td1 = MHD_gtls_MHD_hmac_init (MHD_GNUTLS_MAC_SHA1, key, sizeof (key));
1038 if (td1 == GNUTLS_MAC_FAILED)
1039 {
1040 MHD_gnutls_assert ();
1041 result = GNUTLS_E_INTERNAL_ERROR;
1042 goto cleanup;
1043 }
1044
1045 MHD_gnutls_hash (td1, tmp.data, tmp.size);
1046 MHD__gnutls_free_datum (&tmp);
1047
1048 MHD_gnutls_MHD_hmac_deinit (td1, sha_mac);
1049
1050 len = sizeof (sha_mac_orig);
1051 result =
1052 MHD__asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
1053 &len);
1054 if (result != ASN1_SUCCESS)
1055 {
1056 MHD_gnutls_assert ();
1057 result = MHD_gtls_asn2err (result);
1058 goto cleanup;
1059 }
1060
1061 if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
1062 {
1063 MHD_gnutls_assert ();
1064 return GNUTLS_E_MAC_VERIFY_FAILED;
1065 }
1066
1067 return 0;
1068
1069cleanup:
1070 MHD__gnutls_free_datum (&tmp);
1071 MHD__gnutls_free_datum (&salt);
1072 return result;
1073}
1074
1075
1076static int
1077write_attributes (MHD_gnutlsMHD_pkcs12_bag_t bag, int elem,
1078 ASN1_TYPE c2, const char *where)
1079{
1080 int result;
1081 char root[128];
1082
1083 /* If the bag attributes are empty, then write
1084 * nothing to the attribute field.
1085 */
1086 if (bag->element[elem].friendly_name == NULL &&
1087 bag->element[elem].local_key_id.data == NULL)
1088 {
1089 /* no attributes
1090 */
1091 result = MHD__asn1_write_value (c2, where, NULL, 0);
1092 if (result != ASN1_SUCCESS)
1093 {
1094 MHD_gnutls_assert ();
1095 return MHD_gtls_asn2err (result);
1096 }
1097
1098 return 0;
1099 }
1100
1101 if (bag->element[elem].local_key_id.data != NULL)
1102 {
1103
1104 /* Add a new Attribute
1105 */
1106 result = MHD__asn1_write_value (c2, where, "NEW", 1);
1107 if (result != ASN1_SUCCESS)
1108 {
1109 MHD_gnutls_assert ();
1110 return MHD_gtls_asn2err (result);
1111 }
1112
1113 MHD_gtls_str_cpy (root, sizeof (root), where);
1114 MHD_gtls_str_cat (root, sizeof (root), ".?LAST");
1115
1116 result =
1117 MHD__gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
1118 bag->element[elem].
1119 local_key_id.data,
1120 bag->element[elem].
1121 local_key_id.size, 1);
1122 if (result < 0)
1123 {
1124 MHD_gnutls_assert ();
1125 return result;
1126 }
1127 }
1128
1129 if (bag->element[elem].friendly_name != NULL)
1130 {
1131 opaque *name;
1132 int size, i;
1133 const char *p;
1134
1135 /* Add a new Attribute
1136 */
1137 result = MHD__asn1_write_value (c2, where, "NEW", 1);
1138 if (result != ASN1_SUCCESS)
1139 {
1140 MHD_gnutls_assert ();
1141 return MHD_gtls_asn2err (result);
1142 }
1143
1144 /* convert name to BMPString
1145 */
1146 size = strlen (bag->element[elem].friendly_name) * 2;
1147 name = MHD_gnutls_malloc (size);
1148
1149 if (name == NULL)
1150 {
1151 MHD_gnutls_assert ();
1152 return GNUTLS_E_MEMORY_ERROR;
1153 }
1154
1155 p = bag->element[elem].friendly_name;
1156 for (i = 0; i < size; i += 2)
1157 {
1158 name[i] = 0;
1159 name[i + 1] = *p;
1160 p++;
1161 }
1162
1163 MHD_gtls_str_cpy (root, sizeof (root), where);
1164 MHD_gtls_str_cat (root, sizeof (root), ".?LAST");
1165
1166 result =
1167 MHD__gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
1168 root, name, size, 1);
1169
1170 MHD_gnutls_free (name);
1171
1172 if (result < 0)
1173 {
1174 MHD_gnutls_assert ();
1175 return result;
1176 }
1177 }
1178
1179 return 0;
1180}
1181
1182
1183/* Encodes the bag into a SafeContents structure, and puts the output in
1184 * the given datum. Enc is set to non zero if the data are encrypted;
1185 */
1186int
1187MHD_pkcs12_encode_safe_contents (MHD_gnutlsMHD_pkcs12_bag_t bag, ASN1_TYPE * contents,
1188 int *enc)
1189{
1190 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1191 int result;
1192 int i;
1193 const char *oid;
1194
1195 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
1196 {
1197 *enc = 1;
1198 return 0; /* ENCRYPTED BAG, do nothing. */
1199 }
1200 else if (enc)
1201 *enc = 0;
1202
1203 /* Step 1. Create the SEQUENCE.
1204 */
1205
1206 if ((result = MHD__asn1_create_element
1207 (MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
1208 &c2)) != ASN1_SUCCESS)
1209 {
1210 MHD_gnutls_assert ();
1211 result = MHD_gtls_asn2err (result);
1212 goto cleanup;
1213 }
1214
1215 for (i = 0; i < bag->bag_elements; i++)
1216 {
1217
1218 oid = bag_to_oid (bag->element[i].type);
1219 if (oid == NULL)
1220 {
1221 MHD_gnutls_assert ();
1222 continue;
1223 }
1224
1225 result = MHD__asn1_write_value (c2, "", "NEW", 1);
1226 if (result != ASN1_SUCCESS)
1227 {
1228 MHD_gnutls_assert ();
1229 result = MHD_gtls_asn2err (result);
1230 goto cleanup;
1231 }
1232
1233 /* Copy the bag type.
1234 */
1235 result = MHD__asn1_write_value (c2, "?LAST.bagId", oid, 1);
1236 if (result != ASN1_SUCCESS)
1237 {
1238 MHD_gnutls_assert ();
1239 result = MHD_gtls_asn2err (result);
1240 goto cleanup;
1241 }
1242
1243 /* Set empty attributes
1244 */
1245 result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
1246 if (result < 0)
1247 {
1248 MHD_gnutls_assert ();
1249 goto cleanup;
1250 }
1251
1252
1253 /* Copy the Bag Value
1254 */
1255
1256 if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1257 bag->element[i].type == GNUTLS_BAG_CRL)
1258 {
1259 MHD_gnutls_datum_t tmp;
1260
1261 /* in that case encode it to a CertBag or
1262 * a CrlBag.
1263 */
1264
1265 result =
1266 MHD_pkcs12_encode_crt_bag (bag->element[i].type,
1267 &bag->element[i].data, &tmp);
1268
1269 if (result < 0)
1270 {
1271 MHD_gnutls_assert ();
1272 goto cleanup;
1273 }
1274
1275 result = MHD__gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
1276
1277 MHD__gnutls_free_datum (&tmp);
1278
1279 }
1280 else
1281 {
1282
1283 result = MHD__gnutls_x509_write_value (c2, "?LAST.bagValue",
1284 &bag->element[i].data, 0);
1285 }
1286
1287 if (result < 0)
1288 {
1289 MHD_gnutls_assert ();
1290 goto cleanup;
1291 }
1292
1293 }
1294
1295 /* Encode the data and copy them into the datum
1296 */
1297 *contents = c2;
1298
1299 return 0;
1300
1301cleanup:
1302 if (c2)
1303 MHD__asn1_delete_structure (&c2);
1304 return result;
1305
1306}
1307
1308
1309#endif /* ENABLE_PKI */