Tizen 2.0 Release
[external/libgnutls26.git] / lib / auth_rsa_export.c
1 /*
2  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010 Free
3  * 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 /* This file contains the RSA key exchange part of the certificate
27  * authentication.
28  */
29
30 #include "gnutls_int.h"
31 #include "gnutls_auth.h"
32 #include "gnutls_errors.h"
33 #include "gnutls_dh.h"
34 #include "gnutls_num.h"
35 #include "gnutls_datum.h"
36 #include "auth_cert.h"
37 #include <gnutls_pk.h>
38 #include <gnutls_algorithms.h>
39 #include <gnutls_global.h>
40 #include "debug.h"
41 #include <gnutls_sig.h>
42 #include <gnutls_x509.h>
43 #include <gnutls_rsa_export.h>
44 #include <gnutls_state.h>
45 #include <random.h>
46
47 int _gnutls_gen_rsa_client_kx (gnutls_session_t, opaque **);
48 static int gen_rsa_export_server_kx (gnutls_session_t, opaque **);
49 static int proc_rsa_export_server_kx (gnutls_session_t, opaque *, size_t);
50 static int proc_rsa_export_client_kx (gnutls_session_t session, opaque * data,
51                                       size_t _data_size);
52
53 const mod_auth_st rsa_export_auth_struct = {
54   "RSA EXPORT",
55   _gnutls_gen_cert_server_certificate,
56   _gnutls_gen_cert_client_certificate,
57   gen_rsa_export_server_kx,
58   _gnutls_gen_rsa_client_kx,
59   _gnutls_gen_cert_client_cert_vrfy,    /* gen client cert vrfy */
60   _gnutls_gen_cert_server_cert_req,     /* server cert request */
61
62   _gnutls_proc_cert_server_certificate,
63   _gnutls_proc_cert_client_certificate,
64   proc_rsa_export_server_kx,
65   proc_rsa_export_client_kx,    /* proc client kx */
66   _gnutls_proc_cert_client_cert_vrfy,   /* proc client cert vrfy */
67   _gnutls_proc_cert_cert_req    /* proc server cert request */
68 };
69
70 /* This function reads the RSA parameters from the private key
71  */
72 static int
73 _gnutls_get_private_rsa_params (gnutls_session_t session,
74                                 bigint_t ** params, int *params_size)
75 {
76   int bits;
77   gnutls_certificate_credentials_t cred;
78   gnutls_rsa_params_t rsa_params;
79
80   cred = (gnutls_certificate_credentials_t)
81     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
82   if (cred == NULL)
83     {
84       gnutls_assert ();
85       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
86     }
87
88   if (session->internals.selected_cert_list == NULL)
89     {
90       gnutls_assert ();
91       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
92     }
93
94   bits =
95     _gnutls_mpi_get_nbits (session->internals.
96                            selected_cert_list[0].params[0]);
97
98   if (_gnutls_cipher_suite_get_kx_algo
99       (&session->security_parameters.current_cipher_suite)
100       != GNUTLS_KX_RSA_EXPORT || bits < 512)
101     {
102       gnutls_assert ();
103       return GNUTLS_E_INVALID_REQUEST;
104     }
105
106   rsa_params =
107     _gnutls_certificate_get_rsa_params (cred->rsa_params,
108                                         cred->params_func, session);
109   /* EXPORT case: */
110   if (rsa_params == NULL)
111     {
112       gnutls_assert ();
113       return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
114     }
115
116   /* In the export case, we do use temporary RSA params
117    * of 512 bits size. The params in the certificate are
118    * used to sign this temporary stuff.
119    */
120   *params_size = RSA_PRIVATE_PARAMS;
121   *params = rsa_params->params;
122
123   return 0;
124 }
125
126 int
127 proc_rsa_export_client_kx (gnutls_session_t session, opaque * data,
128                            size_t _data_size)
129 {
130   gnutls_datum_t plaintext;
131   gnutls_datum_t ciphertext;
132   int ret, dsize;
133   bigint_t *params;
134   int params_len;
135   int randomize_key = 0;
136   ssize_t data_size = _data_size;
137
138   if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
139     {
140       /* SSL 3.0 
141        */
142       ciphertext.data = data;
143       ciphertext.size = data_size;
144     }
145   else
146     {
147       /* TLS 1.0
148        */
149       DECR_LEN (data_size, 2);
150       ciphertext.data = &data[2];
151       dsize = _gnutls_read_uint16 (data);
152
153       if (dsize != data_size)
154         {
155           gnutls_assert ();
156           return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
157         }
158       ciphertext.size = dsize;
159     }
160
161   ret = _gnutls_get_private_rsa_params (session, &params, &params_len);
162   if (ret < 0)
163     {
164       gnutls_assert ();
165       return ret;
166     }
167
168   ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, params_len, 2);     /* btype==2 */
169
170   if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
171     {
172       /* In case decryption fails then don't inform
173        * the peer. Just use a random key. (in order to avoid
174        * attack against pkcs-1 formating).
175        */
176       gnutls_assert ();
177       _gnutls_x509_log ("auth_rsa: Possible PKCS #1 format attack\n");
178       randomize_key = 1;
179     }
180   else
181     {
182       /* If the secret was properly formatted, then
183        * check the version number.
184        */
185       if (_gnutls_get_adv_version_major (session) != plaintext.data[0]
186           || _gnutls_get_adv_version_minor (session) != plaintext.data[1])
187         {
188           /* No error is returned here, if the version number check
189            * fails. We proceed normally.
190            * That is to defend against the attack described in the paper
191            * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
192            * Ondej Pokorny and Tomas Rosa.
193            */
194           gnutls_assert ();
195           _gnutls_x509_log
196             ("auth_rsa: Possible PKCS #1 version check format attack\n");
197         }
198     }
199
200   if (randomize_key != 0)
201     {
202       session->key->key.size = GNUTLS_MASTER_SIZE;
203       session->key->key.data = gnutls_malloc (session->key->key.size);
204       if (session->key->key.data == NULL)
205         {
206           gnutls_assert ();
207           return GNUTLS_E_MEMORY_ERROR;
208         }
209
210       /* we do not need strong random numbers here.
211        */
212       ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->key->key.data,
213                          session->key->key.size);
214       if (ret < 0)
215         {
216           gnutls_assert ();
217           return ret;
218         }
219
220     }
221   else
222     {
223       session->key->key.data = plaintext.data;
224       session->key->key.size = plaintext.size;
225     }
226
227   /* This is here to avoid the version check attack
228    * discussed above.
229    */
230   session->key->key.data[0] = _gnutls_get_adv_version_major (session);
231   session->key->key.data[1] = _gnutls_get_adv_version_minor (session);
232
233   return 0;
234 }
235
236 static int
237 gen_rsa_export_server_kx (gnutls_session_t session, opaque ** data)
238 {
239   gnutls_rsa_params_t rsa_params;
240   const bigint_t *rsa_mpis;
241   size_t n_e, n_m;
242   uint8_t *data_e, *data_m;
243   int ret = 0, data_size;
244   gnutls_cert *apr_cert_list;
245   gnutls_privkey_t apr_pkey;
246   int apr_cert_list_length;
247   gnutls_datum_t signature, ddata;
248   gnutls_certificate_credentials_t cred;
249   gnutls_sign_algorithm_t sign_algo;
250   unsigned int bits = 0;
251
252   cred = (gnutls_certificate_credentials_t)
253     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
254   if (cred == NULL)
255     {
256       gnutls_assert ();
257       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
258     }
259
260   /* find the appropriate certificate */
261   if ((ret =
262        _gnutls_get_selected_cert (session, &apr_cert_list,
263                                   &apr_cert_list_length, &apr_pkey)) < 0)
264     {
265       gnutls_assert ();
266       return ret;
267     }
268
269   /* abort sending this message if we have a certificate
270    * of 512 bits or less.
271    */
272   gnutls_privkey_get_pk_algorithm (apr_pkey, &bits);
273   if (apr_pkey && bits <= 512)
274     {
275       gnutls_assert ();
276       return GNUTLS_E_INT_RET_0;
277     }
278
279   rsa_params =
280     _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
281                                         session);
282   rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params);
283   if (rsa_mpis == NULL)
284     {
285       gnutls_assert ();
286       return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
287     }
288
289   if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
290                                     sizeof (cert_auth_info_st), 0)) < 0)
291     {
292       gnutls_assert ();
293       return ret;
294     }
295
296   _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);
297
298   _gnutls_mpi_print (rsa_mpis[0], NULL, &n_m);
299   _gnutls_mpi_print (rsa_mpis[1], NULL, &n_e);
300
301   (*data) = gnutls_malloc (n_e + n_m + 4);
302   if (*data == NULL)
303     {
304       return GNUTLS_E_MEMORY_ERROR;
305     }
306
307   data_m = &(*data)[0];
308   _gnutls_mpi_print (rsa_mpis[0], &data_m[2], &n_m);
309
310   _gnutls_write_uint16 (n_m, data_m);
311
312   data_e = &data_m[2 + n_m];
313   _gnutls_mpi_print (rsa_mpis[1], &data_e[2], &n_e);
314
315   _gnutls_write_uint16 (n_e, data_e);
316
317   data_size = n_m + n_e + 4;
318
319
320   /* Generate the signature. */
321
322   ddata.data = *data;
323   ddata.size = data_size;
324
325   if (apr_cert_list_length > 0)
326     {
327       if ((ret =
328            _gnutls_handshake_sign_data (session, &apr_cert_list[0],
329                                         apr_pkey, &ddata, &signature,
330                                         &sign_algo)) < 0)
331         {
332           gnutls_assert ();
333           gnutls_free (*data);
334           *data = NULL;
335           return ret;
336         }
337     }
338   else
339     {
340       gnutls_assert ();
341       return data_size;         /* do not put a signature - ILLEGAL! */
342     }
343
344   *data = gnutls_realloc_fast (*data, data_size + signature.size + 2);
345   if (*data == NULL)
346     {
347       _gnutls_free_datum (&signature);
348       gnutls_assert ();
349       return GNUTLS_E_MEMORY_ERROR;
350     }
351
352   _gnutls_write_datum16 (&((*data)[data_size]), signature);
353   data_size += signature.size + 2;
354
355   _gnutls_free_datum (&signature);
356
357   return data_size;
358 }
359
360 /* if the peer's certificate is of 512 bits or less, returns non zero.
361  */
362 int
363 _gnutls_peers_cert_less_512 (gnutls_session_t session)
364 {
365   gnutls_cert peer_cert;
366   int ret;
367   cert_auth_info_t info = _gnutls_get_auth_info (session);
368
369   if (info == NULL || info->ncerts == 0)
370     {
371       gnutls_assert ();
372       /* we need this in order to get peer's certificate */
373       return 0;
374     }
375
376   if ((ret =
377        _gnutls_get_auth_info_gcert (&peer_cert,
378                                     session->security_parameters.cert_type,
379                                     info, CERT_NO_COPY)) < 0)
380     {
381       gnutls_assert ();
382       return 0;
383     }
384
385   if (peer_cert.subject_pk_algorithm != GNUTLS_PK_RSA)
386     {
387       gnutls_assert ();
388       _gnutls_gcert_deinit (&peer_cert);
389       return 0;
390     }
391
392   if (_gnutls_mpi_get_nbits (peer_cert.params[0]) <= 512)
393     {
394       _gnutls_gcert_deinit (&peer_cert);
395       return 1;
396     }
397
398   _gnutls_gcert_deinit (&peer_cert);
399
400   return 0;
401 }
402
403 static int
404 proc_rsa_export_server_kx (gnutls_session_t session,
405                            opaque * data, size_t _data_size)
406 {
407   uint16_t n_m, n_e;
408   size_t _n_m, _n_e;
409   uint8_t *data_m;
410   uint8_t *data_e;
411   int i, sigsize;
412   gnutls_datum_t vparams, signature;
413   int ret;
414   ssize_t data_size = _data_size;
415   cert_auth_info_t info;
416   gnutls_cert peer_cert;
417
418   info = _gnutls_get_auth_info (session);
419   if (info == NULL || info->ncerts == 0)
420     {
421       gnutls_assert ();
422       /* we need this in order to get peer's certificate */
423       return GNUTLS_E_INTERNAL_ERROR;
424     }
425
426
427   i = 0;
428
429   DECR_LEN (data_size, 2);
430   n_m = _gnutls_read_uint16 (&data[i]);
431   i += 2;
432
433   DECR_LEN (data_size, n_m);
434   data_m = &data[i];
435   i += n_m;
436
437   DECR_LEN (data_size, 2);
438   n_e = _gnutls_read_uint16 (&data[i]);
439   i += 2;
440
441   DECR_LEN (data_size, n_e);
442   data_e = &data[i];
443   i += n_e;
444
445   _n_e = n_e;
446   _n_m = n_m;
447
448   if (_gnutls_mpi_scan_nz (&session->key->rsa[0], data_m, _n_m) != 0)
449     {
450       gnutls_assert ();
451       return GNUTLS_E_MPI_SCAN_FAILED;
452     }
453
454   if (_gnutls_mpi_scan_nz (&session->key->rsa[1], data_e, _n_e) != 0)
455     {
456       gnutls_assert ();
457       return GNUTLS_E_MPI_SCAN_FAILED;
458     }
459
460   _gnutls_rsa_export_set_pubkey (session, session->key->rsa[1],
461                                  session->key->rsa[0]);
462
463   /* VERIFY SIGNATURE */
464
465   vparams.size = n_m + n_e + 4;
466   vparams.data = data;
467
468   DECR_LEN (data_size, 2);
469   sigsize = _gnutls_read_uint16 (&data[vparams.size]);
470
471   DECR_LEN (data_size, sigsize);
472   signature.data = &data[vparams.size + 2];
473   signature.size = sigsize;
474
475   if ((ret =
476        _gnutls_get_auth_info_gcert (&peer_cert,
477                                     session->security_parameters.cert_type,
478                                     info, CERT_NO_COPY)) < 0)
479     {
480       gnutls_assert ();
481       return ret;
482     }
483
484   ret =
485     _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature,
486                                    GNUTLS_SIGN_UNKNOWN);
487
488   _gnutls_gcert_deinit (&peer_cert);
489   if (ret < 0)
490     {
491       gnutls_assert ();
492     }
493
494   return ret;
495 }