1 /* 2 * Crypto wrapper for internal crypto implementation 3 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "crypto.h" 19 #include "sha1_i.h" 20 #include "md5_i.h" 21 22 struct crypto_hash { 23 enum crypto_hash_alg alg; 24 union { 25 struct MD5Context md5; 26 struct SHA1Context sha1; 27 } u; 28 u8 key[64]; 29 size_t key_len; 30 }; 31 32 33 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 34 size_t key_len) 35 { 36 struct crypto_hash *ctx; 37 u8 k_pad[64]; 38 u8 tk[20]; 39 size_t i; 40 41 ctx = os_zalloc(sizeof(*ctx)); 42 if (ctx == NULL) 43 return NULL; 44 45 ctx->alg = alg; 46 47 switch (alg) { 48 case CRYPTO_HASH_ALG_MD5: 49 MD5Init(&ctx->u.md5); 50 break; 51 case CRYPTO_HASH_ALG_SHA1: 52 SHA1Init(&ctx->u.sha1); 53 break; 54 case CRYPTO_HASH_ALG_HMAC_MD5: 55 if (key_len > sizeof(k_pad)) { 56 MD5Init(&ctx->u.md5); 57 MD5Update(&ctx->u.md5, key, key_len); 58 MD5Final(tk, &ctx->u.md5); 59 key = tk; 60 key_len = 16; 61 } 62 os_memcpy(ctx->key, key, key_len); 63 ctx->key_len = key_len; 64 65 os_memcpy(k_pad, key, key_len); 66 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 67 for (i = 0; i < sizeof(k_pad); i++) 68 k_pad[i] ^= 0x36; 69 MD5Init(&ctx->u.md5); 70 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 71 break; 72 case CRYPTO_HASH_ALG_HMAC_SHA1: 73 if (key_len > sizeof(k_pad)) { 74 SHA1Init(&ctx->u.sha1); 75 SHA1Update(&ctx->u.sha1, key, key_len); 76 SHA1Final(tk, &ctx->u.sha1); 77 key = tk; 78 key_len = 20; 79 } 80 os_memcpy(ctx->key, key, key_len); 81 ctx->key_len = key_len; 82 83 os_memcpy(k_pad, key, key_len); 84 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); 85 for (i = 0; i < sizeof(k_pad); i++) 86 k_pad[i] ^= 0x36; 87 SHA1Init(&ctx->u.sha1); 88 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 89 break; 90 default: 91 os_free(ctx); 92 return NULL; 93 } 94 95 return ctx; 96 } 97 98 99 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 100 { 101 if (ctx == NULL) 102 return; 103 104 switch (ctx->alg) { 105 case CRYPTO_HASH_ALG_MD5: 106 case CRYPTO_HASH_ALG_HMAC_MD5: 107 MD5Update(&ctx->u.md5, data, len); 108 break; 109 case CRYPTO_HASH_ALG_SHA1: 110 case CRYPTO_HASH_ALG_HMAC_SHA1: 111 SHA1Update(&ctx->u.sha1, data, len); 112 break; 113 } 114 } 115 116 117 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 118 { 119 u8 k_pad[64]; 120 size_t i; 121 122 if (ctx == NULL) 123 return -2; 124 125 if (mac == NULL || len == NULL) { 126 os_free(ctx); 127 return 0; 128 } 129 130 switch (ctx->alg) { 131 case CRYPTO_HASH_ALG_MD5: 132 if (*len < 16) { 133 *len = 16; 134 os_free(ctx); 135 return -1; 136 } 137 *len = 16; 138 MD5Final(mac, &ctx->u.md5); 139 break; 140 case CRYPTO_HASH_ALG_SHA1: 141 if (*len < 20) { 142 *len = 20; 143 os_free(ctx); 144 return -1; 145 } 146 *len = 20; 147 SHA1Final(mac, &ctx->u.sha1); 148 break; 149 case CRYPTO_HASH_ALG_HMAC_MD5: 150 if (*len < 16) { 151 *len = 16; 152 os_free(ctx); 153 return -1; 154 } 155 *len = 16; 156 157 MD5Final(mac, &ctx->u.md5); 158 159 os_memcpy(k_pad, ctx->key, ctx->key_len); 160 os_memset(k_pad + ctx->key_len, 0, 161 sizeof(k_pad) - ctx->key_len); 162 for (i = 0; i < sizeof(k_pad); i++) 163 k_pad[i] ^= 0x5c; 164 MD5Init(&ctx->u.md5); 165 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); 166 MD5Update(&ctx->u.md5, mac, 16); 167 MD5Final(mac, &ctx->u.md5); 168 break; 169 case CRYPTO_HASH_ALG_HMAC_SHA1: 170 if (*len < 20) { 171 *len = 20; 172 os_free(ctx); 173 return -1; 174 } 175 *len = 20; 176 177 SHA1Final(mac, &ctx->u.sha1); 178 179 os_memcpy(k_pad, ctx->key, ctx->key_len); 180 os_memset(k_pad + ctx->key_len, 0, 181 sizeof(k_pad) - ctx->key_len); 182 for (i = 0; i < sizeof(k_pad); i++) 183 k_pad[i] ^= 0x5c; 184 SHA1Init(&ctx->u.sha1); 185 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); 186 SHA1Update(&ctx->u.sha1, mac, 20); 187 SHA1Final(mac, &ctx->u.sha1); 188 break; 189 } 190 191 os_free(ctx); 192 193 return 0; 194 } 195 196 197 int crypto_global_init(void) 198 { 199 return 0; 200 } 201 202 203 void crypto_global_deinit(void) 204 { 205 } 206