$search
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 }