1132718Skan/* 2132718Skan * WPA Supplicant / wrapper functions for libgcrypt 3169689Skan * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 4132718Skan * 5132718Skan * This program is free software; you can redistribute it and/or modify 6132718Skan * it under the terms of the GNU General Public License version 2 as 7132718Skan * published by the Free Software Foundation. 8132718Skan * 9132718Skan * Alternatively, this software may be distributed under the terms of BSD 10132718Skan * license. 11132718Skan * 12132718Skan * See README and COPYING for more details. 13132718Skan */ 14132718Skan 15132718Skan#include "includes.h" 16132718Skan#include <gcrypt.h> 17132718Skan 18132718Skan#include "common.h" 19132718Skan#include "crypto.h" 20132718Skan 21132718Skanint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 22132718Skan{ 23169689Skan gcry_md_hd_t hd; 24169689Skan unsigned char *p; 25132718Skan size_t i; 26132718Skan 27132718Skan if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) 28132718Skan return -1; 29132718Skan for (i = 0; i < num_elem; i++) 30132718Skan gcry_md_write(hd, addr[i], len[i]); 31132718Skan p = gcry_md_read(hd, GCRY_MD_MD4); 32132718Skan if (p) 33132718Skan memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); 34132718Skan gcry_md_close(hd); 35132718Skan return 0; 36132718Skan} 37132718Skan 38132718Skan 39132718Skanvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 40132718Skan{ 41132718Skan gcry_cipher_hd_t hd; 42132718Skan u8 pkey[8], next, tmp; 43132718Skan int i; 44132718Skan 45169689Skan /* Add parity bits to the key */ 46169689Skan next = 0; 47132718Skan for (i = 0; i < 7; i++) { 48132718Skan tmp = key[i]; 49132718Skan pkey[i] = (tmp >> i) | next | 1; 50132718Skan next = tmp << (7 - i); 51132718Skan } 52132718Skan pkey[i] = next | 1; 53132718Skan 54132718Skan gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 55132718Skan gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); 56132718Skan gcry_cipher_encrypt(hd, cypher, 8, clear, 8); 57132718Skan gcry_cipher_close(hd); 58132718Skan} 59132718Skan 60132718Skan 61132718Skanint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 62132718Skan{ 63132718Skan gcry_md_hd_t hd; 64132718Skan unsigned char *p; 65132718Skan size_t i; 66132718Skan 67132718Skan if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) 68132718Skan return -1; 69132718Skan for (i = 0; i < num_elem; i++) 70132718Skan gcry_md_write(hd, addr[i], len[i]); 71132718Skan p = gcry_md_read(hd, GCRY_MD_MD5); 72132718Skan if (p) 73132718Skan memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); 74132718Skan gcry_md_close(hd); 75132718Skan return 0; 76132718Skan} 77132718Skan 78132718Skan 79132718Skanint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 80132718Skan{ 81132718Skan gcry_md_hd_t hd; 82132718Skan unsigned char *p; 83132718Skan size_t i; 84132718Skan 85132718Skan if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) 86132718Skan return -1; 87132718Skan for (i = 0; i < num_elem; i++) 88132718Skan gcry_md_write(hd, addr[i], len[i]); 89132718Skan p = gcry_md_read(hd, GCRY_MD_SHA1); 90132718Skan if (p) 91132718Skan memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); 92132718Skan gcry_md_close(hd); 93132718Skan return 0; 94132718Skan} 95132718Skan 96132718Skan 97132718Skanvoid * aes_encrypt_init(const u8 *key, size_t len) 98132718Skan{ 99169689Skan gcry_cipher_hd_t hd; 100169689Skan 101169689Skan if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 102169689Skan GPG_ERR_NO_ERROR) { 103169689Skan printf("cipher open failed\n"); 104132718Skan return NULL; 105132718Skan } 106132718Skan if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 107132718Skan printf("setkey failed\n"); 108132718Skan gcry_cipher_close(hd); 109132718Skan return NULL; 110132718Skan } 111132718Skan 112132718Skan return hd; 113132718Skan} 114132718Skan 115132718Skan 116132718Skanvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 117132718Skan{ 118132718Skan gcry_cipher_hd_t hd = ctx; 119132718Skan gcry_cipher_encrypt(hd, crypt, 16, plain, 16); 120132718Skan} 121132718Skan 122132718Skan 123169689Skanvoid aes_encrypt_deinit(void *ctx) 124169689Skan{ 125132718Skan gcry_cipher_hd_t hd = ctx; 126169689Skan gcry_cipher_close(hd); 127169689Skan} 128169689Skan 129169689Skan 130169689Skanvoid * aes_decrypt_init(const u8 *key, size_t len) 131169689Skan{ 132169689Skan gcry_cipher_hd_t hd; 133169689Skan 134169689Skan if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 135169689Skan GPG_ERR_NO_ERROR) 136169689Skan return NULL; 137169689Skan if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 138169689Skan gcry_cipher_close(hd); 139132718Skan return NULL; 140132718Skan } 141132718Skan 142132718Skan return hd; 143132718Skan} 144132718Skan 145132718Skan 146132718Skanvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 147132718Skan{ 148132718Skan gcry_cipher_hd_t hd = ctx; 149132718Skan gcry_cipher_decrypt(hd, plain, 16, crypt, 16); 150132718Skan} 151132718Skan 152132718Skan 153132718Skanvoid aes_decrypt_deinit(void *ctx) 154132718Skan{ 155132718Skan gcry_cipher_hd_t hd = ctx; 156132718Skan gcry_cipher_close(hd); 157132718Skan} 158132718Skan 159132718Skan 160132718Skanint crypto_mod_exp(const u8 *base, size_t base_len, 161132718Skan const u8 *power, size_t power_len, 162132718Skan const u8 *modulus, size_t modulus_len, 163132718Skan u8 *result, size_t *result_len) 164132718Skan{ 165132718Skan gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, 166132718Skan bn_result = NULL; 167132718Skan int ret = -1; 168132718Skan 169132718Skan if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != 170132718Skan GPG_ERR_NO_ERROR || 171132718Skan gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != 172132718Skan GPG_ERR_NO_ERROR || 173132718Skan gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, 174132718Skan NULL) != GPG_ERR_NO_ERROR) 175132718Skan goto error; 176132718Skan bn_result = gcry_mpi_new(modulus_len * 8); 177132718Skan 178132718Skan gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); 179132718Skan 180132718Skan if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, 181132718Skan bn_result) != GPG_ERR_NO_ERROR) 182132718Skan goto error; 183169689Skan 184132718Skan ret = 0; 185132718Skan 186132718Skanerror: 187132718Skan gcry_mpi_release(bn_base); 188132718Skan gcry_mpi_release(bn_exp); 189132718Skan gcry_mpi_release(bn_modulus); 190132718Skan gcry_mpi_release(bn_result); 191132718Skan return ret; 192132718Skan} 193132718Skan 194169689Skan 195161651Skanstruct crypto_cipher { 196132718Skan gcry_cipher_hd_t enc; 197132718Skan gcry_cipher_hd_t dec; 198132718Skan}; 199132718Skan 200132718Skan 201132718Skanstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 202132718Skan const u8 *iv, const u8 *key, 203132718Skan size_t key_len) 204132718Skan{ 205132718Skan struct crypto_cipher *ctx; 206132718Skan gcry_error_t res; 207132718Skan enum gcry_cipher_algos a; 208132718Skan int ivlen; 209132718Skan 210132718Skan ctx = os_zalloc(sizeof(*ctx)); 211132718Skan if (ctx == NULL) 212132718Skan return NULL; 213132718Skan 214132718Skan switch (alg) { 215132718Skan case CRYPTO_CIPHER_ALG_RC4: 216132718Skan a = GCRY_CIPHER_ARCFOUR; 217132718Skan res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 218132718Skan 0); 219132718Skan gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); 220132718Skan break; 221132718Skan case CRYPTO_CIPHER_ALG_AES: 222132718Skan if (key_len == 24) 223132718Skan a = GCRY_CIPHER_AES192; 224132718Skan else if (key_len == 32) 225132718Skan a = GCRY_CIPHER_AES256; 226132718Skan else 227132718Skan a = GCRY_CIPHER_AES; 228132718Skan res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 229132718Skan gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 230132718Skan break; 231132718Skan case CRYPTO_CIPHER_ALG_3DES: 232132718Skan a = GCRY_CIPHER_3DES; 233132718Skan res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 234132718Skan gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 235132718Skan break; 236132718Skan case CRYPTO_CIPHER_ALG_DES: 237132718Skan a = GCRY_CIPHER_DES; 238132718Skan res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 239132718Skan gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 240132718Skan break; 241132718Skan case CRYPTO_CIPHER_ALG_RC2: 242132718Skan if (key_len == 5) 243132718Skan a = GCRY_CIPHER_RFC2268_40; 244132718Skan else 245132718Skan a = GCRY_CIPHER_RFC2268_128; 246132718Skan res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 247132718Skan gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 248132718Skan break; 249132718Skan default: 250132718Skan os_free(ctx); 251132718Skan return NULL; 252132718Skan } 253132718Skan 254132718Skan if (res != GPG_ERR_NO_ERROR) { 255132718Skan os_free(ctx); 256132718Skan return NULL; 257132718Skan } 258132718Skan 259132718Skan if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || 260132718Skan gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { 261132718Skan gcry_cipher_close(ctx->enc); 262132718Skan gcry_cipher_close(ctx->dec); 263132718Skan os_free(ctx); 264132718Skan return NULL; 265169689Skan } 266132718Skan 267132718Skan ivlen = gcry_cipher_get_algo_blklen(a); 268132718Skan if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || 269132718Skan gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { 270169689Skan gcry_cipher_close(ctx->enc); 271132718Skan gcry_cipher_close(ctx->dec); 272132718Skan os_free(ctx); 273132718Skan return NULL; 274169689Skan } 275132718Skan 276132718Skan return ctx; 277132718Skan} 278132718Skan 279132718Skan 280132718Skanint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 281132718Skan u8 *crypt, size_t len) 282169689Skan{ 283132718Skan if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != 284132718Skan GPG_ERR_NO_ERROR) 285132718Skan return -1; 286132718Skan return 0; 287132718Skan} 288132718Skan 289132718Skan 290132718Skanint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 291132718Skan u8 *plain, size_t len) 292132718Skan{ 293132718Skan if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != 294132718Skan GPG_ERR_NO_ERROR) 295132718Skan return -1; 296132718Skan return 0; 297132718Skan} 298132718Skan 299132718Skan 300132718Skanvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 301132718Skan{ 302132718Skan gcry_cipher_close(ctx->enc); 303132718Skan gcry_cipher_close(ctx->dec); 304132718Skan os_free(ctx); 305132718Skan} 306132718Skan