mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
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 <yagiz@nizipli.com>
This commit is contained in:
parent
431ac161e6
commit
6bf7b6e342
304
deps/ncrypto/dh-primes.h
vendored
Normal file
304
deps/ncrypto/dh-primes.h
vendored
Normal file
@ -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 <openssl/dh.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
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));
|
||||
}
|
236
deps/ncrypto/ncrypto.cc
vendored
236
deps/ncrypto/ncrypto.cc
vendored
@ -1,6 +1,7 @@
|
||||
#include "ncrypto.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
@ -8,6 +9,9 @@
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
#include <openssl/provider.h>
|
||||
#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<CheckResult>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(out.get()), &out_size) <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (out_size < out.size()) {
|
||||
const size_t padding = out.size() - out_size;
|
||||
uint8_t* data = static_cast<uint8_t*>(out.get());
|
||||
memmove(data + padding, data, out_size);
|
||||
memset(data, 0, padding);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace ncrypto
|
||||
|
1
deps/ncrypto/ncrypto.gyp
vendored
1
deps/ncrypto/ncrypto.gyp
vendored
@ -2,6 +2,7 @@
|
||||
'variables': {
|
||||
'ncrypto_sources': [
|
||||
'engine.cc',
|
||||
'dh-primes.h',
|
||||
'ncrypto.cc',
|
||||
'ncrypto.h',
|
||||
],
|
||||
|
79
deps/ncrypto/ncrypto.h
vendored
79
deps/ncrypto/ncrypto.h
vendored
@ -194,7 +194,6 @@ using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
|
||||
|
||||
using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
|
||||
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
|
||||
using DHPointer = DeleteFnPtr<DH, DH_free>;
|
||||
using DSAPointer = DeleteFnPtr<DSA, DSA_free>;
|
||||
using DSASigPointer = DeleteFnPtr<DSA_SIG, DSA_SIG_free>;
|
||||
using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
|
||||
@ -354,10 +353,88 @@ class BignumPointer final {
|
||||
static unsigned long GetWord(const BIGNUM* bn);
|
||||
static const BIGNUM* One();
|
||||
|
||||
BignumPointer clone();
|
||||
|
||||
private:
|
||||
DeleteFnPtr<BIGNUM, BN_clear_free> 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, DH_free> dh_;
|
||||
};
|
||||
|
||||
class X509Pointer;
|
||||
|
||||
class X509View final {
|
||||
|
@ -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 <variant>
|
||||
|
||||
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<Object> wrap)
|
||||
: BaseObject(env, wrap), verifyError_(0) {
|
||||
DiffieHellman::DiffieHellman(Environment* env, Local<Object> wrap, DHPointer dh)
|
||||
: BaseObject(env, wrap), dh_(std::move(dh)) {
|
||||
MakeWeak();
|
||||
}
|
||||
|
||||
void DiffieHellman::Initialize(Environment* env, Local<Object> target) {
|
||||
Isolate* isolate = env->isolate();
|
||||
Local<Context> context = env->context();
|
||||
auto make = [&](Local<String> name, FunctionCallback callback) {
|
||||
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, callback);
|
||||
|
||||
const PropertyAttribute attributes =
|
||||
static_cast<PropertyAttribute>(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<FunctionTemplate> verify_error_getter_templ =
|
||||
FunctionTemplate::New(isolate,
|
||||
DiffieHellman::VerifyErrorGetter,
|
||||
Local<Value>(),
|
||||
Signature::New(env->isolate(), t),
|
||||
/* length */ 0,
|
||||
ConstructorBehavior::kThrow,
|
||||
SideEffectType::kHasNoSideEffect);
|
||||
|
||||
t->InstanceTemplate()->SetAccessorProperty(
|
||||
env->verify_error_string(),
|
||||
verify_error_getter_templ,
|
||||
Local<FunctionTemplate>(),
|
||||
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<Value> 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<Value>());
|
||||
}
|
||||
|
||||
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<const unsigned char*>(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<const unsigned char*>(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<const unsigned char*>(p), p_len);
|
||||
return bn_p && SetDhParams(dh_.get(), &bn_p, &bn_g) && VerifyContext();
|
||||
}
|
||||
|
||||
constexpr int kStandardizedGenerator = 2;
|
||||
|
||||
template <BIGNUM* (*p)(BIGNUM*)>
|
||||
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<p>
|
||||
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<Value>& args) {
|
||||
void DiffieHellmanGroup(const FunctionCallbackInfo<Value>& 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<Value>& args) {
|
||||
void New(const FunctionCallbackInfo<Value>& 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<Int32>()->Value(),
|
||||
args[1].As<Int32>()->Value());
|
||||
}
|
||||
} else {
|
||||
ArrayBufferOrViewContents<char> 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<Int32>()->Value());
|
||||
} else {
|
||||
ArrayBufferOrViewContents<char> 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<Int32>()->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<Int32>()->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<char> arg0(args[0]);
|
||||
if (UNLIKELY(!arg0.CheckSizeInt32()))
|
||||
return THROW_ERR_OUT_OF_RANGE(env, "prime is too big");
|
||||
|
||||
BignumPointer bn_p(reinterpret_cast<uint8_t*>(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<Int32>()->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<char> arg1(args[1]);
|
||||
if (UNLIKELY(!arg1.CheckSizeInt32()))
|
||||
return THROW_ERR_OUT_OF_RANGE(env, "generator is too big");
|
||||
bn_g = BignumPointer(reinterpret_cast<uint8_t*>(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<Value>& args) {
|
||||
void GenerateKeys(const FunctionCallbackInfo<Value>& 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<BackingStore> 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<unsigned char*>(bs->Data()), bs->ByteLength()));
|
||||
|
||||
Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
|
||||
Local<Value> buffer;
|
||||
if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return;
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
|
||||
|
||||
void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& 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<BackingStore> 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<unsigned char*>(bs->Data()), bs->ByteLength()));
|
||||
|
||||
Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
|
||||
Local<Value> buffer;
|
||||
if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return;
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
|
||||
void DiffieHellman::GetPrime(const FunctionCallbackInfo<Value>& 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<Value>& 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<Value>& 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<Value>& 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<Value>& args) {
|
||||
void GetPrime(const FunctionCallbackInfo<Value>& 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<Value> buffer;
|
||||
if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) {
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void GetGenerator(const FunctionCallbackInfo<Value>& 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<Value> buffer;
|
||||
if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) {
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void GetPublicKey(const FunctionCallbackInfo<Value>& 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<Value> buffer;
|
||||
if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) {
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void GetPrivateKey(const FunctionCallbackInfo<Value>& 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<Value> buffer;
|
||||
if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) {
|
||||
args.GetReturnValue().Set(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeSecret(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
DiffieHellman* diffieHellman;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This());
|
||||
DHPointer& dh = *diffieHellman;
|
||||
|
||||
CHECK_EQ(args.Length(), 1);
|
||||
ArrayBufferOrViewContents<unsigned char> key_buf(args[0]);
|
||||
@ -398,93 +257,72 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
|
||||
return THROW_ERR_OUT_OF_RANGE(env, "secret is too big");
|
||||
BignumPointer key(key_buf.data(), key_buf.size());
|
||||
|
||||
std::unique_ptr<BackingStore> 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<unsigned char*>(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<char*>(bs->Data()),
|
||||
bs->ByteLength());
|
||||
|
||||
Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
|
||||
Local<Value> 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<Value>& args,
|
||||
int (*set_field)(DH*, BIGNUM*), const char* what) {
|
||||
void SetPublicKey(const FunctionCallbackInfo<Value>& 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<unsigned char> 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<Value>& args) {
|
||||
SetKey(args,
|
||||
[](DH* dh, BIGNUM* num) { return DH_set0_key(dh, num, nullptr); },
|
||||
"Public key");
|
||||
void SetPrivateKey(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
DiffieHellman* diffieHellman;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.This());
|
||||
DHPointer& dh = *diffieHellman;
|
||||
CHECK_EQ(args.Length(), 1);
|
||||
ArrayBufferOrViewContents<unsigned char> 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<Value>& args) {
|
||||
SetKey(args,
|
||||
[](DH* dh, BIGNUM* num) { return DH_set0_key(dh, nullptr, num); },
|
||||
"Private key");
|
||||
}
|
||||
|
||||
void DiffieHellman::VerifyErrorGetter(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(args.GetIsolate());
|
||||
|
||||
void Check(const FunctionCallbackInfo<Value>& 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<int>(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<bool> 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<bool>();
|
||||
}
|
||||
|
||||
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<BignumPointer>(¶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<unsigned char>(), &out_size) <= 0) {
|
||||
return ByteSource();
|
||||
}
|
||||
|
||||
ZeroPadDiffieHellmanSecret(out_size, out.data<char>(), out.size());
|
||||
return std::move(out).release();
|
||||
return ByteSource::Allocated(dp.release());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void DiffieHellman::Stateless(const FunctionCallbackInfo<Value>& args) {
|
||||
void Stateless(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
CHECK(args[0]->IsObject() && args[1]->IsObject());
|
||||
@ -662,6 +485,7 @@ void DiffieHellman::Stateless(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
args.GetReturnValue().Set(out);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Maybe<bool> DHBitsTraits::AdditionalConfig(
|
||||
CryptoJobMode mode,
|
||||
@ -719,5 +543,75 @@ Maybe<bool> GetDhKeyDetail(
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
void DiffieHellman::Initialize(Environment* env, Local<Object> target) {
|
||||
Isolate* isolate = env->isolate();
|
||||
Local<Context> context = env->context();
|
||||
auto make = [&](Local<String> name, FunctionCallback callback) {
|
||||
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, callback);
|
||||
|
||||
const PropertyAttribute attributes =
|
||||
static_cast<PropertyAttribute>(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<FunctionTemplate> verify_error_getter_templ =
|
||||
FunctionTemplate::New(isolate,
|
||||
Check,
|
||||
Local<Value>(),
|
||||
Signature::New(env->isolate(), t),
|
||||
/* length */ 0,
|
||||
ConstructorBehavior::kThrow,
|
||||
SideEffectType::kHasNoSideEffect);
|
||||
|
||||
t->InstanceTemplate()->SetAccessorProperty(env->verify_error_string(),
|
||||
verify_error_getter_templ,
|
||||
Local<FunctionTemplate>(),
|
||||
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
|
||||
|
@ -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<v8::Object> 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<v8::Value>& args);
|
||||
|
||||
protected:
|
||||
static void DiffieHellmanGroup(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GenerateKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPrime(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetGenerator(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ComputeSecret(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void VerifyErrorGetter(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
DiffieHellman(Environment* env, v8::Local<v8::Object> wrap);
|
||||
DiffieHellman(Environment* env, v8::Local<v8::Object> 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<v8::Value>& args,
|
||||
const BIGNUM* (*get_field)(const DH*),
|
||||
const char* err_if_null);
|
||||
static void SetKey(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
int (*set_field)(DH*, BIGNUM*), const char* what);
|
||||
bool VerifyContext();
|
||||
|
||||
int verifyError_;
|
||||
DHPointer dh_;
|
||||
};
|
||||
|
||||
|
@ -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' });
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user