Tizen 2.0 Release
[external/libgnutls26.git] / lib / x509 / extensions.c
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software
3  * Foundation, 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 to the X.509 extension parsing.
27  */
28
29 #include <gnutls_int.h>
30 #include <gnutls_errors.h>
31 #include <gnutls_global.h>
32 #include <libtasn1.h>
33 #include <common.h>
34 #include <x509_int.h>
35 #include <gnutls_datum.h>
36
37 static int
38 get_extension (ASN1_TYPE asn, const char *root,
39                const char *extension_id, int indx,
40                gnutls_datum_t * ret, unsigned int *_critical)
41 {
42   int k, result, len;
43   char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
44   char str[1024];
45   char str_critical[10];
46   int critical = 0;
47   char extnID[128];
48   gnutls_datum_t value;
49   int indx_counter = 0;
50
51   ret->data = NULL;
52   ret->size = 0;
53
54   k = 0;
55   do
56     {
57       k++;
58
59       snprintf (name, sizeof (name), "%s.?%u", root, k);
60
61       len = sizeof (str) - 1;
62       result = asn1_read_value (asn, name, str, &len);
63
64       /* move to next
65        */
66
67       if (result == ASN1_ELEMENT_NOT_FOUND)
68         {
69           break;
70         }
71
72       do
73         {
74
75           _gnutls_str_cpy (name2, sizeof (name2), name);
76           _gnutls_str_cat (name2, sizeof (name2), ".extnID");
77
78           len = sizeof (extnID) - 1;
79           result = asn1_read_value (asn, name2, extnID, &len);
80
81           if (result == ASN1_ELEMENT_NOT_FOUND)
82             {
83               gnutls_assert ();
84               break;
85             }
86           else if (result != ASN1_SUCCESS)
87             {
88               gnutls_assert ();
89               return _gnutls_asn2err (result);
90             }
91
92           /* Handle Extension 
93            */
94           if (strcmp (extnID, extension_id) == 0 && indx == indx_counter++)
95             {
96               /* extension was found 
97                */
98
99               /* read the critical status.
100                */
101               _gnutls_str_cpy (name2, sizeof (name2), name);
102               _gnutls_str_cat (name2, sizeof (name2), ".critical");
103
104               len = sizeof (str_critical);
105               result = asn1_read_value (asn, name2, str_critical, &len);
106
107               if (result == ASN1_ELEMENT_NOT_FOUND)
108                 {
109                   gnutls_assert ();
110                   break;
111                 }
112               else if (result != ASN1_SUCCESS)
113                 {
114                   gnutls_assert ();
115                   return _gnutls_asn2err (result);
116                 }
117
118               if (str_critical[0] == 'T')
119                 critical = 1;
120               else
121                 critical = 0;
122
123               /* read the value.
124                */
125               _gnutls_str_cpy (name2, sizeof (name2), name);
126               _gnutls_str_cat (name2, sizeof (name2), ".extnValue");
127
128               result = _gnutls_x509_read_value (asn, name2, &value, 0);
129               if (result < 0)
130                 {
131                   gnutls_assert ();
132                   return result;
133                 }
134
135               ret->data = value.data;
136               ret->size = value.size;
137
138               if (_critical)
139                 *_critical = critical;
140
141               return 0;
142             }
143
144
145         }
146       while (0);
147     }
148   while (1);
149
150   if (result == ASN1_ELEMENT_NOT_FOUND)
151     {
152       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
153     }
154   else
155     {
156       gnutls_assert ();
157       return _gnutls_asn2err (result);
158     }
159 }
160
161 /* This function will attempt to return the requested extension found in
162  * the given X509v3 certificate. The return value is allocated and stored into
163  * ret.
164  *
165  * Critical will be either 0 or 1.
166  *
167  * If the extension does not exist, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
168  * be returned.
169  */
170 int
171 _gnutls_x509_crt_get_extension (gnutls_x509_crt_t cert,
172                                 const char *extension_id, int indx,
173                                 gnutls_datum_t * ret, unsigned int *_critical)
174 {
175   return get_extension (cert->cert, "tbsCertificate.extensions", extension_id,
176                         indx, ret, _critical);
177 }
178
179 int
180 _gnutls_x509_crl_get_extension (gnutls_x509_crl_t crl,
181                                 const char *extension_id, int indx,
182                                 gnutls_datum_t * ret, unsigned int *_critical)
183 {
184   return get_extension (crl->crl, "tbsCertList.crlExtensions", extension_id,
185                         indx, ret, _critical);
186 }
187
188
189 /* This function will attempt to return the requested extension OID found in
190  * the given X509v3 certificate. 
191  *
192  * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
193  * be returned.
194  */
195 static int
196 get_extension_oid (ASN1_TYPE asn, const char *root,
197                    int indx, void *oid, size_t * sizeof_oid)
198 {
199   int k, result, len;
200   char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
201   char str[1024];
202   char extnID[128];
203   int indx_counter = 0;
204
205   k = 0;
206   do
207     {
208       k++;
209
210       snprintf (name, sizeof (name), "%s.?%u", root, k);
211
212       len = sizeof (str) - 1;
213       result = asn1_read_value (asn, name, str, &len);
214
215       /* move to next
216        */
217
218       if (result == ASN1_ELEMENT_NOT_FOUND)
219         {
220           break;
221         }
222
223       do
224         {
225
226           _gnutls_str_cpy (name2, sizeof (name2), name);
227           _gnutls_str_cat (name2, sizeof (name2), ".extnID");
228
229           len = sizeof (extnID) - 1;
230           result = asn1_read_value (asn, name2, extnID, &len);
231
232           if (result == ASN1_ELEMENT_NOT_FOUND)
233             {
234               gnutls_assert ();
235               break;
236             }
237           else if (result != ASN1_SUCCESS)
238             {
239               gnutls_assert ();
240               return _gnutls_asn2err (result);
241             }
242
243           /* Handle Extension 
244            */
245           if (indx == indx_counter++)
246             {
247               len = strlen (extnID) + 1;
248
249               if (*sizeof_oid < (unsigned) len)
250                 {
251                   *sizeof_oid = len;
252                   gnutls_assert ();
253                   return GNUTLS_E_SHORT_MEMORY_BUFFER;
254                 }
255
256               memcpy (oid, extnID, len);
257               *sizeof_oid = len - 1;
258
259               return 0;
260             }
261
262
263         }
264       while (0);
265     }
266   while (1);
267
268   if (result == ASN1_ELEMENT_NOT_FOUND)
269     {
270       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
271     }
272   else
273     {
274       gnutls_assert ();
275       return _gnutls_asn2err (result);
276     }
277 }
278
279 /* This function will attempt to return the requested extension OID found in
280  * the given X509v3 certificate. 
281  *
282  * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
283  * be returned.
284  */
285 int
286 _gnutls_x509_crt_get_extension_oid (gnutls_x509_crt_t cert,
287                                     int indx, void *oid, size_t * sizeof_oid)
288 {
289   return get_extension_oid (cert->cert, "tbsCertificate.extensions", indx,
290                             oid, sizeof_oid);
291 }
292
293 int
294 _gnutls_x509_crl_get_extension_oid (gnutls_x509_crl_t crl,
295                                     int indx, void *oid, size_t * sizeof_oid)
296 {
297   return get_extension_oid (crl->crl, "tbsCertList.crlExtensions", indx, oid,
298                             sizeof_oid);
299 }
300
301 /* This function will attempt to set the requested extension in
302  * the given X509v3 certificate. 
303  *
304  * Critical will be either 0 or 1.
305  */
306 static int
307 add_extension (ASN1_TYPE asn, const char *root, const char *extension_id,
308                const gnutls_datum_t * ext_data, unsigned int critical)
309 {
310   int result;
311   const char *str;
312   char name[ASN1_MAX_NAME_SIZE];
313
314   snprintf (name, sizeof (name), "%s", root);
315
316   /* Add a new extension in the list.
317    */
318   result = asn1_write_value (asn, name, "NEW", 1);
319   if (result != ASN1_SUCCESS)
320     {
321       gnutls_assert ();
322       return _gnutls_asn2err (result);
323     }
324
325   if (root[0] != 0)
326     snprintf (name, sizeof (name), "%s.?LAST.extnID", root);
327   else
328     snprintf (name, sizeof (name), "?LAST.extnID");
329
330   result = asn1_write_value (asn, name, extension_id, 1);
331   if (result != ASN1_SUCCESS)
332     {
333       gnutls_assert ();
334       return _gnutls_asn2err (result);
335     }
336
337   if (critical == 0)
338     str = "FALSE";
339   else
340     str = "TRUE";
341
342   if (root[0] != 0)
343     snprintf (name, sizeof (name), "%s.?LAST.critical", root);
344   else
345     snprintf (name, sizeof (name), "?LAST.critical");
346
347   result = asn1_write_value (asn, name, str, 1);
348   if (result != ASN1_SUCCESS)
349     {
350       gnutls_assert ();
351       return _gnutls_asn2err (result);
352     }
353
354   if (root[0] != 0)
355     snprintf (name, sizeof (name), "%s.?LAST.extnValue", root);
356   else
357     snprintf (name, sizeof (name), "?LAST.extnValue");
358
359   result = _gnutls_x509_write_value (asn, name, ext_data, 0);
360   if (result < 0)
361     {
362       gnutls_assert ();
363       return result;
364     }
365
366   return 0;
367 }
368
369 /* Overwrite the given extension (using the index)
370  * index here starts from one.
371  */
372 static int
373 overwrite_extension (ASN1_TYPE asn, const char *root, unsigned int indx,
374                      const gnutls_datum_t * ext_data, unsigned int critical)
375 {
376   char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
377   const char *str;
378   int result;
379
380   if (root[0] != 0)
381     snprintf (name, sizeof (name), "%s.?%u", root, indx);
382   else
383     snprintf (name, sizeof (name), "?%u", indx);
384
385   if (critical == 0)
386     str = "FALSE";
387   else
388     str = "TRUE";
389
390   _gnutls_str_cpy (name2, sizeof (name2), name);
391   _gnutls_str_cat (name2, sizeof (name2), ".critical");
392
393   result = asn1_write_value (asn, name2, str, 1);
394   if (result != ASN1_SUCCESS)
395     {
396       gnutls_assert ();
397       return _gnutls_asn2err (result);
398     }
399
400   _gnutls_str_cpy (name2, sizeof (name2), name);
401   _gnutls_str_cat (name2, sizeof (name2), ".extnValue");
402
403   result = _gnutls_x509_write_value (asn, name2, ext_data, 0);
404   if (result < 0)
405     {
406       gnutls_assert ();
407       return result;
408     }
409
410   return 0;
411 }
412
413 static int
414 set_extension (ASN1_TYPE asn, const char *root,
415                const char *ext_id,
416                const gnutls_datum_t * ext_data, unsigned int critical)
417 {
418   int result;
419   int k, len;
420   char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
421   char extnID[128];
422
423   /* Find the index of the given extension.
424    */
425   k = 0;
426   do
427     {
428       k++;
429
430       if (root[0] != 0)
431         snprintf (name, sizeof (name), "%s.?%u", root, k);
432       else
433         snprintf (name, sizeof (name), "?%u", k);
434
435       len = sizeof (extnID) - 1;
436       result = asn1_read_value (asn, name, extnID, &len);
437
438       /* move to next
439        */
440
441       if (result == ASN1_ELEMENT_NOT_FOUND)
442         {
443           break;
444         }
445
446       do
447         {
448
449           _gnutls_str_cpy (name2, sizeof (name2), name);
450           _gnutls_str_cat (name2, sizeof (name2), ".extnID");
451
452           len = sizeof (extnID) - 1;
453           result = asn1_read_value (asn, name2, extnID, &len);
454
455           if (result == ASN1_ELEMENT_NOT_FOUND)
456             {
457               gnutls_assert ();
458               break;
459             }
460           else if (result != ASN1_SUCCESS)
461             {
462               gnutls_assert ();
463               return _gnutls_asn2err (result);
464             }
465
466           /* Handle Extension 
467            */
468           if (strcmp (extnID, ext_id) == 0)
469             {
470               /* extension was found 
471                */
472               return overwrite_extension (asn, root, k, ext_data, critical);
473             }
474
475
476         }
477       while (0);
478     }
479   while (1);
480
481   if (result == ASN1_ELEMENT_NOT_FOUND)
482     {
483       return add_extension (asn, root, ext_id, ext_data, critical);
484     }
485   else
486     {
487       gnutls_assert ();
488       return _gnutls_asn2err (result);
489     }
490
491
492   return 0;
493 }
494
495 /* This function will attempt to overwrite the requested extension with
496  * the given one. 
497  *
498  * Critical will be either 0 or 1.
499  */
500 int
501 _gnutls_x509_crt_set_extension (gnutls_x509_crt_t cert,
502                                 const char *ext_id,
503                                 const gnutls_datum_t * ext_data,
504                                 unsigned int critical)
505 {
506   return set_extension (cert->cert, "tbsCertificate.extensions", ext_id,
507                         ext_data, critical);
508 }
509
510 int
511 _gnutls_x509_crl_set_extension (gnutls_x509_crl_t crl,
512                                 const char *ext_id,
513                                 const gnutls_datum_t * ext_data,
514                                 unsigned int critical)
515 {
516   return set_extension (crl->crl, "tbsCertList.crlExtensions", ext_id,
517                         ext_data, critical);
518 }
519
520 #ifdef ENABLE_PKI
521 int
522 _gnutls_x509_crq_set_extension (gnutls_x509_crq_t crq,
523                                 const char *ext_id,
524                                 const gnutls_datum_t * ext_data,
525                                 unsigned int critical)
526 {
527   unsigned char *extensions = NULL;
528   size_t extensions_size = 0;
529   gnutls_datum_t der;
530   ASN1_TYPE c2;
531   int result;
532
533   result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
534                                                  0, NULL, &extensions_size);
535   if (result == GNUTLS_E_SHORT_MEMORY_BUFFER)
536     {
537       extensions = gnutls_malloc (extensions_size);
538       if (extensions == NULL)
539         {
540           gnutls_assert ();
541           return GNUTLS_E_MEMORY_ERROR;
542         }
543
544       result = gnutls_x509_crq_get_attribute_by_oid (crq,
545                                                      "1.2.840.113549.1.9.14",
546                                                      0, extensions,
547                                                      &extensions_size);
548     }
549   if (result < 0)
550     {
551       if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
552         {
553           extensions_size = 0;
554         }
555       else
556         {
557           gnutls_assert ();
558           gnutls_free (extensions);
559           return result;
560         }
561     }
562
563   result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.Extensions", &c2);
564   if (result != ASN1_SUCCESS)
565     {
566       gnutls_assert ();
567       gnutls_free (extensions);
568       return _gnutls_asn2err (result);
569     }
570
571   if (extensions_size > 0)
572     {
573       result = asn1_der_decoding (&c2, extensions, extensions_size, NULL);
574       gnutls_free (extensions);
575       if (result != ASN1_SUCCESS)
576         {
577           gnutls_assert ();
578           asn1_delete_structure (&c2);
579           return _gnutls_asn2err (result);
580         }
581     }
582
583   result = set_extension (c2, "", ext_id, ext_data, critical);
584   if (result < 0)
585     {
586       gnutls_assert ();
587       asn1_delete_structure (&c2);
588       return result;
589     }
590
591   result = _gnutls_x509_der_encode (c2, "", &der, 0);
592
593   asn1_delete_structure (&c2);
594
595   if (result < 0)
596     {
597       gnutls_assert ();
598       return result;
599     }
600
601   result = gnutls_x509_crq_set_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
602                                                  der.data, der.size);
603   gnutls_free (der.data);
604   if (result < 0)
605     {
606       gnutls_assert ();
607       return result;
608     }
609
610
611   return 0;
612 }
613
614 #endif
615
616 /* Here we only extract the KeyUsage field, from the DER encoded
617  * extension.
618  */
619 int
620 _gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage,
621                                    opaque * extnValue, int extnValueLen)
622 {
623   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
624   int len, result;
625   uint8_t str[2];
626
627   str[0] = str[1] = 0;
628   *keyUsage = 0;
629
630   if ((result = asn1_create_element
631        (_gnutls_get_pkix (), "PKIX1.KeyUsage", &ext)) != ASN1_SUCCESS)
632     {
633       gnutls_assert ();
634       return _gnutls_asn2err (result);
635     }
636
637   result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
638
639   if (result != ASN1_SUCCESS)
640     {
641       gnutls_assert ();
642       asn1_delete_structure (&ext);
643       return _gnutls_asn2err (result);
644     }
645
646   len = sizeof (str);
647   result = asn1_read_value (ext, "", str, &len);
648   if (result != ASN1_SUCCESS)
649     {
650       gnutls_assert ();
651       asn1_delete_structure (&ext);
652       return 0;
653     }
654
655   *keyUsage = str[0] | (str[1] << 8);
656
657   asn1_delete_structure (&ext);
658
659   return 0;
660 }
661
662 /* extract the basicConstraints from the DER encoded extension
663  */
664 int
665 _gnutls_x509_ext_extract_basicConstraints (int *CA,
666                                            int *pathLenConstraint,
667                                            opaque * extnValue,
668                                            int extnValueLen)
669 {
670   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
671   char str[128];
672   int len, result;
673
674   if ((result = asn1_create_element
675        (_gnutls_get_pkix (), "PKIX1.BasicConstraints", &ext)) != ASN1_SUCCESS)
676     {
677       gnutls_assert ();
678       return _gnutls_asn2err (result);
679     }
680
681   result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
682   if (result != ASN1_SUCCESS)
683     {
684       gnutls_assert ();
685       asn1_delete_structure (&ext);
686       return _gnutls_asn2err (result);
687     }
688
689   if (pathLenConstraint)
690     {
691       result = _gnutls_x509_read_uint (ext, "pathLenConstraint",
692                                        pathLenConstraint);
693       if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
694         *pathLenConstraint = -1;
695       else if (result != GNUTLS_E_SUCCESS)
696         {
697           gnutls_assert ();
698           asn1_delete_structure (&ext);
699           return _gnutls_asn2err (result);
700         }
701     }
702
703   /* the default value of cA is false.
704    */
705   len = sizeof (str) - 1;
706   result = asn1_read_value (ext, "cA", str, &len);
707   if (result == ASN1_SUCCESS && strcmp (str, "TRUE") == 0)
708     *CA = 1;
709   else
710     *CA = 0;
711
712   asn1_delete_structure (&ext);
713
714   return 0;
715 }
716
717 /* generate the basicConstraints in a DER encoded extension
718  * Use 0 or 1 (TRUE) for CA.
719  * Use negative values for pathLenConstraint to indicate that the field
720  * should not be present, >= 0 to indicate set values.
721  */
722 int
723 _gnutls_x509_ext_gen_basicConstraints (int CA,
724                                        int pathLenConstraint,
725                                        gnutls_datum_t * der_ext)
726 {
727   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
728   const char *str;
729   int result;
730
731   if (CA == 0)
732     str = "FALSE";
733   else
734     str = "TRUE";
735
736   result =
737     asn1_create_element (_gnutls_get_pkix (), "PKIX1.BasicConstraints", &ext);
738   if (result != ASN1_SUCCESS)
739     {
740       gnutls_assert ();
741       return _gnutls_asn2err (result);
742     }
743
744   result = asn1_write_value (ext, "cA", str, 1);
745   if (result != ASN1_SUCCESS)
746     {
747       gnutls_assert ();
748       asn1_delete_structure (&ext);
749       return _gnutls_asn2err (result);
750     }
751
752   if (pathLenConstraint < 0)
753     {
754       result = asn1_write_value (ext, "pathLenConstraint", NULL, 0);
755       if (result < 0)
756         result = _gnutls_asn2err (result);
757     }
758   else
759     result = _gnutls_x509_write_uint32 (ext, "pathLenConstraint",
760                                         pathLenConstraint);
761   if (result < 0)
762     {
763       gnutls_assert ();
764       asn1_delete_structure (&ext);
765       return result;
766     }
767
768   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
769
770   asn1_delete_structure (&ext);
771
772   if (result < 0)
773     {
774       gnutls_assert ();
775       return result;
776     }
777
778   return 0;
779 }
780
781 /* extract an INTEGER from the DER encoded extension
782  */
783 int
784 _gnutls_x509_ext_extract_number (opaque * number,
785                                  size_t * _nr_size,
786                                  opaque * extnValue, int extnValueLen)
787 {
788   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
789   int result;
790   int nr_size = *_nr_size;
791
792   /* here it doesn't matter so much that we use CertificateSerialNumber. It is equal
793    * to using INTEGER.
794    */
795   if ((result = asn1_create_element
796        (_gnutls_get_pkix (), "PKIX1.CertificateSerialNumber",
797         &ext)) != ASN1_SUCCESS)
798     {
799       gnutls_assert ();
800       return _gnutls_asn2err (result);
801     }
802
803   result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
804   if (result != ASN1_SUCCESS)
805     {
806       gnutls_assert ();
807       asn1_delete_structure (&ext);
808       return _gnutls_asn2err (result);
809     }
810
811   /* the default value of cA is false.
812    */
813   result = asn1_read_value (ext, "", number, &nr_size);
814   if (result != ASN1_SUCCESS)
815     result = _gnutls_asn2err (result);
816   else
817     result = 0;
818
819   *_nr_size = nr_size;
820
821   asn1_delete_structure (&ext);
822
823   return result;
824 }
825
826 /* generate an INTEGER in a DER encoded extension
827  */
828 int
829 _gnutls_x509_ext_gen_number (const opaque * number, size_t nr_size,
830                              gnutls_datum_t * der_ext)
831 {
832   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
833   int result;
834
835   result =
836     asn1_create_element (_gnutls_get_pkix (), "PKIX1.CertificateSerialNumber",
837                          &ext);
838   if (result != ASN1_SUCCESS)
839     {
840       gnutls_assert ();
841       return _gnutls_asn2err (result);
842     }
843
844   result = asn1_write_value (ext, "", number, nr_size);
845   if (result != ASN1_SUCCESS)
846     {
847       gnutls_assert ();
848       asn1_delete_structure (&ext);
849       return _gnutls_asn2err (result);
850     }
851
852   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
853
854   asn1_delete_structure (&ext);
855
856   if (result < 0)
857     {
858       gnutls_assert ();
859       return result;
860     }
861
862   return 0;
863 }
864
865 /* generate the keyUsage in a DER encoded extension
866  * Use an ORed SEQUENCE of GNUTLS_KEY_* for usage.
867  */
868 int
869 _gnutls_x509_ext_gen_keyUsage (uint16_t usage, gnutls_datum_t * der_ext)
870 {
871   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
872   int result;
873   uint8_t str[2];
874
875   result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.KeyUsage", &ext);
876   if (result != ASN1_SUCCESS)
877     {
878       gnutls_assert ();
879       return _gnutls_asn2err (result);
880     }
881
882   str[0] = usage & 0xff;
883   str[1] = usage >> 8;
884
885   result = asn1_write_value (ext, "", str, 9);
886   if (result != ASN1_SUCCESS)
887     {
888       gnutls_assert ();
889       asn1_delete_structure (&ext);
890       return _gnutls_asn2err (result);
891     }
892
893   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
894
895   asn1_delete_structure (&ext);
896
897   if (result < 0)
898     {
899       gnutls_assert ();
900       return result;
901     }
902
903   return 0;
904 }
905
906 static int
907 write_new_general_name (ASN1_TYPE ext, const char *ext_name,
908                         gnutls_x509_subject_alt_name_t type,
909                         const void *data, unsigned int data_size)
910 {
911   const char *str;
912   int result;
913   char name[128];
914
915   result = asn1_write_value (ext, ext_name, "NEW", 1);
916   if (result != ASN1_SUCCESS)
917     {
918       gnutls_assert ();
919       return _gnutls_asn2err (result);
920     }
921
922   switch (type)
923     {
924     case GNUTLS_SAN_DNSNAME:
925       str = "dNSName";
926       break;
927     case GNUTLS_SAN_RFC822NAME:
928       str = "rfc822Name";
929       break;
930     case GNUTLS_SAN_URI:
931       str = "uniformResourceIdentifier";
932       break;
933     case GNUTLS_SAN_IPADDRESS:
934       str = "iPAddress";
935       break;
936     default:
937       gnutls_assert ();
938       return GNUTLS_E_INTERNAL_ERROR;
939     }
940
941   if (ext_name[0] == 0)
942     {                           /* no dot */
943       _gnutls_str_cpy (name, sizeof (name), "?LAST");
944     }
945   else
946     {
947       _gnutls_str_cpy (name, sizeof (name), ext_name);
948       _gnutls_str_cat (name, sizeof (name), ".?LAST");
949     }
950
951   result = asn1_write_value (ext, name, str, 1);
952   if (result != ASN1_SUCCESS)
953     {
954       gnutls_assert ();
955       return _gnutls_asn2err (result);
956     }
957
958   _gnutls_str_cat (name, sizeof (name), ".");
959   _gnutls_str_cat (name, sizeof (name), str);
960
961   result = asn1_write_value (ext, name, data, data_size);
962   if (result != ASN1_SUCCESS)
963     {
964       gnutls_assert ();
965       asn1_delete_structure (&ext);
966       return _gnutls_asn2err (result);
967     }
968
969   return 0;
970 }
971
972 /* Convert the given name to GeneralNames in a DER encoded extension.
973  * This is the same as subject alternative name.
974  */
975 int
976 _gnutls_x509_ext_gen_subject_alt_name (gnutls_x509_subject_alt_name_t
977                                        type, const void *data,
978                                        unsigned int data_size,
979                                        gnutls_datum_t * prev_der_ext,
980                                        gnutls_datum_t * der_ext)
981 {
982   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
983   int result;
984
985   result =
986     asn1_create_element (_gnutls_get_pkix (), "PKIX1.GeneralNames", &ext);
987   if (result != ASN1_SUCCESS)
988     {
989       gnutls_assert ();
990       return _gnutls_asn2err (result);
991     }
992
993   if (prev_der_ext != NULL && prev_der_ext->data != NULL
994       && prev_der_ext->size != 0)
995     {
996       result =
997         asn1_der_decoding (&ext, prev_der_ext->data, prev_der_ext->size,
998                            NULL);
999
1000       if (result != ASN1_SUCCESS)
1001         {
1002           gnutls_assert ();
1003           asn1_delete_structure (&ext);
1004           return _gnutls_asn2err (result);
1005         }
1006     }
1007
1008   result = write_new_general_name (ext, "", type, data, data_size);
1009   if (result < 0)
1010     {
1011       gnutls_assert ();
1012       asn1_delete_structure (&ext);
1013       return result;
1014     }
1015
1016   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
1017
1018   asn1_delete_structure (&ext);
1019
1020   if (result < 0)
1021     {
1022       gnutls_assert ();
1023       return result;
1024     }
1025
1026   return 0;
1027 }
1028
1029 /* generate the SubjectKeyID in a DER encoded extension
1030  */
1031 int
1032 _gnutls_x509_ext_gen_key_id (const void *id, size_t id_size,
1033                              gnutls_datum_t * der_ext)
1034 {
1035   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
1036   int result;
1037
1038   result =
1039     asn1_create_element (_gnutls_get_pkix (),
1040                          "PKIX1.SubjectKeyIdentifier", &ext);
1041   if (result != ASN1_SUCCESS)
1042     {
1043       gnutls_assert ();
1044       return _gnutls_asn2err (result);
1045     }
1046
1047   result = asn1_write_value (ext, "", id, id_size);
1048   if (result != ASN1_SUCCESS)
1049     {
1050       gnutls_assert ();
1051       asn1_delete_structure (&ext);
1052       return _gnutls_asn2err (result);
1053     }
1054
1055   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
1056
1057   asn1_delete_structure (&ext);
1058
1059   if (result < 0)
1060     {
1061       gnutls_assert ();
1062       return result;
1063     }
1064
1065   return 0;
1066 }
1067
1068 /* generate the AuthorityKeyID in a DER encoded extension
1069  */
1070 int
1071 _gnutls_x509_ext_gen_auth_key_id (const void *id, size_t id_size,
1072                                   gnutls_datum_t * der_ext)
1073 {
1074   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
1075   int result;
1076
1077   result =
1078     asn1_create_element (_gnutls_get_pkix (),
1079                          "PKIX1.AuthorityKeyIdentifier", &ext);
1080   if (result != ASN1_SUCCESS)
1081     {
1082       gnutls_assert ();
1083       return _gnutls_asn2err (result);
1084     }
1085
1086   result = asn1_write_value (ext, "keyIdentifier", id, id_size);
1087   if (result != ASN1_SUCCESS)
1088     {
1089       gnutls_assert ();
1090       asn1_delete_structure (&ext);
1091       return _gnutls_asn2err (result);
1092     }
1093
1094   asn1_write_value (ext, "authorityCertIssuer", NULL, 0);
1095   asn1_write_value (ext, "authorityCertSerialNumber", NULL, 0);
1096
1097   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
1098
1099   asn1_delete_structure (&ext);
1100
1101   if (result < 0)
1102     {
1103       gnutls_assert ();
1104       return result;
1105     }
1106
1107   return 0;
1108 }
1109
1110
1111 /* Creates and encodes the CRL Distribution points. data_string should be a name
1112  * and type holds the type of the name. 
1113  * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*.
1114  *
1115  */
1116 int
1117 _gnutls_x509_ext_gen_crl_dist_points (gnutls_x509_subject_alt_name_t
1118                                       type, const void *data,
1119                                       unsigned int data_size,
1120                                       unsigned int reason_flags,
1121                                       gnutls_datum_t * der_ext)
1122 {
1123   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
1124   gnutls_datum_t gnames = { NULL, 0 };
1125   int result;
1126   uint8_t reasons[2];
1127
1128   reasons[0] = reason_flags & 0xff;
1129   reasons[1] = reason_flags >> 8;
1130
1131   result =
1132     asn1_create_element (_gnutls_get_pkix (),
1133                          "PKIX1.CRLDistributionPoints", &ext);
1134   if (result != ASN1_SUCCESS)
1135     {
1136       gnutls_assert ();
1137       result = _gnutls_asn2err (result);
1138       goto cleanup;
1139     }
1140
1141   result = asn1_write_value (ext, "", "NEW", 1);
1142   if (result != ASN1_SUCCESS)
1143     {
1144       gnutls_assert ();
1145       result = _gnutls_asn2err (result);
1146       goto cleanup;
1147     }
1148
1149   if (reason_flags)
1150     {
1151       result = asn1_write_value (ext, "?LAST.reasons", reasons, 9);
1152       if (result != ASN1_SUCCESS)
1153         {
1154           gnutls_assert ();
1155           result = _gnutls_asn2err (result);
1156           goto cleanup;
1157         }
1158     }
1159   else
1160     {
1161       result = asn1_write_value (ext, "?LAST.reasons", NULL, 0);
1162       if (result != ASN1_SUCCESS)
1163         {
1164           gnutls_assert ();
1165           result = _gnutls_asn2err (result);
1166           goto cleanup;
1167         }
1168     }
1169
1170   result = asn1_write_value (ext, "?LAST.cRLIssuer", NULL, 0);
1171   if (result != ASN1_SUCCESS)
1172     {
1173       gnutls_assert ();
1174       result = _gnutls_asn2err (result);
1175       goto cleanup;
1176     }
1177
1178   /* When used as type CHOICE.
1179    */
1180   result = asn1_write_value (ext, "?LAST.distributionPoint", "fullName", 1);
1181   if (result != ASN1_SUCCESS)
1182     {
1183       gnutls_assert ();
1184       result = _gnutls_asn2err (result);
1185       goto cleanup;
1186     }
1187
1188 #if 0
1189   /* only needed in old code (where defined as SEQUENCE OF) */
1190   asn1_write_value (ext,
1191                     "?LAST.distributionPoint.nameRelativeToCRLIssuer",
1192                     NULL, 0);
1193 #endif
1194
1195   result =
1196     write_new_general_name (ext, "?LAST.distributionPoint.fullName",
1197                             type, data, data_size);
1198   if (result < 0)
1199     {
1200       gnutls_assert ();
1201       goto cleanup;
1202     }
1203
1204   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
1205
1206   if (result < 0)
1207     {
1208       gnutls_assert ();
1209       goto cleanup;
1210     }
1211
1212   result = 0;
1213
1214 cleanup:
1215   _gnutls_free_datum (&gnames);
1216   asn1_delete_structure (&ext);
1217
1218   return result;
1219 }
1220
1221 /* extract the proxyCertInfo from the DER encoded extension
1222  */
1223 int
1224 _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint,
1225                                         char **policyLanguage,
1226                                         char **policy,
1227                                         size_t * sizeof_policy,
1228                                         opaque * extnValue, int extnValueLen)
1229 {
1230   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
1231   int result;
1232   gnutls_datum_t value;
1233
1234   if ((result = asn1_create_element
1235        (_gnutls_get_pkix (), "PKIX1.ProxyCertInfo", &ext)) != ASN1_SUCCESS)
1236     {
1237       gnutls_assert ();
1238       return _gnutls_asn2err (result);
1239     }
1240
1241   result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL);
1242   if (result != ASN1_SUCCESS)
1243     {
1244       gnutls_assert ();
1245       asn1_delete_structure (&ext);
1246       return _gnutls_asn2err (result);
1247     }
1248
1249   if (pathLenConstraint)
1250     {
1251       result = _gnutls_x509_read_uint (ext, "pCPathLenConstraint",
1252                                        pathLenConstraint);
1253       if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1254         *pathLenConstraint = -1;
1255       else if (result != GNUTLS_E_SUCCESS)
1256         {
1257           asn1_delete_structure (&ext);
1258           return _gnutls_asn2err (result);
1259         }
1260     }
1261
1262   result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage",
1263                                     &value, 0);
1264   if (result < 0)
1265     {
1266       gnutls_assert ();
1267       asn1_delete_structure (&ext);
1268       return result;
1269     }
1270
1271   if (policyLanguage)
1272     *policyLanguage = gnutls_strdup (value.data);
1273
1274   result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value, 0);
1275   if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1276     {
1277       if (policy)
1278         *policy = NULL;
1279       if (sizeof_policy)
1280         *sizeof_policy = 0;
1281     }
1282   else if (result < 0)
1283     {
1284       gnutls_assert ();
1285       asn1_delete_structure (&ext);
1286       return result;
1287     }
1288   else
1289     {
1290       if (policy)
1291         *policy = value.data;
1292       if (sizeof_policy)
1293         *sizeof_policy = value.size;
1294     }
1295
1296   asn1_delete_structure (&ext);
1297
1298   return 0;
1299 }
1300
1301 /* generate the proxyCertInfo in a DER encoded extension
1302  */
1303 int
1304 _gnutls_x509_ext_gen_proxyCertInfo (int pathLenConstraint,
1305                                     const char *policyLanguage,
1306                                     const char *policy,
1307                                     size_t sizeof_policy,
1308                                     gnutls_datum_t * der_ext)
1309 {
1310   ASN1_TYPE ext = ASN1_TYPE_EMPTY;
1311   int result;
1312
1313   result = asn1_create_element (_gnutls_get_pkix (),
1314                                 "PKIX1.ProxyCertInfo", &ext);
1315   if (result != ASN1_SUCCESS)
1316     {
1317       gnutls_assert ();
1318       return _gnutls_asn2err (result);
1319     }
1320
1321   if (pathLenConstraint < 0)
1322     {
1323       result = asn1_write_value (ext, "pCPathLenConstraint", NULL, 0);
1324       if (result < 0)
1325         result = _gnutls_asn2err (result);
1326     }
1327   else
1328     result = _gnutls_x509_write_uint32 (ext, "pCPathLenConstraint",
1329                                         pathLenConstraint);
1330   if (result < 0)
1331     {
1332       gnutls_assert ();
1333       asn1_delete_structure (&ext);
1334       return result;
1335     }
1336
1337   result = asn1_write_value (ext, "proxyPolicy.policyLanguage",
1338                              policyLanguage, 1);
1339   if (result < 0)
1340     {
1341       gnutls_assert ();
1342       asn1_delete_structure (&ext);
1343       return _gnutls_asn2err (result);
1344     }
1345
1346   result = asn1_write_value (ext, "proxyPolicy.policy",
1347                              policy, sizeof_policy);
1348   if (result < 0)
1349     {
1350       gnutls_assert ();
1351       asn1_delete_structure (&ext);
1352       return _gnutls_asn2err (result);
1353     }
1354
1355   result = _gnutls_x509_der_encode (ext, "", der_ext, 0);
1356
1357   asn1_delete_structure (&ext);
1358
1359   if (result < 0)
1360     {
1361       gnutls_assert ();
1362       return result;
1363     }
1364
1365   return 0;
1366 }