Add SHA256-hash functions to generic crypto_hash_* functions

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2011-11-27 21:00:59 +02:00
parent b32a8d1dfe
commit dcff088df7
5 changed files with 115 additions and 20 deletions

View file

@ -12,6 +12,7 @@ include ../lib.rules
CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
#CFLAGS += -DALL_DH_GROUPS #CFLAGS += -DALL_DH_GROUPS
CFLAGS += -DCONFIG_SHA256
LIB_OBJS= \ LIB_OBJS= \
aes-cbc.o \ aes-cbc.o \

View file

@ -155,7 +155,8 @@ void aes_decrypt_deinit(void *ctx);
enum crypto_hash_alg { enum crypto_hash_alg {
CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1 CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1,
CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256
}; };
struct crypto_hash; struct crypto_hash;

View file

@ -1,6 +1,6 @@
/* /*
* Crypto wrapper for internal crypto implementation * Crypto wrapper for internal crypto implementation
* Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
@ -16,6 +16,7 @@
#include "common.h" #include "common.h"
#include "crypto.h" #include "crypto.h"
#include "sha256_i.h"
#include "sha1_i.h" #include "sha1_i.h"
#include "md5_i.h" #include "md5_i.h"
@ -24,6 +25,9 @@ struct crypto_hash {
union { union {
struct MD5Context md5; struct MD5Context md5;
struct SHA1Context sha1; struct SHA1Context sha1;
#ifdef CONFIG_SHA256
struct sha256_state sha256;
#endif /* CONFIG_SHA256 */
} u; } u;
u8 key[64]; u8 key[64];
size_t key_len; size_t key_len;
@ -35,7 +39,7 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
{ {
struct crypto_hash *ctx; struct crypto_hash *ctx;
u8 k_pad[64]; u8 k_pad[64];
u8 tk[20]; u8 tk[32];
size_t i; size_t i;
ctx = os_zalloc(sizeof(*ctx)); ctx = os_zalloc(sizeof(*ctx));
@ -51,6 +55,11 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
case CRYPTO_HASH_ALG_SHA1: case CRYPTO_HASH_ALG_SHA1:
SHA1Init(&ctx->u.sha1); SHA1Init(&ctx->u.sha1);
break; break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_SHA256:
sha256_init(&ctx->u.sha256);
break;
#endif /* CONFIG_SHA256 */
case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_MD5:
if (key_len > sizeof(k_pad)) { if (key_len > sizeof(k_pad)) {
MD5Init(&ctx->u.md5); MD5Init(&ctx->u.md5);
@ -89,6 +98,27 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
SHA1Init(&ctx->u.sha1); SHA1Init(&ctx->u.sha1);
SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
break; break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_HMAC_SHA256:
if (key_len > sizeof(k_pad)) {
sha256_init(&ctx->u.sha256);
sha256_process(&ctx->u.sha256, key, key_len);
sha256_done(&ctx->u.sha256, tk);
key = tk;
key_len = 32;
}
os_memcpy(ctx->key, key, key_len);
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
if (key_len < sizeof(k_pad))
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
sha256_init(&ctx->u.sha256);
sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
break;
#endif /* CONFIG_SHA256 */
default: default:
os_free(ctx); os_free(ctx);
return NULL; return NULL;
@ -112,6 +142,14 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
case CRYPTO_HASH_ALG_HMAC_SHA1: case CRYPTO_HASH_ALG_HMAC_SHA1:
SHA1Update(&ctx->u.sha1, data, len); SHA1Update(&ctx->u.sha1, data, len);
break; break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_SHA256:
case CRYPTO_HASH_ALG_HMAC_SHA256:
sha256_process(&ctx->u.sha256, data, len);
break;
#endif /* CONFIG_SHA256 */
default:
break;
} }
} }
@ -148,6 +186,17 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
*len = 20; *len = 20;
SHA1Final(mac, &ctx->u.sha1); SHA1Final(mac, &ctx->u.sha1);
break; break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_SHA256:
if (*len < 32) {
*len = 32;
os_free(ctx);
return -1;
}
*len = 32;
sha256_done(&ctx->u.sha256, mac);
break;
#endif /* CONFIG_SHA256 */
case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_MD5:
if (*len < 16) { if (*len < 16) {
*len = 16; *len = 16;
@ -188,6 +237,31 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
SHA1Update(&ctx->u.sha1, mac, 20); SHA1Update(&ctx->u.sha1, mac, 20);
SHA1Final(mac, &ctx->u.sha1); SHA1Final(mac, &ctx->u.sha1);
break; break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_HMAC_SHA256:
if (*len < 32) {
*len = 32;
os_free(ctx);
return -1;
}
*len = 32;
sha256_done(&ctx->u.sha256, mac);
os_memcpy(k_pad, ctx->key, ctx->key_len);
os_memset(k_pad + ctx->key_len, 0,
sizeof(k_pad) - ctx->key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x5c;
sha256_init(&ctx->u.sha256);
sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
sha256_process(&ctx->u.sha256, mac, 32);
sha256_done(&ctx->u.sha256, mac);
break;
#endif /* CONFIG_SHA256 */
default:
os_free(ctx);
return -1;
} }
os_free(ctx); os_free(ctx);

View file

@ -16,21 +16,9 @@
#include "common.h" #include "common.h"
#include "sha256.h" #include "sha256.h"
#include "sha256_i.h"
#include "crypto.h" #include "crypto.h"
#define SHA256_BLOCK_SIZE 64
struct sha256_state {
u64 length;
u32 state[8], curlen;
u8 buf[SHA256_BLOCK_SIZE];
};
static void sha256_init(struct sha256_state *md);
static int sha256_process(struct sha256_state *md, const unsigned char *in,
unsigned long inlen);
static int sha256_done(struct sha256_state *md, unsigned char *out);
/** /**
* sha256_vector - SHA256 hash for data vector * sha256_vector - SHA256 hash for data vector
@ -139,7 +127,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf)
/* Initialize the hash state */ /* Initialize the hash state */
static void sha256_init(struct sha256_state *md) void sha256_init(struct sha256_state *md)
{ {
md->curlen = 0; md->curlen = 0;
md->length = 0; md->length = 0;
@ -160,8 +148,8 @@ static void sha256_init(struct sha256_state *md)
@param inlen The length of the data (octets) @param inlen The length of the data (octets)
@return CRYPT_OK if successful @return CRYPT_OK if successful
*/ */
static int sha256_process(struct sha256_state *md, const unsigned char *in, int sha256_process(struct sha256_state *md, const unsigned char *in,
unsigned long inlen) unsigned long inlen)
{ {
unsigned long n; unsigned long n;
@ -200,7 +188,7 @@ static int sha256_process(struct sha256_state *md, const unsigned char *in,
@param out [out] The destination of the hash (32 bytes) @param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful @return CRYPT_OK if successful
*/ */
static int sha256_done(struct sha256_state *md, unsigned char *out) int sha256_done(struct sha256_state *md, unsigned char *out)
{ {
int i; int i;

31
src/crypto/sha256_i.h Normal file
View file

@ -0,0 +1,31 @@
/*
* SHA-256 internal definitions
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef SHA256_I_H
#define SHA256_I_H
#define SHA256_BLOCK_SIZE 64
struct sha256_state {
u64 length;
u32 state[8], curlen;
u8 buf[SHA256_BLOCK_SIZE];
};
void sha256_init(struct sha256_state *md);
int sha256_process(struct sha256_state *md, const unsigned char *in,
unsigned long inlen);
int sha256_done(struct sha256_state *md, unsigned char *out);
#endif /* SHA256_I_H */