Tizen 2.0 Release
[external/libgnutls26.git] / lib / x509 / crq.c
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2008, 2009, 2010, 2011 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 /* This file contains functions to handle PKCS #10 certificate
27    requests, see RFC 2986.
28  */
29
30 #include <gnutls_int.h>
31
32 #ifdef ENABLE_PKI
33
34 #include <gnutls_datum.h>
35 #include <gnutls_global.h>
36 #include <gnutls_errors.h>
37 #include <common.h>
38 #include <gnutls_x509.h>
39 #include <x509_b64.h>
40 #include "x509_int.h"
41 #include <libtasn1.h>
42
43 /**
44  * gnutls_x509_crq_init:
45  * @crq: The structure to be initialized
46  *
47  * This function will initialize a PKCS#10 certificate request
48  * structure.
49  *
50  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
51  *   negative error value.
52  **/
53 int
54 gnutls_x509_crq_init (gnutls_x509_crq_t * crq)
55 {
56   int result;
57
58   *crq = gnutls_calloc (1, sizeof (gnutls_x509_crq_int));
59   if (!*crq)
60     return GNUTLS_E_MEMORY_ERROR;
61
62   result = asn1_create_element (_gnutls_get_pkix (),
63                                 "PKIX1.pkcs-10-CertificationRequest",
64                                 &((*crq)->crq));
65   if (result != ASN1_SUCCESS)
66     {
67       gnutls_assert ();
68       gnutls_free (*crq);
69       return _gnutls_asn2err (result);
70     }
71
72   return 0;
73 }
74
75 /**
76  * gnutls_x509_crq_deinit:
77  * @crq: The structure to be initialized
78  *
79  * This function will deinitialize a PKCS#10 certificate request
80  * structure.
81  **/
82 void
83 gnutls_x509_crq_deinit (gnutls_x509_crq_t crq)
84 {
85   if (!crq)
86     return;
87
88   if (crq->crq)
89     asn1_delete_structure (&crq->crq);
90
91   gnutls_free (crq);
92 }
93
94 #define PEM_CRQ "NEW CERTIFICATE REQUEST"
95 #define PEM_CRQ2 "CERTIFICATE REQUEST"
96
97 /**
98  * gnutls_x509_crq_import:
99  * @crq: The structure to store the parsed certificate request.
100  * @data: The DER or PEM encoded certificate.
101  * @format: One of DER or PEM
102  *
103  * This function will convert the given DER or PEM encoded certificate
104  * request to a #gnutls_x509_crq_t structure.  The output will be
105  * stored in @crq.
106  *
107  * If the Certificate is PEM encoded it should have a header of "NEW
108  * CERTIFICATE REQUEST".
109  *
110  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
111  *   negative error value.
112  **/
113 int
114 gnutls_x509_crq_import (gnutls_x509_crq_t crq,
115                         const gnutls_datum_t * data,
116                         gnutls_x509_crt_fmt_t format)
117 {
118   int result = 0, need_free = 0;
119   gnutls_datum_t _data;
120
121   if (crq == NULL)
122     {
123       gnutls_assert ();
124       return GNUTLS_E_INVALID_REQUEST;
125     }
126
127   _data.data = data->data;
128   _data.size = data->size;
129
130   /* If the Certificate is in PEM format then decode it
131    */
132   if (format == GNUTLS_X509_FMT_PEM)
133     {
134       opaque *out;
135
136       /* Try the first header */
137       result = _gnutls_fbase64_decode (PEM_CRQ, data->data, data->size, &out);
138
139       if (result <= 0)          /* Go for the second header */
140         result =
141           _gnutls_fbase64_decode (PEM_CRQ2, data->data, data->size, &out);
142
143       if (result <= 0)
144         {
145           if (result == 0)
146             result = GNUTLS_E_INTERNAL_ERROR;
147           gnutls_assert ();
148           return result;
149         }
150
151       _data.data = out;
152       _data.size = result;
153
154       need_free = 1;
155     }
156
157   result = asn1_der_decoding (&crq->crq, _data.data, _data.size, NULL);
158   if (result != ASN1_SUCCESS)
159     {
160       result = _gnutls_asn2err (result);
161       gnutls_assert ();
162       goto cleanup;
163     }
164
165   result = 0;
166
167 cleanup:
168   if (need_free)
169     _gnutls_free_datum (&_data);
170   return result;
171 }
172
173
174
175 /**
176  * gnutls_x509_crq_get_dn:
177  * @crq: should contain a #gnutls_x509_crq_t structure
178  * @buf: a pointer to a structure to hold the name (may be %NULL)
179  * @sizeof_buf: initially holds the size of @buf
180  *
181  * This function will copy the name of the Certificate request subject
182  * to the provided buffer.  The name will be in the form
183  * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC 2253. The output string
184  * @buf will be ASCII or UTF-8 encoded, depending on the certificate
185  * data.
186  *
187  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
188  *   long enough, and in that case the *@sizeof_buf will be updated with
189  *   the required size.  On success 0 is returned.
190  **/
191 int
192 gnutls_x509_crq_get_dn (gnutls_x509_crq_t crq, char *buf, size_t * sizeof_buf)
193 {
194   if (crq == NULL)
195     {
196       gnutls_assert ();
197       return GNUTLS_E_INVALID_REQUEST;
198     }
199
200   return _gnutls_x509_parse_dn (crq->crq,
201                                 "certificationRequestInfo.subject.rdnSequence",
202                                 buf, sizeof_buf);
203 }
204
205 /**
206  * gnutls_x509_crq_get_dn_by_oid:
207  * @crq: should contain a gnutls_x509_crq_t structure
208  * @oid: holds an Object Identified in null terminated string
209  * @indx: In case multiple same OIDs exist in the RDN, this specifies
210  *   which to send. Use zero to get the first one.
211  * @raw_flag: If non zero returns the raw DER data of the DN part.
212  * @buf: a pointer to a structure to hold the name (may be %NULL)
213  * @sizeof_buf: initially holds the size of @buf
214  *
215  * This function will extract the part of the name of the Certificate
216  * request subject, specified by the given OID. The output will be
217  * encoded as described in RFC2253. The output string will be ASCII
218  * or UTF-8 encoded, depending on the certificate data.
219  *
220  * Some helper macros with popular OIDs can be found in gnutls/x509.h
221  * If raw flag is zero, this function will only return known OIDs as
222  * text. Other OIDs will be DER encoded, as described in RFC2253 --
223  * in hex format with a '\#' prefix.  You can check about known OIDs
224  * using gnutls_x509_dn_oid_known().
225  *
226  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
227  *   not long enough, and in that case the *@sizeof_buf will be
228  *   updated with the required size.  On success 0 is returned.
229  **/
230 int
231 gnutls_x509_crq_get_dn_by_oid (gnutls_x509_crq_t crq, const char *oid,
232                                int indx, unsigned int raw_flag,
233                                void *buf, size_t * sizeof_buf)
234 {
235   if (crq == NULL)
236     {
237       gnutls_assert ();
238       return GNUTLS_E_INVALID_REQUEST;
239     }
240
241   return _gnutls_x509_parse_dn_oid
242     (crq->crq,
243      "certificationRequestInfo.subject.rdnSequence",
244      oid, indx, raw_flag, buf, sizeof_buf);
245 }
246
247 /**
248  * gnutls_x509_crq_get_dn_oid:
249  * @crq: should contain a gnutls_x509_crq_t structure
250  * @indx: Specifies which DN OID to send. Use zero to get the first one.
251  * @oid: a pointer to a structure to hold the name (may be %NULL)
252  * @sizeof_oid: initially holds the size of @oid
253  *
254  * This function will extract the requested OID of the name of the
255  * certificate request subject, specified by the given index.
256  *
257  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
258  *   not long enough, and in that case the *@sizeof_oid will be
259  *   updated with the required size.  On success 0 is returned.
260  **/
261 int
262 gnutls_x509_crq_get_dn_oid (gnutls_x509_crq_t crq,
263                             int indx, void *oid, size_t * sizeof_oid)
264 {
265   if (crq == NULL)
266     {
267       gnutls_assert ();
268       return GNUTLS_E_INVALID_REQUEST;
269     }
270
271   return _gnutls_x509_get_dn_oid (crq->crq,
272                                   "certificationRequestInfo.subject.rdnSequence",
273                                   indx, oid, sizeof_oid);
274 }
275
276 /* Parses an Attribute list in the asn1_struct, and searches for the
277  * given OID. The index indicates the attribute value to be returned.
278  *
279  * If raw==0 only printable data are returned, or
280  * GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
281  *
282  * asn1_attr_name must be a string in the form
283  * "certificationRequestInfo.attributes"
284  *
285  */
286 static int
287 parse_attribute (ASN1_TYPE asn1_struct,
288                  const char *attr_name, const char *given_oid, int indx,
289                  int raw, char *buf, size_t * sizeof_buf)
290 {
291   int k1, result;
292   char tmpbuffer1[ASN1_MAX_NAME_SIZE];
293   char tmpbuffer3[ASN1_MAX_NAME_SIZE];
294   char value[200];
295   char oid[MAX_OID_SIZE];
296   int len, printable;
297
298   k1 = 0;
299   do
300     {
301
302       k1++;
303       /* create a string like "attribute.?1"
304        */
305       if (attr_name[0] != 0)
306         snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", attr_name, k1);
307       else
308         snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
309
310       len = sizeof (value) - 1;
311       result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);
312
313       if (result == ASN1_ELEMENT_NOT_FOUND)
314         {
315           gnutls_assert ();
316           break;
317         }
318
319       if (result != ASN1_VALUE_NOT_FOUND)
320         {
321           gnutls_assert ();
322           result = _gnutls_asn2err (result);
323           goto cleanup;
324         }
325
326       /* Move to the attibute type and values
327        */
328       /* Read the OID
329        */
330       _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer1);
331       _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");
332
333       len = sizeof (oid) - 1;
334       result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);
335
336       if (result == ASN1_ELEMENT_NOT_FOUND)
337         break;
338       else if (result != ASN1_SUCCESS)
339         {
340           gnutls_assert ();
341           result = _gnutls_asn2err (result);
342           goto cleanup;
343         }
344
345       if (strcmp (oid, given_oid) == 0)
346         {                       /* Found the OID */
347
348           /* Read the Value
349            */
350           snprintf (tmpbuffer3, sizeof (tmpbuffer3), "%s.values.?%u",
351                     tmpbuffer1, indx + 1);
352
353           len = sizeof (value) - 1;
354           result = asn1_read_value (asn1_struct, tmpbuffer3, value, &len);
355
356           if (result != ASN1_SUCCESS)
357             {
358               gnutls_assert ();
359               result = _gnutls_asn2err (result);
360               goto cleanup;
361             }
362
363           if (raw == 0)
364             {
365               printable = _gnutls_x509_oid_data_printable (oid);
366               if (printable == 1)
367                 {
368                   if ((result =
369                        _gnutls_x509_oid_data2string
370                        (oid, value, len, buf, sizeof_buf)) < 0)
371                     {
372                       gnutls_assert ();
373                       goto cleanup;
374                     }
375                   return 0;
376                 }
377               else
378                 {
379                   gnutls_assert ();
380                   return GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE;
381                 }
382             }
383           else
384             {                   /* raw!=0 */
385               if (*sizeof_buf >= (size_t) len && buf != NULL)
386                 {
387                   *sizeof_buf = len;
388                   memcpy (buf, value, len);
389
390                   return 0;
391                 }
392               else
393                 {
394                   *sizeof_buf = len;
395                   return GNUTLS_E_SHORT_MEMORY_BUFFER;
396                 }
397             }
398         }
399
400     }
401   while (1);
402
403   gnutls_assert ();
404
405   result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
406
407 cleanup:
408   return result;
409 }
410
411 /**
412  * gnutls_x509_crq_get_challenge_password:
413  * @crq: should contain a #gnutls_x509_crq_t structure
414  * @pass: will hold a zero-terminated password string
415  * @sizeof_pass: Initially holds the size of @pass.
416  *
417  * This function will return the challenge password in the request.
418  * The challenge password is intended to be used for requesting a
419  * revocation of the certificate.
420  *
421  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
422  *   negative error value.
423  **/
424 int
425 gnutls_x509_crq_get_challenge_password (gnutls_x509_crq_t crq,
426                                         char *pass, size_t * sizeof_pass)
427 {
428   if (crq == NULL)
429     {
430       gnutls_assert ();
431       return GNUTLS_E_INVALID_REQUEST;
432     }
433
434   return parse_attribute (crq->crq, "certificationRequestInfo.attributes",
435                           "1.2.840.113549.1.9.7", 0, 0, pass, sizeof_pass);
436 }
437
438 /* This function will attempt to set the requested attribute in
439  * the given X509v3 certificate.
440  *
441  * Critical will be either 0 or 1.
442  */
443 static int
444 add_attribute (ASN1_TYPE asn, const char *root, const char *attribute_id,
445                const gnutls_datum_t * ext_data)
446 {
447   int result;
448   char name[ASN1_MAX_NAME_SIZE];
449
450   snprintf (name, sizeof (name), "%s", root);
451
452   /* Add a new attribute in the list.
453    */
454   result = asn1_write_value (asn, name, "NEW", 1);
455   if (result != ASN1_SUCCESS)
456     {
457       gnutls_assert ();
458       return _gnutls_asn2err (result);
459     }
460
461   snprintf (name, sizeof (name), "%s.?LAST.type", root);
462
463   result = asn1_write_value (asn, name, attribute_id, 1);
464   if (result != ASN1_SUCCESS)
465     {
466       gnutls_assert ();
467       return _gnutls_asn2err (result);
468     }
469
470   snprintf (name, sizeof (name), "%s.?LAST.values", root);
471
472   result = asn1_write_value (asn, name, "NEW", 1);
473   if (result != ASN1_SUCCESS)
474     {
475       gnutls_assert ();
476       return _gnutls_asn2err (result);
477     }
478
479   snprintf (name, sizeof (name), "%s.?LAST.values.?LAST", root);
480
481   result = _gnutls_x509_write_value (asn, name, ext_data, 0);
482   if (result < 0)
483     {
484       gnutls_assert ();
485       return result;
486     }
487
488   return 0;
489 }
490
491 /* Overwrite the given attribute (using the index)
492  * index here starts from one.
493  */
494 static int
495 overwrite_attribute (ASN1_TYPE asn, const char *root, unsigned int indx,
496                      const gnutls_datum_t * ext_data)
497 {
498   char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
499   int result;
500
501   snprintf (name, sizeof (name), "%s.?%u", root, indx);
502
503   _gnutls_str_cpy (name2, sizeof (name2), name);
504   _gnutls_str_cat (name2, sizeof (name2), ".values.?LAST");
505
506   result = _gnutls_x509_write_value (asn, name2, ext_data, 0);
507   if (result < 0)
508     {
509       gnutls_assert ();
510       return result;
511     }
512
513
514   return 0;
515 }
516
517 static int
518 set_attribute (ASN1_TYPE asn, const char *root,
519                const char *ext_id, const gnutls_datum_t * ext_data)
520 {
521   int result;
522   int k, len;
523   char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE];
524   char extnID[MAX_OID_SIZE];
525
526   /* Find the index of the given attribute.
527    */
528   k = 0;
529   do
530     {
531       k++;
532
533       snprintf (name, sizeof (name), "%s.?%u", root, k);
534
535       len = sizeof (extnID) - 1;
536       result = asn1_read_value (asn, name, extnID, &len);
537
538       /* move to next
539        */
540
541       if (result == ASN1_ELEMENT_NOT_FOUND)
542         {
543           break;
544         }
545
546       do
547         {
548
549           _gnutls_str_cpy (name2, sizeof (name2), name);
550           _gnutls_str_cat (name2, sizeof (name2), ".type");
551
552           len = sizeof (extnID) - 1;
553           result = asn1_read_value (asn, name2, extnID, &len);
554
555           if (result == ASN1_ELEMENT_NOT_FOUND)
556             {
557               gnutls_assert ();
558               break;
559             }
560           else if (result != ASN1_SUCCESS)
561             {
562               gnutls_assert ();
563               return _gnutls_asn2err (result);
564             }
565
566           /* Handle Extension
567            */
568           if (strcmp (extnID, ext_id) == 0)
569             {
570               /* attribute was found
571                */
572               return overwrite_attribute (asn, root, k, ext_data);
573             }
574
575
576         }
577       while (0);
578     }
579   while (1);
580
581   if (result == ASN1_ELEMENT_NOT_FOUND)
582     {
583       return add_attribute (asn, root, ext_id, ext_data);
584     }
585   else
586     {
587       gnutls_assert ();
588       return _gnutls_asn2err (result);
589     }
590
591
592   return 0;
593 }
594
595 /**
596  * gnutls_x509_crq_set_attribute_by_oid:
597  * @crq: should contain a #gnutls_x509_crq_t structure
598  * @oid: holds an Object Identified in zero-terminated string
599  * @buf: a pointer to a structure that holds the attribute data
600  * @sizeof_buf: holds the size of @buf
601  *
602  * This function will set the attribute in the certificate request
603  * specified by the given Object ID.  The attribute must be be DER
604  * encoded.
605  *
606  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
607  *   negative error value.
608  **/
609 int
610 gnutls_x509_crq_set_attribute_by_oid (gnutls_x509_crq_t crq,
611                                       const char *oid, void *buf,
612                                       size_t sizeof_buf)
613 {
614   gnutls_datum_t data;
615
616   data.data = buf;
617   data.size = sizeof_buf;
618
619   if (crq == NULL)
620     {
621       gnutls_assert ();
622       return GNUTLS_E_INVALID_REQUEST;
623     }
624
625   return set_attribute (crq->crq, "certificationRequestInfo.attributes",
626                         oid, &data);
627 }
628
629 /**
630  * gnutls_x509_crq_get_attribute_by_oid:
631  * @crq: should contain a #gnutls_x509_crq_t structure
632  * @oid: holds an Object Identified in zero-terminated string
633  * @indx: In case multiple same OIDs exist in the attribute list, this
634  *   specifies which to send, use zero to get the first one
635  * @buf: a pointer to a structure to hold the attribute data (may be %NULL)
636  * @sizeof_buf: initially holds the size of @buf
637  *
638  * This function will return the attribute in the certificate request
639  * specified by the given Object ID.  The attribute will be DER
640  * encoded.
641  *
642  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
643  *   negative error value.
644  **/
645 int
646 gnutls_x509_crq_get_attribute_by_oid (gnutls_x509_crq_t crq,
647                                       const char *oid, int indx, void *buf,
648                                       size_t * sizeof_buf)
649 {
650   if (crq == NULL)
651     {
652       gnutls_assert ();
653       return GNUTLS_E_INVALID_REQUEST;
654     }
655
656   return parse_attribute (crq->crq, "certificationRequestInfo.attributes",
657                           oid, indx, 1, buf, sizeof_buf);
658 }
659
660 /**
661  * gnutls_x509_crq_set_dn_by_oid:
662  * @crq: should contain a #gnutls_x509_crq_t structure
663  * @oid: holds an Object Identifier in a zero-terminated string
664  * @raw_flag: must be 0, or 1 if the data are DER encoded
665  * @data: a pointer to the input data
666  * @sizeof_data: holds the size of @data
667  *
668  * This function will set the part of the name of the Certificate
669  * request subject, specified by the given OID.  The input string
670  * should be ASCII or UTF-8 encoded.
671  *
672  * Some helper macros with popular OIDs can be found in gnutls/x509.h
673  * With this function you can only set the known OIDs.  You can test
674  * for known OIDs using gnutls_x509_dn_oid_known().  For OIDs that are
675  * not known (by gnutls) you should properly DER encode your data, and
676  * call this function with raw_flag set.
677  *
678  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
679  *   negative error value.
680  **/
681 int
682 gnutls_x509_crq_set_dn_by_oid (gnutls_x509_crq_t crq, const char *oid,
683                                unsigned int raw_flag, const void *data,
684                                unsigned int sizeof_data)
685 {
686   if (sizeof_data == 0 || data == NULL || crq == NULL)
687     {
688       return GNUTLS_E_INVALID_REQUEST;
689     }
690
691   return _gnutls_x509_set_dn_oid (crq->crq,
692                                   "certificationRequestInfo.subject", oid,
693                                   raw_flag, data, sizeof_data);
694 }
695
696 /**
697  * gnutls_x509_crq_set_version:
698  * @crq: should contain a #gnutls_x509_crq_t structure
699  * @version: holds the version number, for v1 Requests must be 1
700  *
701  * This function will set the version of the certificate request.  For
702  * version 1 requests this must be one.
703  *
704  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
705  *   negative error value.
706  **/
707 int
708 gnutls_x509_crq_set_version (gnutls_x509_crq_t crq, unsigned int version)
709 {
710   int result;
711   unsigned char null = version;
712
713   if (crq == NULL)
714     {
715       gnutls_assert ();
716       return GNUTLS_E_INVALID_REQUEST;
717     }
718
719   if (null > 0)
720     null--;
721
722   result =
723     asn1_write_value (crq->crq, "certificationRequestInfo.version", &null, 1);
724   if (result != ASN1_SUCCESS)
725     {
726       gnutls_assert ();
727       return _gnutls_asn2err (result);
728     }
729
730   return 0;
731 }
732
733 /**
734  * gnutls_x509_crq_get_version:
735  * @crq: should contain a #gnutls_x509_crq_t structure
736  *
737  * This function will return the version of the specified Certificate
738  * request.
739  *
740  * Returns: version of certificate request, or a negative value on
741  *   error.
742  **/
743 int
744 gnutls_x509_crq_get_version (gnutls_x509_crq_t crq)
745 {
746   opaque version[8];
747   int len, result;
748
749   if (crq == NULL)
750     {
751       gnutls_assert ();
752       return GNUTLS_E_INVALID_REQUEST;
753     }
754
755   len = sizeof (version);
756   if ((result =
757        asn1_read_value (crq->crq, "certificationRequestInfo.version",
758                         version, &len)) != ASN1_SUCCESS)
759     {
760
761       if (result == ASN1_ELEMENT_NOT_FOUND)
762         return 1;               /* the DEFAULT version */
763       gnutls_assert ();
764       return _gnutls_asn2err (result);
765     }
766
767   return (int) version[0] + 1;
768 }
769
770 /**
771  * gnutls_x509_crq_set_key:
772  * @crq: should contain a #gnutls_x509_crq_t structure
773  * @key: holds a private key
774  *
775  * This function will set the public parameters from the given private
776  * key to the request.  Only RSA keys are currently supported.
777  *
778  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
779  *   negative error value.
780  **/
781 int
782 gnutls_x509_crq_set_key (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key)
783 {
784   int result;
785
786   if (crq == NULL)
787     {
788       gnutls_assert ();
789       return GNUTLS_E_INVALID_REQUEST;
790     }
791
792   result = _gnutls_x509_encode_and_copy_PKI_params
793     (crq->crq,
794      "certificationRequestInfo.subjectPKInfo",
795      key->pk_algorithm, key->params, key->params_size);
796
797   if (result < 0)
798     {
799       gnutls_assert ();
800       return result;
801     }
802
803   return 0;
804 }
805
806 /**
807  * gnutls_x509_crq_get_key_rsa_raw:
808  * @crq: Holds the certificate
809  * @m: will hold the modulus
810  * @e: will hold the public exponent
811  *
812  * This function will export the RSA public key's parameters found in
813  * the given structure.  The new parameters will be allocated using
814  * gnutls_malloc() and will be stored in the appropriate datum.
815  *
816  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
817  *   negative error value.
818  *
819  * Since: 2.8.0
820  **/
821 int
822 gnutls_x509_crq_get_key_rsa_raw (gnutls_x509_crq_t crq,
823                                  gnutls_datum_t * m, gnutls_datum_t * e)
824 {
825   int ret;
826   bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
827   int params_size = MAX_PUBLIC_PARAMS_SIZE;
828   int i;
829
830   if (crq == NULL)
831     {
832       gnutls_assert ();
833       return GNUTLS_E_INVALID_REQUEST;
834     }
835
836   ret = gnutls_x509_crq_get_pk_algorithm (crq, NULL);
837   if (ret != GNUTLS_PK_RSA)
838     {
839       gnutls_assert ();
840       return GNUTLS_E_INVALID_REQUEST;
841     }
842
843   ret = _gnutls_x509_crq_get_mpis (crq, params, &params_size);
844   if (ret < 0)
845     {
846       gnutls_assert ();
847       return ret;
848     }
849
850   ret = _gnutls_mpi_dprint (params[0], m);
851   if (ret < 0)
852     {
853       gnutls_assert ();
854       goto cleanup;
855     }
856
857   ret = _gnutls_mpi_dprint (params[1], e);
858   if (ret < 0)
859     {
860       gnutls_assert ();
861       _gnutls_free_datum (m);
862       goto cleanup;
863     }
864
865   ret = 0;
866
867 cleanup:
868   for (i = 0; i < params_size; i++)
869     {
870       _gnutls_mpi_release (&params[i]);
871     }
872   return ret;
873 }
874
875 /**
876  * gnutls_x509_crq_set_key_rsa_raw:
877  * @crq: should contain a #gnutls_x509_crq_t structure
878  * @m: holds the modulus
879  * @e: holds the public exponent
880  *
881  * This function will set the public parameters from the given private
882  * key to the request. Only RSA keys are currently supported.
883  *
884  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
885  *   negative error value.
886  *
887  * Since: 2.6.0
888  **/
889 int
890 gnutls_x509_crq_set_key_rsa_raw (gnutls_x509_crq_t crq,
891                                  const gnutls_datum_t * m,
892                                  const gnutls_datum_t * e)
893 {
894   int result, ret;
895   size_t siz = 0;
896   bigint_t temp_params[RSA_PUBLIC_PARAMS];
897
898   if (crq == NULL)
899     {
900       gnutls_assert ();
901       return GNUTLS_E_INVALID_REQUEST;
902     }
903
904   memset (temp_params, 0, sizeof (temp_params));
905
906   siz = m->size;
907   if (_gnutls_mpi_scan_nz (&temp_params[0], m->data, siz))
908     {
909       gnutls_assert ();
910       ret = GNUTLS_E_MPI_SCAN_FAILED;
911       goto error;
912     }
913
914   siz = e->size;
915   if (_gnutls_mpi_scan_nz (&temp_params[1], e->data, siz))
916     {
917       gnutls_assert ();
918       ret = GNUTLS_E_MPI_SCAN_FAILED;
919       goto error;
920     }
921
922   result = _gnutls_x509_encode_and_copy_PKI_params
923     (crq->crq,
924      "certificationRequestInfo.subjectPKInfo",
925      GNUTLS_PK_RSA, temp_params, RSA_PUBLIC_PARAMS);
926
927   if (result < 0)
928     {
929       gnutls_assert ();
930       ret = result;
931       goto error;
932     }
933
934   ret = 0;
935
936 error:
937   _gnutls_mpi_release (&temp_params[0]);
938   _gnutls_mpi_release (&temp_params[1]);
939   return ret;
940 }
941
942 /**
943  * gnutls_x509_crq_set_challenge_password:
944  * @crq: should contain a #gnutls_x509_crq_t structure
945  * @pass: holds a zero-terminated password
946  *
947  * This function will set a challenge password to be used when
948  * revoking the request.
949  *
950  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
951  *   negative error value.
952  **/
953 int
954 gnutls_x509_crq_set_challenge_password (gnutls_x509_crq_t crq,
955                                         const char *pass)
956 {
957   int result;
958
959   if (crq == NULL)
960     {
961       gnutls_assert ();
962       return GNUTLS_E_INVALID_REQUEST;
963     }
964
965   /* Add the attribute.
966    */
967   result = asn1_write_value (crq->crq, "certificationRequestInfo.attributes",
968                              "NEW", 1);
969   if (result != ASN1_SUCCESS)
970     {
971       gnutls_assert ();
972       return _gnutls_asn2err (result);
973     }
974
975   result = _gnutls_x509_encode_and_write_attribute
976     ("1.2.840.113549.1.9.7", crq->crq,
977      "certificationRequestInfo.attributes.?LAST", pass, strlen (pass), 1);
978   if (result < 0)
979     {
980       gnutls_assert ();
981       return result;
982     }
983
984   return 0;
985 }
986
987 /**
988  * gnutls_x509_crq_sign2:
989  * @crq: should contain a #gnutls_x509_crq_t structure
990  * @key: holds a private key
991  * @dig: The message digest to use, i.e., %GNUTLS_DIG_SHA1
992  * @flags: must be 0
993  *
994  * This function will sign the certificate request with a private key.
995  * This must be the same key as the one used in
996  * gnutls_x509_crt_set_key() since a certificate request is self
997  * signed.
998  *
999  * This must be the last step in a certificate request generation
1000  * since all the previously set parameters are now signed.
1001  *
1002  * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
1003  *   %GNUTLS_E_ASN1_VALUE_NOT_FOUND is returned if you didn't set all
1004  *   information in the certificate request (e.g., the version using
1005  *   gnutls_x509_crq_set_version()).
1006  *
1007  * Deprecated: Use gnutls_x509_crq_privkey_sign() instead.
1008  **/
1009 int
1010 gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key,
1011                        gnutls_digest_algorithm_t dig, unsigned int flags)
1012 {
1013   int result;
1014   gnutls_privkey_t privkey;
1015
1016   if (crq == NULL)
1017     {
1018       gnutls_assert ();
1019       return GNUTLS_E_INVALID_REQUEST;
1020     }
1021
1022   result = gnutls_privkey_init (&privkey);
1023   if (result < 0)
1024     {
1025       gnutls_assert ();
1026       return result;
1027     }
1028
1029   result = gnutls_privkey_import_x509 (privkey, key, 0);
1030   if (result < 0)
1031     {
1032       gnutls_assert ();
1033       goto fail;
1034     }
1035
1036   result = gnutls_x509_crq_privkey_sign (crq, privkey, dig, flags);
1037   if (result < 0)
1038     {
1039       gnutls_assert ();
1040       goto fail;
1041     }
1042
1043   result = 0;
1044
1045 fail:
1046   gnutls_privkey_deinit (privkey);
1047
1048   return result;
1049 }
1050
1051 /**
1052  * gnutls_x509_crq_sign:
1053  * @crq: should contain a #gnutls_x509_crq_t structure
1054  * @key: holds a private key
1055  *
1056  * This function is the same a gnutls_x509_crq_sign2() with no flags,
1057  * and SHA1 as the hash algorithm.
1058  *
1059  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1060  *   negative error value.
1061  *
1062  * Deprecated: Use gnutls_x509_crq_privkey_sign() instead.
1063  */
1064 int
1065 gnutls_x509_crq_sign (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key)
1066 {
1067   return gnutls_x509_crq_sign2 (crq, key, GNUTLS_DIG_SHA1, 0);
1068 }
1069
1070 /**
1071  * gnutls_x509_crq_export:
1072  * @crq: should contain a #gnutls_x509_crq_t structure
1073  * @format: the format of output params. One of PEM or DER.
1074  * @output_data: will contain a certificate request PEM or DER encoded
1075  * @output_data_size: holds the size of output_data (and will be
1076  *   replaced by the actual size of parameters)
1077  *
1078  * This function will export the certificate request to a PEM or DER
1079  * encoded PKCS10 structure.
1080  *
1081  * If the buffer provided is not long enough to hold the output, then
1082  * %GNUTLS_E_SHORT_MEMORY_BUFFER will be returned and
1083  * *@output_data_size will be updated.
1084  *
1085  * If the structure is PEM encoded, it will have a header of "BEGIN
1086  * NEW CERTIFICATE REQUEST".
1087  *
1088  * Return value: In case of failure a negative value will be
1089  *   returned, and 0 on success.
1090  **/
1091 int
1092 gnutls_x509_crq_export (gnutls_x509_crq_t crq,
1093                         gnutls_x509_crt_fmt_t format, void *output_data,
1094                         size_t * output_data_size)
1095 {
1096   if (crq == NULL)
1097     {
1098       gnutls_assert ();
1099       return GNUTLS_E_INVALID_REQUEST;
1100     }
1101
1102   return _gnutls_x509_export_int (crq->crq, format, PEM_CRQ,
1103                                   output_data, output_data_size);
1104 }
1105
1106 /**
1107  * gnutls_x509_crq_get_pk_algorithm:
1108  * @crq: should contain a #gnutls_x509_crq_t structure
1109  * @bits: if bits is non-%NULL it will hold the size of the parameters' in bits
1110  *
1111  * This function will return the public key algorithm of a PKCS#10
1112  * certificate request.
1113  *
1114  * If bits is non-%NULL, it should have enough size to hold the
1115  * parameters size in bits.  For RSA the bits returned is the modulus.
1116  * For DSA the bits returned are of the public exponent.
1117  *
1118  * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
1119  *   success, or a negative value on error.
1120  **/
1121 int
1122 gnutls_x509_crq_get_pk_algorithm (gnutls_x509_crq_t crq, unsigned int *bits)
1123 {
1124   int result;
1125
1126   if (crq == NULL)
1127     {
1128       gnutls_assert ();
1129       return GNUTLS_E_INVALID_REQUEST;
1130     }
1131
1132   result = _gnutls_x509_get_pk_algorithm
1133     (crq->crq, "certificationRequestInfo.subjectPKInfo", bits);
1134   if (result < 0)
1135     {
1136       gnutls_assert ();
1137     }
1138
1139   return result;
1140 }
1141
1142 /**
1143  * gnutls_x509_crq_get_attribute_info:
1144  * @crq: should contain a #gnutls_x509_crq_t structure
1145  * @indx: Specifies which attribute OID to send. Use zero to get the first one.
1146  * @oid: a pointer to a structure to hold the OID
1147  * @sizeof_oid: initially holds the maximum size of @oid, on return
1148  *   holds actual size of @oid.
1149  *
1150  * This function will return the requested attribute OID in the
1151  * certificate, and the critical flag for it.  The attribute OID will
1152  * be stored as a string in the provided buffer.  Use
1153  * gnutls_x509_crq_get_attribute_data() to extract the data.
1154  *
1155  * If the buffer provided is not long enough to hold the output, then
1156  * *@sizeof_oid is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will be
1157  * returned.
1158  *
1159  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1160  *   negative value in case of an error.  If your have reached the
1161  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1162  *   will be returned.
1163  *
1164  * Since: 2.8.0
1165  **/
1166 int
1167 gnutls_x509_crq_get_attribute_info (gnutls_x509_crq_t crq, int indx,
1168                                     void *oid, size_t * sizeof_oid)
1169 {
1170   int result;
1171   char name[ASN1_MAX_NAME_SIZE];
1172   int len;
1173
1174   if (!crq)
1175     {
1176       gnutls_assert ();
1177       return GNUTLS_E_INVALID_REQUEST;
1178     }
1179
1180   snprintf (name, sizeof (name),
1181             "certificationRequestInfo.attributes.?%u.type", indx + 1);
1182
1183   len = *sizeof_oid;
1184   result = asn1_read_value (crq->crq, name, oid, &len);
1185   *sizeof_oid = len;
1186
1187   if (result == ASN1_ELEMENT_NOT_FOUND)
1188     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1189   else if (result < 0)
1190     {
1191       gnutls_assert ();
1192       return _gnutls_asn2err (result);
1193     }
1194
1195   return 0;
1196
1197 }
1198
1199 /**
1200  * gnutls_x509_crq_get_attribute_data:
1201  * @crq: should contain a #gnutls_x509_crq_t structure
1202  * @indx: Specifies which attribute OID to send. Use zero to get the first one.
1203  * @data: a pointer to a structure to hold the data (may be null)
1204  * @sizeof_data: initially holds the size of @oid
1205  *
1206  * This function will return the requested attribute data in the
1207  * certificate request.  The attribute data will be stored as a string in the
1208  * provided buffer.
1209  *
1210  * Use gnutls_x509_crq_get_attribute_info() to extract the OID.
1211  * Use gnutls_x509_crq_get_attribute_by_oid() instead,
1212  * if you want to get data indexed by the attribute OID rather than
1213  * sequence.
1214  *
1215  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1216  *   negative value in case of an error.  If your have reached the
1217  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1218  *   will be returned.
1219  *
1220  * Since: 2.8.0
1221  **/
1222 int
1223 gnutls_x509_crq_get_attribute_data (gnutls_x509_crq_t crq, int indx,
1224                                     void *data, size_t * sizeof_data)
1225 {
1226   int result, len;
1227   char name[ASN1_MAX_NAME_SIZE];
1228
1229   if (!crq)
1230     {
1231       gnutls_assert ();
1232       return GNUTLS_E_INVALID_REQUEST;
1233     }
1234
1235   snprintf (name, sizeof (name),
1236             "certificationRequestInfo.attributes.?%u.values.?1", indx + 1);
1237
1238   len = *sizeof_data;
1239   result = asn1_read_value (crq->crq, name, data, &len);
1240   *sizeof_data = len;
1241
1242   if (result == ASN1_ELEMENT_NOT_FOUND)
1243     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1244   else if (result < 0)
1245     {
1246       gnutls_assert ();
1247       return _gnutls_asn2err (result);
1248     }
1249
1250   return 0;
1251 }
1252
1253 /**
1254  * gnutls_x509_crq_get_extension_info:
1255  * @crq: should contain a #gnutls_x509_crq_t structure
1256  * @indx: Specifies which extension OID to send. Use zero to get the first one.
1257  * @oid: a pointer to a structure to hold the OID
1258  * @sizeof_oid: initially holds the maximum size of @oid, on return
1259  *   holds actual size of @oid.
1260  * @critical: output variable with critical flag, may be NULL.
1261  *
1262  * This function will return the requested extension OID in the
1263  * certificate, and the critical flag for it.  The extension OID will
1264  * be stored as a string in the provided buffer.  Use
1265  * gnutls_x509_crq_get_extension_data() to extract the data.
1266  *
1267  * If the buffer provided is not long enough to hold the output, then
1268  * *@sizeof_oid is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will be
1269  * returned.
1270  *
1271  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1272  *   negative value in case of an error.  If your have reached the
1273  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1274  *   will be returned.
1275  *
1276  * Since: 2.8.0
1277  **/
1278 int
1279 gnutls_x509_crq_get_extension_info (gnutls_x509_crq_t crq, int indx,
1280                                     void *oid, size_t * sizeof_oid,
1281                                     int *critical)
1282 {
1283   int result;
1284   char str_critical[10];
1285   char name[ASN1_MAX_NAME_SIZE];
1286   char *extensions = NULL;
1287   size_t extensions_size = 0;
1288   ASN1_TYPE c2;
1289   int len;
1290
1291   if (!crq)
1292     {
1293       gnutls_assert ();
1294       return GNUTLS_E_INVALID_REQUEST;
1295     }
1296
1297   /* read extensionRequest */
1298   result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
1299                                                  0, NULL, &extensions_size);
1300   if (result == GNUTLS_E_SHORT_MEMORY_BUFFER)
1301     {
1302       extensions = gnutls_malloc (extensions_size);
1303       if (extensions == NULL)
1304         {
1305           gnutls_assert ();
1306           return GNUTLS_E_MEMORY_ERROR;
1307         }
1308
1309       result = gnutls_x509_crq_get_attribute_by_oid (crq,
1310                                                      "1.2.840.113549.1.9.14",
1311                                                      0, extensions,
1312                                                      &extensions_size);
1313     }
1314   if (result < 0)
1315     {
1316       gnutls_assert ();
1317       goto out;
1318     }
1319
1320   result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.Extensions", &c2);
1321   if (result != ASN1_SUCCESS)
1322     {
1323       gnutls_assert ();
1324       result = _gnutls_asn2err (result);
1325       goto out;
1326     }
1327
1328   result = asn1_der_decoding (&c2, extensions, extensions_size, NULL);
1329   if (result != ASN1_SUCCESS)
1330     {
1331       gnutls_assert ();
1332       asn1_delete_structure (&c2);
1333       result = _gnutls_asn2err (result);
1334       goto out;
1335     }
1336
1337   snprintf (name, sizeof (name), "?%u.extnID", indx + 1);
1338
1339   len = *sizeof_oid;
1340   result = asn1_read_value (c2, name, oid, &len);
1341   *sizeof_oid = len;
1342
1343   if (result == ASN1_ELEMENT_NOT_FOUND)
1344     {
1345       asn1_delete_structure (&c2);
1346       result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1347       goto out;
1348     }
1349   else if (result < 0)
1350     {
1351       gnutls_assert ();
1352       asn1_delete_structure (&c2);
1353       result = _gnutls_asn2err (result);
1354       goto out;
1355     }
1356
1357   snprintf (name, sizeof (name), "?%u.critical", indx + 1);
1358   len = sizeof (str_critical);
1359   result = asn1_read_value (c2, name, str_critical, &len);
1360
1361   asn1_delete_structure (&c2);
1362
1363   if (result < 0)
1364     {
1365       gnutls_assert ();
1366       result = _gnutls_asn2err (result);
1367       goto out;
1368     }
1369
1370   if (critical)
1371     {
1372       if (str_critical[0] == 'T')
1373         *critical = 1;
1374       else
1375         *critical = 0;
1376     }
1377
1378   result = 0;
1379
1380 out:
1381   gnutls_free (extensions);
1382   return result;
1383 }
1384
1385 /**
1386  * gnutls_x509_crq_get_extension_data:
1387  * @crq: should contain a #gnutls_x509_crq_t structure
1388  * @indx: Specifies which extension OID to send. Use zero to get the first one.
1389  * @data: a pointer to a structure to hold the data (may be null)
1390  * @sizeof_data: initially holds the size of @oid
1391  *
1392  * This function will return the requested extension data in the
1393  * certificate.  The extension data will be stored as a string in the
1394  * provided buffer.
1395  *
1396  * Use gnutls_x509_crq_get_extension_info() to extract the OID and
1397  * critical flag.  Use gnutls_x509_crq_get_extension_by_oid() instead,
1398  * if you want to get data indexed by the extension OID rather than
1399  * sequence.
1400  *
1401  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1402  *   negative value in case of an error.  If your have reached the
1403  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1404  *   will be returned.
1405  *
1406  * Since: 2.8.0
1407  **/
1408 int
1409 gnutls_x509_crq_get_extension_data (gnutls_x509_crq_t crq, int indx,
1410                                     void *data, size_t * sizeof_data)
1411 {
1412   int result, len;
1413   char name[ASN1_MAX_NAME_SIZE];
1414   unsigned char *extensions;
1415   size_t extensions_size = 0;
1416   ASN1_TYPE c2;
1417
1418   if (!crq)
1419     {
1420       gnutls_assert ();
1421       return GNUTLS_E_INVALID_REQUEST;
1422     }
1423
1424   /* read extensionRequest */
1425   result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
1426                                                  0, NULL, &extensions_size);
1427   if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
1428     {
1429       gnutls_assert ();
1430       if (result == 0)
1431         return GNUTLS_E_INTERNAL_ERROR;
1432       return result;
1433     }
1434
1435   extensions = gnutls_malloc (extensions_size);
1436   if (extensions == NULL)
1437     {
1438       gnutls_assert ();
1439       return GNUTLS_E_MEMORY_ERROR;
1440     }
1441
1442   result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14",
1443                                                  0, extensions,
1444                                                  &extensions_size);
1445   if (result < 0)
1446     {
1447       gnutls_assert ();
1448       return result;
1449     }
1450
1451   result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.Extensions", &c2);
1452   if (result != ASN1_SUCCESS)
1453     {
1454       gnutls_assert ();
1455       gnutls_free (extensions);
1456       return _gnutls_asn2err (result);
1457     }
1458
1459   result = asn1_der_decoding (&c2, extensions, extensions_size, NULL);
1460   gnutls_free (extensions);
1461   if (result != ASN1_SUCCESS)
1462     {
1463       gnutls_assert ();
1464       asn1_delete_structure (&c2);
1465       return _gnutls_asn2err (result);
1466     }
1467
1468   snprintf (name, sizeof (name), "?%u.extnValue", indx + 1);
1469
1470   len = *sizeof_data;
1471   result = asn1_read_value (c2, name, data, &len);
1472   *sizeof_data = len;
1473
1474   asn1_delete_structure (&c2);
1475
1476   if (result == ASN1_ELEMENT_NOT_FOUND)
1477     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1478   else if (result < 0)
1479     {
1480       gnutls_assert ();
1481       return _gnutls_asn2err (result);
1482     }
1483
1484   return 0;
1485 }
1486
1487 /**
1488  * gnutls_x509_crq_get_key_usage:
1489  * @crq: should contain a #gnutls_x509_crq_t structure
1490  * @key_usage: where the key usage bits will be stored
1491  * @critical: will be non zero if the extension is marked as critical
1492  *
1493  * This function will return certificate's key usage, by reading the
1494  * keyUsage X.509 extension (2.5.29.15).  The key usage value will
1495  * ORed values of the: %GNUTLS_KEY_DIGITAL_SIGNATURE,
1496  * %GNUTLS_KEY_NON_REPUDIATION, %GNUTLS_KEY_KEY_ENCIPHERMENT,
1497  * %GNUTLS_KEY_DATA_ENCIPHERMENT, %GNUTLS_KEY_KEY_AGREEMENT,
1498  * %GNUTLS_KEY_KEY_CERT_SIGN, %GNUTLS_KEY_CRL_SIGN,
1499  * %GNUTLS_KEY_ENCIPHER_ONLY, %GNUTLS_KEY_DECIPHER_ONLY.
1500  *
1501  * Returns: the certificate key usage, or a negative value in case of
1502  *   parsing error.  If the certificate does not contain the keyUsage
1503  *   extension %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
1504  *   returned.
1505  *
1506  * Since: 2.8.0
1507  **/
1508 int
1509 gnutls_x509_crq_get_key_usage (gnutls_x509_crq_t crq,
1510                                unsigned int *key_usage,
1511                                unsigned int *critical)
1512 {
1513   int result;
1514   uint16_t _usage;
1515   opaque buf[128];
1516   size_t buf_size = sizeof (buf);
1517
1518   if (crq == NULL)
1519     {
1520       gnutls_assert ();
1521       return GNUTLS_E_INVALID_REQUEST;
1522     }
1523
1524   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.15", 0,
1525                                                  buf, &buf_size, critical);
1526   if (result < 0)
1527     {
1528       gnutls_assert ();
1529       return result;
1530     }
1531
1532   result = _gnutls_x509_ext_extract_keyUsage (&_usage, buf, buf_size);
1533
1534   *key_usage = _usage;
1535
1536   if (result < 0)
1537     {
1538       gnutls_assert ();
1539       return result;
1540     }
1541
1542   return 0;
1543 }
1544
1545 /**
1546  * gnutls_x509_crq_get_basic_constraints:
1547  * @crq: should contain a #gnutls_x509_crq_t structure
1548  * @critical: will be non zero if the extension is marked as critical
1549  * @ca: pointer to output integer indicating CA status, may be NULL,
1550  *   value is 1 if the certificate CA flag is set, 0 otherwise.
1551  * @pathlen: pointer to output integer indicating path length (may be
1552  *   NULL), non-negative values indicate a present pathLenConstraint
1553  *   field and the actual value, -1 indicate that the field is absent.
1554  *
1555  * This function will read the certificate's basic constraints, and
1556  * return the certificates CA status.  It reads the basicConstraints
1557  * X.509 extension (2.5.29.19).
1558  *
1559  * Return value: If the certificate is a CA a positive value will be
1560  *   returned, or zero if the certificate does not have CA flag set.
1561  *   A negative value may be returned in case of errors.  If the
1562  *   certificate does not contain the basicConstraints extension
1563  *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
1564  *
1565  * Since: 2.8.0
1566  **/
1567 int
1568 gnutls_x509_crq_get_basic_constraints (gnutls_x509_crq_t crq,
1569                                        unsigned int *critical,
1570                                        int *ca, int *pathlen)
1571 {
1572   int result;
1573   int tmp_ca;
1574   opaque buf[256];
1575   size_t buf_size = sizeof (buf);
1576
1577   if (crq == NULL)
1578     {
1579       gnutls_assert ();
1580       return GNUTLS_E_INVALID_REQUEST;
1581     }
1582
1583   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.19", 0,
1584                                                  buf, &buf_size, critical);
1585   if (result < 0)
1586     {
1587       gnutls_assert ();
1588       return result;
1589     }
1590
1591   result =
1592     _gnutls_x509_ext_extract_basicConstraints (&tmp_ca,
1593                                                pathlen, buf, buf_size);
1594   if (ca)
1595     *ca = tmp_ca;
1596
1597   if (result < 0)
1598     {
1599       gnutls_assert ();
1600       return result;
1601     }
1602
1603   return tmp_ca;
1604 }
1605
1606 static int
1607 get_subject_alt_name (gnutls_x509_crq_t crq,
1608                       unsigned int seq, void *ret,
1609                       size_t * ret_size, unsigned int *ret_type,
1610                       unsigned int *critical, int othername_oid)
1611 {
1612   int result;
1613   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1614   gnutls_x509_subject_alt_name_t type;
1615   gnutls_datum_t dnsname = { NULL, 0 };
1616   size_t dns_size = 0;
1617
1618   if (crq == NULL)
1619     {
1620       gnutls_assert ();
1621       return GNUTLS_E_INVALID_REQUEST;
1622     }
1623
1624   if (ret)
1625     memset (ret, 0, *ret_size);
1626   else
1627     *ret_size = 0;
1628
1629   /* Extract extension.
1630    */
1631   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.17", 0,
1632                                                  NULL, &dns_size, critical);
1633   if (result < 0)
1634     {
1635       gnutls_assert ();
1636       return result;
1637     }
1638
1639   dnsname.size = dns_size;
1640   dnsname.data = gnutls_malloc (dnsname.size);
1641   if (dnsname.data == NULL)
1642     {
1643       gnutls_assert ();
1644       return GNUTLS_E_MEMORY_ERROR;
1645     }
1646
1647   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.17", 0,
1648                                                  dnsname.data, &dns_size,
1649                                                  critical);
1650   if (result < 0)
1651     {
1652       gnutls_assert ();
1653       gnutls_free (dnsname.data);
1654       return result;
1655     }
1656
1657   result = asn1_create_element
1658     (_gnutls_get_pkix (), "PKIX1.SubjectAltName", &c2);
1659   if (result != ASN1_SUCCESS)
1660     {
1661       gnutls_assert ();
1662       gnutls_free (dnsname.data);
1663       return _gnutls_asn2err (result);
1664     }
1665
1666   result = asn1_der_decoding (&c2, dnsname.data, dnsname.size, NULL);
1667   gnutls_free (dnsname.data);
1668   if (result != ASN1_SUCCESS)
1669     {
1670       gnutls_assert ();
1671       asn1_delete_structure (&c2);
1672       return _gnutls_asn2err (result);
1673     }
1674
1675   result = _gnutls_parse_general_name (c2, "", seq, ret, ret_size,
1676                                        ret_type, othername_oid);
1677   asn1_delete_structure (&c2);
1678   if (result < 0)
1679     {
1680       return result;
1681     }
1682
1683   type = result;
1684
1685   return type;
1686 }
1687
1688 /**
1689  * gnutls_x509_crq_get_subject_alt_name:
1690  * @crq: should contain a #gnutls_x509_crq_t structure
1691  * @seq: specifies the sequence number of the alt name, 0 for the
1692  *   first one, 1 for the second etc.
1693  * @ret: is the place where the alternative name will be copied to
1694  * @ret_size: holds the size of ret.
1695  * @ret_type: holds the #gnutls_x509_subject_alt_name_t name type
1696  * @critical: will be non zero if the extension is marked as critical
1697  *   (may be null)
1698  *
1699  * This function will return the alternative names, contained in the
1700  * given certificate.  It is the same as
1701  * gnutls_x509_crq_get_subject_alt_name() except for the fact that it
1702  * will return the type of the alternative name in @ret_type even if
1703  * the function fails for some reason (i.e.  the buffer provided is
1704  * not enough).
1705  *
1706  * Returns: the alternative subject name type on success, one of the
1707  *   enumerated #gnutls_x509_subject_alt_name_t.  It will return
1708  *   %GNUTLS_E_SHORT_MEMORY_BUFFER if @ret_size is not large enough to
1709  *   hold the value.  In that case @ret_size will be updated with the
1710  *   required size.  If the certificate request does not have an
1711  *   Alternative name with the specified sequence number then
1712  *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
1713  *
1714  * Since: 2.8.0
1715  **/
1716 int
1717 gnutls_x509_crq_get_subject_alt_name (gnutls_x509_crq_t crq,
1718                                       unsigned int seq, void *ret,
1719                                       size_t * ret_size,
1720                                       unsigned int *ret_type,
1721                                       unsigned int *critical)
1722 {
1723   return get_subject_alt_name (crq, seq, ret, ret_size, ret_type, critical,
1724                                0);
1725 }
1726
1727 /**
1728  * gnutls_x509_crq_get_subject_alt_othername_oid:
1729  * @crq: should contain a #gnutls_x509_crq_t structure
1730  * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
1731  * @ret: is the place where the otherName OID will be copied to
1732  * @ret_size: holds the size of ret.
1733  *
1734  * This function will extract the type OID of an otherName Subject
1735  * Alternative Name, contained in the given certificate, and return
1736  * the type as an enumerated element.
1737  *
1738  * This function is only useful if
1739  * gnutls_x509_crq_get_subject_alt_name() returned
1740  * %GNUTLS_SAN_OTHERNAME.
1741  *
1742  * Returns: the alternative subject name type on success, one of the
1743  *   enumerated gnutls_x509_subject_alt_name_t.  For supported OIDs,
1744  *   it will return one of the virtual (GNUTLS_SAN_OTHERNAME_*) types,
1745  *   e.g. %GNUTLS_SAN_OTHERNAME_XMPP, and %GNUTLS_SAN_OTHERNAME for
1746  *   unknown OIDs.  It will return %GNUTLS_E_SHORT_MEMORY_BUFFER if
1747  *   @ret_size is not large enough to hold the value.  In that case
1748  *   @ret_size will be updated with the required size.  If the
1749  *   certificate does not have an Alternative name with the specified
1750  *   sequence number and with the otherName type then
1751  *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
1752  *
1753  * Since: 2.8.0
1754  **/
1755 int
1756 gnutls_x509_crq_get_subject_alt_othername_oid (gnutls_x509_crq_t crq,
1757                                                unsigned int seq,
1758                                                void *ret, size_t * ret_size)
1759 {
1760   return get_subject_alt_name (crq, seq, ret, ret_size, NULL, NULL, 1);
1761 }
1762
1763 /**
1764  * gnutls_x509_crq_get_extension_by_oid:
1765  * @crq: should contain a #gnutls_x509_crq_t structure
1766  * @oid: holds an Object Identified in null terminated string
1767  * @indx: In case multiple same OIDs exist in the extensions, this
1768  *   specifies which to send. Use zero to get the first one.
1769  * @buf: a pointer to a structure to hold the name (may be null)
1770  * @sizeof_buf: initially holds the size of @buf
1771  * @critical: will be non zero if the extension is marked as critical
1772  *
1773  * This function will return the extension specified by the OID in
1774  * the certificate.  The extensions will be returned as binary data
1775  * DER encoded, in the provided buffer.
1776  *
1777  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1778  *   negative value in case of an error.  If the certificate does not
1779  *   contain the specified extension
1780  *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
1781  *
1782  * Since: 2.8.0
1783  **/
1784 int
1785 gnutls_x509_crq_get_extension_by_oid (gnutls_x509_crq_t crq,
1786                                       const char *oid, int indx,
1787                                       void *buf, size_t * sizeof_buf,
1788                                       unsigned int *critical)
1789 {
1790   int result;
1791   unsigned int i;
1792   char _oid[MAX_OID_SIZE];
1793   size_t oid_size;
1794
1795   for (i = 0;; i++)
1796     {
1797       oid_size = sizeof (_oid);
1798       result =
1799         gnutls_x509_crq_get_extension_info (crq, i, _oid, &oid_size,
1800                                             critical);
1801       if (result < 0)
1802         {
1803           gnutls_assert ();
1804           return result;
1805         }
1806
1807       if (strcmp (oid, _oid) == 0)
1808         {                       /* found */
1809           if (indx == 0)
1810             return gnutls_x509_crq_get_extension_data (crq, i, buf,
1811                                                        sizeof_buf);
1812           else
1813             indx--;
1814         }
1815     }
1816
1817
1818   return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1819
1820 }
1821
1822 /**
1823  * gnutls_x509_crq_set_subject_alt_name:
1824  * @crq: a certificate request of type #gnutls_x509_crq_t
1825  * @nt: is one of the #gnutls_x509_subject_alt_name_t enumerations
1826  * @data: The data to be set
1827  * @data_size: The size of data to be set
1828  * @flags: %GNUTLS_FSAN_SET to clear previous data or
1829  *   %GNUTLS_FSAN_APPEND to append.
1830  *
1831  * This function will set the subject alternative name certificate
1832  * extension.  It can set the following types:
1833  *
1834  * &GNUTLS_SAN_DNSNAME: as a text string
1835  *
1836  * &GNUTLS_SAN_RFC822NAME: as a text string
1837  *
1838  * &GNUTLS_SAN_URI: as a text string
1839  *
1840  * &GNUTLS_SAN_IPADDRESS: as a binary IP address (4 or 16 bytes)
1841  *
1842  * Other values can be set as binary values with the proper DER encoding.
1843  *
1844  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1845  *   negative error value.
1846  *
1847  * Since: 2.8.0
1848  **/
1849 int
1850 gnutls_x509_crq_set_subject_alt_name (gnutls_x509_crq_t crq,
1851                                       gnutls_x509_subject_alt_name_t nt,
1852                                       const void *data,
1853                                       unsigned int data_size,
1854                                       unsigned int flags)
1855 {
1856   int result = 0;
1857   gnutls_datum_t der_data = { NULL, 0 };
1858   gnutls_datum_t prev_der_data = { NULL, 0 };
1859   unsigned int critical = 0;
1860   size_t prev_data_size = 0;
1861
1862   if (crq == NULL)
1863     {
1864       gnutls_assert ();
1865       return GNUTLS_E_INVALID_REQUEST;
1866     }
1867
1868   /* Check if the extension already exists.
1869    */
1870   if (flags == GNUTLS_FSAN_APPEND)
1871     {
1872       result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.17", 0,
1873                                                      NULL, &prev_data_size,
1874                                                      &critical);
1875       prev_der_data.size = prev_data_size;
1876
1877       switch (result)
1878         {
1879         case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
1880           /* Replacing non-existing data means the same as set data. */
1881           break;
1882
1883         case GNUTLS_E_SUCCESS:
1884           prev_der_data.data = gnutls_malloc (prev_der_data.size);
1885           if (prev_der_data.data == NULL)
1886             {
1887               gnutls_assert ();
1888               return GNUTLS_E_MEMORY_ERROR;
1889             }
1890
1891           result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.17", 0,
1892                                                          prev_der_data.data,
1893                                                          &prev_data_size,
1894                                                          &critical);
1895           if (result < 0)
1896             {
1897               gnutls_assert ();
1898               gnutls_free (prev_der_data.data);
1899               return result;
1900             }
1901           break;
1902
1903         default:
1904           gnutls_assert ();
1905           return result;
1906         }
1907     }
1908
1909   /* generate the extension.
1910    */
1911   result = _gnutls_x509_ext_gen_subject_alt_name (nt, data, data_size,
1912                                                   &prev_der_data, &der_data);
1913   gnutls_free (prev_der_data.data);
1914   if (result < 0)
1915     {
1916       gnutls_assert ();
1917       goto finish;
1918     }
1919
1920   result = _gnutls_x509_crq_set_extension (crq, "2.5.29.17", &der_data,
1921                                            critical);
1922
1923   _gnutls_free_datum (&der_data);
1924
1925   if (result < 0)
1926     {
1927       gnutls_assert ();
1928       return result;
1929     }
1930
1931   return 0;
1932
1933 finish:
1934   return result;
1935 }
1936
1937 /**
1938  * gnutls_x509_crq_set_basic_constraints:
1939  * @crq: a certificate request of type #gnutls_x509_crq_t
1940  * @ca: true(1) or false(0) depending on the Certificate authority status.
1941  * @pathLenConstraint: non-negative values indicate maximum length of path,
1942  *   and negative values indicate that the pathLenConstraints field should
1943  *   not be present.
1944  *
1945  * This function will set the basicConstraints certificate extension.
1946  *
1947  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1948  *   negative error value.
1949  *
1950  * Since: 2.8.0
1951  **/
1952 int
1953 gnutls_x509_crq_set_basic_constraints (gnutls_x509_crq_t crq,
1954                                        unsigned int ca, int pathLenConstraint)
1955 {
1956   int result;
1957   gnutls_datum_t der_data;
1958
1959   if (crq == NULL)
1960     {
1961       gnutls_assert ();
1962       return GNUTLS_E_INVALID_REQUEST;
1963     }
1964
1965   /* generate the extension.
1966    */
1967   result = _gnutls_x509_ext_gen_basicConstraints (ca, pathLenConstraint,
1968                                                   &der_data);
1969   if (result < 0)
1970     {
1971       gnutls_assert ();
1972       return result;
1973     }
1974
1975   result = _gnutls_x509_crq_set_extension (crq, "2.5.29.19", &der_data, 1);
1976
1977   _gnutls_free_datum (&der_data);
1978
1979   if (result < 0)
1980     {
1981       gnutls_assert ();
1982       return result;
1983     }
1984
1985   return 0;
1986 }
1987
1988 /**
1989  * gnutls_x509_crq_set_key_usage:
1990  * @crq: a certificate request of type #gnutls_x509_crq_t
1991  * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
1992  *
1993  * This function will set the keyUsage certificate extension.
1994  *
1995  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
1996  *   negative error value.
1997  *
1998  * Since: 2.8.0
1999  **/
2000 int
2001 gnutls_x509_crq_set_key_usage (gnutls_x509_crq_t crq, unsigned int usage)
2002 {
2003   int result;
2004   gnutls_datum_t der_data;
2005
2006   if (crq == NULL)
2007     {
2008       gnutls_assert ();
2009       return GNUTLS_E_INVALID_REQUEST;
2010     }
2011
2012   /* generate the extension.
2013    */
2014   result = _gnutls_x509_ext_gen_keyUsage ((uint16_t) usage, &der_data);
2015   if (result < 0)
2016     {
2017       gnutls_assert ();
2018       return result;
2019     }
2020
2021   result = _gnutls_x509_crq_set_extension (crq, "2.5.29.15", &der_data, 1);
2022
2023   _gnutls_free_datum (&der_data);
2024
2025   if (result < 0)
2026     {
2027       gnutls_assert ();
2028       return result;
2029     }
2030
2031   return 0;
2032 }
2033
2034 /**
2035  * gnutls_x509_crq_get_key_purpose_oid:
2036  * @crq: should contain a #gnutls_x509_crq_t structure
2037  * @indx: This specifies which OID to return, use zero to get the first one
2038  * @oid: a pointer to a buffer to hold the OID (may be %NULL)
2039  * @sizeof_oid: initially holds the size of @oid
2040  * @critical: output variable with critical flag, may be %NULL.
2041  *
2042  * This function will extract the key purpose OIDs of the Certificate
2043  * specified by the given index.  These are stored in the Extended Key
2044  * Usage extension (2.5.29.37).  See the GNUTLS_KP_* definitions for
2045  * human readable names.
2046  *
2047  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
2048  *   not long enough, and in that case the *@sizeof_oid will be
2049  *   updated with the required size.  On success 0 is returned.
2050  *
2051  * Since: 2.8.0
2052  **/
2053 int
2054 gnutls_x509_crq_get_key_purpose_oid (gnutls_x509_crq_t crq,
2055                                      int indx, void *oid, size_t * sizeof_oid,
2056                                      unsigned int *critical)
2057 {
2058   char tmpstr[ASN1_MAX_NAME_SIZE];
2059   int result, len;
2060   gnutls_datum_t prev = { NULL, 0 };
2061   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2062   size_t prev_size = 0;
2063
2064   if (oid)
2065     memset (oid, 0, *sizeof_oid);
2066   else
2067     *sizeof_oid = 0;
2068
2069   /* Extract extension.
2070    */
2071   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.37", 0,
2072                                                  NULL, &prev_size, critical);
2073   prev.size = prev_size;
2074
2075   if (result < 0)
2076     {
2077       gnutls_assert ();
2078       return result;
2079     }
2080
2081   prev.data = gnutls_malloc (prev.size);
2082   if (prev.data == NULL)
2083     {
2084       gnutls_assert ();
2085       return GNUTLS_E_MEMORY_ERROR;
2086     }
2087
2088   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.37", 0,
2089                                                  prev.data, &prev_size,
2090                                                  critical);
2091   if (result < 0)
2092     {
2093       gnutls_assert ();
2094       gnutls_free (prev.data);
2095       return result;
2096     }
2097
2098   result = asn1_create_element
2099     (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2);
2100   if (result != ASN1_SUCCESS)
2101     {
2102       gnutls_assert ();
2103       gnutls_free (prev.data);
2104       return _gnutls_asn2err (result);
2105     }
2106
2107   result = asn1_der_decoding (&c2, prev.data, prev.size, NULL);
2108   gnutls_free (prev.data);
2109   if (result != ASN1_SUCCESS)
2110     {
2111       gnutls_assert ();
2112       asn1_delete_structure (&c2);
2113       return _gnutls_asn2err (result);
2114     }
2115
2116   indx++;
2117   /* create a string like "?1"
2118    */
2119   snprintf (tmpstr, sizeof (tmpstr), "?%u", indx);
2120
2121   len = *sizeof_oid;
2122   result = asn1_read_value (c2, tmpstr, oid, &len);
2123
2124   *sizeof_oid = len;
2125   asn1_delete_structure (&c2);
2126
2127   if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND)
2128     {
2129       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2130     }
2131
2132   if (result != ASN1_SUCCESS)
2133     {
2134       if (result != ASN1_MEM_ERROR)
2135         gnutls_assert ();
2136       return _gnutls_asn2err (result);
2137     }
2138
2139   return 0;
2140 }
2141
2142 /**
2143  * gnutls_x509_crq_set_key_purpose_oid:
2144  * @crq: a certificate of type #gnutls_x509_crq_t
2145  * @oid: a pointer to a zero-terminated string that holds the OID
2146  * @critical: Whether this extension will be critical or not
2147  *
2148  * This function will set the key purpose OIDs of the Certificate.
2149  * These are stored in the Extended Key Usage extension (2.5.29.37)
2150  * See the GNUTLS_KP_* definitions for human readable names.
2151  *
2152  * Subsequent calls to this function will append OIDs to the OID list.
2153  *
2154  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
2155  *   negative error value.
2156  *
2157  * Since: 2.8.0
2158  **/
2159 int
2160 gnutls_x509_crq_set_key_purpose_oid (gnutls_x509_crq_t crq,
2161                                      const void *oid, unsigned int critical)
2162 {
2163   int result;
2164   gnutls_datum_t prev = { NULL, 0 }, der_data;
2165   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2166   size_t prev_size = 0;
2167
2168   /* Read existing extension, if there is one.
2169    */
2170   result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.37", 0,
2171                                                  NULL, &prev_size, &critical);
2172   prev.size = prev_size;
2173
2174   switch (result)
2175     {
2176     case GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE:
2177       /* No existing extension, that's fine. */
2178       break;
2179
2180     case GNUTLS_E_SUCCESS:
2181       prev.data = gnutls_malloc (prev.size);
2182       if (prev.data == NULL)
2183         {
2184           gnutls_assert ();
2185           return GNUTLS_E_MEMORY_ERROR;
2186         }
2187
2188       result = gnutls_x509_crq_get_extension_by_oid (crq, "2.5.29.37", 0,
2189                                                      prev.data, &prev_size,
2190                                                      &critical);
2191       if (result < 0)
2192         {
2193           gnutls_assert ();
2194           gnutls_free (prev.data);
2195           return result;
2196         }
2197       break;
2198
2199     default:
2200       gnutls_assert ();
2201       return result;
2202     }
2203
2204   result = asn1_create_element (_gnutls_get_pkix (),
2205                                 "PKIX1.ExtKeyUsageSyntax", &c2);
2206   if (result != ASN1_SUCCESS)
2207     {
2208       gnutls_assert ();
2209       gnutls_free (prev.data);
2210       return _gnutls_asn2err (result);
2211     }
2212
2213   if (prev.data)
2214     {
2215       /* decode it.
2216        */
2217       result = asn1_der_decoding (&c2, prev.data, prev.size, NULL);
2218       gnutls_free (prev.data);
2219       if (result != ASN1_SUCCESS)
2220         {
2221           gnutls_assert ();
2222           asn1_delete_structure (&c2);
2223           return _gnutls_asn2err (result);
2224         }
2225     }
2226
2227   /* generate the extension.
2228    */
2229   /* 1. create a new element.
2230    */
2231   result = asn1_write_value (c2, "", "NEW", 1);
2232   if (result != ASN1_SUCCESS)
2233     {
2234       gnutls_assert ();
2235       asn1_delete_structure (&c2);
2236       return _gnutls_asn2err (result);
2237     }
2238
2239   /* 2. Add the OID.
2240    */
2241   result = asn1_write_value (c2, "?LAST", oid, 1);
2242   if (result != ASN1_SUCCESS)
2243     {
2244       gnutls_assert ();
2245       asn1_delete_structure (&c2);
2246       return _gnutls_asn2err (result);
2247     }
2248
2249   result = _gnutls_x509_der_encode (c2, "", &der_data, 0);
2250   asn1_delete_structure (&c2);
2251
2252   if (result != ASN1_SUCCESS)
2253     {
2254       gnutls_assert ();
2255       return _gnutls_asn2err (result);
2256     }
2257
2258   result = _gnutls_x509_crq_set_extension (crq, "2.5.29.37",
2259                                            &der_data, critical);
2260   _gnutls_free_datum (&der_data);
2261   if (result < 0)
2262     {
2263       gnutls_assert ();
2264       return result;
2265     }
2266
2267   return 0;
2268 }
2269
2270 static int
2271 rsadsa_crq_get_key_id (gnutls_x509_crq_t crq, int pk,
2272                        unsigned char *output_data, size_t * output_data_size)
2273 {
2274   bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
2275   int params_size = MAX_PUBLIC_PARAMS_SIZE;
2276   int i, result = 0;
2277   gnutls_datum_t der = { NULL, 0 };
2278   digest_hd_st hd;
2279
2280   result = _gnutls_x509_crq_get_mpis (crq, params, &params_size);
2281   if (result < 0)
2282     {
2283       gnutls_assert ();
2284       return result;
2285     }
2286
2287   if (pk == GNUTLS_PK_RSA)
2288     {
2289       result = _gnutls_x509_write_rsa_params (params, params_size, &der);
2290       if (result < 0)
2291         {
2292           gnutls_assert ();
2293           goto cleanup;
2294         }
2295     }
2296   else if (pk == GNUTLS_PK_DSA)
2297     {
2298       result = _gnutls_x509_write_dsa_public_key (params, params_size, &der);
2299       if (result < 0)
2300         {
2301           gnutls_assert ();
2302           goto cleanup;
2303         }
2304     }
2305   else
2306     return GNUTLS_E_INTERNAL_ERROR;
2307
2308   result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
2309   if (result < 0)
2310     {
2311       gnutls_assert ();
2312       goto cleanup;
2313     }
2314
2315   _gnutls_hash (&hd, der.data, der.size);
2316
2317   _gnutls_hash_deinit (&hd, output_data);
2318   *output_data_size = 20;
2319
2320   result = 0;
2321
2322 cleanup:
2323
2324   _gnutls_free_datum (&der);
2325
2326   /* release all allocated MPIs
2327    */
2328   for (i = 0; i < params_size; i++)
2329     {
2330       _gnutls_mpi_release (&params[i]);
2331     }
2332   return result;
2333 }
2334
2335 /**
2336  * gnutls_x509_crq_get_key_id:
2337  * @crq: a certificate of type #gnutls_x509_crq_t
2338  * @flags: should be 0 for now
2339  * @output_data: will contain the key ID
2340  * @output_data_size: holds the size of output_data (and will be
2341  *   replaced by the actual size of parameters)
2342  *
2343  * This function will return a unique ID the depends on the public key
2344  * parameters.  This ID can be used in checking whether a certificate
2345  * corresponds to the given private key.
2346  *
2347  * If the buffer provided is not long enough to hold the output, then
2348  * *@output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
2349  * be returned.  The output will normally be a SHA-1 hash output,
2350  * which is 20 bytes.
2351  *
2352  * Return value: In case of failure a negative value will be
2353  *   returned, and 0 on success.
2354  *
2355  * Since: 2.8.0
2356  **/
2357 int
2358 gnutls_x509_crq_get_key_id (gnutls_x509_crq_t crq, unsigned int flags,
2359                             unsigned char *output_data,
2360                             size_t * output_data_size)
2361 {
2362   int pk, result = 0;
2363   gnutls_datum_t pubkey;
2364
2365   if (crq == NULL)
2366     {
2367       gnutls_assert ();
2368       return GNUTLS_E_INVALID_REQUEST;
2369     }
2370
2371   if (*output_data_size < 20)
2372     {
2373       *output_data_size = 20;
2374       return GNUTLS_E_SHORT_MEMORY_BUFFER;
2375     }
2376
2377   pk = gnutls_x509_crq_get_pk_algorithm (crq, NULL);
2378   if (pk < 0)
2379     {
2380       gnutls_assert ();
2381       return pk;
2382     }
2383
2384   if (pk == GNUTLS_PK_RSA || pk == GNUTLS_PK_DSA)
2385     {
2386       /* This is for compatibility with what GnuTLS has printed for
2387          RSA/DSA before the code below was added.  The code below is
2388          applicable to all types, and it would probably be a better
2389          idea to use it for RSA/DSA too, but doing so would break
2390          backwards compatibility.  */
2391       return rsadsa_crq_get_key_id (crq, pk, output_data, output_data_size);
2392     }
2393
2394   pubkey.size = 0;
2395   result =
2396     asn1_der_coding (crq->crq, "certificationRequestInfo.subjectPKInfo", NULL,
2397                      &pubkey.size, NULL);
2398   if (result != ASN1_MEM_ERROR)
2399     {
2400       gnutls_assert ();
2401       return _gnutls_asn2err (result);
2402     }
2403
2404   pubkey.data = gnutls_malloc (pubkey.size);
2405   if (pubkey.data == NULL)
2406     {
2407       gnutls_assert ();
2408       return GNUTLS_E_MEMORY_ERROR;
2409     }
2410
2411   result =
2412     asn1_der_coding (crq->crq, "certificationRequestInfo.subjectPKInfo",
2413                      pubkey.data, &pubkey.size, NULL);
2414   if (result != ASN1_SUCCESS)
2415     {
2416       gnutls_assert ();
2417       gnutls_free (pubkey.data);
2418       return _gnutls_asn2err (result);
2419     }
2420
2421   result = gnutls_fingerprint (GNUTLS_DIG_SHA1, &pubkey,
2422                                output_data, output_data_size);
2423
2424   gnutls_free (pubkey.data);
2425
2426   return result;
2427 }
2428
2429 /**
2430  * gnutls_x509_crq_privkey_sign:
2431  * @crq: should contain a #gnutls_x509_crq_t structure
2432  * @key: holds a private key
2433  * @dig: The message digest to use, i.e., %GNUTLS_DIG_SHA1
2434  * @flags: must be 0
2435  *
2436  * This function will sign the certificate request with a private key.
2437  * This must be the same key as the one used in
2438  * gnutls_x509_crt_set_key() since a certificate request is self
2439  * signed.
2440  *
2441  * This must be the last step in a certificate request generation
2442  * since all the previously set parameters are now signed.
2443  *
2444  * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
2445  *   %GNUTLS_E_ASN1_VALUE_NOT_FOUND is returned if you didn't set all
2446  *   information in the certificate request (e.g., the version using
2447  *   gnutls_x509_crq_set_version()).
2448  *
2449  **/
2450 int
2451 gnutls_x509_crq_privkey_sign (gnutls_x509_crq_t crq, gnutls_privkey_t key,
2452                               gnutls_digest_algorithm_t dig,
2453                               unsigned int flags)
2454 {
2455   int result;
2456   gnutls_datum_t signature;
2457   gnutls_datum_t tbs;
2458
2459   if (crq == NULL)
2460     {
2461       gnutls_assert ();
2462       return GNUTLS_E_INVALID_REQUEST;
2463     }
2464
2465   /* Make sure version field is set. */
2466   if (gnutls_x509_crq_get_version (crq) == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
2467     {
2468       result = gnutls_x509_crq_set_version (crq, 1);
2469       if (result < 0)
2470         {
2471           gnutls_assert ();
2472           return result;
2473         }
2474     }
2475
2476   /* Step 1. Self sign the request.
2477    */
2478   result = _gnutls_x509_get_tbs (crq->crq, "certificationRequestInfo", &tbs);
2479
2480   if (result < 0)
2481     {
2482       gnutls_assert ();
2483       return result;
2484     }
2485
2486   result = gnutls_privkey_sign_data (key, dig, 0, &tbs, &signature);
2487   gnutls_free (tbs.data);
2488
2489   if (result < 0)
2490     {
2491       gnutls_assert ();
2492       return result;
2493     }
2494
2495   /* Step 2. write the signature (bits)
2496    */
2497   result =
2498     asn1_write_value (crq->crq, "signature", signature.data,
2499                       signature.size * 8);
2500
2501   _gnutls_free_datum (&signature);
2502
2503   if (result != ASN1_SUCCESS)
2504     {
2505       gnutls_assert ();
2506       return _gnutls_asn2err (result);
2507     }
2508
2509   /* Step 3. Write the signatureAlgorithm field.
2510    */
2511   result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm",
2512                                           gnutls_privkey_get_pk_algorithm
2513                                           (key, NULL), dig);
2514   if (result < 0)
2515     {
2516       gnutls_assert ();
2517       return result;
2518     }
2519
2520   return 0;
2521 }
2522
2523
2524 /**
2525  * gnutls_x509_crq_verify:
2526  * @crq: is the crq to be verified
2527  * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
2528  *
2529  * This function will verify self signature in the certificate
2530  * request and return its status.
2531  *
2532  * Returns: On success, %GNUTLS_E_SUCCESS is returned, %GNUTLS_E_PK_SIG_VERIFY_FAILED
2533  * if verification failed, otherwise a negative error value.
2534  **/
2535 int
2536 gnutls_x509_crq_verify (gnutls_x509_crq_t crq,
2537                         unsigned int flags)
2538 {
2539 gnutls_datum data = { NULL, 0 };
2540 gnutls_datum signature = { NULL, 0 };
2541 bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
2542 int ret, params_size = 0, i;
2543
2544   ret =
2545     _gnutls_x509_get_signed_data (crq->crq, "certificationRequestInfo", &data);
2546   if (ret < 0)
2547     {
2548       gnutls_assert ();
2549       return ret;
2550     }
2551
2552   ret = _gnutls_x509_get_signature (crq->crq, "signature", &signature);
2553   if (ret < 0)
2554     {
2555       gnutls_assert ();
2556       goto cleanup;
2557     }
2558
2559   params_size = MAX_PUBLIC_PARAMS_SIZE;
2560   ret =
2561     _gnutls_x509_crq_get_mpis(crq, params, &params_size);
2562   if (ret < 0)
2563     {
2564       gnutls_assert ();
2565       goto cleanup;
2566     }
2567
2568   ret = pubkey_verify_sig(&data, NULL, &signature,
2569                           gnutls_x509_crq_get_pk_algorithm (crq, NULL),
2570     params, params_size);
2571   if (ret < 0)
2572     {
2573       gnutls_assert ();
2574       goto cleanup;
2575     }
2576
2577   ret = 0;
2578
2579 cleanup:
2580   _gnutls_free_datum (&data);
2581   _gnutls_free_datum (&signature);
2582
2583   for (i = 0; i < params_size; i++)
2584       {
2585             _gnutls_mpi_release (&params[i]);
2586       }
2587
2588   return ret;
2589 }
2590
2591 #endif /* ENABLE_PKI */
2592