Tizen 2.0 Release
[external/libgnutls26.git] / libextra / openssl_compat.c
1 /*
2  * Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS-EXTRA.
8  *
9  * GnuTLS-extra is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *               
14  * GnuTLS-extra is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *                               
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 /* This file includes all functions that were in the 0.5.x and 0.8.x
24  * gnutls API. They are now implemented over the new certificate parsing
25  * API.
26  */
27
28 #include "gnutls_int.h"
29
30 #include <gnutls_global.h>
31 #include <gnutls_errors.h>
32 #include <string.h>             /* memset */
33 #include <x509/x509_int.h>
34 #include <libtasn1.h>
35 #include <gnutls/x509.h>
36 #include <openssl_compat.h>
37
38 /*-
39  * gnutls_x509_extract_dn:
40  * @idn: should contain a DER encoded RDN sequence
41  * @rdn: a pointer to a structure to hold the name
42  *
43  * This function will return the name of the given RDN sequence.
44  * The name will be returned as a gnutls_x509_dn structure.
45  * Returns a negative error code in case of an error.
46  *
47  -*/
48 int
49 gnutls_x509_extract_dn (const gnutls_datum_t * idn, gnutls_x509_dn * rdn)
50 {
51   ASN1_TYPE dn = ASN1_TYPE_EMPTY;
52   int result;
53   size_t len;
54
55   if ((result =
56        asn1_create_element (_gnutls_get_pkix (),
57                             "PKIX1.Name", &dn)) != ASN1_SUCCESS)
58     {
59       return _gnutls_asn2err (result);
60     }
61
62   result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
63   if (result != ASN1_SUCCESS)
64     {
65       /* couldn't decode DER */
66       asn1_delete_structure (&dn);
67       return _gnutls_asn2err (result);
68     }
69
70   memset (rdn, 0, sizeof (gnutls_x509_dn));
71
72   len = sizeof (rdn->country);
73   _gnutls_x509_parse_dn_oid (dn, "", GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
74                              rdn->country, &len);
75
76   len = sizeof (rdn->organization);
77   _gnutls_x509_parse_dn_oid (dn, "", GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
78                              0, rdn->organization, &len);
79
80   len = sizeof (rdn->organizational_unit_name);
81   _gnutls_x509_parse_dn_oid (dn, "",
82                              GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0,
83                              0, rdn->organizational_unit_name, &len);
84
85   len = sizeof (rdn->common_name);
86   _gnutls_x509_parse_dn_oid (dn, "", GNUTLS_OID_X520_COMMON_NAME, 0, 0,
87                              rdn->common_name, &len);
88
89   len = sizeof (rdn->locality_name);
90   _gnutls_x509_parse_dn_oid (dn, "", GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
91                              rdn->locality_name, &len);
92
93   len = sizeof (rdn->state_or_province_name);
94   _gnutls_x509_parse_dn_oid (dn, "",
95                              GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
96                              rdn->state_or_province_name, &len);
97
98   len = sizeof (rdn->email);
99   _gnutls_x509_parse_dn_oid (dn, "", GNUTLS_OID_PKCS9_EMAIL, 0, 0,
100                              rdn->email, &len);
101
102   asn1_delete_structure (&dn);
103
104   return 0;
105 }
106
107 /*-
108  * gnutls_x509_extract_certificate_dn:
109  * @cert: should contain an X.509 DER encoded certificate
110  * @ret: a pointer to a structure to hold the peer's name
111  *
112  * This function will return the name of the certificate holder. The name is gnutls_x509_dn structure and
113  * is a obtained by the peer's certificate. If the certificate send by the
114  * peer is invalid, or in any other failure this function returns error.
115  * Returns a negative error code in case of an error.
116  -*/
117 int
118 gnutls_x509_extract_certificate_dn (const gnutls_datum_t * cert,
119                                     gnutls_x509_dn * ret)
120 {
121   gnutls_x509_crt_t xcert;
122   int result;
123   size_t len;
124
125   result = gnutls_x509_crt_init (&xcert);
126   if (result < 0)
127     return result;
128
129   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
130   if (result < 0)
131     {
132       gnutls_x509_crt_deinit (xcert);
133       return result;
134     }
135
136   len = sizeof (ret->country);
137   gnutls_x509_crt_get_dn_by_oid (xcert, GNUTLS_OID_X520_COUNTRY_NAME, 0,
138                                  0, ret->country, &len);
139
140   len = sizeof (ret->organization);
141   gnutls_x509_crt_get_dn_by_oid (xcert, GNUTLS_OID_X520_ORGANIZATION_NAME,
142                                  0, 0, ret->organization, &len);
143
144   len = sizeof (ret->organizational_unit_name);
145   gnutls_x509_crt_get_dn_by_oid (xcert,
146                                  GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
147                                  0, 0, ret->organizational_unit_name, &len);
148
149   len = sizeof (ret->common_name);
150   gnutls_x509_crt_get_dn_by_oid (xcert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
151                                  ret->common_name, &len);
152
153   len = sizeof (ret->locality_name);
154   gnutls_x509_crt_get_dn_by_oid (xcert, GNUTLS_OID_X520_LOCALITY_NAME, 0,
155                                  0, ret->locality_name, &len);
156
157   len = sizeof (ret->state_or_province_name);
158   gnutls_x509_crt_get_dn_by_oid (xcert,
159                                  GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME,
160                                  0, 0, ret->state_or_province_name, &len);
161
162   len = sizeof (ret->email);
163   gnutls_x509_crt_get_dn_by_oid (xcert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
164                                  ret->email, &len);
165
166   gnutls_x509_crt_deinit (xcert);
167
168   return 0;
169 }
170
171 /*-
172  * gnutls_x509_extract_certificate_issuer_dn:
173  * @cert: should contain an X.509 DER encoded certificate
174  * @ret: a pointer to a structure to hold the issuer's name
175  *
176  * This function will return the name of the issuer stated in the certificate. The name is a gnutls_x509_dn structure and
177  * is a obtained by the peer's certificate. If the certificate send by the
178  * peer is invalid, or in any other failure this function returns error.
179  * Returns a negative error code in case of an error.
180  -*/
181 int
182 gnutls_x509_extract_certificate_issuer_dn (const gnutls_datum_t * cert,
183                                            gnutls_x509_dn * ret)
184 {
185   gnutls_x509_crt_t xcert;
186   int result;
187   size_t len;
188
189   result = gnutls_x509_crt_init (&xcert);
190   if (result < 0)
191     return result;
192
193   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
194   if (result < 0)
195     {
196       gnutls_x509_crt_deinit (xcert);
197       return result;
198     }
199
200   len = sizeof (ret->country);
201   gnutls_x509_crt_get_issuer_dn_by_oid (xcert,
202                                         GNUTLS_OID_X520_COUNTRY_NAME, 0,
203                                         0, ret->country, &len);
204
205   len = sizeof (ret->organization);
206   gnutls_x509_crt_get_issuer_dn_by_oid (xcert,
207                                         GNUTLS_OID_X520_ORGANIZATION_NAME,
208                                         0, 0, ret->organization, &len);
209
210   len = sizeof (ret->organizational_unit_name);
211   gnutls_x509_crt_get_issuer_dn_by_oid (xcert,
212                                         GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
213                                         0, 0,
214                                         ret->organizational_unit_name, &len);
215
216   len = sizeof (ret->common_name);
217   gnutls_x509_crt_get_issuer_dn_by_oid (xcert,
218                                         GNUTLS_OID_X520_COMMON_NAME, 0, 0,
219                                         ret->common_name, &len);
220
221   len = sizeof (ret->locality_name);
222   gnutls_x509_crt_get_issuer_dn_by_oid (xcert,
223                                         GNUTLS_OID_X520_LOCALITY_NAME, 0,
224                                         0, ret->locality_name, &len);
225
226   len = sizeof (ret->state_or_province_name);
227   gnutls_x509_crt_get_issuer_dn_by_oid (xcert,
228                                         GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME,
229                                         0, 0, ret->state_or_province_name,
230                                         &len);
231
232   len = sizeof (ret->email);
233   gnutls_x509_crt_get_issuer_dn_by_oid (xcert, GNUTLS_OID_PKCS9_EMAIL, 0,
234                                         0, ret->email, &len);
235
236   gnutls_x509_crt_deinit (xcert);
237
238   return 0;
239 }
240
241
242 /*-
243  * gnutls_x509_extract_certificate_subject_alt_name:
244  * @cert: should contain an X.509 DER encoded certificate
245  * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
246  * @ret: is the place where the alternative name will be copied to
247  * @ret_size: holds the size of ret.
248  *
249  * This function will return the alternative names, contained in the
250  * given certificate.
251  *
252  * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the alternative
253  * name, or the type of alternative name if everything was ok. The type is
254  * one of the enumerated GNUTLS_X509_SUBJECT_ALT_NAME.
255  *
256  * If the certificate does not have an Alternative name with the specified
257  * sequence number then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
258  -*/
259 int
260 gnutls_x509_extract_certificate_subject_alt_name (const gnutls_datum_t *
261                                                   cert, int seq,
262                                                   char *ret, int *ret_size)
263 {
264   gnutls_x509_crt_t xcert;
265   int result;
266   size_t size = *ret_size;
267
268   result = gnutls_x509_crt_init (&xcert);
269   if (result < 0)
270     return result;
271
272   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
273   if (result < 0)
274     {
275       gnutls_x509_crt_deinit (xcert);
276       return result;
277     }
278
279   result =
280     gnutls_x509_crt_get_subject_alt_name (xcert, seq, ret, &size, NULL);
281   *ret_size = size;
282
283   gnutls_x509_crt_deinit (xcert);
284
285   return result;
286 }
287
288 /*-
289  * gnutls_x509_extract_certificate_ca_status:
290  * @cert: should contain an X.509 DER encoded certificate
291  *
292  * This function will return certificates CA status, by reading the
293  * basicConstraints X.509 extension. If the certificate is a CA a positive
294  * value will be returned, or zero if the certificate does not have
295  * CA flag set.
296  *
297  * A negative value may be returned in case of parsing error.
298  * If the certificate does not contain the basicConstraints extension
299  * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
300  -*/
301 int
302 gnutls_x509_extract_certificate_ca_status (const gnutls_datum_t * cert)
303 {
304   gnutls_x509_crt_t xcert;
305   int result;
306
307   result = gnutls_x509_crt_init (&xcert);
308   if (result < 0)
309     return result;
310
311   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
312   if (result < 0)
313     {
314       gnutls_x509_crt_deinit (xcert);
315       return result;
316     }
317
318   result = gnutls_x509_crt_get_ca_status (xcert, NULL);
319
320   gnutls_x509_crt_deinit (xcert);
321
322   return result;
323 }
324
325 /*-
326  * gnutls_x509_extract_certificate_activation_time:
327  * @cert: should contain an X.509 DER encoded certificate
328  *
329  * This function will return the certificate's activation time in UNIX time
330  * (ie seconds since 00:00:00 UTC January 1, 1970).
331  * Returns a (time_t) -1 in case of an error.
332  -*/
333 time_t
334 gnutls_x509_extract_certificate_activation_time (const gnutls_datum_t * cert)
335 {
336   gnutls_x509_crt_t xcert;
337   time_t result;
338
339   result = gnutls_x509_crt_init (&xcert);
340   if (result < 0)
341     return result;
342
343   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
344   if (result < 0)
345     {
346       gnutls_x509_crt_deinit (xcert);
347       return result;
348     }
349
350   result = gnutls_x509_crt_get_activation_time (xcert);
351
352   gnutls_x509_crt_deinit (xcert);
353
354   return result;
355 }
356
357 /*-
358  * gnutls_x509_extract_certificate_expiration_time:
359  * @cert: should contain an X.509 DER encoded certificate
360  *
361  * This function will return the certificate's expiration time in UNIX time
362  * (ie seconds since 00:00:00 UTC January 1, 1970).
363  * Returns a (time_t) -1 in case of an error.
364  -*/
365 time_t
366 gnutls_x509_extract_certificate_expiration_time (const gnutls_datum_t * cert)
367 {
368   gnutls_x509_crt_t xcert;
369   time_t result;
370
371   result = gnutls_x509_crt_init (&xcert);
372   if (result < 0)
373     return result;
374
375   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
376   if (result < 0)
377     {
378       gnutls_x509_crt_deinit (xcert);
379       return result;
380     }
381
382   result = gnutls_x509_crt_get_expiration_time (xcert);
383
384   gnutls_x509_crt_deinit (xcert);
385
386   return result;
387 }
388
389 /*-
390  * gnutls_x509_extract_certificate_version:
391  * @cert: is an X.509 DER encoded certificate
392  *
393  * This function will return the X.509 certificate's version (1, 2, 3). This is obtained by the X509 Certificate
394  * Version field. Returns a negative value in case of an error.
395  -*/
396 int
397 gnutls_x509_extract_certificate_version (const gnutls_datum_t * cert)
398 {
399   gnutls_x509_crt_t xcert;
400   int result;
401
402   result = gnutls_x509_crt_init (&xcert);
403   if (result < 0)
404     return result;
405
406   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
407   if (result < 0)
408     {
409       gnutls_x509_crt_deinit (xcert);
410       return result;
411     }
412
413   result = gnutls_x509_crt_get_version (xcert);
414
415   gnutls_x509_crt_deinit (xcert);
416
417   return result;
418
419 }
420
421 /*-
422  * gnutls_x509_extract_certificate_serial:
423  * @cert: is an X.509 DER encoded certificate
424  * @result: The place where the serial number will be copied
425  * @result_size: Holds the size of the result field.
426  *
427  * This function will return the X.509 certificate's serial number.
428  * This is obtained by the X509 Certificate serialNumber
429  * field. Serial is not always a 32 or 64bit number. Some CAs use
430  * large serial numbers, thus it may be wise to handle it as something
431  * opaque.
432  *
433  * Returns a negative value in case of an error.
434  -*/
435 int
436 gnutls_x509_extract_certificate_serial (const gnutls_datum_t * cert,
437                                         char *result, int *result_size)
438 {
439   gnutls_x509_crt_t xcert;
440   size_t size = *result_size;
441   int ret;
442
443   ret = gnutls_x509_crt_init (&xcert);
444   if (ret < 0)
445     return ret;
446
447   ret = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
448   if (ret < 0)
449     {
450       gnutls_x509_crt_deinit (xcert);
451       return ret;
452     }
453
454   ret = gnutls_x509_crt_get_serial (xcert, result, &size);
455   *result_size = size;
456
457   gnutls_x509_crt_deinit (xcert);
458
459   return ret;
460 }
461
462
463 /*-
464  * gnutls_x509_extract_certificate_pk_algorithm:
465  * @cert: is a DER encoded X.509 certificate
466  * @bits: if bits is non null it will hold the size of the parameters' in bits
467  *
468  * This function will return the public key algorithm of an X.509
469  * certificate.
470  *
471  * If bits is non null, it should have enough size to hold the parameters
472  * size in bits. For RSA the bits returned is the modulus.
473  * For DSA the bits returned are of the public
474  * exponent.
475  *
476  * Returns a member of the gnutls_pk_algorithm_t enumeration on success,
477  * or a negative value on error.
478  -*/
479 int
480 gnutls_x509_extract_certificate_pk_algorithm (const gnutls_datum_t *
481                                               cert, int *bits)
482 {
483   gnutls_x509_crt_t xcert;
484   int result;
485
486   result = gnutls_x509_crt_init (&xcert);
487   if (result < 0)
488     return result;
489
490   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
491   if (result < 0)
492     {
493       gnutls_x509_crt_deinit (xcert);
494       return result;
495     }
496
497   result = gnutls_x509_crt_get_pk_algorithm (xcert, bits);
498
499   gnutls_x509_crt_deinit (xcert);
500
501   return result;
502 }
503
504
505 /*-
506  * gnutls_x509_extract_certificate_dn_string:
507  * @cert: should contain an X.509 DER encoded certificate
508  * @buf: a pointer to a structure to hold the peer's name
509  * @sizeof_buf: holds the size of 'buf'
510  * @issuer: if non zero, then extract the name of the issuer, instead of the holder
511  *
512  * This function will copy the name of the certificate holder in the
513  * provided buffer. The name will be in the form
514  * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253.
515  *
516  * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
517  * long enough, and 0 on success.
518  -*/
519 int
520 gnutls_x509_extract_certificate_dn_string (char *buf,
521                                            unsigned int sizeof_buf,
522                                            const gnutls_datum_t * cert,
523                                            int issuer)
524 {
525   gnutls_x509_crt_t xcert;
526   int result;
527   size_t size;
528
529   result = gnutls_x509_crt_init (&xcert);
530   if (result < 0)
531     return result;
532
533   result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
534   if (result < 0)
535     {
536       gnutls_x509_crt_deinit (xcert);
537       return result;
538     }
539
540   size = sizeof_buf;
541   if (!issuer)
542     result = gnutls_x509_crt_get_dn (xcert, buf, &size);
543   else
544     result = gnutls_x509_crt_get_issuer_dn (xcert, buf, &size);
545
546   gnutls_x509_crt_deinit (xcert);
547
548   return result;
549 }
550
551 /*-
552  * gnutls_x509_verify_certificate:
553  * @cert_list: is the certificate list to be verified
554  * @cert_list_length: holds the number of certificate in cert_list
555  * @CA_list: is the CA list which will be used in verification
556  * @CA_list_length: holds the number of CA certificate in CA_list
557  * @CRL_list: not used
558  * @CRL_list_length: not used
559  *
560  * This function will try to verify the given certificate list and
561  * return its status (TRUSTED, EXPIRED etc.).  The return value
562  * (status) should be one or more of the gnutls_certificate_status_t
563  * enumerated elements bitwise or'd. Note that expiration and
564  * activation dates are not checked by this function, you should
565  * check them using the appropriate functions.
566  *
567  * This function understands the basicConstraints (2.5.29.19) PKIX
568  * extension.  This means that only a certificate authority can sign
569  * a certificate.
570  *
571  * However you must also check the peer's name in order to check if
572  * the verified certificate belongs to the actual peer.
573  *
574  * The return value (status) should be one or more of the
575  * gnutls_certificate_status_t enumerated elements bitwise or'd.
576  *
577  * GNUTLS_CERT_INVALID: the peer's certificate is not valid.
578  *
579  * GNUTLS_CERT_REVOKED: the certificate has been revoked.
580  *
581  * A negative error code is returned in case of an error.
582  * GNUTLS_E_NO_CERTIFICATE_FOUND is returned to indicate that
583  * no certificate was sent by the peer.
584  -*/
585 int
586 gnutls_x509_verify_certificate (const gnutls_datum_t * cert_list,
587                                 int cert_list_length,
588                                 const gnutls_datum_t * CA_list,
589                                 int CA_list_length,
590                                 const gnutls_datum_t * CRL_list,
591                                 int CRL_list_length)
592 {
593   unsigned int verify;
594   gnutls_x509_crt_t *peer_certificate_list = NULL;
595   gnutls_x509_crt_t *ca_certificate_list = NULL;
596   gnutls_x509_crl_t *crl_list = NULL;
597   int peer_certificate_list_size = 0, i, x, ret;
598   int ca_certificate_list_size = 0, crl_list_size = 0;
599
600   if (cert_list == NULL || cert_list_length == 0)
601     return GNUTLS_E_NO_CERTIFICATE_FOUND;
602
603   /* generate a list of gnutls_certs based on the auth info
604    * raw certs.
605    */
606   peer_certificate_list_size = cert_list_length;
607   peer_certificate_list =
608     gnutls_calloc (peer_certificate_list_size, sizeof (gnutls_x509_crt_t));
609   if (peer_certificate_list == NULL)
610     {
611       gnutls_assert ();
612       ret = GNUTLS_E_MEMORY_ERROR;
613       goto cleanup;
614     }
615
616   ca_certificate_list_size = CA_list_length;
617   ca_certificate_list =
618     gnutls_calloc (ca_certificate_list_size, sizeof (gnutls_x509_crt_t));
619   if (ca_certificate_list == NULL)
620     {
621       gnutls_assert ();
622       ret = GNUTLS_E_MEMORY_ERROR;
623       goto cleanup;
624     }
625
626   /* allocate memory for CRL
627    */
628   crl_list_size = CRL_list_length;
629   crl_list = gnutls_calloc (crl_list_size, sizeof (gnutls_x509_crl_t));
630   if (crl_list == NULL)
631     {
632       gnutls_assert ();
633       ret = GNUTLS_E_MEMORY_ERROR;
634       goto cleanup;
635     }
636
637   /* convert certA_list to gnutls_cert* list
638    */
639   for (i = 0; i < peer_certificate_list_size; i++)
640     {
641       ret = gnutls_x509_crt_init (&peer_certificate_list[i]);
642       if (ret < 0)
643         {
644           gnutls_assert ();
645           goto cleanup;
646         }
647
648       ret =
649         gnutls_x509_crt_import (peer_certificate_list[i],
650                                 &cert_list[i], GNUTLS_X509_FMT_DER);
651       if (ret < 0)
652         {
653           gnutls_assert ();
654           goto cleanup;
655         }
656     }
657
658   /* convert CA_list to gnutls_x509_cert* list
659    */
660   for (i = 0; i < ca_certificate_list_size; i++)
661     {
662       ret = gnutls_x509_crt_init (&ca_certificate_list[i]);
663       if (ret < 0)
664         {
665           gnutls_assert ();
666           goto cleanup;
667         }
668
669       ret =
670         gnutls_x509_crt_import (ca_certificate_list[i],
671                                 &CA_list[i], GNUTLS_X509_FMT_DER);
672       if (ret < 0)
673         {
674           gnutls_assert ();
675           goto cleanup;
676         }
677     }
678
679 #ifdef ENABLE_PKI
680   /* convert CRL_list to gnutls_x509_crl* list
681    */
682   for (i = 0; i < crl_list_size; i++)
683     {
684       ret = gnutls_x509_crl_init (&crl_list[i]);
685       if (ret < 0)
686         {
687           gnutls_assert ();
688           goto cleanup;
689         }
690
691       ret =
692         gnutls_x509_crl_import (crl_list[i],
693                                 &CRL_list[i], GNUTLS_X509_FMT_DER);
694       if (ret < 0)
695         {
696           gnutls_assert ();
697           goto cleanup;
698         }
699     }
700 #endif
701
702   /* Verify certificate 
703    */
704   ret =
705     gnutls_x509_crt_list_verify (peer_certificate_list,
706                                  peer_certificate_list_size,
707                                  ca_certificate_list,
708                                  ca_certificate_list_size, crl_list,
709                                  crl_list_size, 0, &verify);
710
711   if (ret < 0)
712     {
713       gnutls_assert ();
714       goto cleanup;
715     }
716
717   ret = verify;
718
719 cleanup:
720
721   if (peer_certificate_list != NULL)
722     for (x = 0; x < peer_certificate_list_size; x++)
723       {
724         if (peer_certificate_list[x] != NULL)
725           gnutls_x509_crt_deinit (peer_certificate_list[x]);
726       }
727
728   if (ca_certificate_list != NULL)
729     for (x = 0; x < ca_certificate_list_size; x++)
730       {
731         if (ca_certificate_list[x] != NULL)
732           gnutls_x509_crt_deinit (ca_certificate_list[x]);
733       }
734 #ifdef ENABLE_PKI
735   if (crl_list != NULL)
736     for (x = 0; x < crl_list_size; x++)
737       {
738         if (crl_list[x] != NULL)
739           gnutls_x509_crl_deinit (crl_list[x]);
740       }
741
742   gnutls_free (crl_list);
743 #endif
744
745   gnutls_free (ca_certificate_list);
746   gnutls_free (peer_certificate_list);
747
748   return ret;
749 }
750
751 /*-
752  * gnutls_x509_extract_key_pk_algorithm:
753  * @cert: is a DER encoded private key
754  *
755  * This function will return the public key algorithm of a DER encoded private
756  * key.
757  *
758  * Returns a member of the gnutls_pk_algorithm_t enumeration on success,
759  * or GNUTLS_E_UNKNOWN_PK_ALGORITHM on error.
760  -*/
761 int
762 gnutls_x509_extract_key_pk_algorithm (const gnutls_datum_t * key)
763 {
764   gnutls_x509_privkey_t pkey;
765   int ret, pk;
766
767   ret = gnutls_x509_privkey_init (&pkey);
768   if (ret < 0)
769     {
770       gnutls_assert ();
771       return ret;
772     }
773
774   ret = gnutls_x509_privkey_import (pkey, key, GNUTLS_X509_FMT_DER);
775   if (ret < 0)
776     {
777       gnutls_assert ();
778       return ret;
779     }
780
781   pk = gnutls_x509_privkey_get_pk_algorithm (pkey);
782
783   gnutls_x509_privkey_deinit (pkey);
784   return pk;
785 }
786
787 #ifdef ENABLE_PKI
788
789 /*-
790  * gnutls_x509_pkcs7_extract_certificate:
791  * @pkcs7_struct: should contain a PKCS7 DER formatted structure
792  * @indx: contains the index of the certificate to extract
793  * @certificate: the contents of the certificate will be copied there
794  * @certificate_size: should hold the size of the certificate
795  *
796  * This function will return a certificate of the PKCS7 or RFC2630
797  * certificate set.  Returns 0 on success. If the provided buffer is
798  * not long enough, then GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
799  *
800  * After the last certificate has been read
801  * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
802  -*/
803 int
804 gnutls_x509_pkcs7_extract_certificate (const gnutls_datum_t *
805                                        pkcs7_struct, int indx,
806                                        char *certificate,
807                                        int *certificate_size)
808 {
809   gnutls_pkcs7_t pkcs7;
810   int result;
811   size_t size = *certificate_size;
812
813   result = gnutls_pkcs7_init (&pkcs7);
814   if (result < 0)
815     return result;
816
817   result = gnutls_pkcs7_import (pkcs7, pkcs7_struct, GNUTLS_X509_FMT_DER);
818   if (result < 0)
819     {
820       gnutls_pkcs7_deinit (pkcs7);
821       return result;
822     }
823
824   result = gnutls_pkcs7_get_crt_raw (pkcs7, indx, certificate, &size);
825   *certificate_size = size;
826
827   gnutls_pkcs7_deinit (pkcs7);
828
829   return result;
830 }
831
832 #endif