auth_rsa_export.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000, 2001, 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 the RSA key exchange part of the certificate
00026  * authentication.
00027  */
00028 
00029 #include "gnutls_int.h"
00030 #include "gnutls_auth_int.h"
00031 #include "gnutls_errors.h"
00032 #include "gnutls_dh.h"
00033 #include "gnutls_num.h"
00034 #include "gnutls_datum.h"
00035 #include "auth_cert.h"
00036 #include <gnutls_pk.h>
00037 #include <gnutls_algorithms.h>
00038 #include <gnutls_global.h>
00039 #include "debug.h"
00040 #include <gnutls_sig.h>
00041 #include <gnutls_x509.h>
00042 #include <gnutls_rsa_export.h>
00043 #include <gnutls_state.h>
00044 
00045 int MHD__gnutls_gen_rsa_client_kx (MHD_gtls_session_t, opaque **);
00046 int MHD__gnutls_proc_rsa_client_kx (MHD_gtls_session_t, opaque *, size_t);
00047 static int gen_rsa_export_server_kx (MHD_gtls_session_t, opaque **);
00048 static int proc_rsa_export_server_kx (MHD_gtls_session_t, opaque *, size_t);
00049 
00050 const MHD_gtls_mod_auth_st MHD_rsa_export_auth_struct = {
00051   "RSA EXPORT",
00052   MHD_gtls_gen_cert_server_certificate,
00053   MHD_gtls_gen_cert_client_certificate,
00054   gen_rsa_export_server_kx,
00055   MHD__gnutls_gen_rsa_client_kx,
00056   MHD_gtls_gen_cert_client_cert_vrfy,   /* gen client cert vrfy */
00057   MHD_gtls_gen_cert_server_cert_req,    /* server cert request */
00058 
00059   MHD_gtls_proc_cert_server_certificate,
00060   MHD__gnutls_proc_cert_client_certificate,
00061   proc_rsa_export_server_kx,
00062   MHD__gnutls_proc_rsa_client_kx,       /* proc client kx */
00063   MHD_gtls_proc_cert_client_cert_vrfy,  /* proc client cert vrfy */
00064   MHD_gtls_proc_cert_cert_req   /* proc server cert request */
00065 };
00066 
00067 static int
00068 gen_rsa_export_server_kx (MHD_gtls_session_t session, opaque ** data)
00069 {
00070   MHD_gtls_rsa_params_t rsa_params;
00071   const mpi_t *rsa_mpis;
00072   size_t n_e, n_m;
00073   uint8_t *data_e, *data_m;
00074   int ret = 0, data_size;
00075   MHD_gnutls_cert *apr_cert_list;
00076   MHD_gnutls_privkey *apr_pkey;
00077   int apr_cert_list_length;
00078   MHD_gnutls_datum_t signature, ddata;
00079   MHD_gtls_cert_credentials_t cred;
00080 
00081   cred = (MHD_gtls_cert_credentials_t)
00082     MHD_gtls_get_cred (session->key, MHD_GNUTLS_CRD_CERTIFICATE, NULL);
00083   if (cred == NULL)
00084     {
00085       MHD_gnutls_assert ();
00086       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00087     }
00088 
00089   /* find the appropriate certificate */
00090   if ((ret =
00091        MHD_gtls_get_selected_cert (session, &apr_cert_list,
00092                                    &apr_cert_list_length, &apr_pkey)) < 0)
00093     {
00094       MHD_gnutls_assert ();
00095       return ret;
00096     }
00097 
00098   /* abort sending this message if we have a certificate
00099    * of 512 bits or less.
00100    */
00101   if (apr_pkey && MHD__gnutls_mpi_get_nbits (apr_pkey->params[0]) <= 512)
00102     {
00103       MHD_gnutls_assert ();
00104       return GNUTLS_E_INT_RET_0;
00105     }
00106 
00107   rsa_params =
00108     MHD_gtls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
00109                                          session);
00110   rsa_mpis = MHD__gnutls_rsa_params_to_mpi (rsa_params);
00111   if (rsa_mpis == NULL)
00112     {
00113       MHD_gnutls_assert ();
00114       return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
00115     }
00116 
00117   if ((ret = MHD_gtls_auth_info_set (session, MHD_GNUTLS_CRD_CERTIFICATE,
00118                                      sizeof (cert_auth_info_st), 0)) < 0)
00119     {
00120       MHD_gnutls_assert ();
00121       return ret;
00122     }
00123 
00124   MHD_gtls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);
00125 
00126   MHD_gtls_mpi_print (NULL, &n_m, rsa_mpis[0]);
00127   MHD_gtls_mpi_print (NULL, &n_e, rsa_mpis[1]);
00128 
00129   (*data) = MHD_gnutls_malloc (n_e + n_m + 4);
00130   if (*data == NULL)
00131     {
00132       return GNUTLS_E_MEMORY_ERROR;
00133     }
00134 
00135   data_m = &(*data)[0];
00136   MHD_gtls_mpi_print (&data_m[2], &n_m, rsa_mpis[0]);
00137 
00138   MHD_gtls_write_uint16 (n_m, data_m);
00139 
00140   data_e = &data_m[2 + n_m];
00141   MHD_gtls_mpi_print (&data_e[2], &n_e, rsa_mpis[1]);
00142 
00143   MHD_gtls_write_uint16 (n_e, data_e);
00144 
00145   data_size = n_m + n_e + 4;
00146 
00147 
00148   /* Generate the signature. */
00149 
00150   ddata.data = *data;
00151   ddata.size = data_size;
00152 
00153   if (apr_cert_list_length > 0)
00154     {
00155       if ((ret =
00156            MHD_gtls_tls_sign_params (session, &apr_cert_list[0],
00157                                      apr_pkey, &ddata, &signature)) < 0)
00158         {
00159           MHD_gnutls_assert ();
00160           MHD_gnutls_free (*data);
00161           *data = NULL;
00162           return ret;
00163         }
00164     }
00165   else
00166     {
00167       MHD_gnutls_assert ();
00168       return data_size;         /* do not put a signature - ILLEGAL! */
00169     }
00170 
00171   *data = MHD_gtls_realloc_fast (*data, data_size + signature.size + 2);
00172   if (*data == NULL)
00173     {
00174       MHD__gnutls_free_datum (&signature);
00175       MHD_gnutls_assert ();
00176       return GNUTLS_E_MEMORY_ERROR;
00177     }
00178 
00179   MHD_gtls_write_datum16 (&((*data)[data_size]), signature);
00180   data_size += signature.size + 2;
00181 
00182   MHD__gnutls_free_datum (&signature);
00183 
00184   return data_size;
00185 }
00186 
00187 /* if the peer's certificate is of 512 bits or less, returns non zero.
00188  */
00189 int
00190 MHD__gnutls_peers_cert_less_512 (MHD_gtls_session_t session)
00191 {
00192   MHD_gnutls_cert peer_cert;
00193   int ret;
00194   cert_auth_info_t info = MHD_gtls_get_auth_info (session);
00195 
00196   if (info == NULL || info->ncerts == 0)
00197     {
00198       MHD_gnutls_assert ();
00199       /* we need this in order to get peer's certificate */
00200       return 0;
00201     }
00202 
00203   if ((ret =
00204        MHD_gtls_raw_cert_to_gcert (&peer_cert,
00205                                    session->security_parameters.cert_type,
00206                                    &info->raw_certificate_list[0],
00207                                    CERT_NO_COPY)) < 0)
00208     {
00209       MHD_gnutls_assert ();
00210       return 0;
00211     }
00212 
00213   if (peer_cert.subject_pk_algorithm != MHD_GNUTLS_PK_RSA)
00214     {
00215       MHD_gnutls_assert ();
00216       MHD_gtls_gcert_deinit (&peer_cert);
00217       return 0;
00218     }
00219 
00220   if (MHD__gnutls_mpi_get_nbits (peer_cert.params[0]) <= 512)
00221     {
00222       MHD_gtls_gcert_deinit (&peer_cert);
00223       return 1;
00224     }
00225 
00226   MHD_gtls_gcert_deinit (&peer_cert);
00227 
00228   return 0;
00229 }
00230 
00231 static int
00232 proc_rsa_export_server_kx (MHD_gtls_session_t session,
00233                            opaque * data, size_t _data_size)
00234 {
00235   uint16_t n_m, n_e;
00236   size_t _n_m, _n_e;
00237   uint8_t *data_m;
00238   uint8_t *data_e;
00239   int i, sigsize;
00240   MHD_gnutls_datum_t vparams, signature;
00241   int ret;
00242   ssize_t data_size = _data_size;
00243   cert_auth_info_t info;
00244   MHD_gnutls_cert peer_cert;
00245 
00246   info = MHD_gtls_get_auth_info (session);
00247   if (info == NULL || info->ncerts == 0)
00248     {
00249       MHD_gnutls_assert ();
00250       /* we need this in order to get peer's certificate */
00251       return GNUTLS_E_INTERNAL_ERROR;
00252     }
00253 
00254 
00255   i = 0;
00256 
00257   DECR_LEN (data_size, 2);
00258   n_m = MHD_gtls_read_uint16 (&data[i]);
00259   i += 2;
00260 
00261   DECR_LEN (data_size, n_m);
00262   data_m = &data[i];
00263   i += n_m;
00264 
00265   DECR_LEN (data_size, 2);
00266   n_e = MHD_gtls_read_uint16 (&data[i]);
00267   i += 2;
00268 
00269   DECR_LEN (data_size, n_e);
00270   data_e = &data[i];
00271   i += n_e;
00272 
00273   _n_e = n_e;
00274   _n_m = n_m;
00275 
00276   if (MHD_gtls_mpi_scan_nz (&session->key->rsa[0], data_m, &_n_m) != 0)
00277     {
00278       MHD_gnutls_assert ();
00279       return GNUTLS_E_MPI_SCAN_FAILED;
00280     }
00281 
00282   if (MHD_gtls_mpi_scan_nz (&session->key->rsa[1], data_e, &_n_e) != 0)
00283     {
00284       MHD_gnutls_assert ();
00285       return GNUTLS_E_MPI_SCAN_FAILED;
00286     }
00287 
00288   MHD_gtls_rsa_export_set_pubkey (session, session->key->rsa[1],
00289                                   session->key->rsa[0]);
00290 
00291   /* VERIFY SIGNATURE */
00292 
00293   vparams.size = n_m + n_e + 4;
00294   vparams.data = data;
00295 
00296   DECR_LEN (data_size, 2);
00297   sigsize = MHD_gtls_read_uint16 (&data[vparams.size]);
00298 
00299   DECR_LEN (data_size, sigsize);
00300   signature.data = &data[vparams.size + 2];
00301   signature.size = sigsize;
00302 
00303   if ((ret =
00304        MHD_gtls_raw_cert_to_gcert (&peer_cert,
00305                                    session->security_parameters.cert_type,
00306                                    &info->raw_certificate_list[0],
00307                                    CERT_NO_COPY)) < 0)
00308     {
00309       MHD_gnutls_assert ();
00310       return ret;
00311     }
00312 
00313   ret =
00314     MHD_gtls_verify_sig_params (session, &peer_cert, &vparams, &signature);
00315 
00316   MHD_gtls_gcert_deinit (&peer_cert);
00317   if (ret < 0)
00318     {
00319       MHD_gnutls_assert ();
00320     }
00321 
00322   return ret;
00323 }

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