crypto_internal.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Crypto wrapper for internal crypto implementation 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sha1_i.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "md5_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_hash { 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum crypto_hash_alg alg; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union { 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct MD5Context md5; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct SHA1Context sha1; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } u; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key[64]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t key_len; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t key_len) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_hash *ctx; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_pad[64]; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tk[20]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx = os_zalloc(sizeof(*ctx)); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->alg = alg; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_MD5: 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Init(&ctx->u.md5); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_SHA1: 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Init(&ctx->u.sha1); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_HMAC_MD5: 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len > sizeof(k_pad)) { 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Init(&ctx->u.md5); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Update(&ctx->u.md5, key, key_len); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Final(tk, &ctx->u.md5); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = tk; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ctx->key, key, key_len); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->key_len = key_len; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(k_pad, key, key_len); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < sizeof(k_pad); i++) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt k_pad[i] ^= 0x36; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Init(&ctx->u.md5); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_HMAC_SHA1: 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len > sizeof(k_pad)) { 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Init(&ctx->u.sha1); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Update(&ctx->u.sha1, key, key_len); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Final(tk, &ctx->u.sha1); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = tk; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 20; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ctx->key, key, key_len); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->key_len = key_len; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(k_pad, key, key_len); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < sizeof(k_pad); i++) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt k_pad[i] ^= 0x36; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Init(&ctx->u.sha1); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ctx; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ctx->alg) { 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_MD5: 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_HMAC_MD5: 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Update(&ctx->u.md5, data, len); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_SHA1: 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_HMAC_SHA1: 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Update(&ctx->u.sha1, data, len); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_pad[64]; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mac == NULL || len == NULL) { 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ctx->alg) { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_MD5: 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*len < 16) { 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 16; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 16; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Final(mac, &ctx->u.md5); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_SHA1: 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*len < 20) { 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 20; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 20; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Final(mac, &ctx->u.sha1); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_HMAC_MD5: 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*len < 16) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 16; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 16; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Final(mac, &ctx->u.md5); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(k_pad, ctx->key, ctx->key_len); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(k_pad + ctx->key_len, 0, 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(k_pad) - ctx->key_len); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < sizeof(k_pad); i++) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt k_pad[i] ^= 0x5c; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Init(&ctx->u.md5); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Update(&ctx->u.md5, mac, 16); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MD5Final(mac, &ctx->u.md5); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CRYPTO_HASH_ALG_HMAC_SHA1: 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*len < 20) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 20; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = 20; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Final(mac, &ctx->u.sha1); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(k_pad, ctx->key, ctx->key_len); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(k_pad + ctx->key_len, 0, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(k_pad) - ctx->key_len); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < sizeof(k_pad); i++) 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt k_pad[i] ^= 0x5c; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Init(&ctx->u.sha1); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Update(&ctx->u.sha1, mac, 20); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SHA1Final(mac, &ctx->u.sha1); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint crypto_global_init(void) 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid crypto_global_deinit(void) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 206