Home | History | Annotate | Download | only in crypto
      1 /*
      2  * WPA Supplicant / wrapper functions for libgcrypt
      3  * Copyright (c) 2004-2009, Jouni Malinen <j (at) 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 
     21 void 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 
     38 void 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 
     60 void 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 
     77 void 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
     95 int 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 
    103 void * 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 
    122 void 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 
    129 void aes_encrypt_deinit(void *ctx)
    130 {
    131 	gcry_cipher_hd_t hd = ctx;
    132 	gcry_cipher_close(hd);
    133 }
    134 
    135 
    136 void * 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 
    152 void 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 
    159 void aes_decrypt_deinit(void *ctx)
    160 {
    161 	gcry_cipher_hd_t hd = ctx;
    162 	gcry_cipher_close(hd);
    163 }
    164 
    165 
    166 int 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 
    192 error:
    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 
    201 struct crypto_cipher {
    202 	gcry_cipher_hd_t enc;
    203 	gcry_cipher_hd_t dec;
    204 };
    205 
    206 
    207 struct 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 
    286 int 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 
    296 int 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 
    306 void 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