139beb93cSSam Leffler /* 239beb93cSSam Leffler * WPA Supplicant / wrapper functions for libgcrypt 339beb93cSSam Leffler * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler #include <gcrypt.h> 1739beb93cSSam Leffler 1839beb93cSSam Leffler #include "common.h" 1939beb93cSSam Leffler #include "crypto.h" 2039beb93cSSam Leffler 2139beb93cSSam Leffler void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 2239beb93cSSam Leffler { 2339beb93cSSam Leffler gcry_md_hd_t hd; 2439beb93cSSam Leffler unsigned char *p; 2539beb93cSSam Leffler size_t i; 2639beb93cSSam Leffler 2739beb93cSSam Leffler if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) 2839beb93cSSam Leffler return; 2939beb93cSSam Leffler for (i = 0; i < num_elem; i++) 3039beb93cSSam Leffler gcry_md_write(hd, addr[i], len[i]); 3139beb93cSSam Leffler p = gcry_md_read(hd, GCRY_MD_MD4); 3239beb93cSSam Leffler if (p) 3339beb93cSSam Leffler memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); 3439beb93cSSam Leffler gcry_md_close(hd); 3539beb93cSSam Leffler } 3639beb93cSSam Leffler 3739beb93cSSam Leffler 3839beb93cSSam Leffler void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 3939beb93cSSam Leffler { 4039beb93cSSam Leffler gcry_cipher_hd_t hd; 4139beb93cSSam Leffler u8 pkey[8], next, tmp; 4239beb93cSSam Leffler int i; 4339beb93cSSam Leffler 4439beb93cSSam Leffler /* Add parity bits to the key */ 4539beb93cSSam Leffler next = 0; 4639beb93cSSam Leffler for (i = 0; i < 7; i++) { 4739beb93cSSam Leffler tmp = key[i]; 4839beb93cSSam Leffler pkey[i] = (tmp >> i) | next | 1; 4939beb93cSSam Leffler next = tmp << (7 - i); 5039beb93cSSam Leffler } 5139beb93cSSam Leffler pkey[i] = next | 1; 5239beb93cSSam Leffler 5339beb93cSSam Leffler gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 5439beb93cSSam Leffler gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); 5539beb93cSSam Leffler gcry_cipher_encrypt(hd, cypher, 8, clear, 8); 5639beb93cSSam Leffler gcry_cipher_close(hd); 5739beb93cSSam Leffler } 5839beb93cSSam Leffler 5939beb93cSSam Leffler 6039beb93cSSam Leffler #ifdef EAP_TLS_FUNCS 6139beb93cSSam Leffler void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 6239beb93cSSam Leffler { 6339beb93cSSam Leffler gcry_md_hd_t hd; 6439beb93cSSam Leffler unsigned char *p; 6539beb93cSSam Leffler size_t i; 6639beb93cSSam Leffler 6739beb93cSSam Leffler if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) 6839beb93cSSam Leffler return; 6939beb93cSSam Leffler for (i = 0; i < num_elem; i++) 7039beb93cSSam Leffler gcry_md_write(hd, addr[i], len[i]); 7139beb93cSSam Leffler p = gcry_md_read(hd, GCRY_MD_MD5); 7239beb93cSSam Leffler if (p) 7339beb93cSSam Leffler memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); 7439beb93cSSam Leffler gcry_md_close(hd); 7539beb93cSSam Leffler } 7639beb93cSSam Leffler 7739beb93cSSam Leffler 7839beb93cSSam Leffler void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 7939beb93cSSam Leffler { 8039beb93cSSam Leffler gcry_md_hd_t hd; 8139beb93cSSam Leffler unsigned char *p; 8239beb93cSSam Leffler size_t i; 8339beb93cSSam Leffler 8439beb93cSSam Leffler if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) 8539beb93cSSam Leffler return; 8639beb93cSSam Leffler for (i = 0; i < num_elem; i++) 8739beb93cSSam Leffler gcry_md_write(hd, addr[i], len[i]); 8839beb93cSSam Leffler p = gcry_md_read(hd, GCRY_MD_SHA1); 8939beb93cSSam Leffler if (p) 9039beb93cSSam Leffler memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); 9139beb93cSSam Leffler gcry_md_close(hd); 9239beb93cSSam Leffler } 9339beb93cSSam Leffler 9439beb93cSSam Leffler 9539beb93cSSam Leffler #ifndef CONFIG_NO_FIPS186_2_PRF 9639beb93cSSam Leffler int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) 9739beb93cSSam Leffler { 9839beb93cSSam Leffler /* FIX: how to do this with libgcrypt? */ 9939beb93cSSam Leffler return -1; 10039beb93cSSam Leffler } 10139beb93cSSam Leffler #endif /* CONFIG_NO_FIPS186_2_PRF */ 10239beb93cSSam Leffler 10339beb93cSSam Leffler 10439beb93cSSam Leffler void * aes_encrypt_init(const u8 *key, size_t len) 10539beb93cSSam Leffler { 10639beb93cSSam Leffler gcry_cipher_hd_t hd; 10739beb93cSSam Leffler 10839beb93cSSam Leffler if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 10939beb93cSSam Leffler GPG_ERR_NO_ERROR) { 11039beb93cSSam Leffler printf("cipher open failed\n"); 11139beb93cSSam Leffler return NULL; 11239beb93cSSam Leffler } 11339beb93cSSam Leffler if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 11439beb93cSSam Leffler printf("setkey failed\n"); 11539beb93cSSam Leffler gcry_cipher_close(hd); 11639beb93cSSam Leffler return NULL; 11739beb93cSSam Leffler } 11839beb93cSSam Leffler 11939beb93cSSam Leffler return hd; 12039beb93cSSam Leffler } 12139beb93cSSam Leffler 12239beb93cSSam Leffler 12339beb93cSSam Leffler void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 12439beb93cSSam Leffler { 12539beb93cSSam Leffler gcry_cipher_hd_t hd = ctx; 12639beb93cSSam Leffler gcry_cipher_encrypt(hd, crypt, 16, plain, 16); 12739beb93cSSam Leffler } 12839beb93cSSam Leffler 12939beb93cSSam Leffler 13039beb93cSSam Leffler void aes_encrypt_deinit(void *ctx) 13139beb93cSSam Leffler { 13239beb93cSSam Leffler gcry_cipher_hd_t hd = ctx; 13339beb93cSSam Leffler gcry_cipher_close(hd); 13439beb93cSSam Leffler } 13539beb93cSSam Leffler 13639beb93cSSam Leffler 13739beb93cSSam Leffler void * aes_decrypt_init(const u8 *key, size_t len) 13839beb93cSSam Leffler { 13939beb93cSSam Leffler gcry_cipher_hd_t hd; 14039beb93cSSam Leffler 14139beb93cSSam Leffler if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 14239beb93cSSam Leffler GPG_ERR_NO_ERROR) 14339beb93cSSam Leffler return NULL; 14439beb93cSSam Leffler if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 14539beb93cSSam Leffler gcry_cipher_close(hd); 14639beb93cSSam Leffler return NULL; 14739beb93cSSam Leffler } 14839beb93cSSam Leffler 14939beb93cSSam Leffler return hd; 15039beb93cSSam Leffler } 15139beb93cSSam Leffler 15239beb93cSSam Leffler 15339beb93cSSam Leffler void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 15439beb93cSSam Leffler { 15539beb93cSSam Leffler gcry_cipher_hd_t hd = ctx; 15639beb93cSSam Leffler gcry_cipher_decrypt(hd, plain, 16, crypt, 16); 15739beb93cSSam Leffler } 15839beb93cSSam Leffler 15939beb93cSSam Leffler 16039beb93cSSam Leffler void aes_decrypt_deinit(void *ctx) 16139beb93cSSam Leffler { 16239beb93cSSam Leffler gcry_cipher_hd_t hd = ctx; 16339beb93cSSam Leffler gcry_cipher_close(hd); 16439beb93cSSam Leffler } 16539beb93cSSam Leffler #endif /* EAP_TLS_FUNCS */ 16639beb93cSSam Leffler 16739beb93cSSam Leffler 16839beb93cSSam Leffler int crypto_mod_exp(const u8 *base, size_t base_len, 16939beb93cSSam Leffler const u8 *power, size_t power_len, 17039beb93cSSam Leffler const u8 *modulus, size_t modulus_len, 17139beb93cSSam Leffler u8 *result, size_t *result_len) 17239beb93cSSam Leffler { 17339beb93cSSam Leffler gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, 17439beb93cSSam Leffler bn_result = NULL; 17539beb93cSSam Leffler int ret = -1; 17639beb93cSSam Leffler 17739beb93cSSam Leffler if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != 17839beb93cSSam Leffler GPG_ERR_NO_ERROR || 17939beb93cSSam Leffler gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != 18039beb93cSSam Leffler GPG_ERR_NO_ERROR || 18139beb93cSSam Leffler gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, 18239beb93cSSam Leffler NULL) != GPG_ERR_NO_ERROR) 18339beb93cSSam Leffler goto error; 18439beb93cSSam Leffler bn_result = gcry_mpi_new(modulus_len * 8); 18539beb93cSSam Leffler 18639beb93cSSam Leffler gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); 18739beb93cSSam Leffler 18839beb93cSSam Leffler if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, 18939beb93cSSam Leffler bn_result) != GPG_ERR_NO_ERROR) 19039beb93cSSam Leffler goto error; 19139beb93cSSam Leffler 19239beb93cSSam Leffler ret = 0; 19339beb93cSSam Leffler 19439beb93cSSam Leffler error: 19539beb93cSSam Leffler gcry_mpi_release(bn_base); 19639beb93cSSam Leffler gcry_mpi_release(bn_exp); 19739beb93cSSam Leffler gcry_mpi_release(bn_modulus); 19839beb93cSSam Leffler gcry_mpi_release(bn_result); 19939beb93cSSam Leffler return ret; 20039beb93cSSam Leffler } 20139beb93cSSam Leffler 20239beb93cSSam Leffler 20339beb93cSSam Leffler struct crypto_cipher { 20439beb93cSSam Leffler gcry_cipher_hd_t enc; 20539beb93cSSam Leffler gcry_cipher_hd_t dec; 20639beb93cSSam Leffler }; 20739beb93cSSam Leffler 20839beb93cSSam Leffler 20939beb93cSSam Leffler struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 21039beb93cSSam Leffler const u8 *iv, const u8 *key, 21139beb93cSSam Leffler size_t key_len) 21239beb93cSSam Leffler { 21339beb93cSSam Leffler struct crypto_cipher *ctx; 21439beb93cSSam Leffler gcry_error_t res; 21539beb93cSSam Leffler enum gcry_cipher_algos a; 21639beb93cSSam Leffler int ivlen; 21739beb93cSSam Leffler 21839beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 21939beb93cSSam Leffler if (ctx == NULL) 22039beb93cSSam Leffler return NULL; 22139beb93cSSam Leffler 22239beb93cSSam Leffler switch (alg) { 22339beb93cSSam Leffler case CRYPTO_CIPHER_ALG_RC4: 22439beb93cSSam Leffler a = GCRY_CIPHER_ARCFOUR; 22539beb93cSSam Leffler res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 22639beb93cSSam Leffler 0); 22739beb93cSSam Leffler gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); 22839beb93cSSam Leffler break; 22939beb93cSSam Leffler case CRYPTO_CIPHER_ALG_AES: 23039beb93cSSam Leffler if (key_len == 24) 23139beb93cSSam Leffler a = GCRY_CIPHER_AES192; 23239beb93cSSam Leffler else if (key_len == 32) 23339beb93cSSam Leffler a = GCRY_CIPHER_AES256; 23439beb93cSSam Leffler else 23539beb93cSSam Leffler a = GCRY_CIPHER_AES; 23639beb93cSSam Leffler res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 23739beb93cSSam Leffler gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 23839beb93cSSam Leffler break; 23939beb93cSSam Leffler case CRYPTO_CIPHER_ALG_3DES: 24039beb93cSSam Leffler a = GCRY_CIPHER_3DES; 24139beb93cSSam Leffler res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 24239beb93cSSam Leffler gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 24339beb93cSSam Leffler break; 24439beb93cSSam Leffler case CRYPTO_CIPHER_ALG_DES: 24539beb93cSSam Leffler a = GCRY_CIPHER_DES; 24639beb93cSSam Leffler res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 24739beb93cSSam Leffler gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 24839beb93cSSam Leffler break; 24939beb93cSSam Leffler case CRYPTO_CIPHER_ALG_RC2: 25039beb93cSSam Leffler if (key_len == 5) 25139beb93cSSam Leffler a = GCRY_CIPHER_RFC2268_40; 25239beb93cSSam Leffler else 25339beb93cSSam Leffler a = GCRY_CIPHER_RFC2268_128; 25439beb93cSSam Leffler res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 25539beb93cSSam Leffler gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 25639beb93cSSam Leffler break; 25739beb93cSSam Leffler default: 25839beb93cSSam Leffler os_free(ctx); 25939beb93cSSam Leffler return NULL; 26039beb93cSSam Leffler } 26139beb93cSSam Leffler 26239beb93cSSam Leffler if (res != GPG_ERR_NO_ERROR) { 26339beb93cSSam Leffler os_free(ctx); 26439beb93cSSam Leffler return NULL; 26539beb93cSSam Leffler } 26639beb93cSSam Leffler 26739beb93cSSam Leffler if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || 26839beb93cSSam Leffler gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { 26939beb93cSSam Leffler gcry_cipher_close(ctx->enc); 27039beb93cSSam Leffler gcry_cipher_close(ctx->dec); 27139beb93cSSam Leffler os_free(ctx); 27239beb93cSSam Leffler return NULL; 27339beb93cSSam Leffler } 27439beb93cSSam Leffler 27539beb93cSSam Leffler ivlen = gcry_cipher_get_algo_blklen(a); 27639beb93cSSam Leffler if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || 27739beb93cSSam Leffler gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { 27839beb93cSSam Leffler gcry_cipher_close(ctx->enc); 27939beb93cSSam Leffler gcry_cipher_close(ctx->dec); 28039beb93cSSam Leffler os_free(ctx); 28139beb93cSSam Leffler return NULL; 28239beb93cSSam Leffler } 28339beb93cSSam Leffler 28439beb93cSSam Leffler return ctx; 28539beb93cSSam Leffler } 28639beb93cSSam Leffler 28739beb93cSSam Leffler 28839beb93cSSam Leffler int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 28939beb93cSSam Leffler u8 *crypt, size_t len) 29039beb93cSSam Leffler { 29139beb93cSSam Leffler if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != 29239beb93cSSam Leffler GPG_ERR_NO_ERROR) 29339beb93cSSam Leffler return -1; 29439beb93cSSam Leffler return 0; 29539beb93cSSam Leffler } 29639beb93cSSam Leffler 29739beb93cSSam Leffler 29839beb93cSSam Leffler int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 29939beb93cSSam Leffler u8 *plain, size_t len) 30039beb93cSSam Leffler { 30139beb93cSSam Leffler if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != 30239beb93cSSam Leffler GPG_ERR_NO_ERROR) 30339beb93cSSam Leffler return -1; 30439beb93cSSam Leffler return 0; 30539beb93cSSam Leffler } 30639beb93cSSam Leffler 30739beb93cSSam Leffler 30839beb93cSSam Leffler void crypto_cipher_deinit(struct crypto_cipher *ctx) 30939beb93cSSam Leffler { 31039beb93cSSam Leffler gcry_cipher_close(ctx->enc); 31139beb93cSSam Leffler gcry_cipher_close(ctx->dec); 31239beb93cSSam Leffler os_free(ctx); 31339beb93cSSam Leffler } 314