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 "sha384_i.h"
     15 #include "sha512_i.h"
     16 #include "sha1_i.h"
     17 #include "md5_i.h"
     18 
     19 struct crypto_hash {
     20 	enum crypto_hash_alg alg;
     21 	union {
     22 		struct MD5Context md5;
     23 		struct SHA1Context sha1;
     24 #ifdef CONFIG_SHA256
     25 		struct sha256_state sha256;
     26 #endif /* CONFIG_SHA256 */
     27 #ifdef CONFIG_INTERNAL_SHA384
     28 		struct sha384_state sha384;
     29 #endif /* CONFIG_INTERNAL_SHA384 */
     30 #ifdef CONFIG_INTERNAL_SHA512
     31 		struct sha512_state sha512;
     32 #endif /* CONFIG_INTERNAL_SHA512 */
     33 	} u;
     34 	u8 key[64];
     35 	size_t key_len;
     36 };
     37 
     38 
     39 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
     40 				      size_t key_len)
     41 {
     42 	struct crypto_hash *ctx;
     43 	u8 k_pad[64];
     44 	u8 tk[32];
     45 	size_t i;
     46 
     47 	ctx = os_zalloc(sizeof(*ctx));
     48 	if (ctx == NULL)
     49 		return NULL;
     50 
     51 	ctx->alg = alg;
     52 
     53 	switch (alg) {
     54 	case CRYPTO_HASH_ALG_MD5:
     55 		MD5Init(&ctx->u.md5);
     56 		break;
     57 	case CRYPTO_HASH_ALG_SHA1:
     58 		SHA1Init(&ctx->u.sha1);
     59 		break;
     60 #ifdef CONFIG_SHA256
     61 	case CRYPTO_HASH_ALG_SHA256:
     62 		sha256_init(&ctx->u.sha256);
     63 		break;
     64 #endif /* CONFIG_SHA256 */
     65 #ifdef CONFIG_INTERNAL_SHA384
     66 	case CRYPTO_HASH_ALG_SHA384:
     67 		sha384_init(&ctx->u.sha384);
     68 		break;
     69 #endif /* CONFIG_INTERNAL_SHA384 */
     70 #ifdef CONFIG_INTERNAL_SHA512
     71 	case CRYPTO_HASH_ALG_SHA512:
     72 		sha512_init(&ctx->u.sha512);
     73 		break;
     74 #endif /* CONFIG_INTERNAL_SHA512 */
     75 	case CRYPTO_HASH_ALG_HMAC_MD5:
     76 		if (key_len > sizeof(k_pad)) {
     77 			MD5Init(&ctx->u.md5);
     78 			MD5Update(&ctx->u.md5, key, key_len);
     79 			MD5Final(tk, &ctx->u.md5);
     80 			key = tk;
     81 			key_len = 16;
     82 		}
     83 		os_memcpy(ctx->key, key, key_len);
     84 		ctx->key_len = key_len;
     85 
     86 		os_memcpy(k_pad, key, key_len);
     87 		if (key_len < sizeof(k_pad))
     88 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
     89 		for (i = 0; i < sizeof(k_pad); i++)
     90 			k_pad[i] ^= 0x36;
     91 		MD5Init(&ctx->u.md5);
     92 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
     93 		break;
     94 	case CRYPTO_HASH_ALG_HMAC_SHA1:
     95 		if (key_len > sizeof(k_pad)) {
     96 			SHA1Init(&ctx->u.sha1);
     97 			SHA1Update(&ctx->u.sha1, key, key_len);
     98 			SHA1Final(tk, &ctx->u.sha1);
     99 			key = tk;
    100 			key_len = 20;
    101 		}
    102 		os_memcpy(ctx->key, key, key_len);
    103 		ctx->key_len = key_len;
    104 
    105 		os_memcpy(k_pad, key, key_len);
    106 		if (key_len < sizeof(k_pad))
    107 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
    108 		for (i = 0; i < sizeof(k_pad); i++)
    109 			k_pad[i] ^= 0x36;
    110 		SHA1Init(&ctx->u.sha1);
    111 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
    112 		break;
    113 #ifdef CONFIG_SHA256
    114 	case CRYPTO_HASH_ALG_HMAC_SHA256:
    115 		if (key_len > sizeof(k_pad)) {
    116 			sha256_init(&ctx->u.sha256);
    117 			sha256_process(&ctx->u.sha256, key, key_len);
    118 			sha256_done(&ctx->u.sha256, tk);
    119 			key = tk;
    120 			key_len = 32;
    121 		}
    122 		os_memcpy(ctx->key, key, key_len);
    123 		ctx->key_len = key_len;
    124 
    125 		os_memcpy(k_pad, key, key_len);
    126 		if (key_len < sizeof(k_pad))
    127 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
    128 		for (i = 0; i < sizeof(k_pad); i++)
    129 			k_pad[i] ^= 0x36;
    130 		sha256_init(&ctx->u.sha256);
    131 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
    132 		break;
    133 #endif /* CONFIG_SHA256 */
    134 	default:
    135 		os_free(ctx);
    136 		return NULL;
    137 	}
    138 
    139 	return ctx;
    140 }
    141 
    142 
    143 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
    144 {
    145 	if (ctx == NULL)
    146 		return;
    147 
    148 	switch (ctx->alg) {
    149 	case CRYPTO_HASH_ALG_MD5:
    150 	case CRYPTO_HASH_ALG_HMAC_MD5:
    151 		MD5Update(&ctx->u.md5, data, len);
    152 		break;
    153 	case CRYPTO_HASH_ALG_SHA1:
    154 	case CRYPTO_HASH_ALG_HMAC_SHA1:
    155 		SHA1Update(&ctx->u.sha1, data, len);
    156 		break;
    157 #ifdef CONFIG_SHA256
    158 	case CRYPTO_HASH_ALG_SHA256:
    159 	case CRYPTO_HASH_ALG_HMAC_SHA256:
    160 		sha256_process(&ctx->u.sha256, data, len);
    161 		break;
    162 #endif /* CONFIG_SHA256 */
    163 #ifdef CONFIG_INTERNAL_SHA384
    164 	case CRYPTO_HASH_ALG_SHA384:
    165 		sha384_process(&ctx->u.sha384, data, len);
    166 		break;
    167 #endif /* CONFIG_INTERNAL_SHA384 */
    168 #ifdef CONFIG_INTERNAL_SHA512
    169 	case CRYPTO_HASH_ALG_SHA512:
    170 		sha512_process(&ctx->u.sha512, data, len);
    171 		break;
    172 #endif /* CONFIG_INTERNAL_SHA512 */
    173 	default:
    174 		break;
    175 	}
    176 }
    177 
    178 
    179 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
    180 {
    181 	u8 k_pad[64];
    182 	size_t i;
    183 
    184 	if (ctx == NULL)
    185 		return -2;
    186 
    187 	if (mac == NULL || len == NULL) {
    188 		os_free(ctx);
    189 		return 0;
    190 	}
    191 
    192 	switch (ctx->alg) {
    193 	case CRYPTO_HASH_ALG_MD5:
    194 		if (*len < 16) {
    195 			*len = 16;
    196 			os_free(ctx);
    197 			return -1;
    198 		}
    199 		*len = 16;
    200 		MD5Final(mac, &ctx->u.md5);
    201 		break;
    202 	case CRYPTO_HASH_ALG_SHA1:
    203 		if (*len < 20) {
    204 			*len = 20;
    205 			os_free(ctx);
    206 			return -1;
    207 		}
    208 		*len = 20;
    209 		SHA1Final(mac, &ctx->u.sha1);
    210 		break;
    211 #ifdef CONFIG_SHA256
    212 	case CRYPTO_HASH_ALG_SHA256:
    213 		if (*len < 32) {
    214 			*len = 32;
    215 			os_free(ctx);
    216 			return -1;
    217 		}
    218 		*len = 32;
    219 		sha256_done(&ctx->u.sha256, mac);
    220 		break;
    221 #endif /* CONFIG_SHA256 */
    222 #ifdef CONFIG_INTERNAL_SHA384
    223 	case CRYPTO_HASH_ALG_SHA384:
    224 		if (*len < 48) {
    225 			*len = 48;
    226 			os_free(ctx);
    227 			return -1;
    228 		}
    229 		*len = 48;
    230 		sha384_done(&ctx->u.sha384, mac);
    231 		break;
    232 #endif /* CONFIG_INTERNAL_SHA384 */
    233 #ifdef CONFIG_INTERNAL_SHA512
    234 	case CRYPTO_HASH_ALG_SHA512:
    235 		if (*len < 64) {
    236 			*len = 64;
    237 			os_free(ctx);
    238 			return -1;
    239 		}
    240 		*len = 64;
    241 		sha512_done(&ctx->u.sha512, mac);
    242 		break;
    243 #endif /* CONFIG_INTERNAL_SHA512 */
    244 	case CRYPTO_HASH_ALG_HMAC_MD5:
    245 		if (*len < 16) {
    246 			*len = 16;
    247 			os_free(ctx);
    248 			return -1;
    249 		}
    250 		*len = 16;
    251 
    252 		MD5Final(mac, &ctx->u.md5);
    253 
    254 		os_memcpy(k_pad, ctx->key, ctx->key_len);
    255 		os_memset(k_pad + ctx->key_len, 0,
    256 			  sizeof(k_pad) - ctx->key_len);
    257 		for (i = 0; i < sizeof(k_pad); i++)
    258 			k_pad[i] ^= 0x5c;
    259 		MD5Init(&ctx->u.md5);
    260 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
    261 		MD5Update(&ctx->u.md5, mac, 16);
    262 		MD5Final(mac, &ctx->u.md5);
    263 		break;
    264 	case CRYPTO_HASH_ALG_HMAC_SHA1:
    265 		if (*len < 20) {
    266 			*len = 20;
    267 			os_free(ctx);
    268 			return -1;
    269 		}
    270 		*len = 20;
    271 
    272 		SHA1Final(mac, &ctx->u.sha1);
    273 
    274 		os_memcpy(k_pad, ctx->key, ctx->key_len);
    275 		os_memset(k_pad + ctx->key_len, 0,
    276 			  sizeof(k_pad) - ctx->key_len);
    277 		for (i = 0; i < sizeof(k_pad); i++)
    278 			k_pad[i] ^= 0x5c;
    279 		SHA1Init(&ctx->u.sha1);
    280 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
    281 		SHA1Update(&ctx->u.sha1, mac, 20);
    282 		SHA1Final(mac, &ctx->u.sha1);
    283 		break;
    284 #ifdef CONFIG_SHA256
    285 	case CRYPTO_HASH_ALG_HMAC_SHA256:
    286 		if (*len < 32) {
    287 			*len = 32;
    288 			os_free(ctx);
    289 			return -1;
    290 		}
    291 		*len = 32;
    292 
    293 		sha256_done(&ctx->u.sha256, mac);
    294 
    295 		os_memcpy(k_pad, ctx->key, ctx->key_len);
    296 		os_memset(k_pad + ctx->key_len, 0,
    297 			  sizeof(k_pad) - ctx->key_len);
    298 		for (i = 0; i < sizeof(k_pad); i++)
    299 			k_pad[i] ^= 0x5c;
    300 		sha256_init(&ctx->u.sha256);
    301 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
    302 		sha256_process(&ctx->u.sha256, mac, 32);
    303 		sha256_done(&ctx->u.sha256, mac);
    304 		break;
    305 #endif /* CONFIG_SHA256 */
    306 	default:
    307 		os_free(ctx);
    308 		return -1;
    309 	}
    310 
    311 	os_free(ctx);
    312 
    313 	return 0;
    314 }
    315 
    316 
    317 int crypto_global_init(void)
    318 {
    319 	return 0;
    320 }
    321 
    322 
    323 void crypto_global_deinit(void)
    324 {
    325 }
    326