Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Crypto wrapper for internal crypto implementation
      3  * Copyright (c) 2006-2011, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "crypto.h"
     13 #include "sha256_i.h"
     14 #include "sha1_i.h"
     15 #include "md5_i.h"
     16 
     17 struct crypto_hash {
     18 	enum crypto_hash_alg alg;
     19 	union {
     20 		struct MD5Context md5;
     21 		struct SHA1Context sha1;
     22 #ifdef CONFIG_SHA256
     23 		struct sha256_state sha256;
     24 #endif /* CONFIG_SHA256 */
     25 	} u;
     26 	u8 key[64];
     27 	size_t key_len;
     28 };
     29 
     30 
     31 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
     32 				      size_t key_len)
     33 {
     34 	struct crypto_hash *ctx;
     35 	u8 k_pad[64];
     36 	u8 tk[32];
     37 	size_t i;
     38 
     39 	ctx = os_zalloc(sizeof(*ctx));
     40 	if (ctx == NULL)
     41 		return NULL;
     42 
     43 	ctx->alg = alg;
     44 
     45 	switch (alg) {
     46 	case CRYPTO_HASH_ALG_MD5:
     47 		MD5Init(&ctx->u.md5);
     48 		break;
     49 	case CRYPTO_HASH_ALG_SHA1:
     50 		SHA1Init(&ctx->u.sha1);
     51 		break;
     52 #ifdef CONFIG_SHA256
     53 	case CRYPTO_HASH_ALG_SHA256:
     54 		sha256_init(&ctx->u.sha256);
     55 		break;
     56 #endif /* CONFIG_SHA256 */
     57 	case CRYPTO_HASH_ALG_HMAC_MD5:
     58 		if (key_len > sizeof(k_pad)) {
     59 			MD5Init(&ctx->u.md5);
     60 			MD5Update(&ctx->u.md5, key, key_len);
     61 			MD5Final(tk, &ctx->u.md5);
     62 			key = tk;
     63 			key_len = 16;
     64 		}
     65 		os_memcpy(ctx->key, key, key_len);
     66 		ctx->key_len = key_len;
     67 
     68 		os_memcpy(k_pad, key, key_len);
     69 		if (key_len < sizeof(k_pad))
     70 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
     71 		for (i = 0; i < sizeof(k_pad); i++)
     72 			k_pad[i] ^= 0x36;
     73 		MD5Init(&ctx->u.md5);
     74 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
     75 		break;
     76 	case CRYPTO_HASH_ALG_HMAC_SHA1:
     77 		if (key_len > sizeof(k_pad)) {
     78 			SHA1Init(&ctx->u.sha1);
     79 			SHA1Update(&ctx->u.sha1, key, key_len);
     80 			SHA1Final(tk, &ctx->u.sha1);
     81 			key = tk;
     82 			key_len = 20;
     83 		}
     84 		os_memcpy(ctx->key, key, key_len);
     85 		ctx->key_len = key_len;
     86 
     87 		os_memcpy(k_pad, key, key_len);
     88 		if (key_len < sizeof(k_pad))
     89 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
     90 		for (i = 0; i < sizeof(k_pad); i++)
     91 			k_pad[i] ^= 0x36;
     92 		SHA1Init(&ctx->u.sha1);
     93 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
     94 		break;
     95 #ifdef CONFIG_SHA256
     96 	case CRYPTO_HASH_ALG_HMAC_SHA256:
     97 		if (key_len > sizeof(k_pad)) {
     98 			sha256_init(&ctx->u.sha256);
     99 			sha256_process(&ctx->u.sha256, key, key_len);
    100 			sha256_done(&ctx->u.sha256, tk);
    101 			key = tk;
    102 			key_len = 32;
    103 		}
    104 		os_memcpy(ctx->key, key, key_len);
    105 		ctx->key_len = key_len;
    106 
    107 		os_memcpy(k_pad, key, key_len);
    108 		if (key_len < sizeof(k_pad))
    109 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
    110 		for (i = 0; i < sizeof(k_pad); i++)
    111 			k_pad[i] ^= 0x36;
    112 		sha256_init(&ctx->u.sha256);
    113 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
    114 		break;
    115 #endif /* CONFIG_SHA256 */
    116 	default:
    117 		os_free(ctx);
    118 		return NULL;
    119 	}
    120 
    121 	return ctx;
    122 }
    123 
    124 
    125 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
    126 {
    127 	if (ctx == NULL)
    128 		return;
    129 
    130 	switch (ctx->alg) {
    131 	case CRYPTO_HASH_ALG_MD5:
    132 	case CRYPTO_HASH_ALG_HMAC_MD5:
    133 		MD5Update(&ctx->u.md5, data, len);
    134 		break;
    135 	case CRYPTO_HASH_ALG_SHA1:
    136 	case CRYPTO_HASH_ALG_HMAC_SHA1:
    137 		SHA1Update(&ctx->u.sha1, data, len);
    138 		break;
    139 #ifdef CONFIG_SHA256
    140 	case CRYPTO_HASH_ALG_SHA256:
    141 	case CRYPTO_HASH_ALG_HMAC_SHA256:
    142 		sha256_process(&ctx->u.sha256, data, len);
    143 		break;
    144 #endif /* CONFIG_SHA256 */
    145 	default:
    146 		break;
    147 	}
    148 }
    149 
    150 
    151 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
    152 {
    153 	u8 k_pad[64];
    154 	size_t i;
    155 
    156 	if (ctx == NULL)
    157 		return -2;
    158 
    159 	if (mac == NULL || len == NULL) {
    160 		os_free(ctx);
    161 		return 0;
    162 	}
    163 
    164 	switch (ctx->alg) {
    165 	case CRYPTO_HASH_ALG_MD5:
    166 		if (*len < 16) {
    167 			*len = 16;
    168 			os_free(ctx);
    169 			return -1;
    170 		}
    171 		*len = 16;
    172 		MD5Final(mac, &ctx->u.md5);
    173 		break;
    174 	case CRYPTO_HASH_ALG_SHA1:
    175 		if (*len < 20) {
    176 			*len = 20;
    177 			os_free(ctx);
    178 			return -1;
    179 		}
    180 		*len = 20;
    181 		SHA1Final(mac, &ctx->u.sha1);
    182 		break;
    183 #ifdef CONFIG_SHA256
    184 	case CRYPTO_HASH_ALG_SHA256:
    185 		if (*len < 32) {
    186 			*len = 32;
    187 			os_free(ctx);
    188 			return -1;
    189 		}
    190 		*len = 32;
    191 		sha256_done(&ctx->u.sha256, mac);
    192 		break;
    193 #endif /* CONFIG_SHA256 */
    194 	case CRYPTO_HASH_ALG_HMAC_MD5:
    195 		if (*len < 16) {
    196 			*len = 16;
    197 			os_free(ctx);
    198 			return -1;
    199 		}
    200 		*len = 16;
    201 
    202 		MD5Final(mac, &ctx->u.md5);
    203 
    204 		os_memcpy(k_pad, ctx->key, ctx->key_len);
    205 		os_memset(k_pad + ctx->key_len, 0,
    206 			  sizeof(k_pad) - ctx->key_len);
    207 		for (i = 0; i < sizeof(k_pad); i++)
    208 			k_pad[i] ^= 0x5c;
    209 		MD5Init(&ctx->u.md5);
    210 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
    211 		MD5Update(&ctx->u.md5, mac, 16);
    212 		MD5Final(mac, &ctx->u.md5);
    213 		break;
    214 	case CRYPTO_HASH_ALG_HMAC_SHA1:
    215 		if (*len < 20) {
    216 			*len = 20;
    217 			os_free(ctx);
    218 			return -1;
    219 		}
    220 		*len = 20;
    221 
    222 		SHA1Final(mac, &ctx->u.sha1);
    223 
    224 		os_memcpy(k_pad, ctx->key, ctx->key_len);
    225 		os_memset(k_pad + ctx->key_len, 0,
    226 			  sizeof(k_pad) - ctx->key_len);
    227 		for (i = 0; i < sizeof(k_pad); i++)
    228 			k_pad[i] ^= 0x5c;
    229 		SHA1Init(&ctx->u.sha1);
    230 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
    231 		SHA1Update(&ctx->u.sha1, mac, 20);
    232 		SHA1Final(mac, &ctx->u.sha1);
    233 		break;
    234 #ifdef CONFIG_SHA256
    235 	case CRYPTO_HASH_ALG_HMAC_SHA256:
    236 		if (*len < 32) {
    237 			*len = 32;
    238 			os_free(ctx);
    239 			return -1;
    240 		}
    241 		*len = 32;
    242 
    243 		sha256_done(&ctx->u.sha256, mac);
    244 
    245 		os_memcpy(k_pad, ctx->key, ctx->key_len);
    246 		os_memset(k_pad + ctx->key_len, 0,
    247 			  sizeof(k_pad) - ctx->key_len);
    248 		for (i = 0; i < sizeof(k_pad); i++)
    249 			k_pad[i] ^= 0x5c;
    250 		sha256_init(&ctx->u.sha256);
    251 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
    252 		sha256_process(&ctx->u.sha256, mac, 32);
    253 		sha256_done(&ctx->u.sha256, mac);
    254 		break;
    255 #endif /* CONFIG_SHA256 */
    256 	default:
    257 		os_free(ctx);
    258 		return -1;
    259 	}
    260 
    261 	os_free(ctx);
    262 
    263 	return 0;
    264 }
    265 
    266 
    267 int crypto_global_init(void)
    268 {
    269 	return 0;
    270 }
    271 
    272 
    273 void crypto_global_deinit(void)
    274 {
    275 }
    276