gnutls_hash_int.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000, 2001, 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 handles all the internal functions that cope with hashes
00026  * and HMACs.
00027  */
00028 
00029 #include <gnutls_int.h>
00030 #include <gnutls_hash_int.h>
00031 #include <gnutls_errors.h>
00032 
00033 static inline Gc_hash
00034 MHD__gnutls_mac2gc (enum MHD_GNUTLS_HashAlgorithm mac)
00035 {
00036   switch (mac)
00037     {
00038     case MHD_GNUTLS_MAC_NULL:
00039       return -1;
00040       break;
00041     case MHD_GNUTLS_MAC_SHA1:
00042       return GC_SHA1;
00043       break;
00044     case MHD_GNUTLS_MAC_SHA256:
00045       return GC_SHA256;
00046       break;
00047     case MHD_GNUTLS_MAC_MD5:
00048       return GC_MD5;
00049       break;
00050     default:
00051       MHD_gnutls_assert ();
00052       return -1;
00053     }
00054   return -1;
00055 }
00056 
00057 GNUTLS_HASH_HANDLE
00058 MHD_gtls_hash_init (enum MHD_GNUTLS_HashAlgorithm algorithm)
00059 {
00060   mac_hd_t ret;
00061   int result;
00062 
00063   ret = MHD_gnutls_malloc (sizeof (mac_hd_st));
00064   if (ret == NULL)
00065     {
00066       MHD_gnutls_assert ();
00067       return GNUTLS_HASH_FAILED;
00068     }
00069 
00070   ret->algorithm = algorithm;
00071 
00072   result = MHD_gc_hash_open (MHD__gnutls_mac2gc (algorithm), 0, &ret->handle);
00073   if (result)
00074     {
00075       MHD_gnutls_assert ();
00076       MHD_gnutls_free (ret);
00077       ret = GNUTLS_HASH_FAILED;
00078     }
00079 
00080   return ret;
00081 }
00082 
00083 int
00084 MHD_gnutls_hash_get_algo_len (enum MHD_GNUTLS_HashAlgorithm algorithm)
00085 {
00086   int ret;
00087 
00088   ret = MHD_gc_hash_digest_length (MHD__gnutls_mac2gc (algorithm));
00089 
00090   return ret;
00091 
00092 }
00093 
00094 int
00095 MHD_gnutls_hash (GNUTLS_HASH_HANDLE handle, const void *text, size_t textlen)
00096 {
00097   if (textlen > 0)
00098     MHD_gc_hash_write (handle->handle, textlen, text);
00099   return 0;
00100 }
00101 
00102 GNUTLS_HASH_HANDLE
00103 MHD_gnutls_hash_copy (GNUTLS_HASH_HANDLE handle)
00104 {
00105   GNUTLS_HASH_HANDLE ret;
00106   int result;
00107 
00108   ret = MHD_gnutls_malloc (sizeof (mac_hd_st));
00109 
00110   if (ret == NULL)
00111     return GNUTLS_HASH_FAILED;
00112 
00113   ret->algorithm = handle->algorithm;
00114   ret->key = NULL;              /* it's a hash anyway */
00115   ret->keysize = 0;
00116 
00117   result = MHD_gc_hash_clone (handle->handle, &ret->handle);
00118 
00119   if (result)
00120     {
00121       MHD_gnutls_free (ret);
00122       return GNUTLS_HASH_FAILED;
00123     }
00124 
00125   return ret;
00126 }
00127 
00128 void
00129 MHD_gnutls_hash_deinit (GNUTLS_HASH_HANDLE handle, void *digest)
00130 {
00131   const opaque *mac;
00132   int maclen;
00133 
00134   maclen = MHD_gnutls_hash_get_algo_len (handle->algorithm);
00135 
00136   mac = (unsigned char *) MHD_gc_hash_read (handle->handle);
00137   if (digest != NULL)
00138     memcpy (digest, mac, maclen);
00139 
00140   MHD_gc_hash_close (handle->handle);
00141 
00142   MHD_gnutls_free (handle);
00143 }
00144 
00145 
00146 mac_hd_t
00147 MHD_gtls_MHD_hmac_init (enum MHD_GNUTLS_HashAlgorithm algorithm,
00148                         const void *key, int keylen)
00149 {
00150   mac_hd_t ret;
00151   int result;
00152 
00153   ret = MHD_gnutls_malloc (sizeof (mac_hd_st));
00154   if (ret == NULL)
00155     return GNUTLS_MAC_FAILED;
00156 
00157   result =
00158     MHD_gc_hash_open (MHD__gnutls_mac2gc (algorithm), GC_HMAC, &ret->handle);
00159   if (result)
00160     {
00161       MHD_gnutls_free (ret);
00162       return GNUTLS_MAC_FAILED;
00163     }
00164 
00165   MHD_gc_hash_MHD_hmac_setkey (ret->handle, keylen, key);
00166 
00167   ret->algorithm = algorithm;
00168   ret->key = key;
00169   ret->keysize = keylen;
00170 
00171   return ret;
00172 }
00173 
00174 void
00175 MHD_gnutls_MHD_hmac_deinit (mac_hd_t handle, void *digest)
00176 {
00177   const opaque *mac;
00178   int maclen;
00179 
00180   maclen = MHD_gnutls_hash_get_algo_len (handle->algorithm);
00181 
00182   mac = (unsigned char *) MHD_gc_hash_read (handle->handle);
00183 
00184   if (digest != NULL)
00185     memcpy (digest, mac, maclen);
00186 
00187   MHD_gc_hash_close (handle->handle);
00188 
00189   MHD_gnutls_free (handle);
00190 }
00191 
00192 inline static int
00193 get_padsize (enum MHD_GNUTLS_HashAlgorithm algorithm)
00194 {
00195   switch (algorithm)
00196     {
00197     case MHD_GNUTLS_MAC_MD5:
00198       return 48;
00199     case MHD_GNUTLS_MAC_SHA1:
00200       return 40;
00201     default:
00202       return 0;
00203     }
00204 }
00205 
00206 mac_hd_t
00207 MHD_gnutls_mac_init_ssl3 (enum MHD_GNUTLS_HashAlgorithm algorithm, void *key,
00208                           int keylen)
00209 {
00210   mac_hd_t ret;
00211   opaque ipad[48];
00212   int padsize;
00213 
00214   padsize = get_padsize (algorithm);
00215   if (padsize == 0)
00216     {
00217       MHD_gnutls_assert ();
00218       return GNUTLS_MAC_FAILED;
00219     }
00220 
00221   memset (ipad, 0x36, padsize);
00222 
00223   ret = MHD_gtls_hash_init (algorithm);
00224   if (ret != GNUTLS_HASH_FAILED)
00225     {
00226       ret->key = key;
00227       ret->keysize = keylen;
00228 
00229       if (keylen > 0)
00230         MHD_gnutls_hash (ret, key, keylen);
00231       MHD_gnutls_hash (ret, ipad, padsize);
00232     }
00233 
00234   return ret;
00235 }
00236 
00237 void
00238 MHD_gnutls_mac_deinit_ssl3 (mac_hd_t handle, void *digest)
00239 {
00240   opaque ret[MAX_HASH_SIZE];
00241   mac_hd_t td;
00242   opaque opad[48];
00243   int padsize;
00244   int block;
00245 
00246   padsize = get_padsize (handle->algorithm);
00247   if (padsize == 0)
00248     {
00249       MHD_gnutls_assert ();
00250       return;
00251     }
00252 
00253   memset (opad, 0x5C, padsize);
00254 
00255   td = MHD_gtls_hash_init (handle->algorithm);
00256   if (td != GNUTLS_MAC_FAILED)
00257     {
00258       if (handle->keysize > 0)
00259         MHD_gnutls_hash (td, handle->key, handle->keysize);
00260 
00261       MHD_gnutls_hash (td, opad, padsize);
00262       block = MHD_gnutls_hash_get_algo_len (handle->algorithm);
00263       MHD_gnutls_hash_deinit (handle, ret);     /* get the previous hash */
00264       MHD_gnutls_hash (td, ret, block);
00265 
00266       MHD_gnutls_hash_deinit (td, digest);
00267     }
00268 }
00269 
00270 void
00271 MHD_gnutls_mac_deinit_ssl3_handshake (mac_hd_t handle,
00272                                       void *digest, opaque * key,
00273                                       uint32_t key_size)
00274 {
00275   opaque ret[MAX_HASH_SIZE];
00276   mac_hd_t td;
00277   opaque opad[48];
00278   opaque ipad[48];
00279   int padsize;
00280   int block;
00281 
00282   padsize = get_padsize (handle->algorithm);
00283   if (padsize == 0)
00284     {
00285       MHD_gnutls_assert ();
00286       return;
00287     }
00288 
00289   memset (opad, 0x5C, padsize);
00290   memset (ipad, 0x36, padsize);
00291 
00292   td = MHD_gtls_hash_init (handle->algorithm);
00293   if (td != GNUTLS_HASH_FAILED)
00294     {
00295       if (key_size > 0)
00296         MHD_gnutls_hash (td, key, key_size);
00297 
00298       MHD_gnutls_hash (td, opad, padsize);
00299       block = MHD_gnutls_hash_get_algo_len (handle->algorithm);
00300 
00301       if (key_size > 0)
00302         MHD_gnutls_hash (handle, key, key_size);
00303       MHD_gnutls_hash (handle, ipad, padsize);
00304       MHD_gnutls_hash_deinit (handle, ret);     /* get the previous hash */
00305 
00306       MHD_gnutls_hash (td, ret, block);
00307 
00308       MHD_gnutls_hash_deinit (td, digest);
00309     }
00310 }
00311 
00312 static int
00313 ssl3_sha (int i, opaque * secret, int secret_len,
00314           opaque * rnd, int rnd_len, void *digest)
00315 {
00316   int j;
00317   opaque text1[26];
00318 
00319   GNUTLS_HASH_HANDLE td;
00320 
00321   for (j = 0; j < i + 1; j++)
00322     {
00323       text1[j] = 65 + i;        /* A==65 */
00324     }
00325 
00326   td = MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
00327   if (td == NULL)
00328     {
00329       MHD_gnutls_assert ();
00330       return GNUTLS_E_HASH_FAILED;
00331     }
00332 
00333   MHD_gnutls_hash (td, text1, i + 1);
00334   MHD_gnutls_hash (td, secret, secret_len);
00335   MHD_gnutls_hash (td, rnd, rnd_len);
00336 
00337   MHD_gnutls_hash_deinit (td, digest);
00338   return 0;
00339 }
00340 
00341 static int
00342 ssl3_md5 (int i, opaque * secret, int secret_len,
00343           opaque * rnd, int rnd_len, void *digest)
00344 {
00345   opaque tmp[MAX_HASH_SIZE];
00346   mac_hd_t td;
00347   int ret;
00348 
00349   td = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
00350   if (td == NULL)
00351     {
00352       MHD_gnutls_assert ();
00353       return GNUTLS_E_HASH_FAILED;
00354     }
00355 
00356   MHD_gnutls_hash (td, secret, secret_len);
00357 
00358   ret = ssl3_sha (i, secret, secret_len, rnd, rnd_len, tmp);
00359   if (ret < 0)
00360     {
00361       MHD_gnutls_assert ();
00362       MHD_gnutls_hash_deinit (td, digest);
00363       return ret;
00364     }
00365 
00366   MHD_gnutls_hash (td, tmp,
00367                    MHD_gnutls_hash_get_algo_len (MHD_GNUTLS_MAC_SHA1));
00368 
00369   MHD_gnutls_hash_deinit (td, digest);
00370   return 0;
00371 }
00372 
00373 int
00374 MHD_gnutls_ssl3_hash_md5 (void *first, int first_len,
00375                           void *second, int second_len, int ret_len,
00376                           opaque * ret)
00377 {
00378   opaque digest[MAX_HASH_SIZE];
00379   mac_hd_t td;
00380   int block = MHD_gnutls_hash_get_algo_len (MHD_GNUTLS_MAC_MD5);
00381 
00382   td = MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
00383   if (td == NULL)
00384     {
00385       MHD_gnutls_assert ();
00386       return GNUTLS_E_HASH_FAILED;
00387     }
00388 
00389   MHD_gnutls_hash (td, first, first_len);
00390   MHD_gnutls_hash (td, second, second_len);
00391 
00392   MHD_gnutls_hash_deinit (td, digest);
00393 
00394   if (ret_len > block)
00395     {
00396       MHD_gnutls_assert ();
00397       return GNUTLS_E_INTERNAL_ERROR;
00398     }
00399 
00400   memcpy (ret, digest, ret_len);
00401 
00402   return 0;
00403 
00404 }
00405 
00406 int
00407 MHD_gnutls_ssl3_generate_random (void *secret, int secret_len,
00408                                  void *rnd, int rnd_len,
00409                                  int ret_bytes, opaque * ret)
00410 {
00411   int i = 0, copy, output_bytes;
00412   opaque digest[MAX_HASH_SIZE];
00413   int block = MHD_gnutls_hash_get_algo_len (MHD_GNUTLS_MAC_MD5);
00414   int result, times;
00415 
00416   output_bytes = 0;
00417   do
00418     {
00419       output_bytes += block;
00420     }
00421   while (output_bytes < ret_bytes);
00422 
00423   times = output_bytes / block;
00424 
00425   for (i = 0; i < times; i++)
00426     {
00427 
00428       result = ssl3_md5 (i, secret, secret_len, rnd, rnd_len, digest);
00429       if (result < 0)
00430         {
00431           MHD_gnutls_assert ();
00432           return result;
00433         }
00434 
00435       if ((1 + i) * block < ret_bytes)
00436         {
00437           copy = block;
00438         }
00439       else
00440         {
00441           copy = ret_bytes - (i) * block;
00442         }
00443 
00444       memcpy (&ret[i * block], digest, copy);
00445     }
00446 
00447   return 0;
00448 }

Generated on Tue May 19 23:21:08 2009 for GNU libmicrohttpd by  doxygen 1.5.8