crypto_internal.c revision 225736
1239478Sadrian/* 2239478Sadrian * Crypto wrapper for internal crypto implementation 3239478Sadrian * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 4239478Sadrian * 5239478Sadrian * This program is free software; you can redistribute it and/or modify 6239478Sadrian * it under the terms of the GNU General Public License version 2 as 7239478Sadrian * published by the Free Software Foundation. 8239478Sadrian * 9239478Sadrian * Alternatively, this software may be distributed under the terms of BSD 10239478Sadrian * license. 11239478Sadrian * 12239478Sadrian * See README and COPYING for more details. 13239478Sadrian */ 14239478Sadrian 15239478Sadrian#include "includes.h" 16239478Sadrian 17239478Sadrian#include "common.h" 18239478Sadrian#include "crypto.h" 19239478Sadrian#include "sha1_i.h" 20239478Sadrian#include "md5_i.h" 21239478Sadrian 22239478Sadrianstruct crypto_hash { 23239478Sadrian enum crypto_hash_alg alg; 24239478Sadrian union { 25239478Sadrian struct MD5Context md5; 26239478Sadrian struct SHA1Context sha1; 27239478Sadrian } u; 28239478Sadrian u8 key[64]; 29239478Sadrian size_t key_len; 30239478Sadrian}; 31239478Sadrian 32239478Sadrian 33239478Sadrianstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 34239478Sadrian size_t key_len) 35239478Sadrian{ 36239478Sadrian struct crypto_hash *ctx; 37239478Sadrian u8 k_pad[64]; 38239478Sadrian u8 tk[20]; 39239478Sadrian size_t i; 40239478Sadrian 41239478Sadrian ctx = os_zalloc(sizeof(*ctx)); 42239478Sadrian if (ctx == NULL) 43239478Sadrian return NULL; 44239478Sadrian 45239478Sadrian ctx->alg = alg; 46239478Sadrian 47239478Sadrian switch (alg) { 48239478Sadrian case CRYPTO_HASH_ALG_MD5: 49239478Sadrian MD5Init(&ctx->u.md5); 50239478Sadrian break; 51239478Sadrian case CRYPTO_HASH_ALG_SHA1: 52239478Sadrian SHA1Init(&ctx->u.sha1); 53239478Sadrian break; 54239478Sadrian case CRYPTO_HASH_ALG_HMAC_MD5: 55239478Sadrian if (key_len > sizeof(k_pad)) { 56239478Sadrian MD5Init(&ctx->u.md5); 57239478Sadrian MD5Update(&ctx->u.md5, key, key_len); 58239478Sadrian MD5Final(tk, &ctx->u.md5); 59239478Sadrian key = tk; 60239478Sadrian key_len = 16; 61239478Sadrian } 62239478Sadrian os_memcpy(ctx->key, key, key_len); 63239478Sadrian ctx->key_len = key_len; 64239478Sadrian 65239478Sadrian os_memcpy(k_pad, key, key_len); 66239478Sadrian os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 67239478Sadrian for (i = 0; i < sizeof(k_pad); i++) 68239478Sadrian k_pad[i] ^= 0x36; 69239478Sadrian MD5Init(&ctx->u.md5); 70239478Sadrian MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 71239478Sadrian break; 72239478Sadrian case CRYPTO_HASH_ALG_HMAC_SHA1: 73239478Sadrian if (key_len > sizeof(k_pad)) { 74239478Sadrian SHA1Init(&ctx->u.sha1); 75239478Sadrian SHA1Update(&ctx->u.sha1, key, key_len); 76239478Sadrian SHA1Final(tk, &ctx->u.sha1); 77239478Sadrian key = tk; 78239478Sadrian key_len = 20; 79239478Sadrian } 80239478Sadrian os_memcpy(ctx->key, key, key_len); 81239478Sadrian ctx->key_len = key_len; 82239478Sadrian 83239478Sadrian os_memcpy(k_pad, key, key_len); 84239478Sadrian os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 85239478Sadrian for (i = 0; i < sizeof(k_pad); i++) 86239478Sadrian k_pad[i] ^= 0x36; 87239478Sadrian SHA1Init(&ctx->u.sha1); 88239478Sadrian SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 89239478Sadrian break; 90239478Sadrian default: 91239478Sadrian os_free(ctx); 92239478Sadrian return NULL; 93239478Sadrian } 94239478Sadrian 95239478Sadrian return ctx; 96239478Sadrian} 97239478Sadrian 98239478Sadrian 99239478Sadrianvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 100239478Sadrian{ 101239478Sadrian if (ctx == NULL) 102239478Sadrian return; 103239478Sadrian 104239478Sadrian switch (ctx->alg) { 105239478Sadrian case CRYPTO_HASH_ALG_MD5: 106239478Sadrian case CRYPTO_HASH_ALG_HMAC_MD5: 107239478Sadrian MD5Update(&ctx->u.md5, data, len); 108239478Sadrian break; 109239478Sadrian case CRYPTO_HASH_ALG_SHA1: 110239478Sadrian case CRYPTO_HASH_ALG_HMAC_SHA1: 111239478Sadrian SHA1Update(&ctx->u.sha1, data, len); 112239478Sadrian break; 113239478Sadrian } 114239478Sadrian} 115239478Sadrian 116239478Sadrian 117239478Sadrianint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 118239478Sadrian{ 119239478Sadrian u8 k_pad[64]; 120239478Sadrian size_t i; 121239478Sadrian 122239478Sadrian if (ctx == NULL) 123239478Sadrian return -2; 124239478Sadrian 125239478Sadrian if (mac == NULL || len == NULL) { 126239478Sadrian os_free(ctx); 127239478Sadrian return 0; 128239478Sadrian } 129239478Sadrian 130239478Sadrian switch (ctx->alg) { 131239478Sadrian case CRYPTO_HASH_ALG_MD5: 132239478Sadrian if (*len < 16) { 133239478Sadrian *len = 16; 134239478Sadrian os_free(ctx); 135239478Sadrian return -1; 136239478Sadrian } 137239478Sadrian *len = 16; 138239478Sadrian MD5Final(mac, &ctx->u.md5); 139239478Sadrian break; 140239478Sadrian case CRYPTO_HASH_ALG_SHA1: 141239478Sadrian if (*len < 20) { 142239478Sadrian *len = 20; 143239478Sadrian os_free(ctx); 144239478Sadrian return -1; 145239478Sadrian } 146239478Sadrian *len = 20; 147239478Sadrian SHA1Final(mac, &ctx->u.sha1); 148239478Sadrian break; 149239478Sadrian case CRYPTO_HASH_ALG_HMAC_MD5: 150239478Sadrian if (*len < 16) { 151239478Sadrian *len = 16; 152239478Sadrian os_free(ctx); 153239478Sadrian return -1; 154239478Sadrian } 155239478Sadrian *len = 16; 156239478Sadrian 157239478Sadrian MD5Final(mac, &ctx->u.md5); 158239478Sadrian 159239478Sadrian os_memcpy(k_pad, ctx->key, ctx->key_len); 160239478Sadrian os_memset(k_pad + ctx->key_len, 0, 161239478Sadrian sizeof(k_pad) - ctx->key_len); 162239478Sadrian for (i = 0; i < sizeof(k_pad); i++) 163239478Sadrian k_pad[i] ^= 0x5c; 164239478Sadrian MD5Init(&ctx->u.md5); 165239478Sadrian MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 166239478Sadrian MD5Update(&ctx->u.md5, mac, 16); 167239478Sadrian MD5Final(mac, &ctx->u.md5); 168239478Sadrian break; 169239478Sadrian case CRYPTO_HASH_ALG_HMAC_SHA1: 170239478Sadrian if (*len < 20) { 171239478Sadrian *len = 20; 172239478Sadrian os_free(ctx); 173239478Sadrian return -1; 174239478Sadrian } 175239478Sadrian *len = 20; 176239478Sadrian 177239478Sadrian SHA1Final(mac, &ctx->u.sha1); 178239478Sadrian 179239478Sadrian os_memcpy(k_pad, ctx->key, ctx->key_len); 180239478Sadrian os_memset(k_pad + ctx->key_len, 0, 181239478Sadrian sizeof(k_pad) - ctx->key_len); 182239478Sadrian for (i = 0; i < sizeof(k_pad); i++) 183239478Sadrian k_pad[i] ^= 0x5c; 184239478Sadrian SHA1Init(&ctx->u.sha1); 185239478Sadrian SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 186239478Sadrian SHA1Update(&ctx->u.sha1, mac, 20); 187239478Sadrian SHA1Final(mac, &ctx->u.sha1); 188239478Sadrian break; 189239478Sadrian } 190239478Sadrian 191239478Sadrian os_free(ctx); 192239478Sadrian 193239478Sadrian return 0; 194239478Sadrian} 195239478Sadrian 196239478Sadrian 197239478Sadrianint crypto_global_init(void) 198239478Sadrian{ 199239478Sadrian return 0; 200239478Sadrian} 201239478Sadrian 202239478Sadrian 203239478Sadrianvoid crypto_global_deinit(void) 204239478Sadrian{ 205239478Sadrian} 206239478Sadrian