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" 14337817Scy#include "sha384_i.h" 15337817Scy#include "sha512_i.h" 16214734Srpaulo#include "sha1_i.h" 17214734Srpaulo#include "md5_i.h" 18189251Ssam 19189251Ssamstruct crypto_hash { 20189251Ssam enum crypto_hash_alg alg; 21189251Ssam union { 22189251Ssam struct MD5Context md5; 23189251Ssam struct SHA1Context sha1; 24252726Srpaulo#ifdef CONFIG_SHA256 25252726Srpaulo struct sha256_state sha256; 26252726Srpaulo#endif /* CONFIG_SHA256 */ 27337817Scy#ifdef CONFIG_INTERNAL_SHA384 28337817Scy struct sha384_state sha384; 29337817Scy#endif /* CONFIG_INTERNAL_SHA384 */ 30337817Scy#ifdef CONFIG_INTERNAL_SHA512 31337817Scy struct sha512_state sha512; 32337817Scy#endif /* CONFIG_INTERNAL_SHA512 */ 33189251Ssam } u; 34189251Ssam u8 key[64]; 35189251Ssam size_t key_len; 36189251Ssam}; 37189251Ssam 38189251Ssam 39189251Ssamstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 40189251Ssam size_t key_len) 41189251Ssam{ 42189251Ssam struct crypto_hash *ctx; 43189251Ssam u8 k_pad[64]; 44252726Srpaulo u8 tk[32]; 45189251Ssam size_t i; 46189251Ssam 47189251Ssam ctx = os_zalloc(sizeof(*ctx)); 48189251Ssam if (ctx == NULL) 49189251Ssam return NULL; 50189251Ssam 51189251Ssam ctx->alg = alg; 52189251Ssam 53189251Ssam switch (alg) { 54189251Ssam case CRYPTO_HASH_ALG_MD5: 55189251Ssam MD5Init(&ctx->u.md5); 56189251Ssam break; 57189251Ssam case CRYPTO_HASH_ALG_SHA1: 58189251Ssam SHA1Init(&ctx->u.sha1); 59189251Ssam break; 60252726Srpaulo#ifdef CONFIG_SHA256 61252726Srpaulo case CRYPTO_HASH_ALG_SHA256: 62252726Srpaulo sha256_init(&ctx->u.sha256); 63252726Srpaulo break; 64252726Srpaulo#endif /* CONFIG_SHA256 */ 65337817Scy#ifdef CONFIG_INTERNAL_SHA384 66337817Scy case CRYPTO_HASH_ALG_SHA384: 67337817Scy sha384_init(&ctx->u.sha384); 68337817Scy break; 69337817Scy#endif /* CONFIG_INTERNAL_SHA384 */ 70337817Scy#ifdef CONFIG_INTERNAL_SHA512 71337817Scy case CRYPTO_HASH_ALG_SHA512: 72337817Scy sha512_init(&ctx->u.sha512); 73337817Scy break; 74337817Scy#endif /* CONFIG_INTERNAL_SHA512 */ 75189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 76189251Ssam if (key_len > sizeof(k_pad)) { 77189251Ssam MD5Init(&ctx->u.md5); 78189251Ssam MD5Update(&ctx->u.md5, key, key_len); 79189251Ssam MD5Final(tk, &ctx->u.md5); 80189251Ssam key = tk; 81189251Ssam key_len = 16; 82189251Ssam } 83189251Ssam os_memcpy(ctx->key, key, key_len); 84189251Ssam ctx->key_len = key_len; 85189251Ssam 86189251Ssam os_memcpy(k_pad, key, key_len); 87252726Srpaulo if (key_len < sizeof(k_pad)) 88252726Srpaulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 89189251Ssam for (i = 0; i < sizeof(k_pad); i++) 90189251Ssam k_pad[i] ^= 0x36; 91189251Ssam MD5Init(&ctx->u.md5); 92189251Ssam MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 93189251Ssam break; 94189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 95189251Ssam if (key_len > sizeof(k_pad)) { 96189251Ssam SHA1Init(&ctx->u.sha1); 97189251Ssam SHA1Update(&ctx->u.sha1, key, key_len); 98189251Ssam SHA1Final(tk, &ctx->u.sha1); 99189251Ssam key = tk; 100189251Ssam key_len = 20; 101189251Ssam } 102189251Ssam os_memcpy(ctx->key, key, key_len); 103189251Ssam ctx->key_len = key_len; 104189251Ssam 105189251Ssam os_memcpy(k_pad, key, key_len); 106252726Srpaulo if (key_len < sizeof(k_pad)) 107252726Srpaulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 108189251Ssam for (i = 0; i < sizeof(k_pad); i++) 109189251Ssam k_pad[i] ^= 0x36; 110189251Ssam SHA1Init(&ctx->u.sha1); 111189251Ssam SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 112189251Ssam break; 113252726Srpaulo#ifdef CONFIG_SHA256 114252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 115252726Srpaulo if (key_len > sizeof(k_pad)) { 116252726Srpaulo sha256_init(&ctx->u.sha256); 117252726Srpaulo sha256_process(&ctx->u.sha256, key, key_len); 118252726Srpaulo sha256_done(&ctx->u.sha256, tk); 119252726Srpaulo key = tk; 120252726Srpaulo key_len = 32; 121252726Srpaulo } 122252726Srpaulo os_memcpy(ctx->key, key, key_len); 123252726Srpaulo ctx->key_len = key_len; 124252726Srpaulo 125252726Srpaulo os_memcpy(k_pad, key, key_len); 126252726Srpaulo if (key_len < sizeof(k_pad)) 127252726Srpaulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 128252726Srpaulo for (i = 0; i < sizeof(k_pad); i++) 129252726Srpaulo k_pad[i] ^= 0x36; 130252726Srpaulo sha256_init(&ctx->u.sha256); 131252726Srpaulo sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 132252726Srpaulo break; 133252726Srpaulo#endif /* CONFIG_SHA256 */ 134189251Ssam default: 135189251Ssam os_free(ctx); 136189251Ssam return NULL; 137189251Ssam } 138189251Ssam 139189251Ssam return ctx; 140189251Ssam} 141189251Ssam 142189251Ssam 143189251Ssamvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 144189251Ssam{ 145189251Ssam if (ctx == NULL) 146189251Ssam return; 147189251Ssam 148189251Ssam switch (ctx->alg) { 149189251Ssam case CRYPTO_HASH_ALG_MD5: 150189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 151189251Ssam MD5Update(&ctx->u.md5, data, len); 152189251Ssam break; 153189251Ssam case CRYPTO_HASH_ALG_SHA1: 154189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 155189251Ssam SHA1Update(&ctx->u.sha1, data, len); 156189251Ssam break; 157252726Srpaulo#ifdef CONFIG_SHA256 158252726Srpaulo case CRYPTO_HASH_ALG_SHA256: 159252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 160252726Srpaulo sha256_process(&ctx->u.sha256, data, len); 161252726Srpaulo break; 162252726Srpaulo#endif /* CONFIG_SHA256 */ 163337817Scy#ifdef CONFIG_INTERNAL_SHA384 164337817Scy case CRYPTO_HASH_ALG_SHA384: 165337817Scy sha384_process(&ctx->u.sha384, data, len); 166337817Scy break; 167337817Scy#endif /* CONFIG_INTERNAL_SHA384 */ 168337817Scy#ifdef CONFIG_INTERNAL_SHA512 169337817Scy case CRYPTO_HASH_ALG_SHA512: 170337817Scy sha512_process(&ctx->u.sha512, data, len); 171337817Scy break; 172337817Scy#endif /* CONFIG_INTERNAL_SHA512 */ 173252726Srpaulo default: 174252726Srpaulo break; 175189251Ssam } 176189251Ssam} 177189251Ssam 178189251Ssam 179189251Ssamint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 180189251Ssam{ 181189251Ssam u8 k_pad[64]; 182189251Ssam size_t i; 183189251Ssam 184189251Ssam if (ctx == NULL) 185189251Ssam return -2; 186189251Ssam 187189251Ssam if (mac == NULL || len == NULL) { 188189251Ssam os_free(ctx); 189189251Ssam return 0; 190189251Ssam } 191189251Ssam 192189251Ssam switch (ctx->alg) { 193189251Ssam case CRYPTO_HASH_ALG_MD5: 194189251Ssam if (*len < 16) { 195189251Ssam *len = 16; 196189251Ssam os_free(ctx); 197189251Ssam return -1; 198189251Ssam } 199189251Ssam *len = 16; 200189251Ssam MD5Final(mac, &ctx->u.md5); 201189251Ssam break; 202189251Ssam case CRYPTO_HASH_ALG_SHA1: 203189251Ssam if (*len < 20) { 204189251Ssam *len = 20; 205189251Ssam os_free(ctx); 206189251Ssam return -1; 207189251Ssam } 208189251Ssam *len = 20; 209189251Ssam SHA1Final(mac, &ctx->u.sha1); 210189251Ssam break; 211252726Srpaulo#ifdef CONFIG_SHA256 212252726Srpaulo case CRYPTO_HASH_ALG_SHA256: 213252726Srpaulo if (*len < 32) { 214252726Srpaulo *len = 32; 215252726Srpaulo os_free(ctx); 216252726Srpaulo return -1; 217252726Srpaulo } 218252726Srpaulo *len = 32; 219252726Srpaulo sha256_done(&ctx->u.sha256, mac); 220252726Srpaulo break; 221252726Srpaulo#endif /* CONFIG_SHA256 */ 222337817Scy#ifdef CONFIG_INTERNAL_SHA384 223337817Scy case CRYPTO_HASH_ALG_SHA384: 224337817Scy if (*len < 48) { 225337817Scy *len = 48; 226337817Scy os_free(ctx); 227337817Scy return -1; 228337817Scy } 229337817Scy *len = 48; 230337817Scy sha384_done(&ctx->u.sha384, mac); 231337817Scy break; 232337817Scy#endif /* CONFIG_INTERNAL_SHA384 */ 233337817Scy#ifdef CONFIG_INTERNAL_SHA512 234337817Scy case CRYPTO_HASH_ALG_SHA512: 235337817Scy if (*len < 64) { 236337817Scy *len = 64; 237337817Scy os_free(ctx); 238337817Scy return -1; 239337817Scy } 240337817Scy *len = 64; 241337817Scy sha512_done(&ctx->u.sha512, mac); 242337817Scy break; 243337817Scy#endif /* CONFIG_INTERNAL_SHA512 */ 244189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 245189251Ssam if (*len < 16) { 246189251Ssam *len = 16; 247189251Ssam os_free(ctx); 248189251Ssam return -1; 249189251Ssam } 250189251Ssam *len = 16; 251189251Ssam 252189251Ssam MD5Final(mac, &ctx->u.md5); 253189251Ssam 254189251Ssam os_memcpy(k_pad, ctx->key, ctx->key_len); 255189251Ssam os_memset(k_pad + ctx->key_len, 0, 256189251Ssam sizeof(k_pad) - ctx->key_len); 257189251Ssam for (i = 0; i < sizeof(k_pad); i++) 258189251Ssam k_pad[i] ^= 0x5c; 259189251Ssam MD5Init(&ctx->u.md5); 260189251Ssam MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 261189251Ssam MD5Update(&ctx->u.md5, mac, 16); 262189251Ssam MD5Final(mac, &ctx->u.md5); 263189251Ssam break; 264189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 265189251Ssam if (*len < 20) { 266189251Ssam *len = 20; 267189251Ssam os_free(ctx); 268189251Ssam return -1; 269189251Ssam } 270189251Ssam *len = 20; 271189251Ssam 272189251Ssam SHA1Final(mac, &ctx->u.sha1); 273189251Ssam 274189251Ssam os_memcpy(k_pad, ctx->key, ctx->key_len); 275189251Ssam os_memset(k_pad + ctx->key_len, 0, 276189251Ssam sizeof(k_pad) - ctx->key_len); 277189251Ssam for (i = 0; i < sizeof(k_pad); i++) 278189251Ssam k_pad[i] ^= 0x5c; 279189251Ssam SHA1Init(&ctx->u.sha1); 280189251Ssam SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 281189251Ssam SHA1Update(&ctx->u.sha1, mac, 20); 282189251Ssam SHA1Final(mac, &ctx->u.sha1); 283189251Ssam break; 284252726Srpaulo#ifdef CONFIG_SHA256 285252726Srpaulo case CRYPTO_HASH_ALG_HMAC_SHA256: 286252726Srpaulo if (*len < 32) { 287252726Srpaulo *len = 32; 288252726Srpaulo os_free(ctx); 289252726Srpaulo return -1; 290252726Srpaulo } 291252726Srpaulo *len = 32; 292252726Srpaulo 293252726Srpaulo sha256_done(&ctx->u.sha256, mac); 294252726Srpaulo 295252726Srpaulo os_memcpy(k_pad, ctx->key, ctx->key_len); 296252726Srpaulo os_memset(k_pad + ctx->key_len, 0, 297252726Srpaulo sizeof(k_pad) - ctx->key_len); 298252726Srpaulo for (i = 0; i < sizeof(k_pad); i++) 299252726Srpaulo k_pad[i] ^= 0x5c; 300252726Srpaulo sha256_init(&ctx->u.sha256); 301252726Srpaulo sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 302252726Srpaulo sha256_process(&ctx->u.sha256, mac, 32); 303252726Srpaulo sha256_done(&ctx->u.sha256, mac); 304252726Srpaulo break; 305252726Srpaulo#endif /* CONFIG_SHA256 */ 306252726Srpaulo default: 307252726Srpaulo os_free(ctx); 308252726Srpaulo return -1; 309189251Ssam } 310189251Ssam 311189251Ssam os_free(ctx); 312189251Ssam 313346981Scy if (TEST_FAIL()) 314346981Scy return -1; 315346981Scy 316189251Ssam return 0; 317189251Ssam} 318189251Ssam 319189251Ssam 320189251Ssamint crypto_global_init(void) 321189251Ssam{ 322189251Ssam return 0; 323189251Ssam} 324189251Ssam 325189251Ssam 326189251Ssamvoid crypto_global_deinit(void) 327189251Ssam{ 328189251Ssam} 329