crypto_internal.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
1/* 2 * Crypto wrapper for internal crypto implementation 3 * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#include "common.h" 18#include "crypto.h" 19#include "sha256_i.h" 20#include "sha1_i.h" 21#include "md5_i.h" 22 23struct crypto_hash { 24 enum crypto_hash_alg alg; 25 union { 26 struct MD5Context md5; 27 struct SHA1Context sha1; 28#ifdef CONFIG_SHA256 29 struct sha256_state sha256; 30#endif /* CONFIG_SHA256 */ 31 } u; 32 u8 key[64]; 33 size_t key_len; 34}; 35 36 37struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 38 size_t key_len) 39{ 40 struct crypto_hash *ctx; 41 u8 k_pad[64]; 42 u8 tk[32]; 43 size_t i; 44 45 ctx = os_zalloc(sizeof(*ctx)); 46 if (ctx == NULL) 47 return NULL; 48 49 ctx->alg = alg; 50 51 switch (alg) { 52 case CRYPTO_HASH_ALG_MD5: 53 MD5Init(&ctx->u.md5); 54 break; 55 case CRYPTO_HASH_ALG_SHA1: 56 SHA1Init(&ctx->u.sha1); 57 break; 58#ifdef CONFIG_SHA256 59 case CRYPTO_HASH_ALG_SHA256: 60 sha256_init(&ctx->u.sha256); 61 break; 62#endif /* CONFIG_SHA256 */ 63 case CRYPTO_HASH_ALG_HMAC_MD5: 64 if (key_len > sizeof(k_pad)) { 65 MD5Init(&ctx->u.md5); 66 MD5Update(&ctx->u.md5, key, key_len); 67 MD5Final(tk, &ctx->u.md5); 68 key = tk; 69 key_len = 16; 70 } 71 os_memcpy(ctx->key, key, key_len); 72 ctx->key_len = key_len; 73 74 os_memcpy(k_pad, key, key_len); 75 if (key_len < sizeof(k_pad)) 76 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 77 for (i = 0; i < sizeof(k_pad); i++) 78 k_pad[i] ^= 0x36; 79 MD5Init(&ctx->u.md5); 80 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 81 break; 82 case CRYPTO_HASH_ALG_HMAC_SHA1: 83 if (key_len > sizeof(k_pad)) { 84 SHA1Init(&ctx->u.sha1); 85 SHA1Update(&ctx->u.sha1, key, key_len); 86 SHA1Final(tk, &ctx->u.sha1); 87 key = tk; 88 key_len = 20; 89 } 90 os_memcpy(ctx->key, key, key_len); 91 ctx->key_len = key_len; 92 93 os_memcpy(k_pad, key, key_len); 94 if (key_len < sizeof(k_pad)) 95 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 96 for (i = 0; i < sizeof(k_pad); i++) 97 k_pad[i] ^= 0x36; 98 SHA1Init(&ctx->u.sha1); 99 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 100 break; 101#ifdef CONFIG_SHA256 102 case CRYPTO_HASH_ALG_HMAC_SHA256: 103 if (key_len > sizeof(k_pad)) { 104 sha256_init(&ctx->u.sha256); 105 sha256_process(&ctx->u.sha256, key, key_len); 106 sha256_done(&ctx->u.sha256, tk); 107 key = tk; 108 key_len = 32; 109 } 110 os_memcpy(ctx->key, key, key_len); 111 ctx->key_len = key_len; 112 113 os_memcpy(k_pad, key, key_len); 114 if (key_len < sizeof(k_pad)) 115 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 116 for (i = 0; i < sizeof(k_pad); i++) 117 k_pad[i] ^= 0x36; 118 sha256_init(&ctx->u.sha256); 119 sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 120 break; 121#endif /* CONFIG_SHA256 */ 122 default: 123 os_free(ctx); 124 return NULL; 125 } 126 127 return ctx; 128} 129 130 131void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 132{ 133 if (ctx == NULL) 134 return; 135 136 switch (ctx->alg) { 137 case CRYPTO_HASH_ALG_MD5: 138 case CRYPTO_HASH_ALG_HMAC_MD5: 139 MD5Update(&ctx->u.md5, data, len); 140 break; 141 case CRYPTO_HASH_ALG_SHA1: 142 case CRYPTO_HASH_ALG_HMAC_SHA1: 143 SHA1Update(&ctx->u.sha1, data, len); 144 break; 145#ifdef CONFIG_SHA256 146 case CRYPTO_HASH_ALG_SHA256: 147 case CRYPTO_HASH_ALG_HMAC_SHA256: 148 sha256_process(&ctx->u.sha256, data, len); 149 break; 150#endif /* CONFIG_SHA256 */ 151 default: 152 break; 153 } 154} 155 156 157int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 158{ 159 u8 k_pad[64]; 160 size_t i; 161 162 if (ctx == NULL) 163 return -2; 164 165 if (mac == NULL || len == NULL) { 166 os_free(ctx); 167 return 0; 168 } 169 170 switch (ctx->alg) { 171 case CRYPTO_HASH_ALG_MD5: 172 if (*len < 16) { 173 *len = 16; 174 os_free(ctx); 175 return -1; 176 } 177 *len = 16; 178 MD5Final(mac, &ctx->u.md5); 179 break; 180 case CRYPTO_HASH_ALG_SHA1: 181 if (*len < 20) { 182 *len = 20; 183 os_free(ctx); 184 return -1; 185 } 186 *len = 20; 187 SHA1Final(mac, &ctx->u.sha1); 188 break; 189#ifdef CONFIG_SHA256 190 case CRYPTO_HASH_ALG_SHA256: 191 if (*len < 32) { 192 *len = 32; 193 os_free(ctx); 194 return -1; 195 } 196 *len = 32; 197 sha256_done(&ctx->u.sha256, mac); 198 break; 199#endif /* CONFIG_SHA256 */ 200 case CRYPTO_HASH_ALG_HMAC_MD5: 201 if (*len < 16) { 202 *len = 16; 203 os_free(ctx); 204 return -1; 205 } 206 *len = 16; 207 208 MD5Final(mac, &ctx->u.md5); 209 210 os_memcpy(k_pad, ctx->key, ctx->key_len); 211 os_memset(k_pad + ctx->key_len, 0, 212 sizeof(k_pad) - ctx->key_len); 213 for (i = 0; i < sizeof(k_pad); i++) 214 k_pad[i] ^= 0x5c; 215 MD5Init(&ctx->u.md5); 216 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 217 MD5Update(&ctx->u.md5, mac, 16); 218 MD5Final(mac, &ctx->u.md5); 219 break; 220 case CRYPTO_HASH_ALG_HMAC_SHA1: 221 if (*len < 20) { 222 *len = 20; 223 os_free(ctx); 224 return -1; 225 } 226 *len = 20; 227 228 SHA1Final(mac, &ctx->u.sha1); 229 230 os_memcpy(k_pad, ctx->key, ctx->key_len); 231 os_memset(k_pad + ctx->key_len, 0, 232 sizeof(k_pad) - ctx->key_len); 233 for (i = 0; i < sizeof(k_pad); i++) 234 k_pad[i] ^= 0x5c; 235 SHA1Init(&ctx->u.sha1); 236 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 237 SHA1Update(&ctx->u.sha1, mac, 20); 238 SHA1Final(mac, &ctx->u.sha1); 239 break; 240#ifdef CONFIG_SHA256 241 case CRYPTO_HASH_ALG_HMAC_SHA256: 242 if (*len < 32) { 243 *len = 32; 244 os_free(ctx); 245 return -1; 246 } 247 *len = 32; 248 249 sha256_done(&ctx->u.sha256, mac); 250 251 os_memcpy(k_pad, ctx->key, ctx->key_len); 252 os_memset(k_pad + ctx->key_len, 0, 253 sizeof(k_pad) - ctx->key_len); 254 for (i = 0; i < sizeof(k_pad); i++) 255 k_pad[i] ^= 0x5c; 256 sha256_init(&ctx->u.sha256); 257 sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 258 sha256_process(&ctx->u.sha256, mac, 32); 259 sha256_done(&ctx->u.sha256, mac); 260 break; 261#endif /* CONFIG_SHA256 */ 262 default: 263 os_free(ctx); 264 return -1; 265 } 266 267 os_free(ctx); 268 269 return 0; 270} 271 272 273int crypto_global_init(void) 274{ 275 return 0; 276} 277 278 279void crypto_global_deinit(void) 280{ 281} 282