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