diff --git a/deps/openssl/openssl/crypto/bn/bn_lib.c b/deps/openssl/openssl/crypto/bn/bn_lib.c index 03bd8cd183a694..807db775a74726 100644 --- a/deps/openssl/openssl/crypto/bn/bn_lib.c +++ b/deps/openssl/openssl/crypto/bn/bn_lib.c @@ -889,6 +889,38 @@ void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) a->top ^= t; b->top ^= t; + t = (a->neg ^ b->neg) & condition; + a->neg ^= t; + b->neg ^= t; + + /*- + * BN_FLG_STATIC_DATA: indicates that data may not be written to. Intention + * is actually to treat it as it's read-only data, and some (if not most) + * of it does reside in read-only segment. In other words observation of + * BN_FLG_STATIC_DATA in BN_consttime_swap should be treated as fatal + * condition. It would either cause SEGV or effectively cause data + * corruption. + * + * BN_FLG_MALLOCED: refers to BN structure itself, and hence must be + * preserved. + * + * BN_FLG_SECURE: must be preserved, because it determines how x->d was + * allocated and hence how to free it. + * + * BN_FLG_CONSTTIME: sufficient to mask and swap + * + * BN_FLG_FIXED_TOP: indicates that we haven't called bn_correct_top() on + * the data, so the d array may be padded with additional 0 values (i.e. + * top could be greater than the minimal value that it could be). We should + * be swapping it + */ + +#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP) + + t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition; + a->flags ^= t; + b->flags ^= t; + #define BN_CONSTTIME_SWAP(ind) \ do { \ t = (a->d[ind] ^ b->d[ind]) & condition; \ diff --git a/deps/openssl/openssl/crypto/ec/ec_mult.c b/deps/openssl/openssl/crypto/ec/ec_mult.c index 2231f9957ef67f..c573d4b453d62b 100644 --- a/deps/openssl/openssl/crypto/ec/ec_mult.c +++ b/deps/openssl/openssl/crypto/ec/ec_mult.c @@ -310,6 +310,224 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) return r; } +#define EC_POINT_BN_set_flags(P, flags) do { \ + BN_set_flags(&(P)->X, (flags)); \ + BN_set_flags(&(P)->Y, (flags)); \ + BN_set_flags(&(P)->Z, (flags)); \ +} while(0) + +/*- + * This functions computes (in constant time) a point multiplication over the + * EC group. + * + * At a high level, it is Montgomery ladder with conditional swaps. + * + * It performs either a fixed scalar point multiplication + * (scalar * generator) + * when point is NULL, or a generic scalar point multiplication + * (scalar * point) + * when point is not NULL. + * + * scalar should be in the range [0,n) otherwise all constant time bets are off. + * + * NB: This says nothing about EC_POINT_add and EC_POINT_dbl, + * which of course are not constant time themselves. + * + * The product is stored in r. + * + * Returns 1 on success, 0 otherwise. + */ +static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx) +{ + int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; + EC_POINT *s = NULL; + BIGNUM *k = NULL; + BIGNUM *lambda = NULL; + BIGNUM *cardinality = NULL; + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL && (ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + + s = EC_POINT_new(group); + if (s == NULL) + goto err; + + if (point == NULL) { + if (!EC_POINT_copy(s, group->generator)) + goto err; + } else { + if (!EC_POINT_copy(s, point)) + goto err; + } + + EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME); + + cardinality = BN_CTX_get(ctx); + lambda = BN_CTX_get(ctx); + k = BN_CTX_get(ctx); + if (k == NULL || !BN_mul(cardinality, &group->order, &group->cofactor, ctx)) + goto err; + + /* + * Group cardinalities are often on a word boundary. + * So when we pad the scalar, some timing diff might + * pop if it needs to be expanded due to carries. + * So expand ahead of time. + */ + cardinality_bits = BN_num_bits(cardinality); + group_top = cardinality->top; + if ((bn_wexpand(k, group_top + 2) == NULL) + || (bn_wexpand(lambda, group_top + 2) == NULL)) + goto err; + + if (!BN_copy(k, scalar)) + goto err; + + BN_set_flags(k, BN_FLG_CONSTTIME); + + if ((BN_num_bits(k) > cardinality_bits) || (BN_is_negative(k))) { + /*- + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(k, k, cardinality, ctx)) + goto err; + } + + if (!BN_add(lambda, k, cardinality)) + goto err; + BN_set_flags(lambda, BN_FLG_CONSTTIME); + if (!BN_add(k, lambda, cardinality)) + goto err; + /* + * lambda := scalar + cardinality + * k := scalar + 2*cardinality + */ + kbit = BN_is_bit_set(lambda, cardinality_bits); + BN_consttime_swap(kbit, k, lambda, group_top + 2); + + group_top = group->field.top; + if ((bn_wexpand(&s->X, group_top) == NULL) + || (bn_wexpand(&s->Y, group_top) == NULL) + || (bn_wexpand(&s->Z, group_top) == NULL) + || (bn_wexpand(&r->X, group_top) == NULL) + || (bn_wexpand(&r->Y, group_top) == NULL) + || (bn_wexpand(&r->Z, group_top) == NULL)) + goto err; + + /* top bit is a 1, in a fixed pos */ + if (!EC_POINT_copy(r, s)) + goto err; + + EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME); + + if (!EC_POINT_dbl(group, s, s, ctx)) + goto err; + + pbit = 0; + +#define EC_POINT_CSWAP(c, a, b, w, t) do { \ + BN_consttime_swap(c, &(a)->X, &(b)->X, w); \ + BN_consttime_swap(c, &(a)->Y, &(b)->Y, w); \ + BN_consttime_swap(c, &(a)->Z, &(b)->Z, w); \ + t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \ + (a)->Z_is_one ^= (t); \ + (b)->Z_is_one ^= (t); \ +} while(0) + + /*- + * The ladder step, with branches, is + * + * k[i] == 0: S = add(R, S), R = dbl(R) + * k[i] == 1: R = add(S, R), S = dbl(S) + * + * Swapping R, S conditionally on k[i] leaves you with state + * + * k[i] == 0: T, U = R, S + * k[i] == 1: T, U = S, R + * + * Then perform the ECC ops. + * + * U = add(T, U) + * T = dbl(T) + * + * Which leaves you with state + * + * k[i] == 0: U = add(R, S), T = dbl(R) + * k[i] == 1: U = add(S, R), T = dbl(S) + * + * Swapping T, U conditionally on k[i] leaves you with state + * + * k[i] == 0: R, S = T, U + * k[i] == 1: R, S = U, T + * + * Which leaves you with state + * + * k[i] == 0: S = add(R, S), R = dbl(R) + * k[i] == 1: R = add(S, R), S = dbl(S) + * + * So we get the same logic, but instead of a branch it's a + * conditional swap, followed by ECC ops, then another conditional swap. + * + * Optimization: The end of iteration i and start of i-1 looks like + * + * ... + * CSWAP(k[i], R, S) + * ECC + * CSWAP(k[i], R, S) + * (next iteration) + * CSWAP(k[i-1], R, S) + * ECC + * CSWAP(k[i-1], R, S) + * ... + * + * So instead of two contiguous swaps, you can merge the condition + * bits and do a single swap. + * + * k[i] k[i-1] Outcome + * 0 0 No Swap + * 0 1 Swap + * 1 0 Swap + * 1 1 No Swap + * + * This is XOR. pbit tracks the previous bit of k. + */ + + for (i = cardinality_bits - 1; i >= 0; i--) { + kbit = BN_is_bit_set(k, i) ^ pbit; + EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one); + if (!EC_POINT_add(group, s, r, s, ctx)) + goto err; + if (!EC_POINT_dbl(group, r, r, ctx)) + goto err; + /* + * pbit logic merges this cswap with that of the + * next iteration + */ + pbit ^= kbit; + } + /* one final cswap to move the right value into r */ + EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one); +#undef EC_POINT_CSWAP + + ret = 1; + + err: + EC_POINT_free(s); + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + + return ret; +} + +#undef EC_POINT_BN_set_flags + /* * TODO: table should be optimised for the wNAF-based implementation, * sometimes smaller windows will give better performance (thus the @@ -369,6 +587,34 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, return EC_POINT_set_to_infinity(group, r); } + if (!BN_is_zero(&group->order) && !BN_is_zero(&group->cofactor)) { + /*- + * Handle the common cases where the scalar is secret, enforcing a constant + * time scalar multiplication algorithm. + */ + if ((scalar != NULL) && (num == 0)) { + /*- + * In this case we want to compute scalar * GeneratorPoint: this + * codepath is reached most prominently by (ephemeral) key generation + * of EC cryptosystems (i.e. ECDSA keygen and sign setup, ECDH + * keygen/first half), where the scalar is always secret. This is why + * we ignore if BN_FLG_CONSTTIME is actually set and we always call the + * constant time version. + */ + return ec_mul_consttime(group, r, scalar, NULL, ctx); + } + if ((scalar == NULL) && (num == 1)) { + /*- + * In this case we want to compute scalar * GenericPoint: this codepath + * is reached most prominently by the second half of ECDH, where the + * secret scalar is multiplied by the peer's public point. To protect + * the secret scalar, we ignore if BN_FLG_CONSTTIME is actually set and + * we always call the constant time version. + */ + return ec_mul_consttime(group, r, scalars[0], points[0], ctx); + } + } + for (i = 0; i < num; i++) { if (group->meth != points[i]->meth) { ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 43abf735d38d3e..96f1cd6d46fb23 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 2 #define V8_BUILD_NUMBER 414 -#define V8_PATCH_LEVEL 70 +#define V8_PATCH_LEVEL 73 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/base/debug/stack_trace_posix.cc b/deps/v8/src/base/debug/stack_trace_posix.cc index 87c0a73d191e65..681dfbf9728449 100644 --- a/deps/v8/src/base/debug/stack_trace_posix.cc +++ b/deps/v8/src/base/debug/stack_trace_posix.cc @@ -72,6 +72,7 @@ const char kMangledSymbolPrefix[] = "_Z"; const char kSymbolCharacters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; +#if HAVE_EXECINFO_H // Demangles C++ symbols in the given text. Example: // // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]" @@ -81,7 +82,6 @@ void DemangleSymbols(std::string* text) { // Note: code in this function is NOT async-signal safe (std::string uses // malloc internally). -#if HAVE_EXECINFO_H std::string::size_type search_from = 0; while (search_from < text->size()) { @@ -117,9 +117,8 @@ void DemangleSymbols(std::string* text) { search_from = mangled_start + 2; } } - -#endif // HAVE_EXECINFO_H } +#endif // HAVE_EXECINFO_H class BacktraceOutputHandler { public: @@ -129,6 +128,7 @@ class BacktraceOutputHandler { virtual ~BacktraceOutputHandler() {} }; +#if HAVE_EXECINFO_H void OutputPointer(void* pointer, BacktraceOutputHandler* handler) { // This should be more than enough to store a 64-bit number in hex: // 16 hex digits + 1 for null-terminator. @@ -139,7 +139,6 @@ void OutputPointer(void* pointer, BacktraceOutputHandler* handler) { handler->HandleOutput(buf); } -#if HAVE_EXECINFO_H void ProcessBacktrace(void* const* trace, size_t size, BacktraceOutputHandler* handler) { // NOTE: This code MUST be async-signal safe (it's used by in-process diff --git a/deps/v8/src/compiler/bytecode-graph-builder.cc b/deps/v8/src/compiler/bytecode-graph-builder.cc index 2d68ed8b0378eb..ca98a5fe28830b 100644 --- a/deps/v8/src/compiler/bytecode-graph-builder.cc +++ b/deps/v8/src/compiler/bytecode-graph-builder.cc @@ -475,7 +475,7 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint( BytecodeGraphBuilder::BytecodeGraphBuilder( Zone* local_zone, Handle shared_info, Handle feedback_vector, BailoutId osr_offset, - JSGraph* jsgraph, CallFrequency invocation_frequency, + JSGraph* jsgraph, CallFrequency& invocation_frequency, SourcePositionTable* source_positions, int inlining_id, JSTypeHintLowering::Flags flags, bool stack_check) : local_zone_(local_zone), diff --git a/deps/v8/src/compiler/bytecode-graph-builder.h b/deps/v8/src/compiler/bytecode-graph-builder.h index 0ec8a1f473c55c..7609ec7279eda6 100644 --- a/deps/v8/src/compiler/bytecode-graph-builder.h +++ b/deps/v8/src/compiler/bytecode-graph-builder.h @@ -28,7 +28,7 @@ class BytecodeGraphBuilder { BytecodeGraphBuilder( Zone* local_zone, Handle shared, Handle feedback_vector, BailoutId osr_offset, - JSGraph* jsgraph, CallFrequency invocation_frequency, + JSGraph* jsgraph, CallFrequency& invocation_frequency, SourcePositionTable* source_positions, int inlining_id = SourcePosition::kNotInlined, JSTypeHintLowering::Flags flags = JSTypeHintLowering::kNoFlags, diff --git a/deps/v8/src/compiler/js-inlining.cc b/deps/v8/src/compiler/js-inlining.cc index b74f94fa72cdf7..abce004367e332 100644 --- a/deps/v8/src/compiler/js-inlining.cc +++ b/deps/v8/src/compiler/js-inlining.cc @@ -539,9 +539,10 @@ Reduction JSInliner::ReduceJSCall(Node* node) { if (info_->is_bailout_on_uninitialized()) { flags |= JSTypeHintLowering::kBailoutOnUninitialized; } + CallFrequency frequency = call.frequency(); BytecodeGraphBuilder graph_builder( zone(), shared_info, feedback_vector, BailoutId::None(), jsgraph(), - call.frequency(), source_positions_, inlining_id, flags, false); + frequency, source_positions_, inlining_id, flags, false); graph_builder.CreateGraph(); // Extract the inlinee start/end nodes. diff --git a/deps/v8/src/compiler/js-operator.cc b/deps/v8/src/compiler/js-operator.cc index 2a680cd6769ad7..6ea5b850c6910a 100644 --- a/deps/v8/src/compiler/js-operator.cc +++ b/deps/v8/src/compiler/js-operator.cc @@ -731,7 +731,8 @@ const Operator* JSOperatorBuilder::CallForwardVarargs(size_t arity, parameters); // parameter } -const Operator* JSOperatorBuilder::Call(size_t arity, CallFrequency frequency, +const Operator* JSOperatorBuilder::Call(size_t arity, + CallFrequency const& frequency, VectorSlotPair const& feedback, ConvertReceiverMode convert_mode) { CallParameters parameters(arity, frequency, feedback, convert_mode); @@ -751,7 +752,8 @@ const Operator* JSOperatorBuilder::CallWithArrayLike(CallFrequency frequency) { } const Operator* JSOperatorBuilder::CallWithSpread( - uint32_t arity, CallFrequency frequency, VectorSlotPair const& feedback) { + uint32_t arity, CallFrequency const& frequency, + VectorSlotPair const& feedback) { CallParameters parameters(arity, frequency, feedback, ConvertReceiverMode::kAny); return new (zone()) Operator1( // -- diff --git a/deps/v8/src/compiler/js-operator.h b/deps/v8/src/compiler/js-operator.h index 5ea288f355eeba..0bf2c589818566 100644 --- a/deps/v8/src/compiler/js-operator.h +++ b/deps/v8/src/compiler/js-operator.h @@ -192,7 +192,7 @@ CallForwardVarargsParameters const& CallForwardVarargsParametersOf( // used as a parameter by JSCall and JSCallWithSpread operators. class CallParameters final { public: - CallParameters(size_t arity, CallFrequency frequency, + CallParameters(size_t arity, CallFrequency const& frequency, VectorSlotPair const& feedback, ConvertReceiverMode convert_mode) : bit_field_(ArityField::encode(arity) | @@ -201,7 +201,7 @@ class CallParameters final { feedback_(feedback) {} size_t arity() const { return ArityField::decode(bit_field_); } - CallFrequency frequency() const { return frequency_; } + CallFrequency const& frequency() const { return frequency_; } ConvertReceiverMode convert_mode() const { return ConvertReceiverModeField::decode(bit_field_); } @@ -647,12 +647,12 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final const Operator* CallForwardVarargs(size_t arity, uint32_t start_index); const Operator* Call( - size_t arity, CallFrequency frequency = CallFrequency(), + size_t arity, CallFrequency const& frequency = CallFrequency(), VectorSlotPair const& feedback = VectorSlotPair(), ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny); const Operator* CallWithArrayLike(CallFrequency frequency); const Operator* CallWithSpread( - uint32_t arity, CallFrequency frequency = CallFrequency(), + uint32_t arity, CallFrequency const& frequency = CallFrequency(), VectorSlotPair const& feedback = VectorSlotPair()); const Operator* CallRuntime(Runtime::FunctionId id); const Operator* CallRuntime(Runtime::FunctionId id, size_t arity); diff --git a/deps/v8/src/compiler/pipeline.cc b/deps/v8/src/compiler/pipeline.cc index 4b91e9fc4a22fc..e5aac506e67b60 100644 --- a/deps/v8/src/compiler/pipeline.cc +++ b/deps/v8/src/compiler/pipeline.cc @@ -890,10 +890,11 @@ struct GraphBuilderPhase { if (data->info()->is_bailout_on_uninitialized()) { flags |= JSTypeHintLowering::kBailoutOnUninitialized; } + CallFrequency frequency = CallFrequency(1.0f); BytecodeGraphBuilder graph_builder( temp_zone, data->info()->shared_info(), handle(data->info()->closure()->feedback_vector()), - data->info()->osr_offset(), data->jsgraph(), CallFrequency(1.0f), + data->info()->osr_offset(), data->jsgraph(), frequency, data->source_positions(), SourcePosition::kNotInlined, flags); graph_builder.CreateGraph(); } diff --git a/deps/v8/src/compiler/store-store-elimination.cc b/deps/v8/src/compiler/store-store-elimination.cc index 71aa2110bb7808..eaa74328f09c71 100644 --- a/deps/v8/src/compiler/store-store-elimination.cc +++ b/deps/v8/src/compiler/store-store-elimination.cc @@ -251,6 +251,9 @@ void StoreStoreElimination::Run(JSGraph* js_graph, Zone* temp_zone) { } } +#if V8_OS_AIX +ALLOW_UNUSED_TYPE +#endif bool RedundantStoreFinder::IsEffectful(Node* node) { return (node->op()->EffectInputCount() >= 1); } @@ -552,6 +555,9 @@ bool UnobservableStore::operator==(const UnobservableStore other) const { return (id_ == other.id_) && (offset_ == other.offset_); } +#if V8_OS_AIX +ALLOW_UNUSED_TYPE +#endif bool UnobservableStore::operator!=(const UnobservableStore other) const { return !(*this == other); } diff --git a/deps/v8/src/conversions.cc b/deps/v8/src/conversions.cc index 8956a261688b1b..1071c1f2a1b312 100644 --- a/deps/v8/src/conversions.cc +++ b/deps/v8/src/conversions.cc @@ -53,11 +53,17 @@ class StringCharacterStreamIterator { }; +#if V8_OS_AIX +ALLOW_UNUSED_TYPE +#endif StringCharacterStreamIterator::StringCharacterStreamIterator( StringCharacterStream* stream) : stream_(stream) { ++(*this); } +#if V8_OS_AIX +ALLOW_UNUSED_TYPE +#endif uint16_t StringCharacterStreamIterator::operator*() const { return current_; } diff --git a/deps/v8/testing/gtest.gyp b/deps/v8/testing/gtest.gyp index a94ee884fe9f51..ddc617537130e4 100644 --- a/deps/v8/testing/gtest.gyp +++ b/deps/v8/testing/gtest.gyp @@ -94,6 +94,10 @@ 'action????': ['$(TargetPath)', '--gtest_print_time'], }, }], + ['OS=="aix"', { + 'cflags': [ '-Wno-nonnull-compare', + '-Wno-address' ], + }], ], }], ],