diff options
author | Cy Schubert <cy@FreeBSD.org> | 2019-04-22 15:42:53 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2019-04-22 15:42:53 +0000 |
commit | 6e6d0eb51ef7b7487340bae7f20097ee5a57dbf4 (patch) | |
tree | 406310b03a08c8e00c863a82934ba6a8e33c6b2f /src/crypto/crypto_internal-modexp.c | |
parent | 8a36c5c2ca4d1f8a900ca3d9ffde40b96463def7 (diff) | |
download | src-test2-6e6d0eb51ef7b7487340bae7f20097ee5a57dbf4.tar.gz src-test2-6e6d0eb51ef7b7487340bae7f20097ee5a57dbf4.zip |
Notes
Diffstat (limited to 'src/crypto/crypto_internal-modexp.c')
-rw-r--r-- | src/crypto/crypto_internal-modexp.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/crypto/crypto_internal-modexp.c b/src/crypto/crypto_internal-modexp.c index 92581ac676d3..6819f1a6ab6a 100644 --- a/src/crypto/crypto_internal-modexp.c +++ b/src/crypto/crypto_internal-modexp.c @@ -40,12 +40,49 @@ int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, + const u8 *order, size_t order_len, const u8 *privkey, size_t privkey_len, const u8 *pubkey, size_t pubkey_len, u8 *secret, size_t *len) { - return crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, - prime, prime_len, secret, len); + struct bignum *pub; + int res = -1; + + if (pubkey_len > prime_len || + (pubkey_len == prime_len && + os_memcmp(pubkey, prime, prime_len) >= 0)) + return -1; + + pub = bignum_init(); + if (!pub || bignum_set_unsigned_bin(pub, pubkey, pubkey_len) < 0 || + bignum_cmp_d(pub, 1) <= 0) + goto fail; + + if (order) { + struct bignum *p, *q, *tmp; + int failed; + + /* verify: pubkey^q == 1 mod p */ + p = bignum_init(); + q = bignum_init(); + tmp = bignum_init(); + failed = !p || !q || !tmp || + bignum_set_unsigned_bin(p, prime, prime_len) < 0 || + bignum_set_unsigned_bin(q, order, order_len) < 0 || + bignum_exptmod(pub, q, p, tmp) < 0 || + bignum_cmp_d(tmp, 1) != 0; + bignum_deinit(p); + bignum_deinit(q); + bignum_deinit(tmp); + if (failed) + goto fail; + } + + res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, + prime, prime_len, secret, len); +fail: + bignum_deinit(pub); + return res; } |