1258945Sroberto/* 2258945Sroberto * Crypto wrapper for internal crypto implementation 3258945Sroberto * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 4258945Sroberto * 5258945Sroberto * This program is free software; you can redistribute it and/or modify 6258945Sroberto * it under the terms of the GNU General Public License version 2 as 7258945Sroberto * published by the Free Software Foundation. 8258945Sroberto * 9258945Sroberto * Alternatively, this software may be distributed under the terms of BSD 10258945Sroberto * license. 11258945Sroberto * 12258945Sroberto * See README and COPYING for more details. 13258945Sroberto */ 14258945Sroberto 15258945Sroberto#include "includes.h" 16258945Sroberto 17258945Sroberto#include "common.h" 18258945Sroberto#include "crypto.h" 19258945Sroberto#include "sha1_i.h" 20258945Sroberto#include "md5_i.h" 21258945Sroberto 22258945Srobertostruct crypto_hash { 23258945Sroberto enum crypto_hash_alg alg; 24258945Sroberto union { 25258945Sroberto struct MD5Context md5; 26258945Sroberto struct SHA1Context sha1; 27258945Sroberto } u; 28258945Sroberto u8 key[64]; 29258945Sroberto size_t key_len; 30258945Sroberto}; 31258945Sroberto 32258945Sroberto 33258945Srobertostruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 34258945Sroberto size_t key_len) 35258945Sroberto{ 36258945Sroberto struct crypto_hash *ctx; 37258945Sroberto u8 k_pad[64]; 38258945Sroberto u8 tk[20]; 39330567Sgordon size_t i; 40258945Sroberto 41258945Sroberto ctx = os_zalloc(sizeof(*ctx)); 42258945Sroberto if (ctx == NULL) 43258945Sroberto return NULL; 44258945Sroberto 45258945Sroberto ctx->alg = alg; 46258945Sroberto 47258945Sroberto switch (alg) { 48258945Sroberto case CRYPTO_HASH_ALG_MD5: 49258945Sroberto MD5Init(&ctx->u.md5); 50258945Sroberto break; 51258945Sroberto case CRYPTO_HASH_ALG_SHA1: 52258945Sroberto SHA1Init(&ctx->u.sha1); 53258945Sroberto break; 54258945Sroberto case CRYPTO_HASH_ALG_HMAC_MD5: 55258945Sroberto if (key_len > sizeof(k_pad)) { 56258945Sroberto MD5Init(&ctx->u.md5); 57258945Sroberto MD5Update(&ctx->u.md5, key, key_len); 58258945Sroberto MD5Final(tk, &ctx->u.md5); 59258945Sroberto key = tk; 60258945Sroberto key_len = 16; 61258945Sroberto } 62258945Sroberto os_memcpy(ctx->key, key, key_len); 63258945Sroberto ctx->key_len = key_len; 64258945Sroberto 65258945Sroberto os_memcpy(k_pad, key, key_len); 66258945Sroberto os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 67258945Sroberto for (i = 0; i < sizeof(k_pad); i++) 68258945Sroberto k_pad[i] ^= 0x36; 69280849Scy MD5Init(&ctx->u.md5); 70258945Sroberto MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 71280849Scy break; 72280849Scy case CRYPTO_HASH_ALG_HMAC_SHA1: 73280849Scy if (key_len > sizeof(k_pad)) { 74280849Scy SHA1Init(&ctx->u.sha1); 75280849Scy SHA1Update(&ctx->u.sha1, key, key_len); 76258945Sroberto SHA1Final(tk, &ctx->u.sha1); 77258945Sroberto key = tk; 78258945Sroberto key_len = 20; 79258945Sroberto } 80258945Sroberto os_memcpy(ctx->key, key, key_len); 81258945Sroberto ctx->key_len = key_len; 82258945Sroberto 83258945Sroberto os_memcpy(k_pad, key, key_len); 84258945Sroberto os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 85258945Sroberto for (i = 0; i < sizeof(k_pad); i++) 86280849Scy k_pad[i] ^= 0x36; 87280849Scy SHA1Init(&ctx->u.sha1); 88280849Scy SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 89280849Scy break; 90258945Sroberto default: 91280849Scy os_free(ctx); 92258945Sroberto return NULL; 93258945Sroberto } 94258945Sroberto 95258945Sroberto return ctx; 96258945Sroberto} 97258945Sroberto 98280849Scy 99280849Scyvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 100280849Scy{ 101280849Scy if (ctx == NULL) 102280849Scy return; 103258945Sroberto 104280849Scy switch (ctx->alg) { 105280849Scy case CRYPTO_HASH_ALG_MD5: 106280849Scy case CRYPTO_HASH_ALG_HMAC_MD5: 107280849Scy MD5Update(&ctx->u.md5, data, len); 108280849Scy break; 109280849Scy case CRYPTO_HASH_ALG_SHA1: 110280849Scy case CRYPTO_HASH_ALG_HMAC_SHA1: 111280849Scy SHA1Update(&ctx->u.sha1, data, len); 112280849Scy break; 113280849Scy } 114280849Scy} 115280849Scy 116280849Scy 117280849Scyint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 118280849Scy{ 119280849Scy u8 k_pad[64]; 120280849Scy size_t i; 121280849Scy 122280849Scy if (ctx == NULL) 123280849Scy return -2; 124280849Scy 125280849Scy if (mac == NULL || len == NULL) { 126280849Scy os_free(ctx); 127280849Scy return 0; 128280849Scy } 129280849Scy 130285612Sdelphij switch (ctx->alg) { 131285612Sdelphij case CRYPTO_HASH_ALG_MD5: 132258945Sroberto if (*len < 16) { 133258945Sroberto *len = 16; 134280849Scy os_free(ctx); 135280849Scy return -1; 136258945Sroberto } 137258945Sroberto *len = 16; 138280849Scy MD5Final(mac, &ctx->u.md5); 139280849Scy break; 140280849Scy case CRYPTO_HASH_ALG_SHA1: 141280849Scy if (*len < 20) { 142280849Scy *len = 20; 143280849Scy os_free(ctx); 144280849Scy return -1; 145280849Scy } 146280849Scy *len = 20; 147280849Scy SHA1Final(mac, &ctx->u.sha1); 148280849Scy break; 149280849Scy case CRYPTO_HASH_ALG_HMAC_MD5: 150280849Scy if (*len < 16) { 151280849Scy *len = 16; 152280849Scy os_free(ctx); 153280849Scy return -1; 154280849Scy } 155280849Scy *len = 16; 156280849Scy 157258945Sroberto MD5Final(mac, &ctx->u.md5); 158258945Sroberto 159258945Sroberto os_memcpy(k_pad, ctx->key, ctx->key_len); 160258945Sroberto os_memset(k_pad + ctx->key_len, 0, 161280849Scy sizeof(k_pad) - ctx->key_len); 162258945Sroberto for (i = 0; i < sizeof(k_pad); i++) 163258945Sroberto k_pad[i] ^= 0x5c; 164258945Sroberto MD5Init(&ctx->u.md5); 165258945Sroberto MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 166280849Scy MD5Update(&ctx->u.md5, mac, 16); 167258945Sroberto MD5Final(mac, &ctx->u.md5); 168280849Scy break; 169280849Scy case CRYPTO_HASH_ALG_HMAC_SHA1: 170258945Sroberto if (*len < 20) { 171280849Scy *len = 20; 172280849Scy os_free(ctx); 173280849Scy return -1; 174280849Scy } 175280849Scy *len = 20; 176280849Scy 177280849Scy SHA1Final(mac, &ctx->u.sha1); 178280849Scy 179330567Sgordon os_memcpy(k_pad, ctx->key, ctx->key_len); 180330567Sgordon os_memset(k_pad + ctx->key_len, 0, 181258945Sroberto sizeof(k_pad) - ctx->key_len); 182258945Sroberto for (i = 0; i < sizeof(k_pad); i++) 183258945Sroberto k_pad[i] ^= 0x5c; 184330567Sgordon SHA1Init(&ctx->u.sha1); 185330567Sgordon SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 186258945Sroberto SHA1Update(&ctx->u.sha1, mac, 20); 187330567Sgordon SHA1Final(mac, &ctx->u.sha1); 188330567Sgordon break; 189330567Sgordon } 190330567Sgordon 191280849Scy os_free(ctx); 192258945Sroberto 193280849Scy return 0; 194280849Scy} 195280849Scy 196280849Scy 197330567Sgordonint crypto_global_init(void) 198280849Scy{ 199280849Scy return 0; 200280849Scy} 201330567Sgordon 202280849Scy 203330567Sgordonvoid crypto_global_deinit(void) 204330567Sgordon{ 205280849Scy} 206330567Sgordon