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