139beb93cSSam Leffler /* 2*e28a4053SRui Paulo * Crypto wrapper for internal crypto implementation 3*e28a4053SRui Paulo * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "crypto.h" 19*e28a4053SRui Paulo #include "sha1_i.h" 20*e28a4053SRui Paulo #include "md5_i.h" 2139beb93cSSam Leffler 2239beb93cSSam Leffler struct crypto_hash { 2339beb93cSSam Leffler enum crypto_hash_alg alg; 2439beb93cSSam Leffler union { 2539beb93cSSam Leffler struct MD5Context md5; 2639beb93cSSam Leffler struct SHA1Context sha1; 2739beb93cSSam Leffler } u; 2839beb93cSSam Leffler u8 key[64]; 2939beb93cSSam Leffler size_t key_len; 3039beb93cSSam Leffler }; 3139beb93cSSam Leffler 3239beb93cSSam Leffler 3339beb93cSSam Leffler struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 3439beb93cSSam Leffler size_t key_len) 3539beb93cSSam Leffler { 3639beb93cSSam Leffler struct crypto_hash *ctx; 3739beb93cSSam Leffler u8 k_pad[64]; 3839beb93cSSam Leffler u8 tk[20]; 3939beb93cSSam Leffler size_t i; 4039beb93cSSam Leffler 4139beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 4239beb93cSSam Leffler if (ctx == NULL) 4339beb93cSSam Leffler return NULL; 4439beb93cSSam Leffler 4539beb93cSSam Leffler ctx->alg = alg; 4639beb93cSSam Leffler 4739beb93cSSam Leffler switch (alg) { 4839beb93cSSam Leffler case CRYPTO_HASH_ALG_MD5: 4939beb93cSSam Leffler MD5Init(&ctx->u.md5); 5039beb93cSSam Leffler break; 5139beb93cSSam Leffler case CRYPTO_HASH_ALG_SHA1: 5239beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 5339beb93cSSam Leffler break; 5439beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_MD5: 5539beb93cSSam Leffler if (key_len > sizeof(k_pad)) { 5639beb93cSSam Leffler MD5Init(&ctx->u.md5); 5739beb93cSSam Leffler MD5Update(&ctx->u.md5, key, key_len); 5839beb93cSSam Leffler MD5Final(tk, &ctx->u.md5); 5939beb93cSSam Leffler key = tk; 6039beb93cSSam Leffler key_len = 16; 6139beb93cSSam Leffler } 6239beb93cSSam Leffler os_memcpy(ctx->key, key, key_len); 6339beb93cSSam Leffler ctx->key_len = key_len; 6439beb93cSSam Leffler 6539beb93cSSam Leffler os_memcpy(k_pad, key, key_len); 6639beb93cSSam Leffler os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 6739beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 6839beb93cSSam Leffler k_pad[i] ^= 0x36; 6939beb93cSSam Leffler MD5Init(&ctx->u.md5); 7039beb93cSSam Leffler MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 7139beb93cSSam Leffler break; 7239beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_SHA1: 7339beb93cSSam Leffler if (key_len > sizeof(k_pad)) { 7439beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 7539beb93cSSam Leffler SHA1Update(&ctx->u.sha1, key, key_len); 7639beb93cSSam Leffler SHA1Final(tk, &ctx->u.sha1); 7739beb93cSSam Leffler key = tk; 7839beb93cSSam Leffler key_len = 20; 7939beb93cSSam Leffler } 8039beb93cSSam Leffler os_memcpy(ctx->key, key, key_len); 8139beb93cSSam Leffler ctx->key_len = key_len; 8239beb93cSSam Leffler 8339beb93cSSam Leffler os_memcpy(k_pad, key, key_len); 8439beb93cSSam Leffler os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 8539beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 8639beb93cSSam Leffler k_pad[i] ^= 0x36; 8739beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 8839beb93cSSam Leffler SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 8939beb93cSSam Leffler break; 9039beb93cSSam Leffler default: 9139beb93cSSam Leffler os_free(ctx); 9239beb93cSSam Leffler return NULL; 9339beb93cSSam Leffler } 9439beb93cSSam Leffler 9539beb93cSSam Leffler return ctx; 9639beb93cSSam Leffler } 9739beb93cSSam Leffler 9839beb93cSSam Leffler 9939beb93cSSam Leffler void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 10039beb93cSSam Leffler { 10139beb93cSSam Leffler if (ctx == NULL) 10239beb93cSSam Leffler return; 10339beb93cSSam Leffler 10439beb93cSSam Leffler switch (ctx->alg) { 10539beb93cSSam Leffler case CRYPTO_HASH_ALG_MD5: 10639beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_MD5: 10739beb93cSSam Leffler MD5Update(&ctx->u.md5, data, len); 10839beb93cSSam Leffler break; 10939beb93cSSam Leffler case CRYPTO_HASH_ALG_SHA1: 11039beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_SHA1: 11139beb93cSSam Leffler SHA1Update(&ctx->u.sha1, data, len); 11239beb93cSSam Leffler break; 11339beb93cSSam Leffler } 11439beb93cSSam Leffler } 11539beb93cSSam Leffler 11639beb93cSSam Leffler 11739beb93cSSam Leffler int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 11839beb93cSSam Leffler { 11939beb93cSSam Leffler u8 k_pad[64]; 12039beb93cSSam Leffler size_t i; 12139beb93cSSam Leffler 12239beb93cSSam Leffler if (ctx == NULL) 12339beb93cSSam Leffler return -2; 12439beb93cSSam Leffler 12539beb93cSSam Leffler if (mac == NULL || len == NULL) { 12639beb93cSSam Leffler os_free(ctx); 12739beb93cSSam Leffler return 0; 12839beb93cSSam Leffler } 12939beb93cSSam Leffler 13039beb93cSSam Leffler switch (ctx->alg) { 13139beb93cSSam Leffler case CRYPTO_HASH_ALG_MD5: 13239beb93cSSam Leffler if (*len < 16) { 13339beb93cSSam Leffler *len = 16; 13439beb93cSSam Leffler os_free(ctx); 13539beb93cSSam Leffler return -1; 13639beb93cSSam Leffler } 13739beb93cSSam Leffler *len = 16; 13839beb93cSSam Leffler MD5Final(mac, &ctx->u.md5); 13939beb93cSSam Leffler break; 14039beb93cSSam Leffler case CRYPTO_HASH_ALG_SHA1: 14139beb93cSSam Leffler if (*len < 20) { 14239beb93cSSam Leffler *len = 20; 14339beb93cSSam Leffler os_free(ctx); 14439beb93cSSam Leffler return -1; 14539beb93cSSam Leffler } 14639beb93cSSam Leffler *len = 20; 14739beb93cSSam Leffler SHA1Final(mac, &ctx->u.sha1); 14839beb93cSSam Leffler break; 14939beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_MD5: 15039beb93cSSam Leffler if (*len < 16) { 15139beb93cSSam Leffler *len = 16; 15239beb93cSSam Leffler os_free(ctx); 15339beb93cSSam Leffler return -1; 15439beb93cSSam Leffler } 15539beb93cSSam Leffler *len = 16; 15639beb93cSSam Leffler 15739beb93cSSam Leffler MD5Final(mac, &ctx->u.md5); 15839beb93cSSam Leffler 15939beb93cSSam Leffler os_memcpy(k_pad, ctx->key, ctx->key_len); 16039beb93cSSam Leffler os_memset(k_pad + ctx->key_len, 0, 16139beb93cSSam Leffler sizeof(k_pad) - ctx->key_len); 16239beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 16339beb93cSSam Leffler k_pad[i] ^= 0x5c; 16439beb93cSSam Leffler MD5Init(&ctx->u.md5); 16539beb93cSSam Leffler MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 16639beb93cSSam Leffler MD5Update(&ctx->u.md5, mac, 16); 16739beb93cSSam Leffler MD5Final(mac, &ctx->u.md5); 16839beb93cSSam Leffler break; 16939beb93cSSam Leffler case CRYPTO_HASH_ALG_HMAC_SHA1: 17039beb93cSSam Leffler if (*len < 20) { 17139beb93cSSam Leffler *len = 20; 17239beb93cSSam Leffler os_free(ctx); 17339beb93cSSam Leffler return -1; 17439beb93cSSam Leffler } 17539beb93cSSam Leffler *len = 20; 17639beb93cSSam Leffler 17739beb93cSSam Leffler SHA1Final(mac, &ctx->u.sha1); 17839beb93cSSam Leffler 17939beb93cSSam Leffler os_memcpy(k_pad, ctx->key, ctx->key_len); 18039beb93cSSam Leffler os_memset(k_pad + ctx->key_len, 0, 18139beb93cSSam Leffler sizeof(k_pad) - ctx->key_len); 18239beb93cSSam Leffler for (i = 0; i < sizeof(k_pad); i++) 18339beb93cSSam Leffler k_pad[i] ^= 0x5c; 18439beb93cSSam Leffler SHA1Init(&ctx->u.sha1); 18539beb93cSSam Leffler SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 18639beb93cSSam Leffler SHA1Update(&ctx->u.sha1, mac, 20); 18739beb93cSSam Leffler SHA1Final(mac, &ctx->u.sha1); 18839beb93cSSam Leffler break; 18939beb93cSSam Leffler } 19039beb93cSSam Leffler 19139beb93cSSam Leffler os_free(ctx); 19239beb93cSSam Leffler 19339beb93cSSam Leffler return 0; 19439beb93cSSam Leffler } 19539beb93cSSam Leffler 19639beb93cSSam Leffler 19739beb93cSSam Leffler int crypto_global_init(void) 19839beb93cSSam Leffler { 19939beb93cSSam Leffler return 0; 20039beb93cSSam Leffler } 20139beb93cSSam Leffler 20239beb93cSSam Leffler 20339beb93cSSam Leffler void crypto_global_deinit(void) 20439beb93cSSam Leffler { 20539beb93cSSam Leffler } 206