1189251Ssam/* 2214734Srpaulo * Crypto wrapper for internal crypto implementation 3214734Srpaulo * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam 17189251Ssam#include "common.h" 18189251Ssam#include "crypto.h" 19214734Srpaulo#include "sha1_i.h" 20214734Srpaulo#include "md5_i.h" 21189251Ssam 22189251Ssamstruct crypto_hash { 23189251Ssam enum crypto_hash_alg alg; 24189251Ssam union { 25189251Ssam struct MD5Context md5; 26189251Ssam struct SHA1Context sha1; 27189251Ssam } u; 28189251Ssam u8 key[64]; 29189251Ssam size_t key_len; 30189251Ssam}; 31189251Ssam 32189251Ssam 33189251Ssamstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 34189251Ssam size_t key_len) 35189251Ssam{ 36189251Ssam struct crypto_hash *ctx; 37189251Ssam u8 k_pad[64]; 38189251Ssam u8 tk[20]; 39189251Ssam size_t i; 40189251Ssam 41189251Ssam ctx = os_zalloc(sizeof(*ctx)); 42189251Ssam if (ctx == NULL) 43189251Ssam return NULL; 44189251Ssam 45189251Ssam ctx->alg = alg; 46189251Ssam 47189251Ssam switch (alg) { 48189251Ssam case CRYPTO_HASH_ALG_MD5: 49189251Ssam MD5Init(&ctx->u.md5); 50189251Ssam break; 51189251Ssam case CRYPTO_HASH_ALG_SHA1: 52189251Ssam SHA1Init(&ctx->u.sha1); 53189251Ssam break; 54189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 55189251Ssam if (key_len > sizeof(k_pad)) { 56189251Ssam MD5Init(&ctx->u.md5); 57189251Ssam MD5Update(&ctx->u.md5, key, key_len); 58189251Ssam MD5Final(tk, &ctx->u.md5); 59189251Ssam key = tk; 60189251Ssam key_len = 16; 61189251Ssam } 62189251Ssam os_memcpy(ctx->key, key, key_len); 63189251Ssam ctx->key_len = key_len; 64189251Ssam 65189251Ssam os_memcpy(k_pad, key, key_len); 66189251Ssam os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 67189251Ssam for (i = 0; i < sizeof(k_pad); i++) 68189251Ssam k_pad[i] ^= 0x36; 69189251Ssam MD5Init(&ctx->u.md5); 70189251Ssam MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 71189251Ssam break; 72189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 73189251Ssam if (key_len > sizeof(k_pad)) { 74189251Ssam SHA1Init(&ctx->u.sha1); 75189251Ssam SHA1Update(&ctx->u.sha1, key, key_len); 76189251Ssam SHA1Final(tk, &ctx->u.sha1); 77189251Ssam key = tk; 78189251Ssam key_len = 20; 79189251Ssam } 80189251Ssam os_memcpy(ctx->key, key, key_len); 81189251Ssam ctx->key_len = key_len; 82189251Ssam 83189251Ssam os_memcpy(k_pad, key, key_len); 84189251Ssam os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 85189251Ssam for (i = 0; i < sizeof(k_pad); i++) 86189251Ssam k_pad[i] ^= 0x36; 87189251Ssam SHA1Init(&ctx->u.sha1); 88189251Ssam SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 89189251Ssam break; 90189251Ssam default: 91189251Ssam os_free(ctx); 92189251Ssam return NULL; 93189251Ssam } 94189251Ssam 95189251Ssam return ctx; 96189251Ssam} 97189251Ssam 98189251Ssam 99189251Ssamvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 100189251Ssam{ 101189251Ssam if (ctx == NULL) 102189251Ssam return; 103189251Ssam 104189251Ssam switch (ctx->alg) { 105189251Ssam case CRYPTO_HASH_ALG_MD5: 106189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 107189251Ssam MD5Update(&ctx->u.md5, data, len); 108189251Ssam break; 109189251Ssam case CRYPTO_HASH_ALG_SHA1: 110189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 111189251Ssam SHA1Update(&ctx->u.sha1, data, len); 112189251Ssam break; 113189251Ssam } 114189251Ssam} 115189251Ssam 116189251Ssam 117189251Ssamint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 118189251Ssam{ 119189251Ssam u8 k_pad[64]; 120189251Ssam size_t i; 121189251Ssam 122189251Ssam if (ctx == NULL) 123189251Ssam return -2; 124189251Ssam 125189251Ssam if (mac == NULL || len == NULL) { 126189251Ssam os_free(ctx); 127189251Ssam return 0; 128189251Ssam } 129189251Ssam 130189251Ssam switch (ctx->alg) { 131189251Ssam case CRYPTO_HASH_ALG_MD5: 132189251Ssam if (*len < 16) { 133189251Ssam *len = 16; 134189251Ssam os_free(ctx); 135189251Ssam return -1; 136189251Ssam } 137189251Ssam *len = 16; 138189251Ssam MD5Final(mac, &ctx->u.md5); 139189251Ssam break; 140189251Ssam case CRYPTO_HASH_ALG_SHA1: 141189251Ssam if (*len < 20) { 142189251Ssam *len = 20; 143189251Ssam os_free(ctx); 144189251Ssam return -1; 145189251Ssam } 146189251Ssam *len = 20; 147189251Ssam SHA1Final(mac, &ctx->u.sha1); 148189251Ssam break; 149189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 150189251Ssam if (*len < 16) { 151189251Ssam *len = 16; 152189251Ssam os_free(ctx); 153189251Ssam return -1; 154189251Ssam } 155189251Ssam *len = 16; 156189251Ssam 157189251Ssam MD5Final(mac, &ctx->u.md5); 158189251Ssam 159189251Ssam os_memcpy(k_pad, ctx->key, ctx->key_len); 160189251Ssam os_memset(k_pad + ctx->key_len, 0, 161189251Ssam sizeof(k_pad) - ctx->key_len); 162189251Ssam for (i = 0; i < sizeof(k_pad); i++) 163189251Ssam k_pad[i] ^= 0x5c; 164189251Ssam MD5Init(&ctx->u.md5); 165189251Ssam MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 166189251Ssam MD5Update(&ctx->u.md5, mac, 16); 167189251Ssam MD5Final(mac, &ctx->u.md5); 168189251Ssam break; 169189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 170189251Ssam if (*len < 20) { 171189251Ssam *len = 20; 172189251Ssam os_free(ctx); 173189251Ssam return -1; 174189251Ssam } 175189251Ssam *len = 20; 176189251Ssam 177189251Ssam SHA1Final(mac, &ctx->u.sha1); 178189251Ssam 179189251Ssam os_memcpy(k_pad, ctx->key, ctx->key_len); 180189251Ssam os_memset(k_pad + ctx->key_len, 0, 181189251Ssam sizeof(k_pad) - ctx->key_len); 182189251Ssam for (i = 0; i < sizeof(k_pad); i++) 183189251Ssam k_pad[i] ^= 0x5c; 184189251Ssam SHA1Init(&ctx->u.sha1); 185189251Ssam SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 186189251Ssam SHA1Update(&ctx->u.sha1, mac, 20); 187189251Ssam SHA1Final(mac, &ctx->u.sha1); 188189251Ssam break; 189189251Ssam } 190189251Ssam 191189251Ssam os_free(ctx); 192189251Ssam 193189251Ssam return 0; 194189251Ssam} 195189251Ssam 196189251Ssam 197189251Ssamint crypto_global_init(void) 198189251Ssam{ 199189251Ssam return 0; 200189251Ssam} 201189251Ssam 202189251Ssam 203189251Ssamvoid crypto_global_deinit(void) 204189251Ssam{ 205189251Ssam} 206