1189251Ssam/* 2189251Ssam * WPA Supplicant / wrapper functions for libgcrypt 3189251Ssam * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam#include <gcrypt.h> 11189251Ssam 12189251Ssam#include "common.h" 13189251Ssam#include "crypto.h" 14189251Ssam 15214734Srpauloint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 16189251Ssam{ 17189251Ssam gcry_md_hd_t hd; 18189251Ssam unsigned char *p; 19189251Ssam size_t i; 20189251Ssam 21189251Ssam if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) 22214734Srpaulo return -1; 23189251Ssam for (i = 0; i < num_elem; i++) 24189251Ssam gcry_md_write(hd, addr[i], len[i]); 25189251Ssam p = gcry_md_read(hd, GCRY_MD_MD4); 26189251Ssam if (p) 27189251Ssam memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); 28189251Ssam gcry_md_close(hd); 29214734Srpaulo return 0; 30189251Ssam} 31189251Ssam 32189251Ssam 33189251Ssamvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 34189251Ssam{ 35189251Ssam gcry_cipher_hd_t hd; 36189251Ssam u8 pkey[8], next, tmp; 37189251Ssam int i; 38189251Ssam 39189251Ssam /* Add parity bits to the key */ 40189251Ssam next = 0; 41189251Ssam for (i = 0; i < 7; i++) { 42189251Ssam tmp = key[i]; 43189251Ssam pkey[i] = (tmp >> i) | next | 1; 44189251Ssam next = tmp << (7 - i); 45189251Ssam } 46189251Ssam pkey[i] = next | 1; 47189251Ssam 48189251Ssam gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 49189251Ssam gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); 50189251Ssam gcry_cipher_encrypt(hd, cypher, 8, clear, 8); 51189251Ssam gcry_cipher_close(hd); 52189251Ssam} 53189251Ssam 54189251Ssam 55214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 56189251Ssam{ 57189251Ssam gcry_md_hd_t hd; 58189251Ssam unsigned char *p; 59189251Ssam size_t i; 60189251Ssam 61189251Ssam if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) 62214734Srpaulo return -1; 63189251Ssam for (i = 0; i < num_elem; i++) 64189251Ssam gcry_md_write(hd, addr[i], len[i]); 65189251Ssam p = gcry_md_read(hd, GCRY_MD_MD5); 66189251Ssam if (p) 67189251Ssam memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); 68189251Ssam gcry_md_close(hd); 69214734Srpaulo return 0; 70189251Ssam} 71189251Ssam 72189251Ssam 73214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 74189251Ssam{ 75189251Ssam gcry_md_hd_t hd; 76189251Ssam unsigned char *p; 77189251Ssam size_t i; 78189251Ssam 79189251Ssam if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) 80214734Srpaulo return -1; 81189251Ssam for (i = 0; i < num_elem; i++) 82189251Ssam gcry_md_write(hd, addr[i], len[i]); 83189251Ssam p = gcry_md_read(hd, GCRY_MD_SHA1); 84189251Ssam if (p) 85189251Ssam memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); 86189251Ssam gcry_md_close(hd); 87214734Srpaulo return 0; 88189251Ssam} 89189251Ssam 90189251Ssam 91189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len) 92189251Ssam{ 93189251Ssam gcry_cipher_hd_t hd; 94189251Ssam 95189251Ssam if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 96189251Ssam GPG_ERR_NO_ERROR) { 97189251Ssam printf("cipher open failed\n"); 98189251Ssam return NULL; 99189251Ssam } 100189251Ssam if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 101189251Ssam printf("setkey failed\n"); 102189251Ssam gcry_cipher_close(hd); 103189251Ssam return NULL; 104189251Ssam } 105189251Ssam 106189251Ssam return hd; 107189251Ssam} 108189251Ssam 109189251Ssam 110189251Ssamvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 111189251Ssam{ 112189251Ssam gcry_cipher_hd_t hd = ctx; 113189251Ssam gcry_cipher_encrypt(hd, crypt, 16, plain, 16); 114189251Ssam} 115189251Ssam 116189251Ssam 117189251Ssamvoid aes_encrypt_deinit(void *ctx) 118189251Ssam{ 119189251Ssam gcry_cipher_hd_t hd = ctx; 120189251Ssam gcry_cipher_close(hd); 121189251Ssam} 122189251Ssam 123189251Ssam 124189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len) 125189251Ssam{ 126189251Ssam gcry_cipher_hd_t hd; 127189251Ssam 128189251Ssam if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 129189251Ssam GPG_ERR_NO_ERROR) 130189251Ssam return NULL; 131189251Ssam if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 132189251Ssam gcry_cipher_close(hd); 133189251Ssam return NULL; 134189251Ssam } 135189251Ssam 136189251Ssam return hd; 137189251Ssam} 138189251Ssam 139189251Ssam 140189251Ssamvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 141189251Ssam{ 142189251Ssam gcry_cipher_hd_t hd = ctx; 143189251Ssam gcry_cipher_decrypt(hd, plain, 16, crypt, 16); 144189251Ssam} 145189251Ssam 146189251Ssam 147189251Ssamvoid aes_decrypt_deinit(void *ctx) 148189251Ssam{ 149189251Ssam gcry_cipher_hd_t hd = ctx; 150189251Ssam gcry_cipher_close(hd); 151189251Ssam} 152189251Ssam 153189251Ssam 154189251Ssamint crypto_mod_exp(const u8 *base, size_t base_len, 155189251Ssam const u8 *power, size_t power_len, 156189251Ssam const u8 *modulus, size_t modulus_len, 157189251Ssam u8 *result, size_t *result_len) 158189251Ssam{ 159189251Ssam gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, 160189251Ssam bn_result = NULL; 161189251Ssam int ret = -1; 162189251Ssam 163189251Ssam if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != 164189251Ssam GPG_ERR_NO_ERROR || 165189251Ssam gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != 166189251Ssam GPG_ERR_NO_ERROR || 167189251Ssam gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, 168189251Ssam NULL) != GPG_ERR_NO_ERROR) 169189251Ssam goto error; 170189251Ssam bn_result = gcry_mpi_new(modulus_len * 8); 171189251Ssam 172189251Ssam gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); 173189251Ssam 174189251Ssam if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, 175189251Ssam bn_result) != GPG_ERR_NO_ERROR) 176189251Ssam goto error; 177189251Ssam 178189251Ssam ret = 0; 179189251Ssam 180189251Ssamerror: 181189251Ssam gcry_mpi_release(bn_base); 182189251Ssam gcry_mpi_release(bn_exp); 183189251Ssam gcry_mpi_release(bn_modulus); 184189251Ssam gcry_mpi_release(bn_result); 185189251Ssam return ret; 186189251Ssam} 187189251Ssam 188189251Ssam 189189251Ssamstruct crypto_cipher { 190189251Ssam gcry_cipher_hd_t enc; 191189251Ssam gcry_cipher_hd_t dec; 192189251Ssam}; 193189251Ssam 194189251Ssam 195189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 196189251Ssam const u8 *iv, const u8 *key, 197189251Ssam size_t key_len) 198189251Ssam{ 199189251Ssam struct crypto_cipher *ctx; 200189251Ssam gcry_error_t res; 201189251Ssam enum gcry_cipher_algos a; 202189251Ssam int ivlen; 203189251Ssam 204189251Ssam ctx = os_zalloc(sizeof(*ctx)); 205189251Ssam if (ctx == NULL) 206189251Ssam return NULL; 207189251Ssam 208189251Ssam switch (alg) { 209189251Ssam case CRYPTO_CIPHER_ALG_RC4: 210189251Ssam a = GCRY_CIPHER_ARCFOUR; 211189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 212189251Ssam 0); 213189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); 214189251Ssam break; 215189251Ssam case CRYPTO_CIPHER_ALG_AES: 216189251Ssam if (key_len == 24) 217189251Ssam a = GCRY_CIPHER_AES192; 218189251Ssam else if (key_len == 32) 219189251Ssam a = GCRY_CIPHER_AES256; 220189251Ssam else 221189251Ssam a = GCRY_CIPHER_AES; 222189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 223189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 224189251Ssam break; 225189251Ssam case CRYPTO_CIPHER_ALG_3DES: 226189251Ssam a = GCRY_CIPHER_3DES; 227189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 228189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 229189251Ssam break; 230189251Ssam case CRYPTO_CIPHER_ALG_DES: 231189251Ssam a = GCRY_CIPHER_DES; 232189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 233189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 234189251Ssam break; 235189251Ssam case CRYPTO_CIPHER_ALG_RC2: 236189251Ssam if (key_len == 5) 237189251Ssam a = GCRY_CIPHER_RFC2268_40; 238189251Ssam else 239189251Ssam a = GCRY_CIPHER_RFC2268_128; 240189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 241189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 242189251Ssam break; 243189251Ssam default: 244189251Ssam os_free(ctx); 245189251Ssam return NULL; 246189251Ssam } 247189251Ssam 248189251Ssam if (res != GPG_ERR_NO_ERROR) { 249189251Ssam os_free(ctx); 250189251Ssam return NULL; 251189251Ssam } 252189251Ssam 253189251Ssam if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || 254189251Ssam gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { 255189251Ssam gcry_cipher_close(ctx->enc); 256189251Ssam gcry_cipher_close(ctx->dec); 257189251Ssam os_free(ctx); 258189251Ssam return NULL; 259189251Ssam } 260189251Ssam 261189251Ssam ivlen = gcry_cipher_get_algo_blklen(a); 262189251Ssam if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || 263189251Ssam gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { 264189251Ssam gcry_cipher_close(ctx->enc); 265189251Ssam gcry_cipher_close(ctx->dec); 266189251Ssam os_free(ctx); 267189251Ssam return NULL; 268189251Ssam } 269189251Ssam 270189251Ssam return ctx; 271189251Ssam} 272189251Ssam 273189251Ssam 274189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 275189251Ssam u8 *crypt, size_t len) 276189251Ssam{ 277189251Ssam if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != 278189251Ssam GPG_ERR_NO_ERROR) 279189251Ssam return -1; 280189251Ssam return 0; 281189251Ssam} 282189251Ssam 283189251Ssam 284189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 285189251Ssam u8 *plain, size_t len) 286189251Ssam{ 287189251Ssam if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != 288189251Ssam GPG_ERR_NO_ERROR) 289189251Ssam return -1; 290189251Ssam return 0; 291189251Ssam} 292189251Ssam 293189251Ssam 294189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 295189251Ssam{ 296189251Ssam gcry_cipher_close(ctx->enc); 297189251Ssam gcry_cipher_close(ctx->dec); 298189251Ssam os_free(ctx); 299189251Ssam} 300