auth_dh_common.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation
00003  *
00004  * Author: Nikos Mavrogiannopoulos
00005  *
00006  * This file is part of GNUTLS.
00007  *
00008  * The GNUTLS library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00021  * USA
00022  *
00023  */
00024 
00025 /* This file contains common stuff in Ephemeral Diffie Hellman (DHE) and
00026  * Anonymous DH key exchange(DHA). These are used in the handshake procedure
00027  * of the certificate and anoymous authentication.
00028  */
00029 
00030 #include "gnutls_int.h"
00031 #include "gnutls_auth_int.h"
00032 #include "gnutls_errors.h"
00033 #include "gnutls_dh.h"
00034 #include "gnutls_num.h"
00035 #include "gnutls_sig.h"
00036 #include <gnutls_datum.h>
00037 #include <gnutls_x509.h>
00038 #include <gnutls_state.h>
00039 #include <auth_dh_common.h>
00040 #include <gnutls_algorithms.h>
00041 
00042 /* Frees the MHD_gtls_dh_info_st structure.
00043  */
00044 void
00045 MHD_gtls_free_dh_info (MHD_gtls_dh_info_st * dh)
00046 {
00047   dh->secret_bits = 0;
00048   MHD__gnutls_free_datum (&dh->prime);
00049   MHD__gnutls_free_datum (&dh->generator);
00050   MHD__gnutls_free_datum (&dh->public_key);
00051 }
00052 
00053 int
00054 MHD_gtls_proc_dh_common_client_kx (MHD_gtls_session_t session,
00055                                    opaque * data, size_t _data_size,
00056                                    mpi_t g, mpi_t p)
00057 {
00058   uint16_t n_Y;
00059   size_t _n_Y;
00060   int ret;
00061   ssize_t data_size = _data_size;
00062 
00063 
00064   DECR_LEN (data_size, 2);
00065   n_Y = MHD_gtls_read_uint16 (&data[0]);
00066   _n_Y = n_Y;
00067 
00068   DECR_LEN (data_size, n_Y);
00069   if (MHD_gtls_mpi_scan_nz (&session->key->client_Y, &data[2], &_n_Y))
00070     {
00071       MHD_gnutls_assert ();
00072       return GNUTLS_E_MPI_SCAN_FAILED;
00073     }
00074 
00075   MHD_gtls_dh_set_peer_public (session, session->key->client_Y);
00076 
00077   session->key->KEY =
00078     MHD_gtls_calc_dh_key (session->key->client_Y, session->key->dh_secret, p);
00079 
00080   if (session->key->KEY == NULL)
00081     {
00082       MHD_gnutls_assert ();
00083       return GNUTLS_E_MEMORY_ERROR;
00084     }
00085 
00086   MHD_gtls_mpi_release (&session->key->client_Y);
00087   MHD_gtls_mpi_release (&session->key->dh_secret);
00088 
00089   ret = MHD_gtls_mpi_dprint (&session->key->key, session->key->KEY);
00090 
00091   MHD_gtls_mpi_release (&session->key->KEY);
00092 
00093   if (ret < 0)
00094     {
00095       return ret;
00096     }
00097 
00098   return 0;
00099 }
00100 
00101 int
00102 MHD_gtls_gen_dh_common_client_kx (MHD_gtls_session_t session, opaque ** data)
00103 {
00104   mpi_t x = NULL, X = NULL;
00105   size_t n_X;
00106   int ret;
00107 
00108   *data = NULL;
00109 
00110   X = MHD_gtls_calc_dh_secret (&x, session->key->client_g,
00111                                session->key->client_p);
00112   if (X == NULL || x == NULL)
00113     {
00114       MHD_gnutls_assert ();
00115       ret = GNUTLS_E_MEMORY_ERROR;
00116       goto error;
00117     }
00118 
00119   MHD_gtls_dh_set_secret_bits (session, MHD__gnutls_mpi_get_nbits (x));
00120 
00121   MHD_gtls_mpi_print (NULL, &n_X, X);
00122   (*data) = MHD_gnutls_malloc (n_X + 2);
00123   if (*data == NULL)
00124     {
00125       ret = GNUTLS_E_MEMORY_ERROR;
00126       goto error;
00127     }
00128 
00129   MHD_gtls_mpi_print (&(*data)[2], &n_X, X);
00130   MHD_gtls_mpi_release (&X);
00131 
00132   MHD_gtls_write_uint16 (n_X, &(*data)[0]);
00133 
00134   /* calculate the key after calculating the message */
00135   session->key->KEY =
00136     MHD_gtls_calc_dh_key (session->key->client_Y, x, session->key->client_p);
00137 
00138   MHD_gtls_mpi_release (&x);
00139   if (session->key->KEY == NULL)
00140     {
00141       MHD_gnutls_assert ();
00142       ret = GNUTLS_E_MEMORY_ERROR;
00143       goto error;
00144     }
00145 
00146   /* THESE SHOULD BE DISCARDED */
00147   MHD_gtls_mpi_release (&session->key->client_Y);
00148   MHD_gtls_mpi_release (&session->key->client_p);
00149   MHD_gtls_mpi_release (&session->key->client_g);
00150 
00151   ret = MHD_gtls_mpi_dprint (&session->key->key, session->key->KEY);
00152 
00153   MHD_gtls_mpi_release (&session->key->KEY);
00154 
00155   if (ret < 0)
00156     {
00157       MHD_gnutls_assert ();
00158       goto error;
00159     }
00160 
00161   return n_X + 2;
00162 
00163 error:
00164   MHD_gtls_mpi_release (&x);
00165   MHD_gtls_mpi_release (&X);
00166   MHD_gnutls_free (*data);
00167   *data = NULL;
00168   return ret;
00169 }
00170 
00171 int
00172 MHD_gtls_proc_dh_common_server_kx (MHD_gtls_session_t session,
00173                                    opaque * data, size_t _data_size, int psk)
00174 {
00175   uint16_t n_Y, n_g, n_p;
00176   size_t _n_Y, _n_g, _n_p;
00177   uint8_t *data_p;
00178   uint8_t *data_g;
00179   uint8_t *data_Y;
00180   int i, bits, psk_size, ret;
00181   ssize_t data_size = _data_size;
00182 
00183   i = 0;
00184 
00185   if (psk != 0)
00186     {
00187       DECR_LEN (data_size, 2);
00188       psk_size = MHD_gtls_read_uint16 (&data[i]);
00189       DECR_LEN (data_size, psk_size);
00190       i += 2 + psk_size;
00191     }
00192 
00193   DECR_LEN (data_size, 2);
00194   n_p = MHD_gtls_read_uint16 (&data[i]);
00195   i += 2;
00196 
00197   DECR_LEN (data_size, n_p);
00198   data_p = &data[i];
00199   i += n_p;
00200 
00201   DECR_LEN (data_size, 2);
00202   n_g = MHD_gtls_read_uint16 (&data[i]);
00203   i += 2;
00204 
00205   DECR_LEN (data_size, n_g);
00206   data_g = &data[i];
00207   i += n_g;
00208 
00209   DECR_LEN (data_size, 2);
00210   n_Y = MHD_gtls_read_uint16 (&data[i]);
00211   i += 2;
00212 
00213   DECR_LEN (data_size, n_Y);
00214   data_Y = &data[i];
00215   i += n_Y;
00216 
00217   _n_Y = n_Y;
00218   _n_g = n_g;
00219   _n_p = n_p;
00220 
00221   if (MHD_gtls_mpi_scan_nz (&session->key->client_Y, data_Y, &_n_Y) != 0)
00222     {
00223       MHD_gnutls_assert ();
00224       return GNUTLS_E_MPI_SCAN_FAILED;
00225     }
00226 
00227   if (MHD_gtls_mpi_scan_nz (&session->key->client_g, data_g, &_n_g) != 0)
00228     {
00229       MHD_gnutls_assert ();
00230       return GNUTLS_E_MPI_SCAN_FAILED;
00231     }
00232   if (MHD_gtls_mpi_scan_nz (&session->key->client_p, data_p, &_n_p) != 0)
00233     {
00234       MHD_gnutls_assert ();
00235       return GNUTLS_E_MPI_SCAN_FAILED;
00236     }
00237 
00238   bits = MHD_gtls_dh_get_allowed_prime_bits (session);
00239   if (bits < 0)
00240     {
00241       MHD_gnutls_assert ();
00242       return bits;
00243     }
00244 
00245   if (MHD__gnutls_mpi_get_nbits (session->key->client_p) < (size_t) bits)
00246     {
00247       /* the prime used by the peer is not acceptable
00248        */
00249       MHD_gnutls_assert ();
00250       return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
00251     }
00252 
00253   MHD_gtls_dh_set_group (session, session->key->client_g,
00254                          session->key->client_p);
00255   MHD_gtls_dh_set_peer_public (session, session->key->client_Y);
00256 
00257   ret = n_Y + n_p + n_g + 6;
00258   if (psk != 0)
00259     ret += 2;
00260 
00261   return ret;
00262 }
00263 
00264 /* If the psk flag is set, then an empty psk_identity_hint will
00265  * be inserted */
00266 int
00267 MHD_gtls_dh_common_print_server_kx (MHD_gtls_session_t session,
00268                                     mpi_t g, mpi_t p, opaque ** data, int psk)
00269 {
00270   mpi_t x, X;
00271   size_t n_X, n_g, n_p;
00272   int ret, data_size, pos;
00273   uint8_t *pdata;
00274 
00275   X = MHD_gtls_calc_dh_secret (&x, g, p);
00276   if (X == NULL || x == NULL)
00277     {
00278       MHD_gnutls_assert ();
00279       return GNUTLS_E_MEMORY_ERROR;
00280     }
00281 
00282   session->key->dh_secret = x;
00283   MHD_gtls_dh_set_secret_bits (session, MHD__gnutls_mpi_get_nbits (x));
00284 
00285   MHD_gtls_mpi_print (NULL, &n_g, g);
00286   MHD_gtls_mpi_print (NULL, &n_p, p);
00287   MHD_gtls_mpi_print (NULL, &n_X, X);
00288 
00289   data_size = n_g + n_p + n_X + 6;
00290   if (psk != 0)
00291     data_size += 2;
00292 
00293   (*data) = MHD_gnutls_malloc (data_size);
00294   if (*data == NULL)
00295     {
00296       MHD_gtls_mpi_release (&X);
00297       return GNUTLS_E_MEMORY_ERROR;
00298     }
00299 
00300   pos = 0;
00301   pdata = *data;
00302 
00303   if (psk != 0)
00304     {
00305       MHD_gtls_write_uint16 (0, &pdata[pos]);
00306       pos += 2;
00307     }
00308 
00309   MHD_gtls_mpi_print (&pdata[pos + 2], &n_p, p);
00310   MHD_gtls_write_uint16 (n_p, &pdata[pos]);
00311 
00312   pos += n_p + 2;
00313 
00314   MHD_gtls_mpi_print (&pdata[pos + 2], &n_g, g);
00315   MHD_gtls_write_uint16 (n_g, &pdata[pos]);
00316 
00317   pos += n_g + 2;
00318 
00319   MHD_gtls_mpi_print (&pdata[pos + 2], &n_X, X);
00320   MHD_gtls_mpi_release (&X);
00321 
00322   MHD_gtls_write_uint16 (n_X, &pdata[pos]);
00323 
00324   ret = data_size;
00325 
00326   return ret;
00327 }

Generated on Fri Feb 27 18:31:22 2009 for GNU libmicrohttpd by  doxygen 1.5.7.1