139beb93cSSam Leffler /* 2e28a4053SRui Paulo * Crypto wrapper for internal crypto implementation 3f05cddf9SRui Paulo * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 1239beb93cSSam Leffler #include "crypto.h" 13f05cddf9SRui Paulo #include "sha256_i.h" 14780fb4a2SCy Schubert #include "sha384_i.h" 15780fb4a2SCy Schubert #include "sha512_i.h" 16e28a4053SRui Paulo #include "sha1_i.h" 17e28a4053SRui Paulo #include "md5_i.h" 1839beb93cSSam Leffler 1939beb93cSSam Leffler struct crypto_hash { 2039beb93cSSam Leffler enum crypto_hash_alg alg; 2139beb93cSSam Leffler union { 2239beb93cSSam Leffler struct MD5Context md5; 2339beb93cSSam Leffler struct SHA1Context sha1; 24f05cddf9SRui Paulo #ifdef CONFIG_SHA256 25f05cddf9SRui Paulo struct sha256_state sha256; 26f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */ 27780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384 28780fb4a2SCy Schubert struct sha384_state sha384; 29780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */ 30780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512 31780fb4a2SCy Schubert struct sha512_state sha512; 32780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */ 3339beb93cSSam Leffler } u; 3439beb93cSSam Leffler u8 key[64]; 3539beb93cSSam Leffler size_t key_len; 3639beb93cSSam Leffler }; 3739beb93cSSam Leffler 3839beb93cSSam Leffler 3939beb93cSSam Leffler struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 4039beb93cSSam Leffler size_t key_len) 4139beb93cSSam Leffler { 4239beb93cSSam Leffler struct crypto_hash *ctx; 4339beb93cSSam Leffler u8 k_pad[64]; 44f05cddf9SRui Paulo u8 tk[32]; 4539beb93cSSam Leffler size_t i; 4639beb93cSSam Leffler 4739beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 4839beb93cSSam Leffler if (ctx == NULL) 4939beb93cSSam Leffler return NULL; 5039beb93cSSam Leffler 5139beb93cSSam Leffler ctx->alg = alg; 5239beb93cSSam Leffler 5339beb93cSSam Leffler switch (alg) { 5439beb93cSSam Leffler case CRYPTO_HASH_ALG_MD5: 5539beb93cSSam Leffler MD5Init(&ctx->u.md5); 5639beb93cSSam Leffler break; 5739beb93cSSam Leffler case CRYPTO_HASH_ALG_SHA1: 5839beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 5939beb93cSSam Leffler break; 60f05cddf9SRui Paulo #ifdef CONFIG_SHA256 61f05cddf9SRui Paulo case CRYPTO_HASH_ALG_SHA256: 62f05cddf9SRui Paulo sha256_init(&ctx->u.sha256); 63f05cddf9SRui Paulo break; 64f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */ 65780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384 66780fb4a2SCy Schubert case CRYPTO_HASH_ALG_SHA384: 67780fb4a2SCy Schubert sha384_init(&ctx->u.sha384); 68780fb4a2SCy Schubert break; 69780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */ 70780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512 71780fb4a2SCy Schubert case CRYPTO_HASH_ALG_SHA512: 72780fb4a2SCy Schubert sha512_init(&ctx->u.sha512); 73780fb4a2SCy Schubert break; 74780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */ 7539beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_MD5: 7639beb93cSSam Leffler if (key_len > sizeof(k_pad)) { 7739beb93cSSam Leffler MD5Init(&ctx->u.md5); 7839beb93cSSam Leffler MD5Update(&ctx->u.md5, key, key_len); 7939beb93cSSam Leffler MD5Final(tk, &ctx->u.md5); 8039beb93cSSam Leffler key = tk; 8139beb93cSSam Leffler key_len = 16; 8239beb93cSSam Leffler } 8339beb93cSSam Leffler os_memcpy(ctx->key, key, key_len); 8439beb93cSSam Leffler ctx->key_len = key_len; 8539beb93cSSam Leffler 8639beb93cSSam Leffler os_memcpy(k_pad, key, key_len); 87f05cddf9SRui Paulo if (key_len < sizeof(k_pad)) 8839beb93cSSam Leffler os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 8939beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 9039beb93cSSam Leffler k_pad[i] ^= 0x36; 9139beb93cSSam Leffler MD5Init(&ctx->u.md5); 9239beb93cSSam Leffler MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 9339beb93cSSam Leffler break; 9439beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_SHA1: 9539beb93cSSam Leffler if (key_len > sizeof(k_pad)) { 9639beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 9739beb93cSSam Leffler SHA1Update(&ctx->u.sha1, key, key_len); 9839beb93cSSam Leffler SHA1Final(tk, &ctx->u.sha1); 9939beb93cSSam Leffler key = tk; 10039beb93cSSam Leffler key_len = 20; 10139beb93cSSam Leffler } 10239beb93cSSam Leffler os_memcpy(ctx->key, key, key_len); 10339beb93cSSam Leffler ctx->key_len = key_len; 10439beb93cSSam Leffler 10539beb93cSSam Leffler os_memcpy(k_pad, key, key_len); 106f05cddf9SRui Paulo if (key_len < sizeof(k_pad)) 10739beb93cSSam Leffler os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 10839beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 10939beb93cSSam Leffler k_pad[i] ^= 0x36; 11039beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 11139beb93cSSam Leffler SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 11239beb93cSSam Leffler break; 113f05cddf9SRui Paulo #ifdef CONFIG_SHA256 114f05cddf9SRui Paulo case CRYPTO_HASH_ALG_HMAC_SHA256: 115f05cddf9SRui Paulo if (key_len > sizeof(k_pad)) { 116f05cddf9SRui Paulo sha256_init(&ctx->u.sha256); 117f05cddf9SRui Paulo sha256_process(&ctx->u.sha256, key, key_len); 118f05cddf9SRui Paulo sha256_done(&ctx->u.sha256, tk); 119f05cddf9SRui Paulo key = tk; 120f05cddf9SRui Paulo key_len = 32; 121f05cddf9SRui Paulo } 122f05cddf9SRui Paulo os_memcpy(ctx->key, key, key_len); 123f05cddf9SRui Paulo ctx->key_len = key_len; 124f05cddf9SRui Paulo 125f05cddf9SRui Paulo os_memcpy(k_pad, key, key_len); 126f05cddf9SRui Paulo if (key_len < sizeof(k_pad)) 127f05cddf9SRui Paulo os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 128f05cddf9SRui Paulo for (i = 0; i < sizeof(k_pad); i++) 129f05cddf9SRui Paulo k_pad[i] ^= 0x36; 130f05cddf9SRui Paulo sha256_init(&ctx->u.sha256); 131f05cddf9SRui Paulo sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 132f05cddf9SRui Paulo break; 133f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */ 13439beb93cSSam Leffler default: 13539beb93cSSam Leffler os_free(ctx); 13639beb93cSSam Leffler return NULL; 13739beb93cSSam Leffler } 13839beb93cSSam Leffler 13939beb93cSSam Leffler return ctx; 14039beb93cSSam Leffler } 14139beb93cSSam Leffler 14239beb93cSSam Leffler 14339beb93cSSam Leffler void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 14439beb93cSSam Leffler { 14539beb93cSSam Leffler if (ctx == NULL) 14639beb93cSSam Leffler return; 14739beb93cSSam Leffler 14839beb93cSSam Leffler switch (ctx->alg) { 14939beb93cSSam Leffler case CRYPTO_HASH_ALG_MD5: 15039beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_MD5: 15139beb93cSSam Leffler MD5Update(&ctx->u.md5, data, len); 15239beb93cSSam Leffler break; 15339beb93cSSam Leffler case CRYPTO_HASH_ALG_SHA1: 15439beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_SHA1: 15539beb93cSSam Leffler SHA1Update(&ctx->u.sha1, data, len); 15639beb93cSSam Leffler break; 157f05cddf9SRui Paulo #ifdef CONFIG_SHA256 158f05cddf9SRui Paulo case CRYPTO_HASH_ALG_SHA256: 159f05cddf9SRui Paulo case CRYPTO_HASH_ALG_HMAC_SHA256: 160f05cddf9SRui Paulo sha256_process(&ctx->u.sha256, data, len); 161f05cddf9SRui Paulo break; 162f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */ 163780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384 164780fb4a2SCy Schubert case CRYPTO_HASH_ALG_SHA384: 165780fb4a2SCy Schubert sha384_process(&ctx->u.sha384, data, len); 166780fb4a2SCy Schubert break; 167780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */ 168780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512 169780fb4a2SCy Schubert case CRYPTO_HASH_ALG_SHA512: 170780fb4a2SCy Schubert sha512_process(&ctx->u.sha512, data, len); 171780fb4a2SCy Schubert break; 172780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */ 173f05cddf9SRui Paulo default: 174f05cddf9SRui Paulo break; 17539beb93cSSam Leffler } 17639beb93cSSam Leffler } 17739beb93cSSam Leffler 17839beb93cSSam Leffler 17939beb93cSSam Leffler int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 18039beb93cSSam Leffler { 18139beb93cSSam Leffler u8 k_pad[64]; 18239beb93cSSam Leffler size_t i; 18339beb93cSSam Leffler 18439beb93cSSam Leffler if (ctx == NULL) 18539beb93cSSam Leffler return -2; 18639beb93cSSam Leffler 18739beb93cSSam Leffler if (mac == NULL || len == NULL) { 18839beb93cSSam Leffler os_free(ctx); 18939beb93cSSam Leffler return 0; 19039beb93cSSam Leffler } 19139beb93cSSam Leffler 19239beb93cSSam Leffler switch (ctx->alg) { 19339beb93cSSam Leffler case CRYPTO_HASH_ALG_MD5: 19439beb93cSSam Leffler if (*len < 16) { 19539beb93cSSam Leffler *len = 16; 19639beb93cSSam Leffler os_free(ctx); 19739beb93cSSam Leffler return -1; 19839beb93cSSam Leffler } 19939beb93cSSam Leffler *len = 16; 20039beb93cSSam Leffler MD5Final(mac, &ctx->u.md5); 20139beb93cSSam Leffler break; 20239beb93cSSam Leffler case CRYPTO_HASH_ALG_SHA1: 20339beb93cSSam Leffler if (*len < 20) { 20439beb93cSSam Leffler *len = 20; 20539beb93cSSam Leffler os_free(ctx); 20639beb93cSSam Leffler return -1; 20739beb93cSSam Leffler } 20839beb93cSSam Leffler *len = 20; 20939beb93cSSam Leffler SHA1Final(mac, &ctx->u.sha1); 21039beb93cSSam Leffler break; 211f05cddf9SRui Paulo #ifdef CONFIG_SHA256 212f05cddf9SRui Paulo case CRYPTO_HASH_ALG_SHA256: 213f05cddf9SRui Paulo if (*len < 32) { 214f05cddf9SRui Paulo *len = 32; 215f05cddf9SRui Paulo os_free(ctx); 216f05cddf9SRui Paulo return -1; 217f05cddf9SRui Paulo } 218f05cddf9SRui Paulo *len = 32; 219f05cddf9SRui Paulo sha256_done(&ctx->u.sha256, mac); 220f05cddf9SRui Paulo break; 221f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */ 222780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384 223780fb4a2SCy Schubert case CRYPTO_HASH_ALG_SHA384: 224780fb4a2SCy Schubert if (*len < 48) { 225780fb4a2SCy Schubert *len = 48; 226780fb4a2SCy Schubert os_free(ctx); 227780fb4a2SCy Schubert return -1; 228780fb4a2SCy Schubert } 229780fb4a2SCy Schubert *len = 48; 230780fb4a2SCy Schubert sha384_done(&ctx->u.sha384, mac); 231780fb4a2SCy Schubert break; 232780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */ 233780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512 234780fb4a2SCy Schubert case CRYPTO_HASH_ALG_SHA512: 235780fb4a2SCy Schubert if (*len < 64) { 236780fb4a2SCy Schubert *len = 64; 237780fb4a2SCy Schubert os_free(ctx); 238780fb4a2SCy Schubert return -1; 239780fb4a2SCy Schubert } 240780fb4a2SCy Schubert *len = 64; 241780fb4a2SCy Schubert sha512_done(&ctx->u.sha512, mac); 242780fb4a2SCy Schubert break; 243780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */ 24439beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_MD5: 24539beb93cSSam Leffler if (*len < 16) { 24639beb93cSSam Leffler *len = 16; 24739beb93cSSam Leffler os_free(ctx); 24839beb93cSSam Leffler return -1; 24939beb93cSSam Leffler } 25039beb93cSSam Leffler *len = 16; 25139beb93cSSam Leffler 25239beb93cSSam Leffler MD5Final(mac, &ctx->u.md5); 25339beb93cSSam Leffler 25439beb93cSSam Leffler os_memcpy(k_pad, ctx->key, ctx->key_len); 25539beb93cSSam Leffler os_memset(k_pad + ctx->key_len, 0, 25639beb93cSSam Leffler sizeof(k_pad) - ctx->key_len); 25739beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 25839beb93cSSam Leffler k_pad[i] ^= 0x5c; 25939beb93cSSam Leffler MD5Init(&ctx->u.md5); 26039beb93cSSam Leffler MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 26139beb93cSSam Leffler MD5Update(&ctx->u.md5, mac, 16); 26239beb93cSSam Leffler MD5Final(mac, &ctx->u.md5); 26339beb93cSSam Leffler break; 26439beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_SHA1: 26539beb93cSSam Leffler if (*len < 20) { 26639beb93cSSam Leffler *len = 20; 26739beb93cSSam Leffler os_free(ctx); 26839beb93cSSam Leffler return -1; 26939beb93cSSam Leffler } 27039beb93cSSam Leffler *len = 20; 27139beb93cSSam Leffler 27239beb93cSSam Leffler SHA1Final(mac, &ctx->u.sha1); 27339beb93cSSam Leffler 27439beb93cSSam Leffler os_memcpy(k_pad, ctx->key, ctx->key_len); 27539beb93cSSam Leffler os_memset(k_pad + ctx->key_len, 0, 27639beb93cSSam Leffler sizeof(k_pad) - ctx->key_len); 27739beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 27839beb93cSSam Leffler k_pad[i] ^= 0x5c; 27939beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 28039beb93cSSam Leffler SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 28139beb93cSSam Leffler SHA1Update(&ctx->u.sha1, mac, 20); 28239beb93cSSam Leffler SHA1Final(mac, &ctx->u.sha1); 28339beb93cSSam Leffler break; 284f05cddf9SRui Paulo #ifdef CONFIG_SHA256 285f05cddf9SRui Paulo case CRYPTO_HASH_ALG_HMAC_SHA256: 286f05cddf9SRui Paulo if (*len < 32) { 287f05cddf9SRui Paulo *len = 32; 288f05cddf9SRui Paulo os_free(ctx); 289f05cddf9SRui Paulo return -1; 290f05cddf9SRui Paulo } 291f05cddf9SRui Paulo *len = 32; 292f05cddf9SRui Paulo 293f05cddf9SRui Paulo sha256_done(&ctx->u.sha256, mac); 294f05cddf9SRui Paulo 295f05cddf9SRui Paulo os_memcpy(k_pad, ctx->key, ctx->key_len); 296f05cddf9SRui Paulo os_memset(k_pad + ctx->key_len, 0, 297f05cddf9SRui Paulo sizeof(k_pad) - ctx->key_len); 298f05cddf9SRui Paulo for (i = 0; i < sizeof(k_pad); i++) 299f05cddf9SRui Paulo k_pad[i] ^= 0x5c; 300f05cddf9SRui Paulo sha256_init(&ctx->u.sha256); 301f05cddf9SRui Paulo sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad)); 302f05cddf9SRui Paulo sha256_process(&ctx->u.sha256, mac, 32); 303f05cddf9SRui Paulo sha256_done(&ctx->u.sha256, mac); 304f05cddf9SRui Paulo break; 305f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */ 306f05cddf9SRui Paulo default: 307f05cddf9SRui Paulo os_free(ctx); 308f05cddf9SRui Paulo return -1; 30939beb93cSSam Leffler } 31039beb93cSSam Leffler 31139beb93cSSam Leffler os_free(ctx); 31239beb93cSSam Leffler 3134bc52338SCy Schubert if (TEST_FAIL()) 3144bc52338SCy Schubert return -1; 3154bc52338SCy Schubert 31639beb93cSSam Leffler return 0; 31739beb93cSSam Leffler } 31839beb93cSSam Leffler 31939beb93cSSam Leffler 32039beb93cSSam Leffler int crypto_global_init(void) 32139beb93cSSam Leffler { 32239beb93cSSam Leffler return 0; 32339beb93cSSam Leffler } 32439beb93cSSam Leffler 32539beb93cSSam Leffler 32639beb93cSSam Leffler void crypto_global_deinit(void) 32739beb93cSSam Leffler { 32839beb93cSSam Leffler } 329*a90b9d01SCy Schubert 330*a90b9d01SCy Schubert 331*a90b9d01SCy Schubert void crypto_unload(void) 332*a90b9d01SCy Schubert { 333*a90b9d01SCy Schubert } 334