1/* 2 * WPA Supplicant / wrapper functions for libgcrypt 3 * Copyright (c) 2004-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#include <gcrypt.h> 17 18#include "common.h" 19#include "crypto.h" 20 21void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 22{ 23 gcry_md_hd_t hd; 24 unsigned char *p; 25 size_t i; 26 27 if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) 28 return; 29 for (i = 0; i < num_elem; i++) 30 gcry_md_write(hd, addr[i], len[i]); 31 p = gcry_md_read(hd, GCRY_MD_MD4); 32 if (p) 33 memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); 34 gcry_md_close(hd); 35} 36 37 38void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 39{ 40 gcry_cipher_hd_t hd; 41 u8 pkey[8], next, tmp; 42 int i; 43 44 /* Add parity bits to the key */ 45 next = 0; 46 for (i = 0; i < 7; i++) { 47 tmp = key[i]; 48 pkey[i] = (tmp >> i) | next | 1; 49 next = tmp << (7 - i); 50 } 51 pkey[i] = next | 1; 52 53 gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 54 gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); 55 gcry_cipher_encrypt(hd, cypher, 8, clear, 8); 56 gcry_cipher_close(hd); 57} 58 59 60void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 61{ 62 gcry_md_hd_t hd; 63 unsigned char *p; 64 size_t i; 65 66 if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) 67 return; 68 for (i = 0; i < num_elem; i++) 69 gcry_md_write(hd, addr[i], len[i]); 70 p = gcry_md_read(hd, GCRY_MD_MD5); 71 if (p) 72 memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); 73 gcry_md_close(hd); 74} 75 76 77void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 78{ 79 gcry_md_hd_t hd; 80 unsigned char *p; 81 size_t i; 82 83 if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) 84 return; 85 for (i = 0; i < num_elem; i++) 86 gcry_md_write(hd, addr[i], len[i]); 87 p = gcry_md_read(hd, GCRY_MD_SHA1); 88 if (p) 89 memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); 90 gcry_md_close(hd); 91} 92 93 94#ifndef CONFIG_NO_FIPS186_2_PRF 95int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) 96{ 97 /* FIX: how to do this with libgcrypt? */ 98 return -1; 99} 100#endif /* CONFIG_NO_FIPS186_2_PRF */ 101 102 103void * aes_encrypt_init(const u8 *key, size_t len) 104{ 105 gcry_cipher_hd_t hd; 106 107 if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 108 GPG_ERR_NO_ERROR) { 109 printf("cipher open failed\n"); 110 return NULL; 111 } 112 if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 113 printf("setkey failed\n"); 114 gcry_cipher_close(hd); 115 return NULL; 116 } 117 118 return hd; 119} 120 121 122void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 123{ 124 gcry_cipher_hd_t hd = ctx; 125 gcry_cipher_encrypt(hd, crypt, 16, plain, 16); 126} 127 128 129void aes_encrypt_deinit(void *ctx) 130{ 131 gcry_cipher_hd_t hd = ctx; 132 gcry_cipher_close(hd); 133} 134 135 136void * aes_decrypt_init(const u8 *key, size_t len) 137{ 138 gcry_cipher_hd_t hd; 139 140 if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 141 GPG_ERR_NO_ERROR) 142 return NULL; 143 if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 144 gcry_cipher_close(hd); 145 return NULL; 146 } 147 148 return hd; 149} 150 151 152void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 153{ 154 gcry_cipher_hd_t hd = ctx; 155 gcry_cipher_decrypt(hd, plain, 16, crypt, 16); 156} 157 158 159void aes_decrypt_deinit(void *ctx) 160{ 161 gcry_cipher_hd_t hd = ctx; 162 gcry_cipher_close(hd); 163} 164 165 166int crypto_mod_exp(const u8 *base, size_t base_len, 167 const u8 *power, size_t power_len, 168 const u8 *modulus, size_t modulus_len, 169 u8 *result, size_t *result_len) 170{ 171 gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, 172 bn_result = NULL; 173 int ret = -1; 174 175 if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != 176 GPG_ERR_NO_ERROR || 177 gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != 178 GPG_ERR_NO_ERROR || 179 gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, 180 NULL) != GPG_ERR_NO_ERROR) 181 goto error; 182 bn_result = gcry_mpi_new(modulus_len * 8); 183 184 gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); 185 186 if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, 187 bn_result) != GPG_ERR_NO_ERROR) 188 goto error; 189 190 ret = 0; 191 192error: 193 gcry_mpi_release(bn_base); 194 gcry_mpi_release(bn_exp); 195 gcry_mpi_release(bn_modulus); 196 gcry_mpi_release(bn_result); 197 return ret; 198} 199 200 201struct crypto_cipher { 202 gcry_cipher_hd_t enc; 203 gcry_cipher_hd_t dec; 204}; 205 206 207struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 208 const u8 *iv, const u8 *key, 209 size_t key_len) 210{ 211 struct crypto_cipher *ctx; 212 gcry_error_t res; 213 enum gcry_cipher_algos a; 214 int ivlen; 215 216 ctx = os_zalloc(sizeof(*ctx)); 217 if (ctx == NULL) 218 return NULL; 219 220 switch (alg) { 221 case CRYPTO_CIPHER_ALG_RC4: 222 a = GCRY_CIPHER_ARCFOUR; 223 res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 224 0); 225 gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); 226 break; 227 case CRYPTO_CIPHER_ALG_AES: 228 if (key_len == 24) 229 a = GCRY_CIPHER_AES192; 230 else if (key_len == 32) 231 a = GCRY_CIPHER_AES256; 232 else 233 a = GCRY_CIPHER_AES; 234 res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 235 gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 236 break; 237 case CRYPTO_CIPHER_ALG_3DES: 238 a = GCRY_CIPHER_3DES; 239 res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 240 gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 241 break; 242 case CRYPTO_CIPHER_ALG_DES: 243 a = GCRY_CIPHER_DES; 244 res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 245 gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 246 break; 247 case CRYPTO_CIPHER_ALG_RC2: 248 if (key_len == 5) 249 a = GCRY_CIPHER_RFC2268_40; 250 else 251 a = GCRY_CIPHER_RFC2268_128; 252 res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 253 gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 254 break; 255 default: 256 os_free(ctx); 257 return NULL; 258 } 259 260 if (res != GPG_ERR_NO_ERROR) { 261 os_free(ctx); 262 return NULL; 263 } 264 265 if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || 266 gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { 267 gcry_cipher_close(ctx->enc); 268 gcry_cipher_close(ctx->dec); 269 os_free(ctx); 270 return NULL; 271 } 272 273 ivlen = gcry_cipher_get_algo_blklen(a); 274 if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || 275 gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { 276 gcry_cipher_close(ctx->enc); 277 gcry_cipher_close(ctx->dec); 278 os_free(ctx); 279 return NULL; 280 } 281 282 return ctx; 283} 284 285 286int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 287 u8 *crypt, size_t len) 288{ 289 if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != 290 GPG_ERR_NO_ERROR) 291 return -1; 292 return 0; 293} 294 295 296int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 297 u8 *plain, size_t len) 298{ 299 if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != 300 GPG_ERR_NO_ERROR) 301 return -1; 302 return 0; 303} 304 305 306void crypto_cipher_deinit(struct crypto_cipher *ctx) 307{ 308 gcry_cipher_close(ctx->enc); 309 gcry_cipher_close(ctx->dec); 310 os_free(ctx); 311} 312