Tizen 2.0 Release
[external/libgnutls26.git] / lib / auth_cert.c
1 /*
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3  * 2010 Free Software 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 /* The certificate authentication functions which are needed in the handshake,
27  * and are common to RSA and DHE key exchange, are in this file.
28  */
29
30 #include <gnutls_int.h>
31 #include "gnutls_auth.h"
32 #include "gnutls_errors.h"
33 #include <gnutls_cert.h>
34 #include <auth_cert.h>
35 #include "gnutls_dh.h"
36 #include "gnutls_num.h"
37 #include "libtasn1.h"
38 #include "gnutls_datum.h"
39 #include "ext_signature.h"
40 #include <gnutls_pk.h>
41 #include <gnutls_algorithms.h>
42 #include <gnutls_global.h>
43 #include <gnutls_record.h>
44 #include <gnutls_sig.h>
45 #include <gnutls_state.h>
46 #include <gnutls_pk.h>
47 #include <gnutls_x509.h>
48 #include <gnutls/abstract.h>
49 #include "debug.h"
50
51 #ifdef ENABLE_OPENPGP
52 #include "openpgp/gnutls_openpgp.h"
53
54 static gnutls_privkey_t alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t
55                                                 key, int deinit);
56 static gnutls_cert *alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert);
57
58 #endif
59
60 static gnutls_cert *alloc_and_load_x509_certs (gnutls_x509_crt_t * certs,
61                                                unsigned);
62 static gnutls_privkey_t alloc_and_load_x509_key (gnutls_x509_privkey_t key,
63                                                  int deinit);
64
65 #ifdef ENABLE_PKCS11
66 static gnutls_privkey_t alloc_and_load_pkcs11_key (gnutls_pkcs11_privkey_t
67                                                    key, int deinit);
68 #endif
69
70 /* Copies data from a internal certificate struct (gnutls_cert) to 
71  * exported certificate struct (cert_auth_info_t)
72  */
73 static int
74 _gnutls_copy_certificate_auth_info (cert_auth_info_t info,
75                                     gnutls_cert * cert, size_t ncerts)
76 {
77   /* Copy peer's information to auth_info_t
78    */
79   int ret;
80   size_t i, j;
81
82   if (info->raw_certificate_list != NULL)
83     {
84       for (j = 0; j < info->ncerts; j++)
85         _gnutls_free_datum (&info->raw_certificate_list[j]);
86       gnutls_free (info->raw_certificate_list);
87     }
88
89   if (ncerts == 0)
90     {
91       info->raw_certificate_list = NULL;
92       info->ncerts = 0;
93       return 0;
94     }
95
96   info->raw_certificate_list =
97     gnutls_calloc (ncerts, sizeof (gnutls_datum_t));
98   if (info->raw_certificate_list == NULL)
99     {
100       gnutls_assert ();
101       return GNUTLS_E_MEMORY_ERROR;
102     }
103
104   for (i = 0; i < ncerts; i++)
105     {
106       if (cert->raw.size > 0)
107         {
108           ret =
109             _gnutls_set_datum (&info->raw_certificate_list[i],
110                                cert[i].raw.data, cert[i].raw.size);
111           if (ret < 0)
112             {
113               gnutls_assert ();
114               goto clear;
115             }
116         }
117     }
118   info->ncerts = ncerts;
119
120   info->cert_type = cert[0].cert_type;
121
122 #ifdef ENABLE_OPENPGP
123   if (cert[0].cert_type == GNUTLS_CRT_OPENPGP)
124     {
125       info->use_subkey = cert[0].use_subkey;
126       memcpy (info->subkey_id, cert[0].subkey_id, sizeof (info->subkey_id));
127     }
128 #endif
129
130   return 0;
131
132 clear:
133
134   for (j = 0; j < i; j++)
135     _gnutls_free_datum (&info->raw_certificate_list[j]);
136
137   gnutls_free (info->raw_certificate_list);
138   info->raw_certificate_list = NULL;
139
140   return ret;
141 }
142
143
144
145
146 /* returns 0 if the algo_to-check exists in the pk_algos list,
147  * -1 otherwise.
148  */
149 inline static int
150 _gnutls_check_pk_algo_in_list (const gnutls_pk_algorithm_t *
151                                pk_algos, int pk_algos_length,
152                                gnutls_pk_algorithm_t algo_to_check)
153 {
154   int i;
155   for (i = 0; i < pk_algos_length; i++)
156     {
157       if (algo_to_check == pk_algos[i])
158         {
159           return 0;
160         }
161     }
162   return -1;
163 }
164
165
166 /* Returns the issuer's Distinguished name in odn, of the certificate 
167  * specified in cert.
168  */
169 static int
170 _gnutls_cert_get_issuer_dn (gnutls_cert * cert, gnutls_datum_t * odn)
171 {
172   ASN1_TYPE dn;
173   int len, result;
174   int start, end;
175
176   if ((result = asn1_create_element
177        (_gnutls_get_pkix (), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS)
178     {
179       gnutls_assert ();
180       return _gnutls_asn2err (result);
181     }
182
183   result = asn1_der_decoding (&dn, cert->raw.data, cert->raw.size, NULL);
184   if (result != ASN1_SUCCESS)
185     {
186       /* couldn't decode DER */
187       gnutls_assert ();
188       asn1_delete_structure (&dn);
189       return _gnutls_asn2err (result);
190     }
191
192   result = asn1_der_decoding_startEnd (dn, cert->raw.data, cert->raw.size,
193                                        "tbsCertificate.issuer", &start, &end);
194
195   if (result != ASN1_SUCCESS)
196     {
197       /* couldn't decode DER */
198       gnutls_assert ();
199       asn1_delete_structure (&dn);
200       return _gnutls_asn2err (result);
201     }
202   asn1_delete_structure (&dn);
203
204   len = end - start + 1;
205
206   odn->size = len;
207   odn->data = &cert->raw.data[start];
208
209   return 0;
210 }
211
212
213 /* Locates the most appropriate x509 certificate using the
214  * given DN. If indx == -1 then no certificate was found.
215  *
216  * That is to guess which certificate to use, based on the 
217  * CAs and sign algorithms supported by the peer server.
218  */
219 static int
220 _find_x509_cert (const gnutls_certificate_credentials_t cred,
221                  opaque * _data, size_t _data_size,
222                  const gnutls_pk_algorithm_t * pk_algos,
223                  int pk_algos_length, int *indx)
224 {
225   unsigned size;
226   gnutls_datum_t odn = { NULL, 0 };
227   opaque *data = _data;
228   ssize_t data_size = _data_size;
229   unsigned i, j;
230   int result, cert_pk;
231
232   *indx = -1;
233
234   do
235     {
236
237       DECR_LENGTH_RET (data_size, 2, 0);
238       size = _gnutls_read_uint16 (data);
239       DECR_LENGTH_RET (data_size, size, 0);
240       data += 2;
241
242       for (i = 0; i < cred->ncerts; i++)
243         {
244           for (j = 0; j < cred->cert_list_length[i]; j++)
245             {
246               if ((result =
247                    _gnutls_cert_get_issuer_dn (&cred->cert_list[i][j],
248                                                &odn)) < 0)
249                 {
250                   gnutls_assert ();
251                   return result;
252                 }
253
254               if (odn.size != size)
255                 continue;
256
257               /* If the DN matches and
258                * the *_SIGN algorithm matches
259                * the cert is our cert!
260                */
261               cert_pk = cred->cert_list[i][0].subject_pk_algorithm;
262
263               if ((memcmp (odn.data, data, size) == 0) &&
264                   (_gnutls_check_pk_algo_in_list
265                    (pk_algos, pk_algos_length, cert_pk) == 0))
266                 {
267                   *indx = i;
268                   break;
269                 }
270             }
271           if (*indx != -1)
272             break;
273         }
274
275       if (*indx != -1)
276         break;
277
278       /* move to next record */
279       data += size;
280
281     }
282   while (1);
283
284   return 0;
285
286 }
287
288 #ifdef ENABLE_OPENPGP
289 /* Locates the most appropriate openpgp cert
290  */
291 static int
292 _find_openpgp_cert (const gnutls_certificate_credentials_t cred,
293                     gnutls_pk_algorithm_t * pk_algos,
294                     int pk_algos_length, int *indx)
295 {
296   unsigned i, j;
297
298   *indx = -1;
299
300   for (i = 0; i < cred->ncerts; i++)
301     {
302       for (j = 0; j < cred->cert_list_length[i]; j++)
303         {
304
305           /* If the *_SIGN algorithm matches
306            * the cert is our cert!
307            */
308           if ((_gnutls_check_pk_algo_in_list
309                (pk_algos, pk_algos_length,
310                 cred->cert_list[i][0].subject_pk_algorithm) == 0)
311               && (cred->cert_list[i][0].cert_type == GNUTLS_CRT_OPENPGP))
312             {
313               *indx = i;
314               break;
315             }
316         }
317       if (*indx != -1)
318         break;
319     }
320
321   return 0;
322 }
323 #endif
324
325 /* Returns the number of issuers in the server's
326  * certificate request packet.
327  */
328 static int
329 get_issuers_num (gnutls_session_t session, opaque * data, ssize_t data_size)
330 {
331   int issuers_dn_len = 0, result;
332   unsigned size;
333
334   /* Count the number of the given issuers;
335    * This is used to allocate the issuers_dn without
336    * using realloc().
337    */
338
339   if (data_size == 0 || data == NULL)
340     return 0;
341
342   if (data_size > 0)
343     do
344       {
345         /* This works like DECR_LEN() 
346          */
347         result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
348         DECR_LENGTH_COM (data_size, 2, goto error);
349         size = _gnutls_read_uint16 (data);
350
351         result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
352         DECR_LENGTH_COM (data_size, size, goto error);
353
354         data += 2;
355
356         if (size > 0)
357           {
358             issuers_dn_len++;
359             data += size;
360           }
361
362         if (data_size == 0)
363           break;
364
365       }
366     while (1);
367
368   return issuers_dn_len;
369
370 error:
371   return result;
372 }
373
374 /* Returns the issuers in the server's certificate request
375  * packet.
376  */
377 static int
378 get_issuers (gnutls_session_t session,
379              gnutls_datum_t * issuers_dn, int issuers_len,
380              opaque * data, size_t data_size)
381 {
382   int i;
383   unsigned size;
384
385   if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509)
386     return 0;
387
388   /* put the requested DNs to req_dn, only in case
389    * of X509 certificates.
390    */
391   if (issuers_len > 0)
392     {
393
394       for (i = 0; i < issuers_len; i++)
395         {
396           /* The checks here for the buffer boundaries
397            * are not needed since the buffer has been
398            * parsed above.
399            */
400           data_size -= 2;
401
402           size = _gnutls_read_uint16 (data);
403
404           data += 2;
405
406           issuers_dn[i].data = data;
407           issuers_dn[i].size = size;
408
409           data += size;
410         }
411     }
412
413   return 0;
414 }
415
416 static void
417 st_to_st2 (gnutls_retr2_st * st2, gnutls_retr_st * st)
418 {
419   st2->cert_type = st->type;
420   if (st->type == GNUTLS_CRT_OPENPGP)
421     {
422       st2->key_type = GNUTLS_PRIVKEY_OPENPGP;
423     }
424   else
425     {
426       st2->key_type = GNUTLS_PRIVKEY_X509;
427     }
428   st2->ncerts = st->ncerts;
429   st2->deinit_all = st->deinit_all;
430
431   switch (st2->cert_type)
432     {
433     case GNUTLS_CRT_OPENPGP:
434       st2->cert.pgp = st->cert.pgp;
435       st2->key.pgp = st->key.pgp;
436       break;
437     case GNUTLS_CRT_X509:
438       st2->cert.x509 = st->cert.x509;
439       st2->key.x509 = st->key.x509;
440       break;
441     default:
442       return;
443     }
444
445 }
446
447 /* Calls the client get callback.
448  */
449 static int
450 call_get_cert_callback (gnutls_session_t session,
451                         const gnutls_datum_t * issuers_dn,
452                         int issuers_dn_length,
453                         gnutls_pk_algorithm_t * pk_algos, int pk_algos_length)
454 {
455   unsigned i;
456   gnutls_cert *local_certs = NULL;
457   gnutls_privkey_t local_key = NULL;
458   int ret = GNUTLS_E_INTERNAL_ERROR;
459   gnutls_certificate_type_t type = gnutls_certificate_type_get (session);
460   gnutls_certificate_credentials_t cred;
461   gnutls_retr2_st st2;
462
463   cred = (gnutls_certificate_credentials_t)
464     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
465   if (cred == NULL)
466     {
467       gnutls_assert ();
468       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
469     }
470
471   memset (&st2, 0, sizeof (st2));
472
473   if (cred->get_cert_callback)
474     {
475       ret = cred->get_cert_callback (session, issuers_dn, issuers_dn_length,
476                                      pk_algos, pk_algos_length, &st2);
477
478     }
479   else
480     {                           /* compatibility mode */
481       gnutls_retr_st st;
482       memset (&st, 0, sizeof (st));
483       if (session->security_parameters.entity == GNUTLS_SERVER)
484         {
485           if (cred->server_get_cert_callback == NULL)
486             {
487               gnutls_assert ();
488               return GNUTLS_E_INTERNAL_ERROR;
489             }
490           ret = cred->server_get_cert_callback (session, &st);
491           if (ret >= 0)
492             st_to_st2 (&st2, &st);
493         }
494       else
495         {                       /* CLIENT */
496
497           if (cred->client_get_cert_callback == NULL)
498             {
499               gnutls_assert ();
500               return GNUTLS_E_INTERNAL_ERROR;
501             }
502           ret = cred->client_get_cert_callback (session,
503                                                 issuers_dn, issuers_dn_length,
504                                                 pk_algos, pk_algos_length,
505                                                 &st);
506           if (ret >= 0)
507             st_to_st2 (&st2, &st);
508         }
509     }
510
511   if (ret < 0)
512     {
513       gnutls_assert ();
514       return GNUTLS_E_INTERNAL_ERROR;
515     }
516
517   if (st2.ncerts == 0)
518     return 0;                   /* no certificate was selected */
519
520   if (type != st2.cert_type)
521     {
522       gnutls_assert ();
523       ret = GNUTLS_E_INVALID_REQUEST;
524       goto cleanup;
525     }
526
527
528   if (type == GNUTLS_CRT_X509)
529     {
530       local_certs = alloc_and_load_x509_certs (st2.cert.x509, st2.ncerts);
531     }
532   else
533     {                           /* PGP */
534       if (st2.ncerts > 1)
535         {
536           gnutls_assert ();
537           ret = GNUTLS_E_INVALID_REQUEST;
538           goto cleanup;
539         }
540 #ifdef ENABLE_OPENPGP
541       {
542         local_certs = alloc_and_load_pgp_certs (st2.cert.pgp);
543       }
544 #else
545       ret = GNUTLS_E_UNIMPLEMENTED_FEATURE;
546       goto cleanup;
547 #endif
548     }
549
550   if (local_certs == NULL)
551     {
552       gnutls_assert ();
553       ret = GNUTLS_E_MEMORY_ERROR;
554       goto cleanup;
555     }
556
557   switch (st2.key_type)
558     {
559     case GNUTLS_PRIVKEY_OPENPGP:
560 #ifdef ENABLE_OPENPGP
561       if (st2.key.pgp != NULL)
562         {
563           local_key = alloc_and_load_pgp_key (st2.key.pgp, st2.deinit_all);
564           if (local_key == NULL)
565             {
566               gnutls_assert ();
567               ret = GNUTLS_E_INTERNAL_ERROR;
568               goto cleanup;
569             }
570         }
571 #endif
572       break;
573     case GNUTLS_PRIVKEY_PKCS11:
574 #ifdef ENABLE_PKCS11
575       if (st2.key.pkcs11 != NULL)
576         {
577           local_key =
578             alloc_and_load_pkcs11_key (st2.key.pkcs11, st2.deinit_all);
579           if (local_key == NULL)
580             {
581               gnutls_assert ();
582               ret = GNUTLS_E_INTERNAL_ERROR;
583               goto cleanup;
584             }
585         }
586 #endif
587       break;
588     case GNUTLS_PRIVKEY_X509:
589       if (st2.key.x509 != NULL)
590         {
591           local_key = alloc_and_load_x509_key (st2.key.x509, st2.deinit_all);
592           if (local_key == NULL)
593             {
594               gnutls_assert ();
595               ret = GNUTLS_E_INTERNAL_ERROR;
596               goto cleanup;
597             }
598         }
599       break;
600     }
601
602   _gnutls_selected_certs_set (session, local_certs,
603                               (local_certs != NULL) ? st2.ncerts : 0,
604                               local_key, 1);
605
606   ret = 0;
607
608 cleanup:
609
610   if (st2.cert_type == GNUTLS_CRT_X509)
611     {
612       if (st2.deinit_all)
613         {
614           for (i = 0; i < st2.ncerts; i++)
615             {
616               gnutls_x509_crt_deinit (st2.cert.x509[i]);
617             }
618           gnutls_free(st2.cert.x509);
619         }
620     }
621   else
622     {
623 #ifdef ENABLE_OPENPGP
624       if (st2.deinit_all)
625         {
626           gnutls_openpgp_crt_deinit (st2.cert.pgp);
627         }
628 #endif
629     }
630
631   if (ret < 0)
632     {
633       if (local_key != NULL)
634         gnutls_privkey_deinit (local_key);
635     }
636
637   return ret;
638 }
639
640 /* Finds the appropriate certificate depending on the cA Distinguished name
641  * advertized by the server. If none matches then returns 0 and -1 as index.
642  * In case of an error a negative value, is returned.
643  *
644  * 20020128: added ability to select a certificate depending on the SIGN
645  * algorithm (only in automatic mode).
646  */
647 static int
648 _select_client_cert (gnutls_session_t session,
649                      opaque * _data, size_t _data_size,
650                      gnutls_pk_algorithm_t * pk_algos, int pk_algos_length)
651 {
652   int result;
653   int indx = -1;
654   gnutls_certificate_credentials_t cred;
655   opaque *data = _data;
656   ssize_t data_size = _data_size;
657   int issuers_dn_length;
658   gnutls_datum_t *issuers_dn = NULL;
659
660   cred = (gnutls_certificate_credentials_t)
661     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
662   if (cred == NULL)
663     {
664       gnutls_assert ();
665       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
666     }
667
668   if (cred->client_get_cert_callback != NULL
669       || cred->get_cert_callback != NULL)
670     {
671
672       /* use a callback to get certificate 
673        */
674       if (session->security_parameters.cert_type != GNUTLS_CRT_X509)
675         issuers_dn_length = 0;
676       else
677         {
678           issuers_dn_length = get_issuers_num (session, data, data_size);
679           if (issuers_dn_length < 0)
680             {
681               gnutls_assert ();
682               return issuers_dn_length;
683             }
684
685           if (issuers_dn_length > 0)
686             {
687               issuers_dn =
688                 gnutls_malloc (sizeof (gnutls_datum_t) * issuers_dn_length);
689               if (issuers_dn == NULL)
690                 {
691                   gnutls_assert ();
692                   return GNUTLS_E_MEMORY_ERROR;
693                 }
694
695               result =
696                 get_issuers (session, issuers_dn, issuers_dn_length,
697                              data, data_size);
698               if (result < 0)
699                 {
700                   gnutls_assert ();
701                   goto cleanup;
702                 }
703             }
704         }
705
706       result =
707         call_get_cert_callback (session, issuers_dn, issuers_dn_length,
708                                 pk_algos, pk_algos_length);
709       goto cleanup;
710
711     }
712   else
713     {
714       /* If we have no callbacks, try to guess.
715        */
716       result = 0;
717
718       if (session->security_parameters.cert_type == GNUTLS_CRT_X509)
719         result =
720           _find_x509_cert (cred, _data, _data_size,
721                            pk_algos, pk_algos_length, &indx);
722
723 #ifdef ENABLE_OPENPGP
724       if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP)
725         result = _find_openpgp_cert (cred, pk_algos, pk_algos_length, &indx);
726 #endif
727
728       if (result < 0)
729         {
730           gnutls_assert ();
731           return result;
732         }
733
734       if (indx >= 0)
735         {
736           _gnutls_selected_certs_set (session,
737                                       &cred->cert_list[indx][0],
738                                       cred->cert_list_length[indx],
739                                       cred->pkey[indx], 0);
740         }
741       else
742         {
743           _gnutls_selected_certs_set (session, NULL, 0, NULL, 0);
744         }
745
746       result = 0;
747     }
748
749 cleanup:
750   gnutls_free (issuers_dn);
751   return result;
752
753 }
754
755 /* Generate client certificate
756  */
757
758 static int
759 _gnutls_gen_x509_crt (gnutls_session_t session, opaque ** data)
760 {
761   int ret, i;
762   opaque *pdata;
763   gnutls_cert *apr_cert_list;
764   gnutls_privkey_t apr_pkey;
765   int apr_cert_list_length;
766
767   /* find the appropriate certificate 
768    */
769   if ((ret =
770        _gnutls_get_selected_cert (session, &apr_cert_list,
771                                   &apr_cert_list_length, &apr_pkey)) < 0)
772     {
773       gnutls_assert ();
774       return ret;
775     }
776
777   ret = 3;
778   for (i = 0; i < apr_cert_list_length; i++)
779     {
780       ret += apr_cert_list[i].raw.size + 3;
781       /* hold size
782        * for uint24 */
783     }
784
785   /* if no certificates were found then send:
786    * 0B 00 00 03 00 00 00    // Certificate with no certs
787    * instead of:
788    * 0B 00 00 00          // empty certificate handshake
789    *
790    * ( the above is the whole handshake message, not 
791    * the one produced here )
792    */
793
794   (*data) = gnutls_malloc (ret);
795   pdata = (*data);
796
797   if (pdata == NULL)
798     {
799       gnutls_assert ();
800       return GNUTLS_E_MEMORY_ERROR;
801     }
802   _gnutls_write_uint24 (ret - 3, pdata);
803   pdata += 3;
804   for (i = 0; i < apr_cert_list_length; i++)
805     {
806       _gnutls_write_datum24 (pdata, apr_cert_list[i].raw);
807       pdata += (3 + apr_cert_list[i].raw.size);
808     }
809
810   return ret;
811 }
812
813 enum PGPKeyDescriptorType
814 { PGP_KEY_FINGERPRINT, PGP_KEY, PGP_KEY_SUBKEY, PGP_KEY_FINGERPRINT_SUBKEY };
815
816 #ifdef ENABLE_OPENPGP
817 static int
818 _gnutls_gen_openpgp_certificate (gnutls_session_t session, opaque ** data)
819 {
820   int ret;
821   opaque *pdata;
822   gnutls_cert *apr_cert_list;
823   gnutls_privkey_t apr_pkey;
824   int apr_cert_list_length;
825
826   /* find the appropriate certificate */
827   if ((ret =
828        _gnutls_get_selected_cert (session, &apr_cert_list,
829                                   &apr_cert_list_length, &apr_pkey)) < 0)
830     {
831       gnutls_assert ();
832       return ret;
833     }
834
835   ret = 3 + 1 + 3;
836
837
838   if (apr_cert_list_length > 0)
839     {
840       if (apr_cert_list[0].use_subkey != 0)
841         ret += 1 + sizeof (apr_cert_list[0].subkey_id); /* for the keyid */
842
843       ret += apr_cert_list[0].raw.size;
844     }
845
846   (*data) = gnutls_malloc (ret);
847   pdata = (*data);
848
849   if (pdata == NULL)
850     {
851       gnutls_assert ();
852       return GNUTLS_E_MEMORY_ERROR;
853     }
854
855   _gnutls_write_uint24 (ret - 3, pdata);
856   pdata += 3;
857
858
859   if (apr_cert_list_length > 0)
860     {
861       if (apr_cert_list[0].use_subkey != 0)
862         {
863           *pdata = PGP_KEY_SUBKEY;
864           pdata++;
865           *pdata = sizeof (apr_cert_list[0].subkey_id);
866           pdata++;
867           memcpy (pdata, apr_cert_list[0].subkey_id,
868                   sizeof (apr_cert_list[0].subkey_id));
869           pdata += sizeof (apr_cert_list[0].subkey_id);
870         }
871       else
872         {
873           *pdata = PGP_KEY;
874           pdata++;
875         }
876
877       _gnutls_write_datum24 (pdata, apr_cert_list[0].raw);
878       pdata += (3 + apr_cert_list[0].raw.size);
879     }
880   else                          /* empty - no certificate */
881     {
882       *pdata = PGP_KEY;
883       pdata++;
884       _gnutls_write_uint24 (0, pdata);
885     }
886
887   return ret;
888 }
889
890 static int
891 _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session, opaque ** data)
892 {
893   int ret, packet_size;
894   size_t fpr_size;
895   opaque *pdata;
896   gnutls_cert *apr_cert_list;
897   gnutls_privkey_t apr_pkey;
898   int apr_cert_list_length;
899
900   /* find the appropriate certificate */
901   if ((ret =
902        _gnutls_get_selected_cert (session, &apr_cert_list,
903                                   &apr_cert_list_length, &apr_pkey)) < 0)
904     {
905       gnutls_assert ();
906       return ret;
907     }
908
909   packet_size = 3 + 1;
910
911   if (apr_cert_list[0].use_subkey)
912     packet_size += 1 + sizeof (apr_cert_list[0].subkey_id);     /* for the keyid */
913
914   /* Only v4 fingerprints are sent 
915    */
916   if (apr_cert_list_length > 0 && apr_cert_list[0].version == 4)
917     packet_size += 20 + 1;
918   else                          /* empty certificate case */
919     return _gnutls_gen_openpgp_certificate (session, data);
920
921   (*data) = gnutls_malloc (packet_size);
922   pdata = (*data);
923
924   if (pdata == NULL)
925     {
926       gnutls_assert ();
927       return GNUTLS_E_MEMORY_ERROR;
928     }
929
930   _gnutls_write_uint24 (packet_size - 3, pdata);
931   pdata += 3;
932
933   if (apr_cert_list[0].use_subkey)
934     {
935       *pdata = PGP_KEY_FINGERPRINT_SUBKEY;
936       pdata++;
937       *pdata = sizeof (apr_cert_list[0].subkey_id);
938       pdata++;
939       memcpy (pdata, apr_cert_list[0].subkey_id,
940               sizeof (apr_cert_list[0].subkey_id));
941       pdata += sizeof (apr_cert_list[0].subkey_id);
942     }
943   else
944     {
945       *pdata = PGP_KEY_FINGERPRINT;     /* key fingerprint */
946       pdata++;
947     }
948
949   *pdata = 20;
950   pdata++;
951
952   fpr_size = 20;
953
954   if ((ret =
955        _gnutls_openpgp_fingerprint (&apr_cert_list[0].raw, pdata,
956                                     &fpr_size)) < 0)
957     {
958       gnutls_assert ();
959       return ret;
960     }
961
962   return packet_size;
963 }
964 #endif
965
966
967 int
968 _gnutls_gen_cert_client_certificate (gnutls_session_t session, opaque ** data)
969 {
970   switch (session->security_parameters.cert_type)
971     {
972 #ifdef ENABLE_OPENPGP
973     case GNUTLS_CRT_OPENPGP:
974       if (_gnutls_openpgp_send_fingerprint (session) == 0)
975         return _gnutls_gen_openpgp_certificate (session, data);
976       else
977         return _gnutls_gen_openpgp_certificate_fpr (session, data);
978 #endif
979     case GNUTLS_CRT_X509:
980       return _gnutls_gen_x509_crt (session, data);
981
982     default:
983       gnutls_assert ();
984       return GNUTLS_E_INTERNAL_ERROR;
985     }
986 }
987
988 int
989 _gnutls_gen_cert_server_certificate (gnutls_session_t session, opaque ** data)
990 {
991   switch (session->security_parameters.cert_type)
992     {
993 #ifdef ENABLE_OPENPGP
994     case GNUTLS_CRT_OPENPGP:
995       return _gnutls_gen_openpgp_certificate (session, data);
996 #endif
997     case GNUTLS_CRT_X509:
998       return _gnutls_gen_x509_crt (session, data);
999     default:
1000       gnutls_assert ();
1001       return GNUTLS_E_INTERNAL_ERROR;
1002     }
1003 }
1004
1005 /* Process server certificate
1006  */
1007
1008 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_gcert_deinit(&peer_certificate_list[x])
1009 static int
1010 _gnutls_proc_x509_server_certificate (gnutls_session_t session,
1011                                       opaque * data, size_t data_size)
1012 {
1013   int size, len, ret;
1014   opaque *p = data;
1015   cert_auth_info_t info;
1016   gnutls_certificate_credentials_t cred;
1017   ssize_t dsize = data_size;
1018   int i;
1019   gnutls_cert *peer_certificate_list;
1020   size_t peer_certificate_list_size = 0, j, x;
1021   gnutls_datum_t tmp;
1022
1023   cred = (gnutls_certificate_credentials_t)
1024     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
1025   if (cred == NULL)
1026     {
1027       gnutls_assert ();
1028       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1029     }
1030
1031
1032   if ((ret =
1033        _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
1034                               sizeof (cert_auth_info_st), 1)) < 0)
1035     {
1036       gnutls_assert ();
1037       return ret;
1038     }
1039
1040   info = _gnutls_get_auth_info (session);
1041
1042   if (data == NULL || data_size == 0)
1043     {
1044       gnutls_assert ();
1045       /* no certificate was sent */
1046       return GNUTLS_E_NO_CERTIFICATE_FOUND;
1047     }
1048
1049   DECR_LEN (dsize, 3);
1050   size = _gnutls_read_uint24 (p);
1051   p += 3;
1052
1053   /* some implementations send 0B 00 00 06 00 00 03 00 00 00
1054    * instead of just 0B 00 00 03 00 00 00 as an empty certificate message.
1055    */
1056   if (size == 0 || size == 3)
1057     {
1058       gnutls_assert ();
1059       /* no certificate was sent */
1060       return GNUTLS_E_NO_CERTIFICATE_FOUND;
1061     }
1062
1063   i = dsize;
1064   while (i > 0)
1065     {
1066       DECR_LEN (dsize, 3);
1067       len = _gnutls_read_uint24 (p);
1068       p += 3;
1069       DECR_LEN (dsize, len);
1070       peer_certificate_list_size++;
1071       p += len;
1072       i -= len + 3;
1073     }
1074
1075   if (peer_certificate_list_size == 0)
1076     {
1077       gnutls_assert ();
1078       return GNUTLS_E_NO_CERTIFICATE_FOUND;
1079     }
1080
1081   /* Ok we now allocate the memory to hold the
1082    * certificate list 
1083    */
1084
1085   peer_certificate_list =
1086     gnutls_malloc (sizeof (gnutls_cert) * (peer_certificate_list_size));
1087
1088   if (peer_certificate_list == NULL)
1089     {
1090       gnutls_assert ();
1091       return GNUTLS_E_MEMORY_ERROR;
1092     }
1093   memset (peer_certificate_list, 0, sizeof (gnutls_cert) *
1094           peer_certificate_list_size);
1095
1096   p = data + 3;
1097
1098   /* Now we start parsing the list (again).
1099    * We don't use DECR_LEN since the list has
1100    * been parsed before.
1101    */
1102
1103   for (j = 0; j < peer_certificate_list_size; j++)
1104     {
1105       len = _gnutls_read_uint24 (p);
1106       p += 3;
1107
1108       tmp.size = len;
1109       tmp.data = p;
1110
1111       if ((ret =
1112            _gnutls_x509_raw_cert_to_gcert (&peer_certificate_list
1113                                            [j], &tmp,
1114                                            CERT_ONLY_EXTENSIONS)) < 0)
1115         {
1116           gnutls_assert ();
1117           goto cleanup;
1118         }
1119
1120       /* check if signature algorithm is supported */
1121       ret =
1122         _gnutls_session_sign_algo_enabled (session,
1123                                            peer_certificate_list
1124                                            [j].sign_algo);
1125       if (ret < 0)
1126         {
1127           gnutls_assert ();
1128           goto cleanup;
1129         }
1130
1131       p += len;
1132     }
1133
1134
1135   if ((ret =
1136        _gnutls_copy_certificate_auth_info (info,
1137                                            peer_certificate_list,
1138                                            peer_certificate_list_size)) < 0)
1139     {
1140       gnutls_assert ();
1141       goto cleanup;
1142     }
1143
1144   if ((ret =
1145        _gnutls_check_key_usage (&peer_certificate_list[0],
1146                                 gnutls_kx_get (session))) < 0)
1147     {
1148       gnutls_assert ();
1149       goto cleanup;
1150     }
1151
1152   ret = 0;
1153
1154 cleanup:
1155   CLEAR_CERTS;
1156   gnutls_free (peer_certificate_list);
1157   return ret;
1158
1159 }
1160
1161 #define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) _gnutls_gcert_deinit(&peer_certificate_list[x])
1162 #ifdef ENABLE_OPENPGP
1163 static int
1164 _gnutls_proc_openpgp_server_certificate (gnutls_session_t session,
1165                                          opaque * data, size_t data_size)
1166 {
1167   int size, ret, len;
1168   opaque *p = data;
1169   cert_auth_info_t info;
1170   gnutls_certificate_credentials_t cred;
1171   ssize_t dsize = data_size;
1172   int x, key_type;
1173   gnutls_cert *peer_certificate_list = NULL;
1174   int peer_certificate_list_size = 0;
1175   gnutls_datum_t tmp, akey = { NULL, 0 };
1176   uint8_t subkey_id[GNUTLS_OPENPGP_KEYID_SIZE];
1177   unsigned int subkey_id_set = 0;
1178
1179   cred = (gnutls_certificate_credentials_t)
1180     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
1181   if (cred == NULL)
1182     {
1183       gnutls_assert ();
1184       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1185     }
1186
1187   if ((ret =
1188        _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
1189                               sizeof (cert_auth_info_st), 1)) < 0)
1190     {
1191       gnutls_assert ();
1192       return ret;
1193     }
1194
1195   info = _gnutls_get_auth_info (session);
1196
1197   if (data == NULL || data_size == 0)
1198     {
1199       gnutls_assert ();
1200       return GNUTLS_E_NO_CERTIFICATE_FOUND;
1201     }
1202
1203   DECR_LEN (dsize, 3);
1204   size = _gnutls_read_uint24 (p);
1205   p += 3;
1206
1207   if (size == 0)
1208     {
1209       gnutls_assert ();
1210       /* no certificate was sent */
1211       return GNUTLS_E_NO_CERTIFICATE_FOUND;
1212     }
1213
1214   /* Read PGPKeyDescriptor */
1215   DECR_LEN (dsize, 1);
1216   key_type = *p;
1217   p++;
1218
1219   /* Try to read the keyid if present */
1220   if (key_type == PGP_KEY_FINGERPRINT_SUBKEY || key_type == PGP_KEY_SUBKEY)
1221     {
1222       /* check size */
1223       if (*p != sizeof (subkey_id))
1224         {
1225           gnutls_assert ();
1226           return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
1227         }
1228
1229       DECR_LEN (dsize, 1);
1230       p++;
1231
1232       DECR_LEN (dsize, sizeof (subkey_id));
1233       memcpy (subkey_id, p, sizeof (subkey_id));
1234       p += sizeof (subkey_id);
1235
1236       subkey_id_set = 1;
1237
1238     }
1239
1240   /* read the actual key or fingerprint */
1241   if (key_type == PGP_KEY_FINGERPRINT
1242       || key_type == PGP_KEY_FINGERPRINT_SUBKEY)
1243     {                           /* the fingerprint */
1244
1245       DECR_LEN (dsize, 1);
1246       len = (uint8_t) * p;
1247       p++;
1248
1249       if (len != 20)
1250         {
1251           gnutls_assert ();
1252           return GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED;
1253         }
1254
1255       DECR_LEN (dsize, 20);
1256
1257       /* request the actual key from our database, or
1258        * a key server or anything.
1259        */
1260       if ((ret =
1261            _gnutls_openpgp_request_key (session, &akey, cred, p, 20)) < 0)
1262         {
1263           gnutls_assert ();
1264           return ret;
1265         }
1266       tmp = akey;
1267       peer_certificate_list_size++;
1268
1269     }
1270   else if (key_type == PGP_KEY || key_type == PGP_KEY_SUBKEY)
1271     {                           /* the whole key */
1272
1273       /* Read the actual certificate */
1274       DECR_LEN (dsize, 3);
1275       len = _gnutls_read_uint24 (p);
1276       p += 3;
1277
1278       if (len == 0)
1279         {
1280           gnutls_assert ();
1281           /* no certificate was sent */
1282           return GNUTLS_E_NO_CERTIFICATE_FOUND;
1283         }
1284
1285       DECR_LEN (dsize, len);
1286       peer_certificate_list_size++;
1287
1288       tmp.size = len;
1289       tmp.data = p;
1290
1291     }
1292   else
1293     {
1294       gnutls_assert ();
1295       return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
1296     }
1297
1298   /* ok we now have the peer's key in tmp datum
1299    */
1300
1301   if (peer_certificate_list_size == 0)
1302     {
1303       gnutls_assert ();
1304       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
1305     }
1306
1307   peer_certificate_list =
1308     gnutls_malloc (sizeof (gnutls_cert) * (peer_certificate_list_size));
1309   if (peer_certificate_list == NULL)
1310     {
1311       gnutls_assert ();
1312       ret = GNUTLS_E_MEMORY_ERROR;
1313       goto cleanup;
1314     }
1315   memset (peer_certificate_list, 0, sizeof (gnutls_cert) *
1316           peer_certificate_list_size);
1317
1318   if ((ret =
1319        _gnutls_openpgp_raw_crt_to_gcert (&peer_certificate_list[0],
1320                                          &tmp,
1321                                          subkey_id_set ? subkey_id : NULL)) <
1322       0)
1323     {
1324       gnutls_assert ();
1325       goto cleanup;
1326     }
1327
1328   if ((ret =
1329        _gnutls_copy_certificate_auth_info (info,
1330                                            peer_certificate_list,
1331                                            peer_certificate_list_size)) < 0)
1332     {
1333       gnutls_assert ();
1334       goto cleanup;
1335     }
1336
1337   if ((ret =
1338        _gnutls_check_key_usage (&peer_certificate_list[0],
1339                                 gnutls_kx_get (session))) < 0)
1340     {
1341       gnutls_assert ();
1342       goto cleanup;
1343     }
1344
1345   ret = 0;
1346
1347 cleanup:
1348
1349   _gnutls_free_datum (&akey);
1350   CLEAR_CERTS;
1351   gnutls_free (peer_certificate_list);
1352   return ret;
1353
1354 }
1355 #endif
1356
1357 int
1358 _gnutls_proc_cert_server_certificate (gnutls_session_t session,
1359                                       opaque * data, size_t data_size)
1360 {
1361   int ret;
1362   gnutls_certificate_credentials_t cred;
1363
1364   cred =
1365     (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key,
1366                                                          GNUTLS_CRD_CERTIFICATE,
1367                                                          NULL);
1368   if (cred == NULL)
1369     {
1370       gnutls_assert ();
1371       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1372     }
1373
1374   switch (session->security_parameters.cert_type)
1375     {
1376 #ifdef ENABLE_OPENPGP
1377     case GNUTLS_CRT_OPENPGP:
1378       ret = _gnutls_proc_openpgp_server_certificate (session,
1379                                                      data, data_size);
1380       break;
1381 #endif
1382     case GNUTLS_CRT_X509:
1383       ret = _gnutls_proc_x509_server_certificate (session, data, data_size);
1384       break;
1385     default:
1386       gnutls_assert ();
1387       return GNUTLS_E_INTERNAL_ERROR;
1388     }
1389
1390   if (ret == 0 && cred->verify_callback != NULL)
1391     {
1392       ret = cred->verify_callback (session);
1393       if (ret != 0)
1394         ret = GNUTLS_E_CERTIFICATE_ERROR;
1395     }
1396
1397   return ret;
1398 }
1399
1400 #define MAX_SIGN_ALGOS 2
1401 typedef enum CertificateSigType
1402 { RSA_SIGN = 1, DSA_SIGN
1403 } CertificateSigType;
1404
1405 /* Checks if we support the given signature algorithm 
1406  * (RSA or DSA). Returns the corresponding gnutls_pk_algorithm_t
1407  * if true;
1408  */
1409 inline static int
1410 _gnutls_check_supported_sign_algo (CertificateSigType algo)
1411 {
1412   switch (algo)
1413     {
1414     case RSA_SIGN:
1415       return GNUTLS_PK_RSA;
1416     case DSA_SIGN:
1417       return GNUTLS_PK_DSA;
1418     }
1419
1420   return -1;
1421 }
1422
1423 int
1424 _gnutls_proc_cert_cert_req (gnutls_session_t session, opaque * data,
1425                             size_t data_size)
1426 {
1427   int size, ret;
1428   opaque *p;
1429   gnutls_certificate_credentials_t cred;
1430   ssize_t dsize;
1431   int i, j;
1432   gnutls_pk_algorithm_t pk_algos[MAX_SIGN_ALGOS];
1433   int pk_algos_length;
1434   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
1435
1436   cred = (gnutls_certificate_credentials_t)
1437     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
1438   if (cred == NULL)
1439     {
1440       gnutls_assert ();
1441       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1442     }
1443
1444   if ((ret =
1445        _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
1446                               sizeof (cert_auth_info_st), 0)) < 0)
1447     {
1448       gnutls_assert ();
1449       return ret;
1450     }
1451
1452   p = data;
1453   dsize = data_size;
1454
1455   DECR_LEN (dsize, 1);
1456   size = p[0];
1457   p++;
1458   /* check if the sign algorithm is supported.
1459    */
1460   pk_algos_length = j = 0;
1461   for (i = 0; i < size; i++, p++)
1462     {
1463       DECR_LEN (dsize, 1);
1464       if ((ret = _gnutls_check_supported_sign_algo (*p)) > 0)
1465         {
1466           if (j < MAX_SIGN_ALGOS)
1467             {
1468               pk_algos[j++] = ret;
1469               pk_algos_length++;
1470             }
1471         }
1472     }
1473
1474   if (pk_algos_length == 0)
1475     {
1476       gnutls_assert ();
1477       return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
1478     }
1479
1480   if (_gnutls_version_has_selectable_sighash (ver))
1481     {
1482       /* read supported hashes */
1483       int hash_num;
1484       DECR_LEN (dsize, 2);
1485       hash_num = _gnutls_read_uint16 (p);
1486       p += 2;
1487       DECR_LEN (dsize, hash_num);
1488
1489       ret = _gnutls_sign_algorithm_parse_data (session, p, hash_num);
1490       if (ret < 0)
1491         {
1492           gnutls_assert ();
1493           return ret;
1494         }
1495
1496       p += hash_num;
1497     }
1498
1499   /* read the certificate authorities */
1500   DECR_LEN (dsize, 2);
1501   size = _gnutls_read_uint16 (p);
1502   p += 2;
1503
1504   if (session->security_parameters.cert_type == GNUTLS_CRT_OPENPGP
1505       && size != 0)
1506     {
1507       gnutls_assert ();
1508       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
1509     }
1510
1511   DECR_LEN (dsize, size);
1512
1513   /* now we ask the user to tell which one
1514    * he wants to use.
1515    */
1516   if ((ret =
1517        _select_client_cert (session, p, size, pk_algos, pk_algos_length)) < 0)
1518     {
1519       gnutls_assert ();
1520       return ret;
1521     }
1522
1523   /* We should reply with a certificate message, 
1524    * even if we have no certificate to send.
1525    */
1526   session->key->certificate_requested = 1;
1527
1528   return 0;
1529 }
1530
1531 int
1532 _gnutls_gen_cert_client_cert_vrfy (gnutls_session_t session, opaque ** data)
1533 {
1534   int ret;
1535   gnutls_cert *apr_cert_list;
1536   gnutls_privkey_t apr_pkey;
1537   int apr_cert_list_length, size;
1538   gnutls_datum_t signature = { NULL, 0 };
1539   int total_data;
1540   opaque *p;
1541   gnutls_sign_algorithm_t sign_algo;
1542   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
1543
1544   *data = NULL;
1545
1546   /* find the appropriate certificate */
1547   if ((ret =
1548        _gnutls_get_selected_cert (session, &apr_cert_list,
1549                                   &apr_cert_list_length, &apr_pkey)) < 0)
1550     {
1551       gnutls_assert ();
1552       return ret;
1553     }
1554
1555   if (apr_cert_list_length > 0)
1556     {
1557       if ((ret =
1558            _gnutls_handshake_sign_cert_vrfy (session,
1559                                              &apr_cert_list[0],
1560                                              apr_pkey, &signature)) < 0)
1561         {
1562           gnutls_assert ();
1563           return ret;
1564         }
1565       sign_algo = ret;
1566     }
1567   else
1568     {
1569       return 0;
1570     }
1571
1572   total_data = signature.size + 2;
1573
1574   /* add hash and signature algorithms */
1575   if (_gnutls_version_has_selectable_sighash (ver))
1576     {
1577       total_data += 2;
1578     }
1579
1580   *data = gnutls_malloc (total_data);
1581   if (*data == NULL)
1582     {
1583       _gnutls_free_datum (&signature);
1584       return GNUTLS_E_MEMORY_ERROR;
1585     }
1586
1587   p = *data;
1588   if (_gnutls_version_has_selectable_sighash (ver))
1589     {
1590       const sign_algorithm_st *aid;
1591       /* error checking is not needed here since we have used those algorithms */
1592       aid = _gnutls_sign_to_tls_aid (sign_algo);
1593       if (aid == NULL)
1594         {
1595           ret = GNUTLS_E_UNKNOWN_ALGORITHM;
1596           goto cleanup;
1597         }
1598
1599       p[0] = aid->hash_algorithm;
1600       p[1] = aid->sign_algorithm;
1601       p += 2;
1602     }
1603
1604   size = signature.size;
1605   _gnutls_write_uint16 (size, p);
1606
1607   p += 2;
1608   memcpy (p, signature.data, size);
1609
1610   _gnutls_free_datum (&signature);
1611
1612   return total_data;
1613
1614 cleanup:
1615   _gnutls_free_datum (&signature);
1616   gnutls_free(*data);
1617   return ret;
1618 }
1619
1620 int
1621 _gnutls_proc_cert_client_cert_vrfy (gnutls_session_t session,
1622                                     opaque * data, size_t data_size)
1623 {
1624   int size, ret;
1625   ssize_t dsize = data_size;
1626   opaque *pdata = data;
1627   gnutls_datum_t sig;
1628   cert_auth_info_t info = _gnutls_get_auth_info (session);
1629   gnutls_cert peer_cert;
1630   gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
1631   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
1632
1633   if (info == NULL || info->ncerts == 0)
1634     {
1635       gnutls_assert ();
1636       /* we need this in order to get peer's certificate */
1637       return GNUTLS_E_INTERNAL_ERROR;
1638     }
1639
1640   if (_gnutls_version_has_selectable_sighash (ver))
1641     {
1642       sign_algorithm_st aid;
1643
1644       DECR_LEN (dsize, 2);
1645       aid.hash_algorithm = pdata[0];
1646       aid.sign_algorithm = pdata[1];
1647
1648       sign_algo = _gnutls_tls_aid_to_sign (&aid);
1649       if (sign_algo == GNUTLS_SIGN_UNKNOWN)
1650         {
1651           gnutls_assert ();
1652           return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
1653         }
1654       pdata += 2;
1655     }
1656
1657   ret = _gnutls_session_sign_algo_enabled (session, sign_algo);
1658   if (ret < 0)
1659     {
1660       gnutls_assert ();
1661       return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
1662     }
1663
1664   DECR_LEN (dsize, 2);
1665   size = _gnutls_read_uint16 (pdata);
1666   pdata += 2;
1667
1668   DECR_LEN (dsize, size);
1669
1670   sig.data = pdata;
1671   sig.size = size;
1672
1673   ret = _gnutls_get_auth_info_gcert (&peer_cert,
1674                                      session->security_parameters.cert_type,
1675                                      info, CERT_NO_COPY);
1676
1677   if (ret < 0)
1678     {
1679       gnutls_assert ();
1680       return ret;
1681     }
1682
1683   if ((ret =
1684        _gnutls_handshake_verify_cert_vrfy (session, &peer_cert, &sig,
1685                                            sign_algo)) < 0)
1686     {
1687       gnutls_assert ();
1688       _gnutls_gcert_deinit (&peer_cert);
1689       return ret;
1690     }
1691   _gnutls_gcert_deinit (&peer_cert);
1692
1693   return 0;
1694 }
1695
1696
1697 #define CERTTYPE_SIZE 3
1698 int
1699 _gnutls_gen_cert_server_cert_req (gnutls_session_t session, opaque ** data)
1700 {
1701   gnutls_certificate_credentials_t cred;
1702   int size, ret;
1703   opaque *pdata;
1704   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
1705   const int signalgosize = 2 + MAX_SIGNATURE_ALGORITHMS * 2;
1706
1707   /* Now we need to generate the RDN sequence. This is
1708    * already in the CERTIFICATE_CRED structure, to improve
1709    * performance.
1710    */
1711
1712   cred = (gnutls_certificate_credentials_t)
1713     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
1714   if (cred == NULL)
1715     {
1716       gnutls_assert ();
1717       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1718     }
1719
1720   size = CERTTYPE_SIZE + 2;     /* 2 for gnutls_certificate_type_t + 2 for size of rdn_seq 
1721                                  */
1722
1723   if (session->security_parameters.cert_type == GNUTLS_CRT_X509 &&
1724       session->internals.ignore_rdn_sequence == 0)
1725     size += cred->x509_rdn_sequence.size;
1726
1727   if (_gnutls_version_has_selectable_sighash (ver))
1728     /* Need two bytes to announce the number of supported hash
1729        functions (see below).  */
1730     size += signalgosize;
1731
1732   (*data) = gnutls_malloc (size);
1733   pdata = (*data);
1734
1735   if (pdata == NULL)
1736     {
1737       gnutls_assert ();
1738       return GNUTLS_E_MEMORY_ERROR;
1739     }
1740
1741   pdata[0] = CERTTYPE_SIZE - 1;
1742
1743   pdata[1] = RSA_SIGN;
1744   pdata[2] = DSA_SIGN;          /* only these for now */
1745   pdata += CERTTYPE_SIZE;
1746
1747   if (_gnutls_version_has_selectable_sighash (ver))
1748     {
1749       ret =
1750         _gnutls_sign_algorithm_write_params (session, pdata, signalgosize);
1751       if (ret < 0)
1752         {
1753           gnutls_assert ();
1754           return ret;
1755         }
1756
1757       /* recalculate size */
1758       size = size - signalgosize + ret;
1759       pdata += ret;
1760     }
1761
1762   if (session->security_parameters.cert_type == GNUTLS_CRT_X509 &&
1763       session->internals.ignore_rdn_sequence == 0)
1764     {
1765       _gnutls_write_datum16 (pdata, cred->x509_rdn_sequence);
1766       /* pdata += cred->x509_rdn_sequence.size + 2; */
1767     }
1768   else
1769     {
1770       _gnutls_write_uint16 (0, pdata);
1771       /* pdata+=2; */
1772     }
1773
1774   return size;
1775 }
1776
1777
1778 /* This function will return the appropriate certificate to use. 
1779  * Fills in the apr_cert_list, apr_cert_list_length and apr_pkey.
1780  * The return value is a negative value on error.
1781  *
1782  * It is normal to return 0 with no certificates in client side.
1783  *
1784  */
1785 int
1786 _gnutls_get_selected_cert (gnutls_session_t session,
1787                            gnutls_cert ** apr_cert_list,
1788                            int *apr_cert_list_length,
1789                            gnutls_privkey_t * apr_pkey)
1790 {
1791   if (session->security_parameters.entity == GNUTLS_SERVER)
1792     {
1793
1794       /* select_client_cert() has been called before.
1795        */
1796
1797       *apr_cert_list = session->internals.selected_cert_list;
1798       *apr_pkey = session->internals.selected_key;
1799       *apr_cert_list_length = session->internals.selected_cert_list_length;
1800
1801       if (*apr_cert_list_length == 0 || *apr_cert_list == NULL)
1802         {
1803           gnutls_assert ();
1804           return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
1805         }
1806
1807     }
1808   else
1809     {                           /* CLIENT SIDE 
1810                                  */
1811
1812       /* we have already decided which certificate
1813        * to send.
1814        */
1815       *apr_cert_list = session->internals.selected_cert_list;
1816       *apr_cert_list_length = session->internals.selected_cert_list_length;
1817       *apr_pkey = session->internals.selected_key;
1818
1819     }
1820
1821   return 0;
1822 }
1823
1824 /* converts the given x509 certificate to gnutls_cert* and allocates
1825  * space for them.
1826  */
1827 static gnutls_cert *
1828 alloc_and_load_x509_certs (gnutls_x509_crt_t * certs, unsigned ncerts)
1829 {
1830   gnutls_cert *local_certs;
1831   int ret = 0;
1832   unsigned i, j;
1833
1834   if (certs == NULL)
1835     return NULL;
1836
1837   local_certs = gnutls_malloc (sizeof (gnutls_cert) * ncerts);
1838   if (local_certs == NULL)
1839     {
1840       gnutls_assert ();
1841       return NULL;
1842     }
1843
1844   for (i = 0; i < ncerts; i++)
1845     {
1846       ret = _gnutls_x509_crt_to_gcert (&local_certs[i], certs[i], 0);
1847       if (ret < 0)
1848         break;
1849     }
1850
1851   if (ret < 0)
1852     {
1853       gnutls_assert ();
1854       for (j = 0; j < i; j++)
1855         {
1856           _gnutls_gcert_deinit (&local_certs[j]);
1857         }
1858       gnutls_free (local_certs);
1859       return NULL;
1860     }
1861
1862   return local_certs;
1863 }
1864
1865 /* converts the given x509 key to gnutls_privkey* and allocates
1866  * space for it.
1867  */
1868 static gnutls_privkey_t
1869 alloc_and_load_x509_key (gnutls_x509_privkey_t key, int deinit)
1870 {
1871   gnutls_privkey_t local_key;
1872   int ret = 0;
1873
1874   if (key == NULL)
1875     return NULL;
1876
1877   ret = gnutls_privkey_init (&local_key);
1878   if (ret < 0)
1879     {
1880       gnutls_assert ();
1881       return NULL;
1882     }
1883
1884   ret =
1885     gnutls_privkey_import_x509 (local_key, key,
1886                                 deinit ? GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE :
1887                                 0);
1888   if (ret < 0)
1889     {
1890       gnutls_assert ();
1891       gnutls_privkey_deinit (local_key);
1892       return NULL;
1893     }
1894
1895   return local_key;
1896 }
1897
1898 /* converts the given pgp certificate to gnutls_cert* and allocates
1899  * space for them.
1900  */
1901 #ifdef ENABLE_OPENPGP
1902 static gnutls_cert *
1903 alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert)
1904 {
1905   gnutls_cert *local_certs;
1906   int ret = 0;
1907
1908   if (cert == NULL)
1909     return NULL;
1910
1911   local_certs = gnutls_malloc (sizeof (gnutls_cert));
1912   if (local_certs == NULL)
1913     {
1914       gnutls_assert ();
1915       return NULL;
1916     }
1917
1918   ret = _gnutls_openpgp_crt_to_gcert (local_certs, cert);
1919   if (ret < 0)
1920     {
1921       gnutls_assert ();
1922       return NULL;
1923     }
1924
1925   if (ret < 0)
1926     {
1927       gnutls_assert ();
1928       _gnutls_gcert_deinit (local_certs);
1929       gnutls_free (local_certs);
1930       return NULL;
1931     }
1932
1933   ret =
1934     gnutls_openpgp_crt_get_preferred_key_id (cert, local_certs->subkey_id);
1935   if (ret < 0)
1936     local_certs->use_subkey = 0;
1937   else
1938     local_certs->use_subkey = 1;
1939
1940   return local_certs;
1941 }
1942
1943 /* converts the given raw key to gnutls_privkey* and allocates
1944  * space for it.
1945  */
1946 static gnutls_privkey_t
1947 alloc_and_load_pgp_key (gnutls_openpgp_privkey_t key, int deinit)
1948 {
1949   gnutls_privkey_t local_key;
1950   int ret = 0;
1951
1952   if (key == NULL)
1953     return NULL;
1954
1955   ret = gnutls_privkey_init (&local_key);
1956   if (ret < 0)
1957     {
1958       gnutls_assert ();
1959       return NULL;
1960     }
1961
1962   ret =
1963     gnutls_privkey_import_openpgp (local_key, key,
1964                                    deinit ? GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
1965                                    : 0);
1966   if (ret < 0)
1967     {
1968       gnutls_assert ();
1969       gnutls_privkey_deinit (local_key);
1970       return NULL;
1971     }
1972
1973   return local_key;
1974 }
1975 #endif
1976
1977 #ifdef ENABLE_PKCS11
1978
1979 /* converts the given raw key to gnutls_privkey* and allocates
1980  * space for it.
1981  */
1982 static gnutls_privkey_t
1983 alloc_and_load_pkcs11_key (gnutls_pkcs11_privkey_t key, int deinit)
1984 {
1985   gnutls_privkey_t local_key;
1986   int ret = 0;
1987
1988   if (key == NULL)
1989     return NULL;
1990
1991   ret = gnutls_privkey_init (&local_key);
1992   if (ret < 0)
1993     {
1994       gnutls_assert ();
1995       return NULL;
1996     }
1997
1998   ret =
1999     gnutls_privkey_import_pkcs11 (local_key, key,
2000                                   deinit ? GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
2001                                   : 0);
2002   if (ret < 0)
2003     {
2004       gnutls_assert ();
2005       gnutls_privkey_deinit (local_key);
2006       return NULL;
2007     }
2008
2009   return local_key;
2010 }
2011
2012 #endif
2013
2014 void
2015 _gnutls_selected_certs_deinit (gnutls_session_t session)
2016 {
2017   if (session->internals.selected_need_free != 0)
2018     {
2019       int i;
2020
2021       for (i = 0; i < session->internals.selected_cert_list_length; i++)
2022         {
2023           _gnutls_gcert_deinit (&session->internals.selected_cert_list[i]);
2024         }
2025       gnutls_free (session->internals.selected_cert_list);
2026       session->internals.selected_cert_list = NULL;
2027       session->internals.selected_cert_list_length = 0;
2028
2029       gnutls_privkey_deinit(session->internals.selected_key);
2030       session->internals.selected_key = NULL;
2031     }
2032
2033   return;
2034 }
2035
2036 void
2037 _gnutls_selected_certs_set (gnutls_session_t session,
2038                             gnutls_cert * certs, int ncerts,
2039                             gnutls_privkey_t key, int need_free)
2040 {
2041   _gnutls_selected_certs_deinit (session);
2042
2043   session->internals.selected_cert_list = certs;
2044   session->internals.selected_cert_list_length = ncerts;
2045   session->internals.selected_key = key;
2046   session->internals.selected_need_free = need_free;
2047
2048 }
2049
2050
2051 /* finds the most appropriate certificate in the cert list.
2052  * The 'appropriate' is defined by the user.
2053  *
2054  * requested_algo holds the parameters required by the peer (RSA, DSA
2055  * or -1 for any).
2056  *
2057  * Returns 0 on success and a negative value on error. The
2058  * selected certificate will be in session->internals.selected_*.
2059  *
2060  */
2061 int
2062 _gnutls_server_select_cert (gnutls_session_t session,
2063                             gnutls_pk_algorithm_t requested_algo)
2064 {
2065   unsigned i;
2066   int idx;
2067   gnutls_certificate_credentials_t cred;
2068
2069   cred = (gnutls_certificate_credentials_t)
2070     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
2071   if (cred == NULL)
2072     {
2073       gnutls_assert ();
2074       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
2075     }
2076
2077   /* If the callback which retrieves certificate has been set,
2078    * use it and leave.
2079    */
2080   if (cred->server_get_cert_callback != NULL ||
2081     cred->get_cert_callback != NULL)
2082     return call_get_cert_callback (session, NULL, 0, NULL, 0);
2083
2084   /* Otherwise... */
2085
2086   idx = -1;                     /* default is use no certificate */
2087
2088
2089   for (i = 0; i < cred->ncerts; i++)
2090     {
2091       /* find one compatible certificate
2092        */
2093       if (requested_algo == GNUTLS_PK_ANY ||
2094           requested_algo == cred->cert_list[i][0].subject_pk_algorithm)
2095         {
2096           /* if cert type and signature algorithm matches
2097            */
2098           /* *INDENT-OFF* */
2099           if (session->security_parameters.cert_type
2100               == cred->cert_list[i][0].cert_type
2101               && (cred->cert_list[i][0].cert_type == GNUTLS_CRT_OPENPGP
2102                   ||    /* FIXME: make this a check for certificate
2103                            type capabilities */
2104                   !_gnutls_version_has_selectable_sighash
2105                   (gnutls_protocol_get_version (session))
2106                   ||
2107                   _gnutls_session_sign_algo_requested
2108                   (session, cred->cert_list[i][0].sign_algo) == 0))
2109             {
2110               idx = i;
2111               break;
2112             }
2113           /* *INDENT-ON* */
2114         }
2115     }
2116
2117   /* store the certificate pointer for future use, in the handshake.
2118    * (This will allow not calling this callback again.)
2119    */
2120   if (idx >= 0)
2121     {
2122       _gnutls_selected_certs_set (session,
2123                                   &cred->cert_list[idx][0],
2124                                   cred->cert_list_length[idx],
2125                                   cred->pkey[idx], 0);
2126     }
2127   else
2128     /* Certificate does not support REQUESTED_ALGO.  */
2129     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
2130
2131   return 0;
2132 }
2133
2134 /* Frees the rsa_info_st structure.
2135  */
2136 void
2137 _gnutls_free_rsa_info (rsa_info_st * rsa)
2138 {
2139   _gnutls_free_datum (&rsa->modulus);
2140   _gnutls_free_datum (&rsa->exponent);
2141 }