gnutls_sig.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001, 2004, 2005, 2006, 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 #include <gnutls_int.h>
00026 #include <gnutls_errors.h>
00027 #include <x509_b64.h>
00028 #include <auth_cert.h>
00029 #include <gnutls_cert.h>
00030 #include <gnutls_datum.h>
00031 #include <gnutls_mpi.h>
00032 #include <gnutls_global.h>
00033 #include <gnutls_pk.h>
00034 #include <debug.h>
00035 #include <gnutls_buffers.h>
00036 #include <gnutls_sig.h>
00037 #include <gnutls_kx.h>
00038 
00039 static int MHD__gnutls_tls_sign (MHD_gtls_session_t session,
00040                                  MHD_gnutls_cert * cert,
00041                                  MHD_gnutls_privkey * pkey,
00042                                  const MHD_gnutls_datum_t * hash_concat,
00043                                  MHD_gnutls_datum_t * signature);
00044 
00045 /* Generates a signature of all the previous sent packets in the
00046  * handshake procedure. (20040227: now it works for SSL 3.0 as well)
00047  */
00048 int
00049 MHD_gtls_tls_sign_hdata (MHD_gtls_session_t session,
00050                          MHD_gnutls_cert * cert,
00051                          MHD_gnutls_privkey * pkey,
00052                          MHD_gnutls_datum_t * signature)
00053 {
00054   MHD_gnutls_datum_t dconcat;
00055   int ret;
00056   opaque concat[36];
00057   mac_hd_t td_md5;
00058   mac_hd_t td_sha;
00059   enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
00060 
00061   td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
00062   if (td_sha == NULL)
00063     {
00064       MHD_gnutls_assert ();
00065       return GNUTLS_E_HASH_FAILED;
00066     }
00067 
00068   if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
00069     {
00070       ret = MHD_gtls_generate_master (session, 1);
00071       if (ret < 0)
00072         {
00073           MHD_gnutls_assert ();
00074           return ret;
00075         }
00076 
00077       MHD_gnutls_mac_deinit_ssl3_handshake (td_sha, &concat[16],
00078                                             session->security_parameters.
00079                                             master_secret, TLS_MASTER_SIZE);
00080     }
00081   else
00082     MHD_gnutls_hash_deinit (td_sha, &concat[16]);
00083 
00084   switch (cert->subject_pk_algorithm)
00085     {
00086     case MHD_GNUTLS_PK_RSA:
00087       td_md5 =
00088         MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
00089       if (td_md5 == NULL)
00090         {
00091           MHD_gnutls_assert ();
00092           return GNUTLS_E_HASH_FAILED;
00093         }
00094 
00095       if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
00096         MHD_gnutls_mac_deinit_ssl3_handshake (td_md5, concat,
00097                                               session->security_parameters.
00098                                               master_secret, TLS_MASTER_SIZE);
00099       else
00100         MHD_gnutls_hash_deinit (td_md5, concat);
00101 
00102       dconcat.data = concat;
00103       dconcat.size = 36;
00104       break;
00105     default:
00106       MHD_gnutls_assert ();
00107       return GNUTLS_E_INTERNAL_ERROR;
00108     }
00109   ret = MHD__gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
00110   if (ret < 0)
00111     {
00112       MHD_gnutls_assert ();
00113     }
00114 
00115   return ret;
00116 }
00117 
00118 /* Generates a signature of all the random data and the parameters.
00119  * Used in DHE_* ciphersuites.
00120  */
00121 int
00122 MHD_gtls_tls_sign_params (MHD_gtls_session_t session,
00123                           MHD_gnutls_cert * cert,
00124                           MHD_gnutls_privkey * pkey,
00125                           MHD_gnutls_datum_t * params,
00126                           MHD_gnutls_datum_t * signature)
00127 {
00128   MHD_gnutls_datum_t dconcat;
00129   int ret;
00130   mac_hd_t td_sha;
00131   opaque concat[36];
00132   enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
00133 
00134   td_sha = MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
00135   if (td_sha == NULL)
00136     {
00137       MHD_gnutls_assert ();
00138       return GNUTLS_E_HASH_FAILED;
00139     }
00140 
00141   MHD_gnutls_hash (td_sha, session->security_parameters.client_random,
00142                    TLS_RANDOM_SIZE);
00143   MHD_gnutls_hash (td_sha, session->security_parameters.server_random,
00144                    TLS_RANDOM_SIZE);
00145   MHD_gnutls_hash (td_sha, params->data, params->size);
00146 
00147   switch (cert->subject_pk_algorithm)
00148     {
00149     case MHD_GNUTLS_PK_RSA:
00150       if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
00151         {
00152           mac_hd_t td_md5 = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
00153           if (td_md5 == NULL)
00154             {
00155               MHD_gnutls_assert ();
00156               return GNUTLS_E_HASH_FAILED;
00157             }
00158 
00159           MHD_gnutls_hash (td_md5, session->security_parameters.client_random,
00160                            TLS_RANDOM_SIZE);
00161           MHD_gnutls_hash (td_md5, session->security_parameters.server_random,
00162                            TLS_RANDOM_SIZE);
00163           MHD_gnutls_hash (td_md5, params->data, params->size);
00164 
00165           MHD_gnutls_hash_deinit (td_md5, concat);
00166           MHD_gnutls_hash_deinit (td_sha, &concat[16]);
00167 
00168           dconcat.size = 36;
00169         }
00170       else
00171         {
00172 #if 1
00173           /* Use NULL parameters. */
00174           memcpy (concat,
00175                   "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
00176                   15);
00177           MHD_gnutls_hash_deinit (td_sha, &concat[15]);
00178           dconcat.size = 35;
00179 #else
00180           /* No parameters field. */
00181           memcpy (concat,
00182                   "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
00183           MHD_gnutls_hash_deinit (td_sha, &concat[13]);
00184           dconcat.size = 33;
00185 #endif
00186         }
00187       dconcat.data = concat;
00188       break;
00189     default:
00190       MHD_gnutls_assert ();
00191       MHD_gnutls_hash_deinit (td_sha, NULL);
00192       return GNUTLS_E_INTERNAL_ERROR;
00193     }
00194   ret = MHD__gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
00195   if (ret < 0)
00196     {
00197       MHD_gnutls_assert ();
00198     }
00199 
00200   return ret;
00201 
00202 }
00203 
00204 /* This will create a PKCS1 or DSA signature, using the given parameters, and the
00205  * given data. The output will be allocated and be put in signature.
00206  */
00207 static int
00208 MHD_gtls_sign (enum MHD_GNUTLS_PublicKeyAlgorithm algo,
00209                mpi_t * params,
00210                int params_size,
00211                const MHD_gnutls_datum_t * data,
00212                MHD_gnutls_datum_t * signature)
00213 {
00214   int ret;
00215 
00216   switch (algo)
00217     {
00218     case MHD_GNUTLS_PK_RSA:
00219       /* encrypt */
00220       if ((ret =
00221            MHD_gtls_pkcs1_rsa_encrypt (signature, data, params, params_size,
00222                                        1)) < 0)
00223         {
00224           MHD_gnutls_assert ();
00225           return ret;
00226         }
00227 
00228       break;
00229     default:
00230       MHD_gnutls_assert ();
00231       return GNUTLS_E_INTERNAL_ERROR;
00232       break;
00233     }
00234 
00235   return 0;
00236 }
00237 
00238 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
00239  * Cert is the certificate of the corresponding private key. It is only checked if
00240  * it supports signing.
00241  */
00242 static int
00243 MHD__gnutls_tls_sign (MHD_gtls_session_t session,
00244                       MHD_gnutls_cert * cert,
00245                       MHD_gnutls_privkey * pkey,
00246                       const MHD_gnutls_datum_t * hash_concat,
00247                       MHD_gnutls_datum_t * signature)
00248 {
00249 
00250   /* If our certificate supports signing
00251    */
00252 
00253   if (cert != NULL)
00254     if (cert->key_usage != 0)
00255       if (!(cert->key_usage & KEY_DIGITAL_SIGNATURE))
00256         {
00257           MHD_gnutls_assert ();
00258           return GNUTLS_E_KEY_USAGE_VIOLATION;
00259         }
00260 
00261   /* External signing. */
00262   if (!pkey || pkey->params_size == 0)
00263     {
00264       if (!session->internals.sign_func)
00265         return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00266 
00267       return (*session->internals.sign_func) (session,
00268                                               session->internals.
00269                                               sign_func_userdata,
00270                                               cert->cert_type, &cert->raw,
00271                                               hash_concat, signature);
00272     }
00273 
00274   return MHD_gtls_sign (pkey->pk_algorithm, pkey->params, pkey->params_size,
00275                         hash_concat, signature);
00276 }
00277 
00278 static int
00279 MHD__gnutls_verify_sig (MHD_gnutls_cert * cert,
00280                         const MHD_gnutls_datum_t * hash_concat,
00281                         MHD_gnutls_datum_t * signature, size_t sha1pos)
00282 {
00283   int ret;
00284   MHD_gnutls_datum_t vdata;
00285 
00286   if ((cert == NULL) || (cert->version == 0))
00287     {                           /* this is the only way to check
00288                                  * if it is initialized
00289                                  */
00290       MHD_gnutls_assert ();
00291       return GNUTLS_E_CERTIFICATE_ERROR;
00292     }
00293 
00294   /* If the certificate supports signing continue.
00295    */
00296   if (cert != NULL)
00297     if (cert->key_usage != 0)
00298       if (!(cert->key_usage & KEY_DIGITAL_SIGNATURE))
00299         {
00300           MHD_gnutls_assert ();
00301           return GNUTLS_E_KEY_USAGE_VIOLATION;
00302         }
00303 
00304   switch (cert->subject_pk_algorithm)
00305     {
00306     case MHD_GNUTLS_PK_RSA:
00307 
00308       vdata.data = hash_concat->data;
00309       vdata.size = hash_concat->size;
00310 
00311       /* verify signature */
00312       if ((ret = MHD_gtls_rsa_verify (&vdata, signature, cert->params,
00313                                       cert->params_size, 1)) < 0)
00314         {
00315           MHD_gnutls_assert ();
00316           return ret;
00317         }
00318 
00319       break;
00320     default:
00321       MHD_gnutls_assert ();
00322       return GNUTLS_E_INTERNAL_ERROR;
00323     }
00324 
00325   return 0;
00326 }
00327 
00328 /* Verifies a TLS signature (like the one in the client certificate
00329  * verify message).
00330  */
00331 int
00332 MHD_gtls_verify_sig_hdata (MHD_gtls_session_t session,
00333                            MHD_gnutls_cert * cert,
00334                            MHD_gnutls_datum_t * signature)
00335 {
00336   int ret;
00337   opaque concat[36];
00338   mac_hd_t td_md5;
00339   mac_hd_t td_sha;
00340   MHD_gnutls_datum_t dconcat;
00341   enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
00342 
00343   td_md5 = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
00344   if (td_md5 == NULL)
00345     {
00346       MHD_gnutls_assert ();
00347       return GNUTLS_E_HASH_FAILED;
00348     }
00349 
00350   td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
00351   if (td_sha == NULL)
00352     {
00353       MHD_gnutls_assert ();
00354       MHD_gnutls_hash_deinit (td_md5, NULL);
00355       return GNUTLS_E_HASH_FAILED;
00356     }
00357 
00358   if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
00359     {
00360       ret = MHD_gtls_generate_master (session, 1);
00361       if (ret < 0)
00362         {
00363           MHD_gnutls_assert ();
00364           return ret;
00365         }
00366 
00367       MHD_gnutls_mac_deinit_ssl3_handshake (td_md5, concat,
00368                                             session->security_parameters.
00369                                             master_secret, TLS_MASTER_SIZE);
00370       MHD_gnutls_mac_deinit_ssl3_handshake (td_sha, &concat[16],
00371                                             session->security_parameters.
00372                                             master_secret, TLS_MASTER_SIZE);
00373     }
00374   else
00375     {
00376       MHD_gnutls_hash_deinit (td_md5, concat);
00377       MHD_gnutls_hash_deinit (td_sha, &concat[16]);
00378     }
00379 
00380   dconcat.data = concat;
00381   dconcat.size = 20 + 16;       /* md5+ sha */
00382 
00383   ret = MHD__gnutls_verify_sig (cert, &dconcat, signature, 16);
00384   if (ret < 0)
00385     {
00386       MHD_gnutls_assert ();
00387       return ret;
00388     }
00389 
00390   return ret;
00391 
00392 }
00393 
00394 /* Generates a signature of all the random data and the parameters.
00395  * Used in DHE_* ciphersuites.
00396  */
00397 int
00398 MHD_gtls_verify_sig_params (MHD_gtls_session_t session,
00399                             MHD_gnutls_cert * cert,
00400                             const MHD_gnutls_datum_t * params,
00401                             MHD_gnutls_datum_t * signature)
00402 {
00403   MHD_gnutls_datum_t dconcat;
00404   int ret;
00405   mac_hd_t td_md5 = NULL;
00406   mac_hd_t td_sha;
00407   opaque concat[36];
00408   enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
00409 
00410   if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
00411     {
00412       td_md5 = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
00413       if (td_md5 == NULL)
00414         {
00415           MHD_gnutls_assert ();
00416           return GNUTLS_E_HASH_FAILED;
00417         }
00418 
00419       MHD_gnutls_hash (td_md5, session->security_parameters.client_random,
00420                        TLS_RANDOM_SIZE);
00421       MHD_gnutls_hash (td_md5, session->security_parameters.server_random,
00422                        TLS_RANDOM_SIZE);
00423       MHD_gnutls_hash (td_md5, params->data, params->size);
00424     }
00425 
00426   td_sha = MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
00427   if (td_sha == NULL)
00428     {
00429       MHD_gnutls_assert ();
00430       if (td_md5)
00431         MHD_gnutls_hash_deinit (td_md5, NULL);
00432       return GNUTLS_E_HASH_FAILED;
00433     }
00434 
00435   MHD_gnutls_hash (td_sha, session->security_parameters.client_random,
00436                    TLS_RANDOM_SIZE);
00437   MHD_gnutls_hash (td_sha, session->security_parameters.server_random,
00438                    TLS_RANDOM_SIZE);
00439   MHD_gnutls_hash (td_sha, params->data, params->size);
00440 
00441   if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
00442     {
00443       MHD_gnutls_hash_deinit (td_md5, concat);
00444       MHD_gnutls_hash_deinit (td_sha, &concat[16]);
00445       dconcat.size = 36;
00446     }
00447   else
00448     {
00449 #if 1
00450       /* Use NULL parameters. */
00451       memcpy (concat,
00452               "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
00453               15);
00454       MHD_gnutls_hash_deinit (td_sha, &concat[15]);
00455       dconcat.size = 35;
00456 #else
00457       /* No parameters field. */
00458       memcpy (concat,
00459               "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
00460       MHD_gnutls_hash_deinit (td_sha, &concat[13]);
00461       dconcat.size = 33;
00462 #endif
00463     }
00464 
00465   dconcat.data = concat;
00466 
00467   ret = MHD__gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
00468   if (ret < 0)
00469     {
00470       MHD_gnutls_assert ();
00471       return ret;
00472     }
00473 
00474   return ret;
00475 
00476 }

Generated by  doxygen 1.6.2