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