1189251Ssam/* 2189251Ssam * WPA Supplicant / wrapper functions for libgcrypt 3346981Scy * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam#include <gcrypt.h> 11189251Ssam 12189251Ssam#include "common.h" 13346981Scy#include "md5.h" 14346981Scy#include "sha1.h" 15346981Scy#include "sha256.h" 16346981Scy#include "sha384.h" 17346981Scy#include "sha512.h" 18189251Ssam#include "crypto.h" 19189251Ssam 20346981Scystatic int gnutls_digest_vector(int algo, size_t num_elem, 21346981Scy 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 27346981Scy if (TEST_FAIL()) 28214734Srpaulo return -1; 29346981Scy 30346981Scy if (gcry_md_open(&hd, algo, 0) != GPG_ERR_NO_ERROR) 31346981Scy return -1; 32189251Ssam for (i = 0; i < num_elem; i++) 33189251Ssam gcry_md_write(hd, addr[i], len[i]); 34346981Scy p = gcry_md_read(hd, algo); 35189251Ssam if (p) 36346981Scy memcpy(mac, p, gcry_md_get_algo_dlen(algo)); 37189251Ssam gcry_md_close(hd); 38214734Srpaulo return 0; 39189251Ssam} 40189251Ssam 41189251Ssam 42346981Scyint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 43189251Ssam{ 44346981Scy return gnutls_digest_vector(GCRY_MD_MD4, num_elem, addr, len, mac); 45346981Scy} 46346981Scy 47346981Scy 48346981Scyint des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 49346981Scy{ 50189251Ssam gcry_cipher_hd_t hd; 51189251Ssam u8 pkey[8], next, tmp; 52189251Ssam int i; 53189251Ssam 54189251Ssam /* Add parity bits to the key */ 55189251Ssam next = 0; 56189251Ssam for (i = 0; i < 7; i++) { 57189251Ssam tmp = key[i]; 58189251Ssam pkey[i] = (tmp >> i) | next | 1; 59189251Ssam next = tmp << (7 - i); 60189251Ssam } 61189251Ssam pkey[i] = next | 1; 62189251Ssam 63189251Ssam gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 64189251Ssam gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); 65189251Ssam gcry_cipher_encrypt(hd, cypher, 8, clear, 8); 66189251Ssam gcry_cipher_close(hd); 67346981Scy return 0; 68189251Ssam} 69189251Ssam 70189251Ssam 71214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 72189251Ssam{ 73346981Scy return gnutls_digest_vector(GCRY_MD_MD5, num_elem, addr, len, mac); 74189251Ssam} 75189251Ssam 76189251Ssam 77214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 78189251Ssam{ 79346981Scy return gnutls_digest_vector(GCRY_MD_SHA1, num_elem, addr, len, mac); 80346981Scy} 81346981Scy 82346981Scy 83346981Scyint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 84346981Scy{ 85346981Scy return gnutls_digest_vector(GCRY_MD_SHA256, num_elem, addr, len, mac); 86346981Scy} 87346981Scy 88346981Scy 89346981Scyint sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 90346981Scy{ 91346981Scy return gnutls_digest_vector(GCRY_MD_SHA384, num_elem, addr, len, mac); 92346981Scy} 93346981Scy 94346981Scy 95346981Scyint sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 96346981Scy{ 97346981Scy return gnutls_digest_vector(GCRY_MD_SHA512, num_elem, addr, len, mac); 98346981Scy} 99346981Scy 100346981Scy 101346981Scystatic int gnutls_hmac_vector(int algo, const u8 *key, size_t key_len, 102346981Scy size_t num_elem, const u8 *addr[], 103346981Scy const size_t *len, u8 *mac) 104346981Scy{ 105189251Ssam gcry_md_hd_t hd; 106189251Ssam unsigned char *p; 107189251Ssam size_t i; 108189251Ssam 109346981Scy if (TEST_FAIL()) 110214734Srpaulo return -1; 111346981Scy 112346981Scy if (gcry_md_open(&hd, algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR) 113346981Scy return -1; 114346981Scy if (gcry_md_setkey(hd, key, key_len) != GPG_ERR_NO_ERROR) { 115346981Scy gcry_md_close(hd); 116346981Scy return -1; 117346981Scy } 118189251Ssam for (i = 0; i < num_elem; i++) 119189251Ssam gcry_md_write(hd, addr[i], len[i]); 120346981Scy p = gcry_md_read(hd, algo); 121189251Ssam if (p) 122346981Scy memcpy(mac, p, gcry_md_get_algo_dlen(algo)); 123189251Ssam gcry_md_close(hd); 124214734Srpaulo return 0; 125189251Ssam} 126189251Ssam 127189251Ssam 128346981Scyint hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, 129346981Scy const u8 *addr[], const size_t *len, u8 *mac) 130346981Scy{ 131346981Scy return gnutls_hmac_vector(GCRY_MD_MD5, key, key_len, num_elem, addr, 132346981Scy len, mac); 133346981Scy} 134346981Scy 135346981Scy 136346981Scyint hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, 137346981Scy u8 *mac) 138346981Scy{ 139346981Scy return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); 140346981Scy} 141346981Scy 142346981Scy 143346981Scyint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, 144346981Scy const u8 *addr[], const size_t *len, u8 *mac) 145346981Scy{ 146346981Scy return gnutls_hmac_vector(GCRY_MD_SHA1, key, key_len, num_elem, addr, 147346981Scy len, mac); 148346981Scy} 149346981Scy 150346981Scy 151346981Scyint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, 152346981Scy u8 *mac) 153346981Scy{ 154346981Scy return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); 155346981Scy} 156346981Scy 157346981Scy 158346981Scy#ifdef CONFIG_SHA256 159346981Scy 160346981Scyint hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, 161346981Scy const u8 *addr[], const size_t *len, u8 *mac) 162346981Scy{ 163346981Scy return gnutls_hmac_vector(GCRY_MD_SHA256, key, key_len, num_elem, addr, 164346981Scy len, mac); 165346981Scy} 166346981Scy 167346981Scy 168346981Scyint hmac_sha256(const u8 *key, size_t key_len, const u8 *data, 169346981Scy size_t data_len, u8 *mac) 170346981Scy{ 171346981Scy return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); 172346981Scy} 173346981Scy 174346981Scy#endif /* CONFIG_SHA256 */ 175346981Scy 176346981Scy 177346981Scy#ifdef CONFIG_SHA384 178346981Scy 179346981Scyint hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, 180346981Scy const u8 *addr[], const size_t *len, u8 *mac) 181346981Scy{ 182346981Scy return gnutls_hmac_vector(GCRY_MD_SHA384, key, key_len, num_elem, addr, 183346981Scy len, mac); 184346981Scy} 185346981Scy 186346981Scy 187346981Scyint hmac_sha384(const u8 *key, size_t key_len, const u8 *data, 188346981Scy size_t data_len, u8 *mac) 189346981Scy{ 190346981Scy return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); 191346981Scy} 192346981Scy 193346981Scy#endif /* CONFIG_SHA384 */ 194346981Scy 195346981Scy 196346981Scy#ifdef CONFIG_SHA512 197346981Scy 198346981Scyint hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, 199346981Scy const u8 *addr[], const size_t *len, u8 *mac) 200346981Scy{ 201346981Scy return gnutls_hmac_vector(GCRY_MD_SHA512, key, key_len, num_elem, addr, 202346981Scy len, mac); 203346981Scy} 204346981Scy 205346981Scy 206346981Scyint hmac_sha512(const u8 *key, size_t key_len, const u8 *data, 207346981Scy size_t data_len, u8 *mac) 208346981Scy{ 209346981Scy return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); 210346981Scy} 211346981Scy 212346981Scy#endif /* CONFIG_SHA512 */ 213346981Scy 214346981Scy 215189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len) 216189251Ssam{ 217189251Ssam gcry_cipher_hd_t hd; 218189251Ssam 219346981Scy if (TEST_FAIL()) 220346981Scy return NULL; 221346981Scy 222189251Ssam if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 223189251Ssam GPG_ERR_NO_ERROR) { 224189251Ssam printf("cipher open failed\n"); 225189251Ssam return NULL; 226189251Ssam } 227189251Ssam if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 228189251Ssam printf("setkey failed\n"); 229189251Ssam gcry_cipher_close(hd); 230189251Ssam return NULL; 231189251Ssam } 232189251Ssam 233189251Ssam return hd; 234189251Ssam} 235189251Ssam 236189251Ssam 237346981Scyint aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 238189251Ssam{ 239189251Ssam gcry_cipher_hd_t hd = ctx; 240189251Ssam gcry_cipher_encrypt(hd, crypt, 16, plain, 16); 241346981Scy return 0; 242189251Ssam} 243189251Ssam 244189251Ssam 245189251Ssamvoid aes_encrypt_deinit(void *ctx) 246189251Ssam{ 247189251Ssam gcry_cipher_hd_t hd = ctx; 248189251Ssam gcry_cipher_close(hd); 249189251Ssam} 250189251Ssam 251189251Ssam 252189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len) 253189251Ssam{ 254189251Ssam gcry_cipher_hd_t hd; 255189251Ssam 256346981Scy if (TEST_FAIL()) 257346981Scy return NULL; 258346981Scy 259189251Ssam if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 260189251Ssam GPG_ERR_NO_ERROR) 261189251Ssam return NULL; 262189251Ssam if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 263189251Ssam gcry_cipher_close(hd); 264189251Ssam return NULL; 265189251Ssam } 266189251Ssam 267189251Ssam return hd; 268189251Ssam} 269189251Ssam 270189251Ssam 271346981Scyint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 272189251Ssam{ 273189251Ssam gcry_cipher_hd_t hd = ctx; 274189251Ssam gcry_cipher_decrypt(hd, plain, 16, crypt, 16); 275346981Scy return 0; 276189251Ssam} 277189251Ssam 278189251Ssam 279189251Ssamvoid aes_decrypt_deinit(void *ctx) 280189251Ssam{ 281189251Ssam gcry_cipher_hd_t hd = ctx; 282189251Ssam gcry_cipher_close(hd); 283189251Ssam} 284189251Ssam 285189251Ssam 286346981Scyint crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, 287346981Scy u8 *pubkey) 288346981Scy{ 289346981Scy size_t pubkey_len, pad; 290346981Scy 291346981Scy if (os_get_random(privkey, prime_len) < 0) 292346981Scy return -1; 293346981Scy if (os_memcmp(privkey, prime, prime_len) > 0) { 294346981Scy /* Make sure private value is smaller than prime */ 295346981Scy privkey[0] = 0; 296346981Scy } 297346981Scy 298346981Scy pubkey_len = prime_len; 299346981Scy if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, 300346981Scy pubkey, &pubkey_len) < 0) 301346981Scy return -1; 302346981Scy if (pubkey_len < prime_len) { 303346981Scy pad = prime_len - pubkey_len; 304346981Scy os_memmove(pubkey + pad, pubkey, pubkey_len); 305346981Scy os_memset(pubkey, 0, pad); 306346981Scy } 307346981Scy 308346981Scy return 0; 309346981Scy} 310346981Scy 311346981Scy 312346981Scyint crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, 313346981Scy const u8 *order, size_t order_len, 314346981Scy const u8 *privkey, size_t privkey_len, 315346981Scy const u8 *pubkey, size_t pubkey_len, 316346981Scy u8 *secret, size_t *len) 317346981Scy{ 318346981Scy gcry_mpi_t pub = NULL; 319346981Scy int res = -1; 320346981Scy 321346981Scy if (pubkey_len > prime_len || 322346981Scy (pubkey_len == prime_len && 323346981Scy os_memcmp(pubkey, prime, prime_len) >= 0)) 324346981Scy return -1; 325346981Scy 326346981Scy if (gcry_mpi_scan(&pub, GCRYMPI_FMT_USG, pubkey, pubkey_len, NULL) != 327346981Scy GPG_ERR_NO_ERROR || 328346981Scy gcry_mpi_cmp_ui(pub, 1) <= 0) 329346981Scy goto fail; 330346981Scy 331346981Scy if (order) { 332346981Scy gcry_mpi_t p = NULL, q = NULL, tmp; 333346981Scy int failed; 334346981Scy 335346981Scy /* verify: pubkey^q == 1 mod p */ 336346981Scy tmp = gcry_mpi_new(prime_len * 8); 337346981Scy failed = !tmp || 338346981Scy gcry_mpi_scan(&p, GCRYMPI_FMT_USG, prime, prime_len, 339346981Scy NULL) != GPG_ERR_NO_ERROR || 340346981Scy gcry_mpi_scan(&q, GCRYMPI_FMT_USG, order, order_len, 341346981Scy NULL) != GPG_ERR_NO_ERROR; 342346981Scy if (!failed) { 343346981Scy gcry_mpi_powm(tmp, pub, q, p); 344346981Scy failed = gcry_mpi_cmp_ui(tmp, 1) != 0; 345346981Scy } 346346981Scy gcry_mpi_release(p); 347346981Scy gcry_mpi_release(q); 348346981Scy gcry_mpi_release(tmp); 349346981Scy if (failed) 350346981Scy goto fail; 351346981Scy } 352346981Scy 353346981Scy res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, 354346981Scy prime, prime_len, secret, len); 355346981Scyfail: 356346981Scy gcry_mpi_release(pub); 357346981Scy return res; 358346981Scy} 359346981Scy 360346981Scy 361189251Ssamint crypto_mod_exp(const u8 *base, size_t base_len, 362189251Ssam const u8 *power, size_t power_len, 363189251Ssam const u8 *modulus, size_t modulus_len, 364189251Ssam u8 *result, size_t *result_len) 365189251Ssam{ 366189251Ssam gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, 367189251Ssam bn_result = NULL; 368189251Ssam int ret = -1; 369189251Ssam 370189251Ssam if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != 371189251Ssam GPG_ERR_NO_ERROR || 372189251Ssam gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != 373189251Ssam GPG_ERR_NO_ERROR || 374189251Ssam gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, 375189251Ssam NULL) != GPG_ERR_NO_ERROR) 376189251Ssam goto error; 377189251Ssam bn_result = gcry_mpi_new(modulus_len * 8); 378189251Ssam 379189251Ssam gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); 380189251Ssam 381189251Ssam if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, 382189251Ssam bn_result) != GPG_ERR_NO_ERROR) 383189251Ssam goto error; 384189251Ssam 385189251Ssam ret = 0; 386189251Ssam 387189251Ssamerror: 388189251Ssam gcry_mpi_release(bn_base); 389189251Ssam gcry_mpi_release(bn_exp); 390189251Ssam gcry_mpi_release(bn_modulus); 391189251Ssam gcry_mpi_release(bn_result); 392189251Ssam return ret; 393189251Ssam} 394189251Ssam 395189251Ssam 396189251Ssamstruct crypto_cipher { 397189251Ssam gcry_cipher_hd_t enc; 398189251Ssam gcry_cipher_hd_t dec; 399189251Ssam}; 400189251Ssam 401189251Ssam 402189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 403189251Ssam const u8 *iv, const u8 *key, 404189251Ssam size_t key_len) 405189251Ssam{ 406189251Ssam struct crypto_cipher *ctx; 407189251Ssam gcry_error_t res; 408189251Ssam enum gcry_cipher_algos a; 409189251Ssam int ivlen; 410189251Ssam 411189251Ssam ctx = os_zalloc(sizeof(*ctx)); 412189251Ssam if (ctx == NULL) 413189251Ssam return NULL; 414189251Ssam 415189251Ssam switch (alg) { 416189251Ssam case CRYPTO_CIPHER_ALG_RC4: 417189251Ssam a = GCRY_CIPHER_ARCFOUR; 418189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 419189251Ssam 0); 420189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); 421189251Ssam break; 422189251Ssam case CRYPTO_CIPHER_ALG_AES: 423189251Ssam if (key_len == 24) 424189251Ssam a = GCRY_CIPHER_AES192; 425189251Ssam else if (key_len == 32) 426189251Ssam a = GCRY_CIPHER_AES256; 427189251Ssam else 428189251Ssam a = GCRY_CIPHER_AES; 429189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 430189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 431189251Ssam break; 432189251Ssam case CRYPTO_CIPHER_ALG_3DES: 433189251Ssam a = GCRY_CIPHER_3DES; 434189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 435189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 436189251Ssam break; 437189251Ssam case CRYPTO_CIPHER_ALG_DES: 438189251Ssam a = GCRY_CIPHER_DES; 439189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 440189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 441189251Ssam break; 442189251Ssam case CRYPTO_CIPHER_ALG_RC2: 443189251Ssam if (key_len == 5) 444189251Ssam a = GCRY_CIPHER_RFC2268_40; 445189251Ssam else 446189251Ssam a = GCRY_CIPHER_RFC2268_128; 447189251Ssam res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 448189251Ssam gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 449189251Ssam break; 450189251Ssam default: 451189251Ssam os_free(ctx); 452189251Ssam return NULL; 453189251Ssam } 454189251Ssam 455189251Ssam if (res != GPG_ERR_NO_ERROR) { 456189251Ssam os_free(ctx); 457189251Ssam return NULL; 458189251Ssam } 459189251Ssam 460189251Ssam if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || 461189251Ssam gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { 462189251Ssam gcry_cipher_close(ctx->enc); 463189251Ssam gcry_cipher_close(ctx->dec); 464189251Ssam os_free(ctx); 465189251Ssam return NULL; 466189251Ssam } 467189251Ssam 468189251Ssam ivlen = gcry_cipher_get_algo_blklen(a); 469189251Ssam if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || 470189251Ssam gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { 471189251Ssam gcry_cipher_close(ctx->enc); 472189251Ssam gcry_cipher_close(ctx->dec); 473189251Ssam os_free(ctx); 474189251Ssam return NULL; 475189251Ssam } 476189251Ssam 477189251Ssam return ctx; 478189251Ssam} 479189251Ssam 480189251Ssam 481189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 482189251Ssam u8 *crypt, size_t len) 483189251Ssam{ 484189251Ssam if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != 485189251Ssam GPG_ERR_NO_ERROR) 486189251Ssam return -1; 487189251Ssam return 0; 488189251Ssam} 489189251Ssam 490189251Ssam 491189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 492189251Ssam u8 *plain, size_t len) 493189251Ssam{ 494189251Ssam if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != 495189251Ssam GPG_ERR_NO_ERROR) 496189251Ssam return -1; 497189251Ssam return 0; 498189251Ssam} 499189251Ssam 500189251Ssam 501189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 502189251Ssam{ 503189251Ssam gcry_cipher_close(ctx->enc); 504189251Ssam gcry_cipher_close(ctx->dec); 505189251Ssam os_free(ctx); 506189251Ssam} 507