crypto_internal.c
Go to the documentation of this file.
00001 /*
00002  * Crypto wrapper for internal crypto implementation
00003  * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "crypto.h"
00019 #include "sha1_i.h"
00020 #include "md5_i.h"
00021 
00022 struct crypto_hash {
00023         enum crypto_hash_alg alg;
00024         union {
00025                 struct MD5Context md5;
00026                 struct SHA1Context sha1;
00027         } u;
00028         u8 key[64];
00029         size_t key_len;
00030 };
00031 
00032 
00033 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
00034                                       size_t key_len)
00035 {
00036         struct crypto_hash *ctx;
00037         u8 k_pad[64];
00038         u8 tk[20];
00039         size_t i;
00040 
00041         ctx = os_zalloc(sizeof(*ctx));
00042         if (ctx == NULL)
00043                 return NULL;
00044 
00045         ctx->alg = alg;
00046 
00047         switch (alg) {
00048         case CRYPTO_HASH_ALG_MD5:
00049                 MD5Init(&ctx->u.md5);
00050                 break;
00051         case CRYPTO_HASH_ALG_SHA1:
00052                 SHA1Init(&ctx->u.sha1);
00053                 break;
00054         case CRYPTO_HASH_ALG_HMAC_MD5:
00055                 if (key_len > sizeof(k_pad)) {
00056                         MD5Init(&ctx->u.md5);
00057                         MD5Update(&ctx->u.md5, key, key_len);
00058                         MD5Final(tk, &ctx->u.md5);
00059                         key = tk;
00060                         key_len = 16;
00061                 }
00062                 os_memcpy(ctx->key, key, key_len);
00063                 ctx->key_len = key_len;
00064 
00065                 os_memcpy(k_pad, key, key_len);
00066                 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
00067                 for (i = 0; i < sizeof(k_pad); i++)
00068                         k_pad[i] ^= 0x36;
00069                 MD5Init(&ctx->u.md5);
00070                 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
00071                 break;
00072         case CRYPTO_HASH_ALG_HMAC_SHA1:
00073                 if (key_len > sizeof(k_pad)) {
00074                         SHA1Init(&ctx->u.sha1);
00075                         SHA1Update(&ctx->u.sha1, key, key_len);
00076                         SHA1Final(tk, &ctx->u.sha1);
00077                         key = tk;
00078                         key_len = 20;
00079                 }
00080                 os_memcpy(ctx->key, key, key_len);
00081                 ctx->key_len = key_len;
00082 
00083                 os_memcpy(k_pad, key, key_len);
00084                 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
00085                 for (i = 0; i < sizeof(k_pad); i++)
00086                         k_pad[i] ^= 0x36;
00087                 SHA1Init(&ctx->u.sha1);
00088                 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
00089                 break;
00090         default:
00091                 os_free(ctx);
00092                 return NULL;
00093         }
00094 
00095         return ctx;
00096 }
00097 
00098 
00099 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
00100 {
00101         if (ctx == NULL)
00102                 return;
00103 
00104         switch (ctx->alg) {
00105         case CRYPTO_HASH_ALG_MD5:
00106         case CRYPTO_HASH_ALG_HMAC_MD5:
00107                 MD5Update(&ctx->u.md5, data, len);
00108                 break;
00109         case CRYPTO_HASH_ALG_SHA1:
00110         case CRYPTO_HASH_ALG_HMAC_SHA1:
00111                 SHA1Update(&ctx->u.sha1, data, len);
00112                 break;
00113         }
00114 }
00115 
00116 
00117 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
00118 {
00119         u8 k_pad[64];
00120         size_t i;
00121 
00122         if (ctx == NULL)
00123                 return -2;
00124 
00125         if (mac == NULL || len == NULL) {
00126                 os_free(ctx);
00127                 return 0;
00128         }
00129 
00130         switch (ctx->alg) {
00131         case CRYPTO_HASH_ALG_MD5:
00132                 if (*len < 16) {
00133                         *len = 16;
00134                         os_free(ctx);
00135                         return -1;
00136                 }
00137                 *len = 16;
00138                 MD5Final(mac, &ctx->u.md5);
00139                 break;
00140         case CRYPTO_HASH_ALG_SHA1:
00141                 if (*len < 20) {
00142                         *len = 20;
00143                         os_free(ctx);
00144                         return -1;
00145                 }
00146                 *len = 20;
00147                 SHA1Final(mac, &ctx->u.sha1);
00148                 break;
00149         case CRYPTO_HASH_ALG_HMAC_MD5:
00150                 if (*len < 16) {
00151                         *len = 16;
00152                         os_free(ctx);
00153                         return -1;
00154                 }
00155                 *len = 16;
00156 
00157                 MD5Final(mac, &ctx->u.md5);
00158 
00159                 os_memcpy(k_pad, ctx->key, ctx->key_len);
00160                 os_memset(k_pad + ctx->key_len, 0,
00161                           sizeof(k_pad) - ctx->key_len);
00162                 for (i = 0; i < sizeof(k_pad); i++)
00163                         k_pad[i] ^= 0x5c;
00164                 MD5Init(&ctx->u.md5);
00165                 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
00166                 MD5Update(&ctx->u.md5, mac, 16);
00167                 MD5Final(mac, &ctx->u.md5);
00168                 break;
00169         case CRYPTO_HASH_ALG_HMAC_SHA1:
00170                 if (*len < 20) {
00171                         *len = 20;
00172                         os_free(ctx);
00173                         return -1;
00174                 }
00175                 *len = 20;
00176 
00177                 SHA1Final(mac, &ctx->u.sha1);
00178 
00179                 os_memcpy(k_pad, ctx->key, ctx->key_len);
00180                 os_memset(k_pad + ctx->key_len, 0,
00181                           sizeof(k_pad) - ctx->key_len);
00182                 for (i = 0; i < sizeof(k_pad); i++)
00183                         k_pad[i] ^= 0x5c;
00184                 SHA1Init(&ctx->u.sha1);
00185                 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
00186                 SHA1Update(&ctx->u.sha1, mac, 20);
00187                 SHA1Final(mac, &ctx->u.sha1);
00188                 break;
00189         }
00190 
00191         os_free(ctx);
00192 
00193         return 0;
00194 }
00195 
00196 
00197 int crypto_global_init(void)
00198 {
00199         return 0;
00200 }
00201 
00202 
00203 void crypto_global_deinit(void)
00204 {
00205 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:36