1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * WPA Supplicant / wrapper functions for libgcrypt 3e5b75505Sopenharmony_ci * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "includes.h" 10e5b75505Sopenharmony_ci#include <gcrypt.h> 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "common.h" 13e5b75505Sopenharmony_ci#include "md5.h" 14e5b75505Sopenharmony_ci#include "sha1.h" 15e5b75505Sopenharmony_ci#include "sha256.h" 16e5b75505Sopenharmony_ci#include "sha384.h" 17e5b75505Sopenharmony_ci#include "sha512.h" 18e5b75505Sopenharmony_ci#include "crypto.h" 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_cistatic int gnutls_digest_vector(int algo, size_t num_elem, 21e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 22e5b75505Sopenharmony_ci{ 23e5b75505Sopenharmony_ci gcry_md_hd_t hd; 24e5b75505Sopenharmony_ci unsigned char *p; 25e5b75505Sopenharmony_ci size_t i; 26e5b75505Sopenharmony_ci 27e5b75505Sopenharmony_ci if (TEST_FAIL()) 28e5b75505Sopenharmony_ci return -1; 29e5b75505Sopenharmony_ci 30e5b75505Sopenharmony_ci if (gcry_md_open(&hd, algo, 0) != GPG_ERR_NO_ERROR) 31e5b75505Sopenharmony_ci return -1; 32e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 33e5b75505Sopenharmony_ci gcry_md_write(hd, addr[i], len[i]); 34e5b75505Sopenharmony_ci p = gcry_md_read(hd, algo); 35e5b75505Sopenharmony_ci if (p) 36e5b75505Sopenharmony_ci memcpy(mac, p, gcry_md_get_algo_dlen(algo)); 37e5b75505Sopenharmony_ci gcry_md_close(hd); 38e5b75505Sopenharmony_ci return 0; 39e5b75505Sopenharmony_ci} 40e5b75505Sopenharmony_ci 41e5b75505Sopenharmony_ci 42e5b75505Sopenharmony_ciint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 43e5b75505Sopenharmony_ci{ 44e5b75505Sopenharmony_ci return gnutls_digest_vector(GCRY_MD_MD4, num_elem, addr, len, mac); 45e5b75505Sopenharmony_ci} 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_ci 48e5b75505Sopenharmony_ciint des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 49e5b75505Sopenharmony_ci{ 50e5b75505Sopenharmony_ci gcry_cipher_hd_t hd; 51e5b75505Sopenharmony_ci u8 pkey[8], next, tmp; 52e5b75505Sopenharmony_ci int i; 53e5b75505Sopenharmony_ci 54e5b75505Sopenharmony_ci /* Add parity bits to the key */ 55e5b75505Sopenharmony_ci next = 0; 56e5b75505Sopenharmony_ci for (i = 0; i < 7; i++) { 57e5b75505Sopenharmony_ci tmp = key[i]; 58e5b75505Sopenharmony_ci pkey[i] = (tmp >> i) | next | 1; 59e5b75505Sopenharmony_ci next = tmp << (7 - i); 60e5b75505Sopenharmony_ci } 61e5b75505Sopenharmony_ci pkey[i] = next | 1; 62e5b75505Sopenharmony_ci 63e5b75505Sopenharmony_ci gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 64e5b75505Sopenharmony_ci gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); 65e5b75505Sopenharmony_ci gcry_cipher_encrypt(hd, cypher, 8, clear, 8); 66e5b75505Sopenharmony_ci gcry_cipher_close(hd); 67e5b75505Sopenharmony_ci return 0; 68e5b75505Sopenharmony_ci} 69e5b75505Sopenharmony_ci 70e5b75505Sopenharmony_ci 71e5b75505Sopenharmony_ciint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 72e5b75505Sopenharmony_ci{ 73e5b75505Sopenharmony_ci return gnutls_digest_vector(GCRY_MD_MD5, num_elem, addr, len, mac); 74e5b75505Sopenharmony_ci} 75e5b75505Sopenharmony_ci 76e5b75505Sopenharmony_ci 77e5b75505Sopenharmony_ciint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 78e5b75505Sopenharmony_ci{ 79e5b75505Sopenharmony_ci return gnutls_digest_vector(GCRY_MD_SHA1, num_elem, addr, len, mac); 80e5b75505Sopenharmony_ci} 81e5b75505Sopenharmony_ci 82e5b75505Sopenharmony_ci 83e5b75505Sopenharmony_ciint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 84e5b75505Sopenharmony_ci{ 85e5b75505Sopenharmony_ci return gnutls_digest_vector(GCRY_MD_SHA256, num_elem, addr, len, mac); 86e5b75505Sopenharmony_ci} 87e5b75505Sopenharmony_ci 88e5b75505Sopenharmony_ci 89e5b75505Sopenharmony_ciint sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 90e5b75505Sopenharmony_ci{ 91e5b75505Sopenharmony_ci return gnutls_digest_vector(GCRY_MD_SHA384, num_elem, addr, len, mac); 92e5b75505Sopenharmony_ci} 93e5b75505Sopenharmony_ci 94e5b75505Sopenharmony_ci 95e5b75505Sopenharmony_ciint sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 96e5b75505Sopenharmony_ci{ 97e5b75505Sopenharmony_ci return gnutls_digest_vector(GCRY_MD_SHA512, num_elem, addr, len, mac); 98e5b75505Sopenharmony_ci} 99e5b75505Sopenharmony_ci 100e5b75505Sopenharmony_ci 101e5b75505Sopenharmony_cistatic int gnutls_hmac_vector(int algo, const u8 *key, size_t key_len, 102e5b75505Sopenharmony_ci size_t num_elem, const u8 *addr[], 103e5b75505Sopenharmony_ci const size_t *len, u8 *mac) 104e5b75505Sopenharmony_ci{ 105e5b75505Sopenharmony_ci gcry_md_hd_t hd; 106e5b75505Sopenharmony_ci unsigned char *p; 107e5b75505Sopenharmony_ci size_t i; 108e5b75505Sopenharmony_ci 109e5b75505Sopenharmony_ci if (TEST_FAIL()) 110e5b75505Sopenharmony_ci return -1; 111e5b75505Sopenharmony_ci 112e5b75505Sopenharmony_ci if (gcry_md_open(&hd, algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR) 113e5b75505Sopenharmony_ci return -1; 114e5b75505Sopenharmony_ci if (gcry_md_setkey(hd, key, key_len) != GPG_ERR_NO_ERROR) { 115e5b75505Sopenharmony_ci gcry_md_close(hd); 116e5b75505Sopenharmony_ci return -1; 117e5b75505Sopenharmony_ci } 118e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 119e5b75505Sopenharmony_ci gcry_md_write(hd, addr[i], len[i]); 120e5b75505Sopenharmony_ci p = gcry_md_read(hd, algo); 121e5b75505Sopenharmony_ci if (p) 122e5b75505Sopenharmony_ci memcpy(mac, p, gcry_md_get_algo_dlen(algo)); 123e5b75505Sopenharmony_ci gcry_md_close(hd); 124e5b75505Sopenharmony_ci return 0; 125e5b75505Sopenharmony_ci} 126e5b75505Sopenharmony_ci 127e5b75505Sopenharmony_ci 128e5b75505Sopenharmony_ciint hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, 129e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 130e5b75505Sopenharmony_ci{ 131e5b75505Sopenharmony_ci return gnutls_hmac_vector(GCRY_MD_MD5, key, key_len, num_elem, addr, 132e5b75505Sopenharmony_ci len, mac); 133e5b75505Sopenharmony_ci} 134e5b75505Sopenharmony_ci 135e5b75505Sopenharmony_ci 136e5b75505Sopenharmony_ciint hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, 137e5b75505Sopenharmony_ci u8 *mac) 138e5b75505Sopenharmony_ci{ 139e5b75505Sopenharmony_ci return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); 140e5b75505Sopenharmony_ci} 141e5b75505Sopenharmony_ci 142e5b75505Sopenharmony_ci 143e5b75505Sopenharmony_ciint hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, 144e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 145e5b75505Sopenharmony_ci{ 146e5b75505Sopenharmony_ci return gnutls_hmac_vector(GCRY_MD_SHA1, key, key_len, num_elem, addr, 147e5b75505Sopenharmony_ci len, mac); 148e5b75505Sopenharmony_ci} 149e5b75505Sopenharmony_ci 150e5b75505Sopenharmony_ci 151e5b75505Sopenharmony_ciint hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, 152e5b75505Sopenharmony_ci u8 *mac) 153e5b75505Sopenharmony_ci{ 154e5b75505Sopenharmony_ci return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); 155e5b75505Sopenharmony_ci} 156e5b75505Sopenharmony_ci 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256 159e5b75505Sopenharmony_ci 160e5b75505Sopenharmony_ciint hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, 161e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 162e5b75505Sopenharmony_ci{ 163e5b75505Sopenharmony_ci return gnutls_hmac_vector(GCRY_MD_SHA256, key, key_len, num_elem, addr, 164e5b75505Sopenharmony_ci len, mac); 165e5b75505Sopenharmony_ci} 166e5b75505Sopenharmony_ci 167e5b75505Sopenharmony_ci 168e5b75505Sopenharmony_ciint hmac_sha256(const u8 *key, size_t key_len, const u8 *data, 169e5b75505Sopenharmony_ci size_t data_len, u8 *mac) 170e5b75505Sopenharmony_ci{ 171e5b75505Sopenharmony_ci return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); 172e5b75505Sopenharmony_ci} 173e5b75505Sopenharmony_ci 174e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */ 175e5b75505Sopenharmony_ci 176e5b75505Sopenharmony_ci 177e5b75505Sopenharmony_ci#ifdef CONFIG_SHA384 178e5b75505Sopenharmony_ci 179e5b75505Sopenharmony_ciint hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, 180e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 181e5b75505Sopenharmony_ci{ 182e5b75505Sopenharmony_ci return gnutls_hmac_vector(GCRY_MD_SHA384, key, key_len, num_elem, addr, 183e5b75505Sopenharmony_ci len, mac); 184e5b75505Sopenharmony_ci} 185e5b75505Sopenharmony_ci 186e5b75505Sopenharmony_ci 187e5b75505Sopenharmony_ciint hmac_sha384(const u8 *key, size_t key_len, const u8 *data, 188e5b75505Sopenharmony_ci size_t data_len, u8 *mac) 189e5b75505Sopenharmony_ci{ 190e5b75505Sopenharmony_ci return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); 191e5b75505Sopenharmony_ci} 192e5b75505Sopenharmony_ci 193e5b75505Sopenharmony_ci#endif /* CONFIG_SHA384 */ 194e5b75505Sopenharmony_ci 195e5b75505Sopenharmony_ci 196e5b75505Sopenharmony_ci#ifdef CONFIG_SHA512 197e5b75505Sopenharmony_ci 198e5b75505Sopenharmony_ciint hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, 199e5b75505Sopenharmony_ci const u8 *addr[], const size_t *len, u8 *mac) 200e5b75505Sopenharmony_ci{ 201e5b75505Sopenharmony_ci return gnutls_hmac_vector(GCRY_MD_SHA512, key, key_len, num_elem, addr, 202e5b75505Sopenharmony_ci len, mac); 203e5b75505Sopenharmony_ci} 204e5b75505Sopenharmony_ci 205e5b75505Sopenharmony_ci 206e5b75505Sopenharmony_ciint hmac_sha512(const u8 *key, size_t key_len, const u8 *data, 207e5b75505Sopenharmony_ci size_t data_len, u8 *mac) 208e5b75505Sopenharmony_ci{ 209e5b75505Sopenharmony_ci return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); 210e5b75505Sopenharmony_ci} 211e5b75505Sopenharmony_ci 212e5b75505Sopenharmony_ci#endif /* CONFIG_SHA512 */ 213e5b75505Sopenharmony_ci 214e5b75505Sopenharmony_ci 215e5b75505Sopenharmony_civoid * aes_encrypt_init(const u8 *key, size_t len) 216e5b75505Sopenharmony_ci{ 217e5b75505Sopenharmony_ci gcry_cipher_hd_t hd; 218e5b75505Sopenharmony_ci 219e5b75505Sopenharmony_ci if (TEST_FAIL()) 220e5b75505Sopenharmony_ci return NULL; 221e5b75505Sopenharmony_ci 222e5b75505Sopenharmony_ci if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 223e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR) { 224e5b75505Sopenharmony_ci printf("cipher open failed\n"); 225e5b75505Sopenharmony_ci return NULL; 226e5b75505Sopenharmony_ci } 227e5b75505Sopenharmony_ci if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 228e5b75505Sopenharmony_ci printf("setkey failed\n"); 229e5b75505Sopenharmony_ci gcry_cipher_close(hd); 230e5b75505Sopenharmony_ci return NULL; 231e5b75505Sopenharmony_ci } 232e5b75505Sopenharmony_ci 233e5b75505Sopenharmony_ci return hd; 234e5b75505Sopenharmony_ci} 235e5b75505Sopenharmony_ci 236e5b75505Sopenharmony_ci 237e5b75505Sopenharmony_ciint aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 238e5b75505Sopenharmony_ci{ 239e5b75505Sopenharmony_ci gcry_cipher_hd_t hd = ctx; 240e5b75505Sopenharmony_ci gcry_cipher_encrypt(hd, crypt, 16, plain, 16); 241e5b75505Sopenharmony_ci return 0; 242e5b75505Sopenharmony_ci} 243e5b75505Sopenharmony_ci 244e5b75505Sopenharmony_ci 245e5b75505Sopenharmony_civoid aes_encrypt_deinit(void *ctx) 246e5b75505Sopenharmony_ci{ 247e5b75505Sopenharmony_ci gcry_cipher_hd_t hd = ctx; 248e5b75505Sopenharmony_ci gcry_cipher_close(hd); 249e5b75505Sopenharmony_ci} 250e5b75505Sopenharmony_ci 251e5b75505Sopenharmony_ci 252e5b75505Sopenharmony_civoid * aes_decrypt_init(const u8 *key, size_t len) 253e5b75505Sopenharmony_ci{ 254e5b75505Sopenharmony_ci gcry_cipher_hd_t hd; 255e5b75505Sopenharmony_ci 256e5b75505Sopenharmony_ci if (TEST_FAIL()) 257e5b75505Sopenharmony_ci return NULL; 258e5b75505Sopenharmony_ci 259e5b75505Sopenharmony_ci if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != 260e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR) 261e5b75505Sopenharmony_ci return NULL; 262e5b75505Sopenharmony_ci if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { 263e5b75505Sopenharmony_ci gcry_cipher_close(hd); 264e5b75505Sopenharmony_ci return NULL; 265e5b75505Sopenharmony_ci } 266e5b75505Sopenharmony_ci 267e5b75505Sopenharmony_ci return hd; 268e5b75505Sopenharmony_ci} 269e5b75505Sopenharmony_ci 270e5b75505Sopenharmony_ci 271e5b75505Sopenharmony_ciint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 272e5b75505Sopenharmony_ci{ 273e5b75505Sopenharmony_ci gcry_cipher_hd_t hd = ctx; 274e5b75505Sopenharmony_ci gcry_cipher_decrypt(hd, plain, 16, crypt, 16); 275e5b75505Sopenharmony_ci return 0; 276e5b75505Sopenharmony_ci} 277e5b75505Sopenharmony_ci 278e5b75505Sopenharmony_ci 279e5b75505Sopenharmony_civoid aes_decrypt_deinit(void *ctx) 280e5b75505Sopenharmony_ci{ 281e5b75505Sopenharmony_ci gcry_cipher_hd_t hd = ctx; 282e5b75505Sopenharmony_ci gcry_cipher_close(hd); 283e5b75505Sopenharmony_ci} 284e5b75505Sopenharmony_ci 285e5b75505Sopenharmony_ci 286e5b75505Sopenharmony_ciint crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, 287e5b75505Sopenharmony_ci u8 *pubkey) 288e5b75505Sopenharmony_ci{ 289e5b75505Sopenharmony_ci size_t pubkey_len, pad; 290e5b75505Sopenharmony_ci 291e5b75505Sopenharmony_ci if (os_get_random(privkey, prime_len) < 0) 292e5b75505Sopenharmony_ci return -1; 293e5b75505Sopenharmony_ci if (os_memcmp(privkey, prime, prime_len) > 0) { 294e5b75505Sopenharmony_ci /* Make sure private value is smaller than prime */ 295e5b75505Sopenharmony_ci privkey[0] = 0; 296e5b75505Sopenharmony_ci } 297e5b75505Sopenharmony_ci 298e5b75505Sopenharmony_ci pubkey_len = prime_len; 299e5b75505Sopenharmony_ci if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, 300e5b75505Sopenharmony_ci pubkey, &pubkey_len) < 0) 301e5b75505Sopenharmony_ci return -1; 302e5b75505Sopenharmony_ci if (pubkey_len < prime_len) { 303e5b75505Sopenharmony_ci pad = prime_len - pubkey_len; 304e5b75505Sopenharmony_ci os_memmove(pubkey + pad, pubkey, pubkey_len); 305e5b75505Sopenharmony_ci os_memset(pubkey, 0, pad); 306e5b75505Sopenharmony_ci } 307e5b75505Sopenharmony_ci 308e5b75505Sopenharmony_ci return 0; 309e5b75505Sopenharmony_ci} 310e5b75505Sopenharmony_ci 311e5b75505Sopenharmony_ci 312e5b75505Sopenharmony_ciint crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, 313e5b75505Sopenharmony_ci const u8 *order, size_t order_len, 314e5b75505Sopenharmony_ci const u8 *privkey, size_t privkey_len, 315e5b75505Sopenharmony_ci const u8 *pubkey, size_t pubkey_len, 316e5b75505Sopenharmony_ci u8 *secret, size_t *len) 317e5b75505Sopenharmony_ci{ 318e5b75505Sopenharmony_ci gcry_mpi_t pub = NULL; 319e5b75505Sopenharmony_ci int res = -1; 320e5b75505Sopenharmony_ci 321e5b75505Sopenharmony_ci if (pubkey_len > prime_len || 322e5b75505Sopenharmony_ci (pubkey_len == prime_len && 323e5b75505Sopenharmony_ci os_memcmp(pubkey, prime, prime_len) >= 0)) 324e5b75505Sopenharmony_ci return -1; 325e5b75505Sopenharmony_ci 326e5b75505Sopenharmony_ci if (gcry_mpi_scan(&pub, GCRYMPI_FMT_USG, pubkey, pubkey_len, NULL) != 327e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR || 328e5b75505Sopenharmony_ci gcry_mpi_cmp_ui(pub, 1) <= 0) 329e5b75505Sopenharmony_ci goto fail; 330e5b75505Sopenharmony_ci 331e5b75505Sopenharmony_ci if (order) { 332e5b75505Sopenharmony_ci gcry_mpi_t p = NULL, q = NULL, tmp; 333e5b75505Sopenharmony_ci int failed; 334e5b75505Sopenharmony_ci 335e5b75505Sopenharmony_ci /* verify: pubkey^q == 1 mod p */ 336e5b75505Sopenharmony_ci tmp = gcry_mpi_new(prime_len * 8); 337e5b75505Sopenharmony_ci failed = !tmp || 338e5b75505Sopenharmony_ci gcry_mpi_scan(&p, GCRYMPI_FMT_USG, prime, prime_len, 339e5b75505Sopenharmony_ci NULL) != GPG_ERR_NO_ERROR || 340e5b75505Sopenharmony_ci gcry_mpi_scan(&q, GCRYMPI_FMT_USG, order, order_len, 341e5b75505Sopenharmony_ci NULL) != GPG_ERR_NO_ERROR; 342e5b75505Sopenharmony_ci if (!failed) { 343e5b75505Sopenharmony_ci gcry_mpi_powm(tmp, pub, q, p); 344e5b75505Sopenharmony_ci failed = gcry_mpi_cmp_ui(tmp, 1) != 0; 345e5b75505Sopenharmony_ci } 346e5b75505Sopenharmony_ci gcry_mpi_release(p); 347e5b75505Sopenharmony_ci gcry_mpi_release(q); 348e5b75505Sopenharmony_ci gcry_mpi_release(tmp); 349e5b75505Sopenharmony_ci if (failed) 350e5b75505Sopenharmony_ci goto fail; 351e5b75505Sopenharmony_ci } 352e5b75505Sopenharmony_ci 353e5b75505Sopenharmony_ci res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, 354e5b75505Sopenharmony_ci prime, prime_len, secret, len); 355e5b75505Sopenharmony_cifail: 356e5b75505Sopenharmony_ci gcry_mpi_release(pub); 357e5b75505Sopenharmony_ci return res; 358e5b75505Sopenharmony_ci} 359e5b75505Sopenharmony_ci 360e5b75505Sopenharmony_ci 361e5b75505Sopenharmony_ciint crypto_mod_exp(const u8 *base, size_t base_len, 362e5b75505Sopenharmony_ci const u8 *power, size_t power_len, 363e5b75505Sopenharmony_ci const u8 *modulus, size_t modulus_len, 364e5b75505Sopenharmony_ci u8 *result, size_t *result_len) 365e5b75505Sopenharmony_ci{ 366e5b75505Sopenharmony_ci gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, 367e5b75505Sopenharmony_ci bn_result = NULL; 368e5b75505Sopenharmony_ci int ret = -1; 369e5b75505Sopenharmony_ci 370e5b75505Sopenharmony_ci if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != 371e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR || 372e5b75505Sopenharmony_ci gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != 373e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR || 374e5b75505Sopenharmony_ci gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, 375e5b75505Sopenharmony_ci NULL) != GPG_ERR_NO_ERROR) 376e5b75505Sopenharmony_ci goto error; 377e5b75505Sopenharmony_ci bn_result = gcry_mpi_new(modulus_len * 8); 378e5b75505Sopenharmony_ci 379e5b75505Sopenharmony_ci gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); 380e5b75505Sopenharmony_ci 381e5b75505Sopenharmony_ci if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, 382e5b75505Sopenharmony_ci bn_result) != GPG_ERR_NO_ERROR) 383e5b75505Sopenharmony_ci goto error; 384e5b75505Sopenharmony_ci 385e5b75505Sopenharmony_ci ret = 0; 386e5b75505Sopenharmony_ci 387e5b75505Sopenharmony_cierror: 388e5b75505Sopenharmony_ci gcry_mpi_release(bn_base); 389e5b75505Sopenharmony_ci gcry_mpi_release(bn_exp); 390e5b75505Sopenharmony_ci gcry_mpi_release(bn_modulus); 391e5b75505Sopenharmony_ci gcry_mpi_release(bn_result); 392e5b75505Sopenharmony_ci return ret; 393e5b75505Sopenharmony_ci} 394e5b75505Sopenharmony_ci 395e5b75505Sopenharmony_ci 396e5b75505Sopenharmony_cistruct crypto_cipher { 397e5b75505Sopenharmony_ci gcry_cipher_hd_t enc; 398e5b75505Sopenharmony_ci gcry_cipher_hd_t dec; 399e5b75505Sopenharmony_ci}; 400e5b75505Sopenharmony_ci 401e5b75505Sopenharmony_ci 402e5b75505Sopenharmony_cistruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 403e5b75505Sopenharmony_ci const u8 *iv, const u8 *key, 404e5b75505Sopenharmony_ci size_t key_len) 405e5b75505Sopenharmony_ci{ 406e5b75505Sopenharmony_ci struct crypto_cipher *ctx; 407e5b75505Sopenharmony_ci gcry_error_t res; 408e5b75505Sopenharmony_ci enum gcry_cipher_algos a; 409e5b75505Sopenharmony_ci int ivlen; 410e5b75505Sopenharmony_ci 411e5b75505Sopenharmony_ci ctx = os_zalloc(sizeof(*ctx)); 412e5b75505Sopenharmony_ci if (ctx == NULL) 413e5b75505Sopenharmony_ci return NULL; 414e5b75505Sopenharmony_ci 415e5b75505Sopenharmony_ci switch (alg) { 416e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_RC4: 417e5b75505Sopenharmony_ci a = GCRY_CIPHER_ARCFOUR; 418e5b75505Sopenharmony_ci res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 419e5b75505Sopenharmony_ci 0); 420e5b75505Sopenharmony_ci gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); 421e5b75505Sopenharmony_ci break; 422e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_AES: 423e5b75505Sopenharmony_ci if (key_len == 24) 424e5b75505Sopenharmony_ci a = GCRY_CIPHER_AES192; 425e5b75505Sopenharmony_ci else if (key_len == 32) 426e5b75505Sopenharmony_ci a = GCRY_CIPHER_AES256; 427e5b75505Sopenharmony_ci else 428e5b75505Sopenharmony_ci a = GCRY_CIPHER_AES; 429e5b75505Sopenharmony_ci res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 430e5b75505Sopenharmony_ci gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 431e5b75505Sopenharmony_ci break; 432e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_3DES: 433e5b75505Sopenharmony_ci a = GCRY_CIPHER_3DES; 434e5b75505Sopenharmony_ci res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 435e5b75505Sopenharmony_ci gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 436e5b75505Sopenharmony_ci break; 437e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_DES: 438e5b75505Sopenharmony_ci a = GCRY_CIPHER_DES; 439e5b75505Sopenharmony_ci res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 440e5b75505Sopenharmony_ci gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 441e5b75505Sopenharmony_ci break; 442e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_RC2: 443e5b75505Sopenharmony_ci if (key_len == 5) 444e5b75505Sopenharmony_ci a = GCRY_CIPHER_RFC2268_40; 445e5b75505Sopenharmony_ci else 446e5b75505Sopenharmony_ci a = GCRY_CIPHER_RFC2268_128; 447e5b75505Sopenharmony_ci res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); 448e5b75505Sopenharmony_ci gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); 449e5b75505Sopenharmony_ci break; 450e5b75505Sopenharmony_ci default: 451e5b75505Sopenharmony_ci os_free(ctx); 452e5b75505Sopenharmony_ci return NULL; 453e5b75505Sopenharmony_ci } 454e5b75505Sopenharmony_ci 455e5b75505Sopenharmony_ci if (res != GPG_ERR_NO_ERROR) { 456e5b75505Sopenharmony_ci os_free(ctx); 457e5b75505Sopenharmony_ci return NULL; 458e5b75505Sopenharmony_ci } 459e5b75505Sopenharmony_ci 460e5b75505Sopenharmony_ci if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || 461e5b75505Sopenharmony_ci gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { 462e5b75505Sopenharmony_ci gcry_cipher_close(ctx->enc); 463e5b75505Sopenharmony_ci gcry_cipher_close(ctx->dec); 464e5b75505Sopenharmony_ci os_free(ctx); 465e5b75505Sopenharmony_ci return NULL; 466e5b75505Sopenharmony_ci } 467e5b75505Sopenharmony_ci 468e5b75505Sopenharmony_ci ivlen = gcry_cipher_get_algo_blklen(a); 469e5b75505Sopenharmony_ci if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || 470e5b75505Sopenharmony_ci gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { 471e5b75505Sopenharmony_ci gcry_cipher_close(ctx->enc); 472e5b75505Sopenharmony_ci gcry_cipher_close(ctx->dec); 473e5b75505Sopenharmony_ci os_free(ctx); 474e5b75505Sopenharmony_ci return NULL; 475e5b75505Sopenharmony_ci } 476e5b75505Sopenharmony_ci 477e5b75505Sopenharmony_ci return ctx; 478e5b75505Sopenharmony_ci} 479e5b75505Sopenharmony_ci 480e5b75505Sopenharmony_ci 481e5b75505Sopenharmony_ciint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 482e5b75505Sopenharmony_ci u8 *crypt, size_t len) 483e5b75505Sopenharmony_ci{ 484e5b75505Sopenharmony_ci if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != 485e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR) 486e5b75505Sopenharmony_ci return -1; 487e5b75505Sopenharmony_ci return 0; 488e5b75505Sopenharmony_ci} 489e5b75505Sopenharmony_ci 490e5b75505Sopenharmony_ci 491e5b75505Sopenharmony_ciint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 492e5b75505Sopenharmony_ci u8 *plain, size_t len) 493e5b75505Sopenharmony_ci{ 494e5b75505Sopenharmony_ci if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != 495e5b75505Sopenharmony_ci GPG_ERR_NO_ERROR) 496e5b75505Sopenharmony_ci return -1; 497e5b75505Sopenharmony_ci return 0; 498e5b75505Sopenharmony_ci} 499e5b75505Sopenharmony_ci 500e5b75505Sopenharmony_ci 501e5b75505Sopenharmony_civoid crypto_cipher_deinit(struct crypto_cipher *ctx) 502e5b75505Sopenharmony_ci{ 503e5b75505Sopenharmony_ci gcry_cipher_close(ctx->enc); 504e5b75505Sopenharmony_ci gcry_cipher_close(ctx->dec); 505e5b75505Sopenharmony_ci os_free(ctx); 506e5b75505Sopenharmony_ci} 507