Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d7ba4e4e5 | |||
| 9f69f139ed |
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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(©, &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(©, &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(©) != 0) {
|
||||
if (!parse_base128_integer(©, &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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -22,7 +22,6 @@ add_library(
|
||||
e_rc4.c
|
||||
e_aesgcmsiv.c
|
||||
e_aesctrhmac.c
|
||||
e_aesccm.c
|
||||
e_chacha20poly1305.c
|
||||
|
||||
tls_cbc.c
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -57,8 +57,6 @@
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/nid.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define c2l(c, l) \
|
||||
do { \
|
||||
|
||||
@@ -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
@@ -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) {}
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,2 +1 @@
|
||||
OBJ,101,INVALID_OID_STRING
|
||||
OBJ,100,UNKNOWN_NID
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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); }
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
___
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,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,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,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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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,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,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");
|
||||
|
||||
@@ -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>
|
||||
#
|
||||
|
||||
@@ -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].
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+157
-604
File diff suppressed because it is too large
Load Diff
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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
@@ -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
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user