crypto_internal.c revision 252726
1189251Ssam/* 2214734Srpaulo * Crypto wrapper for internal crypto implementation 3252726Srpaulo * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12189251Ssam#include "crypto.h" 13252726Srpaulo#include "sha256_i.h" 14214734Srpaulo#include "sha1_i.h" 15214734Srpaulo#include "md5_i.h" 16189251Ssam 17189251Ssamstruct crypto_hash { 18189251Ssam enum crypto_hash_alg alg; 19189251Ssam union { 20189251Ssam struct MD5Context md5; 21189251Ssam struct SHA1Context sha1; 22252726Srpaulo#ifdef CONFIG_SHA256 23252726Srpaulo struct sha256_state sha256; 24252726Srpaulo#endif /* CONFIG_SHA256 */ 25189251Ssam } u; 26189251Ssam u8 key[64]; 27189251Ssam size_t key_len; 28189251Ssam}; 29189251Ssam 30189251Ssam 31189251Ssamstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 32189251Ssam size_t key_len) 33189251Ssam{ 34189251Ssam struct crypto_hash *ctx; 35189251Ssam u8 k_pad[64]; 36252726Srpaulo u8 tk[32]; 37189251Ssam size_t i; 38189251Ssam 39189251Ssam ctx = os_zalloc(sizeof(*ctx)); 40189251Ssam if (ctx == NULL) 41189251Ssam return NULL; 42189251Ssam 43189251Ssam ctx->alg = alg; 44189251Ssam 45189251Ssam switch (alg) { 46189251Ssam case CRYPTO_HASH_ALG_MD5: 47189251Ssam MD5Init(&ctx->u.md5); 48189251Ssam break; 49189251Ssam case CRYPTO_HASH_ALG_SHA1: 50189251Ssam SHA1Init(&ctx->u.sha1); 51189251Ssam break; 52252726Srpaulo#ifdef CONFIG_SHA256 53252726Srpaulo case CRYPTO_HASH_ALG_SHA256: 54252726Srpaulo sha256_init(&ctx->u.sha256); 55252726Srpaulo break; 56252726Srpaulo#endif /* CONFIG_SHA256 */ 57189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 58189251Ssam if (key_len > sizeof(k_pad)) { 59189251Ssam MD5Init(&ctx->u.md5); 60189251Ssam MD5Update(&ctx->u.md5, key, key_len); 61189251Ssam MD5Final(tk, &ctx->u.md5); 62189251Ssam key = tk; 63189251Ssam key_len = 16; 64189251Ssam } 65189251Ssam os_memcpy(ctx->key, key, key_len); 66189251Ssam ctx->key_len = key_len; 67189251Ssam 68189251Ssam os_memcpy(k_pad, key, key_len); 69252726Srpaulo if (key_len < sizeof(k_pad)) 70252726Srpaulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 71189251Ssam for (i = 0; i < sizeof(k_pad); i++) 72189251Ssam k_pad[i] ^= 0x36; 73189251Ssam MD5Init(&ctx->u.md5); 74189251Ssam MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 75189251Ssam break; 76189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 77189251Ssam if (key_len > sizeof(k_pad)) { 78189251Ssam SHA1Init(&ctx->u.sha1); 79189251Ssam SHA1Update(&ctx->u.sha1, key, key_len); 80189251Ssam SHA1Final(tk, &ctx->u.sha1); 81189251Ssam key = tk; 82189251Ssam key_len = 20; 83189251Ssam } 84189251Ssam os_memcpy(ctx->key, key, key_len); 85189251Ssam ctx->key_len = key_len; 86189251Ssam 87189251Ssam os_memcpy(k_pad, key, key_len); 88252726Srpaulo if (key_len < sizeof(k_pad)) 89252726Srpaulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 90189251Ssam for (i = 0; i < sizeof(k_pad); i++) 91189251Ssam k_pad[i] ^= 0x36; 92189251Ssam SHA1Init(&ctx->u.sha1); 93189251Ssam SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 94189251Ssam break; 95252726Srpaulo#ifdef CONFIG_SHA256 96252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 97252726Srpaulo if (key_len > sizeof(k_pad)) { 98252726Srpaulo sha256_init(&ctx->u.sha256); 99252726Srpaulo sha256_process(&ctx->u.sha256, key, key_len); 100252726Srpaulo sha256_done(&ctx->u.sha256, tk); 101252726Srpaulo key = tk; 102252726Srpaulo key_len = 32; 103252726Srpaulo } 104252726Srpaulo os_memcpy(ctx->key, key, key_len); 105252726Srpaulo ctx->key_len = key_len; 106252726Srpaulo 107252726Srpaulo os_memcpy(k_pad, key, key_len); 108252726Srpaulo if (key_len < sizeof(k_pad)) 109252726Srpaulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 110252726Srpaulo for (i = 0; i < sizeof(k_pad); i++) 111252726Srpaulo k_pad[i] ^= 0x36; 112252726Srpaulo sha256_init(&ctx->u.sha256); 113252726Srpaulo sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 114252726Srpaulo break; 115252726Srpaulo#endif /* CONFIG_SHA256 */ 116189251Ssam default: 117189251Ssam os_free(ctx); 118189251Ssam return NULL; 119189251Ssam } 120189251Ssam 121189251Ssam return ctx; 122189251Ssam} 123189251Ssam 124189251Ssam 125189251Ssamvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 126189251Ssam{ 127189251Ssam if (ctx == NULL) 128189251Ssam return; 129189251Ssam 130189251Ssam switch (ctx->alg) { 131189251Ssam case CRYPTO_HASH_ALG_MD5: 132189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 133189251Ssam MD5Update(&ctx->u.md5, data, len); 134189251Ssam break; 135189251Ssam case CRYPTO_HASH_ALG_SHA1: 136189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 137189251Ssam SHA1Update(&ctx->u.sha1, data, len); 138189251Ssam break; 139252726Srpaulo#ifdef CONFIG_SHA256 140252726Srpaulo case CRYPTO_HASH_ALG_SHA256: 141252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 142252726Srpaulo sha256_process(&ctx->u.sha256, data, len); 143252726Srpaulo break; 144252726Srpaulo#endif /* CONFIG_SHA256 */ 145252726Srpaulo default: 146252726Srpaulo break; 147189251Ssam } 148189251Ssam} 149189251Ssam 150189251Ssam 151189251Ssamint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 152189251Ssam{ 153189251Ssam u8 k_pad[64]; 154189251Ssam size_t i; 155189251Ssam 156189251Ssam if (ctx == NULL) 157189251Ssam return -2; 158189251Ssam 159189251Ssam if (mac == NULL || len == NULL) { 160189251Ssam os_free(ctx); 161189251Ssam return 0; 162189251Ssam } 163189251Ssam 164189251Ssam switch (ctx->alg) { 165189251Ssam case CRYPTO_HASH_ALG_MD5: 166189251Ssam if (*len < 16) { 167189251Ssam *len = 16; 168189251Ssam os_free(ctx); 169189251Ssam return -1; 170189251Ssam } 171189251Ssam *len = 16; 172189251Ssam MD5Final(mac, &ctx->u.md5); 173189251Ssam break; 174189251Ssam case CRYPTO_HASH_ALG_SHA1: 175189251Ssam if (*len < 20) { 176189251Ssam *len = 20; 177189251Ssam os_free(ctx); 178189251Ssam return -1; 179189251Ssam } 180189251Ssam *len = 20; 181189251Ssam SHA1Final(mac, &ctx->u.sha1); 182189251Ssam break; 183252726Srpaulo#ifdef CONFIG_SHA256 184252726Srpaulo case CRYPTO_HASH_ALG_SHA256: 185252726Srpaulo if (*len < 32) { 186252726Srpaulo *len = 32; 187252726Srpaulo os_free(ctx); 188252726Srpaulo return -1; 189252726Srpaulo } 190252726Srpaulo *len = 32; 191252726Srpaulo sha256_done(&ctx->u.sha256, mac); 192252726Srpaulo break; 193252726Srpaulo#endif /* CONFIG_SHA256 */ 194189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 195189251Ssam if (*len < 16) { 196189251Ssam *len = 16; 197189251Ssam os_free(ctx); 198189251Ssam return -1; 199189251Ssam } 200189251Ssam *len = 16; 201189251Ssam 202189251Ssam MD5Final(mac, &ctx->u.md5); 203189251Ssam 204189251Ssam os_memcpy(k_pad, ctx->key, ctx->key_len); 205189251Ssam os_memset(k_pad + ctx->key_len, 0, 206189251Ssam sizeof(k_pad) - ctx->key_len); 207189251Ssam for (i = 0; i < sizeof(k_pad); i++) 208189251Ssam k_pad[i] ^= 0x5c; 209189251Ssam MD5Init(&ctx->u.md5); 210189251Ssam MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 211189251Ssam MD5Update(&ctx->u.md5, mac, 16); 212189251Ssam MD5Final(mac, &ctx->u.md5); 213189251Ssam break; 214189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 215189251Ssam if (*len < 20) { 216189251Ssam *len = 20; 217189251Ssam os_free(ctx); 218189251Ssam return -1; 219189251Ssam } 220189251Ssam *len = 20; 221189251Ssam 222189251Ssam SHA1Final(mac, &ctx->u.sha1); 223189251Ssam 224189251Ssam os_memcpy(k_pad, ctx->key, ctx->key_len); 225189251Ssam os_memset(k_pad + ctx->key_len, 0, 226189251Ssam sizeof(k_pad) - ctx->key_len); 227189251Ssam for (i = 0; i < sizeof(k_pad); i++) 228189251Ssam k_pad[i] ^= 0x5c; 229189251Ssam SHA1Init(&ctx->u.sha1); 230189251Ssam SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 231189251Ssam SHA1Update(&ctx->u.sha1, mac, 20); 232189251Ssam SHA1Final(mac, &ctx->u.sha1); 233189251Ssam break; 234252726Srpaulo#ifdef CONFIG_SHA256 235252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 236252726Srpaulo if (*len < 32) { 237252726Srpaulo *len = 32; 238252726Srpaulo os_free(ctx); 239252726Srpaulo return -1; 240252726Srpaulo } 241252726Srpaulo *len = 32; 242252726Srpaulo 243252726Srpaulo sha256_done(&ctx->u.sha256, mac); 244252726Srpaulo 245252726Srpaulo os_memcpy(k_pad, ctx->key, ctx->key_len); 246252726Srpaulo os_memset(k_pad + ctx->key_len, 0, 247252726Srpaulo sizeof(k_pad) - ctx->key_len); 248252726Srpaulo for (i = 0; i < sizeof(k_pad); i++) 249252726Srpaulo k_pad[i] ^= 0x5c; 250252726Srpaulo sha256_init(&ctx->u.sha256); 251252726Srpaulo sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 252252726Srpaulo sha256_process(&ctx->u.sha256, mac, 32); 253252726Srpaulo sha256_done(&ctx->u.sha256, mac); 254252726Srpaulo break; 255252726Srpaulo#endif /* CONFIG_SHA256 */ 256252726Srpaulo default: 257252726Srpaulo os_free(ctx); 258252726Srpaulo return -1; 259189251Ssam } 260189251Ssam 261189251Ssam os_free(ctx); 262189251Ssam 263189251Ssam return 0; 264189251Ssam} 265189251Ssam 266189251Ssam 267189251Ssamint crypto_global_init(void) 268189251Ssam{ 269189251Ssam return 0; 270189251Ssam} 271189251Ssam 272189251Ssam 273189251Ssamvoid crypto_global_deinit(void) 274189251Ssam{ 275189251Ssam} 276