1/* 2 * Crypto wrapper for internal crypto implementation 3 * Copyright (c) 2006-2011, Jouni Malinen <j@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 17struct 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 31struct 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 125void 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 151int 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 267int crypto_global_init(void) 268{ 269 return 0; 270} 271 272 273void crypto_global_deinit(void) 274{ 275} 276