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