Compare commits

..

2 Commits

Author SHA1 Message Date
David Benjamin 4d7ba4e4e5 bn/asm/rsaz-avx2.pl: fix digit correction bug in rsaz_1024_mul_avx2.
Credit to OSS-Fuzz for finding this.

CVE-2017-3738

(Imported from upstream's 5630661aecbea5fe3c4740f5fea744a1f07a6253 and
77d75993651b63e872244a3256e37967bb3c3e9e.)

Confirmed with Intel SDE that the fix makes the test vector pass and
that, without the fix, the test vector does not. (Well, we knew the
latter already, since it was our test vector.)

(cherry-picked from 296a61d600)

Change-Id: I167aa3407ddab3b434bacbd18e099c55aa40ac4c
Reviewed-on: https://boringssl-review.googlesource.com/23884
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-on: https://boringssl-review.googlesource.com/23924
2017-12-07 19:16:01 +00:00
Adam Langley 9f69f139ed Clear bottom three bits of password scalar in SPAKE2.
Due to a copy-paste error, the call to |left_shift_3| is missing after
reducing the password scalar in SPAKE2. This means that three bits of
the password leak in Alice's message. (Two in Bob's message as the point
N happens to have order 4l, not 8l.)

The “correct” fix is to put in the missing call to |left_shift_3|, but
that would be a breaking change. In order to fix this in a unilateral
way, we add points of small order to the masking point to bring it into
prime-order subgroup.

BUG=chromium:778101

Change-Id: I440931a3df7f009b324d2a3e3af2d893a101804f
Reviewed-on: https://boringssl-review.googlesource.com/22445
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-11-16 08:19:54 -08:00
1816 changed files with 35813 additions and 36977 deletions
-1
View File
@@ -5,7 +5,6 @@ ssl/test/runner/runner
doc/*.html
doc/doc.css
util/bot/android_ndk
util/bot/android_tools
util/bot/cmake-linux64
util/bot/cmake-linux64.tar.gz
+16 -9
View File
@@ -79,15 +79,14 @@ for other variables which may be used to configure the build.
### Building for Android
It's possible to build BoringSSL with the Android NDK using CMake. Recent
versions of the NDK include a CMake toolchain file which works with CMake 3.6.0
or later. This has been tested with version r16b of the NDK.
It's possible to build BoringSSL with the Android NDK using CMake. This has
been tested with version 10d of the NDK.
Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the
directory. Then make a build directory as above and run CMake like this:
cmake -DANDROID_ABI=armeabi-v7a \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
-DCMAKE_TOOLCHAIN_FILE=../third_party/android-cmake/android.toolchain.cmake \
-DANDROID_NATIVE_API_LEVEL=16 \
-GNinja ..
@@ -95,11 +94,7 @@ Once you've run that, Ninja should produce Android-compatible binaries. You
can replace `armeabi-v7a` in the above with `arm64-v8a` and use API level 21 or
higher to build aarch64 binaries.
For older NDK versions, BoringSSL ships a third-party CMake toolchain file. Use
`../third_party/android-cmake/android.toolchain.cmake` for
`CMAKE_TOOLCHAIN_FILE` instead.
For other options, see the documentation in the toolchain file.
For other options, see [android-cmake's documentation](./third_party/android-cmake/README.md).
### Building for iOS
@@ -150,6 +145,18 @@ corresponding ARM feature.
Note that if a feature is enabled in this way, but not actually supported at
run-time, BoringSSL will likely crash.
## Assembling ARMv8 with Clang
In order to support the ARMv8 crypto instructions, Clang requires that the
architecture be `armv8-a+crypto`. However, setting that as a general build flag
would allow the compiler to assume that crypto instructions are *always*
supported, even without testing for them.
It's possible to set the architecture in an assembly file using the `.arch`
directive, but only very recent versions of Clang support this. If
`BORINGSSL_CLANG_SUPPORTS_DOT_ARCH` is defined then `.arch` directives will be
used with Clang, otherwise you may need to craft acceptable assembler flags.
# Running tests
There are two sets of tests: the C/C++ tests and the blackbox tests. For former
+13 -54
View File
@@ -1,11 +1,5 @@
cmake_minimum_required (VERSION 2.8.11)
# Report AppleClang separately from Clang. Their version numbers are different.
# https://cmake.org/cmake/help/v3.0/policy/CMP0025.html
if(POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif()
# Defer enabling C and CXX languages.
project (BoringSSL NONE)
@@ -48,18 +42,17 @@ endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
# Note clang-cl is odd and sets both CLANG and MSVC. We base our configuration
# primarily on our normal Clang one.
set(C_CXX_FLAGS "-Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings")
# primarily on our normal Clang one because the MSVC one is mostly
# suppressions for an overaggressive -Wall.
set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings")
if(MSVC)
# clang-cl sets different default warnings than clang. It also treats -Wall
# as -Weverything, to match MSVC. Instead -W3 is the alias for -Wall.
# See http://llvm.org/viewvc/llvm-project?view=revision&revision=319116
set(C_CXX_FLAGS "${C_CXX_FLAGS} -W3 -Wno-unused-parameter -fmsc-version=1900")
# clang-cl sets different default warnings than clang.
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-unused-parameter -fmsc-version=1900")
# googletest suppresses warning C4996 via a pragma, but clang-cl does not
# honor it. Suppress it here to compensate. See https://crbug.com/772117.
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-deprecated-declarations")
else()
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wall -ggdb -fvisibility=hidden -fno-common")
set(C_CXX_FLAGS "${C_CXX_FLAGS} -ggdb -fvisibility=hidden -fno-common")
endif()
if(CLANG)
@@ -70,18 +63,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-free-nonheap-object")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
NOT "6.0.0" VERSION_GREATER CMAKE_C_COMPILER_VERSION)
# Clang's -Wtautological-constant-compare is far too aggressive and does not
# account for, say, wanting the same code to work on both 32-bit and 64-bit
# platforms.
#
# Note "Clang" and "AppleClang" version differently, so we check for an
# exact match on the COMPILER_ID. As of writing, the warning is not in any
# release of AppleClang yet.
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-tautological-constant-compare -Wtautological-constant-out-of-range-compare")
endif()
if(CLANG OR NOT "7.0.0" VERSION_GREATER CMAKE_C_COMPILER_VERSION)
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wimplicit-fallthrough")
endif()
@@ -91,9 +72,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
if(NOT BORINGSSL_ALLOW_CXX_RUNTIME)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
endif()
@@ -257,24 +235,6 @@ if (ASAN)
set(OPENSSL_NO_ASM "1")
endif()
if(CFI)
if(NOT CLANG)
message(FATAL_ERROR "Cannot enable CFI unless using Clang")
endif()
# TODO(crbug.com/785442): Remove -fsanitize-cfi-icall-generalize-pointers.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=cfi -fno-sanitize-trap=cfi -fsanitize-cfi-icall-generalize-pointers -flto")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=cfi -fno-sanitize-trap=cfi -fsanitize-cfi-icall-generalize-pointers -flto")
# We use Chromium's copy of clang, which requires -fuse-ld=lld if building
# with -flto. That, in turn, can't handle -ggdb.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
string(REPLACE "-ggdb" "-g" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REPLACE "-ggdb" "-g" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# -flto causes object files to contain LLVM bitcode. Mixing those with
# assembly output in the same static library breaks the linker.
set(OPENSSL_NO_ASM "1")
endif()
if (GCOV)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
@@ -340,14 +300,14 @@ else()
message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (ANDROID AND NOT ANDROID_NDK_REVISION AND ${ARCH} STREQUAL "arm")
# The third-party Android-NDK CMake files somehow fail to set the -march flag
# for assembly files. Without this flag, the compiler believes that it's
if (ANDROID AND ${ARCH} STREQUAL "arm")
# The Android-NDK CMake files somehow fail to set the -march flag for
# assembly files. Without this flag, the compiler believes that it's
# building for ARMv5.
set(CMAKE_ASM_FLAGS "-march=${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_ASM_FLAGS}")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -march=${CMAKE_SYSTEM_PROCESSOR}")
endif()
if (${ARCH} STREQUAL "x86" AND APPLE AND ${CMAKE_VERSION} VERSION_LESS "3.0")
if (${ARCH} STREQUAL "x86" AND APPLE)
# With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X,
# but clang defaults to 64-bit builds on OS X unless otherwise told.
# Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3.
@@ -356,8 +316,8 @@ endif()
# Add minimal googletest targets. The provided one has many side-effects, and
# googletest has a very straightforward build.
add_library(boringssl_gtest third_party/googletest/src/gtest-all.cc)
target_include_directories(boringssl_gtest PRIVATE third_party/googletest)
add_library(gtest third_party/googletest/src/gtest-all.cc)
target_include_directories(gtest PRIVATE third_party/googletest)
include_directories(third_party/googletest/include)
@@ -375,7 +335,6 @@ add_custom_command(
add_library(crypto_test_data OBJECT crypto_test_data.cc)
add_subdirectory(crypto)
add_subdirectory(third_party/fiat)
add_subdirectory(ssl)
add_subdirectory(ssl/test)
add_subdirectory(fipstools)
+35 -24
View File
@@ -5,9 +5,8 @@ license. This license is reproduced at the bottom of this file.
Contributors to BoringSSL are required to follow the CLA rules for Chromium:
https://cla.developers.google.com/clas
Files in third_party/ have their own licenses, as described therein. The MIT
license, for third_party/fiat, which, unlike other third_party directories, is
compiled into non-test libraries, is included below.
Some files from Intel are under yet another license, which is also included
underneath.
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
OpenSSL License and the original SSLeay license apply to the toolkit. See below
@@ -157,25 +156,37 @@ ISC license used for completely new code in BoringSSL:
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
The code in third_party/fiat carries the MIT license:
Some files from Intel carry the following license:
Copyright (c) 2015-2016 the fiat-crypto authors (see
https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Copyright (c) 2012, Intel Corporation
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * 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.
#
# * Neither the name of the Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
#
# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
# EXPRESS 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 INTEL CORPORATION OR
# 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.
+1 -1
View File
@@ -210,7 +210,7 @@ strings and loading algorithms, etc. All of these functions still exist in
BoringSSL for convenience, but they do nothing and are not necessary.
The one exception is `CRYPTO_library_init`. In `BORINGSSL_NO_STATIC_INITIALIZER`
builds, it must be called to query CPU capabilities before the rest of the
builds, it must be called to query CPU capabitilies before the rest of the
library. In the default configuration, this is done with a static initializer
and is also unnecessary.
+3 -7
View File
@@ -53,7 +53,7 @@ if(NOT OPENSSL_NO_ASM)
set(PERLASM_STYLE win32n)
set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
endif()
set(CMAKE_ASM_NASM_FLAGS "-gcv8")
set(CMAKE_ASM_NASM_FLAGS "-g cv8")
# On Windows, we use the NASM output, specifically built with Yasm.
set(ASM_EXT asm)
@@ -134,7 +134,6 @@ add_library(
OBJECT
cpu-aarch64-fuchsia.c
cpu-aarch64-linux.c
cpu-arm.c
cpu-arm-linux.c
@@ -180,7 +179,6 @@ add_library(
$<TARGET_OBJECTS:chacha>
$<TARGET_OBJECTS:poly1305>
$<TARGET_OBJECTS:curve25519>
$<TARGET_OBJECTS:fiat>
$<TARGET_OBJECTS:buf>
$<TARGET_OBJECTS:bn_extra>
$<TARGET_OBJECTS:bio>
@@ -222,7 +220,6 @@ add_executable(
asn1/asn1_test.cc
base64/base64_test.cc
buf/buf_test.cc
bio/bio_test.cc
bytestring/bytestring_test.cc
chacha/chacha_test.cc
@@ -261,7 +258,6 @@ add_executable(
pool/pool_test.cc
refcount_test.cc
rsa_extra/rsa_test.cc
self_test.cc
test/file_test_gtest.cc
thread_test.cc
x509/x509_test.cc
@@ -269,11 +265,11 @@ add_executable(
x509v3/v3name_test.cc
$<TARGET_OBJECTS:crypto_test_data>
$<TARGET_OBJECTS:boringssl_gtest_main>
$<TARGET_OBJECTS:gtest_main>
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(crypto_test crypto boringssl_gtest)
target_link_libraries(crypto_test crypto gtest)
if (WIN32)
target_link_libraries(crypto_test ws2_32)
endif()
+9 -20
View File
@@ -56,7 +56,6 @@
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
@@ -111,6 +110,7 @@ int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
{
int neg = 0, i;
long r = 0;
if (a == NULL)
return (0L);
@@ -120,31 +120,20 @@ long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
else if (i != V_ASN1_ENUMERATED)
return -1;
OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
long_larger_than_uint64_t);
if (a->length > (int)sizeof(uint64_t)) {
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly */
return -1;
return (0xffffffffL);
}
if (a->data == NULL)
return 0;
uint64_t r64 = 0;
if (a->data != NULL) {
for (i = 0; i < a->length; i++) {
r64 <<= 8;
r64 |= (unsigned char)a->data[i];
}
if (r64 > LONG_MAX) {
return -1;
}
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
long r = (long) r64;
if (neg)
r = -r;
return r;
return (r);
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
-3
View File
@@ -81,9 +81,6 @@ int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x)
int i, j = 0, n, ret = 1;
n = i2d(x, NULL);
if (n <= 0)
return 0;
b = (char *)OPENSSL_malloc(n);
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+36 -52
View File
@@ -57,7 +57,6 @@
#include <openssl/asn1.h>
#include <string.h>
#include <limits.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -347,50 +346,46 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
if (v >= 0) {
return ASN1_INTEGER_set_uint64(a, (uint64_t) v);
int j, k;
unsigned int i;
unsigned char buf[sizeof(long) + 1];
long d;
a->type = V_ASN1_INTEGER;
if (a->length < (int)(sizeof(long) + 1)) {
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data =
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
}
if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t) v)) {
return 0;
}
a->type = V_ASN1_NEG_INTEGER;
return 1;
}
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v)
{
uint8_t *const newdata = OPENSSL_malloc(sizeof(uint64_t));
if (newdata == NULL) {
if (a->data == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
return (0);
}
d = v;
if (d < 0) {
d = -d;
a->type = V_ASN1_NEG_INTEGER;
}
OPENSSL_free(out->data);
out->data = newdata;
v = CRYPTO_bswap8(v);
memcpy(out->data, &v, sizeof(v));
out->type = V_ASN1_INTEGER;
size_t leading_zeros;
for (leading_zeros = 0; leading_zeros < sizeof(uint64_t) - 1;
leading_zeros++) {
if (out->data[leading_zeros] != 0) {
for (i = 0; i < sizeof(long); i++) {
if (d == 0)
break;
}
buf[i] = (int)d & 0xff;
d >>= 8;
}
out->length = sizeof(uint64_t) - leading_zeros;
OPENSSL_memmove(out->data, out->data + leading_zeros, out->length);
return 1;
j = 0;
for (k = i - 1; k >= 0; k--)
a->data[j++] = buf[k];
a->length = j;
return (1);
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
long r = 0;
if (a == NULL)
return (0L);
@@ -400,31 +395,20 @@ long ASN1_INTEGER_get(const ASN1_INTEGER *a)
else if (i != V_ASN1_INTEGER)
return -1;
OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
long_larger_than_uint64_t);
if (a->length > (int)sizeof(uint64_t)) {
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
if (a->data == NULL)
return 0;
uint64_t r64 = 0;
if (a->data != NULL) {
for (i = 0; i < a->length; i++) {
r64 <<= 8;
r64 |= (unsigned char)a->data[i];
}
if (r64 > LONG_MAX) {
return -1;
}
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
long r = (long) r64;
if (neg)
r = -r;
return r;
return (r);
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
+22 -24
View File
@@ -61,19 +61,17 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc) (uint32_t value, void *in),
int (*rfunc) (unsigned long value, void *in),
void *arg);
static int in_utf8(uint32_t value, void *arg);
static int out_utf8(uint32_t value, void *arg);
static int type_str(uint32_t value, void *arg);
static int cpy_asc(uint32_t value, void *arg);
static int cpy_bmp(uint32_t value, void *arg);
static int cpy_univ(uint32_t value, void *arg);
static int cpy_utf8(uint32_t value, void *arg);
static int is_printable(uint32_t value);
static int in_utf8(unsigned long value, void *arg);
static int out_utf8(unsigned long value, void *arg);
static int type_str(unsigned long value, void *arg);
static int cpy_asc(unsigned long value, void *arg);
static int cpy_bmp(unsigned long value, void *arg);
static int cpy_univ(unsigned long value, void *arg);
static int cpy_utf8(unsigned long value, void *arg);
static int is_printable(unsigned long value);
/*
* These functions take a string in UTF8, ASCII or multibyte form and a mask
@@ -102,7 +100,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
unsigned char *p;
int nchar;
char strbuf[32];
int (*cpyfunc) (uint32_t, void *) = NULL;
int (*cpyfunc) (unsigned long, void *) = NULL;
if (len == -1)
len = strlen((const char *)in);
if (!mask)
@@ -255,10 +253,10 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
*/
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc) (uint32_t value, void *in),
int (*rfunc) (unsigned long value, void *in),
void *arg)
{
uint32_t value;
unsigned long value;
int ret;
while (len) {
if (inform == MBSTRING_ASC) {
@@ -269,8 +267,8 @@ static int traverse_string(const unsigned char *p, int len, int inform,
value |= *p++;
len -= 2;
} else if (inform == MBSTRING_UNIV) {
value = ((uint32_t)*p++) << 24;
value |= ((uint32_t)*p++) << 16;
value = ((unsigned long)*p++) << 24;
value |= ((unsigned long)*p++) << 16;
value |= *p++ << 8;
value |= *p++;
len -= 4;
@@ -294,7 +292,7 @@ static int traverse_string(const unsigned char *p, int len, int inform,
/* Just count number of characters */
static int in_utf8(uint32_t value, void *arg)
static int in_utf8(unsigned long value, void *arg)
{
int *nchar;
nchar = arg;
@@ -304,7 +302,7 @@ static int in_utf8(uint32_t value, void *arg)
/* Determine size of output as a UTF8 String */
static int out_utf8(uint32_t value, void *arg)
static int out_utf8(unsigned long value, void *arg)
{
int *outlen;
outlen = arg;
@@ -317,7 +315,7 @@ static int out_utf8(uint32_t value, void *arg)
* "mask".
*/
static int type_str(uint32_t value, void *arg)
static int type_str(unsigned long value, void *arg)
{
unsigned long types;
types = *((unsigned long *)arg);
@@ -337,7 +335,7 @@ static int type_str(uint32_t value, void *arg)
/* Copy one byte per character ASCII like strings */
static int cpy_asc(uint32_t value, void *arg)
static int cpy_asc(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
@@ -349,7 +347,7 @@ static int cpy_asc(uint32_t value, void *arg)
/* Copy two byte per character BMPStrings */
static int cpy_bmp(uint32_t value, void *arg)
static int cpy_bmp(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
@@ -362,7 +360,7 @@ static int cpy_bmp(uint32_t value, void *arg)
/* Copy four byte per character UniversalStrings */
static int cpy_univ(uint32_t value, void *arg)
static int cpy_univ(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
@@ -377,7 +375,7 @@ static int cpy_univ(uint32_t value, void *arg)
/* Copy to a UTF8String */
static int cpy_utf8(uint32_t value, void *arg)
static int cpy_utf8(unsigned long value, void *arg)
{
unsigned char **p;
int ret;
@@ -389,7 +387,7 @@ static int cpy_utf8(uint32_t value, void *arg)
}
/* Return 1 if the character is permitted in a PrintableString */
static int is_printable(uint32_t value)
static int is_printable(unsigned long value)
{
int ch;
if (value > 0x7f)
+128
View File
@@ -87,6 +87,134 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
return (objsize);
}
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
{
int i, first, len = 0, c, use_bn;
char ftmp[24], *tmp = ftmp;
int tmpsize = sizeof ftmp;
const char *p;
unsigned long l;
BIGNUM *bl = NULL;
if (num == 0)
return (0);
else if (num == -1)
num = strlen(buf);
p = buf;
c = *(p++);
num--;
if ((c >= '0') && (c <= '2')) {
first = c - '0';
} else {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
goto err;
}
if (num <= 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
goto err;
}
c = *(p++);
num--;
for (;;) {
if (num <= 0)
break;
if ((c != '.') && (c != ' ')) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
goto err;
}
l = 0;
use_bn = 0;
for (;;) {
if (num <= 0)
break;
num--;
c = *(p++);
if ((c == ' ') || (c == '.'))
break;
if ((c < '0') || (c > '9')) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
goto err;
}
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
use_bn = 1;
if (!bl)
bl = BN_new();
if (!bl || !BN_set_word(bl, l))
goto err;
}
if (use_bn) {
if (!BN_mul_word(bl, 10L)
|| !BN_add_word(bl, c - '0'))
goto err;
} else
l = l * 10L + (long)(c - '0');
}
if (len == 0) {
if ((first < 2) && (l >= 40)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
goto err;
}
if (use_bn) {
if (!BN_add_word(bl, first * 40))
goto err;
} else
l += (long)first *40;
}
i = 0;
if (use_bn) {
int blsize;
blsize = BN_num_bits(bl);
blsize = (blsize + 6) / 7;
if (blsize > tmpsize) {
if (tmp != ftmp)
OPENSSL_free(tmp);
tmpsize = blsize + 32;
tmp = OPENSSL_malloc(tmpsize);
if (!tmp)
goto err;
}
while (blsize--) {
BN_ULONG t = BN_div_word(bl, 0x80L);
if (t == (BN_ULONG)-1)
goto err;
tmp[i++] = (unsigned char)t;
}
} else {
for (;;) {
tmp[i++] = (unsigned char)l & 0x7f;
l >>= 7L;
if (l == 0L)
break;
}
}
if (out != NULL) {
if (len + i > olen) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
goto err;
}
while (--i > 0)
out[len++] = tmp[i] | 0x80;
out[len++] = tmp[0];
} else
len += i;
}
if (tmp != ftmp)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return (len);
err:
if (tmp != ftmp)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return (0);
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
+11 -13
View File
@@ -59,8 +59,6 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
/* UTF8 utilities */
/*
@@ -72,10 +70,10 @@
* incorrectly (not minimal length).
*/
int UTF8_getc(const unsigned char *str, int len, uint32_t *val)
int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
{
const unsigned char *p;
uint32_t value;
unsigned long value;
int ret;
if (len <= 0)
return 0;
@@ -114,7 +112,7 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80))
return -3;
value = ((uint32_t)(*p++ & 0x7)) << 18;
value = ((unsigned long)(*p++ & 0x7)) << 18;
value |= (*p++ & 0x3f) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
@@ -129,9 +127,9 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80))
return -3;
value = ((uint32_t)(*p++ & 0x3)) << 24;
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
value |= ((uint32_t)(*p++ & 0x3f)) << 12;
value = ((unsigned long)(*p++ & 0x3)) << 24;
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x200000)
@@ -146,10 +144,10 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val)
|| ((p[4] & 0xc0) != 0x80)
|| ((p[5] & 0xc0) != 0x80))
return -3;
value = ((uint32_t)(*p++ & 0x1)) << 30;
value |= ((uint32_t)(*p++ & 0x3f)) << 24;
value |= ((uint32_t)(*p++ & 0x3f)) << 18;
value |= ((uint32_t)(*p++ & 0x3f)) << 12;
value = ((unsigned long)(*p++ & 0x1)) << 30;
value |= ((unsigned long)(*p++ & 0x3f)) << 24;
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x4000000)
@@ -169,7 +167,7 @@ int UTF8_getc(const unsigned char *str, int len, uint32_t *val)
* most 6 characters.
*/
int UTF8_putc(unsigned char *str, int len, uint32_t value)
int UTF8_putc(unsigned char *str, int len, unsigned long value)
{
if (!str)
len = 6; /* Maximum we will need */
-6
View File
@@ -90,12 +90,6 @@ int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
int UTF8_getc(const unsigned char *str, int len, uint32_t *val);
int UTF8_putc(unsigned char *str, int len, uint32_t value);
#if defined(__cplusplus)
} /* extern C */
-28
View File
@@ -15,7 +15,6 @@
#include <stdio.h>
#include <gtest/gtest.h>
#include <limits.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
@@ -61,30 +60,3 @@ TEST(ASN1Test, LargeTags) {
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
obj->value.asn1_string->length));
}
TEST(ASN1Test, IntegerSetting) {
bssl::UniquePtr<ASN1_INTEGER> by_bn(M_ASN1_INTEGER_new());
bssl::UniquePtr<ASN1_INTEGER> by_long(M_ASN1_INTEGER_new());
bssl::UniquePtr<ASN1_INTEGER> by_uint64(M_ASN1_INTEGER_new());
bssl::UniquePtr<BIGNUM> bn(BN_new());
const std::vector<int64_t> kValues = {
LONG_MIN, -2, -1, 0, 1, 2, 0xff, 0x100, 0xffff, 0x10000, LONG_MAX,
};
for (const auto &i : kValues) {
SCOPED_TRACE(i);
ASSERT_EQ(1, ASN1_INTEGER_set(by_long.get(), i));
const uint64_t abs = i < 0 ? (0 - (uint64_t) i) : i;
ASSERT_TRUE(BN_set_u64(bn.get(), abs));
BN_set_negative(bn.get(), i < 0);
ASSERT_TRUE(BN_to_ASN1_INTEGER(bn.get(), by_bn.get()));
EXPECT_EQ(0, ASN1_INTEGER_cmp(by_bn.get(), by_long.get()));
if (i >= 0) {
ASSERT_EQ(1, ASN1_INTEGER_set_uint64(by_uint64.get(), i));
EXPECT_EQ(0, ASN1_INTEGER_cmp(by_bn.get(), by_uint64.get()));
}
}
}
+4 -2
View File
@@ -59,7 +59,8 @@
#include <openssl/asn1t.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
/* Free up an ASN1 structure */
@@ -73,7 +74,8 @@ void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
asn1_item_combine_free(pval, it, 0);
}
void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
+2 -3
View File
@@ -63,7 +63,6 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
#include "asn1_locl.h"
#include "../internal.h"
@@ -202,7 +201,7 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
return 1;
memerr2:
asn1_item_combine_free(pval, it, combine);
ASN1_item_ex_free(pval, it);
memerr:
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
@@ -212,7 +211,7 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
return 0;
auxerr2:
asn1_item_combine_free(pval, it, combine);
ASN1_item_ex_free(pval, it);
auxerr:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
#ifdef CRYPTO_MDEBUG
-1
View File
@@ -27,7 +27,6 @@
#if !defined(OPENSSL_WINDOWS)
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
-1
View File
@@ -73,7 +73,6 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
#include <openssl/mem.h>
#include "internal.h"
#include "../internal.h"
static int bio_fd_non_fatal_error(int err) {
-2
View File
@@ -81,8 +81,6 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../internal.h"
#define BIO_FP_READ 0x02
#define BIO_FP_WRITE 0x04
+16
View File
@@ -42,6 +42,22 @@ int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
CBS child;
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
CBS_len(&child) == 0) {
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
return 0;
}
// This function intentionally does not reject negative numbers or non-minimal
// encodings. Estonian IDs issued between September 2014 to September 2015 are
// broken. See https://crbug.com/532048 and https://crbug.com/534766.
//
// TODO(davidben): Remove this code and callers in March 2016.
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
// Negative numbers are unsupported.
if (BN_is_negative(bn)) {
+5 -6
View File
@@ -77,9 +77,8 @@ int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
static const char hextable[] = "0123456789abcdef";
char *BN_bn2hex(const BIGNUM *bn) {
int width = bn_minimal_width(bn);
char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
width * BN_BYTES * 2 + 1 /* trailing NUL */);
bn->top * BN_BYTES * 2 + 1 /* trailing NUL */);
if (buf == NULL) {
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
return NULL;
@@ -95,7 +94,7 @@ char *BN_bn2hex(const BIGNUM *bn) {
}
int z = 0;
for (int i = width - 1; i >= 0; i--) {
for (int i = bn->top - 1; i >= 0; i--) {
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
// strip leading zeros
int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
@@ -154,7 +153,7 @@ static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
in_len -= todo;
}
assert(i <= bn->dmax);
bn->width = i;
bn->top = i;
return 1;
}
@@ -223,7 +222,7 @@ static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_
goto err;
}
bn_set_minimal_width(ret);
bn_correct_top(ret);
if (!BN_is_zero(ret)) {
ret->neg = neg;
}
@@ -348,7 +347,7 @@ int BN_print(BIO *bp, const BIGNUM *a) {
goto end;
}
for (i = bn_minimal_width(a) - 1; i >= 0; i--) {
for (i = a->top - 1; i >= 0; i--) {
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
// strip leading zeros
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
-14
View File
@@ -131,20 +131,6 @@ size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
return BUF_MEM_grow(buf, len);
}
int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
size_t new_len = buf->length + len;
if (new_len < len) {
OPENSSL_PUT_ERROR(BUF, ERR_R_OVERFLOW);
return 0;
}
if (!BUF_MEM_reserve(buf, new_len)) {
return 0;
}
OPENSSL_memcpy(buf->data + buf->length, in, len);
buf->length = new_len;
return 1;
}
char *BUF_strdup(const char *str) {
if (str == NULL) {
return NULL;
-97
View File
@@ -1,97 +0,0 @@
/* Copyright (c) 2017, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/buf.h>
#include <string.h>
#include <string>
#include <gtest/gtest.h>
TEST(BufTest, Basic) {
bssl::UniquePtr<BUF_MEM> buf(BUF_MEM_new());
ASSERT_TRUE(buf);
EXPECT_EQ(0u, buf->length);
// Use BUF_MEM_reserve to increase buf->max.
ASSERT_TRUE(BUF_MEM_reserve(buf.get(), 200));
EXPECT_GE(buf->max, 200u);
EXPECT_EQ(0u, buf->length);
// BUF_MEM_reserve with a smaller cap is a no-op.
size_t old_max = buf->max;
ASSERT_TRUE(BUF_MEM_reserve(buf.get(), 100));
EXPECT_EQ(old_max, buf->max);
EXPECT_EQ(0u, buf->length);
// BUF_MEM_grow can increase the length without reallocating.
ASSERT_EQ(100u, BUF_MEM_grow(buf.get(), 100));
EXPECT_EQ(100u, buf->length);
EXPECT_EQ(old_max, buf->max);
memset(buf->data, 'A', buf->length);
// If BUF_MEM_reserve reallocates, it preserves the contents.
ASSERT_TRUE(BUF_MEM_reserve(buf.get(), old_max + 1));
ASSERT_GE(buf->max, old_max + 1);
EXPECT_EQ(100u, buf->length);
for (size_t i = 0; i < 100; i++) {
EXPECT_EQ('A', buf->data[i]);
}
// BUF_MEM_grow should zero everything beyond buf->length.
memset(buf->data, 'B', buf->max);
ASSERT_EQ(150u, BUF_MEM_grow(buf.get(), 150));
EXPECT_EQ(150u, buf->length);
for (size_t i = 0; i < 100; i++) {
EXPECT_EQ('B', buf->data[i]);
}
for (size_t i = 100; i < 150; i++) {
EXPECT_EQ(0, buf->data[i]);
}
// BUF_MEM_grow can rellocate if necessary.
size_t new_len = buf->max + 1;
ASSERT_EQ(new_len, BUF_MEM_grow(buf.get(), new_len));
EXPECT_GE(buf->max, new_len);
EXPECT_EQ(new_len, buf->length);
for (size_t i = 0; i < 100; i++) {
EXPECT_EQ('B', buf->data[i]);
}
for (size_t i = 100; i < new_len; i++) {
EXPECT_EQ(0, buf->data[i]);
}
// BUF_MEM_grow can shink.
ASSERT_EQ(50u, BUF_MEM_grow(buf.get(), 50));
EXPECT_EQ(50u, buf->length);
for (size_t i = 0; i < 50; i++) {
EXPECT_EQ('B', buf->data[i]);
}
}
TEST(BufTest, Append) {
bssl::UniquePtr<BUF_MEM> buf(BUF_MEM_new());
ASSERT_TRUE(buf);
ASSERT_TRUE(BUF_MEM_append(buf.get(), nullptr, 0));
ASSERT_TRUE(BUF_MEM_append(buf.get(), "hello ", 6));
ASSERT_TRUE(BUF_MEM_append(buf.get(), nullptr, 0));
ASSERT_TRUE(BUF_MEM_append(buf.get(), "world", 5));
std::string str(128, 'A');
ASSERT_TRUE(BUF_MEM_append(buf.get(), str.data(), str.size()));
EXPECT_EQ("hello world" + str, std::string(buf->data, buf->length));
}
+4 -1
View File
@@ -29,7 +29,10 @@ static const unsigned kMaxDepth = 2048;
// is_string_type returns one if |tag| is a string type and zero otherwise. It
// ignores the constructed bit.
static int is_string_type(unsigned tag) {
switch (tag & ~CBS_ASN1_CONSTRUCTED) {
if ((tag & 0xc0) != 0) {
return 0;
}
switch (tag & 0x1f) {
case CBS_ASN1_BITSTRING:
case CBS_ASN1_OCTETSTRING:
case CBS_ASN1_UTF8STRING:
+30 -294
View File
@@ -123,27 +123,27 @@ TEST(CBSTest, GetASN1) {
uint64_t value;
CBS_init(&data, kData1, sizeof(kData1));
EXPECT_FALSE(CBS_peek_asn1_tag(&data, CBS_ASN1_BOOLEAN));
EXPECT_TRUE(CBS_peek_asn1_tag(&data, CBS_ASN1_SEQUENCE));
EXPECT_FALSE(CBS_peek_asn1_tag(&data, 0x1));
EXPECT_TRUE(CBS_peek_asn1_tag(&data, 0x30));
ASSERT_TRUE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBS_get_asn1(&data, &contents, 0x30));
EXPECT_EQ(Bytes("\x01\x02"), Bytes(CBS_data(&contents), CBS_len(&contents)));
CBS_init(&data, kData2, sizeof(kData2));
// data is truncated
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
CBS_init(&data, kData3, sizeof(kData3));
// zero byte length of length
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
CBS_init(&data, kData4, sizeof(kData4));
// long form mistakenly used.
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
CBS_init(&data, kData5, sizeof(kData5));
// length takes too many bytes.
EXPECT_FALSE(CBS_get_asn1(&data, &contents, CBS_ASN1_SEQUENCE));
EXPECT_FALSE(CBS_get_asn1(&data, &contents, 0x30));
CBS_init(&data, kData1, sizeof(kData1));
// wrong tag.
@@ -151,72 +151,56 @@ TEST(CBSTest, GetASN1) {
CBS_init(&data, NULL, 0);
// peek at empty data.
EXPECT_FALSE(CBS_peek_asn1_tag(&data, CBS_ASN1_SEQUENCE));
EXPECT_FALSE(CBS_peek_asn1_tag(&data, 0x30));
CBS_init(&data, NULL, 0);
// optional elements at empty data.
ASSERT_TRUE(CBS_get_optional_asn1(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
EXPECT_FALSE(present);
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
ASSERT_TRUE(
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0));
EXPECT_FALSE(present);
EXPECT_EQ(0u, CBS_len(&contents));
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
&data, &contents, NULL,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0));
EXPECT_EQ(0u, CBS_len(&contents));
ASSERT_TRUE(CBS_get_optional_asn1_uint64(
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, 42));
ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
EXPECT_EQ(42u, value);
CBS_init(&data, kData6, sizeof(kData6));
// optional element.
ASSERT_TRUE(CBS_get_optional_asn1(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
EXPECT_FALSE(present);
ASSERT_TRUE(CBS_get_optional_asn1(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
ASSERT_TRUE(CBS_get_optional_asn1(&data, &contents, &present, 0xa1));
EXPECT_TRUE(present);
EXPECT_EQ(Bytes("\x04\x01\x01"),
Bytes(CBS_data(&contents), CBS_len(&contents)));
CBS_init(&data, kData6, sizeof(kData6));
// optional octet string.
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
ASSERT_TRUE(
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0));
EXPECT_FALSE(present);
EXPECT_EQ(0u, CBS_len(&contents));
ASSERT_TRUE(CBS_get_optional_asn1_octet_string(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
ASSERT_TRUE(
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1));
EXPECT_TRUE(present);
EXPECT_EQ(Bytes("\x01"), Bytes(CBS_data(&contents), CBS_len(&contents)));
CBS_init(&data, kData7, sizeof(kData7));
// invalid optional octet string.
EXPECT_FALSE(CBS_get_optional_asn1_octet_string(
&data, &contents, &present,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1));
EXPECT_FALSE(
CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1));
CBS_init(&data, kData8, sizeof(kData8));
// optional integer.
ASSERT_TRUE(CBS_get_optional_asn1_uint64(
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, 42));
ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
EXPECT_EQ(42u, value);
ASSERT_TRUE(CBS_get_optional_asn1_uint64(
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, 42));
ASSERT_TRUE(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
EXPECT_EQ(1u, value);
CBS_init(&data, kData9, sizeof(kData9));
// invalid optional integer.
EXPECT_FALSE(CBS_get_optional_asn1_uint64(
&data, &value, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, 42));
EXPECT_FALSE(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
unsigned tag;
CBS_init(&data, kData1, sizeof(kData1));
@@ -233,54 +217,6 @@ TEST(CBSTest, GetASN1) {
Bytes(CBS_data(&contents), CBS_len(&contents)));
}
TEST(CBSTest, ParseASN1Tag) {
const struct {
bool ok;
unsigned tag;
std::vector<uint8_t> in;
} kTests[] = {
{true, CBS_ASN1_SEQUENCE, {0x30, 0}},
{true, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4, {0xa4, 0}},
{true, CBS_ASN1_APPLICATION | 30, {0x5e, 0}},
{true, CBS_ASN1_APPLICATION | 31, {0x5f, 0x1f, 0}},
{true, CBS_ASN1_APPLICATION | 32, {0x5f, 0x20, 0}},
{true,
CBS_ASN1_PRIVATE | CBS_ASN1_CONSTRUCTED | 0x1fffffff,
{0xff, 0x81, 0xff, 0xff, 0xff, 0x7f, 0}},
// Tag number fits in unsigned but not |CBS_ASN1_TAG_NUMBER_MASK|.
{false, 0, {0xff, 0x82, 0xff, 0xff, 0xff, 0x7f, 0}},
// Tag number does not fit in unsigned.
{false, 0, {0xff, 0x90, 0x80, 0x80, 0x80, 0, 0}},
// Tag number is not minimally-encoded
{false, 0, {0x5f, 0x80, 0x1f, 0}},
// Tag number should have used short form.
{false, 0, {0x5f, 0x80, 0x1e, 0}},
};
for (const auto &t : kTests) {
SCOPED_TRACE(Bytes(t.in));
unsigned tag;
CBS cbs, child;
CBS_init(&cbs, t.in.data(), t.in.size());
ASSERT_EQ(t.ok, !!CBS_get_any_asn1(&cbs, &child, &tag));
if (t.ok) {
EXPECT_EQ(t.tag, tag);
EXPECT_EQ(0u, CBS_len(&child));
EXPECT_EQ(0u, CBS_len(&cbs));
CBS_init(&cbs, t.in.data(), t.in.size());
EXPECT_TRUE(CBS_peek_asn1_tag(&cbs, t.tag));
EXPECT_FALSE(CBS_peek_asn1_tag(&cbs, t.tag + 1));
EXPECT_TRUE(CBS_get_asn1(&cbs, &child, t.tag));
EXPECT_EQ(0u, CBS_len(&child));
EXPECT_EQ(0u, CBS_len(&cbs));
CBS_init(&cbs, t.in.data(), t.in.size());
EXPECT_FALSE(CBS_get_asn1(&cbs, &child, t.tag + 1));
}
}
}
TEST(CBSTest, GetOptionalASN1Bool) {
static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
@@ -480,42 +416,15 @@ TEST(CBBTest, Misuse) {
}
TEST(CBBTest, ASN1) {
static const uint8_t kExpected[] = {
// SEQUENCE { 1 2 3 }
0x30, 3, 1, 2, 3,
// [4 CONSTRUCTED] { 4 5 6 }
0xa4, 3, 4, 5, 6,
// [APPLICATION 30 PRIMITIVE] { 7 8 9 }
0x5e, 3, 7, 8, 9,
// [APPLICATION 31 PRIMITIVE] { 10 11 12 }
0x5f, 0x1f, 3, 10, 11, 12,
// [PRIVATE 2^29-1 CONSTRUCTED] { 13 14 15 }
0xff, 0x81, 0xff, 0xff, 0xff, 0x7f, 3, 13, 14, 15,
};
static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
uint8_t *buf;
size_t buf_len;
bssl::ScopedCBB cbb;
CBB contents, inner_contents;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x01\x02\x03", 3));
ASSERT_TRUE(
CBB_add_asn1(cbb.get(), &contents,
CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4));
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x04\x05\x06", 3));
ASSERT_TRUE(
CBB_add_asn1(cbb.get(), &contents,
CBS_ASN1_APPLICATION | 30));
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x07\x08\x09", 3));
ASSERT_TRUE(
CBB_add_asn1(cbb.get(), &contents,
CBS_ASN1_APPLICATION | 31));
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x0a\x0b\x0c", 3));
ASSERT_TRUE(
CBB_add_asn1(cbb.get(), &contents,
CBS_ASN1_PRIVATE | CBS_ASN1_CONSTRUCTED | 0x1fffffff));
ASSERT_TRUE(CBB_add_bytes(&contents, (const uint8_t *)"\x0d\x0e\x0f", 3));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
bssl::UniquePtr<uint8_t> scoper(buf);
@@ -523,7 +432,7 @@ TEST(CBBTest, ASN1) {
std::vector<uint8_t> test_data(100000, 0x42);
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
ASSERT_TRUE(CBB_add_bytes(&contents, test_data.data(), 130));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
scoper.reset(buf);
@@ -533,7 +442,7 @@ TEST(CBBTest, ASN1) {
EXPECT_EQ(Bytes(test_data.data(), 130), Bytes(buf + 3, 130));
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
ASSERT_TRUE(CBB_add_bytes(&contents, test_data.data(), 1000));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
scoper.reset(buf);
@@ -543,8 +452,8 @@ TEST(CBBTest, ASN1) {
EXPECT_EQ(Bytes(test_data.data(), 1000), Bytes(buf + 4, 1000));
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_asn1(&contents, &inner_contents, CBS_ASN1_SEQUENCE));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &contents, 0x30));
ASSERT_TRUE(CBB_add_asn1(&contents, &inner_contents, 0x30));
ASSERT_TRUE(CBB_add_bytes(&inner_contents, test_data.data(), 100000));
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
scoper.reset(buf);
@@ -581,12 +490,6 @@ TEST(CBSTest, BerConvert) {
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
// kIndefBER2 contains a constructed [APPLICATION 31] with an indefinite
// length.
static const uint8_t kIndefBER2[] = {0x7f, 0x1f, 0x80, 0x01,
0x01, 0x02, 0x00, 0x00};
static const uint8_t kIndefDER2[] = {0x7f, 0x1f, 0x03, 0x01, 0x01, 0x02};
// kOctetStringBER contains an indefinite length OCTET STRING with two parts.
// These parts need to be concatenated in DER form.
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
@@ -631,8 +534,6 @@ TEST(CBSTest, BerConvert) {
sizeof(kSimpleBER));
ExpectBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
sizeof(kIndefBER));
ExpectBerConvert("kIndefBER2", kIndefDER2, sizeof(kIndefDER2), kIndefBER2,
sizeof(kIndefBER2));
ExpectBerConvert("kOctetStringBER", kOctetStringDER, sizeof(kOctetStringDER),
kOctetStringBER, sizeof(kOctetStringBER));
ExpectBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
@@ -886,168 +787,3 @@ TEST(CBSTest, BitString) {
CBS_asn1_bitstring_has_bit(&cbs, test.bit));
}
}
TEST(CBBTest, AddOIDFromText) {
const struct {
const char *text;
std::vector<uint8_t> der;
} kValidOIDs[] = {
// Some valid values.
{"0.0", {0x00}},
{"0.2.3.4", {0x2, 0x3, 0x4}},
{"1.2.3.4", {0x2a, 0x3, 0x4}},
{"2.2.3.4", {0x52, 0x3, 0x4}},
{"1.2.840.113554.4.1.72585",
{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09}},
// Test edge cases around the first component.
{"0.39", {0x27}},
{"1.0", {0x28}},
{"1.39", {0x4f}},
{"2.0", {0x50}},
{"2.1", {0x51}},
{"2.40", {0x78}},
// Edge cases near an overflow.
{"1.2.18446744073709551615",
{0x2a, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}},
{"2.18446744073709551535",
{0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}},
};
const char *kInvalidTexts[] = {
// Invalid second component.
"0.40",
"1.40",
// Invalid first component.
"3.1",
// The empty string is not an OID.
"",
// No empty components.
".1.2.3.4.5",
"1..2.3.4.5",
"1.2.3.4.5.",
// There must be at least two components.
"1",
// No extra leading zeros.
"00.1.2.3.4",
"01.1.2.3.4",
// Overflow for both components or 40*A + B.
"1.2.18446744073709551616",
"2.18446744073709551536",
};
const std::vector<uint8_t> kInvalidDER[] = {
// The empty string is not an OID.
{},
// Non-minimal representation.
{0x80, 0x01},
// Overflow. This is the DER representation of
// 1.2.840.113554.4.1.72585.18446744073709551616. (The final value is
// 2^64.)
{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09,
0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00},
};
for (const auto &t : kValidOIDs) {
SCOPED_TRACE(t.text);
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1_oid_from_text(cbb.get(), t.text, strlen(t.text)));
uint8_t *out;
size_t len;
ASSERT_TRUE(CBB_finish(cbb.get(), &out, &len));
bssl::UniquePtr<uint8_t> free_out(out);
EXPECT_EQ(Bytes(t.der), Bytes(out, len));
CBS cbs;
CBS_init(&cbs, t.der.data(), t.der.size());
bssl::UniquePtr<char> text(CBS_asn1_oid_to_text(&cbs));
ASSERT_TRUE(text.get());
EXPECT_STREQ(t.text, text.get());
}
for (const char *t : kInvalidTexts) {
SCOPED_TRACE(t);
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
EXPECT_FALSE(CBB_add_asn1_oid_from_text(cbb.get(), t, strlen(t)));
}
for (const auto &t : kInvalidDER) {
SCOPED_TRACE(Bytes(t));
CBS cbs;
CBS_init(&cbs, t.data(), t.size());
bssl::UniquePtr<char> text(CBS_asn1_oid_to_text(&cbs));
EXPECT_FALSE(text);
}
}
TEST(CBBTest, FlushASN1SetOf) {
const struct {
std::vector<uint8_t> in, out;
} kValidInputs[] = {
// No elements.
{{}, {}},
// One element.
{{0x30, 0x00}, {0x30, 0x00}},
// Two identical elements.
{{0x30, 0x00, 0x30, 0x00}, {0x30, 0x00, 0x30, 0x00}},
// clang-format off
{{0x30, 0x02, 0x00, 0x00,
0x30, 0x00,
0x01, 0x00,
0x30, 0x02, 0x00, 0x00,
0x30, 0x03, 0x00, 0x00, 0x00,
0x30, 0x00,
0x30, 0x03, 0x00, 0x00, 0x01,
0x30, 0x01, 0x00,
0x01, 0x01, 0x00},
{0x01, 0x00,
0x01, 0x01, 0x00,
0x30, 0x00,
0x30, 0x00,
0x30, 0x01, 0x00,
0x30, 0x02, 0x00, 0x00,
0x30, 0x02, 0x00, 0x00,
0x30, 0x03, 0x00, 0x00, 0x00,
0x30, 0x03, 0x00, 0x00, 0x01}},
// clang-format on
};
for (const auto &t : kValidInputs) {
SCOPED_TRACE(Bytes(t.in));
bssl::ScopedCBB cbb;
CBB child;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &child, CBS_ASN1_SET));
ASSERT_TRUE(CBB_add_bytes(&child, t.in.data(), t.in.size()));
ASSERT_TRUE(CBB_flush_asn1_set_of(&child));
EXPECT_EQ(Bytes(t.out), Bytes(CBB_data(&child), CBB_len(&child)));
// Running it again should be idempotent.
ASSERT_TRUE(CBB_flush_asn1_set_of(&child));
EXPECT_EQ(Bytes(t.out), Bytes(CBB_data(&child), CBB_len(&child)));
// The ASN.1 header remain intact.
ASSERT_TRUE(CBB_flush(cbb.get()));
EXPECT_EQ(0x31, CBB_data(cbb.get())[0]);
}
const std::vector<uint8_t> kInvalidInputs[] = {
{0x30},
{0x30, 0x01},
{0x30, 0x00, 0x30, 0x00, 0x30, 0x01},
};
for (const auto &t : kInvalidInputs) {
SCOPED_TRACE(Bytes(t));
bssl::ScopedCBB cbb;
CBB child;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
ASSERT_TRUE(CBB_add_asn1(cbb.get(), &child, CBS_ASN1_SET));
ASSERT_TRUE(CBB_add_bytes(&child, t.data(), t.size()));
EXPECT_FALSE(CBB_flush_asn1_set_of(&child));
}
}
+8 -201
View File
@@ -15,10 +15,8 @@
#include <openssl/bytestring.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/mem.h>
#include "../internal.h"
@@ -330,47 +328,18 @@ int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
return cbb_add_length_prefixed(cbb, out_contents, 3);
}
// add_base128_integer encodes |v| as a big-endian base-128 integer where the
// high bit of each byte indicates where there is more data. This is the
// encoding used in DER for both high tag number form and OID components.
static int add_base128_integer(CBB *cbb, uint64_t v) {
unsigned len_len = 0;
uint64_t copy = v;
while (copy > 0) {
len_len++;
copy >>= 7;
}
if (len_len == 0) {
len_len = 1; // Zero is encoded with one byte.
}
for (unsigned i = len_len - 1; i < len_len; i--) {
uint8_t byte = (v >> (7 * i)) & 0x7f;
if (i != 0) {
// The high bit denotes whether there is more data.
byte |= 0x80;
}
if (!CBB_add_u8(cbb, byte)) {
return 0;
}
}
return 1;
}
int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
if (!CBB_flush(cbb)) {
if (tag > 0xff ||
(tag & 0x1f) == 0x1f) {
// Long form identifier octets are not supported. Further, all current valid
// tag serializations are 8 bits.
cbb->base->error = 1;
return 0;
}
// Split the tag into leading bits and tag number.
uint8_t tag_bits = (tag >> CBS_ASN1_TAG_SHIFT) & 0xe0;
unsigned tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
if (tag_number >= 0x1f) {
// Set all the bits in the tag number to signal high tag number form.
if (!CBB_add_u8(cbb, tag_bits | 0x1f) ||
!add_base128_integer(cbb, tag_number)) {
return 0;
}
} else if (!CBB_add_u8(cbb, tag_bits | tag_number)) {
if (!CBB_flush(cbb) ||
// |tag|'s representation matches the DER encoding.
!CBB_add_u8(cbb, (uint8_t)tag)) {
return 0;
}
@@ -504,165 +473,3 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
return CBB_flush(cbb);
}
int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child, data, data_len) ||
!CBB_flush(cbb)) {
return 0;
}
return 1;
}
int CBB_add_asn1_bool(CBB *cbb, int value) {
CBB child;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_BOOLEAN) ||
!CBB_add_u8(&child, value != 0 ? 0xff : 0) ||
!CBB_flush(cbb)) {
return 0;
}
return 1;
}
// parse_dotted_decimal parses one decimal component from |cbs|, where |cbs| is
// an OID literal, e.g., "1.2.840.113554.4.1.72585". It consumes both the
// component and the dot, so |cbs| may be passed into the function again for the
// next value.
static int parse_dotted_decimal(CBS *cbs, uint64_t *out) {
*out = 0;
int seen_digit = 0;
for (;;) {
// Valid terminators for a component are the end of the string or a
// non-terminal dot. If the string ends with a dot, this is not a valid OID
// string.
uint8_t u;
if (!CBS_get_u8(cbs, &u) ||
(u == '.' && CBS_len(cbs) > 0)) {
break;
}
if (u < '0' || u > '9' ||
// Forbid stray leading zeros.
(seen_digit && *out == 0) ||
// Check for overflow.
*out > UINT64_MAX / 10 ||
*out * 10 > UINT64_MAX - (u - '0')) {
return 0;
}
*out = *out * 10 + (u - '0');
seen_digit = 1;
}
// The empty string is not a legal OID component.
return seen_digit;
}
int CBB_add_asn1_oid_from_text(CBB *cbb, const char *text, size_t len) {
if (!CBB_flush(cbb)) {
return 0;
}
CBS cbs;
CBS_init(&cbs, (const uint8_t *)text, len);
// OIDs must have at least two components.
uint64_t a, b;
if (!parse_dotted_decimal(&cbs, &a) ||
!parse_dotted_decimal(&cbs, &b)) {
return 0;
}
// The first component is encoded as 40 * |a| + |b|. This assumes that |a| is
// 0, 1, or 2 and that, when it is 0 or 1, |b| is at most 39.
if (a > 2 ||
(a < 2 && b > 39) ||
b > UINT64_MAX - 80 ||
!add_base128_integer(cbb, 40u * a + b)) {
return 0;
}
// The remaining components are encoded unmodified.
while (CBS_len(&cbs) > 0) {
if (!parse_dotted_decimal(&cbs, &a) ||
!add_base128_integer(cbb, a)) {
return 0;
}
}
return 1;
}
static int compare_set_of_element(const void *a_ptr, const void *b_ptr) {
// See X.690, section 11.6 for the ordering. They are sorted in ascending
// order by their DER encoding.
const CBS *a = a_ptr, *b = b_ptr;
size_t a_len = CBS_len(a), b_len = CBS_len(b);
size_t min_len = a_len < b_len ? a_len : b_len;
int ret = OPENSSL_memcmp(CBS_data(a), CBS_data(b), min_len);
if (ret != 0) {
return ret;
}
if (a_len == b_len) {
return 0;
}
// If one is a prefix of the other, the shorter one sorts first. (This is not
// actually reachable. No DER encoding is a prefix of another DER encoding.)
return a_len < b_len ? -1 : 1;
}
int CBB_flush_asn1_set_of(CBB *cbb) {
if (!CBB_flush(cbb)) {
return 0;
}
CBS cbs;
size_t num_children = 0;
CBS_init(&cbs, CBB_data(cbb), CBB_len(cbb));
while (CBS_len(&cbs) != 0) {
if (!CBS_get_any_asn1_element(&cbs, NULL, NULL, NULL)) {
return 0;
}
num_children++;
}
if (num_children < 2) {
return 1; // Nothing to do. This is the common case for X.509.
}
if (num_children > ((size_t)-1) / sizeof(CBS)) {
return 0; // Overflow.
}
// Parse out the children and sort. We alias them into a copy of so they
// remain valid as we rewrite |cbb|.
int ret = 0;
size_t buf_len = CBB_len(cbb);
uint8_t *buf = BUF_memdup(CBB_data(cbb), buf_len);
CBS *children = OPENSSL_malloc(num_children * sizeof(CBS));
if (buf == NULL || children == NULL) {
goto err;
}
CBS_init(&cbs, buf, buf_len);
for (size_t i = 0; i < num_children; i++) {
if (!CBS_get_any_asn1_element(&cbs, &children[i], NULL, NULL)) {
goto err;
}
}
qsort(children, num_children, sizeof(CBS), compare_set_of_element);
// Rewind |cbb| and write the contents back in the new order.
cbb->base->len = cbb->offset + cbb->pending_len_len;
for (size_t i = 0; i < num_children; i++) {
if (!CBB_add_bytes(cbb, CBS_data(&children[i]), CBS_len(&children[i]))) {
goto err;
}
}
assert(CBB_len(cbb) == buf_len);
ret = 1;
err:
OPENSSL_free(buf);
OPENSSL_free(children);
return ret;
}
+20 -150
View File
@@ -12,16 +12,11 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#if !defined(__STDC_FORMAT_MACROS)
#define __STDC_FORMAT_MACROS
#endif
#include <openssl/buf.h>
#include <openssl/mem.h>
#include <openssl/bytestring.h>
#include <assert.h>
#include <inttypes.h>
#include <string.h>
#include "internal.h"
@@ -180,36 +175,18 @@ int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
return cbs_get_length_prefixed(cbs, out, 3);
}
// parse_base128_integer reads a big-endian base-128 integer from |cbs| and sets
// |*out| to the result. This is the encoding used in DER for both high tag
// number form and OID components.
static int parse_base128_integer(CBS *cbs, uint64_t *out) {
uint64_t v = 0;
uint8_t b;
do {
if (!CBS_get_u8(cbs, &b)) {
return 0;
}
if ((v >> (64 - 7)) != 0) {
// The value is too large.
return 0;
}
if (v == 0 && b == 0x80) {
// The value must be minimally encoded.
return 0;
}
v = (v << 7) | (b & 0x7f);
static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
size_t *out_header_len, int ber_ok) {
uint8_t tag, length_byte;
CBS header = *cbs;
CBS throwaway;
// Values end at an octet with the high bit cleared.
} while (b & 0x80);
if (out == NULL) {
out = &throwaway;
}
*out = v;
return 1;
}
static int parse_asn1_tag(CBS *cbs, unsigned *out) {
uint8_t tag_byte;
if (!CBS_get_u8(cbs, &tag_byte)) {
if (!CBS_get_u8(&header, &tag) ||
!CBS_get_u8(&header, &length_byte)) {
return 0;
}
@@ -220,58 +197,22 @@ static int parse_asn1_tag(CBS *cbs, unsigned *out) {
// allotted bits), then the tag is more than one byte long and the
// continuation bytes contain the tag number. This parser only supports tag
// numbers less than 31 (and thus single-byte tags).
unsigned tag = ((unsigned)tag_byte & 0xe0) << CBS_ASN1_TAG_SHIFT;
unsigned tag_number = tag_byte & 0x1f;
if (tag_number == 0x1f) {
uint64_t v;
if (!parse_base128_integer(cbs, &v) ||
// Check the tag number is within our supported bounds.
v > CBS_ASN1_TAG_NUMBER_MASK ||
// Small tag numbers should have used low tag number form.
v < 0x1f) {
return 0;
}
tag_number = (unsigned)v;
}
tag |= tag_number;
*out = tag;
return 1;
}
static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
size_t *out_header_len, int ber_ok) {
CBS header = *cbs;
CBS throwaway;
if (out == NULL) {
out = &throwaway;
}
unsigned tag;
if (!parse_asn1_tag(&header, &tag)) {
if ((tag & 0x1f) == 0x1f) {
return 0;
}
if (out_tag != NULL) {
*out_tag = tag;
}
uint8_t length_byte;
if (!CBS_get_u8(&header, &length_byte)) {
return 0;
}
size_t header_len = CBS_len(cbs) - CBS_len(&header);
size_t len;
// The format for the length encoding is specified in ITU-T X.690 section
// 8.1.3.
if ((length_byte & 0x80) == 0) {
// Short form length.
len = ((size_t) length_byte) + header_len;
len = ((size_t) length_byte) + 2;
if (out_header_len != NULL) {
*out_header_len = header_len;
*out_header_len = 2;
}
} else {
// The high bit indicate that this is the long form, while the next 7 bits
@@ -283,9 +224,9 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
// indefinite length
if (out_header_len != NULL) {
*out_header_len = header_len;
*out_header_len = 2;
}
return CBS_get_bytes(cbs, out, header_len);
return CBS_get_bytes(cbs, out, 2);
}
// ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
@@ -308,13 +249,13 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return 0;
}
len = len32;
if (len + header_len + num_bytes < len) {
if (len + 2 + num_bytes < len) {
// Overflow.
return 0;
}
len += header_len + num_bytes;
len += 2 + num_bytes;
if (out_header_len != NULL) {
*out_header_len = header_len + num_bytes;
*out_header_len = 2 + num_bytes;
}
}
@@ -382,10 +323,7 @@ int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
if (CBS_len(cbs) < 1) {
return 0;
}
CBS copy = *cbs;
unsigned actual_tag;
return parse_asn1_tag(&copy, &actual_tag) && tag_value == actual_tag;
return CBS_data(cbs)[0] == tag_value;
}
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
@@ -425,22 +363,6 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
return 1;
}
int CBS_get_asn1_bool(CBS *cbs, int *out) {
CBS bytes;
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
CBS_len(&bytes) != 1) {
return 0;
}
const uint8_t value = *CBS_data(&bytes);
if (value != 0 && value != 0xff) {
return 0;
}
*out = !!value;
return 1;
}
int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
int present = 0;
@@ -563,55 +485,3 @@ int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
return byte_num < CBS_len(cbs) &&
(CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
}
static int add_decimal(CBB *out, uint64_t v) {
char buf[DECIMAL_SIZE(uint64_t) + 1];
BIO_snprintf(buf, sizeof(buf), "%" PRIu64, v);
return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf));
}
char *CBS_asn1_oid_to_text(const CBS *cbs) {
CBB cbb;
if (!CBB_init(&cbb, 32)) {
goto err;
}
CBS copy = *cbs;
// The first component is 40 * value1 + value2, where value1 is 0, 1, or 2.
uint64_t v;
if (!parse_base128_integer(&copy, &v)) {
goto err;
}
if (v >= 80) {
if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) ||
!add_decimal(&cbb, v - 80)) {
goto err;
}
} else if (!add_decimal(&cbb, v / 40) ||
!CBB_add_u8(&cbb, '.') ||
!add_decimal(&cbb, v % 40)) {
goto err;
}
while (CBS_len(&copy) != 0) {
if (!parse_base128_integer(&copy, &v) ||
!CBB_add_u8(&cbb, '.') ||
!add_decimal(&cbb, v)) {
goto err;
}
}
uint8_t *txt;
size_t txt_len;
if (!CBB_add_u8(&cbb, '\0') ||
!CBB_finish(&cbb, &txt, &txt_len)) {
goto err;
}
return (char *)txt;
err:
CBB_cleanup(&cbb);
return NULL;
}
-4
View File
@@ -171,10 +171,6 @@ my @ret;
$code.=<<___;
#include <openssl/arm_arch.h>
@ Silence ARMv8 deprecated IT instruction warnings. This file is used by both
@ ARMv7 and ARMv8 processors and does not use ARMv8 instructions.
.arch armv7-a
.text
#if defined(__thumb2__) || defined(__clang__)
.syntax unified
-1
View File
@@ -28,7 +28,6 @@
# Denver 4.50/+82% 2.63 2.67(*)
# X-Gene 9.50/+46% 8.82 8.89(*)
# Mongoose 8.00/+44% 3.64 3.25
# Kryo 8.17/+50% 4.83 4.65
#
# (*) it's expected that doubling interleave factor doesn't help
# all processors, only those with higher NEON latency and
+1 -8
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
-1
View File
@@ -22,7 +22,6 @@ add_library(
e_rc4.c
e_aesgcmsiv.c
e_aesctrhmac.c
e_aesccm.c
e_chacha20poly1305.c
tls_cbc.c
-38
View File
@@ -93,8 +93,6 @@ static const struct KnownAEAD kAEADs[] = {
"aes_128_ctr_hmac_sha256.txt", false, true, 0},
{"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
"aes_256_ctr_hmac_sha256.txt", false, true, 0},
{"AES_128_CCM_BLUETOOTH", EVP_aead_aes_128_ccm_bluetooth,
"aes_128_ccm_bluetooth_tests.txt", false, false, 0},
};
class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
@@ -653,39 +651,3 @@ TEST(AEADTest, AESGCMEmptyNonce) {
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
}
TEST(AEADTest, AESCCMLargeAD) {
static const std::vector<uint8_t> kKey(16, 'A');
static const std::vector<uint8_t> kNonce(13, 'N');
static const std::vector<uint8_t> kAD(65536, 'D');
static const std::vector<uint8_t> kPlaintext = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
static const std::vector<uint8_t> kCiphertext = {
0xa2, 0x12, 0x3f, 0x0b, 0x07, 0xd5, 0x02, 0xff,
0xa9, 0xcd, 0xa0, 0xf3, 0x69, 0x1c, 0x49, 0x0c};
static const std::vector<uint8_t> kTag = {0x4a, 0x31, 0x82, 0x96};
// Test AES-128-CCM-Bluetooth.
bssl::ScopedEVP_AEAD_CTX ctx;
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_ccm_bluetooth(),
kKey.data(), kKey.size(),
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
std::vector<uint8_t> out(kCiphertext.size() + kTag.size());
size_t out_len;
EXPECT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
kNonce.data(), kNonce.size(), kPlaintext.data(),
kPlaintext.size(), kAD.data(), kAD.size()));
ASSERT_EQ(out_len, kCiphertext.size() + kTag.size());
EXPECT_EQ(Bytes(kCiphertext), Bytes(out.data(), kCiphertext.size()));
EXPECT_EQ(Bytes(kTag), Bytes(out.data() + kCiphertext.size(), kTag.size()));
EXPECT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
kNonce.data(), kNonce.size(), out.data(),
out.size(), kAD.data(), kAD.size()));
ASSERT_EQ(out_len, kPlaintext.size());
EXPECT_EQ(Bytes(kPlaintext), Bytes(out.data(), kPlaintext.size()));
}
-171
View File
@@ -1,171 +0,0 @@
/* Copyright (c) 2018, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/aead.h>
#include <assert.h>
#include <openssl/cipher.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "../fipsmodule/cipher/internal.h"
#define EVP_AEAD_AES_CCM_BLUETOOTH_TAG_LEN 4
#define EVP_AEAD_AES_CCM_BLUETOOTH_NONCE_LEN 13
#define EVP_AEAD_AES_CCM_MAX_TAG_LEN 16
struct aead_aes_ccm_ctx {
union {
double align;
AES_KEY ks;
} ks;
CCM128_CONTEXT ccm;
};
static int aead_aes_ccm_bluetooth_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
if (key_len != 16) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
return 0; // EVP_AEAD_CTX_init should catch this.
}
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
tag_len = EVP_AEAD_AES_CCM_BLUETOOTH_TAG_LEN;
}
if (tag_len != EVP_AEAD_AES_CCM_BLUETOOTH_TAG_LEN) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
return 0;
}
struct aead_aes_ccm_ctx *ccm_ctx =
OPENSSL_malloc(sizeof(struct aead_aes_ccm_ctx));
if (ccm_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
return 0;
}
block128_f block;
ctr128_f ctr = aes_ctr_set_key(&ccm_ctx->ks.ks, NULL, &block, key, key_len);
ctx->tag_len = tag_len;
if (!CRYPTO_ccm128_init(&ccm_ctx->ccm, &ccm_ctx->ks.ks, block, ctr, tag_len,
15 - EVP_AEAD_AES_CCM_BLUETOOTH_NONCE_LEN)) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_INTERNAL_ERROR);
OPENSSL_free(ccm_ctx);
return 0;
}
ctx->aead_state = ccm_ctx;
return 1;
}
static void aead_aes_ccm_cleanup(EVP_AEAD_CTX *ctx) {
OPENSSL_free(ctx->aead_state);
}
static int aead_aes_ccm_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ccm_ctx *ccm_ctx = ctx->aead_state;
if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (max_out_tag_len < ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (!CRYPTO_ccm128_encrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, out_tag,
ctx->tag_len, nonce, nonce_len, in, in_len, ad,
ad_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
*out_tag_len = ctx->tag_len;
return 1;
}
static int aead_aes_ccm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *in_tag, size_t in_tag_len,
const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ccm_ctx *ccm_ctx = ctx->aead_state;
if (in_len > CRYPTO_ccm128_max_input(&ccm_ctx->ccm)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (in_tag_len != ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
uint8_t tag[EVP_AEAD_AES_CCM_MAX_TAG_LEN];
assert(ctx->tag_len <= EVP_AEAD_AES_CCM_MAX_TAG_LEN);
if (!CRYPTO_ccm128_decrypt(&ccm_ctx->ccm, &ccm_ctx->ks.ks, out, tag,
ctx->tag_len, nonce, nonce_len, in, in_len, ad,
ad_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0;
}
if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
return 1;
}
static const EVP_AEAD aead_aes_128_ccm_bluetooth = {
16,
EVP_AEAD_AES_CCM_BLUETOOTH_NONCE_LEN, // nonce length
EVP_AEAD_AES_CCM_BLUETOOTH_TAG_LEN, // overhead
EVP_AEAD_AES_CCM_BLUETOOTH_TAG_LEN, // max tag length
0, // seal_scatter_supports_extra_in
aead_aes_ccm_bluetooth_init,
NULL /* init_with_direction */,
aead_aes_ccm_cleanup,
NULL /* open */,
aead_aes_ccm_seal_scatter,
aead_aes_ccm_open_gather,
NULL /* get_iv */,
NULL /* tag_len */,
};
const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth(void) {
return &aead_aes_128_ccm_bluetooth;
}
-2
View File
@@ -57,8 +57,6 @@
#include <openssl/cipher.h>
#include <openssl/nid.h>
#include "../internal.h"
#define c2l(c, l) \
do { \
+2 -1
View File
@@ -191,7 +191,8 @@ static int aead_tls_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
// block from encrypting the input and split the result between |out| and
// |out_tag|. Then feed the rest.
const size_t early_mac_len = (block_size - (in_len % block_size)) % block_size;
const size_t early_mac_len =
(block_size - (in_len % block_size) % block_size);
if (early_mac_len != 0) {
assert(len + block_size - early_mac_len == in_len);
uint8_t buf[EVP_MAX_BLOCK_LENGTH];
@@ -1,20 +0,0 @@
KEY: 404142434445464748494a4b4c4d4e4f
NONCE: 101112131415161718191a1b1c
IN: 20212223
AD: 0001020304050607
CT: 69915dad
TAG: 064617ca
KEY: 404142434445464748494a4b4c4d4e4f
NONCE: 101112131415161718191a1b1c
IN: 202122232425262728292a2b2c2d2e2f
AD: 0001020304050607
CT: 69915dad1e84c6376a68c2967e4dab61
TAG: 99763ebb
KEY: 404142434445464748494a4b4c4d4e4f
NONCE: 101112131415161718191a1b1c
IN: 202122232425262728292a2b2c2d2e2f
AD:
CT: 69915dad1e84c6376a68c2967e4dab61
TAG: c4630026
+2 -2
View File
@@ -791,13 +791,13 @@ int CONF_parse_list(const char *list, char sep, int remove_whitespace,
}
}
int CONF_modules_load_file(const char *filename, const char *appname,
int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, const char *appname,
unsigned long flags) {
return 1;
}
void CONF_modules_free(void) {}
void OPENSSL_config(const char *config_name) {}
void OPENSSL_config(CONF_MUST_BE_NULL *config_name) {}
void OPENSSL_no_config(void) {}
-55
View File
@@ -1,55 +0,0 @@
/* Copyright (c) 2018, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/cpu.h>
#if defined(OPENSSL_AARCH64) && defined(OPENSSL_FUCHSIA) && \
!defined(OPENSSL_STATIC_ARMCAP)
#include <zircon/features.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <openssl/arm_arch.h>
#include "internal.h"
extern uint32_t OPENSSL_armcap_P;
void OPENSSL_cpuid_setup(void) {
uint32_t hwcap;
zx_status_t rc = zx_system_get_features(ZX_FEATURE_KIND_CPU, &hwcap);
if (rc != ZX_OK || (hwcap & ZX_ARM64_FEATURE_ISA_ASIMD) == 0) {
// Matching OpenSSL, if NEON/ASIMD is missing, don't report other features
// either.
return;
}
OPENSSL_armcap_P |= ARMV7_NEON;
if (hwcap & ZX_ARM64_FEATURE_ISA_AES) {
OPENSSL_armcap_P |= ARMV8_AES;
}
if (hwcap & ZX_ARM64_FEATURE_ISA_PMULL) {
OPENSSL_armcap_P |= ARMV8_PMULL;
}
if (hwcap & ZX_ARM64_FEATURE_ISA_SHA1) {
OPENSSL_armcap_P |= ARMV8_SHA1;
}
if (hwcap & ZX_ARM64_FEATURE_ISA_SHA2) {
OPENSSL_armcap_P |= ARMV8_SHA256;
}
}
#endif // OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP
+1 -2
View File
@@ -14,8 +14,7 @@
#include <openssl/cpu.h>
#if defined(OPENSSL_AARCH64) && defined(OPENSSL_LINUX) && \
!defined(OPENSSL_STATIC_ARMCAP)
#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP)
#include <sys/auxv.h>
+17 -17
View File
@@ -164,7 +164,7 @@ void OPENSSL_cpuid_setup(void) {
uint32_t num_extended_ids = eax;
if (num_extended_ids >= 0x80000001) {
OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0x80000001);
if (ecx & (1u << 11)) {
if (ecx & (1 << 11)) {
has_amd_xop = 1;
}
}
@@ -193,68 +193,68 @@ void OPENSSL_cpuid_setup(void) {
OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 1);
// Adjust the hyper-threading bit.
if (edx & (1u << 28)) {
if (edx & (1 << 28)) {
uint32_t num_logical_cores = (ebx >> 16) & 0xff;
if (cores_per_cache == 1 || num_logical_cores <= 1) {
edx &= ~(1u << 28);
edx &= ~(1 << 28);
}
}
// Reserved bit #20 was historically repurposed to control the in-memory
// representation of RC4 state. Always set it to zero.
edx &= ~(1u << 20);
edx &= ~(1 << 20);
// Reserved bit #30 is repurposed to signal an Intel CPU.
if (is_intel) {
edx |= (1u << 30);
edx |= (1 << 30);
// Clear the XSAVE bit on Knights Landing to mimic Silvermont. This enables
// some Silvermont-specific codepaths which perform better. See OpenSSL
// commit 64d92d74985ebb3d0be58a9718f9e080a14a8e7f.
if ((eax & 0x0fff0ff0) == 0x00050670 /* Knights Landing */ ||
(eax & 0x0fff0ff0) == 0x00080650 /* Knights Mill (per SDE) */) {
ecx &= ~(1u << 26);
ecx &= ~(1 << 26);
}
} else {
edx &= ~(1u << 30);
edx &= ~(1 << 30);
}
// The SDBG bit is repurposed to denote AMD XOP support.
if (has_amd_xop) {
ecx |= (1u << 11);
ecx |= (1 << 11);
} else {
ecx &= ~(1u << 11);
ecx &= ~(1 << 11);
}
uint64_t xcr0 = 0;
if (ecx & (1u << 27)) {
if (ecx & (1 << 27)) {
// XCR0 may only be queried if the OSXSAVE bit is set.
xcr0 = OPENSSL_xgetbv(0);
}
// See Intel manual, volume 1, section 14.3.
if ((xcr0 & 6) != 6) {
// YMM registers cannot be used.
ecx &= ~(1u << 28); // AVX
ecx &= ~(1u << 12); // FMA
ecx &= ~(1u << 11); // AMD XOP
ecx &= ~(1 << 28); // AVX
ecx &= ~(1 << 12); // FMA
ecx &= ~(1 << 11); // AMD XOP
// Clear AVX2 and AVX512* bits.
//
// TODO(davidben): Should bits 17 and 26-28 also be cleared? Upstream
// doesn't clear those.
extended_features &=
~((1u << 5) | (1u << 16) | (1u << 21) | (1u << 30) | (1u << 31));
~((1 << 5) | (1 << 16) | (1 << 21) | (1 << 30) | (1 << 31));
}
// See Intel manual, volume 1, section 15.2.
if ((xcr0 & 0xe6) != 0xe6) {
// Clear AVX512F. Note we don't touch other AVX512 extensions because they
// can be used with YMM.
extended_features &= ~(1u << 16);
extended_features &= ~(1 << 16);
}
// Disable ADX instructions on Knights Landing. See OpenSSL commit
// 64d92d74985ebb3d0be58a9718f9e080a14a8e7f.
if ((ecx & (1u << 26)) == 0) {
extended_features &= ~(1u << 19);
if ((ecx & (1 << 26)) == 0) {
extended_features &= ~(1 << 19);
}
OPENSSL_ia32cap_P[0] = edx;
+4 -16
View File
@@ -40,18 +40,6 @@
OPENSSL_ARM || OPENSSL_AARCH64) */
// Our assembly does not use the GOT to reference symbols, which means
// references to visible symbols will often require a TEXTREL. This is
// undesirable, so all assembly-referenced symbols should be hidden. CPU
// capabilities are the only such symbols defined in C. Explicitly hide them,
// rather than rely on being built with -fvisibility=hidden.
#if defined(OPENSSL_WINDOWS)
#define HIDDEN
#else
#define HIDDEN __attribute__((visibility("hidden")))
#endif
// The capability variables are defined in this file in order to work around a
// linker bug. When linking with a .a, if no symbols in a .o are referenced
// then the .o is discarded, even if it has constructor functions.
@@ -69,11 +57,11 @@
// archive, linking on OS X will fail to resolve common symbols. By
// initialising it to zero, it becomes a "data symbol", which isn't so
// affected.
HIDDEN uint32_t OPENSSL_ia32cap_P[4] = {0};
uint32_t OPENSSL_ia32cap_P[4] = {0};
#elif defined(OPENSSL_PPC64LE)
HIDDEN unsigned long OPENSSL_ppc64le_hwcap2 = 0;
unsigned long OPENSSL_ppc64le_hwcap2 = 0;
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
@@ -81,7 +69,7 @@ HIDDEN unsigned long OPENSSL_ppc64le_hwcap2 = 0;
#if defined(OPENSSL_STATIC_ARMCAP)
HIDDEN uint32_t OPENSSL_armcap_P =
uint32_t OPENSSL_armcap_P =
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
ARMV7_NEON |
#endif
@@ -100,7 +88,7 @@ HIDDEN uint32_t OPENSSL_armcap_P =
0;
#else
HIDDEN uint32_t OPENSSL_armcap_P = 0;
uint32_t OPENSSL_armcap_P = 0;
#endif
#endif
+10
View File
@@ -8,12 +8,22 @@ if (${ARCH} STREQUAL "arm")
)
endif()
if (${ARCH} STREQUAL "x86_64")
set(
CURVE25519_ARCH_SOURCES
asm/x25519-asm-x86_64.S
)
endif()
add_library(
curve25519
OBJECT
curve25519.c
spake25519.c
x25519-x86_64.c
${CURVE25519_ARCH_SOURCES}
)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-22
View File
@@ -44,28 +44,6 @@ TEST(Ed25519Test, TestVectors) {
});
}
TEST(Ed25519Test, Malleability) {
// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
// that s be in [0, order). This prevents someone from adding a multiple of
// order to s and obtaining a second valid signature for the same message.
static const uint8_t kMsg[] = {0x54, 0x65, 0x73, 0x74};
static const uint8_t kSig[] = {
0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
};
static const uint8_t kPub[] = {
0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
};
EXPECT_FALSE(ED25519_verify(kMsg, sizeof(kMsg), kSig, kPub));
}
TEST(Ed25519Test, KeypairFromSeed) {
uint8_t public_key1[32], private_key1[64];
ED25519_keypair(public_key1, private_key1);
+129
View File
@@ -0,0 +1,129 @@
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#ifndef OPENSSL_HEADER_CURVE25519_INTERNAL_H
#define OPENSSL_HEADER_CURVE25519_INTERNAL_H
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \
!defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM)
#define BORINGSSL_X25519_X86_64
void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]);
#endif
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_APPLE)
#define BORINGSSL_X25519_NEON
// x25519_NEON is defined in asm/x25519-arm.S.
void x25519_NEON(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]);
#endif
// fe means field element. Here the field is \Z/(2^255-19). An element t,
// entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
// context.
typedef int32_t fe[10];
/* ge means group element.
* Here the group is the set of pairs (x,y) of field elements (see fe.h)
* satisfying -x^2 + y^2 = 1 + d x^2y^2
* where d = -121665/121666.
*
* Representations:
* ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
* ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
* ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
* ge_precomp (Duif): (y+x,y-x,2dxy) */
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h);
int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s);
void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void x25519_ge_scalarmult_small_precomp(
ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]);
void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]);
void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A);
void x25519_sc_reduce(uint8_t *s);
enum spake2_state_t {
spake2_state_init = 0,
spake2_state_msg_generated,
spake2_state_key_generated,
};
struct spake2_ctx_st {
uint8_t private_key[32];
uint8_t my_msg[32];
uint8_t password_scalar[32];
uint8_t password_hash[64];
uint8_t *my_name;
size_t my_name_len;
uint8_t *their_name;
size_t their_name_len;
enum spake2_role_t my_role;
enum spake2_state_t state;
char disable_password_scalar_hack;
};
#if defined(__cplusplus)
} // extern C
#endif
#endif // OPENSSL_HEADER_CURVE25519_INTERNAL_H
+11 -11
View File
@@ -22,8 +22,8 @@
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "internal.h"
#include "../internal.h"
#include "../../third_party/fiat/internal.h"
// The following precomputation tables are for the following
@@ -44,14 +44,14 @@
// see curve25519.c in this directory.
//
// Exact copies of the source code are kept in bug 27296743.
//
// import hashlib
// import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py
//
// SEED_N = 'edwards25519 point generation seed (N)'
// SEED_M = 'edwards25519 point generation seed (M)'
/*
import hashlib
import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py
SEED_N = 'edwards25519 point generation seed (N)'
SEED_M = 'edwards25519 point generation seed (M)'
def genpoint(seed):
v = hashlib.sha256(seed).digest()
it = 1
@@ -73,10 +73,10 @@ def genpoint(seed):
def gentable(P):
t = []
for i in range(1,16):
k = ((i >> 3 & 1) * (1 << 192) +
(i >> 2 & 1) * (1 << 128) +
(i >> 1 & 1) * (1 << 64) +
(i & 1))
k = (i >> 3 & 1) * (1 << 192) + \
(i >> 2 & 1) * (1 << 128) + \
(i >> 1 & 1) * (1 << 64) + \
(i & 1)
t.append(E.scalarmult(P, k))
return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)
+1 -1
View File
@@ -23,7 +23,7 @@
#include <gtest/gtest.h>
#include "../internal.h"
#include "../../third_party/fiat/internal.h"
#include "internal.h"
// TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down.
+247
View File
@@ -0,0 +1,247 @@
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
// This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
// 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
// public domain but this file has the ISC license just to keep licencing
// simple.
//
// The field functions are shared by Ed25519 and X25519 where possible.
#include <openssl/curve25519.h>
#include <string.h>
#include "../internal.h"
#include "internal.h"
#if defined(BORINGSSL_X25519_X86_64)
typedef struct { uint64_t v[5]; } fe25519;
// These functions are defined in asm/x25519-x86_64.S
void x25519_x86_64_work_cswap(fe25519 *, uint64_t);
void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b);
void x25519_x86_64_square(fe25519 *out, const fe25519 *a);
void x25519_x86_64_freeze(fe25519 *);
void x25519_x86_64_ladderstep(fe25519 *work);
static void fe25519_setint(fe25519 *r, unsigned v) {
r->v[0] = v;
r->v[1] = 0;
r->v[2] = 0;
r->v[3] = 0;
r->v[4] = 0;
}
// Assumes input x being reduced below 2^255
static void fe25519_pack(unsigned char r[32], const fe25519 *x) {
fe25519 t;
t = *x;
x25519_x86_64_freeze(&t);
r[0] = (uint8_t)(t.v[0] & 0xff);
r[1] = (uint8_t)((t.v[0] >> 8) & 0xff);
r[2] = (uint8_t)((t.v[0] >> 16) & 0xff);
r[3] = (uint8_t)((t.v[0] >> 24) & 0xff);
r[4] = (uint8_t)((t.v[0] >> 32) & 0xff);
r[5] = (uint8_t)((t.v[0] >> 40) & 0xff);
r[6] = (uint8_t)((t.v[0] >> 48));
r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8);
r[7] = (uint8_t)((t.v[1] >> 5) & 0xff);
r[8] = (uint8_t)((t.v[1] >> 13) & 0xff);
r[9] = (uint8_t)((t.v[1] >> 21) & 0xff);
r[10] = (uint8_t)((t.v[1] >> 29) & 0xff);
r[11] = (uint8_t)((t.v[1] >> 37) & 0xff);
r[12] = (uint8_t)((t.v[1] >> 45));
r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0);
r[13] = (uint8_t)((t.v[2] >> 2) & 0xff);
r[14] = (uint8_t)((t.v[2] >> 10) & 0xff);
r[15] = (uint8_t)((t.v[2] >> 18) & 0xff);
r[16] = (uint8_t)((t.v[2] >> 26) & 0xff);
r[17] = (uint8_t)((t.v[2] >> 34) & 0xff);
r[18] = (uint8_t)((t.v[2] >> 42) & 0xff);
r[19] = (uint8_t)((t.v[2] >> 50));
r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe);
r[20] = (uint8_t)((t.v[3] >> 7) & 0xff);
r[21] = (uint8_t)((t.v[3] >> 15) & 0xff);
r[22] = (uint8_t)((t.v[3] >> 23) & 0xff);
r[23] = (uint8_t)((t.v[3] >> 31) & 0xff);
r[24] = (uint8_t)((t.v[3] >> 39) & 0xff);
r[25] = (uint8_t)((t.v[3] >> 47));
r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0);
r[26] = (uint8_t)((t.v[4] >> 4) & 0xff);
r[27] = (uint8_t)((t.v[4] >> 12) & 0xff);
r[28] = (uint8_t)((t.v[4] >> 20) & 0xff);
r[29] = (uint8_t)((t.v[4] >> 28) & 0xff);
r[30] = (uint8_t)((t.v[4] >> 36) & 0xff);
r[31] = (uint8_t)((t.v[4] >> 44));
}
static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) {
r->v[0] = x[0];
r->v[0] += (uint64_t)x[1] << 8;
r->v[0] += (uint64_t)x[2] << 16;
r->v[0] += (uint64_t)x[3] << 24;
r->v[0] += (uint64_t)x[4] << 32;
r->v[0] += (uint64_t)x[5] << 40;
r->v[0] += ((uint64_t)x[6] & 7) << 48;
r->v[1] = x[6] >> 3;
r->v[1] += (uint64_t)x[7] << 5;
r->v[1] += (uint64_t)x[8] << 13;
r->v[1] += (uint64_t)x[9] << 21;
r->v[1] += (uint64_t)x[10] << 29;
r->v[1] += (uint64_t)x[11] << 37;
r->v[1] += ((uint64_t)x[12] & 63) << 45;
r->v[2] = x[12] >> 6;
r->v[2] += (uint64_t)x[13] << 2;
r->v[2] += (uint64_t)x[14] << 10;
r->v[2] += (uint64_t)x[15] << 18;
r->v[2] += (uint64_t)x[16] << 26;
r->v[2] += (uint64_t)x[17] << 34;
r->v[2] += (uint64_t)x[18] << 42;
r->v[2] += ((uint64_t)x[19] & 1) << 50;
r->v[3] = x[19] >> 1;
r->v[3] += (uint64_t)x[20] << 7;
r->v[3] += (uint64_t)x[21] << 15;
r->v[3] += (uint64_t)x[22] << 23;
r->v[3] += (uint64_t)x[23] << 31;
r->v[3] += (uint64_t)x[24] << 39;
r->v[3] += ((uint64_t)x[25] & 15) << 47;
r->v[4] = x[25] >> 4;
r->v[4] += (uint64_t)x[26] << 4;
r->v[4] += (uint64_t)x[27] << 12;
r->v[4] += (uint64_t)x[28] << 20;
r->v[4] += (uint64_t)x[29] << 28;
r->v[4] += (uint64_t)x[30] << 36;
r->v[4] += ((uint64_t)x[31] & 127) << 44;
}
static void fe25519_invert(fe25519 *r, const fe25519 *x) {
fe25519 z2;
fe25519 z9;
fe25519 z11;
fe25519 z2_5_0;
fe25519 z2_10_0;
fe25519 z2_20_0;
fe25519 z2_50_0;
fe25519 z2_100_0;
fe25519 t;
int i;
/* 2 */ x25519_x86_64_square(&z2, x);
/* 4 */ x25519_x86_64_square(&t, &z2);
/* 8 */ x25519_x86_64_square(&t, &t);
/* 9 */ x25519_x86_64_mul(&z9, &t, x);
/* 11 */ x25519_x86_64_mul(&z11, &z9, &z2);
/* 22 */ x25519_x86_64_square(&t, &z11);
/* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9);
/* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0);
/* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); }
/* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0);
/* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0);
/* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
/* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0);
/* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0);
/* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); }
/* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0);
/* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t);
/* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
/* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0);
/* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0);
/* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
/* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0);
/* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0);
/* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
x25519_x86_64_square(&t, &t);
}
/* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0);
/* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t);
/* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
/* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0);
/* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t);
/* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t);
/* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t);
/* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t);
/* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t);
/* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11);
}
static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) {
fe25519 work[5];
work[0] = *xr;
fe25519_setint(work + 1, 1);
fe25519_setint(work + 2, 0);
work[3] = *xr;
fe25519_setint(work + 4, 1);
int i, j;
uint8_t prevbit = 0;
j = 6;
for (i = 31; i >= 0; i--) {
while (j >= 0) {
const uint8_t bit = 1 & (s[i] >> j);
const uint64_t swap = bit ^ prevbit;
prevbit = bit;
x25519_x86_64_work_cswap(work + 1, swap);
x25519_x86_64_ladderstep(work);
j -= 1;
}
j = 7;
}
*xr = work[1];
*zr = work[2];
}
void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]) {
uint8_t e[32];
OPENSSL_memcpy(e, scalar, sizeof(e));
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
fe25519 t;
fe25519 z;
fe25519_unpack(&t, point);
mladder(&t, &z, e);
fe25519_invert(&z, &z);
x25519_x86_64_mul(&t, &t, &z);
fe25519_pack(out, &t);
}
#endif // BORINGSSL_X25519_X86_64
-19
View File
@@ -105,22 +105,3 @@ TEST(X25519Test, Iterated) {
EXPECT_EQ(Bytes(kExpected), Bytes(scalar));
}
TEST(X25519Test, DISABLED_IteratedLarge) {
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2.
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
for (unsigned i = 0; i < 1000000; i++) {
EXPECT_TRUE(X25519(out, scalar, point));
OPENSSL_memcpy(point, scalar, sizeof(point));
OPENSSL_memcpy(scalar, out, sizeof(scalar));
}
static const uint8_t kExpected[32] = {
0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd, 0x86, 0x44, 0x97,
0x29, 0x7e, 0x57, 0x5e, 0x6f, 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c,
0x30, 0xdf, 0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24,
};
EXPECT_EQ(Bytes(kExpected), Bytes(scalar));
}
+75 -25
View File
@@ -82,9 +82,6 @@
// Rabin-Miller
#define DSS_prime_checks 50
static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
BIGNUM **out_r);
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
DSA *DSA_new(void) {
@@ -120,6 +117,8 @@ void DSA_free(DSA *dsa) {
BN_clear_free(dsa->g);
BN_clear_free(dsa->pub_key);
BN_clear_free(dsa->priv_key);
BN_clear_free(dsa->kinv);
BN_clear_free(dsa->r);
BN_MONT_CTX_free(dsa->method_mont_p);
BN_MONT_CTX_free(dsa->method_mont_q);
CRYPTO_MUTEX_cleanup(&dsa->method_mont_lock);
@@ -239,6 +238,11 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
}
BN_CTX_start(ctx);
mont = BN_MONT_CTX_new();
if (mont == NULL) {
goto err;
}
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
@@ -396,9 +400,8 @@ end:
goto err;
}
mont = BN_MONT_CTX_new_for_modulus(p, ctx);
if (mont == NULL ||
!BN_set_word(test, h)) {
if (!BN_set_word(test, h) ||
!BN_MONT_CTX_set(mont, p, ctx)) {
goto err;
}
@@ -541,13 +544,14 @@ void DSA_SIG_free(DSA_SIG *sig) {
OPENSSL_free(sig);
}
DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, const DSA *dsa) {
DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) {
BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
BIGNUM m;
BIGNUM xr;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int noredo = 0;
BN_init(&m);
BN_init(&xr);
@@ -567,8 +571,16 @@ DSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, const DSA *dsa) {
}
redo:
if (!dsa_sign_setup(dsa, ctx, &kinv, &r)) {
goto err;
if (dsa->kinv == NULL || dsa->r == NULL) {
if (!DSA_sign_setup(dsa, ctx, &kinv, &r)) {
goto err;
}
} else {
kinv = dsa->kinv;
dsa->kinv = NULL;
r = dsa->r;
dsa->r = NULL;
noredo = 1;
}
if (digest_len > BN_num_bytes(dsa->q)) {
@@ -601,6 +613,10 @@ redo:
// Redo if r or s is zero as required by FIPS 186-3: this is
// very unlikely.
if (BN_is_zero(r) || BN_is_zero(s)) {
if (noredo) {
reason = DSA_R_NEED_NEW_SETUP_VALUES;
goto err;
}
goto redo;
}
ret = DSA_SIG_new();
@@ -742,7 +758,7 @@ err:
}
int DSA_sign(int type, const uint8_t *digest, size_t digest_len,
uint8_t *out_sig, unsigned int *out_siglen, const DSA *dsa) {
uint8_t *out_sig, unsigned int *out_siglen, DSA *dsa) {
DSA_SIG *s;
s = DSA_do_sign(digest, digest_len, dsa);
@@ -832,10 +848,10 @@ int DSA_size(const DSA *dsa) {
return ret;
}
static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
BIGNUM **out_r) {
int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
BIGNUM **out_r) {
BN_CTX *ctx;
BIGNUM k, *kinv = NULL, *r = NULL;
BIGNUM k, kq, *kinv = NULL, *r = NULL;
int ret = 0;
if (!dsa->p || !dsa->q || !dsa->g) {
@@ -844,6 +860,7 @@ static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
}
BN_init(&k);
BN_init(&kq);
ctx = ctx_in;
if (ctx == NULL) {
@@ -854,22 +871,54 @@ static int dsa_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
}
r = BN_new();
kinv = BN_new();
if (r == NULL || kinv == NULL ||
// Get random k
!BN_rand_range_ex(&k, 1, dsa->q) ||
!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
if (r == NULL) {
goto err;
}
// Get random k
if (!BN_rand_range_ex(&k, 1, dsa->q)) {
goto err;
}
if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
(CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p,
ctx) ||
!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_q,
(CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->q,
ctx) ||
// Compute r = (g^k mod p) mod q
!BN_mod_exp_mont_consttime(r, dsa->g, &k, dsa->p, ctx,
dsa->method_mont_p) ||
!BN_mod(r, r, dsa->q, ctx) ||
// Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little
// Theorem.
ctx)) {
goto err;
}
// Compute r = (g^k mod p) mod q
if (!BN_copy(&kq, &k)) {
goto err;
}
// We do not want timing information to leak the length of k,
// so we compute g^k using an equivalent exponent of fixed length.
//
// (This is a kludge that we need because the BN_mod_exp_mont()
// does not let us specify the desired timing behaviour.)
if (!BN_add(&kq, &kq, dsa->q)) {
goto err;
}
if (BN_num_bits(&kq) <= BN_num_bits(dsa->q) && !BN_add(&kq, &kq, dsa->q)) {
goto err;
}
if (!BN_mod_exp_mont_consttime(r, dsa->g, &kq, dsa->p, ctx,
dsa->method_mont_p)) {
goto err;
}
if (!BN_mod(r, r, dsa->q, ctx)) {
goto err;
}
// Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little
// Theorem.
kinv = BN_new();
if (kinv == NULL ||
!bn_mod_inverse_prime(kinv, &k, dsa->q, ctx, dsa->method_mont_q)) {
goto err;
}
@@ -893,6 +942,7 @@ err:
BN_CTX_free(ctx);
}
BN_clear_free(&k);
BN_clear_free(&kq);
BN_clear_free(kinv);
return ret;
}
+2 -2
View File
@@ -67,9 +67,9 @@
#include "../internal.h"
static const unsigned kParametersTag =
static const uint8_t kParametersTag =
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0;
static const unsigned kPublicKeyTag =
static const uint8_t kPublicKeyTag =
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
-97
View File
@@ -14,7 +14,6 @@
#include <stdio.h>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
@@ -24,7 +23,6 @@
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/ecdh.h>
#include <openssl/err.h>
#include <openssl/nid.h>
#include "../test/file_test.h"
@@ -114,98 +112,3 @@ TEST(ECDHTest, TestVectors) {
Bytes(actual_z.data(), static_cast<size_t>(ret)));
});
}
// MakeCustomGroup returns an |EC_GROUP| containing a non-standard group. (P-256
// with the wrong generator.)
static bssl::UniquePtr<EC_GROUP> MakeCustomGroup() {
static const uint8_t kP[] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const uint8_t kA[] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
};
static const uint8_t kB[] = {
0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
};
static const uint8_t kX[] = {
0xe6, 0x2b, 0x69, 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e,
0x0d, 0x94, 0x8a, 0x4c, 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d,
0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, 0x9d, 0xdc, 0xba, 0x5a,
};
static const uint8_t kY[] = {
0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, 0xc3, 0xc4, 0xa3,
0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, 0x1c, 0xf5,
0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1,
};
static const uint8_t kOrder[] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
};
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
bssl::UniquePtr<BIGNUM> x(BN_bin2bn(kX, sizeof(kX), nullptr));
bssl::UniquePtr<BIGNUM> y(BN_bin2bn(kY, sizeof(kY), nullptr));
bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
if (!ctx || !p || !a || !b || !x || !y || !order) {
return nullptr;
}
bssl::UniquePtr<EC_GROUP> group(
EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
if (!group) {
return nullptr;
}
bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
if (!generator ||
!EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(),
x.get(), y.get(), ctx.get()) ||
!EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
BN_value_one())) {
return nullptr;
}
return group;
}
TEST(ECDHTest, GroupMismatch) {
const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
std::vector<EC_builtin_curve> curves(num_curves);
EC_get_builtin_curves(curves.data(), num_curves);
// Instantiate all the built-in curves.
std::vector<bssl::UniquePtr<EC_GROUP>> groups;
for (const auto &curve : curves) {
groups.emplace_back(EC_GROUP_new_by_curve_name(curve.nid));
ASSERT_TRUE(groups.back());
}
// Also create some arbitrary group. (This is P-256 with the wrong generator.)
groups.push_back(MakeCustomGroup());
ASSERT_TRUE(groups.back());
for (const auto &a : groups) {
for (const auto &b : groups) {
if (a.get() == b.get()) {
continue;
}
bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
ASSERT_TRUE(EC_KEY_set_group(key.get(), a.get()));
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
// ECDH across the groups should not work.
char out[64];
const EC_POINT *peer = EC_GROUP_get0_generator(b.get());
EXPECT_EQ(-1,
ECDH_compute_key(out, sizeof(out), peer, key.get(), nullptr));
ERR_clear_error();
}
}
}
+8 -1
View File
@@ -73,6 +73,13 @@ int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
(EC_KEY*) eckey /* cast away const */);
}
return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL,
eckey);
}
int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len,
uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv,
const BIGNUM *r, const EC_KEY *eckey) {
int ret = 0;
ECDSA_SIG *s = NULL;
@@ -82,7 +89,7 @@ int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
goto err;
}
s = ECDSA_do_sign(digest, digest_len, eckey);
s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey);
if (s == NULL) {
*sig_len = 0;
goto err;
-1
View File
@@ -17,7 +17,6 @@ EC,110,INVALID_FIELD
EC,111,INVALID_FORM
EC,112,INVALID_GROUP_ORDER
EC,113,INVALID_PRIVATE_KEY
EC,133,INVALID_SCALAR
EC,114,MISSING_PARAMETERS
EC,115,MISSING_PRIVATE_KEY
EC,116,NON_NAMED_CURVE
-1
View File
@@ -1,2 +1 @@
OBJ,101,INVALID_OID_STRING
OBJ,100,UNKNOWN_NID
-6
View File
@@ -52,9 +52,7 @@ SSL,254,DOWNGRADE_DETECTED
SSL,143,DTLS_MESSAGE_TOO_BIG
SSL,257,DUPLICATE_EXTENSION
SSL,264,DUPLICATE_KEY_SHARE
SSL,283,EARLY_DATA_NOT_IN_USE
SSL,144,ECC_CERT_NOT_FOR_SIGNING
SSL,282,EMPTY_HELLO_RETRY_REQUEST
SSL,145,EMS_STATE_INCONSISTENT
SSL,146,ENCRYPTED_LENGTH_TOO_LONG
SSL,147,ERROR_ADDING_EXTENSION
@@ -65,7 +63,6 @@ SSL,151,EXTRA_DATA_IN_MESSAGE
SSL,152,FRAGMENT_MISMATCH
SSL,153,GOT_NEXT_PROTO_WITHOUT_EXTENSION
SSL,154,HANDSHAKE_FAILURE_ON_CLIENT_HELLO
SSL,284,HANDSHAKE_NOT_COMPLETE
SSL,155,HTTPS_PROXY_REQUEST
SSL,156,HTTP_REQUEST
SSL,157,INAPPROPRIATE_FALLBACK
@@ -86,7 +83,6 @@ SSL,167,MISSING_TMP_ECDH_KEY
SSL,168,MIXED_SPECIAL_OPERATOR_WITH_GROUPS
SSL,169,MTU_TOO_SMALL
SSL,170,NEGOTIATED_BOTH_NPN_AND_ALPN
SSL,285,NEGOTIATED_TB_WITHOUT_EMS_OR_RI
SSL,171,NESTED_GROUP
SSL,172,NO_CERTIFICATES_RETURNED
SSL,173,NO_CERTIFICATE_ASSIGNED
@@ -117,7 +113,6 @@ SSL,191,PATH_TOO_LONG
SSL,192,PEER_DID_NOT_RETURN_A_CERTIFICATE
SSL,193,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
SSL,267,PRE_SHARED_KEY_MUST_BE_LAST
SSL,287,PRIVATE_KEY_OPERATION_FAILED
SSL,194,PROTOCOL_IS_SHUTDOWN
SSL,271,PSK_IDENTITY_BINDER_COUNT_MISMATCH
SSL,195,PSK_IDENTITY_NOT_FOUND
@@ -135,7 +130,6 @@ SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION
SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
SSL,207,SERVERHELLO_TLSEXT
SSL,273,SERVER_CERT_CHANGED
SSL,286,SERVER_ECHOED_INVALID_SESSION_ID
SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
SSL,209,SESSION_MAY_NOT_BE_CREATED
SSL,250,SHUTDOWN_WHILE_IN_INIT
-22
View File
@@ -545,28 +545,6 @@ OAEPLabel = 00112233445566778899aabbccddeeff
Input = "Hello World"
CheckDecrypt
# Though we will never generate such a key, test that RSA keys where p < q work
# properly.
PrivateKey = RSA-Swapped
Type = RSA
Input = 30820275020100300d06092a864886f70d01010105000482025f3082025b02010002818100ab28f98747934779011417d5bbb4095eae6f48ed09e13081616cf390aac75b10a206a98953d402647dfef7fa363be2765a303b05ec388bd9a1d75123a1205b4ecb43c33f2e37d3e30842181d694a3acfc39afc52554946e699d97d97066596a46725ce6dea322623afcafecbd2884d9a0c5eae9c4d7da8874c29c19edb762e1902030100010281800d637ea568e169f15ab6be288f6ec55edd29425c9c6dbb941b5160fa1b89cda34ef15378b5107c016d63b0f52721e71497f876dd7f3d6b1f228c4bc20c3c12384644200e91130c9195660d1e706f55b2accf00c5e2174a1d9ee289f0e763ee58860485ec97d19d7fa2df38af5b5910b1fa52087768d288e6ec4c8d5eca23c8d3024100be757a24dc2c923692d964693b2d71ca33ccb2f946f9e5232d2090b715a97dca554068fab8876105bc9ed6dccfd0917c5e0b80339306535c3eeb787e89397bc7024100e60f5c9e52434da079b8c641791a81a96daa4d9921a07e5b48292a9fce230df7c9fc2b97b5e38834ed5caaa387a0bca35c474e989a68dd65b79a6f691a74471f0240438ccf017bc5a3260ff76291a01782204136fcd344c524ebd0f997da17a8c1a09d93f6a7d602cdfa86e79f3539cfb389f4a1079b432e1f2abc762f8a51893dc9024046604ca4e1e554c9d27283b363a888219c3a8ca25b770d303f52d8872a37eefdedfc0619d2ba57e058fc0ff71676453e73ec1c4ef26d41ccebed824754a05d6102404445374d8450e753e0a42085b56b0d6d500b3e3518536dc8f12ec8fd77aa75491835327ac0e12d73b5c3f1b09d03f6a24fe63b9c551dee6559b625435ec92429
Sign = RSA-Swapped
Digest = SHA256
Input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Output = 07fa4e3de9c002c41c952dc292ef5a814c4c17dc1a6cf958c4c971e8089676d6661b442270ef9295c41e5385c9628aa1bdee2cc2558b8473ba212f2ba04b9ff2264c19187b9506b1d0a1cc2751844cc8dedf555d62ce81bc0e70bfe83d0184ee964593af91b9b327c0fb272c799148cd8737d412cbf36c2ad25fd66977bf805f
# Though we will never generate such a key, test that RSA keys where p and q are
# different sizes work properly.
PrivateKey = RSA-PrimeMismatch
Type = RSA
Input = 30820295020100300d06092a864886f70d01010105000482027f3082027b02010002818100c766f4fef89f5e9a8e13ed500fb38523ea94d7f8be066900eee58c913b4c6fdcb13d63d39b9108feabcefd1ffd04776403dc58f968ae817977d0809e567d8af512d604a0e9cb448fa5e402204ee519712a5ebbfd002faf8169495a782f54366b4665aac0d968bfec63c5446b6f9b13061c7f3d1f3f1b6bede8fff881b410a66f0203010001028180528c062f49485c771a0b18ca747d8a47f8941ea63c305626cb3f1f067e6861c4441c432687dbd08d484aac3b01f3ffdc3b762c719167f7cb22e565aa6acd597306ef6f7828b9720e9d440816186d940c4c5a9720dddf71fe0b59483f02a751515c8c27e43c575d6725d55f5bb77e0f977773b00afc058cfab6617ec90d0b62a9026100cb8f97c37b4fbc298b645bc3dc0526f8a4274e9a193b33c3acb76499b5b96330e4b586cbaa56368ffc12644952322253bc669496d572c0980f125fd7273739cf790d24401052b13732114d397c8c16a44716dc62d2320fb1ced99290dfd53e07022100fac51ac653609cdaba53280c6b6f209052e270be0c3c68fe8b37d6bf05fbba59026038dff2f04c58d7e2e7ae6fb1469d2de954bc22cb0d77ac1be4fb0ca1a1d39d7240c4b357de4cde4bd68b30f8077e38771af1b25c7e60e48cd7d1337402e1fc460ab57046720918b8aa4589452196669119c7ba65e602d4bdc264a9fdce7c5f2b0220773af0180bdc8bb7938fa6230191bcb1e236b7d4248d347e9242e25fc0c0874102605c4894cde334889f5b52ed8f86a2ee9c1fbe4166287e24ce44f3093bff383962f08043842f6ff3e6002104b0e29442c4a4483c5d06e2254fbe5e3930de3d0e28af10e96c6e341a4b8859382dbba24536a38ae71118e3e22413a93f298a7f744c
Sign = RSA-PrimeMismatch
Digest = SHA256
Input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Output = 6192b1ce630c87d02e8245fd74d4f6ecac37eef979d188c8fa48c4d355fbe814e7dd3152f42bb020d769b540d11867af5b947387b8c99158d56901ff3708e423931178213916ae1002f162c9d497aacacdcb20e6ffe7ed40138a253fc943ddf3587433df5831a3ce46aeefce358a009bf6bad12d82d77424c2755d984d7da196
# EC tests
+23 -2
View File
@@ -63,9 +63,19 @@
#include <openssl/rsa.h>
#include "../fipsmodule/rsa/internal.h"
#include "../internal.h"
#include "internal.h"
static struct CRYPTO_STATIC_MUTEX g_buggy_lock = CRYPTO_STATIC_MUTEX_INIT;
static int g_buggy = 0;
void EVP_set_buggy_rsa_parser(int buggy) {
CRYPTO_STATIC_MUTEX_lock_write(&g_buggy_lock);
g_buggy = buggy;
CRYPTO_STATIC_MUTEX_unlock_write(&g_buggy_lock);
}
static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
// See RFC 3279, section 2.3.1.
CBB spki, algorithm, oid, null, key_bitstring;
@@ -86,6 +96,11 @@ static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
}
static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
int buggy;
CRYPTO_STATIC_MUTEX_lock_read(&g_buggy_lock);
buggy = g_buggy;
CRYPTO_STATIC_MUTEX_unlock_read(&g_buggy_lock);
// See RFC 3279, section 2.3.1.
// The parameters must be NULL.
@@ -97,7 +112,13 @@ static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
return 0;
}
RSA *rsa = RSA_parse_public_key(key);
// Estonian IDs issued between September 2014 to September 2015 are
// broken. See https://crbug.com/532048 and https://crbug.com/534766.
//
// TODO(davidben): Switch this to the strict version in March 2016 or when
// Chromium can force client certificates down a different codepath, whichever
// comes first.
RSA *rsa = buggy ? RSA_parse_public_key_buggy(key) : RSA_parse_public_key(key);
if (rsa == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
RSA_free(rsa);
@@ -161,7 +182,7 @@ static int int_rsa_size(const EVP_PKEY *pkey) {
}
static int rsa_bits(const EVP_PKEY *pkey) {
return RSA_bits(pkey->pkey.rsa);
return BN_num_bits(pkey->pkey.rsa->n);
}
static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
+1
View File
@@ -113,6 +113,7 @@
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/stack.h>
#include <openssl/thread.h>
+1 -1
View File
@@ -8,7 +8,7 @@ Please note that we cannot answer questions about FIPS, nor about using BoringSS
BoringCrypto has undergone the following validations:
1. 2017-06-15: certificate [#2964](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/2964), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx) (in docx format).
1. 2017-06-15: certificate [#2964](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/1401val2017.htm#2964), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx) (in docx format).
## Running CAVP tests
+11 -18
View File
@@ -1,14 +1,7 @@
#! /usr/bin/env perl
# Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
@@ -39,7 +32,7 @@
# for scaling too, I [try to] avoid the latter by favoring off-by-2
# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF.
#
# As was shown by Dean Gaudet, the above note turned out to be
# As was shown by Dean Gaudet <dean@arctic.org>, the above note turned
# void. Performance improvement with off-by-2 shifts was observed on
# intermediate implementation, which was spilling yet another register
# to stack... Final offset*4 code below runs just a tad faster on P4,
@@ -55,8 +48,8 @@
# better performance on most recent µ-archs...
#
# Third version adds AES_cbc_encrypt implementation, which resulted in
# up to 40% performance improvement of CBC benchmark results. 40% was
# observed on P4 core, where "overall" improvement coefficient, i.e. if
# up to 40% performance imrovement of CBC benchmark results. 40% was
# observed on P4 core, where "overall" imrovement coefficient, i.e. if
# compared to PIC generated by GCC and in CBC mode, was observed to be
# as large as 4x:-) CBC performance is virtually identical to ECB now
# and on some platforms even better, e.g. 17.6 "small" cycles/byte on
@@ -159,7 +152,7 @@
# combinations then attack becomes infeasible. This is why revised
# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk
# of data is to be processed in one stroke. The current size limit of
# 512 bytes is chosen to provide same [diminishingly low] probability
# 512 bytes is chosen to provide same [diminishigly low] probability
# for cache-line to remain untouched in large chunk operation with
# large S-box as for single block operation with compact S-box and
# surely needs more careful consideration...
@@ -171,12 +164,12 @@
# yield execution to process performing AES just before timer fires
# off the scheduler, immediately regain control of CPU and analyze the
# cache state. For this attack to be efficient attacker would have to
# effectively slow down the operation by several *orders* of magnitude,
# effectively slow down the operation by several *orders* of magnitute,
# by ratio of time slice to duration of handful of AES rounds, which
# unlikely to remain unnoticed. Not to mention that this also means
# that he would spend correspondingly more time to collect enough
# that he would spend correspondigly more time to collect enough
# statistical data to mount the attack. It's probably appropriate to
# say that if adversary reckons that this attack is beneficial and
# say that if adeversary reckons that this attack is beneficial and
# risks to be noticed, you probably have larger problems having him
# mere opportunity. In other words suggested code design expects you
# to preclude/mitigate this attack by overall system security design.
@@ -240,7 +233,7 @@ $small_footprint=1; # $small_footprint=1 code is ~5% slower [on
# contention and in hope to "collect" 5% back
# in real-life applications...
$vertical_spin=0; # shift "vertically" defaults to 0, because of
$vertical_spin=0; # shift "verticaly" defaults to 0, because of
# its proof-of-concept status...
# Note that there is no decvert(), as well as last encryption round is
# performed with "horizontal" shifts. This is because this "vertical"
@@ -1606,7 +1599,7 @@ sub decstep()
# no instructions are reordered, as performance appears
# optimal... or rather that all attempts to reorder didn't
# result in better performance [which by the way is not a
# bit lower than encryption].
# bit lower than ecryption].
if($i==3) { &mov ($key,$__key); }
else { &mov ($out,$s[0]); }
&and ($out,0xFF);
+6 -11
View File
@@ -76,11 +76,6 @@ $code=<<___;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
#endif
@ Silence ARMv8 deprecated IT instruction warnings. This file is used by both
@ ARMv7 and ARMv8 processors and does not use ARMv8 instructions. (ARMv8 AES
@ instructions are in aesv8-armx.pl.)
.arch armv7-a
.text
#if defined(__thumb2__) && !defined(__APPLE__)
.syntax unified
@@ -205,10 +200,10 @@ asm_AES_encrypt:
#ifndef __thumb2__
sub r3,pc,#8 @ asm_AES_encrypt
#else
adr r3,.
adr r3,asm_AES_encrypt
#endif
stmdb sp!,{r1,r4-r12,lr}
#if defined(__thumb2__) || defined(__APPLE__)
#ifdef __APPLE__
adr $tbl,AES_Te
#else
sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te
@@ -455,7 +450,7 @@ _armv4_AES_set_encrypt_key:
#ifndef __thumb2__
sub r3,pc,#8 @ asm_AES_set_encrypt_key
#else
adr r3,.
adr r3,asm_AES_set_encrypt_key
#endif
teq r0,#0
#ifdef __thumb2__
@@ -486,7 +481,7 @@ _armv4_AES_set_encrypt_key:
mov lr,r1 @ bits
mov $key,r2 @ key
#if defined(__thumb2__) || defined(__APPLE__)
#ifdef __APPLE__
adr $tbl,AES_Te+1024 @ Te4
#else
sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
@@ -981,10 +976,10 @@ asm_AES_decrypt:
#ifndef __thumb2__
sub r3,pc,#8 @ asm_AES_decrypt
#else
adr r3,.
adr r3,asm_AES_decrypt
#endif
stmdb sp!,{r1,r4-r12,lr}
#if defined(__thumb2__) || defined(__APPLE__)
#ifdef __APPLE__
adr $tbl,AES_Td
#else
sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td
+3 -94
View File
@@ -1,14 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
@@ -597,21 +590,13 @@ $code.=<<___;
.type asm_AES_encrypt,\@function,3
.hidden asm_AES_encrypt
asm_AES_encrypt:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
# allocate frame "above" key schedule
lea -63(%rdx),%rcx # %rdx is key argument
@@ -624,7 +609,6 @@ asm_AES_encrypt:
mov %rsi,16(%rsp) # save out
mov %rax,24(%rsp) # save original stack pointer
.cfi_cfa_expression %rsp+24,deref,+8
.Lenc_prologue:
mov %rdx,$key
@@ -651,29 +635,20 @@ asm_AES_encrypt:
mov 16(%rsp),$out # restore out
mov 24(%rsp),%rsi # restore saved stack pointer
.cfi_def_cfa %rsi,8
mov $s0,0($out) # write output vector
mov $s1,4($out)
mov $s2,8($out)
mov $s3,12($out)
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lenc_epilogue:
ret
.cfi_endproc
.size asm_AES_encrypt,.-asm_AES_encrypt
___
@@ -1211,21 +1186,13 @@ $code.=<<___;
.type asm_AES_decrypt,\@function,3
.hidden asm_AES_decrypt
asm_AES_decrypt:
.cfi_startproc
mov %rsp,%rax
.cfi_def_cfa_register %rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
# allocate frame "above" key schedule
lea -63(%rdx),%rcx # %rdx is key argument
@@ -1238,7 +1205,6 @@ asm_AES_decrypt:
mov %rsi,16(%rsp) # save out
mov %rax,24(%rsp) # save original stack pointer
.cfi_cfa_expression %rsp+24,deref,+8
.Ldec_prologue:
mov %rdx,$key
@@ -1267,29 +1233,20 @@ asm_AES_decrypt:
mov 16(%rsp),$out # restore out
mov 24(%rsp),%rsi # restore saved stack pointer
.cfi_def_cfa %rsi,8
mov $s0,0($out) # write output vector
mov $s1,4($out)
mov $s2,8($out)
mov $s3,12($out)
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Ldec_epilogue:
ret
.cfi_endproc
.size asm_AES_decrypt,.-asm_AES_decrypt
___
#------------------------------------------------------------------#
@@ -1327,34 +1284,22 @@ $code.=<<___;
.globl asm_AES_set_encrypt_key
.type asm_AES_set_encrypt_key,\@function,3
asm_AES_set_encrypt_key:
.cfi_startproc
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12 # redundant, but allows to share
.cfi_push %r12
push %r13 # exception handler...
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
sub \$8,%rsp
.cfi_adjust_cfa_offset 8
.Lenc_key_prologue:
call _x86_64_AES_set_encrypt_key
mov 40(%rsp),%rbp
.cfi_restore %rbp
mov 48(%rsp),%rbx
.cfi_restore %rbx
add \$56,%rsp
.cfi_adjust_cfa_offset -56
.Lenc_key_epilogue:
ret
.cfi_endproc
.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent
@@ -1604,21 +1549,13 @@ $code.=<<___;
.globl asm_AES_set_decrypt_key
.type asm_AES_set_decrypt_key,\@function,3
asm_AES_set_decrypt_key:
.cfi_startproc
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
push %rdx # save key schedule
.cfi_adjust_cfa_offset 8
.Ldec_key_prologue:
call _x86_64_AES_set_encrypt_key
@@ -1672,22 +1609,14 @@ $code.=<<___;
xor %rax,%rax
.Labort:
mov 8(%rsp),%r15
.cfi_restore %r15
mov 16(%rsp),%r14
.cfi_restore %r14
mov 24(%rsp),%r13
.cfi_restore %r13
mov 32(%rsp),%r12
.cfi_restore %r12
mov 40(%rsp),%rbp
.cfi_restore %rbp
mov 48(%rsp),%rbx
.cfi_restore %rbx
add \$56,%rsp
.cfi_adjust_cfa_offset -56
.Ldec_key_epilogue:
ret
.cfi_endproc
.size asm_AES_set_decrypt_key,.-asm_AES_set_decrypt_key
___
@@ -1716,23 +1645,15 @@ $code.=<<___;
.extern OPENSSL_ia32cap_P
.hidden asm_AES_cbc_encrypt
asm_AES_cbc_encrypt:
.cfi_startproc
cmp \$0,%rdx # check length
je .Lcbc_epilogue
pushfq
.cfi_push 49 # %rflags
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
.Lcbc_prologue:
cld
@@ -1778,10 +1699,8 @@ asm_AES_cbc_encrypt:
.Lcbc_te_ok:
xchg %rsp,$key
.cfi_def_cfa_register $key
#add \$8,%rsp # reserve for return address!
mov $key,$_rsp # save %rsp
.cfi_cfa_expression $_rsp,deref,+64
.Lcbc_fast_body:
mov %rdi,$_inp # save copy of inp
mov %rsi,$_out # save copy of out
@@ -2011,7 +1930,7 @@ asm_AES_cbc_encrypt:
lea ($key,%rax),%rax
mov %rax,$keyend
# pick Te4 copy which can't "overlap" with stack frame or key schedule
# pick Te4 copy which can't "overlap" with stack frame or key scdedule
lea 2048($sbox),$sbox
lea 768-8(%rsp),%rax
sub $sbox,%rax
@@ -2163,27 +2082,17 @@ asm_AES_cbc_encrypt:
.align 16
.Lcbc_exit:
mov $_rsp,%rsi
.cfi_def_cfa %rsi,64
mov (%rsi),%r15
.cfi_restore %r15
mov 8(%rsi),%r14
.cfi_restore %r14
mov 16(%rsi),%r13
.cfi_restore %r13
mov 24(%rsi),%r12
.cfi_restore %r12
mov 32(%rsi),%rbp
.cfi_restore %rbp
mov 40(%rsi),%rbx
.cfi_restore %rbx
lea 48(%rsi),%rsp
.cfi_def_cfa %rsp,16
.Lcbc_popfq:
popfq
.cfi_pop 49 # %rflags
.Lcbc_epilogue:
ret
.cfi_endproc
.size asm_AES_cbc_encrypt,.-asm_AES_cbc_encrypt
___
}
+10 -21
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -50,22 +43,18 @@
# Add aesni_xts_[en|de]crypt. Westmere spends 1.50 cycles processing
# one byte out of 8KB with 128-bit key, Sandy Bridge - 1.09.
# November 2015
#
# Add aesni_ocb_[en|de]crypt. [Removed in BoringSSL]
######################################################################
# Current large-block performance in cycles per byte processed with
# 128-bit key (less is better).
#
# CBC en-/decrypt CTR XTS ECB OCB
# CBC en-/decrypt CTR XTS ECB
# Westmere 3.77/1.37 1.37 1.52 1.27
# * Bridge 5.07/0.98 0.99 1.09 0.91 1.10
# Haswell 4.44/0.80 0.97 1.03 0.72 0.76
# Skylake 2.68/0.65 0.65 0.66 0.64 0.66
# Silvermont 5.77/3.56 3.67 4.03 3.46 4.03
# Goldmont 3.84/1.39 1.39 1.63 1.31 1.70
# Bulldozer 5.80/0.98 1.05 1.24 0.93 1.23
# * Bridge 5.07/0.98 0.99 1.09 0.91
# Haswell 4.44/0.80 0.97 1.03 0.72
# Skylake 2.68/0.65 0.65 0.66 0.64
# Silvermont 5.77/3.56 3.67 4.03 3.46
# Goldmont 3.84/1.39 1.39 1.63 1.31
# Bulldozer 5.80/0.98 1.05 1.24 0.93
$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
# generates drop-in replacement for
@@ -239,7 +228,7 @@ sub aesni_generate1 # fully unrolled loop
# can schedule aes[enc|dec] every cycle optimal interleave factor
# equals to corresponding instructions latency. 8x is optimal for
# * Bridge, but it's unfeasible to accommodate such implementation
# in XMM registers addressable in 32-bit mode and therefore maximum
# in XMM registers addreassable in 32-bit mode and therefore maximum
# of 6x is used instead...
sub aesni_generate2
@@ -2436,7 +2425,7 @@ if ($PREFIX eq "aesni") {
&pxor ("xmm3","xmm3");
&aesenclast ("xmm2","xmm3");
&movdqa ("xmm3","xmm1");
&movdqa ("xmm3","xmm1")
&pslldq ("xmm1",4);
&pxor ("xmm3","xmm1");
&pslldq ("xmm1",4);
+12 -71
View File
@@ -60,7 +60,7 @@
# identical to CBC, because CBC-MAC is essentially CBC encrypt without
# saving output. CCM CTR "stays invisible," because it's neatly
# interleaved wih CBC-MAC. This provides ~30% improvement over
# "straightforward" CCM implementation with CTR and CBC-MAC performed
# "straghtforward" CCM implementation with CTR and CBC-MAC performed
# disjointly. Parallelizable modes practically achieve the theoretical
# limit.
#
@@ -143,14 +143,14 @@
# asymptotic, if it can be surpassed, isn't it? What happens there?
# Rewind to CBC paragraph for the answer. Yes, out-of-order execution
# magic is responsible for this. Processor overlaps not only the
# additional instructions with AES ones, but even AES instructions
# additional instructions with AES ones, but even AES instuctions
# processing adjacent triplets of independent blocks. In the 6x case
# additional instructions still claim disproportionally small amount
# of additional cycles, but in 8x case number of instructions must be
# a tad too high for out-of-order logic to cope with, and AES unit
# remains underutilized... As you can see 8x interleave is hardly
# justifiable, so there no need to feel bad that 32-bit aesni-x86.pl
# utilizes 6x interleave because of limited register bank capacity.
# utilizies 6x interleave because of limited register bank capacity.
#
# Higher interleave factors do have negative impact on Westmere
# performance. While for ECB mode it's negligible ~1.5%, other
@@ -1182,7 +1182,6 @@ $code.=<<___;
.type aesni_ctr32_encrypt_blocks,\@function,5
.align 16
aesni_ctr32_encrypt_blocks:
.cfi_startproc
cmp \$1,$len
jne .Lctr32_bulk
@@ -1205,9 +1204,7 @@ $code.=<<___;
.align 16
.Lctr32_bulk:
lea (%rsp),$key_ # use $key_ as frame pointer
.cfi_def_cfa_register $key_
push %rbp
.cfi_push %rbp
sub \$$frame_size,%rsp
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
@@ -1551,7 +1548,7 @@ $code.=<<___;
sub \$8,$len
jnc .Lctr32_loop8 # loop if $len-=8 didn't borrow
add \$8,$len # restore real remaining $len
add \$8,$len # restore real remainig $len
jz .Lctr32_done # done if ($len==0)
lea -0x80($key),$key
@@ -1668,7 +1665,7 @@ $code.=<<___;
movups $inout2,0x20($out) # $len was 3, stop store
.Lctr32_done:
xorps %xmm0,%xmm0 # clear register bank
xorps %xmm0,%xmm0 # clear regiser bank
xor $key0,$key0
pxor %xmm1,%xmm1
pxor %xmm2,%xmm2
@@ -1728,12 +1725,9 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -8($key_),%rbp
.cfi_restore %rbp
lea ($key_),%rsp
.cfi_def_cfa_register %rsp
.Lctr32_epilogue:
ret
.cfi_endproc
.size aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
___
}
@@ -1755,11 +1749,8 @@ $code.=<<___;
.type aesni_xts_encrypt,\@function,6
.align 16
aesni_xts_encrypt:
.cfi_startproc
lea (%rsp),%r11 # frame pointer
.cfi_def_cfa_register %r11
push %rbp
.cfi_push %rbp
sub \$$frame_size,%rsp
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
@@ -1857,7 +1848,7 @@ $code.=<<___;
lea `16*6`($inp),$inp
pxor $twmask,$inout5
pxor $twres,@tweak[0] # calculate tweaks^round[last]
pxor $twres,@tweak[0] # calclulate tweaks^round[last]
aesenc $rndkey1,$inout4
pxor $twres,@tweak[1]
movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^round[last]
@@ -2224,12 +2215,9 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -8(%r11),%rbp
.cfi_restore %rbp
lea (%r11),%rsp
.cfi_def_cfa_register %rsp
.Lxts_enc_epilogue:
ret
.cfi_endproc
.size aesni_xts_encrypt,.-aesni_xts_encrypt
___
@@ -2238,11 +2226,8 @@ $code.=<<___;
.type aesni_xts_decrypt,\@function,6
.align 16
aesni_xts_decrypt:
.cfi_startproc
lea (%rsp),%r11 # frame pointer
.cfi_def_cfa_register %r11
push %rbp
.cfi_push %rbp
sub \$$frame_size,%rsp
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
@@ -2343,7 +2328,7 @@ $code.=<<___;
lea `16*6`($inp),$inp
pxor $twmask,$inout5
pxor $twres,@tweak[0] # calculate tweaks^round[last]
pxor $twres,@tweak[0] # calclulate tweaks^round[last]
aesdec $rndkey1,$inout4
pxor $twres,@tweak[1]
movdqa @tweak[0],`16*0`(%rsp) # put aside tweaks^last round key
@@ -2733,12 +2718,9 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -8(%r11),%rbp
.cfi_restore %rbp
lea (%r11),%rsp
.cfi_def_cfa_register %rsp
.Lxts_dec_epilogue:
ret
.cfi_endproc
.size aesni_xts_decrypt,.-aesni_xts_decrypt
___
}
@@ -2763,18 +2745,12 @@ $code.=<<___;
.type aesni_ocb_encrypt,\@function,6
.align 32
aesni_ocb_encrypt:
.cfi_startproc
lea (%rsp),%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
___
$code.=<<___ if ($win64);
lea -0xa0(%rsp),%rsp
@@ -2969,7 +2945,6 @@ $code.=<<___ if (!$win64);
pxor %xmm14,%xmm14
pxor %xmm15,%xmm15
lea 0x28(%rsp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x00(%rsp),%xmm6
@@ -2997,20 +2972,13 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -40(%rax),%r14
.cfi_restore %r14
mov -32(%rax),%r13
.cfi_restore %r13
mov -24(%rax),%r12
.cfi_restore %r12
mov -16(%rax),%rbp
.cfi_restore %rbp
mov -8(%rax),%rbx
.cfi_restore %rbx
lea (%rax),%rsp
.cfi_def_cfa_register %rsp
.Locb_enc_epilogue:
ret
.cfi_endproc
.size aesni_ocb_encrypt,.-aesni_ocb_encrypt
.type __ocb_encrypt6,\@abi-omnipotent
@@ -3223,18 +3191,12 @@ __ocb_encrypt1:
.type aesni_ocb_decrypt,\@function,6
.align 32
aesni_ocb_decrypt:
.cfi_startproc
lea (%rsp),%rax
push %rbx
.cfi_push %rbx
push %rbp
.cfi_push %rbp
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
___
$code.=<<___ if ($win64);
lea -0xa0(%rsp),%rsp
@@ -3451,7 +3413,6 @@ $code.=<<___ if (!$win64);
pxor %xmm14,%xmm14
pxor %xmm15,%xmm15
lea 0x28(%rsp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x00(%rsp),%xmm6
@@ -3479,20 +3440,13 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -40(%rax),%r14
.cfi_restore %r14
mov -32(%rax),%r13
.cfi_restore %r13
mov -24(%rax),%r12
.cfi_restore %r12
mov -16(%rax),%rbp
.cfi_restore %rbp
mov -8(%rax),%rbx
.cfi_restore %rbx
lea (%rax),%rsp
.cfi_def_cfa_register %rsp
.Locb_dec_epilogue:
ret
.cfi_endproc
.size aesni_ocb_decrypt,.-aesni_ocb_decrypt
.type __ocb_decrypt6,\@abi-omnipotent
@@ -3705,7 +3659,6 @@ $code.=<<___;
.type ${PREFIX}_cbc_encrypt,\@function,6
.align 16
${PREFIX}_cbc_encrypt:
.cfi_startproc
test $len,$len # check length
jz .Lcbc_ret
@@ -3782,9 +3735,7 @@ $code.=<<___;
.align 16
.Lcbc_decrypt_bulk:
lea (%rsp),%r11 # frame pointer
.cfi_def_cfa_register %r11
push %rbp
.cfi_push %rbp
sub \$$frame_size,%rsp
and \$-16,%rsp # Linux kernel stack can be incorrectly seeded
___
@@ -4228,12 +4179,9 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -8(%r11),%rbp
.cfi_restore %rbp
lea (%r11),%rsp
.cfi_def_cfa_register %rsp
.Lcbc_ret:
ret
.cfi_endproc
.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
___
}
@@ -4254,9 +4202,7 @@ $code.=<<___;
.type ${PREFIX}_set_decrypt_key,\@abi-omnipotent
.align 16
${PREFIX}_set_decrypt_key:
.cfi_startproc
.byte 0x48,0x83,0xEC,0x08 # sub rsp,8
.cfi_adjust_cfa_offset 8
call __aesni_set_encrypt_key
shl \$4,$bits # rounds-1 after _aesni_set_encrypt_key
test %eax,%eax
@@ -4289,16 +4235,15 @@ ${PREFIX}_set_decrypt_key:
pxor %xmm0,%xmm0
.Ldec_key_ret:
add \$8,%rsp
.cfi_adjust_cfa_offset -8
ret
.cfi_endproc
.LSEH_end_set_decrypt_key:
.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
___
# This is based on submission from Intel by
# Huang Ying
# Vinodh Gopal
# This is based on submission by
#
# Huang Ying <ying.huang@intel.com>
# Vinodh Gopal <vinodh.gopal@intel.com>
# Kahraman Akdemir
#
# Aggressively optimized in respect to aeskeygenassist's critical path
@@ -4326,9 +4271,7 @@ $code.=<<___;
.align 16
${PREFIX}_set_encrypt_key:
__aesni_set_encrypt_key:
.cfi_startproc
.byte 0x48,0x83,0xEC,0x08 # sub rsp,8
.cfi_adjust_cfa_offset 8
mov \$-1,%rax
test $inp,$inp
jz .Lenc_key_ret
@@ -4518,7 +4461,7 @@ __aesni_set_encrypt_key:
.align 16
.L14rounds:
movups 16($inp),%xmm2 # remaining half of *userKey
movups 16($inp),%xmm2 # remaning half of *userKey
mov \$13,$bits # 14 rounds for 256
lea 16(%rax),%rax
cmp \$`1<<28`,%r10d # AVX, but no XOP
@@ -4622,9 +4565,7 @@ __aesni_set_encrypt_key:
pxor %xmm4,%xmm4
pxor %xmm5,%xmm5
add \$8,%rsp
.cfi_adjust_cfa_offset -8
ret
.cfi_endproc
.LSEH_end_set_encrypt_key:
.align 16
+7 -3
View File
@@ -58,7 +58,11 @@ $code=<<___;
#if __ARM_MAX_ARCH__>=7
.text
___
$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour =~ /64/);
#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
.arch armv8-a+crypto
#endif
___
$code.=<<___ if ($flavour !~ /64/);
.arch armv7-a // don't confuse not-so-latest binutils with argv8 :-)
.fpu neon
@@ -929,7 +933,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/^(\s+)v/$1/o or # strip off v prefix
s/\bbx\s+lr\b/ret/o;
# fix up remaining legacy suffixes
# fix up remainig legacy suffixes
s/\.[ui]?8//o;
m/\],#8/o and s/\.16b/\.8b/go;
s/\.[ui]?32//o and s/\.16b/\.4s/go;
@@ -988,7 +992,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/\bv([0-9])\.[12468]+[bsd]\b/q$1/go; # new->old registers
s/\/\/\s?/@ /o; # new->old style commentary
# fix up remaining new-style suffixes
# fix up remainig new-style suffixes
s/\{q([0-9]+)\},\s*\[(.+)\],#8/sprintf "{d%d},[$2]!",2*$1/eo or
s/\],#[0-9]+/]!/o;
+12 -8
View File
@@ -14,7 +14,8 @@
# details see http://www.openssl.org/~appro/cryptogams/.
#
# Specific modes and adaptation for Linux kernel by Ard Biesheuvel
# of Linaro. Permission to use under GPL terms is granted.
# <ard.biesheuvel@linaro.org>. Permission to use under GPL terms is
# granted.
# ====================================================================
# Bit-sliced AES for ARM NEON
@@ -48,7 +49,10 @@
# <appro@openssl.org>
# April-August 2013
# Add CBC, CTR and XTS subroutines and adapt for kernel use; courtesy of Ard.
#
# Add CBC, CTR and XTS subroutines, adapt for kernel use.
#
# <ard.biesheuvel@linaro.org>
$flavour = shift;
if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
@@ -740,9 +744,9 @@ $code.=<<___;
.type _bsaes_decrypt8,%function
.align 4
_bsaes_decrypt8:
adr $const,.
adr $const,_bsaes_decrypt8
vldmia $key!, {@XMM[9]} @ round 0 key
#if defined(__thumb2__) || defined(__APPLE__)
#ifdef __APPLE__
adr $const,.LM0ISR
#else
add $const,$const,#.LM0ISR-_bsaes_decrypt8
@@ -839,9 +843,9 @@ _bsaes_const:
.type _bsaes_encrypt8,%function
.align 4
_bsaes_encrypt8:
adr $const,.
adr $const,_bsaes_encrypt8
vldmia $key!, {@XMM[9]} @ round 0 key
#if defined(__thumb2__) || defined(__APPLE__)
#ifdef __APPLE__
adr $const,.LM0SR
#else
sub $const,$const,#_bsaes_encrypt8-.LM0SR
@@ -947,9 +951,9 @@ $code.=<<___;
.type _bsaes_key_convert,%function
.align 4
_bsaes_key_convert:
adr $const,.
adr $const,_bsaes_key_convert
vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key
#if defined(__thumb2__) || defined(__APPLE__)
#ifdef __APPLE__
adr $const,.LM0
#else
sub $const,$const,#_bsaes_key_convert-.LM0
+1 -115
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
###################################################################
### AES-128 [originally in CTR mode] ###
@@ -1165,23 +1158,15 @@ $code.=<<___;
.type bsaes_ecb_encrypt_blocks,\@abi-omnipotent
.align 16
bsaes_ecb_encrypt_blocks:
.cfi_startproc
mov %rsp, %rax
.Lecb_enc_prologue:
push %rbp
.cfi_push %rbp
push %rbx
.cfi_push %rbx
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
lea -0x48(%rsp),%rsp
.cfi_adjust_cfa_offset 0x48
___
$code.=<<___ if ($win64);
lea -0xa0(%rsp), %rsp
@@ -1199,7 +1184,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rsp,%rbp # backup %rsp
.cfi_def_cfa_register %rbp
mov 240($arg4),%eax # rounds
mov $arg1,$inp # backup arguments
mov $arg2,$out
@@ -1344,7 +1328,6 @@ $code.=<<___;
jb .Lecb_enc_bzero
lea 0x78(%rbp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -1362,45 +1345,29 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax), %r15
.cfi_restore %r15
mov -40(%rax), %r14
.cfi_restore %r14
mov -32(%rax), %r13
.cfi_restore %r13
mov -24(%rax), %r12
.cfi_restore %r12
mov -16(%rax), %rbx
.cfi_restore %rbx
mov -8(%rax), %rbp
.cfi_restore %rbp
lea (%rax), %rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lecb_enc_epilogue:
ret
.cfi_endproc
.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
.globl bsaes_ecb_decrypt_blocks
.type bsaes_ecb_decrypt_blocks,\@abi-omnipotent
.align 16
bsaes_ecb_decrypt_blocks:
.cfi_startproc
mov %rsp, %rax
.Lecb_dec_prologue:
push %rbp
.cfi_push %rbp
push %rbx
.cfi_push %rbx
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
lea -0x48(%rsp),%rsp
.cfi_adjust_cfa_offset 0x48
___
$code.=<<___ if ($win64);
lea -0xa0(%rsp), %rsp
@@ -1418,7 +1385,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rsp,%rbp # backup %rsp
.cfi_def_cfa_register %rbp
mov 240($arg4),%eax # rounds
mov $arg1,$inp # backup arguments
mov $arg2,$out
@@ -1564,7 +1530,6 @@ $code.=<<___;
jb .Lecb_dec_bzero
lea 0x78(%rbp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -1582,22 +1547,14 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax), %r15
.cfi_restore %r15
mov -40(%rax), %r14
.cfi_restore %r14
mov -32(%rax), %r13
.cfi_restore %r13
mov -24(%rax), %r12
.cfi_restore %r12
mov -16(%rax), %rbx
.cfi_restore %rbx
mov -8(%rax), %rbp
.cfi_restore %rbp
lea (%rax), %rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lecb_dec_epilogue:
ret
.cfi_endproc
.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
___
}
@@ -1607,7 +1564,6 @@ $code.=<<___;
.type bsaes_cbc_encrypt,\@abi-omnipotent
.align 16
bsaes_cbc_encrypt:
.cfi_startproc
___
$code.=<<___ if ($win64);
mov 48(%rsp),$arg6 # pull direction flag
@@ -1621,19 +1577,12 @@ $code.=<<___;
mov %rsp, %rax
.Lcbc_dec_prologue:
push %rbp
.cfi_push %rbp
push %rbx
.cfi_push %rbx
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
lea -0x48(%rsp), %rsp
.cfi_adjust_cfa_offset 0x48
___
$code.=<<___ if ($win64);
mov 0xa0(%rsp),$arg5 # pull ivp
@@ -1652,7 +1601,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rsp, %rbp # backup %rsp
.cfi_def_cfa_register %rbp
mov 240($arg4), %eax # rounds
mov $arg1, $inp # backup arguments
mov $arg2, $out
@@ -1872,7 +1820,6 @@ $code.=<<___;
ja .Lcbc_dec_bzero
lea 0x78(%rbp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -1890,45 +1837,29 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax), %r15
.cfi_restore %r15
mov -40(%rax), %r14
.cfi_restore %r14
mov -32(%rax), %r13
.cfi_restore %r13
mov -24(%rax), %r12
.cfi_restore %r12
mov -16(%rax), %rbx
.cfi_restore %rbx
mov -8(%rax), %rbp
.cfi_restore %rbp
lea (%rax), %rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lcbc_dec_epilogue:
ret
.cfi_endproc
.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
.globl bsaes_ctr32_encrypt_blocks
.type bsaes_ctr32_encrypt_blocks,\@abi-omnipotent
.align 16
bsaes_ctr32_encrypt_blocks:
.cfi_startproc
mov %rsp, %rax
.Lctr_enc_prologue:
push %rbp
.cfi_push %rbp
push %rbx
.cfi_push %rbx
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
lea -0x48(%rsp), %rsp
.cfi_adjust_cfa_offset 0x48
___
$code.=<<___ if ($win64);
mov 0xa0(%rsp),$arg5 # pull ivp
@@ -1947,7 +1878,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rsp, %rbp # backup %rsp
.cfi_def_cfa_register %rbp
movdqu ($arg5), %xmm0 # load counter
mov 240($arg4), %eax # rounds
mov $arg1, $inp # backup arguments
@@ -2122,7 +2052,6 @@ $code.=<<___;
ja .Lctr_enc_bzero
lea 0x78(%rbp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -2140,22 +2069,14 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax), %r15
.cfi_restore %r15
mov -40(%rax), %r14
.cfi_restore %r14
mov -32(%rax), %r13
.cfi_restore %r13
mov -24(%rax), %r12
.cfi_restore %r12
mov -16(%rax), %rbx
.cfi_restore %rbx
mov -8(%rax), %rbp
.cfi_restore %rbp
lea (%rax), %rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lctr_enc_epilogue:
ret
.cfi_endproc
.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
___
######################################################################
@@ -2171,23 +2092,15 @@ $code.=<<___;
.type bsaes_xts_encrypt,\@abi-omnipotent
.align 16
bsaes_xts_encrypt:
.cfi_startproc
mov %rsp, %rax
.Lxts_enc_prologue:
push %rbp
.cfi_push %rbp
push %rbx
.cfi_push %rbx
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
lea -0x48(%rsp), %rsp
.cfi_adjust_cfa_offset 0x48
___
$code.=<<___ if ($win64);
mov 0xa0(%rsp),$arg5 # pull key2
@@ -2207,7 +2120,6 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov %rsp, %rbp # backup %rsp
.cfi_def_cfa_register %rbp
mov $arg1, $inp # backup arguments
mov $arg2, $out
mov $arg3, $len
@@ -2530,7 +2442,6 @@ $code.=<<___;
ja .Lxts_enc_bzero
lea 0x78(%rbp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -2548,45 +2459,29 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax), %r15
.cfi_restore %r15
mov -40(%rax), %r14
.cfi_restore %r14
mov -32(%rax), %r13
.cfi_restore %r13
mov -24(%rax), %r12
.cfi_restore %r12
mov -16(%rax), %rbx
.cfi_restore %rbx
mov -8(%rax), %rbp
.cfi_restore %rbp
lea (%rax), %rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lxts_enc_epilogue:
ret
.cfi_endproc
.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
.globl bsaes_xts_decrypt
.type bsaes_xts_decrypt,\@abi-omnipotent
.align 16
bsaes_xts_decrypt:
.cfi_startproc
mov %rsp, %rax
.Lxts_dec_prologue:
push %rbp
.cfi_push %rbp
push %rbx
.cfi_push %rbx
push %r12
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
lea -0x48(%rsp), %rsp
.cfi_adjust_cfa_offset 0x48
___
$code.=<<___ if ($win64);
mov 0xa0(%rsp),$arg5 # pull key2
@@ -2954,7 +2849,6 @@ $code.=<<___;
ja .Lxts_dec_bzero
lea 0x78(%rbp),%rax
.cfi_def_cfa %rax,8
___
$code.=<<___ if ($win64);
movaps 0x40(%rbp), %xmm6
@@ -2972,22 +2866,14 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
mov -48(%rax), %r15
.cfi_restore %r15
mov -40(%rax), %r14
.cfi_restore %r14
mov -32(%rax), %r13
.cfi_restore %r13
mov -24(%rax), %r12
.cfi_restore %r12
mov -16(%rax), %rbx
.cfi_restore %rbx
mov -8(%rax), %rbp
.cfi_restore %rbp
lea (%rax), %rsp # restore %rsp
.cfi_def_cfa_register %rsp
.Lxts_dec_epilogue:
ret
.cfi_endproc
.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
___
}
+1 -8
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
######################################################################
## Constant-time SSSE3 AES core implementation.
+1 -8
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
######################################################################
## Constant-time SSSE3 AES core implementation.
+542 -11
View File
@@ -16,15 +16,21 @@
#define _GNU_SOURCE // needed for syscall() on Linux.
#endif
#include <openssl/aead.h>
#include <openssl/aes.h>
#include <openssl/base.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <stdlib.h>
#include <openssl/digest.h>
#include <openssl/des.h>
#include <openssl/ecdsa.h>
#include <openssl/ec_key.h>
#include <openssl/hmac.h>
#include <openssl/nid.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include "../internal.h"
#include "rand/internal.h"
#include "aes/aes.c"
#include "aes/key_wrap.c"
@@ -61,16 +67,15 @@
#include "ec/ec_montgomery.c"
#include "ec/oct.c"
#include "ec/p224-64.c"
#include "../../third_party/fiat/p256.c"
#include "ec/p256-64.c"
#include "ec/p256-x86_64.c"
#include "ec/simple.c"
#include "ec/util.c"
#include "ec/util-64.c"
#include "ec/wnaf.c"
#include "hmac/hmac.c"
#include "md4/md4.c"
#include "md5/md5.c"
#include "modes/cbc.c"
#include "modes/ccm.c"
#include "modes/cfb.c"
#include "modes/ctr.c"
#include "modes/gcm.c"
@@ -83,16 +88,205 @@
#include "rsa/padding.c"
#include "rsa/rsa.c"
#include "rsa/rsa_impl.c"
#include "self_check/self_check.c"
#include "sha/sha1-altivec.c"
#include "sha/sha1.c"
#include "sha/sha256.c"
#include "sha/sha512.c"
#include "tls/kdf.c"
#if defined(BORINGSSL_FIPS)
static void hexdump(const uint8_t *in, size_t len) {
for (size_t i = 0; i < len; i++) {
printf("%02x", in[i]);
}
}
static int check_test(const void *expected, const void *actual,
size_t expected_len, const char *name) {
if (OPENSSL_memcmp(actual, expected, expected_len) != 0) {
printf("%s failed.\nExpected: ", name);
hexdump(expected, expected_len);
printf("\nCalculated: ");
hexdump(actual, expected_len);
printf("\n");
return 0;
}
return 1;
}
static int set_bignum(BIGNUM **out, const uint8_t *in, size_t len) {
*out = BN_bin2bn(in, len, NULL);
return *out != NULL;
}
static RSA *self_test_rsa_key(void) {
static const uint8_t kN[] = {
0xd3, 0x3a, 0x62, 0x9f, 0x07, 0x77, 0xb0, 0x18, 0xf3, 0xff, 0xfe, 0xcc,
0xc9, 0xa2, 0xc2, 0x3a, 0xa6, 0x1d, 0xd8, 0xf0, 0x26, 0x5b, 0x38, 0x90,
0x17, 0x48, 0x15, 0xce, 0x21, 0xcd, 0xd6, 0x62, 0x99, 0xe2, 0xd7, 0xda,
0x40, 0x80, 0x3c, 0xad, 0x18, 0xb7, 0x26, 0xe9, 0x30, 0x8a, 0x23, 0x3f,
0x68, 0x9a, 0x9c, 0x31, 0x34, 0x91, 0x99, 0x06, 0x11, 0x36, 0xb2, 0x9e,
0x3a, 0xd0, 0xbc, 0xb9, 0x93, 0x4e, 0xb8, 0x72, 0xa1, 0x9f, 0xb6, 0x8c,
0xd5, 0x17, 0x1f, 0x7e, 0xaa, 0x75, 0xbb, 0xdf, 0xa1, 0x70, 0x48, 0xc4,
0xec, 0x9a, 0x51, 0xed, 0x41, 0xc9, 0x74, 0xc0, 0x3e, 0x1e, 0x85, 0x2f,
0xbe, 0x34, 0xc7, 0x65, 0x34, 0x8b, 0x4d, 0x55, 0x4b, 0xe1, 0x45, 0x54,
0x0d, 0x75, 0x7e, 0x89, 0x4d, 0x0c, 0xf6, 0x33, 0xe5, 0xfc, 0xfb, 0x56,
0x1b, 0xf2, 0x39, 0x9d, 0xe0, 0xff, 0x55, 0xcf, 0x02, 0x05, 0xb9, 0x74,
0xd2, 0x91, 0xfc, 0x87, 0xe1, 0xbb, 0x97, 0x2a, 0xe4, 0xdd, 0x20, 0xc0,
0x38, 0x47, 0xc0, 0x76, 0x3f, 0xa1, 0x9b, 0x5c, 0x20, 0xff, 0xff, 0xc7,
0x49, 0x3b, 0x4c, 0xaf, 0x99, 0xa6, 0x3e, 0x82, 0x5c, 0x58, 0x27, 0xce,
0x01, 0x03, 0xc3, 0x16, 0x35, 0x20, 0xe9, 0xf0, 0x15, 0x7a, 0x41, 0xd5,
0x1f, 0x52, 0xea, 0xdf, 0xad, 0x4c, 0xbb, 0x0d, 0xcb, 0x04, 0x91, 0xb0,
0x95, 0xa8, 0xce, 0x25, 0xfd, 0xd2, 0x62, 0x47, 0x77, 0xee, 0x13, 0xf1,
0x48, 0x72, 0x9e, 0xd9, 0x2d, 0xe6, 0x5f, 0xa4, 0xc6, 0x9e, 0x5a, 0xb2,
0xc6, 0xa2, 0xf7, 0x0a, 0x16, 0x17, 0xae, 0x6b, 0x1c, 0x30, 0x7c, 0x63,
0x08, 0x83, 0xe7, 0x43, 0xec, 0x54, 0x5e, 0x2c, 0x08, 0x0b, 0x5e, 0x46,
0xa7, 0x10, 0x93, 0x43, 0x53, 0x4e, 0xe3, 0x16, 0x73, 0x55, 0xce, 0xf2,
0x94, 0xc0, 0xbe, 0xb3,
};
static const uint8_t kE[] = {0x01, 0x00, 0x01}; // 65537
static const uint8_t kD[] = {
0x2f, 0x2c, 0x1e, 0xd2, 0x3d, 0x2c, 0xb1, 0x9b, 0x21, 0x02, 0xce, 0xb8,
0x95, 0x5f, 0x4f, 0xd9, 0x21, 0x38, 0x11, 0x36, 0xb0, 0x9a, 0x36, 0xab,
0x97, 0x47, 0x75, 0xf7, 0x2e, 0xfd, 0x75, 0x1f, 0x58, 0x16, 0x9c, 0xf6,
0x14, 0xe9, 0x8e, 0xa3, 0x69, 0x9d, 0x9d, 0x86, 0xfe, 0x5c, 0x1b, 0x3b,
0x11, 0xf5, 0x55, 0x64, 0x77, 0xc4, 0xfc, 0x53, 0xaa, 0x8c, 0x78, 0x9f,
0x75, 0xab, 0x20, 0x3a, 0xa1, 0x77, 0x37, 0x22, 0x02, 0x8e, 0x54, 0x8a,
0x67, 0x1c, 0x5e, 0xe0, 0x3e, 0xd9, 0x44, 0x37, 0xd1, 0x29, 0xee, 0x56,
0x6c, 0x30, 0x9a, 0x93, 0x4d, 0xd9, 0xdb, 0xc5, 0x03, 0x1a, 0x75, 0xcc,
0x0f, 0xc2, 0x61, 0xb5, 0x6c, 0x62, 0x9f, 0xc6, 0xa8, 0xc7, 0x8a, 0x60,
0x17, 0x11, 0x62, 0x4c, 0xef, 0x74, 0x31, 0x97, 0xad, 0x89, 0x2d, 0xe8,
0x31, 0x1d, 0x8b, 0x58, 0x82, 0xe3, 0x03, 0x1a, 0x6b, 0xdf, 0x3f, 0x3e,
0xa4, 0x27, 0x19, 0xef, 0x46, 0x7a, 0x90, 0xdf, 0xa7, 0xe7, 0xc9, 0x66,
0xab, 0x41, 0x1d, 0x65, 0x78, 0x1c, 0x18, 0x40, 0x5c, 0xd6, 0x87, 0xb5,
0xea, 0x29, 0x44, 0xb3, 0xf5, 0xb3, 0xd2, 0x4f, 0xce, 0x88, 0x78, 0x49,
0x27, 0x4e, 0x0b, 0x30, 0x85, 0xfb, 0x73, 0xfd, 0x8b, 0x32, 0x15, 0xee,
0x1f, 0xc9, 0x0e, 0x89, 0xb9, 0x43, 0x2f, 0xe9, 0x60, 0x8d, 0xda, 0xae,
0x2b, 0x30, 0x99, 0xee, 0x88, 0x81, 0x20, 0x7b, 0x4a, 0xc3, 0x18, 0xf2,
0x94, 0x02, 0x79, 0x94, 0xaa, 0x65, 0xd9, 0x1b, 0x45, 0x2a, 0xac, 0x6e,
0x30, 0x48, 0x57, 0xea, 0xbe, 0x79, 0x7d, 0xfc, 0x67, 0xaa, 0x47, 0xc0,
0xf7, 0x52, 0xfd, 0x0b, 0x63, 0x4e, 0x3d, 0x2e, 0xcc, 0x36, 0xa0, 0xdb,
0x92, 0x0b, 0xa9, 0x1b, 0xeb, 0xc2, 0xd5, 0x08, 0xd3, 0x85, 0x87, 0xf8,
0x5d, 0x1a, 0xf6, 0xc1,
};
static const uint8_t kP[] = {
0xf7, 0x06, 0xa3, 0x98, 0x8a, 0x52, 0xf8, 0x63, 0x68, 0x27, 0x4f, 0x68,
0x7f, 0x34, 0xec, 0x8e, 0x5d, 0xf8, 0x30, 0x92, 0xb3, 0x62, 0x4c, 0xeb,
0xdb, 0x19, 0x6b, 0x09, 0xc5, 0xa3, 0xf0, 0xbb, 0xff, 0x0f, 0xc2, 0xd4,
0x9b, 0xc9, 0x54, 0x4f, 0xb9, 0xf9, 0xe1, 0x4c, 0xf0, 0xe3, 0x4c, 0x90,
0xda, 0x7a, 0x01, 0xc2, 0x9f, 0xc4, 0xc8, 0x8e, 0xb1, 0x1e, 0x93, 0x75,
0x75, 0xc6, 0x13, 0x25, 0xc3, 0xee, 0x3b, 0xcc, 0xb8, 0x72, 0x6c, 0x49,
0xb0, 0x09, 0xfb, 0xab, 0x44, 0xeb, 0x4d, 0x40, 0xf0, 0x61, 0x6b, 0xe5,
0xe6, 0xfe, 0x3e, 0x0a, 0x77, 0x26, 0x39, 0x76, 0x3d, 0x4c, 0x3e, 0x9b,
0x5b, 0xc0, 0xaf, 0xa2, 0x58, 0x76, 0xb0, 0xe9, 0xda, 0x7f, 0x0e, 0x78,
0xc9, 0x76, 0x49, 0x5c, 0xfa, 0xb3, 0xb0, 0x15, 0x4b, 0x41, 0xc7, 0x27,
0xa4, 0x75, 0x28, 0x5c, 0x30, 0x69, 0x50, 0x29,
};
static const uint8_t kQ[] = {
0xda, 0xe6, 0xd2, 0xbb, 0x44, 0xff, 0x4f, 0xdf, 0x57, 0xc1, 0x11, 0xa3,
0x51, 0xba, 0x17, 0x89, 0x4c, 0x01, 0xc0, 0x0c, 0x97, 0x34, 0x50, 0xcf,
0x32, 0x1e, 0xc0, 0xbd, 0x7b, 0x35, 0xb5, 0x6a, 0x26, 0xcc, 0xea, 0x4c,
0x8e, 0x87, 0x4a, 0x67, 0x8b, 0xd3, 0xe5, 0x4f, 0x3a, 0x60, 0x48, 0x59,
0x04, 0x93, 0x39, 0xd7, 0x7c, 0xfb, 0x19, 0x1a, 0x34, 0xd5, 0xe8, 0xaf,
0xe7, 0x22, 0x2c, 0x0d, 0xc2, 0x91, 0x69, 0xb6, 0xe9, 0x2a, 0xe9, 0x1c,
0x4c, 0x6e, 0x8f, 0x40, 0xf5, 0xa8, 0x3e, 0x82, 0x69, 0x69, 0xbe, 0x9f,
0x7d, 0x5c, 0x7f, 0x92, 0x78, 0x17, 0xa3, 0x6d, 0x41, 0x2d, 0x72, 0xed,
0x3f, 0x71, 0xfa, 0x97, 0xb4, 0x63, 0xe4, 0x4f, 0xd9, 0x46, 0x03, 0xfb,
0x00, 0xeb, 0x30, 0x70, 0xb9, 0x51, 0xd9, 0x0a, 0xd2, 0xf8, 0x50, 0xd4,
0xfb, 0x43, 0x84, 0xf8, 0xac, 0x58, 0xc3, 0x7b,
};
static const uint8_t kDModPMinusOne[] = {
0xf5, 0x50, 0x8f, 0x88, 0x7d, 0xdd, 0xb5, 0xb4, 0x2a, 0x8b, 0xd7, 0x4d,
0x23, 0xfe, 0xaf, 0xe9, 0x16, 0x22, 0xd2, 0x41, 0xed, 0x88, 0xf2, 0x70,
0xcb, 0x4d, 0xeb, 0xc1, 0x71, 0x97, 0xc4, 0x0b, 0x3e, 0x5a, 0x2d, 0x96,
0xab, 0xfa, 0xfd, 0x12, 0x8b, 0xd3, 0x3e, 0x4e, 0x05, 0x6f, 0x04, 0xeb,
0x59, 0x3c, 0x0e, 0xa1, 0x73, 0xbe, 0x9d, 0x99, 0x2f, 0x05, 0xf9, 0x54,
0x8d, 0x98, 0x1e, 0x0d, 0xc4, 0x0c, 0xc3, 0x30, 0x23, 0xff, 0xe5, 0xd0,
0x2b, 0xd5, 0x4e, 0x2b, 0xa0, 0xae, 0xb8, 0x32, 0x84, 0x45, 0x8b, 0x3c,
0x6d, 0xf0, 0x10, 0x36, 0x9e, 0x6a, 0xc4, 0x67, 0xca, 0xa9, 0xfc, 0x06,
0x96, 0xd0, 0xbc, 0xda, 0xd1, 0x55, 0x55, 0x8d, 0x77, 0x21, 0xf4, 0x82,
0x39, 0x37, 0x91, 0xd5, 0x97, 0x56, 0x78, 0xc8, 0x3c, 0xcb, 0x5e, 0xf6,
0xdc, 0x58, 0x48, 0xb3, 0x7c, 0x94, 0x29, 0x39,
};
static const uint8_t kDModQMinusOne[] = {
0x64, 0x65, 0xbd, 0x7d, 0x1a, 0x96, 0x26, 0xa1, 0xfe, 0xf3, 0x94, 0x0d,
0x5d, 0xec, 0x85, 0xe2, 0xf8, 0xb3, 0x4c, 0xcb, 0xf9, 0x85, 0x8b, 0x12,
0x9c, 0xa0, 0x32, 0x32, 0x35, 0x92, 0x5a, 0x94, 0x47, 0x1b, 0x70, 0xd2,
0x90, 0x04, 0x49, 0x01, 0xd8, 0xc5, 0xe4, 0xc4, 0x43, 0xb7, 0xe9, 0x36,
0xba, 0xbc, 0x73, 0xa8, 0xfb, 0xaf, 0x86, 0xc1, 0xd8, 0x3d, 0xcb, 0xac,
0xf1, 0xcb, 0x60, 0x7d, 0x27, 0x21, 0xde, 0x64, 0x7f, 0xe8, 0xa8, 0x65,
0xcc, 0x40, 0x60, 0xff, 0xa0, 0x2b, 0xfc, 0x0f, 0x80, 0x1d, 0x79, 0xca,
0x58, 0x8a, 0xd6, 0x0f, 0xed, 0x78, 0x9a, 0x02, 0x00, 0x04, 0xc2, 0x53,
0x41, 0xe8, 0x1a, 0xd0, 0xfd, 0x71, 0x5b, 0x43, 0xac, 0x19, 0x4a, 0xb6,
0x12, 0xa3, 0xcb, 0xe1, 0xc7, 0x7d, 0x5c, 0x98, 0x74, 0x4e, 0x63, 0x74,
0x6b, 0x91, 0x7a, 0x29, 0x3b, 0x92, 0xb2, 0x85,
};
static const uint8_t kQInverseModP[] = {
0xd0, 0xde, 0x19, 0xda, 0x1e, 0xa2, 0xd8, 0x8f, 0x1c, 0x92, 0x73, 0xb0,
0xc9, 0x90, 0xc7, 0xf5, 0xec, 0xc5, 0x89, 0x01, 0x05, 0x78, 0x11, 0x2d,
0x74, 0x34, 0x44, 0xad, 0xd5, 0xf7, 0xa4, 0xfe, 0x9f, 0x25, 0x4d, 0x0b,
0x92, 0xe3, 0xb8, 0x7d, 0xd3, 0xfd, 0xa5, 0xca, 0x95, 0x60, 0xa3, 0xf9,
0x55, 0x42, 0x14, 0xb2, 0x45, 0x51, 0x9f, 0x73, 0x88, 0x43, 0x8a, 0xd1,
0x65, 0x9e, 0xd1, 0xf7, 0x82, 0x2a, 0x2a, 0x8d, 0x70, 0x56, 0xe3, 0xef,
0xc9, 0x0e, 0x2a, 0x2c, 0x15, 0xaf, 0x7f, 0x97, 0x81, 0x66, 0xf3, 0xb5,
0x00, 0xa9, 0x26, 0xcc, 0x1e, 0xc2, 0x98, 0xdd, 0xd3, 0x37, 0x06, 0x79,
0xb3, 0x60, 0x58, 0x79, 0x99, 0x3f, 0xa3, 0x15, 0x1f, 0x31, 0xe3, 0x11,
0x88, 0x4c, 0x35, 0x57, 0xfa, 0x79, 0xd7, 0xd8, 0x72, 0xee, 0x73, 0x95,
0x89, 0x29, 0xc7, 0x05, 0x27, 0x68, 0x90, 0x15,
};
RSA *rsa = RSA_new();
if (rsa == NULL ||
!set_bignum(&rsa->n, kN, sizeof(kN)) ||
!set_bignum(&rsa->e, kE, sizeof(kE)) ||
!set_bignum(&rsa->d, kD, sizeof(kD)) ||
!set_bignum(&rsa->p, kP, sizeof(kP)) ||
!set_bignum(&rsa->q, kQ, sizeof(kQ)) ||
!set_bignum(&rsa->dmp1, kDModPMinusOne, sizeof(kDModPMinusOne)) ||
!set_bignum(&rsa->dmq1, kDModQMinusOne, sizeof(kDModQMinusOne)) ||
!set_bignum(&rsa->iqmp, kQInverseModP, sizeof(kQInverseModP))) {
RSA_free(rsa);
return NULL;
}
return rsa;
}
static EC_KEY *self_test_ecdsa_key(void) {
static const uint8_t kQx[] = {
0xc8, 0x15, 0x61, 0xec, 0xf2, 0xe5, 0x4e, 0xde, 0xfe, 0x66, 0x17,
0xdb, 0x1c, 0x7a, 0x34, 0xa7, 0x07, 0x44, 0xdd, 0xb2, 0x61, 0xf2,
0x69, 0xb8, 0x3d, 0xac, 0xfc, 0xd2, 0xad, 0xe5, 0xa6, 0x81,
};
static const uint8_t kQy[] = {
0xe0, 0xe2, 0xaf, 0xa3, 0xf9, 0xb6, 0xab, 0xe4, 0xc6, 0x98, 0xef,
0x64, 0x95, 0xf1, 0xbe, 0x49, 0xa3, 0x19, 0x6c, 0x50, 0x56, 0xac,
0xb3, 0x76, 0x3f, 0xe4, 0x50, 0x7e, 0xec, 0x59, 0x6e, 0x88,
};
static const uint8_t kD[] = {
0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c,
0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0,
0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
};
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
BIGNUM *qx = BN_bin2bn(kQx, sizeof(kQx), NULL);
BIGNUM *qy = BN_bin2bn(kQy, sizeof(kQy), NULL);
BIGNUM *d = BN_bin2bn(kD, sizeof(kD), NULL);
if (ec_key == NULL || qx == NULL || qy == NULL || d == NULL ||
!EC_KEY_set_public_key_affine_coordinates(ec_key, qx, qy) ||
!EC_KEY_set_private_key(ec_key, d)) {
EC_KEY_free(ec_key);
ec_key = NULL;
}
BN_free(qx);
BN_free(qy);
BN_free(d);
return ec_key;
}
#if !defined(OPENSSL_ASAN)
// These symbols are filled in by delocate.go. They point to the start and end
// of the module, and the location of the integrity hash, respectively.
@@ -128,7 +322,345 @@ BORINGSSL_bcm_power_on_self_test(void) {
}
#endif
if (!BORINGSSL_self_test()) {
static const uint8_t kAESKey[16] = "BoringCrypto Key";
static const uint8_t kAESIV[16] = {0};
static const uint8_t kPlaintext[64] =
"BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!";
static const uint8_t kAESCBCCiphertext[64] = {
0x87, 0x2d, 0x98, 0xc2, 0xcc, 0x31, 0x5b, 0x41, 0xe0, 0xfa, 0x7b,
0x0a, 0x71, 0xc0, 0x42, 0xbf, 0x4f, 0x61, 0xd0, 0x0d, 0x58, 0x8c,
0xf7, 0x05, 0xfb, 0x94, 0x89, 0xd3, 0xbc, 0xaa, 0x1a, 0x50, 0x45,
0x1f, 0xc3, 0x8c, 0xb8, 0x98, 0x86, 0xa3, 0xe3, 0x6c, 0xfc, 0xad,
0x3a, 0xb5, 0x59, 0x27, 0x7d, 0x21, 0x07, 0xca, 0x4c, 0x1d, 0x55,
0x34, 0xdd, 0x5a, 0x2d, 0xc4, 0xb4, 0xf5, 0xa8,
#if !defined(BORINGSSL_FIPS_BREAK_AES_CBC)
0x35
#else
0x00
#endif
};
static const uint8_t kAESGCMCiphertext[80] = {
0x4a, 0xd8, 0xe7, 0x7d, 0x78, 0xd7, 0x7d, 0x5e, 0xb2, 0x11, 0xb6, 0xc9,
0xa4, 0xbc, 0xb2, 0xae, 0xbe, 0x93, 0xd1, 0xb7, 0xfe, 0x65, 0xc1, 0x82,
0x2a, 0xb6, 0x71, 0x5f, 0x1a, 0x7c, 0xe0, 0x1b, 0x2b, 0xe2, 0x53, 0xfa,
0xa0, 0x47, 0xfa, 0xd7, 0x8f, 0xb1, 0x4a, 0xc4, 0xdc, 0x89, 0xf9, 0xb4,
0x14, 0x4d, 0xde, 0x95, 0xea, 0x29, 0x69, 0x76, 0x81, 0xa3, 0x5c, 0x33,
0xd8, 0x37, 0xd8, 0xfa, 0x47, 0x19, 0x46, 0x2f, 0xf1, 0x90, 0xb7, 0x61,
0x8f, 0x6f, 0xdd, 0x31, 0x3f, 0x6a, 0x64,
#if !defined(BORINGSSL_FIPS_BREAK_AES_GCM)
0x0d
#else
0x00
#endif
};
static const DES_cblock kDESKey1 = {"BCMDESK1"};
static const DES_cblock kDESKey2 = {"BCMDESK2"};
static const DES_cblock kDESKey3 = {"BCMDESK3"};
static const DES_cblock kDESIV = {"BCMDESIV"};
static const uint8_t kDESCiphertext[64] = {
0xa4, 0x30, 0x7a, 0x4c, 0x1f, 0x60, 0x16, 0xd7, 0x4f, 0x41, 0xe1,
0xbb, 0x27, 0xc4, 0x27, 0x37, 0xd4, 0x7f, 0xb9, 0x10, 0xf8, 0xbc,
0xaf, 0x93, 0x91, 0xb8, 0x88, 0x24, 0xb1, 0xf6, 0xf8, 0xbd, 0x31,
0x96, 0x06, 0x76, 0xde, 0x32, 0xcd, 0x29, 0x29, 0xba, 0x70, 0x5f,
0xea, 0xc0, 0xcb, 0xde, 0xc7, 0x75, 0x90, 0xe0, 0x0f, 0x5e, 0x2c,
0x0d, 0x49, 0x20, 0xd5, 0x30, 0x83, 0xf8, 0x08,
#if !defined(BORINGSSL_FIPS_BREAK_DES)
0x5a
#else
0x00
#endif
};
static const uint8_t kPlaintextSHA1[20] = {
0xc6, 0xf8, 0xc9, 0x63, 0x1c, 0x14, 0x23, 0x62, 0x9b, 0xbd,
0x55, 0x82, 0xf4, 0xd6, 0x1d, 0xf2, 0xab, 0x7d, 0xc8,
#if !defined(BORINGSSL_FIPS_BREAK_SHA_1)
0x28
#else
0x00
#endif
};
static const uint8_t kPlaintextSHA256[32] = {
0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb,
0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb,
0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce,
#if !defined(BORINGSSL_FIPS_BREAK_SHA_256)
0x0f
#else
0x00
#endif
};
static const uint8_t kPlaintextSHA512[64] = {
0x08, 0x6a, 0x1c, 0x84, 0x61, 0x9d, 0x8e, 0xb3, 0xc0, 0x97, 0x4e,
0xa1, 0x9f, 0x9c, 0xdc, 0xaf, 0x3b, 0x5c, 0x31, 0xf0, 0xf2, 0x74,
0xc3, 0xbd, 0x6e, 0xd6, 0x1e, 0xb2, 0xbb, 0x34, 0x74, 0x72, 0x5c,
0x51, 0x29, 0x8b, 0x87, 0x3a, 0xa3, 0xf2, 0x25, 0x23, 0xd4, 0x1c,
0x82, 0x1b, 0xfe, 0xd3, 0xc6, 0xee, 0xb5, 0xd6, 0xaf, 0x07, 0x7b,
0x98, 0xca, 0xa7, 0x01, 0xf3, 0x94, 0xf3, 0x68,
#if !defined(BORINGSSL_FIPS_BREAK_SHA_512)
0x14
#else
0x00
#endif
};
static const uint8_t kRSASignature[256] = {
0x62, 0x66, 0x4b, 0xe3, 0xb1, 0xd2, 0x83, 0xf1, 0xa8, 0x56, 0x2b, 0x33,
0x60, 0x1e, 0xdb, 0x1e, 0x06, 0xf7, 0xa7, 0x1e, 0xa8, 0xef, 0x03, 0x4d,
0x0c, 0xf6, 0x83, 0x75, 0x7a, 0xf0, 0x14, 0xc7, 0xe2, 0x94, 0x3a, 0xb5,
0x67, 0x56, 0xa5, 0x48, 0x7f, 0x3a, 0xa5, 0xbf, 0xf7, 0x1d, 0x44, 0xa6,
0x34, 0xed, 0x9b, 0xd6, 0x51, 0xaa, 0x2c, 0x4e, 0xce, 0x60, 0x5f, 0xe9,
0x0e, 0xd5, 0xcd, 0xeb, 0x23, 0x27, 0xf8, 0xfb, 0x45, 0xe5, 0x34, 0x63,
0x77, 0x7f, 0x2e, 0x80, 0xcf, 0x9d, 0x2e, 0xfc, 0xe2, 0x50, 0x75, 0x29,
0x46, 0xf4, 0xaf, 0x91, 0xed, 0x36, 0xe1, 0x5e, 0xef, 0x66, 0xa1, 0xff,
0x27, 0xfc, 0x87, 0x7e, 0x60, 0x84, 0x0f, 0x54, 0x51, 0x56, 0x0f, 0x68,
0x99, 0xc0, 0x3f, 0xeb, 0xa5, 0xa0, 0x46, 0xb0, 0x86, 0x02, 0xb0, 0xc8,
0xe8, 0x46, 0x13, 0x06, 0xcd, 0xb7, 0x8a, 0xd0, 0x3b, 0x46, 0xd0, 0x14,
0x64, 0x53, 0x9b, 0x5b, 0x5e, 0x02, 0x45, 0xba, 0x6e, 0x7e, 0x0a, 0xb9,
0x9e, 0x62, 0xb7, 0xd5, 0x7a, 0x87, 0xea, 0xd3, 0x24, 0xa5, 0xef, 0xb3,
0xdc, 0x05, 0x9c, 0x04, 0x60, 0x4b, 0xde, 0xa8, 0x90, 0x08, 0x7b, 0x6a,
0x5f, 0xb4, 0x3f, 0xda, 0xc5, 0x1f, 0x6e, 0xd6, 0x15, 0xde, 0x65, 0xa4,
0x6e, 0x62, 0x9d, 0x8f, 0xa8, 0xbe, 0x86, 0xf6, 0x09, 0x90, 0x40, 0xa5,
0xf4, 0x23, 0xc5, 0xf6, 0x38, 0x86, 0x0d, 0x1c, 0xed, 0x4a, 0x0a, 0xae,
0xa4, 0x26, 0xc2, 0x2e, 0xd3, 0x13, 0x66, 0x61, 0xea, 0x35, 0x01, 0x0e,
0x13, 0xda, 0x78, 0x20, 0xae, 0x59, 0x5f, 0x9b, 0xa9, 0x6c, 0xf9, 0x1b,
0xdf, 0x76, 0x53, 0xc8, 0xa7, 0xf5, 0x63, 0x6d, 0xf3, 0xff, 0xfd, 0xaf,
0x75, 0x4b, 0xac, 0x67, 0xb1, 0x3c, 0xbf, 0x5e, 0xde, 0x73, 0x02, 0x6d,
0xd2, 0x0c, 0xb1,
#if !defined(BORINGSSL_FIPS_BREAK_RSA_SIG)
0x64
#else
0x00
#endif
};
const uint8_t kDRBGEntropy[48] =
"BCM Known Answer Test DBRG Initial Entropy ";
const uint8_t kDRBGPersonalization[18] = "BCMPersonalization";
const uint8_t kDRBGAD[16] = "BCM DRBG KAT AD ";
const uint8_t kDRBGOutput[64] = {
0x1d, 0x63, 0xdf, 0x05, 0x51, 0x49, 0x22, 0x46, 0xcd, 0x9b, 0xc5,
0xbb, 0xf1, 0x5d, 0x44, 0xae, 0x13, 0x78, 0xb1, 0xe4, 0x7c, 0xf1,
0x96, 0x33, 0x3d, 0x60, 0xb6, 0x29, 0xd4, 0xbb, 0x6b, 0x44, 0xf9,
0xef, 0xd9, 0xf4, 0xa2, 0xba, 0x48, 0xea, 0x39, 0x75, 0x59, 0x32,
0xf7, 0x31, 0x2c, 0x98, 0x14, 0x2b, 0x49, 0xdf, 0x02, 0xb6, 0x5d,
0x71, 0x09, 0x50, 0xdb, 0x23, 0xdb, 0xe5, 0x22,
#if !defined(BORINGSSL_FIPS_BREAK_DRBG)
0x95
#else
0x00
#endif
};
const uint8_t kDRBGEntropy2[48] =
"BCM Known Answer Test DBRG Reseed Entropy ";
const uint8_t kDRBGReseedOutput[64] = {
0xa4, 0x77, 0x05, 0xdb, 0x14, 0x11, 0x76, 0x71, 0x42, 0x5b, 0xd8,
0xd7, 0xa5, 0x4f, 0x8b, 0x39, 0xf2, 0x10, 0x4a, 0x50, 0x5b, 0xa2,
0xc8, 0xf0, 0xbb, 0x3e, 0xa1, 0xa5, 0x90, 0x7d, 0x54, 0xd9, 0xc6,
0xb0, 0x96, 0xc0, 0x2b, 0x7e, 0x9b, 0xc9, 0xa1, 0xdd, 0x78, 0x2e,
0xd5, 0xa8, 0x66, 0x16, 0xbd, 0x18, 0x3c, 0xf2, 0xaa, 0x7a, 0x2b,
0x37, 0xf9, 0xab, 0x35, 0x64, 0x15, 0x01, 0x3f, 0xc4,
};
const uint8_t kECDSASigR[32] = {
0x67, 0x80, 0xc5, 0xfc, 0x70, 0x27, 0x5e, 0x2c, 0x70, 0x61, 0xa0,
0xe7, 0x87, 0x7b, 0xb1, 0x74, 0xde, 0xad, 0xeb, 0x98, 0x87, 0x02,
0x7f, 0x3f, 0xa8, 0x36, 0x54, 0x15, 0x8b, 0xa7, 0xf5,
#if !defined(BORINGSSL_FIPS_BREAK_ECDSA_SIG)
0x0c,
#else
0x00,
#endif
};
const uint8_t kECDSASigS[32] = {
0xa5, 0x93, 0xe0, 0x23, 0x91, 0xe7, 0x4b, 0x8d, 0x77, 0x25, 0xa6,
0xba, 0x4d, 0xd9, 0x86, 0x77, 0xda, 0x7d, 0x8f, 0xef, 0xc4, 0x1a,
0xf0, 0xcc, 0x81, 0xe5, 0xea, 0x3f, 0xc2, 0x41, 0x7f, 0xd8,
};
AES_KEY aes_key;
uint8_t aes_iv[16];
uint8_t output[256];
// AES-CBC Encryption KAT
memcpy(aes_iv, kAESIV, sizeof(kAESIV));
if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
goto err;
}
AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv,
AES_ENCRYPT);
if (!check_test(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext),
"AES-CBC Encryption KAT")) {
goto err;
}
// AES-CBC Decryption KAT
memcpy(aes_iv, kAESIV, sizeof(kAESIV));
if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
goto err;
}
AES_cbc_encrypt(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext),
&aes_key, aes_iv, AES_DECRYPT);
if (!check_test(kPlaintext, output, sizeof(kPlaintext),
"AES-CBC Decryption KAT")) {
goto err;
}
size_t out_len;
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
OPENSSL_memset(nonce, 0, sizeof(nonce));
EVP_AEAD_CTX aead_ctx;
if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
sizeof(kAESKey), 0, NULL)) {
goto err;
}
// AES-GCM Encryption KAT
if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce,
EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
kPlaintext, sizeof(kPlaintext), NULL, 0) ||
!check_test(kAESGCMCiphertext, output, sizeof(kAESGCMCiphertext),
"AES-GCM Encryption KAT")) {
goto err;
}
// AES-GCM Decryption KAT
if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce,
EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()),
kAESGCMCiphertext, sizeof(kAESGCMCiphertext), NULL,
0) ||
!check_test(kPlaintext, output, sizeof(kPlaintext),
"AES-GCM Decryption KAT")) {
goto err;
}
EVP_AEAD_CTX_cleanup(&aead_ctx);
DES_key_schedule des1, des2, des3;
DES_cblock des_iv;
DES_set_key(&kDESKey1, &des1);
DES_set_key(&kDESKey2, &des2);
DES_set_key(&kDESKey3, &des3);
// 3DES Encryption KAT
memcpy(&des_iv, &kDESIV, sizeof(des_iv));
DES_ede3_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &des1, &des2,
&des3, &des_iv, DES_ENCRYPT);
if (!check_test(kDESCiphertext, output, sizeof(kDESCiphertext),
"3DES Encryption KAT")) {
goto err;
}
// 3DES Decryption KAT
memcpy(&des_iv, &kDESIV, sizeof(des_iv));
DES_ede3_cbc_encrypt(kDESCiphertext, output, sizeof(kDESCiphertext), &des1,
&des2, &des3, &des_iv, DES_DECRYPT);
if (!check_test(kPlaintext, output, sizeof(kPlaintext),
"3DES Decryption KAT")) {
goto err;
}
// SHA-1 KAT
SHA1(kPlaintext, sizeof(kPlaintext), output);
if (!check_test(kPlaintextSHA1, output, sizeof(kPlaintextSHA1),
"SHA-1 KAT")) {
goto err;
}
// SHA-256 KAT
SHA256(kPlaintext, sizeof(kPlaintext), output);
if (!check_test(kPlaintextSHA256, output, sizeof(kPlaintextSHA256),
"SHA-256 KAT")) {
goto err;
}
// SHA-512 KAT
SHA512(kPlaintext, sizeof(kPlaintext), output);
if (!check_test(kPlaintextSHA512, output, sizeof(kPlaintextSHA512),
"SHA-512 KAT")) {
goto err;
}
RSA *rsa_key = self_test_rsa_key();
if (rsa_key == NULL) {
printf("RSA KeyGen failed\n");
goto err;
}
// RSA Sign KAT
unsigned sig_len;
// Disable blinding for the power-on tests because it's not needed and
// triggers an entropy draw.
rsa_key->flags |= RSA_FLAG_NO_BLINDING;
if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output,
&sig_len, rsa_key) ||
!check_test(kRSASignature, output, sizeof(kRSASignature),
"RSA Sign KAT")) {
goto err;
}
// RSA Verify KAT
if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256),
kRSASignature, sizeof(kRSASignature), rsa_key)) {
printf("RSA Verify KAT failed.\n");
goto err;
}
RSA_free(rsa_key);
EC_KEY *ec_key = self_test_ecdsa_key();
if (ec_key == NULL) {
printf("ECDSA KeyGen failed\n");
goto err;
}
// ECDSA Sign/Verify PWCT
// The 'k' value for ECDSA is fixed to avoid an entropy draw.
ec_key->fixed_k = BN_new();
if (ec_key->fixed_k == NULL ||
!BN_set_word(ec_key->fixed_k, 42)) {
printf("Out of memory\n");
goto err;
}
ECDSA_SIG *sig =
ECDSA_do_sign(kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key);
uint8_t ecdsa_r_bytes[sizeof(kECDSASigR)];
uint8_t ecdsa_s_bytes[sizeof(kECDSASigS)];
if (sig == NULL ||
BN_num_bytes(sig->r) != sizeof(ecdsa_r_bytes) ||
!BN_bn2bin(sig->r, ecdsa_r_bytes) ||
BN_num_bytes(sig->s) != sizeof(ecdsa_s_bytes) ||
!BN_bn2bin(sig->s, ecdsa_s_bytes) ||
!check_test(kECDSASigR, ecdsa_r_bytes, sizeof(kECDSASigR), "ECDSA R") ||
!check_test(kECDSASigS, ecdsa_s_bytes, sizeof(kECDSASigS), "ECDSA S")) {
printf("ECDSA KAT failed.\n");
goto err;
}
ECDSA_SIG_free(sig);
EC_KEY_free(ec_key);
// DBRG KAT
CTR_DRBG_STATE drbg;
if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization,
sizeof(kDRBGPersonalization)) ||
!CTR_DRBG_generate(&drbg, output, sizeof(kDRBGOutput), kDRBGAD,
sizeof(kDRBGAD)) ||
!check_test(kDRBGOutput, output, sizeof(kDRBGOutput),
"DBRG Generate KAT") ||
!CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)) ||
!CTR_DRBG_generate(&drbg, output, sizeof(kDRBGReseedOutput), kDRBGAD,
sizeof(kDRBGAD)) ||
!check_test(kDRBGReseedOutput, output, sizeof(kDRBGReseedOutput),
"DRBG Reseed KAT")) {
goto err;
}
CTR_DRBG_clear(&drbg);
CTR_DRBG_STATE kZeroDRBG;
memset(&kZeroDRBG, 0, sizeof(kZeroDRBG));
if (!check_test(&kZeroDRBG, &drbg, sizeof(drbg), "DRBG Clear KAT")) {
goto err;
}
@@ -144,5 +676,4 @@ void BORINGSSL_FIPS_abort(void) {
exit(1);
}
}
#endif // BORINGSSL_FIPS
+73 -38
View File
@@ -100,38 +100,61 @@ int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
return ret;
}
int bn_uadd_fixed(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
// Widths are public, so we normalize to make |a| the larger one.
if (a->width < b->width) {
const BIGNUM *tmp = a;
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
int max, min, dif;
BN_ULONG *ap, *bp, *rp, carry, t1, t2;
const BIGNUM *tmp;
if (a->top < b->top) {
tmp = a;
a = b;
b = tmp;
}
max = a->top;
min = b->top;
dif = max - min;
int max = a->width;
int min = b->width;
if (!bn_wexpand(r, max + 1)) {
return 0;
}
r->width = max + 1;
BN_ULONG carry = bn_add_words(r->d, a->d, b->d, min);
for (int i = min; i < max; i++) {
// |r| and |a| may alias, so use a temporary.
BN_ULONG tmp = carry + a->d[i];
carry = tmp < a->d[i];
r->d[i] = tmp;
r->top = max;
ap = a->d;
bp = b->d;
rp = r->d;
carry = bn_add_words(rp, ap, bp, min);
rp += min;
ap += min;
bp += min;
if (carry) {
while (dif) {
dif--;
t1 = *(ap++);
t2 = (t1 + 1) & BN_MASK2;
*(rp++) = t2;
if (t2) {
carry = 0;
break;
}
}
if (carry) {
// carry != 0 => dif == 0
*rp = 1;
r->top++;
}
}
r->d[max] = carry;
return 1;
}
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
if (!bn_uadd_fixed(r, a, b)) {
return 0;
if (dif && rp != ap) {
while (dif--) {
// copy remaining words if ap != rp
*(rp++) = *(ap++);
}
}
bn_set_minimal_width(r);
r->neg = 0;
return 1;
}
@@ -139,6 +162,8 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) {
BN_ULONG l;
int i;
w &= BN_MASK2;
// degenerate case: w is zero
if (!w) {
return 1;
@@ -159,16 +184,16 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) {
return i;
}
for (i = 0; w != 0 && i < a->width; i++) {
a->d[i] = l = a->d[i] + w;
for (i = 0; w != 0 && i < a->top; i++) {
a->d[i] = l = (a->d[i] + w) & BN_MASK2;
w = (w > l) ? 1 : 0;
}
if (w && i == a->width) {
if (!bn_wexpand(a, a->width + 1)) {
if (w && i == a->top) {
if (!bn_wexpand(a, a->top + 1)) {
return 0;
}
a->width++;
a->top++;
a->d[i] = w;
}
@@ -176,6 +201,7 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) {
}
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
int max;
int add = 0, neg = 0;
const BIGNUM *tmp;
@@ -208,6 +234,13 @@ int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
return 1;
}
// We are actually doing a - b :-)
max = (a->top > b->top) ? a->top : b->top;
if (!bn_wexpand(r, max)) {
return 0;
}
if (BN_ucmp(a, b) < 0) {
if (!BN_usub(r, b, a)) {
return 0;
@@ -228,8 +261,8 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
register BN_ULONG t1, t2, *ap, *bp, *rp;
int i, carry;
max = bn_minimal_width(a);
min = bn_minimal_width(b);
max = a->top;
min = b->top;
dif = max - min;
if (dif < 0) // hmm... should not be happening
@@ -252,12 +285,12 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
t2 = *(bp++);
if (carry) {
carry = (t1 <= t2);
t1 -= t2 + 1;
t1 = (t1 - t2 - 1) & BN_MASK2;
} else {
carry = (t1 < t2);
t1 -= t2;
t1 = (t1 - t2) & BN_MASK2;
}
*(rp++) = t1;
*(rp++) = t1 & BN_MASK2;
}
if (carry) // subtracted
@@ -270,7 +303,7 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
while (dif) {
dif--;
t1 = *(ap++);
t2 = t1 - 1;
t2 = (t1 - 1) & BN_MASK2;
*(rp++) = t2;
if (t1) {
break;
@@ -282,9 +315,9 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif);
}
r->width = max;
r->top = max;
r->neg = 0;
bn_set_minimal_width(r);
bn_correct_top(r);
return 1;
}
@@ -292,6 +325,8 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
int BN_sub_word(BIGNUM *a, BN_ULONG w) {
int i;
w &= BN_MASK2;
// degenerate case: w is zero
if (!w) {
return 1;
@@ -314,7 +349,7 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) {
return i;
}
if ((bn_minimal_width(a) == 1) && (a->d[0] < w)) {
if ((a->top == 1) && (a->d[0] < w)) {
a->d[0] = w - a->d[0];
a->neg = 1;
return 1;
@@ -326,14 +361,14 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) {
a->d[i] -= w;
break;
} else {
a->d[i] -= w;
a->d[i] = (a->d[i] - w) & BN_MASK2;
i++;
w = 1;
}
}
if ((a->d[i] == 0) && (i == (a->width - 1))) {
a->width--;
if ((a->d[i] == 0) && (i == (a->top - 1))) {
a->top--;
}
return 1;
-4
View File
@@ -97,10 +97,6 @@ $_num="$num,#15*4"; $_bpend=$_num;
$code=<<___;
#include <openssl/arm_arch.h>
@ Silence ARMv8 deprecated IT instruction warnings. This file is used by both
@ ARMv7 and ARMv8 processors and does not use ARMv8 instructions.
.arch armv7-a
.text
#if defined(__thumb2__)
.syntax unified
+1 -8
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../../perlasm");
+1 -7
View File
@@ -1,10 +1,4 @@
#! /usr/bin/env perl
# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/local/bin/perl
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../../perlasm");
+58 -27
View File
@@ -1,30 +1,61 @@
#! /usr/bin/env perl
# Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
# Copyright (c) 2012, Intel Corporation. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#
# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1)
# (1) Intel Corporation, Israel Development Center, Haifa, Israel
# (2) University of Haifa, Israel
#
# References:
# [1] S. Gueron, V. Krasnov: "Software Implementation of Modular
# Exponentiation, Using Advanced Vector Instructions Architectures",
# F. Ozbudak and F. Rodriguez-Henriquez (Eds.): WAIFI 2012, LNCS 7369,
# pp. 119?135, 2012. Springer-Verlag Berlin Heidelberg 2012
# [2] S. Gueron: "Efficient Software Implementations of Modular
# Exponentiation", Journal of Cryptographic Engineering 2:31-43 (2012).
# [3] S. Gueron, V. Krasnov: "Speeding up Big-numbers Squaring",IEEE
# Proceedings of 9th International Conference on Information Technology:
# New Generations (ITNG 2012), pp.821-823 (2012)
# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis
# resistant 1024-bit modular exponentiation, for optimizing RSA2048
# on AVX2 capable x86_64 platforms",
# http://rt.openssl.org/Ticket/Display.html?id=2850&user=guest&pass=guest
#!/usr/bin/env perl
##############################################################################
# #
# Copyright (c) 2012, Intel Corporation #
# #
# All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without #
# modification, are permitted provided that the following conditions are #
# met: #
# #
# * Redistributions of source code must retain the above copyright #
# notice, this list of conditions and the following disclaimer. #
# #
# * 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. #
# #
# * Neither the name of the Intel Corporation nor the names of its #
# contributors may be used to endorse or promote products derived from #
# this software without specific prior written permission. #
# #
# #
# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY #
# EXPRESS 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 INTEL CORPORATION OR #
# 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. #
# #
##############################################################################
# Developers and authors: #
# Shay Gueron (1, 2), and Vlad Krasnov (1) #
# (1) Intel Corporation, Israel Development Center, Haifa, Israel #
# (2) University of Haifa, Israel #
##############################################################################
# Reference: #
# [1] S. Gueron, V. Krasnov: "Software Implementation of Modular #
# Exponentiation, Using Advanced Vector Instructions Architectures", #
# F. Ozbudak and F. Rodriguez-Henriquez (Eds.): WAIFI 2012, LNCS 7369, #
# pp. 119?135, 2012. Springer-Verlag Berlin Heidelberg 2012 #
# [2] S. Gueron: "Efficient Software Implementations of Modular #
# Exponentiation", Journal of Cryptographic Engineering 2:31-43 (2012). #
# [3] S. Gueron, V. Krasnov: "Speeding up Big-numbers Squaring",IEEE #
# Proceedings of 9th International Conference on Information Technology: #
# New Generations (ITNG 2012), pp.821-823 (2012) #
# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis #
# resistant 1024-bit modular exponentiation, for optimizing RSA2048 #
# on AVX2 capable x86_64 platforms", #
# http://rt.openssl.org/Ticket/Display.html?id=2850&user=guest&pass=guest#
##############################################################################
#
# +13% improvement over original submission by <appro@openssl.org>
#
+3 -10
View File
@@ -1,14 +1,7 @@
#! /usr/bin/env perl
# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
@@ -78,7 +71,7 @@ $frame=32; # size of above frame rounded up to 16n
&lea ("ebp",&DWP(-$frame,"esp","edi",4)); # future alloca($frame+4*(num+2))
&neg ("edi");
# minimize cache contention by arranging 2K window between stack
# minimize cache contention by arraning 2K window between stack
# pointer and ap argument [np is also position sensitive vector,
# but it's assumed to be near ap, as it's allocated at ~same
# time].
+19 -23
View File
@@ -52,9 +52,8 @@
#include <openssl/bn.h>
// TODO(davidben): Get this file working on MSVC x64.
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
(defined(__GNUC__) || defined(__clang__))
// TODO(davidben): Get this file working on Windows x64.
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
#include "../internal.h"
@@ -94,11 +93,11 @@
#undef sqr
#define sqr(r0, r1, a) __asm__("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w) {
BN_ULONG c1 = 0;
if (num == 0) {
if (num <= 0) {
return (c1);
}
@@ -127,11 +126,10 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
return c1;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w) {
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
BN_ULONG c1 = 0;
if (num == 0) {
if (num <= 0) {
return c1;
}
@@ -158,8 +156,8 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
return c1;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, size_t n) {
if (n == 0) {
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
if (n <= 0) {
return;
}
@@ -186,11 +184,11 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, size_t n) {
}
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
size_t n) {
int n) {
BN_ULONG ret;
size_t i = 0;
if (n == 0) {
if (n <= 0) {
return 0;
}
@@ -203,8 +201,7 @@ BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
" adcq (%5,%2,8),%0 \n"
" movq %0,(%3,%2,8) \n"
" lea 1(%2),%2 \n"
" dec %1 \n"
" jnz 1b \n"
" loop 1b \n"
" sbbq %0,%0 \n"
: "=&r"(ret), "+c"(n), "+r"(i)
: "r"(rp), "r"(ap), "r"(bp)
@@ -214,11 +211,11 @@ BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
}
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
size_t n) {
int n) {
BN_ULONG ret;
size_t i = 0;
if (n == 0) {
if (n <= 0) {
return 0;
}
@@ -231,8 +228,7 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
" sbbq (%5,%2,8),%0 \n"
" movq %0,(%3,%2,8) \n"
" lea 1(%2),%2 \n"
" dec %1 \n"
" jnz 1b \n"
" loop 1b \n"
" sbbq %0,%0 \n"
: "=&r"(ret), "+c"(n), "+r"(i)
: "r"(rp), "r"(ap), "r"(bp)
@@ -284,7 +280,7 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
void bn_mul_comba8(BN_ULONG r[16], const BN_ULONG a[8], const BN_ULONG b[8]) {
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -386,7 +382,7 @@ void bn_mul_comba8(BN_ULONG r[16], const BN_ULONG a[8], const BN_ULONG b[8]) {
r[15] = c1;
}
void bn_mul_comba4(BN_ULONG r[8], const BN_ULONG a[4], const BN_ULONG b[4]) {
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -424,7 +420,7 @@ void bn_mul_comba4(BN_ULONG r[8], const BN_ULONG a[4], const BN_ULONG b[4]) {
r[7] = c2;
}
void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[8]) {
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -498,7 +494,7 @@ void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[8]) {
r[15] = c1;
}
void bn_sqr_comba4(BN_ULONG r[8], const BN_ULONG a[4]) {
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -538,4 +534,4 @@ void bn_sqr_comba4(BN_ULONG r[8], const BN_ULONG a[4]) {
#undef mul_add_c2
#undef sqr_add_c2
#endif // !NO_ASM && X86_64 && (__GNUC__ || __clang__)
#endif // !NO_ASM && X86_64 && __GNUC__
+5 -11
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -303,11 +296,12 @@ $code.=<<___;
mov $num,$j # j=num
jmp .Lsub
.align 16
.Lsub: sbb ($np,$i,8),%rax
.Lsub:
sbb ($np,$i,8),%rax
mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i]
mov 8($ap,$i,8),%rax # tp[i+1]
lea 1($i),$i # i++
dec $j # doesn't affect CF!
dec $j # doesnn't affect CF!
jnz .Lsub
sbb \$0,%rax # handle upmost overflow bit
@@ -738,7 +732,7 @@ $code.=<<___;
mov 56($ap,$i,8),@ri[3]
sbb 40($np,$i,8),@ri[1]
lea 4($i),$i # i++
dec $j # doesn't affect CF!
dec $j # doesnn't affect CF!
jnz .Lsub4x
mov @ri[0],0($rp,$i,8) # rp[i]=tp[i]-np[i]
+7 -21
View File
@@ -1,11 +1,4 @@
#! /usr/bin/env perl
# Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -403,11 +396,12 @@ $code.=<<___;
mov $num,$j # j=num
jmp .Lsub
.align 16
.Lsub: sbb ($np,$i,8),%rax
.Lsub:
sbb ($np,$i,8),%rax
mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i]
mov 8($ap,$i,8),%rax # tp[i+1]
lea 1($i),$i # i++
dec $j # doesn't affect CF!
dec $j # doesnn't affect CF!
jnz .Lsub
sbb \$0,%rax # handle upmost overflow bit
@@ -2411,7 +2405,7 @@ my $N=$STRIDE/4; # should match cache line size
$code.=<<___;
movdqa 0(%rax),%xmm0 # 00000001000000010000000000000000
movdqa 16(%rax),%xmm1 # 00000002000000020000000200000002
lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimization)
lea 88-112(%rsp,%r10),%r10 # place the mask after tp[num+1] (+ICache optimizaton)
lea 128($bp),$bptr # size optimization
pshufd \$0,%xmm5,%xmm5 # broadcast index
@@ -3196,19 +3190,11 @@ $code.=<<___;
.align 32
.Lsqrx8x_break:
xor $zero,$zero
sub 16+8(%rsp),%rbx # mov 16(%rsp),%cf
adcx $zero,%r8
sub 16+8(%rsp),%r8 # consume last carry
mov 24+8(%rsp),$carry # initial $tptr, borrow $carry
adcx $zero,%r9
mov 0*8($aptr),%rdx # a[8], modulo-scheduled
adc \$0,%r10
xor %ebp,%ebp # xor $zero,$zero
mov %r8,0*8($tptr)
adc \$0,%r11
adc \$0,%r12
adc \$0,%r13
adc \$0,%r14
adc \$0,%r15
cmp $carry,$tptr # cf=0, of=0
je .Lsqrx8x_outer_loop
+69 -121
View File
@@ -148,13 +148,13 @@ BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) {
return dest;
}
if (!bn_wexpand(dest, src->width)) {
if (!bn_wexpand(dest, src->top)) {
return NULL;
}
OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->width);
OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top);
dest->width = src->width;
dest->top = src->top;
dest->neg = src->neg;
return dest;
}
@@ -164,14 +164,14 @@ void BN_clear(BIGNUM *bn) {
OPENSSL_memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
}
bn->width = 0;
bn->top = 0;
bn->neg = 0;
}
DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one) {
static const BN_ULONG kOneLimbs[1] = { 1 };
out->d = (BN_ULONG*) kOneLimbs;
out->width = 1;
out->top = 1;
out->dmax = 1;
out->neg = 0;
out->flags = BN_FLG_STATIC_DATA;
@@ -180,59 +180,61 @@ DEFINE_METHOD_FUNCTION(BIGNUM, BN_value_one) {
// BN_num_bits_word returns the minimum number of bits needed to represent the
// value in |l|.
unsigned BN_num_bits_word(BN_ULONG l) {
// |BN_num_bits| is often called on RSA prime factors. These have public bit
// lengths, but all bits beyond the high bit are secret, so count bits in
// constant time.
BN_ULONG x, mask;
int bits = (l != 0);
static const unsigned char bits[256] = {
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
#if BN_BITS2 > 32
x = l >> 32;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 32 & mask;
l ^= (x ^ l) & mask;
#if defined(OPENSSL_64_BIT)
if (l & 0xffffffff00000000L) {
if (l & 0xffff000000000000L) {
if (l & 0xff00000000000000L) {
return (bits[(int)(l >> 56)] + 56);
} else {
return (bits[(int)(l >> 48)] + 48);
}
} else {
if (l & 0x0000ff0000000000L) {
return (bits[(int)(l >> 40)] + 40);
} else {
return (bits[(int)(l >> 32)] + 32);
}
}
} else
#endif
x = l >> 16;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 16 & mask;
l ^= (x ^ l) & mask;
x = l >> 8;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 8 & mask;
l ^= (x ^ l) & mask;
x = l >> 4;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 4 & mask;
l ^= (x ^ l) & mask;
x = l >> 2;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 2 & mask;
l ^= (x ^ l) & mask;
x = l >> 1;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 1 & mask;
return bits;
{
if (l & 0xffff0000L) {
if (l & 0xff000000L) {
return (bits[(int)(l >> 24L)] + 24);
} else {
return (bits[(int)(l >> 16L)] + 16);
}
} else {
if (l & 0xff00L) {
return (bits[(int)(l >> 8)] + 8);
} else {
return (bits[(int)(l)]);
}
}
}
}
unsigned BN_num_bits(const BIGNUM *bn) {
const int width = bn_minimal_width(bn);
if (width == 0) {
const int max = bn->top - 1;
if (BN_is_zero(bn)) {
return 0;
}
return (width - 1) * BN_BITS2 + BN_num_bits_word(bn->d[width - 1]);
return max*BN_BITS2 + BN_num_bits_word(bn->d[max]);
}
unsigned BN_num_bytes(const BIGNUM *bn) {
@@ -240,7 +242,7 @@ unsigned BN_num_bytes(const BIGNUM *bn) {
}
void BN_zero(BIGNUM *bn) {
bn->width = bn->neg = 0;
bn->top = bn->neg = 0;
}
int BN_one(BIGNUM *bn) {
@@ -259,7 +261,7 @@ int BN_set_word(BIGNUM *bn, BN_ULONG value) {
bn->neg = 0;
bn->d[0] = value;
bn->width = 1;
bn->top = 1;
return 1;
}
@@ -278,7 +280,7 @@ int BN_set_u64(BIGNUM *bn, uint64_t value) {
bn->neg = 0;
bn->d[0] = (BN_ULONG)value;
bn->d[1] = (BN_ULONG)(value >> 32);
bn->width = 2;
bn->top = 2;
return 1;
#else
#error "BN_BITS2 must be 32 or 64."
@@ -291,40 +293,12 @@ int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
}
OPENSSL_memmove(bn->d, words, num * sizeof(BN_ULONG));
// |bn_wexpand| verified that |num| isn't too large.
bn->width = (int)num;
bn->top = (int)num;
bn_correct_top(bn);
bn->neg = 0;
return 1;
}
int bn_fits_in_words(const BIGNUM *bn, size_t num) {
// All words beyond |num| must be zero.
BN_ULONG mask = 0;
for (size_t i = num; i < (size_t)bn->width; i++) {
mask |= bn->d[i];
}
return mask == 0;
}
int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn) {
if (bn->neg) {
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
return 0;
}
size_t width = (size_t)bn->width;
if (width > num) {
if (!bn_fits_in_words(bn, num)) {
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
return 0;
}
width = num;
}
OPENSSL_memset(out, 0, sizeof(BN_ULONG) * num);
OPENSSL_memcpy(out, bn->d, sizeof(BN_ULONG) * width);
return 1;
}
int BN_is_negative(const BIGNUM *bn) {
return bn->neg != 0;
}
@@ -360,7 +334,7 @@ int bn_wexpand(BIGNUM *bn, size_t words) {
return 0;
}
OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->width);
OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
OPENSSL_free(bn->d);
bn->d = a;
@@ -377,46 +351,20 @@ int bn_expand(BIGNUM *bn, size_t bits) {
return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2);
}
int bn_resize_words(BIGNUM *bn, size_t words) {
if ((size_t)bn->width <= words) {
if (!bn_wexpand(bn, words)) {
return 0;
void bn_correct_top(BIGNUM *bn) {
BN_ULONG *ftl;
int tmp_top = bn->top;
if (tmp_top > 0) {
for (ftl = &(bn->d[tmp_top - 1]); tmp_top > 0; tmp_top--) {
if (*(ftl--)) {
break;
}
}
OPENSSL_memset(bn->d + bn->width, 0,
(words - bn->width) * sizeof(BN_ULONG));
bn->width = words;
return 1;
bn->top = tmp_top;
}
// All words beyond the new width must be zero.
if (!bn_fits_in_words(bn, words)) {
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
return 0;
}
bn->width = words;
return 1;
}
void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a,
const BN_ULONG *b, size_t num) {
for (size_t i = 0; i < num; i++) {
OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t),
crypto_word_t_too_small);
r[i] = constant_time_select_w(mask, a[i], b[i]);
}
}
int bn_minimal_width(const BIGNUM *bn) {
int ret = bn->width;
while (ret > 0 && bn->d[ret - 1] == 0) {
ret--;
}
return ret;
}
void bn_set_minimal_width(BIGNUM *bn) {
bn->width = bn_minimal_width(bn);
if (bn->width == 0) {
if (bn->top == 0) {
bn->neg = 0;
}
}
File diff suppressed because it is too large Load Diff
-234
View File
@@ -1,234 +0,0 @@
// Copyright (c) 2017, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main
import (
"bufio"
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"math/big"
"os"
"path/filepath"
"strings"
)
type test struct {
LineNumber int
Type string
Values map[string]*big.Int
}
type testScanner struct {
scanner *bufio.Scanner
lineNo int
err error
test test
}
func newTestScanner(r io.Reader) *testScanner {
return &testScanner{scanner: bufio.NewScanner(r)}
}
func (s *testScanner) scanLine() bool {
if !s.scanner.Scan() {
return false
}
s.lineNo++
return true
}
func (s *testScanner) addAttribute(line string) (key string, ok bool) {
fields := strings.SplitN(line, "=", 2)
if len(fields) != 2 {
s.setError(errors.New("invalid syntax"))
return "", false
}
key = strings.TrimSpace(fields[0])
value := strings.TrimSpace(fields[1])
valueInt, ok := new(big.Int).SetString(value, 16)
if !ok {
s.setError(fmt.Errorf("could not parse %q", value))
return "", false
}
if _, dup := s.test.Values[key]; dup {
s.setError(fmt.Errorf("duplicate key %q", key))
return "", false
}
s.test.Values[key] = valueInt
return key, true
}
func (s *testScanner) Scan() bool {
s.test = test{
Values: make(map[string]*big.Int),
}
// Scan until the first attribute.
for {
if !s.scanLine() {
return false
}
if len(s.scanner.Text()) != 0 && s.scanner.Text()[0] != '#' {
break
}
}
var ok bool
s.test.Type, ok = s.addAttribute(s.scanner.Text())
if !ok {
return false
}
s.test.LineNumber = s.lineNo
for s.scanLine() {
if len(s.scanner.Text()) == 0 {
break
}
if s.scanner.Text()[0] == '#' {
continue
}
if _, ok := s.addAttribute(s.scanner.Text()); !ok {
return false
}
}
return s.scanner.Err() == nil
}
func (s *testScanner) Test() test {
return s.test
}
func (s *testScanner) Err() error {
if s.err != nil {
return s.err
}
return s.scanner.Err()
}
func (s *testScanner) setError(err error) {
s.err = fmt.Errorf("line %d: %s", s.lineNo, err)
}
func checkKeys(t test, keys ...string) bool {
var foundErrors bool
for _, k := range keys {
if _, ok := t.Values[k]; !ok {
fmt.Fprintf(os.Stderr, "Line %d: missing key %q.\n", t.LineNumber, k)
foundErrors = true
}
}
for k, _ := range t.Values {
var found bool
for _, k2 := range keys {
if k == k2 {
found = true
break
}
}
if !found {
fmt.Fprintf(os.Stderr, "Line %d: unexpected key %q.\n", t.LineNumber, k)
foundErrors = true
}
}
return !foundErrors
}
func appendLengthPrefixed(ret, b []byte) []byte {
ret = append(ret, byte(len(b)>>8), byte(len(b)))
ret = append(ret, b...)
return ret
}
func appendUnsigned(ret []byte, n *big.Int) []byte {
b := n.Bytes()
if n.Sign() == 0 {
b = []byte{0}
}
return appendLengthPrefixed(ret, b)
}
func appendSigned(ret []byte, n *big.Int) []byte {
var sign byte
if n.Sign() < 0 {
sign = 1
}
b := []byte{sign}
b = append(b, n.Bytes()...)
if n.Sign() == 0 {
b = append(b, 0)
}
return appendLengthPrefixed(ret, b)
}
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, "Usage: %s TESTS FUZZ_DIR\n", os.Args[0])
os.Exit(1)
}
in, err := os.Open(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "Error opening %s: %s.\n", os.Args[0], err)
os.Exit(1)
}
defer in.Close()
fuzzerDir := os.Args[2]
scanner := newTestScanner(in)
for scanner.Scan() {
var fuzzer string
var b []byte
test := scanner.Test()
switch test.Type {
case "Quotient":
if checkKeys(test, "A", "B", "Quotient", "Remainder") {
fuzzer = "bn_div"
b = appendSigned(b, test.Values["A"])
b = appendSigned(b, test.Values["B"])
}
case "ModExp":
if checkKeys(test, "A", "E", "M", "ModExp") {
fuzzer = "bn_mod_exp"
b = appendSigned(b, test.Values["A"])
b = appendUnsigned(b, test.Values["E"])
b = appendUnsigned(b, test.Values["M"])
}
}
if len(fuzzer) != 0 {
hash := sha1.Sum(b)
path := filepath.Join(fuzzerDir, fuzzer + "_corpus", hex.EncodeToString(hash[:]))
if err := ioutil.WriteFile(path, b, 0666); err != nil {
fmt.Fprintf(os.Stderr, "Error writing to %s: %s.\n", path, err)
os.Exit(1)
}
}
}
if scanner.Err() != nil {
fmt.Fprintf(os.Stderr, "Error reading tests: %s.\n", scanner.Err())
}
}
-92
View File
@@ -5349,12 +5349,6 @@ A = -e53ad05c88568f09f616797f0b7f2756fb543d691ec2a5b645c1e5892a247302826419a35b1
Square = eea8028b26e0df090504d54da714a6f5f2695202e53cff479c78aedd47a8dc676243ec586740fde53b3eca9ca02b91031ce766242184109503fbe25b1b6d318e3cd5970fabd16dfa22984dd2e9f1e0f14c189170fc69c031d66663703e6235a942d51a4545bd7b0769d01d302ce2b00b83f01568a1e378f61fd0ca6201b0490330580cd9de85719e174a71915d7efbf65cd73d8f4e66f27e0dd3144d58ec09ed0f7ed7d1238ee596922807100fb7a11127944ddcdec6a9ca3bbf6df7301e354f3f049bfb7c275b43c3d8cda5907a932fba507c9145ea3166081c1b48fcc710ee32cd931f936c796b14f8a78a592e67753a7c9e428a01719c8ba82652f3a89fae110
A = -3dcb44be1e54c5a5d7db48055ca9afa1ebe2ae648aa6e16ac497502a7deee09ffa124720fad0ab163ce8b3ea6a90f110ea52b67dbc424d0cf1e8c9726dfd9e45bebcefaa5cd5706edeed27896525f31c6bbea3d67ee97badefabf3e2532470b66e3ae3100f66ddf50cf02fc3a8e3f44c304251d3b6a7ca3a6e4bd5d16a41bd97a4
Square = 0
A = 0
Square = 1
A = 1
# Product tests.
#
@@ -5960,86 +5954,6 @@ Product = -366c125f96b38b58d01c939c27c4100af3377eabb792b5491a
A = a57da276998c548101f514e9f
B = -542fb814f45924aa09a16f2a6
Product = 0
A = 0
B = 542fb814f45924aa09a16f2a6
Product = 0
A = 542fb814f45924aa09a16f2a6
B = 0
Product = 542fb814f45924aa09a16f2a6
A = 1
B = 542fb814f45924aa09a16f2a6
Product = 542fb814f45924aa09a16f2a6
A = 542fb814f45924aa09a16f2a6
B = 1
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a817a4d8899f571f257fa81c36a868d80e7fa2bcbda68a72ca3e31db8892b94d073e006433dd7128b7bf677d2b411532e5662cdff66d657673d58e03d4a338bae1a5513296f91d4d2b5b680527a2e12318e422ec2b7f05ea4fd3ef4780576488211dad5733685a8f0e5d2ecda549a15eebb235495e70d26b194c994cf16d98d356218d08a34d1593d90bc0d3572df0e84bdb1705c6c5e64ea4895599bb21bf219abdd4329813ecc198e708cee199c22f749bdeb0c206690e8420883f6c0661e47b29969986a7a72996ef63234c31aa39b7be37995d2898063ef5c3b672c43afbc1a065dec2671ae87e17639cfcd3148145a8323e1e9dc4f9c9daf981dd6aba4e8be01344c2eda185b87
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c58ba611f7
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea39224eed9ef1
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a817a4d8899aa73af54a4e1825aa6714016da99d9e3d0c02eb139716db437705cd9efabf0123b0831689735f4e488f226e577d4688d30914dd50ed368939452af0a7a094c065c6718bd54f53a808585fc1728c3bd1e7c968d76c6dca32f95a8323bacad31cdd4aae544d4208262c40bcf726c2f26cf1e60341c3e1e0c8ed4542555b9bf00488680b737a245cc9b7817231f1f6f1e614cdf43ea281fb850ebbb9305b1aa441a45dfdaa1e98b9d79d9ca511be070bfa94d8cd3cc750607c93e1b451a14e32356bd48d77860b37fd2e714827e770a5648ce8579a00ba5cae034502a8b03ba754994d9e002130cfdee6bfdf078dc8f6767b927c964197664c8e32bd3d31bd461ce
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c58ba611f7
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea3922
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a80dbb5a46feff82a92989bca577998c68ee619d9ea9972c6f139e97f5bdde635152830bedf302873508d2ed73badb82f9e32e1f4d12ea8c8b1059aa6d15f8e17d649bf41467903ab40d220d50570b5a263f637c0fcebc0ca29f8a81e2a01bf39bcb60cb9229dfd40618f706b941836bc5c291dec45ee9193e74d3a4cc5f73054ca56fd774a359f17a687268587393b76204a37cd48dcb09d3daed57a7e6d7d93a0ca3d6de8557fc4ddbfe9cb163fd10b7fe5f270dc57aa2fb88cdca2a3795015a17fd352d85fb688a38fa54883d0cab67aab08dbabd58d307c601f0f810014d78b101ff0bddb6d550b2480782406a905b9201e70ef6c1cb9765e91c10c8f5d240c
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c58ba611f7
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef96c826c5268b0a6788e14a9e3812764dd3ebb7489e6e66058ca6ccf9c007f8c049eda369b2889cc411bca78d4f5b0e3a9e80243e87e112072b01922b595afdef4dd562e58ce917f11e69c8fe050de54fdb2d607d05f09afd6dd140e9d195b91d85269610a1e5d5036e8c9fea2d4fa693d80ecdc819b201c0aed27dfe0b92b4b3b9ecabb3b9548f0d27dc917ffb14308c4f970863e163f375852fcd9fb115640dc40534f8f51a7b903599117dca6c80924fa9a1aeb43cf5a9a3f67ae818b484feed51d7ef60b3656720891b13a983c02c281c8a0954f13b7bfaca844d2cb66de5c11ff507e39cf774c7c93b38e296a44f04e5ecf2819b57943fb0509774ddbcfeb
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c58ba611f7
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a817a4d8899c7bedb01951b0f4fdb2c0fb64ad74707fda20027f4cee25da9b59be288d404cbd348f27600b87015d28f03cdf411f0e8c22deb9de5b3e0094f7820d78d59c90017cbd426297f8a32fb4b55b09362cf7cfb5910085acb24dbf618752b8b74c7e87f9cac44cb3b7486c43aa9b19a64d40a74eaf1de8b5f168b43d5750236aef753278c11294efd1adaddb6addb846f45fa55d7391898e8ec1c82bcf0008d9850c4c096571e8872e975dc8af1ba01bfbe8c8c27dc30cdaddd198936e4496579741a3a20e1b8e17241fe4abe5e98794e469180b742b2e1904940381f703f512885bda0340fe74e997ab269be00a3ca29bb937db2e06d8054e26dc13a5014ba51b175
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c5
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea39224eed9ef1
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a817a4d88997cc097fe3f7ace3ffb0fcee52b45551165bb02354b229788b59128489879b1a0373e9862a17692464a2dfc5d09185a0f1c67d2359ba70b52b03f21c7b24feb96e25e1a2dc7f4723952bf203979f7c9e38790f881e2b35006157825555d4c867fce9ea0a3cc6f1c94ee308a68e33f64f286247465ffe854033e9c64f5d79d6d66dcb38ad03535b20376bf4c3cf26e07ef445192ba2baf08bb5286695a61ff6b5dc7aa1832017198d61a324b8c244572157323c7bb3a2fee226133e1b0e0f2ff067cf71fc24bf38d0e172f459b0cdf0707c5bc586390faacf428bfdeb04e850ee0c35f6807eb6ca8d3a473dcc2239541115a8b0d33ea33295ff8c13b2a
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c5
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea3922
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a80dbb5a46fc245133c3335163cce37555d36c555182e6d9a754b9aa9305c070083d0fe806d2c5eda4a976f749d6ef40515c425e6531a7f4d11926e49907b7a8a938205e0d6fefaacb145200cbe3deec686476bcdc1f6bb3535147ecb00818f2cd666ac0dd497f0fbc087bf05c6425b7752a02e2a695655d4310f04943a6178946a74dbe4688bd1eb3f1a166aef37e39f3e1d36b6d6d422ec0db264cae8d44869f57a92952bd74a026dd7cfc672803905f029c723487d4123a7520688fc9c68b2384be32e881f64d0ed7ae555bf00e5799740dd8c6accc40f3fe573f194f4848bb05aea8a5509f2dd10fce023093f1ef20267244a990d7ffd462f4e85a4
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c5
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef96c826c5268b0a6788e14a9e353744d86d954c06f3b84ef271b184ac9957a5f88b08b606fa6aa97afc4983a62f1e74aa3f242e14a3f4cf5ea415d1437818663556a29d117ea7df1cf1ee32f70d6d5566e25d53f892c42d3f92e481b622455fce36e400de09e2d435099695354ceee249c793b76b3c544d70164381e0420ef8b85609502afff9130729ba7851e0775dc5d8c606ba614e7607625fbc38908c88fac43e29ff9b8728f5809e63f20289246b5128016478437550a833c60edb0df43dd9a47654f2e4ef308d4a18cea57ea4b0c6d08add07f2e7adc427cf591c29dbd1f975432922e3f2b71c75e4d2557efccf626be7a0d522b658d420ae321
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9ffec082c5
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a8126efa5e7be8e75d54e5ba9405f671d624eaf8d7a115d0479f6fb773b940525fd46b69bc43c815b6bb1798813ca95790bc68032f0b9e73fc964a9922507d8aac25f859745939b828ef5ed326b226b555e5088f13531be16272a89ad41ae82c940935b5d8fe75dc520a230cc279a887bce01bae0a79356f044af13c6f4a5e53c00b2d03cfcbb0f93b26202441a207ec91576410ac1750e257906d945bfe9204b73fc417600bd191edcf2e3eb79acbf4f84dda372405b5e98397abe85c1593543cd7a5b17cb90e299f422f0ce107d86b56474e435dbbcbb5314fb579cd68d54777aa2d0ff9b6b96de62b4676edea5b09589698ed829cad22a52aaec732b79edf6af
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9f
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea39224eed9ef1
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a8126efa5e7739032d1f8bb68307f4adc912f1d9b83797606874d4f2c669fe0b263565c4898a07701585237aa444234719adb869c17142126611a9cbd6e689fabb2847bb9dc5e2dc89694621a7179df1fe7371deb9bbdf5fea0b271d86bcde2796a65331c27365fb97fa3647435c47e5c854a95718fa49072cc239d046ca0ac2bf453beb31070370d59483adb42b9876776e43fccb663887f1a999f625eb8e9c4cdd0a89099c42cdff06be29ad9ea66a957002925c9425a83c3e74096ca31324134f5d4a2b7d3b8d7fd8d72192049f79c670874f65201c068c5aac2008a7df4e5eba02d88be8ec23683513a9cffe06671a7c2fa5da7a7aa571914caba1e
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9f
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea3922
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef989b0c6121e293a808857c1bdb914ae0fec75b02d527263093a9d9b8a42289ec74dc73e0e46568a9e8ee117659597434048308c9b66fa7a539694285b1238a13d1163fbac33db147e5431af1c7aca5b1a118db4f6650ec6340491ef7a2d203b53e43d536639f980eb6e92a37bffb2149c5eb45d6718a9496f0784370674c1d29732b944a3c3885b68f0fd2a121f556dc82d1b942e7aabba780f087b9df359d86e2055248c3aabc568e93bba67d3ccca2c4240c876506d63bb05aad6fc4c77dfafff1731a46c6711bc60c4d23976268928bc63e1d133add0633c737bb508c81fa1ff3b452b49b992ebac930432d555ab8c62ae17357b1186e80689672f5a9f472c
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9f
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef96c826c5268b0a6783ab6c7314a43e85a92955a5fbfbffcd31ef0913ba93563dab2b7f54d90fa21ca827ad15b5b1fb399a303f94837536b2813cb563f793fb780e91f8333a2de7bb9f10efdb652a504d6f242e7c15362d3a6eb6e3d1a5abb03023dfe964656979765a14fe8fc36af3d785030ce549b92a91dcb8e2aa13f5b89eb8449b31961a0f77117c8cac79af95ee69f6594e557af7bb017cd885027ff7c0cb1d2f99d1ed5eacb788f645c25150e737cf1184b546bb2d55f2014a18015ffe647580df6fe4d528ce983309baeac0347ae8739e2b1f6d1a83e12e4dbfea1cd81b11b8628837432ad1906c70323529b718c8c6e398e1dfa73
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc95262b94a0aca2f9f
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef96ebae79ce1360c374bc58f225bca564b7e6561b56e0edbb3a7f5934f382b916ab38423221d656357ce0e9bf1e9b04c0678b9c555e8365a0f977c95bd8dca1fb2ad2268193531ca36cbe7f40da8e1afe097e451dc2931b323ce731c03cc027a92ed8ae105c5e9c1bd385e238d989fadbf3aa54c097a8666df8a66b7e2d016e65a2a632603f2c84290ccd7346ada28dff79dd06c7f7989689aca4f494b977f984650f91327ab9936cb92675932440f135e54e4abeecf255d7061482b4c8d91769e02fc94b8acc43325d69541903c3ef7a7a8a5bd19bf886506d42bcf0efcb6197a8d178d6a60516a5aa771ae238a342dc61df8c18c6ba1ed952d4e0c3409c14639
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc9
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea39224eed9ef1
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef96ebae79ce1360c374bc58f2210cc134828c520a58df29ae28863a158a044937809d7d84d2940efbdddb448c64da5f1f31977e7865fd5529eac82fee3e804064a6315936295f8cb26f0de16a47373f5e8365939e280a57dacb508166a583a630c75730c2fe54971e70a35e224e7a1a21e3bd8f417a47c4796d34148cae15068e19eec637bed8f32846dc5aa7e8f50599e840903a8129206fc384e0b4085f9f1e7e3bf2fc67b62b02566ce73cb4b22d471cde35b4f0cccb74283cdded5748d62286f7ea5c184c1308d520ecc7c7f1535b1132708298bf94c0967bc8f8541bb2f2b3c81f11e50f1d8cba4ce3746ad5f85e6bacbefada657c9b386b991b2
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc9
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954a6ea3922
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef96ebae79ce1360c36ad2daaf856508e861c7f68a2611a215a93e3a15f68f72bb80a4fe9f4cfb6c7f91639179342c633db0f70c9dd849b5b5767908b27e61b812659dcd1a0613433f2c0940be49010886bb384d4676bd523f9827c1a48c7649fbfa73e872a5160796813956979b0f3fd3af728dd48f8a7348090300e41b181c8acae08a3b3106b61f90b0421803e6eba0d68e9bc93d3b659fd6316ba2815cb4b3b6a74f1f3fd24b0c07f619d995ac2beada44188eb72d371a6894f90087eaabe148755409bbff60114bcfefbfe2182e6dc4218d0da75af80059bbb14e848c2e60790fb35bf1cb685cbb133b2baf3f2faefcc3f69e34102def4
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc9
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad1eb654821c4af954
Product = 4f993781409d730da892c8451cc47a4c5c132a2c079f6c13a2689e9552450ed0b35c5291b82aae5614c0fc34f777940798a33b8bd5e010eb3c5c88595e8668fc8fb88ccd3d0cd5eee7c88e5b0b2be4605980fea4f8f2e42457963abe7860060482cfa2291e568ea55095ae2ada1c6bf9fda228664c9e02e7f12a8da4c355af044a537dd65dbf9c5d746c3c5f05a3d4d0515a48d9434b38fcbcc485558964fd9f212cf3c4aee9c03aebc468c25740df679d17823bfb20d96620c64b29f4013f0385cdd1a40fcbec3b06132a52aee615c4dbd880d0b030d5bc6aa06801d21fabd49774cd81ef504696d9655652db220ef9518c8ddd2bbd782e5f8cb06be77fc8d0c29f12d4ce67bb2478369710d003f0cb6f40a1341a5a5f2509d2d189084ea4346a44368a54f44c2be4c7b90c4d22976a31985927d0379b2e5d715a7e67eb3228943a07325a29316c695867e8f4ff676e00ffca0a6dfe8fe24652aef9e7f12616e8a54e367b90942f543a01dc7c1b8000ff991228ae83fe0131cfc235ba12ab2bdb33bd4ab0ba1b356bdbc6da4a70eed9fbf2c704e14ed6230eb5478dac0b02f4def1d8c076d1c0c0e2c4cdadb248de4acf961cee51dc41e545bd5a605a0860fb343c28ebf3f8814a9d5a7e0f3e9c93e742db76bc5671258d1da7758b41efead5
A = f33cad5d3876f0b60a001e13043e41033ee78c29ed8528fd6f22a87fc65c8c650277fab430722fcf63b3984c35ac46883127d544e2f44a465647814e15c0ff595382eff8bdff3be862f8a57a51f27ab4af9899861240855380f5bb883476699ef9eff179a1b88c64cfd6648240a5fc68de054468dc91dac11aaebe696dc05b6b0de0f54bd365ad798f3c85bceaf6ddf976b72cdf69de58335520d358f90e9856de5357dd5d2686cd1a41293d8c2687ba2cb1504420ae2c07014521889172b30df89521e2f66142345115110adf3dc603b1ddba5d80dc6b42fb980e9994aba2dfca00a3df8ea9062f570ec7e0e94d2bc9
B = 53c66ff2bc0e0d733d26f809aeedd151406ae8f44104f4e58f99e3eb54b06d542806932966bdbf30e13d81e5d6fa96f5308fc45613894b49dc7b766af02738dd89b10ca372d6232b0cbd57dcb873dea3c7598ef69b58ea5d72a0f2aaabd71025b488824a35cc33f8068ae4cd999fbb536be54e07f26df5d3bf8705281c8e94dd3712ad7c6a88f9d7b04f6f8924e18568ea07d46e58d197984824d797dd9ca1efe9763c62cc55fff69fad60d6501765dcf4926c18c027b4f9825d53cc38e99365c1b869245e66e7792f40dabeefe63e404cffc1d2ea63a9dd3fd4643afb2ddd288c6d4737abf20cec860584a7a600b4ad
# Quotient tests.
#
@@ -9983,12 +9897,6 @@ ModSquare = fffffffdfffffd01000009000002f6fffdf403000312000402f3fff5f602fe080a00
A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff00000000
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff
# Regression test for CVE-2017-3736.
ModSquare = fe06fe0b06160c09
A = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8f800000000000010000000006c000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffff8f8f8f800000000000010000000006c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff00fcfdfc
# A in Montgomery form is fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ffeadbcfc4dae7fff908e92820306b9544d954000000006c000000000000000000000000000000000000000000000000000000000000000000ff030202fffff8ffebdbcfc4dae7fff908e92820306b9544d954000000006c000000ff0302030000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01fc00ff02ffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fcfdfcffffffffff000000000000000000ff0302030000000000ffffffffffffffffff00fcfdfdff030202ff00000000ffffffffffffffffff00fcfdfcffffffffff
M = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8f800000000000010000000006c000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffff8f8f8f800000000000010000000006c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff
# ModExp tests.
#
+73 -34
View File
@@ -77,7 +77,7 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
}
if (len == 0) {
ret->width = 0;
ret->top = 0;
return ret;
}
@@ -93,7 +93,7 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
// |bn_wexpand| must check bounds on |num_words| to write it into
// |ret->dmax|.
assert(num_words <= INT_MAX);
ret->width = (int)num_words;
ret->top = (int)num_words;
ret->neg = 0;
while (len--) {
@@ -105,6 +105,9 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
}
}
// need to call this due to clear byte at top if avoiding having the top bit
// set (-ve number)
bn_correct_top(ret);
return ret;
}
@@ -120,7 +123,7 @@ BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
}
if (len == 0) {
ret->width = 0;
ret->top = 0;
ret->neg = 0;
return ret;
}
@@ -131,7 +134,7 @@ BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
BN_free(bn);
return NULL;
}
ret->width = num_words;
ret->top = num_words;
// Make sure the top bytes will be zeroed.
ret->d[num_words - 1] = 0;
@@ -139,6 +142,8 @@ BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
// We only support little-endian platforms, so we can simply memcpy the
// internal representation.
OPENSSL_memcpy(ret->d, in, len);
bn_correct_top(ret);
return ret;
}
@@ -154,54 +159,88 @@ size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
return n;
}
static int fits_in_bytes(const uint8_t *bytes, size_t num_bytes, size_t len) {
uint8_t mask = 0;
for (size_t i = len; i < num_bytes; i++) {
mask |= bytes[i];
}
return mask == 0;
}
int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
const uint8_t *bytes = (const uint8_t *)in->d;
size_t num_bytes = in->width * BN_BYTES;
// If we don't have enough space, fail out.
size_t num_bytes = BN_num_bytes(in);
if (len < num_bytes) {
if (!fits_in_bytes(bytes, num_bytes, len)) {
return 0;
}
num_bytes = len;
return 0;
}
// We only support little-endian platforms, so we can simply memcpy into the
// internal representation.
OPENSSL_memcpy(out, bytes, num_bytes);
OPENSSL_memcpy(out, in->d, num_bytes);
// Pad out the rest of the buffer with zeroes.
OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
return 1;
}
// constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
// behavior is undefined if |v| takes any other value.
static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
BN_ULONG mask = v;
mask--;
return (~mask & x) | (mask & y);
}
// constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y|
// must not have their MSBs set.
static int constant_time_le_size_t(size_t x, size_t y) {
return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1;
}
// read_word_padded returns the |i|'th word of |in|, if it is not out of
// bounds. Otherwise, it returns 0. It does so without branches on the size of
// |in|, however it necessarily does not have the same memory access pattern. If
// the access would be out of bounds, it reads the last word of |in|. |in| must
// not be zero.
static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
// Read |in->d[i]| if valid. Otherwise, read the last word.
BN_ULONG l = in->d[constant_time_select_ulong(
constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
// Clamp to zero if above |d->top|.
return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
}
int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
const uint8_t *bytes = (const uint8_t *)in->d;
size_t num_bytes = in->width * BN_BYTES;
if (len < num_bytes) {
if (!fits_in_bytes(bytes, num_bytes, len)) {
return 0;
}
num_bytes = len;
// Special case for |in| = 0. Just branch as the probability is negligible.
if (BN_is_zero(in)) {
OPENSSL_memset(out, 0, len);
return 1;
}
// We only support little-endian platforms, so we can simply write the buffer
// in reverse.
for (size_t i = 0; i < num_bytes; i++) {
out[len - i - 1] = bytes[i];
// Check if the integer is too big. This case can exit early in non-constant
// time.
if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
return 0;
}
if ((len % BN_BYTES) != 0) {
BN_ULONG l = read_word_padded(in, len / BN_BYTES);
if (l >> (8 * (len % BN_BYTES)) != 0) {
return 0;
}
}
// Write the bytes out one by one. Serialization is done without branching on
// the bits of |in| or on |in->top|, but if the routine would otherwise read
// out of bounds, the memory access pattern can't be fixed. However, for an
// RSA key of size a multiple of the word size, the probability of BN_BYTES
// leading zero octets is low.
//
// See Falko Stenzke, "Manger's Attack revisited", ICICS 2010.
size_t i = len;
while (i--) {
BN_ULONG l = read_word_padded(in, i / BN_BYTES);
*(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
}
// Pad out the rest of the buffer with zeroes.
OPENSSL_memset(out, 0, len - num_bytes);
return 1;
}
BN_ULONG BN_get_word(const BIGNUM *bn) {
switch (bn_minimal_width(bn)) {
switch (bn->top) {
case 0:
return 0;
case 1:
@@ -212,7 +251,7 @@ BN_ULONG BN_get_word(const BIGNUM *bn) {
}
int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
switch (bn_minimal_width(bn)) {
switch (bn->top) {
case 0:
*out = 0;
return 1;
+103 -64
View File
@@ -57,49 +57,37 @@
#include <openssl/bn.h>
#include <openssl/mem.h>
#include <openssl/type_check.h>
#include "internal.h"
#include "../../internal.h"
static int bn_cmp_words_consttime(const BN_ULONG *a, size_t a_len,
const BN_ULONG *b, size_t b_len) {
OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t),
crypto_word_t_too_small);
int ret = 0;
// Process the common words in little-endian order.
size_t min = a_len < b_len ? a_len : b_len;
for (size_t i = 0; i < min; i++) {
crypto_word_t eq = constant_time_eq_w(a[i], b[i]);
crypto_word_t lt = constant_time_lt_w(a[i], b[i]);
ret =
constant_time_select_int(eq, ret, constant_time_select_int(lt, -1, 1));
}
// If |a| or |b| has non-zero words beyond |min|, they take precedence.
if (a_len < b_len) {
crypto_word_t mask = 0;
for (size_t i = a_len; i < b_len; i++) {
mask |= b[i];
}
ret = constant_time_select_int(constant_time_is_zero_w(mask), ret, -1);
} else if (b_len < a_len) {
crypto_word_t mask = 0;
for (size_t i = b_len; i < a_len; i++) {
mask |= a[i];
}
ret = constant_time_select_int(constant_time_is_zero_w(mask), ret, 1);
}
return ret;
}
int BN_ucmp(const BIGNUM *a, const BIGNUM *b) {
return bn_cmp_words_consttime(a->d, a->width, b->d, b->width);
int i;
BN_ULONG t1, t2, *ap, *bp;
i = a->top - b->top;
if (i != 0) {
return i;
}
ap = a->d;
bp = b->d;
for (i = a->top - 1; i >= 0; i--) {
t1 = ap[i];
t2 = bp[i];
if (t1 != t2) {
return (t1 > t2) ? 1 : -1;
}
}
return 0;
}
int BN_cmp(const BIGNUM *a, const BIGNUM *b) {
int i;
int gt, lt;
BN_ULONG t1, t2;
if ((a == NULL) || (b == NULL)) {
if (a != NULL) {
return -1;
@@ -110,25 +98,84 @@ int BN_cmp(const BIGNUM *a, const BIGNUM *b) {
}
}
// We do not attempt to process the sign bit in constant time. Negative
// |BIGNUM|s should never occur in crypto, only calculators.
if (a->neg != b->neg) {
if (a->neg) {
return -1;
}
return 1;
}
if (a->neg == 0) {
gt = 1;
lt = -1;
} else {
gt = -1;
lt = 1;
}
int ret = BN_ucmp(a, b);
return a->neg ? -ret : ret;
if (a->top > b->top) {
return gt;
}
if (a->top < b->top) {
return lt;
}
for (i = a->top - 1; i >= 0; i--) {
t1 = a->d[i];
t2 = b->d[i];
if (t1 > t2) {
return gt;
} if (t1 < t2) {
return lt;
}
}
return 0;
}
int bn_less_than_words(const BN_ULONG *a, const BN_ULONG *b, size_t len) {
return bn_cmp_words_consttime(a, len, b, len) < 0;
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) {
int i;
BN_ULONG aa, bb;
aa = a[n - 1];
bb = b[n - 1];
if (aa != bb) {
return (aa > bb) ? 1 : -1;
}
for (i = n - 2; i >= 0; i--) {
aa = a[i];
bb = b[i];
if (aa != bb) {
return (aa > bb) ? 1 : -1;
}
}
return 0;
}
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) {
int n, i;
n = cl - 1;
if (dl < 0) {
for (i = dl; i < 0; i++) {
if (b[n - i] != 0) {
return -1; // a < b
}
}
}
if (dl > 0) {
for (i = dl; i > 0; i--) {
if (a[n + i] != 0) {
return 1; // a > b
}
}
}
return bn_cmp_words(a, b, cl);
}
int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) {
switch (bn_minimal_width(bn)) {
switch (bn->top) {
case 1:
return bn->d[0] == w;
case 0:
@@ -143,14 +190,14 @@ int BN_cmp_word(const BIGNUM *a, BN_ULONG b) {
BN_init(&b_bn);
b_bn.d = &b;
b_bn.width = b > 0;
b_bn.top = b > 0;
b_bn.dmax = 1;
b_bn.flags = BN_FLG_STATIC_DATA;
return BN_cmp(a, &b_bn);
}
int BN_is_zero(const BIGNUM *bn) {
return bn_minimal_width(bn) == 0;
return bn->top == 0;
}
int BN_is_one(const BIGNUM *bn) {
@@ -162,39 +209,31 @@ int BN_is_word(const BIGNUM *bn, BN_ULONG w) {
}
int BN_is_odd(const BIGNUM *bn) {
return bn->width > 0 && (bn->d[0] & 1) == 1;
return bn->top > 0 && (bn->d[0] & 1) == 1;
}
int BN_is_pow2(const BIGNUM *bn) {
int width = bn_minimal_width(bn);
if (width == 0 || bn->neg) {
if (bn->top == 0 || bn->neg) {
return 0;
}
for (int i = 0; i < width - 1; i++) {
for (int i = 0; i < bn->top - 1; i++) {
if (bn->d[i] != 0) {
return 0;
}
}
return 0 == (bn->d[width-1] & (bn->d[width-1] - 1));
return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1));
}
int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
BN_ULONG mask = 0;
// If |a| or |b| has more words than the other, all those words must be zero.
for (int i = a->width; i < b->width; i++) {
mask |= b->d[i];
if (a->top != b->top) {
return 0;
}
for (int i = b->width; i < a->width; i++) {
mask |= a->d[i];
}
// Common words must match.
int min = a->width < b->width ? a->width : b->width;
for (int i = 0; i < min; i++) {
mask |= (a->d[i] ^ b->d[i]);
}
// The sign bit must match.
mask |= (a->neg ^ b->neg);
return mask == 0;
int limbs_are_equal =
CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0;
return constant_time_select_int(constant_time_eq_int(a->neg, b->neg),
limbs_are_equal, 0);
}
+167 -250
View File
@@ -128,7 +128,7 @@ static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
}
ret = q << BN_BITS4;
h = (h << BN_BITS4) | (l >> BN_BITS4);
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
l = (l & BN_MASK2l) << BN_BITS4;
}
@@ -155,18 +155,18 @@ static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
//
// These issues aren't specific to x86 and x86_64, so it might be worthwhile
// to add more assembly language implementations.
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && \
(defined(__GNUC__) || defined(__clang__))
__asm__ volatile("divl %4"
: "=a"(*quotient_out), "=d"(*rem_out)
: "a"(n1), "d"(n0), "rm"(d0)
: "cc");
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
(defined(__GNUC__) || defined(__clang__))
__asm__ volatile("divq %4"
: "=a"(*quotient_out), "=d"(*rem_out)
: "a"(n1), "d"(n0), "rm"(d0)
: "cc");
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__)
__asm__ volatile (
"divl %4"
: "=a"(*quotient_out), "=d"(*rem_out)
: "a"(n1), "d"(n0), "rm"(d0)
: "cc" );
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
__asm__ volatile (
"divq %4"
: "=a"(*quotient_out), "=d"(*rem_out)
: "a"(n1), "d"(n0), "rm"(d0)
: "cc" );
#else
#if defined(BN_ULLONG)
BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
@@ -178,40 +178,29 @@ static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
#endif
}
// BN_div computes "quotient := numerator / divisor", rounding towards zero,
// and sets up |rem| such that "quotient * divisor + rem = numerator" holds.
//
// BN_div computes dv := num / divisor, rounding towards
// zero, and sets up rm such that dv*divisor + rm = num holds.
// Thus:
//
// quotient->neg == numerator->neg ^ divisor->neg
// (unless the result is zero)
// rem->neg == numerator->neg
// (unless the remainder is zero)
//
// If |quotient| or |rem| is NULL, the respective value is not returned.
// dv->neg == num->neg ^ divisor->neg (unless the result is zero)
// rm->neg == num->neg (unless the remainder is zero)
// If 'dv' or 'rm' is NULL, the respective value is not returned.
//
// This was specifically designed to contain fewer branches that may leak
// sensitive information; see "New Branch Prediction Vulnerabilities in OpenSSL
// and Necessary Software Countermeasures" by Onur Acıçmez, Shay Gueron, and
// Jean-Pierre Seifert.
int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator,
const BIGNUM *divisor, BN_CTX *ctx) {
int norm_shift, loop;
BIGNUM wnum;
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
BN_CTX *ctx) {
int norm_shift, i, loop;
BIGNUM *tmp, wnum, *snum, *sdiv, *res;
BN_ULONG *resp, *wnump;
BN_ULONG d0, d1;
int num_n, div_n;
// This function relies on the historical minimal-width |BIGNUM| invariant.
// It is already not constant-time (constant-time reductions should use
// Montgomery logic), so we shrink all inputs and intermediate values to
// retain the previous behavior.
// Invalid zero-padding would have particularly bad consequences.
int numerator_width = bn_minimal_width(numerator);
int divisor_width = bn_minimal_width(divisor);
if ((numerator_width > 0 && numerator->d[numerator_width - 1] == 0) ||
(divisor_width > 0 && divisor->d[divisor_width - 1] == 0)) {
// Invalid zero-padding would have particularly bad consequences
// so don't just rely on bn_check_top() here
if ((num->top > 0 && num->d[num->top - 1] == 0) ||
(divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) {
OPENSSL_PUT_ERROR(BN, BN_R_NOT_INITIALIZED);
return 0;
}
@@ -222,66 +211,63 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator,
}
BN_CTX_start(ctx);
BIGNUM *tmp = BN_CTX_get(ctx);
BIGNUM *snum = BN_CTX_get(ctx);
BIGNUM *sdiv = BN_CTX_get(ctx);
BIGNUM *res = NULL;
if (quotient == NULL) {
tmp = BN_CTX_get(ctx);
snum = BN_CTX_get(ctx);
sdiv = BN_CTX_get(ctx);
if (dv == NULL) {
res = BN_CTX_get(ctx);
} else {
res = quotient;
res = dv;
}
if (sdiv == NULL || res == NULL) {
if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL) {
goto err;
}
// First we normalise the numbers
norm_shift = BN_BITS2 - (BN_num_bits(divisor) % BN_BITS2);
if (!BN_lshift(sdiv, divisor, norm_shift)) {
norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2);
if (!(BN_lshift(sdiv, divisor, norm_shift))) {
goto err;
}
bn_set_minimal_width(sdiv);
sdiv->neg = 0;
norm_shift += BN_BITS2;
if (!BN_lshift(snum, numerator, norm_shift)) {
if (!(BN_lshift(snum, num, norm_shift))) {
goto err;
}
bn_set_minimal_width(snum);
snum->neg = 0;
// Since we don't want to have special-case logic for the case where snum is
// larger than sdiv, we pad snum with enough zeroes without changing its
// value.
if (snum->width <= sdiv->width + 1) {
if (!bn_wexpand(snum, sdiv->width + 2)) {
if (snum->top <= sdiv->top + 1) {
if (!bn_wexpand(snum, sdiv->top + 2)) {
goto err;
}
for (int i = snum->width; i < sdiv->width + 2; i++) {
for (i = snum->top; i < sdiv->top + 2; i++) {
snum->d[i] = 0;
}
snum->width = sdiv->width + 2;
snum->top = sdiv->top + 2;
} else {
if (!bn_wexpand(snum, snum->width + 1)) {
if (!bn_wexpand(snum, snum->top + 1)) {
goto err;
}
snum->d[snum->width] = 0;
snum->width++;
snum->d[snum->top] = 0;
snum->top++;
}
div_n = sdiv->width;
num_n = snum->width;
div_n = sdiv->top;
num_n = snum->top;
loop = num_n - div_n;
// Lets setup a 'window' into snum
// This is the part that corresponds to the current
// 'area' being divided
wnum.neg = 0;
wnum.d = &(snum->d[loop]);
wnum.width = div_n;
// only needed when BN_ucmp messes up the values between width and max
wnum.top = div_n;
// only needed when BN_ucmp messes up the values between top and max
wnum.dmax = snum->dmax - loop; // so we don't step out of bounds
// Get the top 2 words of sdiv
// div_n=sdiv->width;
// div_n=sdiv->top;
d0 = sdiv->d[div_n - 1];
d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];
@@ -289,31 +275,31 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator,
wnump = &(snum->d[num_n - 1]);
// Setup to 'res'
res->neg = (numerator->neg ^ divisor->neg);
if (!bn_wexpand(res, loop + 1)) {
res->neg = (num->neg ^ divisor->neg);
if (!bn_wexpand(res, (loop + 1))) {
goto err;
}
res->width = loop - 1;
res->top = loop - 1;
resp = &(res->d[loop - 1]);
// space for temp
if (!bn_wexpand(tmp, div_n + 1)) {
if (!bn_wexpand(tmp, (div_n + 1))) {
goto err;
}
// if res->width == 0 then clear the neg value otherwise decrease
// if res->top == 0 then clear the neg value otherwise decrease
// the resp pointer
if (res->width == 0) {
if (res->top == 0) {
res->neg = 0;
} else {
resp--;
}
for (int i = 0; i < loop - 1; i++, wnump--, resp--) {
for (i = 0; i < loop - 1; i++, wnump--, resp--) {
BN_ULONG q, l0;
// the first part of the loop uses the top two words of snum and sdiv to
// calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv
BN_ULONG n0, n1, rm = 0;
BN_ULONG n0, n1, rem = 0;
n0 = wnump[0];
n1 = wnump[-1];
@@ -321,18 +307,18 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator,
q = BN_MASK2;
} else {
// n0 < d0
bn_div_rem_words(&q, &rm, n0, n1, d0);
bn_div_rem_words(&q, &rem, n0, n1, d0);
#ifdef BN_ULLONG
BN_ULLONG t2 = (BN_ULLONG)d1 * q;
for (;;) {
if (t2 <= ((((BN_ULLONG)rm) << BN_BITS2) | wnump[-2])) {
if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
break;
}
q--;
rm += d0;
if (rm < d0) {
break; // don't let rm overflow
rem += d0;
if (rem < d0) {
break; // don't let rem overflow
}
t2 -= d1;
}
@@ -340,14 +326,13 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator,
BN_ULONG t2l, t2h;
BN_UMULT_LOHI(t2l, t2h, d1, q);
for (;;) {
if (t2h < rm ||
(t2h == rm && t2l <= wnump[-2])) {
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
break;
}
q--;
rm += d0;
if (rm < d0) {
break; // don't let rm overflow
rem += d0;
if (rem < d0) {
break; // don't let rem overflow
}
if (t2l < d1) {
t2h--;
@@ -378,22 +363,19 @@ int BN_div(BIGNUM *quotient, BIGNUM *rem, const BIGNUM *numerator,
// store part of the result
*resp = q;
}
bn_set_minimal_width(snum);
if (rem != NULL) {
// Keep a copy of the neg flag in numerator because if |rem| == |numerator|
// |BN_rshift| will overwrite it.
int neg = numerator->neg;
if (!BN_rshift(rem, snum, norm_shift)) {
bn_correct_top(snum);
if (rm != NULL) {
// Keep a copy of the neg flag in num because if rm==num
// BN_rshift() will overwrite it.
int neg = num->neg;
if (!BN_rshift(rm, snum, norm_shift)) {
goto err;
}
if (!BN_is_zero(rem)) {
rem->neg = neg;
if (!BN_is_zero(rm)) {
rm->neg = neg;
}
}
bn_set_minimal_width(res);
bn_correct_top(res);
BN_CTX_end(ctx);
return 1;
@@ -414,78 +396,6 @@ int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) {
return (d->neg ? BN_sub : BN_add)(r, r, d);
}
// bn_mod_sub_words sets |r| to |a| - |b| (mod |m|), using |tmp| as scratch
// space. Each array is |num| words long. |a| and |b| must be < |m|. Any pair of
// |r|, |a|, and |b| may alias.
static void bn_mod_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
const BN_ULONG *m, BN_ULONG *tmp, size_t num) {
// r = a - b
BN_ULONG borrow = bn_sub_words(r, a, b, num);
// tmp = a - b + m
bn_add_words(tmp, r, m, num);
bn_select_words(r, 0 - borrow, tmp /* r < 0 */, r /* r >= 0 */, num);
}
// bn_mod_add_words sets |r| to |a| + |b| (mod |m|), using |tmp| as scratch
// space. Each array is |num| words long. |a| and |b| must be < |m|. Any pair of
// |r|, |a|, and |b| may alias.
static void bn_mod_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
const BN_ULONG *m, BN_ULONG *tmp, size_t num) {
// tmp = a + b. Note the result fits in |num|+1 words. We store the extra word
// in |carry|.
BN_ULONG carry = bn_add_words(tmp, a, b, num);
// r = a + b - m. We use |bn_sub_words| to perform the bulk of the
// subtraction, and then apply the borrow to |carry|.
carry -= bn_sub_words(r, tmp, m, num);
// |a| and |b| were both fully-reduced, so we know:
//
// 0 + 0 - m <= r < m + m - m
// -m <= r < m
//
// If 0 <= |r| < |m|, |r| fits in |num| words and |carry| is zero. We then
// wish to select |r| as the answer. Otherwise -m <= r < 0 and we wish to
// return |r| + |m|, or |tmp|. |carry| must then be -1 or all ones. In both
// cases, |carry| is a suitable input to |bn_select_words|.
//
// Although |carry| may be one if |bn_add_words| returns one and
// |bn_sub_words| returns zero, this would give |r| > |m|, which violates are
// input assumptions.
assert(carry == 0 || carry == (BN_ULONG)-1);
bn_select_words(r, carry, tmp /* r < 0 */, r /* r >= 0 */, num);
}
static BIGNUM *bn_scratch_space_from_ctx(size_t width, BN_CTX *ctx) {
BIGNUM *ret = BN_CTX_get(ctx);
if (ret == NULL ||
!bn_wexpand(ret, width)) {
return NULL;
}
ret->neg = 0;
ret->width = width;
return ret;
}
// bn_resized_from_ctx returns |bn| with width at least |width| or NULL on
// error. This is so it may be used with low-level "words" functions. If
// necessary, it allocates a new |BIGNUM| with a lifetime of the current scope
// in |ctx|, so the caller does not need to explicitly free it. |bn| must fit in
// |width| words.
static const BIGNUM *bn_resized_from_ctx(const BIGNUM *bn, size_t width,
BN_CTX *ctx) {
if ((size_t)bn->width >= width) {
// Any excess words must be zero.
assert(bn_fits_in_words(bn, width));
return bn;
}
BIGNUM *ret = bn_scratch_space_from_ctx(width, ctx);
if (ret == NULL ||
!BN_copy(ret, bn) ||
!bn_resize_words(ret, width)) {
return NULL;
}
return ret;
}
int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx) {
if (!BN_add(r, a, b)) {
@@ -496,27 +406,13 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m) {
BN_CTX *ctx = BN_CTX_new();
int ok = ctx != NULL &&
bn_mod_add_quick_ctx(r, a, b, m, ctx);
BN_CTX_free(ctx);
return ok;
}
int bn_mod_add_quick_ctx(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m, BN_CTX *ctx) {
BN_CTX_start(ctx);
a = bn_resized_from_ctx(a, m->width, ctx);
b = bn_resized_from_ctx(b, m->width, ctx);
BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
int ok = a != NULL && b != NULL && tmp != NULL &&
bn_wexpand(r, m->width);
if (ok) {
bn_mod_add_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
r->width = m->width;
if (!BN_uadd(r, a, b)) {
return 0;
}
BN_CTX_end(ctx);
return ok;
if (BN_ucmp(r, m) >= 0) {
return BN_usub(r, r, m);
}
return 1;
}
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
@@ -527,29 +423,17 @@ int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
return BN_nnmod(r, r, m, ctx);
}
int bn_mod_sub_quick_ctx(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m, BN_CTX *ctx) {
BN_CTX_start(ctx);
a = bn_resized_from_ctx(a, m->width, ctx);
b = bn_resized_from_ctx(b, m->width, ctx);
BIGNUM *tmp = bn_scratch_space_from_ctx(m->width, ctx);
int ok = a != NULL && b != NULL && tmp != NULL &&
bn_wexpand(r, m->width);
if (ok) {
bn_mod_sub_words(r->d, a->d, b->d, m->d, tmp->d, m->width);
r->width = m->width;
}
BN_CTX_end(ctx);
return ok;
}
// BN_mod_sub variant that may be used if both a and b are non-negative
// and less than m
int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m) {
BN_CTX *ctx = BN_CTX_new();
int ok = ctx != NULL &&
bn_mod_sub_quick_ctx(r, a, b, m, ctx);
BN_CTX_free(ctx);
return ok;
if (!BN_sub(r, a, b)) {
return 0;
}
if (r->neg) {
return BN_add(r, r, m);
}
return 1;
}
int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
@@ -610,31 +494,56 @@ int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
abs_m->neg = 0;
}
ret = bn_mod_lshift_quick_ctx(r, r, n, (abs_m ? abs_m : m), ctx);
ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m));
BN_free(abs_m);
return ret;
}
int bn_mod_lshift_quick_ctx(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
BN_CTX *ctx) {
if (!BN_copy(r, a)) {
return 0;
}
for (int i = 0; i < n; i++) {
if (!bn_mod_lshift1_quick_ctx(r, r, m, ctx)) {
int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) {
if (r != a) {
if (BN_copy(r, a) == NULL) {
return 0;
}
}
return 1;
}
int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) {
BN_CTX *ctx = BN_CTX_new();
int ok = ctx != NULL &&
bn_mod_lshift_quick_ctx(r, a, n, m, ctx);
BN_CTX_free(ctx);
return ok;
while (n > 0) {
int max_shift;
// 0 < r < m
max_shift = BN_num_bits(m) - BN_num_bits(r);
// max_shift >= 0
if (max_shift < 0) {
OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED);
return 0;
}
if (max_shift > n) {
max_shift = n;
}
if (max_shift) {
if (!BN_lshift(r, r, max_shift)) {
return 0;
}
n -= max_shift;
} else {
if (!BN_lshift1(r, r)) {
return 0;
}
--n;
}
// BN_num_bits(r) <= BN_num_bits(m)
if (BN_cmp(r, m) >= 0) {
if (!BN_sub(r, r, m)) {
return 0;
}
}
}
return 1;
}
int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
@@ -645,29 +554,29 @@ int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) {
return BN_nnmod(r, r, m, ctx);
}
int bn_mod_lshift1_quick_ctx(BIGNUM *r, const BIGNUM *a, const BIGNUM *m,
BN_CTX *ctx) {
return bn_mod_add_quick_ctx(r, a, a, m, ctx);
}
int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) {
BN_CTX *ctx = BN_CTX_new();
int ok = ctx != NULL &&
bn_mod_lshift1_quick_ctx(r, a, m, ctx);
BN_CTX_free(ctx);
return ok;
if (!BN_lshift1(r, a)) {
return 0;
}
if (BN_cmp(r, m) >= 0) {
return BN_sub(r, r, m);
}
return 1;
}
BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
BN_ULONG ret = 0;
int i, j;
w &= BN_MASK2;
if (!w) {
// actually this an error (division by zero)
return (BN_ULONG) - 1;
}
if (a->width == 0) {
if (a->top == 0) {
return 0;
}
@@ -678,22 +587,29 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
return (BN_ULONG) - 1;
}
for (i = a->width - 1; i >= 0; i--) {
for (i = a->top - 1; i >= 0; i--) {
BN_ULONG l = a->d[i];
BN_ULONG d;
BN_ULONG unused_rem;
bn_div_rem_words(&d, &unused_rem, ret, l, w);
ret = l - (d * w);
ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
a->d[i] = d;
}
bn_set_minimal_width(a);
if ((a->top > 0) && (a->d[a->top - 1] == 0)) {
a->top--;
}
if (a->top == 0) {
a->neg = 0;
}
ret >>= j;
return ret;
}
BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
#ifndef BN_CAN_DIVIDE_ULLONG
#ifndef BN_ULLONG
BN_ULONG ret = 0;
#else
BN_ULLONG ret = 0;
@@ -704,9 +620,9 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
return (BN_ULONG) -1;
}
#ifndef BN_CAN_DIVIDE_ULLONG
// If |w| is too long and we don't have |BN_ULLONG| division then we need to
// fall back to using |BN_div_word|.
#ifndef BN_ULLONG
// If |w| is too long and we don't have |BN_ULLONG| then we need to fall back
// to using |BN_div_word|.
if (w > ((BN_ULONG)1 << BN_BITS4)) {
BIGNUM *tmp = BN_dup(a);
if (tmp == NULL) {
@@ -718,8 +634,9 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
}
#endif
for (i = a->width - 1; i >= 0; i--) {
#ifndef BN_CAN_DIVIDE_ULLONG
w &= BN_MASK2;
for (i = a->top - 1; i >= 0; i--) {
#ifndef BN_ULLONG
ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w;
ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
#else
@@ -730,7 +647,7 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
}
int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
if (e == 0 || a->width == 0) {
if (e == 0 || a->top == 0) {
BN_zero(r);
return 1;
}
@@ -738,7 +655,7 @@ int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
size_t num_words = 1 + ((e - 1) / BN_BITS2);
// If |a| definitely has less than |e| bits, just BN_copy.
if ((size_t) a->width < num_words) {
if ((size_t) a->top < num_words) {
return BN_copy(r, a) != NULL;
}
@@ -759,8 +676,8 @@ int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
// Fill in the remaining fields of |r|.
r->neg = a->neg;
r->width = (int) num_words;
bn_set_minimal_width(r);
r->top = (int) num_words;
bn_correct_top(r);
return 1;
}
@@ -782,27 +699,27 @@ int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
}
// Clear the upper words of |r|.
OPENSSL_memset(&r->d[r->width], 0, (num_words - r->width) * BN_BYTES);
OPENSSL_memset(&r->d[r->top], 0, (num_words - r->top) * BN_BYTES);
// Set parameters of |r|.
r->neg = 0;
r->width = (int) num_words;
r->top = (int) num_words;
// Now, invert every word. The idea here is that we want to compute 2^e-|x|,
// which is actually equivalent to the twos-complement representation of |x|
// in |e| bits, which is -x = ~x + 1.
for (int i = 0; i < r->width; i++) {
for (int i = 0; i < r->top; i++) {
r->d[i] = ~r->d[i];
}
// If our exponent doesn't span the top word, we have to mask the rest.
size_t top_word_exponent = e % BN_BITS2;
if (top_word_exponent != 0) {
r->d[r->width - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
r->d[r->top - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
}
// Keep the minimal-width invariant for |BIGNUM|.
bn_set_minimal_width(r);
// Keep the correct_top invariant for BN_add.
bn_correct_top(r);
// Finally, add one, for the reason described above.
return BN_add(r, r, BN_value_one());
+124 -247
View File
@@ -188,6 +188,9 @@ err:
return ret;
}
// maximum precomputation table size for *variable* sliding windows
#define TABLE_SIZE 32
typedef struct bn_recp_ctx_st {
BIGNUM N; // the divisor
BIGNUM Nr; // the reciprocal
@@ -390,8 +393,8 @@ err:
return ret;
}
// BN_window_bits_for_exponent_size returns sliding window size for mod_exp with
// a |b| bit exponent.
// BN_window_bits_for_exponent_size -- macro for sliding window mod_exp
// functions
//
// For window size 'w' (w >= 2) and a random 'b' bits exponent, the number of
// multiplications is a constant plus on average
@@ -413,35 +416,11 @@ err:
//
// (with draws in between). Very small exponents are often selected
// with low Hamming weight, so we use w = 1 for b <= 23.
static int BN_window_bits_for_exponent_size(int b) {
if (b > 671) {
return 6;
}
if (b > 239) {
return 5;
}
if (b > 79) {
return 4;
}
if (b > 23) {
return 3;
}
return 1;
}
// TABLE_SIZE is the maximum precomputation table size for *variable* sliding
// windows. This must be 2^(max_window - 1), where max_window is the largest
// value returned from |BN_window_bits_for_exponent_size|.
#define TABLE_SIZE 32
// TABLE_BITS_SMALL is the smallest value returned from
// |BN_window_bits_for_exponent_size| when |b| is at most |BN_BITS2| *
// |BN_SMALL_MAX_WORDS| words.
#define TABLE_BITS_SMALL 5
// TABLE_SIZE_SMALL is the same as |TABLE_SIZE|, but when |b| is at most
// |BN_BITS2| * |BN_SMALL_MAX_WORDS|.
#define TABLE_SIZE_SMALL (1 << (TABLE_BITS_SMALL - 1))
#define BN_window_bits_for_exponent_size(b) \
((b) > 671 ? 6 : \
(b) > 239 ? 5 : \
(b) > 79 ? 4 : \
(b) > 23 ? 3 : 1)
static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx) {
@@ -522,7 +501,7 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
int wvalue; // The 'value' of the window
int wend; // The bottom bit of the window
if (!BN_is_bit_set(p, wstart)) {
if (BN_is_bit_set(p, wstart) == 0) {
if (!start) {
if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) {
goto err;
@@ -594,11 +573,19 @@ int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont) {
int i, j, bits, ret = 0, wstart, window;
int start = 1;
BIGNUM *d, *r;
const BIGNUM *aa;
// Table of variables obtained from 'ctx'
BIGNUM *val[TABLE_SIZE];
BN_MONT_CTX *new_mont = NULL;
if (!BN_is_odd(m)) {
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
int bits = BN_num_bits(p);
bits = BN_num_bits(p);
if (bits == 0) {
// x**0 mod 1 is still zero.
if (BN_is_one(m)) {
@@ -608,13 +595,9 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
return BN_one(rr);
}
int ret = 0;
BIGNUM *val[TABLE_SIZE];
BN_MONT_CTX *new_mont = NULL;
BN_CTX_start(ctx);
BIGNUM *d = BN_CTX_get(ctx);
BIGNUM *r = BN_CTX_get(ctx);
d = BN_CTX_get(ctx);
r = BN_CTX_get(ctx);
val[0] = BN_CTX_get(ctx);
if (!d || !r || !val[0]) {
goto err;
@@ -622,14 +605,13 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// Allocate a montgomery context if it was not supplied by the caller.
if (mont == NULL) {
new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
if (new_mont == NULL) {
new_mont = BN_MONT_CTX_new();
if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
goto err;
}
mont = new_mont;
}
const BIGNUM *aa;
if (a->neg || BN_ucmp(a, m) >= 0) {
if (!BN_nnmod(val[0], a, m, ctx)) {
goto err;
@@ -644,37 +626,53 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
ret = 1;
goto err;
}
// We exponentiate by looking at sliding windows of the exponent and
// precomputing powers of |aa|. Windows may be shifted so they always end on a
// set bit, so only precompute odd powers. We compute val[i] = aa^(2*i + 1)
// for i = 0 to 2^(window-1), all in Montgomery form.
int window = BN_window_bits_for_exponent_size(bits);
if (!BN_to_montgomery(val[0], aa, mont, ctx)) {
goto err;
goto err; // 1
}
window = BN_window_bits_for_exponent_size(bits);
if (window > 1) {
if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx)) {
goto err;
goto err; // 2
}
for (int i = 1; i < 1 << (window - 1); i++) {
val[i] = BN_CTX_get(ctx);
if (val[i] == NULL ||
j = 1 << (window - 1);
for (i = 1; i < j; i++) {
if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
!BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx)) {
goto err;
}
}
}
if (!bn_one_to_montgomery(r, mont, ctx)) {
start = 1; // This is used to avoid multiplication etc
// when there is only the value '1' in the
// buffer.
wstart = bits - 1; // The top bit of the window
j = m->top; // borrow j
if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
if (!bn_wexpand(r, j)) {
goto err;
}
// 2^(top*BN_BITS2) - m
r->d[0] = (0 - m->d[0]) & BN_MASK2;
for (i = 1; i < j; i++) {
r->d[i] = (~m->d[i]) & BN_MASK2;
}
r->top = j;
// Upper words will be zero if the corresponding words of 'm'
// were 0xfff[...], so decrement r->top accordingly.
bn_correct_top(r);
} else if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) {
goto err;
}
int r_is_one = 1;
int wstart = bits - 1; // The top bit of the window.
for (;;) {
if (!BN_is_bit_set(p, wstart)) {
if (!r_is_one && !BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
int wvalue; // The 'value' of the window
int wend; // The bottom bit of the window
if (BN_is_bit_set(p, wstart) == 0) {
if (!start && !BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
goto err;
}
if (wstart == 0) {
@@ -684,37 +682,44 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
continue;
}
// We now have wstart on a set bit. Find the largest window we can use.
int wvalue = 1;
int wsize = 0;
for (int i = 1; i < window && i <= wstart; i++) {
// We now have wstart on a 'set' bit, we now need to work out how bit a
// window to do. To do this we need to scan forward until the last set bit
// before the end of the window
wvalue = 1;
wend = 0;
for (i = 1; i < window; i++) {
if (wstart - i < 0) {
break;
}
if (BN_is_bit_set(p, wstart - i)) {
wvalue <<= (i - wsize);
wvalue <<= (i - wend);
wvalue |= 1;
wsize = i;
wend = i;
}
}
// Shift |r| to the end of the window.
if (!r_is_one) {
for (int i = 0; i < wsize + 1; i++) {
// wend is the size of the current window
j = wend + 1;
// add the 'bytes above'
if (!start) {
for (i = 0; i < j; i++) {
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
goto err;
}
}
}
assert(wvalue & 1);
assert(wvalue < (1 << window));
// wvalue will be an odd number < 2^window
if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx)) {
goto err;
}
r_is_one = 0;
if (wstart == wsize) {
// move the 'window' down further
wstart -= wend + 1;
start = 0;
if (wstart < 0) {
break;
}
wstart -= wsize + 1;
}
if (!BN_from_montgomery(rr, r, mont, ctx)) {
@@ -728,161 +733,25 @@ err:
return ret;
}
int bn_mod_exp_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_ULONG *p, size_t num_p,
const BN_MONT_CTX *mont) {
size_t num_n = mont->N.width;
if (num_n != num_a || num_n != num_r || num_n > BN_SMALL_MAX_WORDS) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!BN_is_odd(&mont->N)) {
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
unsigned bits = 0;
if (num_p != 0) {
bits = BN_num_bits_word(p[num_p - 1]) + (num_p - 1) * BN_BITS2;
}
if (bits == 0) {
OPENSSL_memset(r, 0, num_r * sizeof(BN_ULONG));
if (!BN_is_one(&mont->N)) {
r[0] = 1;
}
return 1;
}
// We exponentiate by looking at sliding windows of the exponent and
// precomputing powers of |a|. Windows may be shifted so they always end on a
// set bit, so only precompute odd powers. We compute val[i] = a^(2*i + 1) for
// i = 0 to 2^(window-1), all in Montgomery form.
unsigned window = BN_window_bits_for_exponent_size(bits);
if (window > TABLE_BITS_SMALL) {
window = TABLE_BITS_SMALL; // Tolerate excessively large |p|.
}
int ret = 0;
BN_ULONG val[TABLE_SIZE_SMALL][BN_SMALL_MAX_WORDS];
OPENSSL_memcpy(val[0], a, num_n * sizeof(BN_ULONG));
if (window > 1) {
BN_ULONG d[BN_SMALL_MAX_WORDS];
if (!bn_mod_mul_montgomery_small(d, num_n, val[0], num_n, val[0], num_n,
mont)) {
goto err;
}
for (unsigned i = 1; i < 1u << (window - 1); i++) {
if (!bn_mod_mul_montgomery_small(val[i], num_n, val[i - 1], num_n, d,
num_n, mont)) {
goto err;
}
}
}
if (!bn_one_to_montgomery_small(r, num_r, mont)) {
goto err;
}
int r_is_one = 1;
unsigned wstart = bits - 1; // The top bit of the window.
for (;;) {
if (!bn_is_bit_set_words(p, num_p, wstart)) {
if (!r_is_one &&
!bn_mod_mul_montgomery_small(r, num_r, r, num_r, r, num_r, mont)) {
goto err;
}
if (wstart == 0) {
break;
}
wstart--;
continue;
}
// We now have wstart on a set bit. Find the largest window we can use.
unsigned wvalue = 1;
unsigned wsize = 0;
for (unsigned i = 1; i < window && i <= wstart; i++) {
if (bn_is_bit_set_words(p, num_p, wstart - i)) {
wvalue <<= (i - wsize);
wvalue |= 1;
wsize = i;
}
}
// Shift |r| to the end of the window.
if (!r_is_one) {
for (unsigned i = 0; i < wsize + 1; i++) {
if (!bn_mod_mul_montgomery_small(r, num_r, r, num_r, r, num_r, mont)) {
goto err;
}
}
}
assert(wvalue & 1);
assert(wvalue < (1u << window));
if (!bn_mod_mul_montgomery_small(r, num_r, r, num_r, val[wvalue >> 1],
num_n, mont)) {
goto err;
}
r_is_one = 0;
if (wstart == wsize) {
break;
}
wstart -= wsize + 1;
}
ret = 1;
err:
OPENSSL_cleanse(val, sizeof(val));
return ret;
}
int bn_mod_inverse_prime_mont_small(BN_ULONG *r, size_t num_r,
const BN_ULONG *a, size_t num_a,
const BN_MONT_CTX *mont) {
const BN_ULONG *p = mont->N.d;
size_t num_p = mont->N.width;
if (num_p > BN_SMALL_MAX_WORDS || num_p == 0) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
// Per Fermat's Little Theorem, a^-1 = a^(p-2) (mod p) for p prime.
BN_ULONG p_minus_two[BN_SMALL_MAX_WORDS];
OPENSSL_memcpy(p_minus_two, p, num_p * sizeof(BN_ULONG));
if (p_minus_two[0] >= 2) {
p_minus_two[0] -= 2;
} else {
p_minus_two[0] -= 2;
for (size_t i = 1; i < num_p; i++) {
if (p_minus_two[i]-- != 0) {
break;
}
}
}
return bn_mod_exp_mont_small(r, num_r, a, num_a, p_minus_two, num_p, mont);
}
// |BN_mod_exp_mont_consttime| stores the precomputed powers in a specific
// BN_mod_exp_mont_consttime() stores the precomputed powers in a specific
// layout so that accessing any of these table values shows the same access
// pattern as far as cache lines are concerned. The following functions are
// used to transfer a BIGNUM from/to that table.
static void copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf,
int idx, int window) {
static int copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx,
int window) {
int i, j;
const int width = 1 << window;
BN_ULONG *table = (BN_ULONG *) buf;
if (top > b->width) {
top = b->width; // this works because 'buf' is explicitly zeroed
if (top > b->top) {
top = b->top; // this works because 'buf' is explicitly zeroed
}
for (i = 0, j = idx; i < top; i++, j += width) {
table[j] = b->d[i];
}
return 1;
}
static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
@@ -930,7 +799,8 @@ static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
}
}
b->width = top;
b->top = top;
bn_correct_top(b);
return 1;
}
@@ -980,7 +850,8 @@ static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
const BN_MONT_CTX *mont) {
int i, ret = 0, window, wvalue;
int i, bits, ret = 0, window, wvalue;
int top;
BN_MONT_CTX *new_mont = NULL;
int numPowers;
@@ -995,10 +866,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
return 0;
}
// Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak
// whether the top bits are zero.
int max_bits = p->width * BN_BITS2;
int bits = max_bits;
top = m->top;
bits = BN_num_bits(p);
if (bits == 0) {
// x**0 mod 1 is still zero.
if (BN_is_one(m)) {
@@ -1010,17 +880,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// Allocate a montgomery context if it was not supplied by the caller.
if (mont == NULL) {
new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
if (new_mont == NULL) {
new_mont = BN_MONT_CTX_new();
if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
goto err;
}
mont = new_mont;
}
// Use the width in |mont->N|, rather than the copy in |m|. The assembly
// implementation assumes it can use |top| to size R.
int top = mont->N.width;
if (a->neg || BN_ucmp(a, m) >= 0) {
new_a = BN_new();
if (new_a == NULL ||
@@ -1034,14 +900,15 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// If the size of the operands allow it, perform the optimized
// RSAZ exponentiation. For further information see
// crypto/bn/rsaz_exp.c and accompanying assembly modules.
if ((16 == a->width) && (16 == p->width) && (BN_num_bits(m) == 1024) &&
if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) &&
rsaz_avx2_eligible()) {
if (!bn_wexpand(rr, 16)) {
goto err;
}
RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, mont->n0[0]);
rr->width = 16;
rr->top = 16;
rr->neg = 0;
bn_correct_top(rr);
ret = 1;
goto err;
}
@@ -1087,12 +954,21 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// lay down tmp and am right after powers table
tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers);
am.d = tmp.d + top;
tmp.width = am.width = 0;
tmp.top = am.top = 0;
tmp.dmax = am.dmax = top;
tmp.neg = am.neg = 0;
tmp.flags = am.flags = BN_FLG_STATIC_DATA;
if (!bn_one_to_montgomery(&tmp, mont, ctx)) {
// prepare a^0 in Montgomery domain
// by Shay Gueron's suggestion
if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
// 2^(top*BN_BITS2) - m
tmp.d[0] = (0 - m->d[0]) & BN_MASK2;
for (i = 1; i < top; i++) {
tmp.d[i] = (~m->d[i]) & BN_MASK2;
}
tmp.top = top;
} else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) {
goto err;
}
@@ -1116,10 +992,10 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// BN_to_montgomery can contaminate words above .top
// [in BN_DEBUG[_DEBUG] build]...
for (i = am.width; i < top; i++) {
for (i = am.top; i < top; i++) {
am.d[i] = 0;
}
for (i = tmp.width; i < top; i++) {
for (i = tmp.top; i < top; i++) {
tmp.d[i] = 0;
}
@@ -1129,7 +1005,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
bn_scatter5(tmp.d, top, powerbuf, 0);
bn_scatter5(am.d, am.width, powerbuf, 1);
bn_scatter5(am.d, am.top, powerbuf, 1);
bn_mul_mont(tmp.d, am.d, am.d, np, n0, top);
bn_scatter5(tmp.d, top, powerbuf, 2);
@@ -1185,6 +1061,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
} else {
const uint8_t *p_bytes = (const uint8_t *)p->d;
int max_bits = p->top * BN_BITS2;
assert(bits < max_bits);
// |p = 0| has been handled as a special case, so |max_bits| is at least
// one word.
@@ -1196,7 +1073,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
// here is the top bit, inclusive.
if (bits - 4 >= max_bits - 8) {
// Read five bits from |bits-4| through |bits|, inclusive.
wvalue = p_bytes[p->width * BN_BYTES - 1];
wvalue = p_bytes[p->top * BN_BYTES - 1];
wvalue >>= (bits - 4) & 7;
wvalue &= 0x1f;
bits -= 5;
@@ -1215,7 +1092,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
tmp.width = top;
tmp.top = top;
bn_correct_top(&tmp);
if (ret) {
if (!BN_copy(rr, &tmp)) {
ret = 0;
@@ -1225,27 +1103,26 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
} else
#endif
{
copy_to_prebuf(&tmp, top, powerbuf, 0, window);
copy_to_prebuf(&am, top, powerbuf, 1, window);
if (!copy_to_prebuf(&tmp, top, powerbuf, 0, window) ||
!copy_to_prebuf(&am, top, powerbuf, 1, window)) {
goto err;
}
// If the window size is greater than 1, then calculate
// val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
// (even powers could instead be computed as (a^(i/2))^2
// to use the slight performance advantage of sqr over mul).
if (window > 1) {
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx)) {
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) ||
!copy_to_prebuf(&tmp, top, powerbuf, 2, window)) {
goto err;
}
copy_to_prebuf(&tmp, top, powerbuf, 2, window);
for (i = 3; i < numPowers; i++) {
// Calculate a^i = a^(i-1) * a
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx)) {
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) ||
!copy_to_prebuf(&tmp, top, powerbuf, i, window)) {
goto err;
}
copy_to_prebuf(&tmp, top, powerbuf, i, window);
}
}
@@ -1329,8 +1206,8 @@ int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
// Allocate a montgomery context if it was not supplied by the caller.
if (mont == NULL) {
new_mont = BN_MONT_CTX_new_for_modulus(m, ctx);
if (new_mont == NULL) {
new_mont = BN_MONT_CTX_new();
if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
goto err;
}
mont = new_mont;
+48 -44
View File
@@ -64,8 +64,7 @@
// This file has two other implementations: x86 assembly language in
// asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c.
#if defined(OPENSSL_NO_ASM) || \
!(defined(OPENSSL_X86) || \
(defined(OPENSSL_X86_64) && (defined(__GNUC__) || defined(__clang__))))
!(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
#ifdef BN_ULLONG
#define mul_add(r, a, w, c) \
@@ -125,11 +124,12 @@
#endif // !BN_ULLONG
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w) {
BN_ULONG c1 = 0;
if (num == 0) {
assert(num >= 0);
if (num <= 0) {
return c1;
}
@@ -153,11 +153,11 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
return c1;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w) {
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
BN_ULONG c1 = 0;
if (num == 0) {
assert(num >= 0);
if (num <= 0) {
return c1;
}
@@ -179,8 +179,9 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
return c1;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, size_t n) {
if (n == 0) {
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
assert(n >= 0);
if (n <= 0) {
return;
}
@@ -203,25 +204,26 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, size_t n) {
#ifdef BN_ULLONG
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
size_t n) {
int n) {
BN_ULLONG ll = 0;
if (n == 0) {
return 0;
assert(n >= 0);
if (n <= 0) {
return (BN_ULONG)0;
}
while (n & ~3) {
ll += (BN_ULLONG)a[0] + b[0];
r[0] = (BN_ULONG)ll;
r[0] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
ll += (BN_ULLONG)a[1] + b[1];
r[1] = (BN_ULONG)ll;
r[1] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
ll += (BN_ULLONG)a[2] + b[2];
r[2] = (BN_ULONG)ll;
r[2] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
ll += (BN_ULLONG)a[3] + b[3];
r[3] = (BN_ULONG)ll;
r[3] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
a += 4;
b += 4;
@@ -230,7 +232,7 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
}
while (n) {
ll += (BN_ULLONG)a[0] + b[0];
r[0] = (BN_ULONG)ll;
r[0] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
a++;
b++;
@@ -243,37 +245,38 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#else // !BN_ULLONG
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
size_t n) {
int n) {
BN_ULONG c, l, t;
if (n == 0) {
assert(n >= 0);
if (n <= 0) {
return (BN_ULONG)0;
}
c = 0;
while (n & ~3) {
t = a[0];
t += c;
t = (t + c) & BN_MASK2;
c = (t < c);
l = t + b[0];
l = (t + b[0]) & BN_MASK2;
c += (l < t);
r[0] = l;
t = a[1];
t += c;
t = (t + c) & BN_MASK2;
c = (t < c);
l = t + b[1];
l = (t + b[1]) & BN_MASK2;
c += (l < t);
r[1] = l;
t = a[2];
t += c;
t = (t + c) & BN_MASK2;
c = (t < c);
l = t + b[2];
l = (t + b[2]) & BN_MASK2;
c += (l < t);
r[2] = l;
t = a[3];
t += c;
t = (t + c) & BN_MASK2;
c = (t < c);
l = t + b[3];
l = (t + b[3]) & BN_MASK2;
c += (l < t);
r[3] = l;
a += 4;
@@ -283,9 +286,9 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
}
while (n) {
t = a[0];
t += c;
t = (t + c) & BN_MASK2;
c = (t < c);
l = t + b[0];
l = (t + b[0]) & BN_MASK2;
c += (l < t);
r[0] = l;
a++;
@@ -299,36 +302,37 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#endif // !BN_ULLONG
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
size_t n) {
int n) {
BN_ULONG t1, t2;
int c = 0;
if (n == 0) {
assert(n >= 0);
if (n <= 0) {
return (BN_ULONG)0;
}
while (n & ~3) {
t1 = a[0];
t2 = b[0];
r[0] = t1 - t2 - c;
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
t1 = a[1];
t2 = b[1];
r[1] = t1 - t2 - c;
r[1] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
t1 = a[2];
t2 = b[2];
r[2] = t1 - t2 - c;
r[2] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
t1 = a[3];
t2 = b[3];
r[3] = t1 - t2 - c;
r[3] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
@@ -340,7 +344,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
while (n) {
t1 = a[0];
t2 = b[0];
r[0] = t1 - t2 - c;
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
@@ -368,7 +372,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
t += (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
(c1) += (hi); \
(c1) = ((c1) + (hi)) & BN_MASK2; \
if ((c1) < hi) { \
(c2)++; \
} \
@@ -381,14 +385,14 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
BN_ULLONG tt = t + (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(tt); \
hi = (BN_ULONG)Hw(tt); \
(c1) += hi; \
(c1) = ((c1) + hi) & BN_MASK2; \
if ((c1) < hi) { \
(c2)++; \
} \
t += (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
(c1) += hi; \
(c1) = ((c1) + hi) & BN_MASK2; \
if ((c1) < hi) { \
(c2)++; \
} \
@@ -401,7 +405,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
t += (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
(c1) += hi; \
(c1) = ((c1) + hi) & BN_MASK2; \
if ((c1) < hi) { \
(c2)++; \
} \
@@ -454,7 +458,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#endif // !BN_ULLONG
void bn_mul_comba8(BN_ULONG r[16], const BN_ULONG a[8], const BN_ULONG b[8]) {
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -556,7 +560,7 @@ void bn_mul_comba8(BN_ULONG r[16], const BN_ULONG a[8], const BN_ULONG b[8]) {
r[15] = c1;
}
void bn_mul_comba4(BN_ULONG r[8], const BN_ULONG a[4], const BN_ULONG b[4]) {
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -594,7 +598,7 @@ void bn_mul_comba4(BN_ULONG r[8], const BN_ULONG a[4], const BN_ULONG b[4]) {
r[7] = c2;
}
void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[8]) {
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -668,7 +672,7 @@ void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[8]) {
r[15] = c1;
}
void bn_sqr_comba4(BN_ULONG r[8], const BN_ULONG a[4]) {
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG c1, c2, c3;
c1 = 0;
+46 -271
View File
@@ -140,45 +140,43 @@ extern "C" {
#if defined(OPENSSL_64_BIT)
#if defined(BORINGSSL_HAS_UINT128)
#if !defined(_MSC_VER)
// MSVC doesn't support two-word integers on 64-bit.
#define BN_ULLONG uint128_t
#if defined(BORINGSSL_CAN_DIVIDE_UINT128)
#define BN_CAN_DIVIDE_ULLONG
#endif
#define BN_ULLONG uint128_t
#endif
#define BN_BITS2 64
#define BN_BYTES 8
#define BN_BITS4 32
#define BN_MASK2 (0xffffffffffffffffUL)
#define BN_MASK2l (0xffffffffUL)
#define BN_MASK2h (0xffffffff00000000UL)
#define BN_MASK2h1 (0xffffffff80000000UL)
#define BN_BITS2 64
#define BN_BYTES 8
#define BN_BITS4 32
#define BN_MASK2 (0xffffffffffffffffUL)
#define BN_MASK2l (0xffffffffUL)
#define BN_MASK2h (0xffffffff00000000UL)
#define BN_MASK2h1 (0xffffffff80000000UL)
#define BN_MONT_CTX_N0_LIMBS 1
#define BN_DEC_CONV (10000000000000000000UL)
#define BN_DEC_NUM 19
#define BN_TBIT (0x8000000000000000UL)
#define BN_DEC_CONV (10000000000000000000UL)
#define BN_DEC_NUM 19
#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo))
#elif defined(OPENSSL_32_BIT)
#define BN_ULLONG uint64_t
#define BN_CAN_DIVIDE_ULLONG
#define BN_BITS2 32
#define BN_BYTES 4
#define BN_BITS4 16
#define BN_MASK2 (0xffffffffUL)
#define BN_MASK2l (0xffffUL)
#define BN_MASK2h1 (0xffff8000UL)
#define BN_MASK2h (0xffff0000UL)
#define BN_ULLONG uint64_t
#define BN_BITS2 32
#define BN_BYTES 4
#define BN_BITS4 16
#define BN_MASK2 (0xffffffffUL)
#define BN_MASK2l (0xffffUL)
#define BN_MASK2h1 (0xffff8000UL)
#define BN_MASK2h (0xffff0000UL)
// On some 32-bit platforms, Montgomery multiplication is done using 64-bit
// arithmetic with SIMD instructions. On such platforms, |BN_MONT_CTX::n0|
// needs to be two words long. Only certain 32-bit platforms actually make use
// of n0[1] and shorter R value would suffice for the others. However,
// currently only the assembly files know which is which.
#define BN_MONT_CTX_N0_LIMBS 2
#define BN_DEC_CONV (1000000000UL)
#define BN_DEC_NUM 9
#define BN_TBIT (0x80000000UL)
#define BN_DEC_CONV (1000000000UL)
#define BN_DEC_NUM 9
#define TOBN(hi, lo) (lo), (hi)
#else
@@ -193,17 +191,13 @@ extern "C" {
}
#if defined(BN_ULLONG)
#define Lw(t) ((BN_ULONG)(t))
#define Hw(t) ((BN_ULONG)((t) >> BN_BITS2))
#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
#endif
// bn_minimal_width returns the minimal value of |bn->top| which fits the
// value of |bn|.
int bn_minimal_width(const BIGNUM *bn);
// bn_set_minimal_width sets |bn->width| to |bn_minimal_width(bn)|. If |bn| is
// zero, |bn->neg| is set to zero.
void bn_set_minimal_width(BIGNUM *bn);
// bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or
// until |top| is zero. If |bn| is zero, |bn->neg| is set to zero.
void bn_correct_top(BIGNUM *bn);
// bn_wexpand ensures that |bn| has at least |words| works of space without
// altering its value. It returns one on success or zero on allocation
@@ -214,106 +208,36 @@ int bn_wexpand(BIGNUM *bn, size_t words);
// than a number of words.
int bn_expand(BIGNUM *bn, size_t bits);
// bn_resize_words adjusts |bn->top| to be |words|. It returns one on success
// and zero on allocation error or if |bn|'s value is too large.
OPENSSL_EXPORT int bn_resize_words(BIGNUM *bn, size_t words);
// bn_select_words sets |r| to |a| if |mask| is all ones or |b| if |mask| is
// all zeros.
void bn_select_words(BN_ULONG *r, BN_ULONG mask, const BN_ULONG *a,
const BN_ULONG *b, size_t num);
// bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
// least significant word first.
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
// bn_fits_in_words returns one if |bn| may be represented in |num| words, plus
// a sign bit, and zero otherwise.
int bn_fits_in_words(const BIGNUM *bn, size_t num);
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
// bn_copy_words copies the value of |bn| to |out| and returns one if the value
// is representable in |num| words. Otherwise, it returns zero.
int bn_copy_words(BN_ULONG *out, size_t num, const BIGNUM *bn);
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
// bn_mul_add_words multiples |ap| by |w|, adds the result to |rp|, and places
// the result in |rp|. |ap| and |rp| must both be |num| words long. It returns
// the carry word of the operation. |ap| and |rp| may be equal but otherwise may
// not alias.
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w);
// bn_cmp_words returns a value less than, equal to or greater than zero if
// the, length |n|, array |a| is less than, equal to or greater than |b|.
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);
// bn_mul_words multiples |ap| by |w| and places the result in |rp|. |ap| and
// |rp| must both be |num| words long. It returns the carry word of the
// operation. |ap| and |rp| may be equal but otherwise may not alias.
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num, BN_ULONG w);
// bn_sqr_words sets |rp[2*i]| and |rp[2*i+1]| to |ap[i]|'s square, for all |i|
// up to |num|. |ap| is an array of |num| words and |rp| an array of |2*num|
// words. |ap| and |rp| may not alias.
//
// This gives the contribution of the |ap[i]*ap[i]| terms when squaring |ap|.
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num);
// bn_add_words adds |ap| to |bp| and places the result in |rp|, each of which
// are |num| words long. It returns the carry bit, which is one if the operation
// overflowed and zero otherwise. Any pair of |ap|, |bp|, and |rp| may be equal
// to each other but otherwise may not alias.
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
size_t num);
// bn_sub_words subtracts |bp| from |ap| and places the result in |rp|. It
// returns the borrow bit, which is one if the computation underflowed and zero
// otherwise. Any pair of |ap|, |bp|, and |rp| may be equal to each other but
// otherwise may not alias.
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
size_t num);
// bn_mul_comba4 sets |r| to the product of |a| and |b|.
void bn_mul_comba4(BN_ULONG r[8], const BN_ULONG a[4], const BN_ULONG b[4]);
// bn_mul_comba8 sets |r| to the product of |a| and |b|.
void bn_mul_comba8(BN_ULONG r[16], const BN_ULONG a[8], const BN_ULONG b[8]);
// bn_sqr_comba8 sets |r| to |a|^2.
void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[4]);
// bn_sqr_comba4 sets |r| to |a|^2.
void bn_sqr_comba4(BN_ULONG r[8], const BN_ULONG a[4]);
// bn_less_than_words returns one if |a| < |b| and zero otherwise, where |a|
// and |b| both are |len| words long. It runs in constant time.
int bn_less_than_words(const BN_ULONG *a, const BN_ULONG *b, size_t len);
// bn_in_range_words returns one if |min_inclusive| <= |a| < |max_exclusive|,
// where |a| and |max_exclusive| both are |len| words long. This function leaks
// which of [0, min_inclusive), [min_inclusive, max_exclusive), and
// [max_exclusive, 2^(BN_BITS2*len)) contains |a|, but otherwise the value of
// |a| is secret.
int bn_in_range_words(const BN_ULONG *a, BN_ULONG min_inclusive,
const BN_ULONG *max_exclusive, size_t len);
// bn_rand_range_words sets |out| to a uniformly distributed random number from
// |min_inclusive| to |max_exclusive|. Both |out| and |max_exclusive| are |len|
// words long.
//
// This function runs in time independent of the result, but |min_inclusive| and
// |max_exclusive| are public data. (Information about the range is unavoidably
// leaked by how many iterations it took to select a number.)
int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive,
const BN_ULONG *max_exclusive, size_t len,
const uint8_t additional_data[32]);
// bn_cmp_words returns a value less than, equal to or greater than zero if the
// array |a| is less than, equal to or greater than |b|. The arrays can be of
// different lengths: |cl| gives the minimum of the two lengths and |dl| gives
// the length of |a| minus the length of |b|.
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num);
uint64_t bn_mont_n0(const BIGNUM *n);
// bn_mod_exp_base_2_consttime calculates r = 2**p (mod n). |p| must be larger
// than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and
// odd. |p| and the bit width of |n| are assumed public, but |n| is otherwise
// treated as secret.
int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n,
BN_CTX *ctx);
int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n);
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
@@ -339,155 +263,6 @@ int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
// -2 on error.
int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
// bn_is_bit_set_words returns one if bit |bit| is set in |a| and zero
// otherwise.
int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit);
// bn_one_to_montgomery sets |r| to one in Montgomery form. It returns one on
// success and zero on error. This function treats the bit width of the modulus
// as public.
int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx);
// bn_less_than_montgomery_R returns one if |bn| is less than the Montgomery R
// value for |mont| and zero otherwise.
int bn_less_than_montgomery_R(const BIGNUM *bn, const BN_MONT_CTX *mont);
// Fixed-width arithmetic.
//
// The following functions implement non-modular arithmetic in constant-time
// and pessimally set |r->width| to the largest possible word size.
//
// Note this means that, e.g., repeatedly multiplying by one will cause widths
// to increase without bound. The corresponding public API functions minimize
// their outputs to avoid regressing calculator consumers.
// bn_uadd_fixed behaves like |BN_uadd|, but it pessimally sets
// |r->width| = |a->width| + |b->width| + 1.
int bn_uadd_fixed(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
// bn_mul_fixed behaves like |BN_mul|, but it rejects negative inputs and
// pessimally sets |r->width| to |a->width| + |b->width|, to avoid leaking
// information about |a| and |b|.
int bn_mul_fixed(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
// bn_sqrt_fixed behaves like |BN_sqrt|, but it pessimally sets |r->width| to
// 2*|a->width|, to avoid leaking information about |a| and |b|.
int bn_sqr_fixed(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
// Constant-time modular arithmetic.
//
// The following functions implement basic constant-time modular arithemtic on
// word arrays.
// bn_mod_add_quick_ctx acts like |BN_mod_add_quick| but takes a |BN_CTX|.
int bn_mod_add_quick_ctx(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m, BN_CTX *ctx);
// bn_mod_sub_quick_ctx acts like |BN_mod_sub_quick| but takes a |BN_CTX|.
int bn_mod_sub_quick_ctx(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m, BN_CTX *ctx);
// bn_mod_lshift1_quick_ctx acts like |BN_mod_lshift1_quick| but takes a
// |BN_CTX|.
int bn_mod_lshift1_quick_ctx(BIGNUM *r, const BIGNUM *a, const BIGNUM *m,
BN_CTX *ctx);
// bn_mod_lshift_quick_ctx acts like |BN_mod_lshift_quick| but takes a |BN_CTX|.
int bn_mod_lshift_quick_ctx(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
BN_CTX *ctx);
// Low-level operations for small numbers.
//
// The following functions implement algorithms suitable for use with scalars
// and field elements in elliptic curves. They rely on the number being small
// both to stack-allocate various temporaries and because they do not implement
// optimizations useful for the larger values used in RSA.
// BN_SMALL_MAX_WORDS is the largest size input these functions handle. This
// limit allows temporaries to be more easily stack-allocated. This limit is set
// to accommodate P-521.
#if defined(OPENSSL_32_BIT)
#define BN_SMALL_MAX_WORDS 17
#else
#define BN_SMALL_MAX_WORDS 9
#endif
// bn_mul_small sets |r| to |a|*|b|. |num_r| must be |num_a| + |num_b|. |r| may
// not alias with |a| or |b|. This function returns one on success and zero if
// lengths are inconsistent.
int bn_mul_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a,
const BN_ULONG *b, size_t num_b);
// bn_sqr_small sets |r| to |a|^2. |num_a| must be at most |BN_SMALL_MAX_WORDS|.
// |num_r| must be |num_a|*2. |r| and |a| may not alias. This function returns
// one on success and zero on programmer error.
int bn_sqr_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a, size_t num_a);
// In the following functions, the modulus must be at most |BN_SMALL_MAX_WORDS|
// words long.
// bn_to_montgomery_small sets |r| to |a| translated to the Montgomery domain.
// |num_a| and |num_r| must be the length of the modulus, which is
// |mont->N.top|. |a| must be fully reduced. This function returns one on
// success and zero if lengths are inconsistent. |r| and |a| may alias.
int bn_to_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont);
// bn_from_montgomery_small sets |r| to |a| translated out of the Montgomery
// domain. |num_r| must be the length of the modulus, which is |mont->N.top|.
// |a| must be at most |mont->N.top| * R and |num_a| must be at most 2 *
// |mont->N.top|. This function returns one on success and zero if lengths are
// inconsistent. |r| and |a| may alias.
int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont);
// bn_one_to_montgomery_small sets |r| to one in Montgomery form. It returns one
// on success and zero on error. |num_r| must be the length of the modulus,
// which is |mont->N.top|. This function treats the bit width of the modulus as
// public.
int bn_one_to_montgomery_small(BN_ULONG *r, size_t num_r,
const BN_MONT_CTX *mont);
// bn_mod_mul_montgomery_small sets |r| to |a| * |b| mod |mont->N|. Both inputs
// and outputs are in the Montgomery domain. |num_r| must be the length of the
// modulus, which is |mont->N.top|. This function returns one on success and
// zero on internal error or inconsistent lengths. Any two of |r|, |a|, and |b|
// may alias.
//
// This function requires |a| * |b| < N * R, where N is the modulus and R is the
// Montgomery divisor, 2^(N.top * BN_BITS2). This should generally be satisfied
// by ensuring |a| and |b| are fully reduced, however ECDSA has one computation
// which requires the more general bound.
int bn_mod_mul_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_ULONG *b, size_t num_b,
const BN_MONT_CTX *mont);
// bn_mod_exp_mont_small sets |r| to |a|^|p| mod |mont->N|. It returns one on
// success and zero on programmer or internal error. Both inputs and outputs are
// in the Montgomery domain. |num_r| and |num_a| must be |mont->N.top|, which
// must be at most |BN_SMALL_MAX_WORDS|. |a| must be fully-reduced. This
// function runs in time independent of |a|, but |p| and |mont->N| are public
// values.
//
// Note this function differs from |BN_mod_exp_mont| which uses Montgomery
// reduction but takes input and output outside the Montgomery domain. Combine
// this function with |bn_from_montgomery_small| and |bn_to_montgomery_small|
// if necessary.
int bn_mod_exp_mont_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_ULONG *p, size_t num_p,
const BN_MONT_CTX *mont);
// bn_mod_inverse_prime_mont_small sets |r| to |a|^-1 mod |mont->N|. |mont->N|
// must be a prime. |num_r| and |num_a| must be |mont->N.top|, which must be at
// most |BN_SMALL_MAX_WORDS|. |a| must be fully-reduced. This function runs in
// time independent of |a|, but |mont->N| is a public value.
int bn_mod_inverse_prime_mont_small(BN_ULONG *r, size_t num_r,
const BN_ULONG *a, size_t num_a,
const BN_MONT_CTX *mont);
#if defined(__cplusplus)
} // extern C
+1 -1
View File
@@ -58,7 +58,7 @@
// least significant word
#define BN_lsw(n) (((n)->width == 0) ? (BN_ULONG) 0 : (n)->d[0])
#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
int bn_jacobi(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
// In 'tab', only odd-indexed entries are relevant:
+132 -228
View File
@@ -114,7 +114,6 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
#include <openssl/type_check.h>
#include "internal.h"
#include "../../internal.h"
@@ -126,6 +125,10 @@
#define OPENSSL_BN_ASM_MONT
#endif
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_new(void) {
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
@@ -189,10 +192,6 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
// |mont->N| is always stored minimally. Computing RR efficiently leaks the
// size of the modulus. While the modulus may be private in RSA (one of the
// primes), their sizes are public, so this is fine.
bn_set_minimal_width(&mont->N);
// Find n0 such that n0 * N == -1 (mod r).
//
@@ -200,7 +199,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
// others, we could use a shorter R value and use faster |BN_ULONG|-based
// math instead of |uint64_t|-based math, which would be double-precision.
// However, currently only the assembler files know which is which.
uint64_t n0 = bn_mont_n0(&mont->N);
uint64_t n0 = bn_mont_n0(mod);
mont->n0[0] = (BN_ULONG)n0;
#if BN_MONT_CTX_N0_LIMBS == 2
mont->n0[1] = (BN_ULONG)(n0 >> BN_BITS2);
@@ -208,34 +207,20 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
mont->n0[1] = 0;
#endif
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
new_ctx = BN_CTX_new();
if (new_ctx == NULL) {
return 0;
}
ctx = new_ctx;
}
// Save RR = R**2 (mod N). R is the smallest power of 2**BN_BITS2 such that R
// Save RR = R**2 (mod N). R is the smallest power of 2**BN_BITS such that R
// > mod. Even though the assembly on some 32-bit platforms works with 64-bit
// values, using |BN_BITS2| here, rather than |BN_MONT_CTX_N0_LIMBS *
// BN_BITS2|, is correct because R**2 will still be a multiple of the latter
// as |BN_MONT_CTX_N0_LIMBS| is either one or two.
unsigned lgBigR = mont->N.width * BN_BITS2;
int ok = bn_mod_exp_base_2_consttime(&mont->RR, lgBigR * 2, &mont->N, ctx);
BN_CTX_free(new_ctx);
return ok;
}
BN_MONT_CTX *BN_MONT_CTX_new_for_modulus(const BIGNUM *mod, BN_CTX *ctx) {
BN_MONT_CTX *mont = BN_MONT_CTX_new();
if (mont == NULL ||
!BN_MONT_CTX_set(mont, mod, ctx)) {
BN_MONT_CTX_free(mont);
return NULL;
//
// XXX: This is not constant time with respect to |mont->N|, but it should
// be.
unsigned lgBigR = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
if (!bn_mod_exp_base_2_vartime(&mont->RR, lgBigR * 2, &mont->N)) {
return 0;
}
return mont;
return 1;
}
int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
@@ -249,12 +234,25 @@ int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
}
CRYPTO_MUTEX_lock_write(lock);
if (*pmont == NULL) {
*pmont = BN_MONT_CTX_new_for_modulus(mod, bn_ctx);
ctx = *pmont;
if (ctx) {
goto out;
}
const int ok = *pmont != NULL;
ctx = BN_MONT_CTX_new();
if (ctx == NULL) {
goto out;
}
if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) {
BN_MONT_CTX_free(ctx);
ctx = NULL;
goto out;
}
*pmont = ctx;
out:
CRYPTO_MUTEX_unlock_write(lock);
return ok;
return ctx != NULL;
}
int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -262,70 +260,88 @@ int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
}
static int bn_from_montgomery_in_place(BN_ULONG *r, size_t num_r, BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont) {
const BN_ULONG *n = mont->N.d;
size_t num_n = mont->N.width;
if (num_r != num_n || num_a != 2 * num_n) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
// Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On
// input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r|
// includes |carry| which is stored separately.
BN_ULONG n0 = mont->n0[0];
BN_ULONG carry = 0;
for (size_t i = 0; i < num_n; i++) {
BN_ULONG v = bn_mul_add_words(a + i, n, num_n, a[i] * n0);
v += carry + a[i + num_n];
carry |= (v != a[i + num_n]);
carry &= (v <= a[i + num_n]);
a[i + num_n] = v;
}
// Shift |num_n| words to divide by R. We have |a| < 2 * |n|. Note that |a|
// includes |carry| which is stored separately.
a += num_n;
// |a| thus requires at most one additional subtraction |n| to be reduced.
// Subtract |n| and select the answer in constant time.
OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t),
crypto_word_t_too_small);
BN_ULONG v = bn_sub_words(r, a, n, num_n) - carry;
// |v| is one if |a| - |n| underflowed or zero if it did not. Note |v| cannot
// be -1. That would imply the subtraction did not fit in |num_n| words, and
// we know at most one subtraction is needed.
v = 0u - v;
for (size_t i = 0; i < num_n; i++) {
r[i] = constant_time_select_w(v, a[i], r[i]);
a[i] = 0;
}
return 1;
}
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
const BN_MONT_CTX *mont) {
if (r->neg) {
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
return 0;
}
BN_ULONG *ap, *np, *rp, n0, v, carry;
int nl, max, i;
const BIGNUM *n = &mont->N;
if (n->width == 0) {
ret->width = 0;
nl = n->top;
if (nl == 0) {
ret->top = 0;
return 1;
}
int max = 2 * n->width; // carry is stored separately
if (!bn_resize_words(r, max) ||
!bn_wexpand(ret, n->width)) {
max = (2 * nl); // carry is stored separately
if (!bn_wexpand(r, max)) {
return 0;
}
ret->width = n->width;
ret->neg = 0;
return bn_from_montgomery_in_place(ret->d, ret->width, r->d, r->width, mont);
r->neg ^= n->neg;
np = n->d;
rp = r->d;
// clear the top words of T
if (max > r->top) {
OPENSSL_memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
}
r->top = max;
n0 = mont->n0[0];
for (carry = 0, i = 0; i < nl; i++, rp++) {
v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
v = (v + carry + rp[nl]) & BN_MASK2;
carry |= (v != rp[nl]);
carry &= (v <= rp[nl]);
rp[nl] = v;
}
if (!bn_wexpand(ret, nl)) {
return 0;
}
ret->top = nl;
ret->neg = r->neg;
rp = ret->d;
ap = &(r->d[nl]);
{
BN_ULONG *nrp;
uintptr_t m;
v = bn_sub_words(rp, ap, np, nl) - carry;
// if subtraction result is real, then trick unconditional memcpy below to
// perform in-place "refresh" instead of actual copy.
m = (0u - (uintptr_t)v);
nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m));
for (i = 0, nl -= 4; i < nl; i += 4) {
BN_ULONG t1, t2, t3, t4;
t1 = nrp[i + 0];
t2 = nrp[i + 1];
t3 = nrp[i + 2];
ap[i + 0] = 0;
t4 = nrp[i + 3];
ap[i + 1] = 0;
rp[i + 0] = t1;
ap[i + 2] = 0;
rp[i + 1] = t2;
ap[i + 3] = 0;
rp[i + 2] = t3;
rp[i + 3] = t4;
}
for (nl += 4; i < nl; i++) {
rp[i] = nrp[i], ap[i] = 0;
}
}
bn_correct_top(r);
bn_correct_top(ret);
return 1;
}
int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -348,24 +364,35 @@ err:
return ret;
}
int bn_one_to_montgomery(BIGNUM *r, const BN_MONT_CTX *mont, BN_CTX *ctx) {
// If the high bit of |n| is set, R = 2^(width*BN_BITS2) < 2 * |n|, so we
// compute R - |n| rather than perform Montgomery reduction.
const BIGNUM *n = &mont->N;
if (n->width > 0 && (n->d[n->width - 1] >> (BN_BITS2 - 1)) != 0) {
if (!bn_wexpand(r, n->width)) {
return 0;
}
r->d[0] = 0 - n->d[0];
for (int i = 1; i < n->width; i++) {
r->d[i] = ~n->d[i];
}
r->width = n->width;
r->neg = 0;
return 1;
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx) {
#if !defined(OPENSSL_BN_ASM_MONT)
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
#else
int num = mont->N.top;
// |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
if (num < (128 / BN_BITS2) ||
a->top != num ||
b->top != num) {
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
}
return BN_from_montgomery(r, &mont->RR, mont, ctx);
if (!bn_wexpand(r, num)) {
return 0;
}
if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
// The check above ensures this won't happen.
assert(0);
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
r->neg = a->neg ^ b->neg;
r->top = num;
bn_correct_top(r);
return 1;
#endif
}
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
@@ -381,11 +408,11 @@ static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
}
if (a == b) {
if (!bn_sqr_fixed(tmp, a, ctx)) {
if (!BN_sqr(tmp, a, ctx)) {
goto err;
}
} else {
if (!bn_mul_fixed(tmp, a, b, ctx)) {
if (!BN_mul(tmp, a, b, ctx)) {
goto err;
}
}
@@ -401,126 +428,3 @@ err:
BN_CTX_end(ctx);
return ret;
}
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BN_MONT_CTX *mont, BN_CTX *ctx) {
if (a->neg || b->neg) {
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
return 0;
}
#if defined(OPENSSL_BN_ASM_MONT)
// |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
int num = mont->N.width;
if (num >= (128 / BN_BITS2) &&
a->width == num &&
b->width == num) {
if (!bn_wexpand(r, num)) {
return 0;
}
if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
// The check above ensures this won't happen.
assert(0);
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
r->neg = 0;
r->width = num;
return 1;
}
#endif
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
}
int bn_less_than_montgomery_R(const BIGNUM *bn, const BN_MONT_CTX *mont) {
return !BN_is_negative(bn) &&
bn_fits_in_words(bn, mont->N.width);
}
int bn_to_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont) {
return bn_mod_mul_montgomery_small(r, num_r, a, num_a, mont->RR.d,
mont->RR.width, mont);
}
int bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_MONT_CTX *mont) {
size_t num_n = mont->N.width;
if (num_a > 2 * num_n || num_r != num_n || num_n > BN_SMALL_MAX_WORDS) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
BN_ULONG tmp[BN_SMALL_MAX_WORDS * 2];
size_t num_tmp = 2 * num_n;
OPENSSL_memcpy(tmp, a, num_a * sizeof(BN_ULONG));
OPENSSL_memset(tmp + num_a, 0, (num_tmp - num_a) * sizeof(BN_ULONG));
int ret = bn_from_montgomery_in_place(r, num_r, tmp, num_tmp, mont);
OPENSSL_cleanse(tmp, num_tmp * sizeof(BN_ULONG));
return ret;
}
int bn_one_to_montgomery_small(BN_ULONG *r, size_t num_r,
const BN_MONT_CTX *mont) {
const BN_ULONG *n = mont->N.d;
size_t num_n = mont->N.width;
if (num_n == 0 || num_r != num_n) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
// If the high bit of |n| is set, R = 2^(num_n*BN_BITS2) < 2 * |n|, so we
// compute R - |n| rather than perform Montgomery reduction.
if (num_n > 0 && (n[num_n - 1] >> (BN_BITS2 - 1)) != 0) {
r[0] = 0 - n[0];
for (size_t i = 1; i < num_n; i++) {
r[i] = ~n[i];
}
return 1;
}
return bn_from_montgomery_small(r, num_r, mont->RR.d, mont->RR.width, mont);
}
int bn_mod_mul_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
size_t num_a, const BN_ULONG *b, size_t num_b,
const BN_MONT_CTX *mont) {
size_t num_n = mont->N.width;
if (num_r != num_n || num_a + num_b > 2 * num_n ||
num_n > BN_SMALL_MAX_WORDS) {
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
#if defined(OPENSSL_BN_ASM_MONT)
// |bn_mul_mont| requires at least 128 bits of limbs, at least for x86.
if (num_n >= (128 / BN_BITS2) &&
num_a == num_n &&
num_b == num_n) {
if (!bn_mul_mont(r, a, b, mont->N.d, mont->n0, num_n)) {
assert(0); // The check above ensures this won't happen.
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#endif
// Compute the product.
BN_ULONG tmp[2 * BN_SMALL_MAX_WORDS];
size_t num_tmp = 2 * num_n;
size_t num_ab = num_a + num_b;
if (a == b && num_a == num_b) {
if (!bn_sqr_small(tmp, num_ab, a, num_a)) {
return 0;
}
} else if (!bn_mul_small(tmp, num_ab, a, num_a, b, num_b)) {
return 0;
}
// Zero-extend to full width and reduce.
OPENSSL_memset(tmp + num_ab, 0, (num_tmp - num_ab) * sizeof(BN_ULONG));
int ret = bn_from_montgomery_in_place(r, num_r, tmp, num_tmp, mont);
OPENSSL_cleanse(tmp, num_tmp * sizeof(BN_ULONG));
return ret;
}
+30 -8
View File
@@ -71,7 +71,7 @@ uint64_t bn_mont_n0(const BIGNUM *n) {
// |BN_MONT_CTX_N0_LIMBS| limbs of |n|.
uint64_t n_mod_r = n->d[0];
#if BN_MONT_CTX_N0_LIMBS == 2
if (n->width > 1) {
if (n->top > 1) {
n_mod_r |= (uint64_t)n->d[1] << BN_BITS2;
}
#endif
@@ -159,8 +159,10 @@ static uint64_t bn_neg_inv_mod_r_u64(uint64_t n) {
return v;
}
int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n,
BN_CTX *ctx) {
// bn_mod_exp_base_2_vartime calculates r = 2**p (mod n). |p| must be larger
// than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and
// odd.
int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n) {
assert(!BN_is_zero(n));
assert(!BN_is_negative(n));
assert(BN_is_odd(n));
@@ -169,17 +171,37 @@ int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n,
unsigned n_bits = BN_num_bits(n);
assert(n_bits != 0);
assert(p > n_bits);
if (n_bits == 1) {
return 1;
}
// Set |r| to the larger power of two smaller than |n|, then shift with
// reductions the rest of the way.
if (!BN_set_bit(r, n_bits - 1) ||
!bn_mod_lshift_quick_ctx(r, r, p - (n_bits - 1), n, ctx)) {
// Set |r| to the smallest power of two larger than |n|.
assert(p > n_bits);
if (!BN_set_bit(r, n_bits)) {
return 0;
}
// Unconditionally reduce |r|.
assert(BN_cmp(r, n) > 0);
if (!BN_usub(r, r, n)) {
return 0;
}
assert(BN_cmp(r, n) < 0);
for (unsigned i = n_bits; i < p; ++i) {
// This is like |BN_mod_lshift1_quick| except using |BN_usub|.
//
// TODO: Replace this with the use of a constant-time variant of
// |BN_mod_lshift1_quick|.
if (!BN_lshift1(r, r)) {
return 0;
}
if (BN_cmp(r, n) >= 0) {
if (!BN_usub(r, r, n)) {
return 0;
}
}
}
return 1;
}
+395 -384
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -586,8 +586,9 @@ int BN_enhanced_miller_rabin_primality_test(
}
// Montgomery setup for computations mod A
mont = BN_MONT_CTX_new_for_modulus(w, ctx);
if (mont == NULL) {
mont = BN_MONT_CTX_new();
if (mont == NULL ||
!BN_MONT_CTX_set(mont, w, ctx)) {
goto err;
}
+64 -79
View File
@@ -113,16 +113,18 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/type_check.h>
#include "internal.h"
#include "../../internal.h"
#include "../rand/internal.h"
static const uint8_t kDefaultAdditionalData[32] = {0};
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
static int bn_rand_with_additional_data(BIGNUM *rnd, int bits, int top,
int bottom,
const uint8_t additional_data[32]) {
uint8_t *buf = NULL;
int ret = 0, bit, bytes, mask;
@@ -157,7 +159,7 @@ int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
}
// Make a random number and set the top and bottom bits.
RAND_bytes(buf, bytes);
RAND_bytes_with_additional_data(buf, bytes, additional_data);
if (top != BN_RAND_TOP_ANY) {
if (top == BN_RAND_TOP_TWO && bits > 1) {
@@ -190,103 +192,54 @@ err:
return ret;
}
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
return bn_rand_with_additional_data(rnd, bits, top, bottom,
kDefaultAdditionalData);
}
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) {
return BN_rand(rnd, bits, top, bottom);
}
// bn_less_than_word returns one if the number represented by |len| words at |a|
// is less than |b| and zero otherwise. It performs this computation in time
// independent of the value of |a|. |b| is assumed public.
static int bn_less_than_word(const BN_ULONG *a, size_t len, BN_ULONG b) {
if (b == 0) {
return 0;
}
if (len == 0) {
return 1;
}
// |a| < |b| iff a[1..len-1] are all zero and a[0] < b.
OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) <= sizeof(crypto_word_t),
crypto_word_t_too_small);
crypto_word_t mask = 0;
for (size_t i = 1; i < len; i++) {
mask |= a[i];
}
// |mask| is now zero iff a[1..len-1] are all zero.
mask = constant_time_is_zero_w(mask);
mask &= constant_time_lt_w(a[0], b);
return constant_time_select_int(mask, 1, 0);
}
int bn_in_range_words(const BN_ULONG *a, BN_ULONG min_inclusive,
const BN_ULONG *max_exclusive, size_t len) {
return bn_less_than_words(a, max_exclusive, len) &&
!bn_less_than_word(a, len, min_inclusive);
}
int bn_rand_range_words(BN_ULONG *out, BN_ULONG min_inclusive,
const BN_ULONG *max_exclusive, size_t len,
const uint8_t additional_data[32]) {
// This function implements the equivalent of steps 4 through 7 of FIPS 186-4
// appendices B.4.2 and B.5.2. When called in those contexts, |max_exclusive|
// is n and |min_inclusive| is one.
// Compute the bit length of |max_exclusive| (step 1), in terms of a number of
// |words| worth of entropy to fill and a mask of bits to clear in the top
// word.
size_t words = len;
while (words > 0 && max_exclusive[words - 1] == 0) {
words--;
}
if (words == 0 ||
(words == 1 && max_exclusive[0] <= min_inclusive)) {
static int bn_rand_range_with_additional_data(
BIGNUM *r, BN_ULONG min_inclusive, const BIGNUM *max_exclusive,
const uint8_t additional_data[32]) {
if (BN_cmp_word(max_exclusive, min_inclusive) <= 0) {
OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE);
return 0;
}
BN_ULONG mask = max_exclusive[words - 1];
// This sets all bits in |mask| below the most significant bit.
mask |= mask >> 1;
mask |= mask >> 2;
mask |= mask >> 4;
mask |= mask >> 8;
mask |= mask >> 16;
#if defined(OPENSSL_64_BIT)
mask |= mask >> 32;
#endif
// Fill any unused words with zero.
OPENSSL_memset(out + words, 0, (len - words) * sizeof(BN_ULONG));
// This function is used to implement steps 4 through 7 of FIPS 186-4
// appendices B.4.2 and B.5.2. When called in those contexts, |max_exclusive|
// is n and |min_inclusive| is one.
unsigned count = 100;
unsigned n = BN_num_bits(max_exclusive); // n > 0
do {
if (!--count) {
OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
return 0;
}
// Steps 4 and 5. Use |words| and |mask| together to obtain a string of N
// bits, where N is the bit length of |max_exclusive|.
RAND_bytes_with_additional_data((uint8_t *)out, words * sizeof(BN_ULONG),
additional_data);
out[words - 1] &= mask;
if (// steps 4 and 5
!bn_rand_with_additional_data(r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY,
additional_data) ||
// step 7
!BN_add_word(r, min_inclusive)) {
return 0;
}
// Step 6. This loops if |r| >= |max_exclusive|. This is identical to
// checking |r| > |max_exclusive| - 1 or |r| - 1 > |max_exclusive| - 2, the
// formulation stated in FIPS 186-4.
} while (BN_cmp(r, max_exclusive) >= 0);
// If out >= max_exclusive or out < min_inclusive, retry. This implements
// the equivalent of steps 6 and 7 without leaking the value of |out|.
} while (!bn_in_range_words(out, min_inclusive, max_exclusive, words));
return 1;
}
int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
const BIGNUM *max_exclusive) {
if (!bn_wexpand(r, max_exclusive->width) ||
!bn_rand_range_words(r->d, min_inclusive, max_exclusive->d,
max_exclusive->width, kDefaultAdditionalData)) {
return 0;
}
r->neg = 0;
r->width = max_exclusive->width;
return 1;
return bn_rand_range_with_additional_data(r, min_inclusive, max_exclusive,
kDefaultAdditionalData);
}
int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
@@ -296,3 +249,35 @@ int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) {
return BN_rand_range(r, range);
}
int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
const uint8_t *message, size_t message_len,
BN_CTX *ctx) {
// We copy |priv| into a local buffer to avoid furthur exposing its
// length.
uint8_t private_bytes[96];
size_t todo = sizeof(priv->d[0]) * priv->top;
if (todo > sizeof(private_bytes)) {
// No reasonable DSA or ECDSA key should have a private key
// this large and we don't handle this case in order to avoid
// leaking the length of the private key.
OPENSSL_PUT_ERROR(BN, BN_R_PRIVATE_KEY_TOO_LARGE);
return 0;
}
OPENSSL_memcpy(private_bytes, priv->d, todo);
OPENSSL_memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
// Pass a SHA512 hash of the private key and message as additional data into
// the RBG. This is a hardening measure against entropy failure.
OPENSSL_COMPILE_ASSERT(SHA512_DIGEST_LENGTH >= 32,
additional_data_is_too_large_for_sha512);
SHA512_CTX sha;
uint8_t digest[SHA512_DIGEST_LENGTH];
SHA512_Init(&sha);
SHA512_Update(&sha, private_bytes, sizeof(private_bytes));
SHA512_Update(&sha, message, message_len);
SHA512_Final(digest, &sha);
// Select a value k from [1, range-1], following FIPS 186-4 appendix B.5.2.
return bn_rand_range_with_additional_data(out, 1, range, digest);
}
+209 -186
View File
@@ -1,16 +1,44 @@
/*
* Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2012, Intel Corporation. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1)
* (1) Intel Corporation, Israel Development Center, Haifa, Israel
* (2) University of Haifa, Israel
*/
/*****************************************************************************
* *
* Copyright (c) 2012, Intel Corporation *
* *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions are *
* met: *
* *
* * Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* * 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. *
* *
* * Neither the name of the Intel Corporation nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* *
* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY *
* EXPRESS 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 INTEL CORPORATION OR *
* 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. *
* *
******************************************************************************
* Developers and authors: *
* Shay Gueron (1, 2), and Vlad Krasnov (1) *
* (1) Intel Corporation, Israel Development Center, Haifa, Israel *
* (2) University of Haifa, Israel *
*****************************************************************************/
#include <openssl/base.h>
@@ -23,209 +51,204 @@
#include "../../internal.h"
// See crypto/bn/asm/rsaz-avx2.pl for further details.
void rsaz_1024_norm2red_avx2(void *red, const void *norm);
void rsaz_1024_mul_avx2(void *ret, const void *a, const void *b, const void *n,
BN_ULONG k);
void rsaz_1024_sqr_avx2(void *ret, const void *a, const void *n, BN_ULONG k,
int cnt);
void rsaz_1024_scatter5_avx2(void *tbl, const void *val, int i);
void rsaz_1024_gather5_avx2(void *val, const void *tbl, int i);
void rsaz_1024_red2norm_avx2(void *norm, const void *red);
/*
* See crypto/bn/asm/rsaz-avx2.pl for further details.
*/
void rsaz_1024_norm2red_avx2(void *red,const void *norm);
void rsaz_1024_mul_avx2(void *ret,const void *a,const void *b,const void *n,BN_ULONG k);
void rsaz_1024_sqr_avx2(void *ret,const void *a,const void *n,BN_ULONG k,int cnt);
void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i);
void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i);
void rsaz_1024_red2norm_avx2(void *norm,const void *red);
// one is 1 in RSAZ's representation.
alignas(64) static const BN_ULONG one[40] = {
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// two80 is 2^80 in RSAZ's representation. Note RSAZ uses base 2^29, so this is
// 2^(29*2 + 22) = 2^80, not 2^(64*2 + 22).
alignas(64) static const BN_ULONG two80[40] = {
0, 0, 1 << 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
alignas(64) static const BN_ULONG one[40] =
{1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
alignas(64) static const BN_ULONG two80[40] =
{0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0) {
alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; // 5.5KB
unsigned char *a_inv, *m, *result, *table_s = storage + (320 * 3),
*R2 = table_s; // borrow
if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) {
result = storage;
a_inv = storage + 320;
m = storage + (320 * 2); // should not cross page
} else {
m = storage; // should not cross page
result = storage + 320;
a_inv = storage + (320 * 2);
}
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0)
{
alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */
unsigned char *a_inv, *m, *result,
*table_s = storage + (320 * 3),
*R2 = table_s; /* borrow */
int index;
int wvalue;
rsaz_1024_norm2red_avx2(m, m_norm);
rsaz_1024_norm2red_avx2(a_inv, base_norm);
rsaz_1024_norm2red_avx2(R2, RR);
if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) {
result = storage;
a_inv = storage + 320;
m = storage + (320 * 2); /* should not cross page */
} else {
m = storage; /* should not cross page */
result = storage + 320;
a_inv = storage + (320 * 2);
}
// Convert |R2| from the usual radix, giving R = 2^1024, to RSAZ's radix,
// giving R = 2^(36*29) = 2^1044.
rsaz_1024_mul_avx2(R2, R2, R2, m, k0);
// R2 = 2^2048 * 2^2048 / 2^1044 = 2^3052
rsaz_1024_mul_avx2(R2, R2, two80, m, k0);
// R2 = 2^3052 * 2^80 / 2^1044 = 2^2088 = (2^1044)^2
rsaz_1024_norm2red_avx2(m, m_norm);
rsaz_1024_norm2red_avx2(a_inv, base_norm);
rsaz_1024_norm2red_avx2(R2, RR);
// table[0] = 1
rsaz_1024_mul_avx2(result, R2, one, m, k0);
// table[1] = a_inv^1
rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0);
rsaz_1024_mul_avx2(R2, R2, R2, m, k0);
rsaz_1024_mul_avx2(R2, R2, two80, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 0);
rsaz_1024_scatter5_avx2(table_s, a_inv, 1);
/* table[0] = 1 */
rsaz_1024_mul_avx2(result, R2, one, m, k0);
/* table[1] = a_inv^1 */
rsaz_1024_mul_avx2(a_inv, a_inv, R2, m, k0);
// table[2] = a_inv^2
rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 2);
rsaz_1024_scatter5_avx2(table_s,result,0);
rsaz_1024_scatter5_avx2(table_s,a_inv,1);
/* table[2] = a_inv^2 */
rsaz_1024_sqr_avx2(result, a_inv, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,2);
#if 0
// This is almost 2x smaller and less than 1% slower.
for (int index = 3; index < 32; index++) {
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, index);
}
/* this is almost 2x smaller and less than 1% slower */
for (index=3; index<32; index++) {
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,index);
}
#else
// table[4] = a_inv^4
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 4);
// table[8] = a_inv^8
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 8);
// table[16] = a_inv^16
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 16);
// table[17] = a_inv^17
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 17);
/* table[4] = a_inv^4 */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,4);
/* table[8] = a_inv^8 */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,8);
/* table[16] = a_inv^16 */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,16);
/* table[17] = a_inv^17 */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,17);
// table[3]
rsaz_1024_gather5_avx2(result, table_s, 2);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 3);
// table[6]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 6);
// table[12]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 12);
// table[24]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 24);
// table[25]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 25);
/* table[3] */
rsaz_1024_gather5_avx2(result,table_s,2);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,3);
/* table[6] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,6);
/* table[12] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,12);
/* table[24] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,24);
/* table[25] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,25);
// table[5]
rsaz_1024_gather5_avx2(result, table_s, 4);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 5);
// table[10]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 10);
// table[20]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 20);
// table[21]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 21);
/* table[5] */
rsaz_1024_gather5_avx2(result,table_s,4);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,5);
/* table[10] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,10);
/* table[20] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,20);
/* table[21] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,21);
// table[7]
rsaz_1024_gather5_avx2(result, table_s, 6);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 7);
// table[14]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 14);
// table[28]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 28);
// table[29]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 29);
/* table[7] */
rsaz_1024_gather5_avx2(result,table_s,6);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,7);
/* table[14] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,14);
/* table[28] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,28);
/* table[29] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,29);
// table[9]
rsaz_1024_gather5_avx2(result, table_s, 8);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 9);
// table[18]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 18);
// table[19]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 19);
/* table[9] */
rsaz_1024_gather5_avx2(result,table_s,8);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,9);
/* table[18] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,18);
/* table[19] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,19);
// table[11]
rsaz_1024_gather5_avx2(result, table_s, 10);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 11);
// table[22]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 22);
// table[23]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 23);
/* table[11] */
rsaz_1024_gather5_avx2(result,table_s,10);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,11);
/* table[22] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,22);
/* table[23] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,23);
// table[13]
rsaz_1024_gather5_avx2(result, table_s, 12);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 13);
// table[26]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 26);
// table[27]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 27);
/* table[13] */
rsaz_1024_gather5_avx2(result,table_s,12);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,13);
/* table[26] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,26);
/* table[27] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,27);
// table[15]
rsaz_1024_gather5_avx2(result, table_s, 14);
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 15);
// table[30]
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s, result, 30);
// table[31]
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s, result, 31);
/* table[15] */
rsaz_1024_gather5_avx2(result,table_s,14);
rsaz_1024_mul_avx2(result,result,a_inv,m,k0);
rsaz_1024_scatter5_avx2(table_s,result,15);
/* table[30] */
rsaz_1024_sqr_avx2(result, result, m, k0, 1);
rsaz_1024_scatter5_avx2(table_s,result,30);
/* table[31] */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_scatter5_avx2(table_s,result,31);
#endif
const uint8_t *p_str = (const uint8_t *)exponent;
const uint8_t *p_str = (const uint8_t *)exponent;
// load first window
int wvalue = p_str[127] >> 3;
rsaz_1024_gather5_avx2(result, table_s, wvalue);
/* load first window */
wvalue = p_str[127] >> 3;
rsaz_1024_gather5_avx2(result,table_s,wvalue);
int index = 1014;
while (index > -1) { // Loop for the remaining 127 windows.
index = 1014;
rsaz_1024_sqr_avx2(result, result, m, k0, 5);
while(index > -1) { /* loop for the remaining 127 windows */
uint16_t wvalue_16;
memcpy(&wvalue_16, &p_str[index / 8], sizeof(wvalue_16));
wvalue = wvalue_16;
wvalue = (wvalue >> (index % 8)) & 31;
index -= 5;
rsaz_1024_sqr_avx2(result, result, m, k0, 5);
rsaz_1024_gather5_avx2(a_inv, table_s, wvalue); // Borrow |a_inv|.
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
}
wvalue = *((const unsigned short*)&p_str[index / 8]);
wvalue = (wvalue>> (index%8)) & 31;
index-=5;
// Square four times.
rsaz_1024_sqr_avx2(result, result, m, k0, 4);
rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
}
wvalue = p_str[0] & 15;
/* square four times */
rsaz_1024_sqr_avx2(result, result, m, k0, 4);
rsaz_1024_gather5_avx2(a_inv, table_s, wvalue); // Borrow |a_inv|.
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
wvalue = p_str[0] & 15;
// Convert from Montgomery.
rsaz_1024_mul_avx2(result, result, one, m, k0);
rsaz_1024_gather5_avx2(a_inv,table_s,wvalue); /* borrow a_inv */
rsaz_1024_mul_avx2(result, result, a_inv, m, k0);
rsaz_1024_red2norm_avx2(result_norm, result);
/* from Montgomery */
rsaz_1024_mul_avx2(result, result, one, m, k0);
OPENSSL_cleanse(storage, sizeof(storage));
rsaz_1024_red2norm_avx2(result_norm, result);
OPENSSL_cleanse(storage,sizeof(storage));
}
#endif // OPENSSL_X86_64
#endif /* OPENSSL_X86_64 */
+47 -27
View File
@@ -1,33 +1,53 @@
/*
* Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2012, Intel Corporation. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1)
* (1) Intel Corporation, Israel Development Center, Haifa, Israel
* (2) University of Haifa, Israel
*/
/*****************************************************************************
* *
* Copyright (c) 2012, Intel Corporation *
* *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions are *
* met: *
* *
* * Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* * 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. *
* *
* * Neither the name of the Intel Corporation nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* *
* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY *
* EXPRESS 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 INTEL CORPORATION OR *
* 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. *
* *
******************************************************************************
* Developers and authors: *
* Shay Gueron (1, 2), and Vlad Krasnov (1) *
* (1) Intel Corporation, Israel Development Center, Haifa, Israel *
* (2) University of Haifa, Israel *
*****************************************************************************/
#ifndef OPENSSL_HEADER_BN_RSAZ_EXP_H
#define OPENSSL_HEADER_BN_RSAZ_EXP_H
#ifndef RSAZ_EXP_H
#define RSAZ_EXP_H
#include <openssl/bn.h>
// RSAZ_1024_mod_exp_avx2 sets |result| to |base_norm| raised to |exponent|
// modulo |m_norm|. |base_norm| must be fully-reduced and |exponent| must have
// the high bit set (it is 1024 bits wide). |RR| and |k0| must be |RR| and |n0|,
// respectively, extracted from |m_norm|'s |BN_MONT_CTX|.
void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16], const BN_ULONG base_norm[16],
const BN_ULONG exponent[16],
const BN_ULONG m_norm[16], const BN_ULONG RR[16],
BN_ULONG k0);
// rsaz_avx2_eligible returns one if |RSAZ_1024_mod_exp_avx2| should be used and
// zero otherwise.
void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16],
const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0);
int rsaz_avx2_eligible(void);
#endif // OPENSSL_HEADER_BN_RSAZ_EXP_H
#endif
+54 -69
View File
@@ -75,28 +75,28 @@ int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) {
r->neg = a->neg;
nw = n / BN_BITS2;
if (!bn_wexpand(r, a->width + nw + 1)) {
if (!bn_wexpand(r, a->top + nw + 1)) {
return 0;
}
lb = n % BN_BITS2;
rb = BN_BITS2 - lb;
f = a->d;
t = r->d;
t[a->width + nw] = 0;
t[a->top + nw] = 0;
if (lb == 0) {
for (i = a->width - 1; i >= 0; i--) {
for (i = a->top - 1; i >= 0; i--) {
t[nw + i] = f[i];
}
} else {
for (i = a->width - 1; i >= 0; i--) {
for (i = a->top - 1; i >= 0; i--) {
l = f[i];
t[nw + i + 1] |= l >> rb;
t[nw + i] = l << lb;
t[nw + i + 1] |= (l >> rb) & BN_MASK2;
t[nw + i] = (l << lb) & BN_MASK2;
}
}
OPENSSL_memset(t, 0, nw * sizeof(t[0]));
r->width = a->width + nw + 1;
bn_set_minimal_width(r);
r->top = a->top + nw + 1;
bn_correct_top(r);
return 1;
}
@@ -107,26 +107,26 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a) {
if (r != a) {
r->neg = a->neg;
if (!bn_wexpand(r, a->width + 1)) {
if (!bn_wexpand(r, a->top + 1)) {
return 0;
}
r->width = a->width;
r->top = a->top;
} else {
if (!bn_wexpand(r, a->width + 1)) {
if (!bn_wexpand(r, a->top + 1)) {
return 0;
}
}
ap = a->d;
rp = r->d;
c = 0;
for (i = 0; i < a->width; i++) {
for (i = 0; i < a->top; i++) {
t = *(ap++);
*(rp++) = (t << 1) | c;
c = t >> (BN_BITS2 - 1);
*(rp++) = ((t << 1) | c) & BN_MASK2;
c = (t & BN_TBIT) ? 1 : 0;
}
if (c) {
*rp = 1;
r->width++;
r->top++;
}
return 1;
@@ -142,11 +142,10 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) {
return 0;
}
int a_width = bn_minimal_width(a);
nw = n / BN_BITS2;
rb = n % BN_BITS2;
lb = BN_BITS2 - rb;
if (nw >= a_width || a_width == 0) {
if (nw >= a->top || a->top == 0) {
BN_zero(r);
return 1;
}
@@ -164,8 +163,8 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) {
f = &(a->d[nw]);
t = r->d;
j = a_width - nw;
r->width = i;
j = a->top - nw;
r->top = i;
if (rb == 0) {
for (i = j; i != 0; i--) {
@@ -174,17 +173,16 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) {
} else {
l = *(f++);
for (i = j - 1; i != 0; i--) {
tmp = l >> rb;
tmp = (l >> rb) & BN_MASK2;
l = *(f++);
*(t++) = tmp | (l << lb);
*(t++) = (tmp | (l << lb)) & BN_MASK2;
}
l >>= rb;
if (l) {
if ((l = (l >> rb) & BN_MASK2)) {
*(t) = l;
}
}
if (r->width == 0) {
if (r->top == 0) {
r->neg = 0;
}
@@ -199,7 +197,7 @@ int BN_rshift1(BIGNUM *r, const BIGNUM *a) {
BN_zero(r);
return 1;
}
i = bn_minimal_width(a);
i = a->top;
ap = a->d;
j = i - (ap[i - 1] == 1);
if (a != r) {
@@ -210,18 +208,18 @@ int BN_rshift1(BIGNUM *r, const BIGNUM *a) {
}
rp = r->d;
t = ap[--i];
c = t << (BN_BITS2 - 1);
c = (t & 1) ? BN_TBIT : 0;
if (t >>= 1) {
rp[i] = t;
}
while (i > 0) {
t = ap[--i];
rp[i] = (t >> 1) | c;
c = t << (BN_BITS2 - 1);
rp[i] = ((t >> 1) & BN_MASK2) | c;
c = (t & 1) ? BN_TBIT : 0;
}
r->width = j;
r->top = j;
if (r->width == 0) {
if (r->top == 0) {
r->neg = 0;
}
@@ -229,20 +227,22 @@ int BN_rshift1(BIGNUM *r, const BIGNUM *a) {
}
int BN_set_bit(BIGNUM *a, int n) {
int i, j, k;
if (n < 0) {
return 0;
}
int i = n / BN_BITS2;
int j = n % BN_BITS2;
if (a->width <= i) {
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i) {
if (!bn_wexpand(a, i + 1)) {
return 0;
}
for (int k = a->width; k < i + 1; k++) {
for (k = a->top; k < i + 1; k++) {
a->d[k] = 0;
}
a->width = i + 1;
a->top = i + 1;
}
a->d[i] |= (((BN_ULONG)1) << j);
@@ -259,64 +259,49 @@ int BN_clear_bit(BIGNUM *a, int n) {
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->width <= i) {
if (a->top <= i) {
return 0;
}
a->d[i] &= (~(((BN_ULONG)1) << j));
bn_set_minimal_width(a);
bn_correct_top(a);
return 1;
}
int bn_is_bit_set_words(const BN_ULONG *a, size_t num, unsigned bit) {
unsigned i = bit / BN_BITS2;
unsigned j = bit % BN_BITS2;
if (i >= num) {
return 0;
}
return (a[i] >> j) & 1;
}
int BN_is_bit_set(const BIGNUM *a, int n) {
int i, j;
if (n < 0) {
return 0;
}
return bn_is_bit_set_words(a->d, a->width, n);
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i) {
return 0;
}
return (a->d[i]>>j)&1;
}
int BN_mask_bits(BIGNUM *a, int n) {
int b, w;
if (n < 0) {
return 0;
}
int w = n / BN_BITS2;
int b = n % BN_BITS2;
if (w >= a->width) {
w = n / BN_BITS2;
b = n % BN_BITS2;
if (w >= a->top) {
return 0;
}
if (b == 0) {
a->width = w;
a->top = w;
} else {
a->width = w + 1;
a->top = w + 1;
a->d[w] &= ~(BN_MASK2 << b);
}
bn_set_minimal_width(a);
bn_correct_top(a);
return 1;
}
int BN_count_low_zero_bits(const BIGNUM *bn) {
for (int i = 0; i < bn->width; i++) {
if (bn->d[i] != 0) {
int bits = 0;
for (BN_ULONG w = bn->d[i]; (w & 1) == 0; w >>= 1) {
bits++;
}
return i * BN_BITS2 + bits;
}
}
// We got to the end of |bn| and saw no non-zero words. |bn| is zero, so
// return zero.
return 0;
}

Some files were not shown because too many files have changed in this diff Show More