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