From 6bf7b6e342f97cf48319e0bc251200fabe132c21 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 19 Aug 2024 16:53:33 -0700 Subject: [PATCH] src: move more crypto_dh.cc code to ncrypto Update deps/ncrypto/ncrypto.cc PR-URL: https://github.com/nodejs/node/pull/54459 Reviewed-By: Yagiz Nizipli --- deps/ncrypto/dh-primes.h | 304 +++++++++++++ deps/ncrypto/ncrypto.cc | 236 +++++++++++ deps/ncrypto/ncrypto.gyp | 1 + deps/ncrypto/ncrypto.h | 79 +++- src/crypto/crypto_dh.cc | 728 ++++++++++++++------------------ src/crypto/crypto_dh.h | 35 +- test/parallel/test-crypto-dh.js | 2 +- 7 files changed, 934 insertions(+), 451 deletions(-) create mode 100644 deps/ncrypto/dh-primes.h diff --git a/deps/ncrypto/dh-primes.h b/deps/ncrypto/dh-primes.h new file mode 100644 index 00000000000..e8e8da3dddd --- /dev/null +++ b/deps/ncrypto/dh-primes.h @@ -0,0 +1,304 @@ +/* ==================================================================== + * Copyright (c) 2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). */ + +#include + +#include +#include +#include + +extern "C" int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num); + +// Backporting primes that may not be supported in earlier boringssl versions. Intentionally +// keeping the existing C-style formatting. + +#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +#if defined(OPENSSL_64_BIT) +#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo)) +#elif defined(OPENSSL_32_BIT) +#define TOBN(hi, lo) (lo), (hi) +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + +static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words, size_t num_words) { + BIGNUM *alloc = NULL; + if (ret == NULL) { + alloc = BN_new(); + if (alloc == NULL) { + return NULL; + } + ret = alloc; + } + + if (!bn_set_words(ret, words, num_words)) { + BN_free(alloc); + return NULL; + } + + return ret; +} + +BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x15728e5a, 0x8aacaa68), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x4b82d120, 0xa93ad2ca), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x4df435c9, 0x34063199), + TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), + TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), + TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), + TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), + TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), + TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), + TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), + TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0xe694f91e, 0x6dcc4024), + TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), + TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), + TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), + TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), + TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), + TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), + TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), + TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), + TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), + TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), + TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), + TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), + TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), + TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), + TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), + TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), + TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), + TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), + TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), + TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), + TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), + TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), + TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), + TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x60c980dd, 0x98edd3df), + TOBN(0xc81f56e8, 0x80b96e71), TOBN(0x9e3050e2, 0x765694df), + TOBN(0x9558e447, 0x5677e9aa), TOBN(0xc9190da6, 0xfc026e47), + TOBN(0x889a002e, 0xd5ee382b), TOBN(0x4009438b, 0x481c6cd7), + TOBN(0x359046f4, 0xeb879f92), TOBN(0xfaf36bc3, 0x1ecfa268), + TOBN(0xb1d510bd, 0x7ee74d73), TOBN(0xf9ab4819, 0x5ded7ea1), + TOBN(0x64f31cc5, 0x0846851d), TOBN(0x4597e899, 0xa0255dc1), + TOBN(0xdf310ee0, 0x74ab6a36), TOBN(0x6d2a13f8, 0x3f44f82d), + TOBN(0x062b3cf5, 0xb3a278a6), TOBN(0x79683303, 0xed5bdd3a), + TOBN(0xfa9d4b7f, 0xa2c087e8), TOBN(0x4bcbc886, 0x2f8385dd), + TOBN(0x3473fc64, 0x6cea306b), TOBN(0x13eb57a8, 0x1a23f0c7), + TOBN(0x22222e04, 0xa4037c07), TOBN(0xe3fdb8be, 0xfc848ad9), + TOBN(0x238f16cb, 0xe39d652d), TOBN(0x3423b474, 0x2bf1c978), + TOBN(0x3aab639c, 0x5ae4f568), TOBN(0x2576f693, 0x6ba42466), + TOBN(0x741fa7bf, 0x8afc47ed), TOBN(0x3bc832b6, 0x8d9dd300), + TOBN(0xd8bec4d0, 0x73b931ba), TOBN(0x38777cb6, 0xa932df8c), + TOBN(0x74a3926f, 0x12fee5e4), TOBN(0xe694f91e, 0x6dbe1159), + TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), + TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), + TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), + TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), + TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), + TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), + TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), + TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), + TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), + TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), + TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), + TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), + TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), + TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), + TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), + TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), + TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), + TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), + TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), + TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), + TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), + TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), + TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), + TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index c3f4b3fd989..2a02ae79e4e 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -1,6 +1,7 @@ #include "ncrypto.h" #include #include +#include #include #include #include @@ -8,6 +9,9 @@ #if OPENSSL_VERSION_MAJOR >= 3 #include #endif +#ifdef OPENSSL_IS_BORINGSSL +#include "dh-primes.h" +#endif // OPENSSL_IS_BORINGSSL namespace ncrypto { namespace { @@ -289,6 +293,11 @@ const BIGNUM* BignumPointer::One() { return BN_value_one(); } +BignumPointer BignumPointer::clone() { + if (!bn_) return {}; + return BignumPointer(BN_dup(bn_.get())); +} + // ============================================================================ // Utility methods @@ -1016,4 +1025,231 @@ int BIOPointer::Write(BIOPointer* bio, std::string_view message) { return BIO_write(bio->get(), message.data(), message.size()); } +// ============================================================================ +// DHPointer + +namespace { +bool EqualNoCase(const std::string_view a, const std::string_view b) { + if (a.size() != b.size()) return false; + return std::equal(a.begin(), a.end(), b.begin(), b.end(), + [](char a, char b) { return std::tolower(a) == std::tolower(b); }); +} +} // namespace + +DHPointer::DHPointer(DH* dh) : dh_(dh) {} + +DHPointer::DHPointer(DHPointer&& other) noexcept : dh_(other.release()) {} + +DHPointer& DHPointer::operator=(DHPointer&& other) noexcept { + if (this == &other) return *this; + this->~DHPointer(); + return *new (this) DHPointer(std::move(other)); +} + +DHPointer::~DHPointer() { reset(); } + +void DHPointer::reset(DH* dh) { dh_.reset(dh); } + +DH* DHPointer::release() { return dh_.release(); } + +BignumPointer DHPointer::FindGroup(const std::string_view name, + FindGroupOption option) { +#define V(n, p) if (EqualNoCase(name, n)) return BignumPointer(p(nullptr)); + if (option != FindGroupOption::NO_SMALL_PRIMES) { + V("modp1", BN_get_rfc2409_prime_768); + V("modp2", BN_get_rfc2409_prime_1024); + V("modp5", BN_get_rfc3526_prime_1536); + } + V("modp14", BN_get_rfc3526_prime_2048); + V("modp15", BN_get_rfc3526_prime_3072); + V("modp16", BN_get_rfc3526_prime_4096); + V("modp17", BN_get_rfc3526_prime_6144); + V("modp18", BN_get_rfc3526_prime_8192); +#undef V + return {}; +} + +BignumPointer DHPointer::GetStandardGenerator() { + auto bn = BignumPointer::New(); + if (!bn) return {}; + if (!bn.setWord(DH_GENERATOR_2)) return {}; + return bn; +} + +DHPointer DHPointer::FromGroup(const std::string_view name, + FindGroupOption option) { + auto group = FindGroup(name, option); + if (!group) return {}; // Unable to find the named group. + + auto generator = GetStandardGenerator(); + if (!generator) return {}; // Unable to create the generator. + + return New(std::move(group), std::move(generator)); +} + +DHPointer DHPointer::New(BignumPointer&& p, BignumPointer&& g) { + if (!p || !g) return {}; + + DHPointer dh(DH_new()); + if (!dh) return {}; + + if (DH_set0_pqg(dh.get(), p.get(), nullptr, g.get()) != 1) return {}; + + // If the call above is successful, the DH object takes ownership of the + // BIGNUMs, so we must release them here. + p.release(); + g.release(); + + return dh; +} + +DHPointer DHPointer::New(size_t bits, unsigned int generator) { + DHPointer dh(DH_new()); + if (!dh) return {}; + + if (DH_generate_parameters_ex(dh.get(), bits, generator, nullptr) != 1) { + return {}; + } + + return dh; +} + +DHPointer::CheckResult DHPointer::check() { + ClearErrorOnReturn clearErrorOnReturn; + if (!dh_) return DHPointer::CheckResult::NONE; + int codes = 0; + if (DH_check(dh_.get(), &codes) != 1) + return DHPointer::CheckResult::CHECK_FAILED; + return static_cast(codes); +} + +DHPointer::CheckPublicKeyResult DHPointer::checkPublicKey(const BignumPointer& pub_key) { + ClearErrorOnReturn clearErrorOnReturn; + if (!pub_key || !dh_) return DHPointer::CheckPublicKeyResult::CHECK_FAILED; + int codes = 0; + if (DH_check_pub_key(dh_.get(), pub_key.get(), &codes) != 1) + return DHPointer::CheckPublicKeyResult::CHECK_FAILED; + if (codes & DH_CHECK_PUBKEY_TOO_SMALL) { + return DHPointer::CheckPublicKeyResult::TOO_SMALL; + } else if (codes & DH_CHECK_PUBKEY_TOO_SMALL) { + return DHPointer::CheckPublicKeyResult::TOO_LARGE; + } else if (codes != 0) { + return DHPointer::CheckPublicKeyResult::INVALID; + } + return CheckPublicKeyResult::NONE; +} + +DataPointer DHPointer::getPrime() const { + if (!dh_) return {}; + const BIGNUM* p; + DH_get0_pqg(dh_.get(), &p, nullptr, nullptr); + return BignumPointer::Encode(p); +} + +DataPointer DHPointer::getGenerator() const { + if (!dh_) return {}; + const BIGNUM* g; + DH_get0_pqg(dh_.get(), nullptr, nullptr, &g); + return BignumPointer::Encode(g); +} + +DataPointer DHPointer::getPublicKey() const { + if (!dh_) return {}; + const BIGNUM* pub_key; + DH_get0_key(dh_.get(), &pub_key, nullptr); + return BignumPointer::Encode(pub_key); +} + +DataPointer DHPointer::getPrivateKey() const { + if (!dh_) return {}; + const BIGNUM* pvt_key; + DH_get0_key(dh_.get(), nullptr, &pvt_key); + return BignumPointer::Encode(pvt_key); +} + +DataPointer DHPointer::generateKeys() const { + ClearErrorOnReturn clearErrorOnReturn; + if (!dh_) return {}; + + // Key generation failed + if (!DH_generate_key(dh_.get())) return {}; + + return getPublicKey(); +} + +size_t DHPointer::size() const { + if (!dh_) return 0; + return DH_size(dh_.get()); +} + +DataPointer DHPointer::computeSecret(const BignumPointer& peer) const { + ClearErrorOnReturn clearErrorOnReturn; + if (!dh_ || !peer) return {}; + + auto dp = DataPointer::Alloc(size()); + if (!dp) return {}; + + int size = DH_compute_key(static_cast(dp.get()), peer.get(), dh_.get()); + if (size < 0) return {}; + + // The size of the computed key can be smaller than the size of the DH key. + // We want to make sure that the key is correctly padded. + if (size < dp.size()) { + const size_t padding = dp.size() - size; + uint8_t* data = static_cast(dp.get()); + memmove(data + padding, data, size); + memset(data, 0, padding); + } + + return dp; +} + +bool DHPointer::setPublicKey(BignumPointer&& key) { + if (!dh_) return false; + if (DH_set0_key(dh_.get(), key.get(), nullptr) == 1) { + key.release(); + return true; + } + return false; +} + +bool DHPointer::setPrivateKey(BignumPointer&& key) { + if (!dh_) return false; + if (DH_set0_key(dh_.get(), nullptr, key.get()) == 1) { + key.release(); + return true; + } + return false; +} + +DataPointer DHPointer::stateless(const EVPKeyPointer& ourKey, + const EVPKeyPointer& theirKey) { + size_t out_size; + if (!ourKey || !theirKey) return {}; + + EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(ourKey.get(), nullptr)); + if (!ctx || + EVP_PKEY_derive_init(ctx.get()) <= 0 || + EVP_PKEY_derive_set_peer(ctx.get(), theirKey.get()) <= 0 || + EVP_PKEY_derive(ctx.get(), nullptr, &out_size) <= 0) { + return {}; + } + + if (out_size == 0) return {}; + + auto out = DataPointer::Alloc(out_size); + if (EVP_PKEY_derive(ctx.get(), reinterpret_cast(out.get()), &out_size) <= 0) { + return {}; + } + + if (out_size < out.size()) { + const size_t padding = out.size() - out_size; + uint8_t* data = static_cast(out.get()); + memmove(data + padding, data, out_size); + memset(data, 0, padding); + } + + return out; +} + } // namespace ncrypto diff --git a/deps/ncrypto/ncrypto.gyp b/deps/ncrypto/ncrypto.gyp index cf9b7c6cdb6..90ac158d7e2 100644 --- a/deps/ncrypto/ncrypto.gyp +++ b/deps/ncrypto/ncrypto.gyp @@ -2,6 +2,7 @@ 'variables': { 'ncrypto_sources': [ 'engine.cc', + 'dh-primes.h', 'ncrypto.cc', 'ncrypto.h', ], diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index e62a99595ae..9b6aecaaecd 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -194,7 +194,6 @@ using DeleteFnPtr = typename FunctionDeleter::Pointer; using BignumCtxPointer = DeleteFnPtr; using CipherCtxPointer = DeleteFnPtr; -using DHPointer = DeleteFnPtr; using DSAPointer = DeleteFnPtr; using DSASigPointer = DeleteFnPtr; using ECDSASigPointer = DeleteFnPtr; @@ -354,10 +353,88 @@ class BignumPointer final { static unsigned long GetWord(const BIGNUM* bn); static const BIGNUM* One(); + BignumPointer clone(); + private: DeleteFnPtr bn_; }; +class DHPointer final { +public: + + enum class FindGroupOption { + NONE, + // There are known and documented security issues with prime groups smaller + // than 2048 bits. When the NO_SMALL_PRIMES option is set, these small prime + // groups will not be supported. + NO_SMALL_PRIMES, + }; + + static BignumPointer GetStandardGenerator(); + + static BignumPointer FindGroup(const std::string_view name, + FindGroupOption option = FindGroupOption::NONE); + static DHPointer FromGroup(const std::string_view name, + FindGroupOption option = FindGroupOption::NONE); + + static DHPointer New(BignumPointer&& p, BignumPointer&& g); + static DHPointer New(size_t bits, unsigned int generator); + + DHPointer() = default; + explicit DHPointer(DH* dh); + DHPointer(DHPointer&& other) noexcept; + DHPointer& operator=(DHPointer&& other) noexcept; + NCRYPTO_DISALLOW_COPY(DHPointer) + ~DHPointer(); + + inline bool operator==(std::nullptr_t) noexcept { return dh_ == nullptr; } + inline operator bool() const { return dh_ != nullptr; } + inline DH* get() const { return dh_.get(); } + void reset(DH* dh = nullptr); + DH* release(); + + enum class CheckResult { + NONE, + P_NOT_PRIME = DH_CHECK_P_NOT_PRIME, + P_NOT_SAFE_PRIME = DH_CHECK_P_NOT_SAFE_PRIME, + UNABLE_TO_CHECK_GENERATOR = DH_UNABLE_TO_CHECK_GENERATOR, + NOT_SUITABLE_GENERATOR = DH_NOT_SUITABLE_GENERATOR, + Q_NOT_PRIME = DH_CHECK_Q_NOT_PRIME, + INVALID_Q = DH_CHECK_INVALID_Q_VALUE, + INVALID_J = DH_CHECK_INVALID_J_VALUE, + CHECK_FAILED = 512, + }; + CheckResult check(); + + enum class CheckPublicKeyResult { + NONE, + TOO_SMALL = DH_R_CHECK_PUBKEY_TOO_SMALL, + TOO_LARGE = DH_R_CHECK_PUBKEY_TOO_LARGE, + INVALID = DH_R_CHECK_PUBKEY_INVALID, + CHECK_FAILED = 512, + }; + // Check to see if the given public key is suitable for this DH instance. + CheckPublicKeyResult checkPublicKey(const BignumPointer& pub_key); + + DataPointer getPrime() const; + DataPointer getGenerator() const; + DataPointer getPublicKey() const; + DataPointer getPrivateKey() const; + DataPointer generateKeys() const; + DataPointer computeSecret(const BignumPointer& peer) const; + + bool setPublicKey(BignumPointer&& key); + bool setPrivateKey(BignumPointer&& key); + + size_t size() const; + + static DataPointer stateless(const EVPKeyPointer& ourKey, + const EVPKeyPointer& theirKey); + +private: + DeleteFnPtr dh_; +}; + class X509Pointer; class X509View final { diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc index 57dd1c0b36b..1203cc46941 100644 --- a/src/crypto/crypto_dh.cc +++ b/src/crypto/crypto_dh.cc @@ -5,27 +5,28 @@ #include "crypto/crypto_util.h" #include "env-inl.h" #include "memory_tracker-inl.h" +#include "ncrypto.h" +#include "node_errors.h" +#include "openssl/bnerr.h" +#include "openssl/dh.h" #include "threadpoolwork-inl.h" #include "v8.h" -#include - namespace node { using v8::ArrayBuffer; -using v8::BackingStore; using v8::ConstructorBehavior; using v8::Context; using v8::DontDelete; using v8::FunctionCallback; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; -using v8::HandleScope; using v8::Int32; using v8::Isolate; using v8::Just; using v8::Local; using v8::Maybe; +using v8::MaybeLocal; using v8::Nothing; using v8::Object; using v8::PropertyAttribute; @@ -36,361 +37,219 @@ using v8::String; using v8::Value; namespace crypto { -namespace { -void ZeroPadDiffieHellmanSecret(size_t remainder_size, - char* data, - size_t length) { - // DH_size returns number of bytes in a prime number. - // DH_compute_key returns number of bytes in a remainder of exponent, which - // may have less bytes than a prime number. Therefore add 0-padding to the - // allocated buffer. - const size_t prime_size = length; - if (remainder_size != prime_size) { - CHECK_LT(remainder_size, prime_size); - const size_t padding = prime_size - remainder_size; - memmove(data + padding, data, remainder_size); - memset(data, 0, padding); - } -} -} // namespace - -DiffieHellman::DiffieHellman(Environment* env, Local wrap) - : BaseObject(env, wrap), verifyError_(0) { +DiffieHellman::DiffieHellman(Environment* env, Local wrap, DHPointer dh) + : BaseObject(env, wrap), dh_(std::move(dh)) { MakeWeak(); } -void DiffieHellman::Initialize(Environment* env, Local target) { - Isolate* isolate = env->isolate(); - Local context = env->context(); - auto make = [&](Local name, FunctionCallback callback) { - Local t = NewFunctionTemplate(isolate, callback); - - const PropertyAttribute attributes = - static_cast(ReadOnly | DontDelete); - - t->InstanceTemplate()->SetInternalFieldCount( - DiffieHellman::kInternalFieldCount); - - SetProtoMethod(isolate, t, "generateKeys", GenerateKeys); - SetProtoMethod(isolate, t, "computeSecret", ComputeSecret); - SetProtoMethodNoSideEffect(isolate, t, "getPrime", GetPrime); - SetProtoMethodNoSideEffect(isolate, t, "getGenerator", GetGenerator); - SetProtoMethodNoSideEffect(isolate, t, "getPublicKey", GetPublicKey); - SetProtoMethodNoSideEffect(isolate, t, "getPrivateKey", GetPrivateKey); - SetProtoMethod(isolate, t, "setPublicKey", SetPublicKey); - SetProtoMethod(isolate, t, "setPrivateKey", SetPrivateKey); - - Local verify_error_getter_templ = - FunctionTemplate::New(isolate, - DiffieHellman::VerifyErrorGetter, - Local(), - Signature::New(env->isolate(), t), - /* length */ 0, - ConstructorBehavior::kThrow, - SideEffectType::kHasNoSideEffect); - - t->InstanceTemplate()->SetAccessorProperty( - env->verify_error_string(), - verify_error_getter_templ, - Local(), - attributes); - - SetConstructorFunction(context, target, name, t); - }; - - make(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellman"), New); - make(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellmanGroup"), - DiffieHellmanGroup); - - SetMethodNoSideEffect( - context, target, "statelessDH", DiffieHellman::Stateless); - DHKeyPairGenJob::Initialize(env, target); - DHKeyExportJob::Initialize(env, target); - DHBitsJob::Initialize(env, target); -} - -void DiffieHellman::RegisterExternalReferences( - ExternalReferenceRegistry* registry) { - registry->Register(New); - registry->Register(DiffieHellmanGroup); - - registry->Register(GenerateKeys); - registry->Register(ComputeSecret); - registry->Register(GetPrime); - registry->Register(GetGenerator); - registry->Register(GetPublicKey); - registry->Register(GetPrivateKey); - registry->Register(SetPublicKey); - registry->Register(SetPrivateKey); - - registry->Register(DiffieHellman::VerifyErrorGetter); - registry->Register(DiffieHellman::Stateless); - - DHKeyPairGenJob::RegisterExternalReferences(registry); - DHKeyExportJob::RegisterExternalReferences(registry); - DHBitsJob::RegisterExternalReferences(registry); -} - -bool DiffieHellman::Init(int primeLength, int g) { - dh_.reset(DH_new()); - if (!DH_generate_parameters_ex(dh_.get(), primeLength, g, nullptr)) - return false; - return VerifyContext(); -} - void DiffieHellman::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackFieldWithSize("dh", dh_ ? kSizeOf_DH : 0); } namespace { -bool SetDhParams(DH* dh, BignumPointer* p, BignumPointer* g) { - // If DH_set0_pqg returns 0, ownership of the input parameters has - // not been transferred to the DH object. If the return value is 1, - // ownership has been transferred and we need to release them. - // The documentation for DH_set0_pqg is not clear on this point. - // It says that ownership is transfered when the method is called - // but there is an internal check that returns 0 if the input is - // not valid, and in that case ownership is not transferred. - if (DH_set0_pqg(dh, p->get(), nullptr, g->get()) == 0) return false; - p->release(); - g->release(); - return true; -} -} // namespace +MaybeLocal DataPointerToBuffer(Environment* env, + ncrypto::DataPointer&& data) { + auto backing = ArrayBuffer::NewBackingStore( + data.get(), + data.size(), + [](void* data, size_t len, void* ptr) { + ncrypto::DataPointer free_ne(data, len); + }, + nullptr); + data.release(); -bool DiffieHellman::Init(BignumPointer&& bn_p, int g) { - dh_.reset(DH_new()); - CHECK_GE(g, 2); - auto bn_g = BignumPointer::New(); - return bn_p && bn_g.setWord(g) && SetDhParams(dh_.get(), &bn_p, &bn_g) && - VerifyContext(); + auto ab = ArrayBuffer::New(env->isolate(), std::move(backing)); + return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local()); } -bool DiffieHellman::Init(const char* p, int p_len, int g) { - dh_.reset(DH_new()); - if (p_len <= 0) { - ERR_put_error(ERR_LIB_BN, BN_F_BN_GENERATE_PRIME_EX, - BN_R_BITS_TOO_SMALL, __FILE__, __LINE__); - return false; - } - if (g <= 1) { - ERR_put_error(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, - DH_R_BAD_GENERATOR, __FILE__, __LINE__); - return false; - } - BignumPointer bn_p(reinterpret_cast(p), p_len); - auto bn_g = BignumPointer::New(); - return bn_p && bn_g.setWord(g) && SetDhParams(dh_.get(), &bn_p, &bn_g) && - VerifyContext(); -} - -bool DiffieHellman::Init(const char* p, int p_len, const char* g, int g_len) { - dh_.reset(DH_new()); - if (p_len <= 0) { - ERR_put_error(ERR_LIB_BN, BN_F_BN_GENERATE_PRIME_EX, - BN_R_BITS_TOO_SMALL, __FILE__, __LINE__); - return false; - } - if (g_len <= 0) { - ERR_put_error(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, - DH_R_BAD_GENERATOR, __FILE__, __LINE__); - return false; - } - BignumPointer bn_g(reinterpret_cast(g), g_len); - if (!bn_g || bn_g.isZero() || bn_g.isOne()) { - ERR_put_error(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, - DH_R_BAD_GENERATOR, __FILE__, __LINE__); - return false; - } - BignumPointer bn_p(reinterpret_cast(p), p_len); - return bn_p && SetDhParams(dh_.get(), &bn_p, &bn_g) && VerifyContext(); -} - -constexpr int kStandardizedGenerator = 2; - -template -BignumPointer InstantiateStandardizedGroup() { - return BignumPointer(p(nullptr)); -} - -typedef BignumPointer (*StandardizedGroupInstantiator)(); - -// Returns a function that can be used to create an instance of a standardized -// Diffie-Hellman group. The generator is always kStandardizedGenerator. -inline StandardizedGroupInstantiator FindDiffieHellmanGroup(const char* name) { -#define V(n, p) \ - if (StringEqualNoCase(name, n)) return InstantiateStandardizedGroup

- V("modp1", BN_get_rfc2409_prime_768); - V("modp2", BN_get_rfc2409_prime_1024); - V("modp5", BN_get_rfc3526_prime_1536); - V("modp14", BN_get_rfc3526_prime_2048); - V("modp15", BN_get_rfc3526_prime_3072); - V("modp16", BN_get_rfc3526_prime_4096); - V("modp17", BN_get_rfc3526_prime_6144); - V("modp18", BN_get_rfc3526_prime_8192); -#undef V - return nullptr; -} - -void DiffieHellman::DiffieHellmanGroup( - const FunctionCallbackInfo& args) { +void DiffieHellmanGroup(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = new DiffieHellman(env, args.This()); - CHECK_EQ(args.Length(), 1); THROW_AND_RETURN_IF_NOT_STRING(env, args[0], "Group name"); - - bool initialized = false; - const node::Utf8Value group_name(env->isolate(), args[0]); - auto group = FindDiffieHellmanGroup(*group_name); - if (group == nullptr) - return THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP(env); - initialized = diffieHellman->Init(group(), kStandardizedGenerator); - if (!initialized) - THROW_ERR_CRYPTO_INITIALIZATION_FAILED(env); + DHPointer dh = DHPointer::FromGroup(group_name.ToStringView()); + if (!dh) { + return THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP(env); + } + + new DiffieHellman(env, args.This(), std::move(dh)); } - -void DiffieHellman::New(const FunctionCallbackInfo& args) { +void New(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = - new DiffieHellman(env, args.This()); - bool initialized = false; - if (args.Length() == 2) { - if (args[0]->IsInt32()) { - if (args[1]->IsInt32()) { - initialized = diffieHellman->Init(args[0].As()->Value(), - args[1].As()->Value()); - } - } else { - ArrayBufferOrViewContents arg0(args[0]); - if (UNLIKELY(!arg0.CheckSizeInt32())) - return THROW_ERR_OUT_OF_RANGE(env, "prime is too big"); - if (args[1]->IsInt32()) { - initialized = diffieHellman->Init(arg0.data(), - arg0.size(), - args[1].As()->Value()); - } else { - ArrayBufferOrViewContents arg1(args[1]); - if (UNLIKELY(!arg1.CheckSizeInt32())) - return THROW_ERR_OUT_OF_RANGE(env, "generator is too big"); - initialized = diffieHellman->Init(arg0.data(), arg0.size(), - arg1.data(), arg1.size()); - } + if (args.Length() != 2) { + return THROW_ERR_MISSING_ARGS(env, "Constructor must have two arguments"); + } + + if (args[0]->IsInt32()) { + int32_t bits = args[0].As()->Value(); + if (bits < 2) { +#if OPENSSL_VERSION_MAJOR >= 3 + ERR_put_error(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_SMALL, __FILE__, __LINE__); +#else + ERR_put_error(ERR_LIB_BN, 0, BN_R_BITS_TOO_SMALL, __FILE__, __LINE__); +#endif + return ThrowCryptoError(env, ERR_get_error(), "Invalid prime length"); + } + + // If the first argument is an Int32 then we are generating a new + // prime and then using that to generate the Diffie-Hellman parameters. + // The second argument must be an Int32 as well. + if (!args[1]->IsInt32()) { + return THROW_ERR_INVALID_ARG_TYPE(env, + "Second argument must be an int32"); + } + int32_t generator = args[1].As()->Value(); + if (generator < 2) { + ERR_put_error(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR, __FILE__, __LINE__); + return ThrowCryptoError(env, ERR_get_error(), "Invalid generator"); + } + + auto dh = DHPointer::New(bits, generator); + if (!dh) { + return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid DH parameters"); + } + new DiffieHellman(env, args.This(), std::move(dh)); + return; + } + + // The first argument must be an ArrayBuffer or ArrayBufferView with the + // prime, and the second argument must be an int32 with the generator + // or an ArrayBuffer or ArrayBufferView with the generator. + + ArrayBufferOrViewContents arg0(args[0]); + if (UNLIKELY(!arg0.CheckSizeInt32())) + return THROW_ERR_OUT_OF_RANGE(env, "prime is too big"); + + BignumPointer bn_p(reinterpret_cast(arg0.data()), arg0.size()); + BignumPointer bn_g; + if (!bn_p) { + return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid prime"); + } + + if (args[1]->IsInt32()) { + int32_t generator = args[1].As()->Value(); + if (generator < 2) { + ERR_put_error(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR, __FILE__, __LINE__); + return ThrowCryptoError(env, ERR_get_error(), "Invalid generator"); + } + bn_g = BignumPointer::New(); + if (!bn_g.setWord(generator)) { + ERR_put_error(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR, __FILE__, __LINE__); + return ThrowCryptoError(env, ERR_get_error(), "Invalid generator"); + } + } else { + ArrayBufferOrViewContents arg1(args[1]); + if (UNLIKELY(!arg1.CheckSizeInt32())) + return THROW_ERR_OUT_OF_RANGE(env, "generator is too big"); + bn_g = BignumPointer(reinterpret_cast(arg1.data()), arg1.size()); + if (!bn_g) { + ERR_put_error(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR, __FILE__, __LINE__); + return ThrowCryptoError(env, ERR_get_error(), "Invalid generator"); + } + if (bn_g.getWord() < 2) { + ERR_put_error(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR, __FILE__, __LINE__); + return ThrowCryptoError(env, ERR_get_error(), "Invalid generator"); } } - if (!initialized) { - return ThrowCryptoError(env, ERR_get_error(), "Initialization failed"); + auto dh = DHPointer::New(std::move(bn_p), std::move(bn_g)); + if (!dh) { + return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid DH parameters"); } + new DiffieHellman(env, args.This(), std::move(dh)); } - -void DiffieHellman::GenerateKeys(const FunctionCallbackInfo& args) { +void GenerateKeys(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman; ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; - if (!DH_generate_key(diffieHellman->dh_.get())) { - return ThrowCryptoError(env, ERR_get_error(), "Key generation failed"); + auto dp = dh.generateKeys(); + if (!dp) { + return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Key generation failed"); } - const BIGNUM* pub_key; - DH_get0_key(diffieHellman->dh_.get(), &pub_key, nullptr); - - std::unique_ptr bs; - { - const int size = BignumPointer::GetByteCount(pub_key); - CHECK_GE(size, 0); - NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); - bs = ArrayBuffer::NewBackingStore(env->isolate(), size); - } - - CHECK_EQ( - bs->ByteLength(), - BignumPointer::EncodePaddedInto( - pub_key, static_cast(bs->Data()), bs->ByteLength())); - - Local ab = ArrayBuffer::New(env->isolate(), std::move(bs)); Local buffer; - if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return; - args.GetReturnValue().Set(buffer); -} - - -void DiffieHellman::GetField(const FunctionCallbackInfo& args, - const BIGNUM* (*get_field)(const DH*), - const char* err_if_null) { - Environment* env = Environment::GetCurrent(args); - - DiffieHellman* dh; - ASSIGN_OR_RETURN_UNWRAP(&dh, args.This()); - - const BIGNUM* num = get_field(dh->dh_.get()); - if (num == nullptr) - return THROW_ERR_CRYPTO_INVALID_STATE(env, err_if_null); - - std::unique_ptr bs; - { - const int size = BignumPointer::GetByteCount(num); - CHECK_GE(size, 0); - NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); - bs = ArrayBuffer::NewBackingStore(env->isolate(), size); + if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); } - - CHECK_EQ(bs->ByteLength(), - BignumPointer::EncodePaddedInto( - num, static_cast(bs->Data()), bs->ByteLength())); - - Local ab = ArrayBuffer::New(env->isolate(), std::move(bs)); - Local buffer; - if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return; - args.GetReturnValue().Set(buffer); } -void DiffieHellman::GetPrime(const FunctionCallbackInfo& args) { - GetField(args, [](const DH* dh) -> const BIGNUM* { - const BIGNUM* p; - DH_get0_pqg(dh, &p, nullptr, nullptr); - return p; - }, "p is null"); -} - -void DiffieHellman::GetGenerator(const FunctionCallbackInfo& args) { - GetField(args, [](const DH* dh) -> const BIGNUM* { - const BIGNUM* g; - DH_get0_pqg(dh, nullptr, nullptr, &g); - return g; - }, "g is null"); -} - -void DiffieHellman::GetPublicKey(const FunctionCallbackInfo& args) { - GetField(args, [](const DH* dh) -> const BIGNUM* { - const BIGNUM* pub_key; - DH_get0_key(dh, &pub_key, nullptr); - return pub_key; - }, "No public key - did you forget to generate one?"); -} - -void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo& args) { - GetField(args, [](const DH* dh) -> const BIGNUM* { - const BIGNUM* priv_key; - DH_get0_key(dh, nullptr, &priv_key); - return priv_key; - }, "No private key - did you forget to generate one?"); -} - -void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) { +void GetPrime(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman; ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; - ClearErrorOnReturn clear_error_on_return; + auto dp = dh.getPrime(); + if (!dp) { + return THROW_ERR_CRYPTO_INVALID_STATE(env, "p is null"); + } + Local buffer; + if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); + } +} + +void GetGenerator(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; + + auto dp = dh.getGenerator(); + if (!dp) { + return THROW_ERR_CRYPTO_INVALID_STATE(env, "g is null"); + } + Local buffer; + if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); + } +} + +void GetPublicKey(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; + + auto dp = dh.getPublicKey(); + if (!dp) { + return THROW_ERR_CRYPTO_INVALID_STATE( + env, "No public key - did you forget to generate one?"); + } + Local buffer; + if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); + } +} + +void GetPrivateKey(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; + + auto dp = dh.getPrivateKey(); + if (!dp) { + return THROW_ERR_CRYPTO_INVALID_STATE( + env, "No private key - did you forget to generate one?"); + } + Local buffer; + if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); + } +} + +void ComputeSecret(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; CHECK_EQ(args.Length(), 1); ArrayBufferOrViewContents key_buf(args[0]); @@ -398,93 +257,72 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) { return THROW_ERR_OUT_OF_RANGE(env, "secret is too big"); BignumPointer key(key_buf.data(), key_buf.size()); - std::unique_ptr bs; - { - NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); - bs = ArrayBuffer::NewBackingStore(env->isolate(), - DH_size(diffieHellman->dh_.get())); + switch (dh.checkPublicKey(key)) { + case DHPointer::CheckPublicKeyResult::INVALID: + // Fall-through + case DHPointer::CheckPublicKeyResult::CHECK_FAILED: + return THROW_ERR_CRYPTO_INVALID_KEYTYPE(env, + "Unspecified validation error"); + case DHPointer::CheckPublicKeyResult::TOO_SMALL: + return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, "Supplied key is too small"); + case DHPointer::CheckPublicKeyResult::TOO_LARGE: + return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, "Supplied key is too large"); + case DHPointer::CheckPublicKeyResult::NONE: + break; } - int size = DH_compute_key(static_cast(bs->Data()), - key.get(), - diffieHellman->dh_.get()); + auto dp = dh.computeSecret(key); - if (size == -1) { - int checkResult; - int checked; - - checked = DH_check_pub_key(diffieHellman->dh_.get(), - key.get(), - &checkResult); - - if (!checked) { - return ThrowCryptoError(env, ERR_get_error(), "Invalid Key"); - } else if (checkResult) { - if (checkResult & DH_CHECK_PUBKEY_TOO_SMALL) { - return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, - "Supplied key is too small"); - } else if (checkResult & DH_CHECK_PUBKEY_TOO_LARGE) { - return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, - "Supplied key is too large"); - } - } - - return THROW_ERR_CRYPTO_INVALID_KEYTYPE(env); - } - - CHECK_GE(size, 0); - ZeroPadDiffieHellmanSecret(size, - static_cast(bs->Data()), - bs->ByteLength()); - - Local ab = ArrayBuffer::New(env->isolate(), std::move(bs)); Local buffer; - if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return; - args.GetReturnValue().Set(buffer); + if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); + } } -void DiffieHellman::SetKey(const FunctionCallbackInfo& args, - int (*set_field)(DH*, BIGNUM*), const char* what) { +void SetPublicKey(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* dh; - ASSIGN_OR_RETURN_UNWRAP(&dh, args.This()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; CHECK_EQ(args.Length(), 1); ArrayBufferOrViewContents buf(args[0]); if (UNLIKELY(!buf.CheckSizeInt32())) return THROW_ERR_OUT_OF_RANGE(env, "buf is too big"); BignumPointer num(buf.data(), buf.size()); CHECK(num); - CHECK_EQ(1, set_field(dh->dh_.get(), num.release())); + CHECK(dh.setPublicKey(std::move(num))); } -void DiffieHellman::SetPublicKey(const FunctionCallbackInfo& args) { - SetKey(args, - [](DH* dh, BIGNUM* num) { return DH_set0_key(dh, num, nullptr); }, - "Public key"); +void SetPrivateKey(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); + DHPointer& dh = *diffieHellman; + CHECK_EQ(args.Length(), 1); + ArrayBufferOrViewContents buf(args[0]); + if (UNLIKELY(!buf.CheckSizeInt32())) + return THROW_ERR_OUT_OF_RANGE(env, "buf is too big"); + BignumPointer num(buf.data(), buf.size()); + CHECK(num); + CHECK(dh.setPrivateKey(std::move(num))); } -void DiffieHellman::SetPrivateKey(const FunctionCallbackInfo& args) { - SetKey(args, - [](DH* dh, BIGNUM* num) { return DH_set0_key(dh, nullptr, num); }, - "Private key"); -} - -void DiffieHellman::VerifyErrorGetter(const FunctionCallbackInfo& args) { - HandleScope scope(args.GetIsolate()); - +void Check(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); DiffieHellman* diffieHellman; ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This()); - args.GetReturnValue().Set(diffieHellman->verifyError_); + DHPointer& dh = *diffieHellman; + auto result = dh.check(); + if (result == DHPointer::CheckResult::CHECK_FAILED) { + return THROW_ERR_CRYPTO_OPERATION_FAILED(env, + "Checking DH parameters failed"); + } + + args.GetReturnValue().Set(static_cast(result)); } -bool DiffieHellman::VerifyContext() { - int codes; - if (!DH_check(dh_.get(), &codes)) - return false; - verifyError_ = codes; - return true; -} +} // namespace // The input arguments to DhKeyPairGenJob can vary // 1. CryptoJobMode @@ -509,13 +347,15 @@ Maybe DhKeyGenTraits::AdditionalConfig( if (args[*offset]->IsString()) { Utf8Value group_name(env->isolate(), args[*offset]); - auto group = FindDiffieHellmanGroup(*group_name); - if (group == nullptr) { + auto group = DHPointer::FindGroup(group_name.ToStringView()); + if (!group) { THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP(env); return Nothing(); } - params->params.prime = group(); + static constexpr int kStandardizedGenerator = 2; + + params->params.prime = std::move(group); params->params.generator = kStandardizedGenerator; *offset += 1; } else { @@ -547,15 +387,13 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) { EVPKeyPointer key_params; if (BignumPointer* prime_fixed_value = std::get_if(¶ms->params.prime)) { - DHPointer dh(DH_new()); - if (!dh) - return EVPKeyCtxPointer(); - + auto prime = prime_fixed_value->clone(); auto bn_g = BignumPointer::New(); - if (!bn_g.setWord(params->params.generator) || - !SetDhParams(dh.get(), prime_fixed_value, &bn_g)) { - return EVPKeyCtxPointer(); + if (!prime || !bn_g || !bn_g.setWord(params->params.generator)) { + return {}; } + auto dh = DHPointer::New(std::move(prime), std::move(bn_g)); + if (!dh) return {}; key_params = EVPKeyPointer(EVP_PKEY_new()); CHECK(key_params); @@ -572,7 +410,7 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) { param_ctx.get(), params->params.generator) <= 0 || EVP_PKEY_paramgen(param_ctx.get(), &raw_params) <= 0) { - return EVPKeyCtxPointer(); + return {}; } key_params = EVPKeyPointer(raw_params); @@ -581,8 +419,7 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) { } EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(key_params.get(), nullptr)); - if (!ctx || EVP_PKEY_keygen_init(ctx.get()) <= 0) - return EVPKeyCtxPointer(); + if (!ctx || EVP_PKEY_keygen_init(ctx.get()) <= 0) return {}; return ctx; } @@ -616,29 +453,15 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport( } namespace { -ByteSource StatelessDiffieHellmanThreadsafe( - const ManagedEVPPKey& our_key, - const ManagedEVPPKey& their_key) { - size_t out_size; +ByteSource StatelessDiffieHellmanThreadsafe(const ManagedEVPPKey& our_key, + const ManagedEVPPKey& their_key) { + auto dp = DHPointer::stateless(our_key.pkey(), their_key.pkey()); + if (!dp) return {}; - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(our_key.get(), nullptr)); - if (!ctx || - EVP_PKEY_derive_init(ctx.get()) <= 0 || - EVP_PKEY_derive_set_peer(ctx.get(), their_key.get()) <= 0 || - EVP_PKEY_derive(ctx.get(), nullptr, &out_size) <= 0) - return ByteSource(); - - ByteSource::Builder out(out_size); - if (EVP_PKEY_derive(ctx.get(), out.data(), &out_size) <= 0) { - return ByteSource(); - } - - ZeroPadDiffieHellmanSecret(out_size, out.data(), out.size()); - return std::move(out).release(); + return ByteSource::Allocated(dp.release()); } -} // namespace -void DiffieHellman::Stateless(const FunctionCallbackInfo& args) { +void Stateless(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsObject() && args[1]->IsObject()); @@ -662,6 +485,7 @@ void DiffieHellman::Stateless(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(out); } +} // namespace Maybe DHBitsTraits::AdditionalConfig( CryptoJobMode mode, @@ -719,5 +543,75 @@ Maybe GetDhKeyDetail( return Just(true); } +void DiffieHellman::Initialize(Environment* env, Local target) { + Isolate* isolate = env->isolate(); + Local context = env->context(); + auto make = [&](Local name, FunctionCallback callback) { + Local t = NewFunctionTemplate(isolate, callback); + + const PropertyAttribute attributes = + static_cast(ReadOnly | DontDelete); + + t->InstanceTemplate()->SetInternalFieldCount( + DiffieHellman::kInternalFieldCount); + + SetProtoMethod(isolate, t, "generateKeys", GenerateKeys); + SetProtoMethod(isolate, t, "computeSecret", ComputeSecret); + SetProtoMethodNoSideEffect(isolate, t, "getPrime", GetPrime); + SetProtoMethodNoSideEffect(isolate, t, "getGenerator", GetGenerator); + SetProtoMethodNoSideEffect(isolate, t, "getPublicKey", GetPublicKey); + SetProtoMethodNoSideEffect(isolate, t, "getPrivateKey", GetPrivateKey); + SetProtoMethod(isolate, t, "setPublicKey", SetPublicKey); + SetProtoMethod(isolate, t, "setPrivateKey", SetPrivateKey); + + Local verify_error_getter_templ = + FunctionTemplate::New(isolate, + Check, + Local(), + Signature::New(env->isolate(), t), + /* length */ 0, + ConstructorBehavior::kThrow, + SideEffectType::kHasNoSideEffect); + + t->InstanceTemplate()->SetAccessorProperty(env->verify_error_string(), + verify_error_getter_templ, + Local(), + attributes); + + SetConstructorFunction(context, target, name, t); + }; + + make(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellman"), New); + make(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellmanGroup"), + DiffieHellmanGroup); + + SetMethodNoSideEffect(context, target, "statelessDH", Stateless); + DHKeyPairGenJob::Initialize(env, target); + DHKeyExportJob::Initialize(env, target); + DHBitsJob::Initialize(env, target); +} + +void DiffieHellman::RegisterExternalReferences( + ExternalReferenceRegistry* registry) { + registry->Register(New); + registry->Register(DiffieHellmanGroup); + + registry->Register(GenerateKeys); + registry->Register(ComputeSecret); + registry->Register(GetPrime); + registry->Register(GetGenerator); + registry->Register(GetPublicKey); + registry->Register(GetPrivateKey); + registry->Register(SetPublicKey); + registry->Register(SetPrivateKey); + + registry->Register(Check); + registry->Register(Stateless); + + DHKeyPairGenJob::RegisterExternalReferences(registry); + DHKeyExportJob::RegisterExternalReferences(registry); + DHBitsJob::RegisterExternalReferences(registry); +} + } // namespace crypto } // namespace node diff --git a/src/crypto/crypto_dh.h b/src/crypto/crypto_dh.h index ec12548dbe5..b2df7ca7bb5 100644 --- a/src/crypto/crypto_dh.h +++ b/src/crypto/crypto_dh.h @@ -14,48 +14,19 @@ namespace node { namespace crypto { -class DiffieHellman : public BaseObject { +class DiffieHellman final : public BaseObject { public: static void Initialize(Environment* env, v8::Local target); static void RegisterExternalReferences(ExternalReferenceRegistry* registry); - bool Init(int primeLength, int g); - bool Init(BignumPointer&& bn_p, int g); - bool Init(const char* p, int p_len, int g); - bool Init(const char* p, int p_len, const char* g, int g_len); - - static void Stateless(const v8::FunctionCallbackInfo& args); - - protected: - static void DiffieHellmanGroup( - const v8::FunctionCallbackInfo& args); - static void New(const v8::FunctionCallbackInfo& args); - static void GenerateKeys(const v8::FunctionCallbackInfo& args); - static void GetPrime(const v8::FunctionCallbackInfo& args); - static void GetGenerator(const v8::FunctionCallbackInfo& args); - static void GetPublicKey(const v8::FunctionCallbackInfo& args); - static void GetPrivateKey(const v8::FunctionCallbackInfo& args); - static void ComputeSecret(const v8::FunctionCallbackInfo& args); - static void SetPublicKey(const v8::FunctionCallbackInfo& args); - static void SetPrivateKey(const v8::FunctionCallbackInfo& args); - static void VerifyErrorGetter( - const v8::FunctionCallbackInfo& args); - - DiffieHellman(Environment* env, v8::Local wrap); + DiffieHellman(Environment* env, v8::Local wrap, DHPointer dh); + operator DHPointer&() { return dh_; } void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(DiffieHellman) SET_SELF_SIZE(DiffieHellman) private: - static void GetField(const v8::FunctionCallbackInfo& args, - const BIGNUM* (*get_field)(const DH*), - const char* err_if_null); - static void SetKey(const v8::FunctionCallbackInfo& args, - int (*set_field)(DH*, BIGNUM*), const char* what); - bool VerifyContext(); - - int verifyError_; DHPointer dh_; }; diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 8ae0a002fec..9ebe14011ee 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -92,7 +92,7 @@ const crypto = require('crypto'); assert.throws(() => { dh3.computeSecret(''); }, { message: common.hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ? - 'error:02800080:Diffie-Hellman routines::invalid secret' : + 'Unspecified validation error' : 'Supplied key is too small' }); } }