diff options
Diffstat (limited to 'src/daemon/https/x509/pkcs12.c')
-rw-r--r-- | src/daemon/https/x509/pkcs12.c | 1309 |
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 | */ | ||
48 | static 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 | |||
121 | cleanup: | ||
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 | **/ | ||
139 | int | ||
140 | MHD_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 | **/ | ||
167 | void | ||
168 | MHD_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 | **/ | ||
194 | int | ||
195 | MHD_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 | |||
247 | cleanup: | ||
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 | **/ | ||
275 | int | ||
276 | MHD_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 | |||
290 | static int | ||
291 | oid2bag (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 | |||
305 | static const char * | ||
306 | bag_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 | |||
322 | static inline char * | ||
323 | ucs2_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 | */ | ||
343 | int | ||
344 | MHD_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 | |||
526 | cleanup: | ||
527 | if (c2) | ||
528 | MHD__asn1_delete_structure (&c2); | ||
529 | return result; | ||
530 | |||
531 | } | ||
532 | |||
533 | |||
534 | static 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 | |||
562 | cleanup: | ||
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 | **/ | ||
581 | int | ||
582 | MHD_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 | |||
651 | cleanup: | ||
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 | */ | ||
659 | static int | ||
660 | create_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 | |||
710 | cleanup: | ||
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 | **/ | ||
725 | int | ||
726 | MHD_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 | |||
841 | cleanup: | ||
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 | **/ | ||
856 | int | ||
857 | MHD_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 | |||
958 | cleanup: | ||
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 | **/ | ||
972 | int | ||
973 | MHD_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 | |||
1069 | cleanup: | ||
1070 | MHD__gnutls_free_datum (&tmp); | ||
1071 | MHD__gnutls_free_datum (&salt); | ||
1072 | return result; | ||
1073 | } | ||
1074 | |||
1075 | |||
1076 | static int | ||
1077 | write_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 | */ | ||
1186 | int | ||
1187 | MHD_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 | |||
1301 | cleanup: | ||
1302 | if (c2) | ||
1303 | MHD__asn1_delete_structure (&c2); | ||
1304 | return result; | ||
1305 | |||
1306 | } | ||
1307 | |||
1308 | |||
1309 | #endif /* ENABLE_PKI */ | ||