1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) 3e5b75505Sopenharmony_ci * Copyright (c) 2005-2006, 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 <tomcrypt.h> 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "common.h" 13e5b75505Sopenharmony_ci#include "crypto.h" 14e5b75505Sopenharmony_ci 15e5b75505Sopenharmony_ci#ifndef mp_init_multi 16e5b75505Sopenharmony_ci#define mp_init_multi ltc_init_multi 17e5b75505Sopenharmony_ci#define mp_clear_multi ltc_deinit_multi 18e5b75505Sopenharmony_ci#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) 19e5b75505Sopenharmony_ci#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) 20e5b75505Sopenharmony_ci#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) 21e5b75505Sopenharmony_ci#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) 22e5b75505Sopenharmony_ci#endif 23e5b75505Sopenharmony_ci 24e5b75505Sopenharmony_ci 25e5b75505Sopenharmony_ciint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 26e5b75505Sopenharmony_ci{ 27e5b75505Sopenharmony_ci hash_state md; 28e5b75505Sopenharmony_ci size_t i; 29e5b75505Sopenharmony_ci 30e5b75505Sopenharmony_ci md4_init(&md); 31e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 32e5b75505Sopenharmony_ci md4_process(&md, addr[i], len[i]); 33e5b75505Sopenharmony_ci md4_done(&md, mac); 34e5b75505Sopenharmony_ci return 0; 35e5b75505Sopenharmony_ci} 36e5b75505Sopenharmony_ci 37e5b75505Sopenharmony_ci 38e5b75505Sopenharmony_ciint des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 39e5b75505Sopenharmony_ci{ 40e5b75505Sopenharmony_ci u8 pkey[8], next, tmp; 41e5b75505Sopenharmony_ci int i; 42e5b75505Sopenharmony_ci symmetric_key skey; 43e5b75505Sopenharmony_ci 44e5b75505Sopenharmony_ci /* Add parity bits to the key */ 45e5b75505Sopenharmony_ci next = 0; 46e5b75505Sopenharmony_ci for (i = 0; i < 7; i++) { 47e5b75505Sopenharmony_ci tmp = key[i]; 48e5b75505Sopenharmony_ci pkey[i] = (tmp >> i) | next | 1; 49e5b75505Sopenharmony_ci next = tmp << (7 - i); 50e5b75505Sopenharmony_ci } 51e5b75505Sopenharmony_ci pkey[i] = next | 1; 52e5b75505Sopenharmony_ci 53e5b75505Sopenharmony_ci des_setup(pkey, 8, 0, &skey); 54e5b75505Sopenharmony_ci des_ecb_encrypt(clear, cypher, &skey); 55e5b75505Sopenharmony_ci des_done(&skey); 56e5b75505Sopenharmony_ci return 0; 57e5b75505Sopenharmony_ci} 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_ci 60e5b75505Sopenharmony_ciint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 61e5b75505Sopenharmony_ci{ 62e5b75505Sopenharmony_ci hash_state md; 63e5b75505Sopenharmony_ci size_t i; 64e5b75505Sopenharmony_ci 65e5b75505Sopenharmony_ci md5_init(&md); 66e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 67e5b75505Sopenharmony_ci md5_process(&md, addr[i], len[i]); 68e5b75505Sopenharmony_ci md5_done(&md, mac); 69e5b75505Sopenharmony_ci return 0; 70e5b75505Sopenharmony_ci} 71e5b75505Sopenharmony_ci 72e5b75505Sopenharmony_ci 73e5b75505Sopenharmony_ciint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 74e5b75505Sopenharmony_ci{ 75e5b75505Sopenharmony_ci hash_state md; 76e5b75505Sopenharmony_ci size_t i; 77e5b75505Sopenharmony_ci 78e5b75505Sopenharmony_ci sha1_init(&md); 79e5b75505Sopenharmony_ci for (i = 0; i < num_elem; i++) 80e5b75505Sopenharmony_ci sha1_process(&md, addr[i], len[i]); 81e5b75505Sopenharmony_ci sha1_done(&md, mac); 82e5b75505Sopenharmony_ci return 0; 83e5b75505Sopenharmony_ci} 84e5b75505Sopenharmony_ci 85e5b75505Sopenharmony_ci 86e5b75505Sopenharmony_civoid * aes_encrypt_init(const u8 *key, size_t len) 87e5b75505Sopenharmony_ci{ 88e5b75505Sopenharmony_ci symmetric_key *skey; 89e5b75505Sopenharmony_ci skey = os_malloc(sizeof(*skey)); 90e5b75505Sopenharmony_ci if (skey == NULL) 91e5b75505Sopenharmony_ci return NULL; 92e5b75505Sopenharmony_ci if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 93e5b75505Sopenharmony_ci os_free(skey); 94e5b75505Sopenharmony_ci return NULL; 95e5b75505Sopenharmony_ci } 96e5b75505Sopenharmony_ci return skey; 97e5b75505Sopenharmony_ci} 98e5b75505Sopenharmony_ci 99e5b75505Sopenharmony_ci 100e5b75505Sopenharmony_ciint aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 101e5b75505Sopenharmony_ci{ 102e5b75505Sopenharmony_ci symmetric_key *skey = ctx; 103e5b75505Sopenharmony_ci return aes_ecb_encrypt(plain, crypt, skey) == CRYPT_OK ? 0 : -1; 104e5b75505Sopenharmony_ci} 105e5b75505Sopenharmony_ci 106e5b75505Sopenharmony_ci 107e5b75505Sopenharmony_civoid aes_encrypt_deinit(void *ctx) 108e5b75505Sopenharmony_ci{ 109e5b75505Sopenharmony_ci symmetric_key *skey = ctx; 110e5b75505Sopenharmony_ci aes_done(skey); 111e5b75505Sopenharmony_ci os_free(skey); 112e5b75505Sopenharmony_ci} 113e5b75505Sopenharmony_ci 114e5b75505Sopenharmony_ci 115e5b75505Sopenharmony_civoid * aes_decrypt_init(const u8 *key, size_t len) 116e5b75505Sopenharmony_ci{ 117e5b75505Sopenharmony_ci symmetric_key *skey; 118e5b75505Sopenharmony_ci skey = os_malloc(sizeof(*skey)); 119e5b75505Sopenharmony_ci if (skey == NULL) 120e5b75505Sopenharmony_ci return NULL; 121e5b75505Sopenharmony_ci if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 122e5b75505Sopenharmony_ci os_free(skey); 123e5b75505Sopenharmony_ci return NULL; 124e5b75505Sopenharmony_ci } 125e5b75505Sopenharmony_ci return skey; 126e5b75505Sopenharmony_ci} 127e5b75505Sopenharmony_ci 128e5b75505Sopenharmony_ci 129e5b75505Sopenharmony_ciint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 130e5b75505Sopenharmony_ci{ 131e5b75505Sopenharmony_ci symmetric_key *skey = ctx; 132e5b75505Sopenharmony_ci return aes_ecb_encrypt(plain, (u8 *) crypt, skey) == CRYPT_OK ? 0 : -1; 133e5b75505Sopenharmony_ci} 134e5b75505Sopenharmony_ci 135e5b75505Sopenharmony_ci 136e5b75505Sopenharmony_civoid aes_decrypt_deinit(void *ctx) 137e5b75505Sopenharmony_ci{ 138e5b75505Sopenharmony_ci symmetric_key *skey = ctx; 139e5b75505Sopenharmony_ci aes_done(skey); 140e5b75505Sopenharmony_ci os_free(skey); 141e5b75505Sopenharmony_ci} 142e5b75505Sopenharmony_ci 143e5b75505Sopenharmony_ci 144e5b75505Sopenharmony_cistruct crypto_hash { 145e5b75505Sopenharmony_ci enum crypto_hash_alg alg; 146e5b75505Sopenharmony_ci int error; 147e5b75505Sopenharmony_ci union { 148e5b75505Sopenharmony_ci hash_state md; 149e5b75505Sopenharmony_ci hmac_state hmac; 150e5b75505Sopenharmony_ci } u; 151e5b75505Sopenharmony_ci}; 152e5b75505Sopenharmony_ci 153e5b75505Sopenharmony_ci 154e5b75505Sopenharmony_cistruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 155e5b75505Sopenharmony_ci size_t key_len) 156e5b75505Sopenharmony_ci{ 157e5b75505Sopenharmony_ci struct crypto_hash *ctx; 158e5b75505Sopenharmony_ci 159e5b75505Sopenharmony_ci ctx = os_zalloc(sizeof(*ctx)); 160e5b75505Sopenharmony_ci if (ctx == NULL) 161e5b75505Sopenharmony_ci return NULL; 162e5b75505Sopenharmony_ci 163e5b75505Sopenharmony_ci ctx->alg = alg; 164e5b75505Sopenharmony_ci 165e5b75505Sopenharmony_ci switch (alg) { 166e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_MD5: 167e5b75505Sopenharmony_ci if (md5_init(&ctx->u.md) != CRYPT_OK) 168e5b75505Sopenharmony_ci goto fail; 169e5b75505Sopenharmony_ci break; 170e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_SHA1: 171e5b75505Sopenharmony_ci if (sha1_init(&ctx->u.md) != CRYPT_OK) 172e5b75505Sopenharmony_ci goto fail; 173e5b75505Sopenharmony_ci break; 174e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_HMAC_MD5: 175e5b75505Sopenharmony_ci if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != 176e5b75505Sopenharmony_ci CRYPT_OK) 177e5b75505Sopenharmony_ci goto fail; 178e5b75505Sopenharmony_ci break; 179e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_HMAC_SHA1: 180e5b75505Sopenharmony_ci if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != 181e5b75505Sopenharmony_ci CRYPT_OK) 182e5b75505Sopenharmony_ci goto fail; 183e5b75505Sopenharmony_ci break; 184e5b75505Sopenharmony_ci default: 185e5b75505Sopenharmony_ci goto fail; 186e5b75505Sopenharmony_ci } 187e5b75505Sopenharmony_ci 188e5b75505Sopenharmony_ci return ctx; 189e5b75505Sopenharmony_ci 190e5b75505Sopenharmony_cifail: 191e5b75505Sopenharmony_ci os_free(ctx); 192e5b75505Sopenharmony_ci return NULL; 193e5b75505Sopenharmony_ci} 194e5b75505Sopenharmony_ci 195e5b75505Sopenharmony_civoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 196e5b75505Sopenharmony_ci{ 197e5b75505Sopenharmony_ci if (ctx == NULL || ctx->error) 198e5b75505Sopenharmony_ci return; 199e5b75505Sopenharmony_ci 200e5b75505Sopenharmony_ci switch (ctx->alg) { 201e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_MD5: 202e5b75505Sopenharmony_ci ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; 203e5b75505Sopenharmony_ci break; 204e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_SHA1: 205e5b75505Sopenharmony_ci ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; 206e5b75505Sopenharmony_ci break; 207e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_HMAC_MD5: 208e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_HMAC_SHA1: 209e5b75505Sopenharmony_ci ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; 210e5b75505Sopenharmony_ci break; 211e5b75505Sopenharmony_ci } 212e5b75505Sopenharmony_ci} 213e5b75505Sopenharmony_ci 214e5b75505Sopenharmony_ci 215e5b75505Sopenharmony_ciint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 216e5b75505Sopenharmony_ci{ 217e5b75505Sopenharmony_ci int ret = 0; 218e5b75505Sopenharmony_ci unsigned long clen; 219e5b75505Sopenharmony_ci 220e5b75505Sopenharmony_ci if (ctx == NULL) 221e5b75505Sopenharmony_ci return -2; 222e5b75505Sopenharmony_ci 223e5b75505Sopenharmony_ci if (mac == NULL || len == NULL) { 224e5b75505Sopenharmony_ci os_free(ctx); 225e5b75505Sopenharmony_ci return 0; 226e5b75505Sopenharmony_ci } 227e5b75505Sopenharmony_ci 228e5b75505Sopenharmony_ci if (ctx->error) { 229e5b75505Sopenharmony_ci os_free(ctx); 230e5b75505Sopenharmony_ci return -2; 231e5b75505Sopenharmony_ci } 232e5b75505Sopenharmony_ci 233e5b75505Sopenharmony_ci switch (ctx->alg) { 234e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_MD5: 235e5b75505Sopenharmony_ci if (*len < 16) { 236e5b75505Sopenharmony_ci *len = 16; 237e5b75505Sopenharmony_ci os_free(ctx); 238e5b75505Sopenharmony_ci return -1; 239e5b75505Sopenharmony_ci } 240e5b75505Sopenharmony_ci *len = 16; 241e5b75505Sopenharmony_ci if (md5_done(&ctx->u.md, mac) != CRYPT_OK) 242e5b75505Sopenharmony_ci ret = -2; 243e5b75505Sopenharmony_ci break; 244e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_SHA1: 245e5b75505Sopenharmony_ci if (*len < 20) { 246e5b75505Sopenharmony_ci *len = 20; 247e5b75505Sopenharmony_ci os_free(ctx); 248e5b75505Sopenharmony_ci return -1; 249e5b75505Sopenharmony_ci } 250e5b75505Sopenharmony_ci *len = 20; 251e5b75505Sopenharmony_ci if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) 252e5b75505Sopenharmony_ci ret = -2; 253e5b75505Sopenharmony_ci break; 254e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_HMAC_SHA1: 255e5b75505Sopenharmony_ci if (*len < 20) { 256e5b75505Sopenharmony_ci *len = 20; 257e5b75505Sopenharmony_ci os_free(ctx); 258e5b75505Sopenharmony_ci return -1; 259e5b75505Sopenharmony_ci } 260e5b75505Sopenharmony_ci /* continue */ 261e5b75505Sopenharmony_ci case CRYPTO_HASH_ALG_HMAC_MD5: 262e5b75505Sopenharmony_ci if (*len < 16) { 263e5b75505Sopenharmony_ci *len = 16; 264e5b75505Sopenharmony_ci os_free(ctx); 265e5b75505Sopenharmony_ci return -1; 266e5b75505Sopenharmony_ci } 267e5b75505Sopenharmony_ci clen = *len; 268e5b75505Sopenharmony_ci if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { 269e5b75505Sopenharmony_ci os_free(ctx); 270e5b75505Sopenharmony_ci return -1; 271e5b75505Sopenharmony_ci } 272e5b75505Sopenharmony_ci *len = clen; 273e5b75505Sopenharmony_ci break; 274e5b75505Sopenharmony_ci default: 275e5b75505Sopenharmony_ci ret = -2; 276e5b75505Sopenharmony_ci break; 277e5b75505Sopenharmony_ci } 278e5b75505Sopenharmony_ci 279e5b75505Sopenharmony_ci os_free(ctx); 280e5b75505Sopenharmony_ci 281e5b75505Sopenharmony_ci if (TEST_FAIL()) 282e5b75505Sopenharmony_ci return -1; 283e5b75505Sopenharmony_ci 284e5b75505Sopenharmony_ci return ret; 285e5b75505Sopenharmony_ci} 286e5b75505Sopenharmony_ci 287e5b75505Sopenharmony_ci 288e5b75505Sopenharmony_cistruct crypto_cipher { 289e5b75505Sopenharmony_ci int rc4; 290e5b75505Sopenharmony_ci union { 291e5b75505Sopenharmony_ci symmetric_CBC cbc; 292e5b75505Sopenharmony_ci struct { 293e5b75505Sopenharmony_ci size_t used_bytes; 294e5b75505Sopenharmony_ci u8 key[16]; 295e5b75505Sopenharmony_ci size_t keylen; 296e5b75505Sopenharmony_ci } rc4; 297e5b75505Sopenharmony_ci } u; 298e5b75505Sopenharmony_ci}; 299e5b75505Sopenharmony_ci 300e5b75505Sopenharmony_ci 301e5b75505Sopenharmony_cistruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 302e5b75505Sopenharmony_ci const u8 *iv, const u8 *key, 303e5b75505Sopenharmony_ci size_t key_len) 304e5b75505Sopenharmony_ci{ 305e5b75505Sopenharmony_ci struct crypto_cipher *ctx; 306e5b75505Sopenharmony_ci int idx, res, rc4 = 0; 307e5b75505Sopenharmony_ci 308e5b75505Sopenharmony_ci switch (alg) { 309e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_AES: 310e5b75505Sopenharmony_ci idx = find_cipher("aes"); 311e5b75505Sopenharmony_ci break; 312e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_3DES: 313e5b75505Sopenharmony_ci idx = find_cipher("3des"); 314e5b75505Sopenharmony_ci break; 315e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_DES: 316e5b75505Sopenharmony_ci idx = find_cipher("des"); 317e5b75505Sopenharmony_ci break; 318e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_RC2: 319e5b75505Sopenharmony_ci idx = find_cipher("rc2"); 320e5b75505Sopenharmony_ci break; 321e5b75505Sopenharmony_ci case CRYPTO_CIPHER_ALG_RC4: 322e5b75505Sopenharmony_ci idx = -1; 323e5b75505Sopenharmony_ci rc4 = 1; 324e5b75505Sopenharmony_ci break; 325e5b75505Sopenharmony_ci default: 326e5b75505Sopenharmony_ci return NULL; 327e5b75505Sopenharmony_ci } 328e5b75505Sopenharmony_ci 329e5b75505Sopenharmony_ci ctx = os_zalloc(sizeof(*ctx)); 330e5b75505Sopenharmony_ci if (ctx == NULL) 331e5b75505Sopenharmony_ci return NULL; 332e5b75505Sopenharmony_ci 333e5b75505Sopenharmony_ci if (rc4) { 334e5b75505Sopenharmony_ci ctx->rc4 = 1; 335e5b75505Sopenharmony_ci if (key_len > sizeof(ctx->u.rc4.key)) { 336e5b75505Sopenharmony_ci os_free(ctx); 337e5b75505Sopenharmony_ci return NULL; 338e5b75505Sopenharmony_ci } 339e5b75505Sopenharmony_ci ctx->u.rc4.keylen = key_len; 340e5b75505Sopenharmony_ci os_memcpy(ctx->u.rc4.key, key, key_len); 341e5b75505Sopenharmony_ci } else { 342e5b75505Sopenharmony_ci res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); 343e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 344e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " 345e5b75505Sopenharmony_ci "failed: %s", error_to_string(res)); 346e5b75505Sopenharmony_ci os_free(ctx); 347e5b75505Sopenharmony_ci return NULL; 348e5b75505Sopenharmony_ci } 349e5b75505Sopenharmony_ci } 350e5b75505Sopenharmony_ci 351e5b75505Sopenharmony_ci return ctx; 352e5b75505Sopenharmony_ci} 353e5b75505Sopenharmony_ci 354e5b75505Sopenharmony_ciint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 355e5b75505Sopenharmony_ci u8 *crypt, size_t len) 356e5b75505Sopenharmony_ci{ 357e5b75505Sopenharmony_ci int res; 358e5b75505Sopenharmony_ci 359e5b75505Sopenharmony_ci if (ctx->rc4) { 360e5b75505Sopenharmony_ci if (plain != crypt) 361e5b75505Sopenharmony_ci os_memcpy(crypt, plain, len); 362e5b75505Sopenharmony_ci rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 363e5b75505Sopenharmony_ci ctx->u.rc4.used_bytes, crypt, len); 364e5b75505Sopenharmony_ci ctx->u.rc4.used_bytes += len; 365e5b75505Sopenharmony_ci return 0; 366e5b75505Sopenharmony_ci } 367e5b75505Sopenharmony_ci 368e5b75505Sopenharmony_ci res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); 369e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 370e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " 371e5b75505Sopenharmony_ci "failed: %s", error_to_string(res)); 372e5b75505Sopenharmony_ci return -1; 373e5b75505Sopenharmony_ci } 374e5b75505Sopenharmony_ci return 0; 375e5b75505Sopenharmony_ci} 376e5b75505Sopenharmony_ci 377e5b75505Sopenharmony_ci 378e5b75505Sopenharmony_ciint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 379e5b75505Sopenharmony_ci u8 *plain, size_t len) 380e5b75505Sopenharmony_ci{ 381e5b75505Sopenharmony_ci int res; 382e5b75505Sopenharmony_ci 383e5b75505Sopenharmony_ci if (ctx->rc4) { 384e5b75505Sopenharmony_ci if (plain != crypt) 385e5b75505Sopenharmony_ci os_memcpy(plain, crypt, len); 386e5b75505Sopenharmony_ci rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 387e5b75505Sopenharmony_ci ctx->u.rc4.used_bytes, plain, len); 388e5b75505Sopenharmony_ci ctx->u.rc4.used_bytes += len; 389e5b75505Sopenharmony_ci return 0; 390e5b75505Sopenharmony_ci } 391e5b75505Sopenharmony_ci 392e5b75505Sopenharmony_ci res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); 393e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 394e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " 395e5b75505Sopenharmony_ci "failed: %s", error_to_string(res)); 396e5b75505Sopenharmony_ci return -1; 397e5b75505Sopenharmony_ci } 398e5b75505Sopenharmony_ci 399e5b75505Sopenharmony_ci return 0; 400e5b75505Sopenharmony_ci} 401e5b75505Sopenharmony_ci 402e5b75505Sopenharmony_ci 403e5b75505Sopenharmony_civoid crypto_cipher_deinit(struct crypto_cipher *ctx) 404e5b75505Sopenharmony_ci{ 405e5b75505Sopenharmony_ci if (!ctx->rc4) 406e5b75505Sopenharmony_ci cbc_done(&ctx->u.cbc); 407e5b75505Sopenharmony_ci os_free(ctx); 408e5b75505Sopenharmony_ci} 409e5b75505Sopenharmony_ci 410e5b75505Sopenharmony_ci 411e5b75505Sopenharmony_cistruct crypto_public_key { 412e5b75505Sopenharmony_ci rsa_key rsa; 413e5b75505Sopenharmony_ci}; 414e5b75505Sopenharmony_ci 415e5b75505Sopenharmony_cistruct crypto_private_key { 416e5b75505Sopenharmony_ci rsa_key rsa; 417e5b75505Sopenharmony_ci}; 418e5b75505Sopenharmony_ci 419e5b75505Sopenharmony_ci 420e5b75505Sopenharmony_cistruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) 421e5b75505Sopenharmony_ci{ 422e5b75505Sopenharmony_ci int res; 423e5b75505Sopenharmony_ci struct crypto_public_key *pk; 424e5b75505Sopenharmony_ci 425e5b75505Sopenharmony_ci pk = os_zalloc(sizeof(*pk)); 426e5b75505Sopenharmony_ci if (pk == NULL) 427e5b75505Sopenharmony_ci return NULL; 428e5b75505Sopenharmony_ci 429e5b75505Sopenharmony_ci res = rsa_import(key, len, &pk->rsa); 430e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 431e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 432e5b75505Sopenharmony_ci "public key (res=%d '%s')", 433e5b75505Sopenharmony_ci res, error_to_string(res)); 434e5b75505Sopenharmony_ci os_free(pk); 435e5b75505Sopenharmony_ci return NULL; 436e5b75505Sopenharmony_ci } 437e5b75505Sopenharmony_ci 438e5b75505Sopenharmony_ci if (pk->rsa.type != PK_PUBLIC) { 439e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " 440e5b75505Sopenharmony_ci "correct type"); 441e5b75505Sopenharmony_ci rsa_free(&pk->rsa); 442e5b75505Sopenharmony_ci os_free(pk); 443e5b75505Sopenharmony_ci return NULL; 444e5b75505Sopenharmony_ci } 445e5b75505Sopenharmony_ci 446e5b75505Sopenharmony_ci return pk; 447e5b75505Sopenharmony_ci} 448e5b75505Sopenharmony_ci 449e5b75505Sopenharmony_ci 450e5b75505Sopenharmony_cistruct crypto_private_key * crypto_private_key_import(const u8 *key, 451e5b75505Sopenharmony_ci size_t len, 452e5b75505Sopenharmony_ci const char *passwd) 453e5b75505Sopenharmony_ci{ 454e5b75505Sopenharmony_ci int res; 455e5b75505Sopenharmony_ci struct crypto_private_key *pk; 456e5b75505Sopenharmony_ci 457e5b75505Sopenharmony_ci pk = os_zalloc(sizeof(*pk)); 458e5b75505Sopenharmony_ci if (pk == NULL) 459e5b75505Sopenharmony_ci return NULL; 460e5b75505Sopenharmony_ci 461e5b75505Sopenharmony_ci res = rsa_import(key, len, &pk->rsa); 462e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 463e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 464e5b75505Sopenharmony_ci "private key (res=%d '%s')", 465e5b75505Sopenharmony_ci res, error_to_string(res)); 466e5b75505Sopenharmony_ci os_free(pk); 467e5b75505Sopenharmony_ci return NULL; 468e5b75505Sopenharmony_ci } 469e5b75505Sopenharmony_ci 470e5b75505Sopenharmony_ci if (pk->rsa.type != PK_PRIVATE) { 471e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " 472e5b75505Sopenharmony_ci "correct type"); 473e5b75505Sopenharmony_ci rsa_free(&pk->rsa); 474e5b75505Sopenharmony_ci os_free(pk); 475e5b75505Sopenharmony_ci return NULL; 476e5b75505Sopenharmony_ci } 477e5b75505Sopenharmony_ci 478e5b75505Sopenharmony_ci return pk; 479e5b75505Sopenharmony_ci} 480e5b75505Sopenharmony_ci 481e5b75505Sopenharmony_ci 482e5b75505Sopenharmony_cistruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, 483e5b75505Sopenharmony_ci size_t len) 484e5b75505Sopenharmony_ci{ 485e5b75505Sopenharmony_ci /* No X.509 support in LibTomCrypt */ 486e5b75505Sopenharmony_ci return NULL; 487e5b75505Sopenharmony_ci} 488e5b75505Sopenharmony_ci 489e5b75505Sopenharmony_ci 490e5b75505Sopenharmony_cistatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, 491e5b75505Sopenharmony_ci const u8 *in, size_t inlen, 492e5b75505Sopenharmony_ci u8 *out, size_t *outlen) 493e5b75505Sopenharmony_ci{ 494e5b75505Sopenharmony_ci size_t ps_len; 495e5b75505Sopenharmony_ci u8 *pos; 496e5b75505Sopenharmony_ci 497e5b75505Sopenharmony_ci /* 498e5b75505Sopenharmony_ci * PKCS #1 v1.5, 8.1: 499e5b75505Sopenharmony_ci * 500e5b75505Sopenharmony_ci * EB = 00 || BT || PS || 00 || D 501e5b75505Sopenharmony_ci * BT = 00 or 01 for private-key operation; 02 for public-key operation 502e5b75505Sopenharmony_ci * PS = k-3-||D||; at least eight octets 503e5b75505Sopenharmony_ci * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) 504e5b75505Sopenharmony_ci * k = length of modulus in octets (modlen) 505e5b75505Sopenharmony_ci */ 506e5b75505Sopenharmony_ci 507e5b75505Sopenharmony_ci if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { 508e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " 509e5b75505Sopenharmony_ci "lengths (modlen=%lu outlen=%lu inlen=%lu)", 510e5b75505Sopenharmony_ci __func__, (unsigned long) modlen, 511e5b75505Sopenharmony_ci (unsigned long) *outlen, 512e5b75505Sopenharmony_ci (unsigned long) inlen); 513e5b75505Sopenharmony_ci return -1; 514e5b75505Sopenharmony_ci } 515e5b75505Sopenharmony_ci 516e5b75505Sopenharmony_ci pos = out; 517e5b75505Sopenharmony_ci *pos++ = 0x00; 518e5b75505Sopenharmony_ci *pos++ = block_type; /* BT */ 519e5b75505Sopenharmony_ci ps_len = modlen - inlen - 3; 520e5b75505Sopenharmony_ci switch (block_type) { 521e5b75505Sopenharmony_ci case 0: 522e5b75505Sopenharmony_ci os_memset(pos, 0x00, ps_len); 523e5b75505Sopenharmony_ci pos += ps_len; 524e5b75505Sopenharmony_ci break; 525e5b75505Sopenharmony_ci case 1: 526e5b75505Sopenharmony_ci os_memset(pos, 0xff, ps_len); 527e5b75505Sopenharmony_ci pos += ps_len; 528e5b75505Sopenharmony_ci break; 529e5b75505Sopenharmony_ci case 2: 530e5b75505Sopenharmony_ci if (os_get_random(pos, ps_len) < 0) { 531e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " 532e5b75505Sopenharmony_ci "random data for PS", __func__); 533e5b75505Sopenharmony_ci return -1; 534e5b75505Sopenharmony_ci } 535e5b75505Sopenharmony_ci while (ps_len--) { 536e5b75505Sopenharmony_ci if (*pos == 0x00) 537e5b75505Sopenharmony_ci *pos = 0x01; 538e5b75505Sopenharmony_ci pos++; 539e5b75505Sopenharmony_ci } 540e5b75505Sopenharmony_ci break; 541e5b75505Sopenharmony_ci default: 542e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " 543e5b75505Sopenharmony_ci "%d", __func__, block_type); 544e5b75505Sopenharmony_ci return -1; 545e5b75505Sopenharmony_ci } 546e5b75505Sopenharmony_ci *pos++ = 0x00; 547e5b75505Sopenharmony_ci os_memcpy(pos, in, inlen); /* D */ 548e5b75505Sopenharmony_ci 549e5b75505Sopenharmony_ci return 0; 550e5b75505Sopenharmony_ci} 551e5b75505Sopenharmony_ci 552e5b75505Sopenharmony_ci 553e5b75505Sopenharmony_cistatic int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, 554e5b75505Sopenharmony_ci const u8 *in, size_t inlen, 555e5b75505Sopenharmony_ci u8 *out, size_t *outlen) 556e5b75505Sopenharmony_ci{ 557e5b75505Sopenharmony_ci unsigned long len, modlen; 558e5b75505Sopenharmony_ci int res; 559e5b75505Sopenharmony_ci 560e5b75505Sopenharmony_ci modlen = mp_unsigned_bin_size(key->N); 561e5b75505Sopenharmony_ci 562e5b75505Sopenharmony_ci if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, 563e5b75505Sopenharmony_ci out, outlen) < 0) 564e5b75505Sopenharmony_ci return -1; 565e5b75505Sopenharmony_ci 566e5b75505Sopenharmony_ci len = *outlen; 567e5b75505Sopenharmony_ci res = rsa_exptmod(out, modlen, out, &len, key_type, key); 568e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 569e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 570e5b75505Sopenharmony_ci error_to_string(res)); 571e5b75505Sopenharmony_ci return -1; 572e5b75505Sopenharmony_ci } 573e5b75505Sopenharmony_ci *outlen = len; 574e5b75505Sopenharmony_ci 575e5b75505Sopenharmony_ci return 0; 576e5b75505Sopenharmony_ci} 577e5b75505Sopenharmony_ci 578e5b75505Sopenharmony_ci 579e5b75505Sopenharmony_ciint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, 580e5b75505Sopenharmony_ci const u8 *in, size_t inlen, 581e5b75505Sopenharmony_ci u8 *out, size_t *outlen) 582e5b75505Sopenharmony_ci{ 583e5b75505Sopenharmony_ci return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, 584e5b75505Sopenharmony_ci out, outlen); 585e5b75505Sopenharmony_ci} 586e5b75505Sopenharmony_ci 587e5b75505Sopenharmony_ci 588e5b75505Sopenharmony_ciint crypto_private_key_sign_pkcs1(struct crypto_private_key *key, 589e5b75505Sopenharmony_ci const u8 *in, size_t inlen, 590e5b75505Sopenharmony_ci u8 *out, size_t *outlen) 591e5b75505Sopenharmony_ci{ 592e5b75505Sopenharmony_ci return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, 593e5b75505Sopenharmony_ci out, outlen); 594e5b75505Sopenharmony_ci} 595e5b75505Sopenharmony_ci 596e5b75505Sopenharmony_ci 597e5b75505Sopenharmony_civoid crypto_public_key_free(struct crypto_public_key *key) 598e5b75505Sopenharmony_ci{ 599e5b75505Sopenharmony_ci if (key) { 600e5b75505Sopenharmony_ci rsa_free(&key->rsa); 601e5b75505Sopenharmony_ci os_free(key); 602e5b75505Sopenharmony_ci } 603e5b75505Sopenharmony_ci} 604e5b75505Sopenharmony_ci 605e5b75505Sopenharmony_ci 606e5b75505Sopenharmony_civoid crypto_private_key_free(struct crypto_private_key *key) 607e5b75505Sopenharmony_ci{ 608e5b75505Sopenharmony_ci if (key) { 609e5b75505Sopenharmony_ci rsa_free(&key->rsa); 610e5b75505Sopenharmony_ci os_free(key); 611e5b75505Sopenharmony_ci } 612e5b75505Sopenharmony_ci} 613e5b75505Sopenharmony_ci 614e5b75505Sopenharmony_ci 615e5b75505Sopenharmony_ciint crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, 616e5b75505Sopenharmony_ci const u8 *crypt, size_t crypt_len, 617e5b75505Sopenharmony_ci u8 *plain, size_t *plain_len) 618e5b75505Sopenharmony_ci{ 619e5b75505Sopenharmony_ci int res; 620e5b75505Sopenharmony_ci unsigned long len; 621e5b75505Sopenharmony_ci u8 *pos; 622e5b75505Sopenharmony_ci 623e5b75505Sopenharmony_ci len = *plain_len; 624e5b75505Sopenharmony_ci res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, 625e5b75505Sopenharmony_ci &key->rsa); 626e5b75505Sopenharmony_ci if (res != CRYPT_OK) { 627e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 628e5b75505Sopenharmony_ci error_to_string(res)); 629e5b75505Sopenharmony_ci return -1; 630e5b75505Sopenharmony_ci } 631e5b75505Sopenharmony_ci 632e5b75505Sopenharmony_ci /* 633e5b75505Sopenharmony_ci * PKCS #1 v1.5, 8.1: 634e5b75505Sopenharmony_ci * 635e5b75505Sopenharmony_ci * EB = 00 || BT || PS || 00 || D 636e5b75505Sopenharmony_ci * BT = 01 637e5b75505Sopenharmony_ci * PS = k-3-||D|| times FF 638e5b75505Sopenharmony_ci * k = length of modulus in octets 639e5b75505Sopenharmony_ci */ 640e5b75505Sopenharmony_ci 641e5b75505Sopenharmony_ci if (len < 3 + 8 + 16 /* min hash len */ || 642e5b75505Sopenharmony_ci plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { 643e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 644e5b75505Sopenharmony_ci "structure"); 645e5b75505Sopenharmony_ci return -1; 646e5b75505Sopenharmony_ci } 647e5b75505Sopenharmony_ci 648e5b75505Sopenharmony_ci pos = plain + 3; 649e5b75505Sopenharmony_ci while (pos < plain + len && *pos == 0xff) 650e5b75505Sopenharmony_ci pos++; 651e5b75505Sopenharmony_ci if (pos - plain - 2 < 8) { 652e5b75505Sopenharmony_ci /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ 653e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " 654e5b75505Sopenharmony_ci "padding"); 655e5b75505Sopenharmony_ci return -1; 656e5b75505Sopenharmony_ci } 657e5b75505Sopenharmony_ci 658e5b75505Sopenharmony_ci if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { 659e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 660e5b75505Sopenharmony_ci "structure (2)"); 661e5b75505Sopenharmony_ci return -1; 662e5b75505Sopenharmony_ci } 663e5b75505Sopenharmony_ci pos++; 664e5b75505Sopenharmony_ci len -= pos - plain; 665e5b75505Sopenharmony_ci 666e5b75505Sopenharmony_ci /* Strip PKCS #1 header */ 667e5b75505Sopenharmony_ci os_memmove(plain, pos, len); 668e5b75505Sopenharmony_ci *plain_len = len; 669e5b75505Sopenharmony_ci 670e5b75505Sopenharmony_ci return 0; 671e5b75505Sopenharmony_ci} 672e5b75505Sopenharmony_ci 673e5b75505Sopenharmony_ci 674e5b75505Sopenharmony_ciint crypto_global_init(void) 675e5b75505Sopenharmony_ci{ 676e5b75505Sopenharmony_ci ltc_mp = tfm_desc; 677e5b75505Sopenharmony_ci /* TODO: only register algorithms that are really needed */ 678e5b75505Sopenharmony_ci if (register_hash(&md4_desc) < 0 || 679e5b75505Sopenharmony_ci register_hash(&md5_desc) < 0 || 680e5b75505Sopenharmony_ci register_hash(&sha1_desc) < 0 || 681e5b75505Sopenharmony_ci register_cipher(&aes_desc) < 0 || 682e5b75505Sopenharmony_ci register_cipher(&des_desc) < 0 || 683e5b75505Sopenharmony_ci register_cipher(&des3_desc) < 0) { 684e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TLSv1: Failed to register " 685e5b75505Sopenharmony_ci "hash/cipher functions"); 686e5b75505Sopenharmony_ci return -1; 687e5b75505Sopenharmony_ci } 688e5b75505Sopenharmony_ci 689e5b75505Sopenharmony_ci return 0; 690e5b75505Sopenharmony_ci} 691e5b75505Sopenharmony_ci 692e5b75505Sopenharmony_ci 693e5b75505Sopenharmony_civoid crypto_global_deinit(void) 694e5b75505Sopenharmony_ci{ 695e5b75505Sopenharmony_ci} 696e5b75505Sopenharmony_ci 697e5b75505Sopenharmony_ci 698e5b75505Sopenharmony_ci#ifdef CONFIG_MODEXP 699e5b75505Sopenharmony_ci 700e5b75505Sopenharmony_ciint crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, 701e5b75505Sopenharmony_ci u8 *pubkey) 702e5b75505Sopenharmony_ci{ 703e5b75505Sopenharmony_ci size_t pubkey_len, pad; 704e5b75505Sopenharmony_ci 705e5b75505Sopenharmony_ci if (os_get_random(privkey, prime_len) < 0) 706e5b75505Sopenharmony_ci return -1; 707e5b75505Sopenharmony_ci if (os_memcmp(privkey, prime, prime_len) > 0) { 708e5b75505Sopenharmony_ci /* Make sure private value is smaller than prime */ 709e5b75505Sopenharmony_ci privkey[0] = 0; 710e5b75505Sopenharmony_ci } 711e5b75505Sopenharmony_ci 712e5b75505Sopenharmony_ci pubkey_len = prime_len; 713e5b75505Sopenharmony_ci if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, 714e5b75505Sopenharmony_ci pubkey, &pubkey_len) < 0) 715e5b75505Sopenharmony_ci return -1; 716e5b75505Sopenharmony_ci if (pubkey_len < prime_len) { 717e5b75505Sopenharmony_ci pad = prime_len - pubkey_len; 718e5b75505Sopenharmony_ci os_memmove(pubkey + pad, pubkey, pubkey_len); 719e5b75505Sopenharmony_ci os_memset(pubkey, 0, pad); 720e5b75505Sopenharmony_ci } 721e5b75505Sopenharmony_ci 722e5b75505Sopenharmony_ci return 0; 723e5b75505Sopenharmony_ci} 724e5b75505Sopenharmony_ci 725e5b75505Sopenharmony_ci 726e5b75505Sopenharmony_ciint crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, 727e5b75505Sopenharmony_ci const u8 *order, size_t order_len, 728e5b75505Sopenharmony_ci const u8 *privkey, size_t privkey_len, 729e5b75505Sopenharmony_ci const u8 *pubkey, size_t pubkey_len, 730e5b75505Sopenharmony_ci u8 *secret, size_t *len) 731e5b75505Sopenharmony_ci{ 732e5b75505Sopenharmony_ci /* TODO: check pubkey */ 733e5b75505Sopenharmony_ci return crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, 734e5b75505Sopenharmony_ci prime, prime_len, secret, len); 735e5b75505Sopenharmony_ci} 736e5b75505Sopenharmony_ci 737e5b75505Sopenharmony_ci 738e5b75505Sopenharmony_ciint crypto_mod_exp(const u8 *base, size_t base_len, 739e5b75505Sopenharmony_ci const u8 *power, size_t power_len, 740e5b75505Sopenharmony_ci const u8 *modulus, size_t modulus_len, 741e5b75505Sopenharmony_ci u8 *result, size_t *result_len) 742e5b75505Sopenharmony_ci{ 743e5b75505Sopenharmony_ci void *b, *p, *m, *r; 744e5b75505Sopenharmony_ci 745e5b75505Sopenharmony_ci if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) 746e5b75505Sopenharmony_ci return -1; 747e5b75505Sopenharmony_ci 748e5b75505Sopenharmony_ci if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || 749e5b75505Sopenharmony_ci mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || 750e5b75505Sopenharmony_ci mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) 751e5b75505Sopenharmony_ci goto fail; 752e5b75505Sopenharmony_ci 753e5b75505Sopenharmony_ci if (mp_exptmod(b, p, m, r) != CRYPT_OK) 754e5b75505Sopenharmony_ci goto fail; 755e5b75505Sopenharmony_ci 756e5b75505Sopenharmony_ci *result_len = mp_unsigned_bin_size(r); 757e5b75505Sopenharmony_ci if (mp_to_unsigned_bin(r, result) != CRYPT_OK) 758e5b75505Sopenharmony_ci goto fail; 759e5b75505Sopenharmony_ci 760e5b75505Sopenharmony_ci mp_clear_multi(b, p, m, r, NULL); 761e5b75505Sopenharmony_ci return 0; 762e5b75505Sopenharmony_ci 763e5b75505Sopenharmony_cifail: 764e5b75505Sopenharmony_ci mp_clear_multi(b, p, m, r, NULL); 765e5b75505Sopenharmony_ci return -1; 766e5b75505Sopenharmony_ci} 767e5b75505Sopenharmony_ci 768e5b75505Sopenharmony_ci#endif /* CONFIG_MODEXP */ 769