Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8f760191e |
@@ -4,8 +4,4 @@ AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
# TODO(davidben): The default for Google style is now Regroup, but the default
|
||||
# IncludeCategories does not recognize <openssl/header.h>. We should
|
||||
# reconfigure IncludeCategories to match. For now, keep it at Preserve.
|
||||
IncludeBlocks: Preserve
|
||||
|
||||
|
||||
+10
-28
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
# Defer enabling C and CXX languages.
|
||||
project(BoringSSL NONE)
|
||||
@@ -387,14 +387,6 @@ if(FIPS)
|
||||
set(FIPS_DELOCATE "1")
|
||||
endif()
|
||||
endif()
|
||||
if(FIPS_SHARED)
|
||||
# The Android CMake files set -ffunction-sections and -fdata-sections,
|
||||
# which is incompatible with FIPS_SHARED.
|
||||
set(CMAKE_C_FLAGS
|
||||
"${CMAKE_C_FLAGS} -fno-function-sections -fno-data-sections")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fno-function-sections -fno-data-sections")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OPENSSL_SMALL)
|
||||
@@ -458,10 +450,6 @@ if(NOT OPENSSL_NO_ASM AND CMAKE_OSX_ARCHITECTURES)
|
||||
list(GET CMAKE_OSX_ARCHITECTURES 0 CMAKE_SYSTEM_PROCESSOR)
|
||||
endif()
|
||||
|
||||
if(OPENSSL_NO_SSE2_FOR_TESTING)
|
||||
add_definitions(-DOPENSSL_NO_SSE2_FOR_TESTING)
|
||||
endif()
|
||||
|
||||
if(OPENSSL_NO_ASM)
|
||||
add_definitions(-DOPENSSL_NO_ASM)
|
||||
set(ARCH "generic")
|
||||
@@ -471,7 +459,7 @@ elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
|
||||
set(ARCH "x86_64")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
|
||||
# cmake reports AMD64 on Windows, but we might be building for 32-bit.
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if(CMAKE_CL_64)
|
||||
set(ARCH "x86_64")
|
||||
else()
|
||||
set(ARCH "x86")
|
||||
@@ -573,21 +561,10 @@ include_directories(third_party/googletest/include)
|
||||
# themselves as dependencies next to the target definition.
|
||||
add_custom_target(all_tests)
|
||||
|
||||
# On Windows, CRYPTO_TEST_DATA is too long to fit in command-line limits.
|
||||
# TODO(davidben): CMake 3.12 has a list(JOIN) command. Use that when we've
|
||||
# updated the minimum version.
|
||||
set(EMBED_TEST_DATA_ARGS "")
|
||||
foreach(arg ${CRYPTO_TEST_DATA})
|
||||
set(EMBED_TEST_DATA_ARGS "${EMBED_TEST_DATA_ARGS}${arg}\n")
|
||||
endforeach()
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/embed_test_data_args.txt"
|
||||
"${EMBED_TEST_DATA_ARGS}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT crypto_test_data.cc
|
||||
COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go -file-list
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/embed_test_data_args.txt" >
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc"
|
||||
COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go ${CRYPTO_TEST_DATA} >
|
||||
${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc
|
||||
DEPENDS util/embed_test_data.go ${CRYPTO_TEST_DATA}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
@@ -613,6 +590,11 @@ if(FUZZ)
|
||||
add_subdirectory(fuzz)
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.2")
|
||||
# USES_TERMINAL is only available in CMake 3.2 or later.
|
||||
set(MAYBE_USES_TERMINAL USES_TERMINAL)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
set(HANDSHAKER_ARGS "-handshaker-path" $<TARGET_FILE:handshaker>)
|
||||
endif()
|
||||
@@ -626,4 +608,4 @@ add_custom_target(
|
||||
${HANDSHAKER_ARGS} ${RUNNER_ARGS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
DEPENDS all_tests bssl_shim handshaker
|
||||
USES_TERMINAL)
|
||||
${MAYBE_USES_TERMINAL})
|
||||
|
||||
@@ -26,7 +26,6 @@ The recommended values of `max_len` for each test are:
|
||||
|
||||
| Test | `max_len` value |
|
||||
|---------------|-----------------|
|
||||
| `bn_div` | 384 |
|
||||
| `bn_mod_exp` | 4096 |
|
||||
| `cert` | 10000 |
|
||||
| `client` | 20000 |
|
||||
|
||||
@@ -181,6 +181,29 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
The code in third_party/sike also carries the MIT license:
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
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
|
||||
|
||||
|
||||
Licenses for support code
|
||||
-------------------------
|
||||
|
||||
|
||||
@@ -39,4 +39,3 @@ There are other files in this directory which might be helpful:
|
||||
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
|
||||
* [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.
|
||||
* [BREAKING-CHANGES.md](/BREAKING-CHANGES.md): notes on potentially-breaking changes.
|
||||
* [SANDBOXING.md](/SANDBOXING.md): notes on using BoringSSL in a sandboxed environment.
|
||||
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
# Using BoringSSL in a Sandbox
|
||||
|
||||
Sandboxes are a valuable tool for securing applications, so BoringSSL aims to
|
||||
support them. However, it is difficult to make concrete API guarantees with
|
||||
sandboxes. Sandboxes remove low-level OS resources and system calls, which
|
||||
breaks platform abstractions. A syscall-filtering sandbox may, for instance, be
|
||||
sensitive to otherwise non-breaking changes to use newer syscalls
|
||||
in either BoringSSL or the C library.
|
||||
|
||||
Some functions in BoringSSL, such as `BIO_new_file`, inherently need OS
|
||||
resources like the filesystem. We assume that sandboxed consumers either avoid
|
||||
those functions or make necessary resources available. Other functions like
|
||||
`RSA_sign` are purely computational, but still have some baseline OS
|
||||
dependencies.
|
||||
|
||||
Sandboxes which drop privileges partway through a process's lifetime are
|
||||
additionally sensitive to OS resources retained across the transitions. For
|
||||
instance, if a library function internally opened and retained a handle to the
|
||||
user's home directory, and then the application called `chroot`, that handle
|
||||
would be a sandbox escape.
|
||||
|
||||
This document attempts to describe these baseline OS dependencies and long-lived
|
||||
internal resources. These dependencies may change over time, but we aim to
|
||||
[work with sandboxed consumers](/BREAKING-CHANGES.md) when they do. However,
|
||||
each sandbox imposes different constraints, so, above all, sandboxed consumers
|
||||
must have ample test coverage to detect issues as they arise.
|
||||
|
||||
## Baseline dependencies
|
||||
|
||||
Callers must assume that any BoringSSL function may perform one of the following
|
||||
operations:
|
||||
|
||||
### Memory allocation
|
||||
|
||||
Any BoringSSL function may allocate memory via `malloc` and related functions.
|
||||
|
||||
### Thread synchronization
|
||||
|
||||
Any BoringSSL function may call into the platform's thread synchronization
|
||||
primitives, including read/write locks and the equivalent of `pthread_once`.
|
||||
These must succeed, or BoringSSL will abort the process. Callers, however, can
|
||||
assume that BoringSSL functions will not spawn internal threads, unless
|
||||
otherwise documented.
|
||||
|
||||
Syscall-filtering sandboxes should note that BoringSSL uses `pthread_rwlock_t`
|
||||
on POSIX systems, which is less common and may not be part of other libraries'
|
||||
syscall surface. Additionally, thread synchronization primitives usually have an
|
||||
atomics-based fast path. If a sandbox blocks a necessary pthreads syscall, it
|
||||
may not show up in testing without lock contention.
|
||||
|
||||
### Standard error
|
||||
|
||||
Any BoringSSL function may write to `stderr` or file descriptor
|
||||
`STDERR_FILENO` (2), either via `FILE` APIs or low-level functions like `write`.
|
||||
Writes to `stderr` may fail, but there must some file at `STDERR_FILENO` which
|
||||
will tolerate error messages from BoringSSL. (The file descriptor must be
|
||||
allocated so calls to `open` do not accidentally open something else there.)
|
||||
|
||||
Note some C standard library implementations also log to `stderr`, so callers
|
||||
should ensure this regardless.
|
||||
|
||||
### Entropy
|
||||
|
||||
Any BoringSSL function may draw entropy from the OS. On Windows, this uses
|
||||
`RtlGenRandom` and, on POSIX systems, this uses `getrandom`, `getentropy`, or a
|
||||
`read` from a file descriptor to `/dev/urandom`. These operations must succeed
|
||||
or BoringSSL will abort the process. BoringSSL only probes for `getrandom`
|
||||
support once and assumes support is consistent for the lifetime of the address
|
||||
space (and any copies made via `fork`). If a syscall-filtering sandbox is
|
||||
enabled partway through this lifetime and changes whether `getrandom` works,
|
||||
BoringSSL may abort the process. Sandboxes are recommended to allow
|
||||
`getrandom`.
|
||||
|
||||
Note even deterministic algorithms may require OS entropy. For example,
|
||||
RSASSA-PKCS1-v1_5 is deterministic, but BoringSSL draws entropy to implement
|
||||
RSA blinding.
|
||||
|
||||
Entropy gathering additionally has some initialization dependencies described in
|
||||
the following section.
|
||||
|
||||
## Initialization
|
||||
|
||||
BoringSSL has some uncommon OS dependencies which are only used once to
|
||||
initialize some state. Sandboxes which drop privileges after some setup work may
|
||||
use `CRYPTO_pre_sandbox_init` to initialize this state ahead of time. Otherwise,
|
||||
callers must assume any BoringSSL function may depend on these resources, in
|
||||
addition to the operations above.
|
||||
|
||||
### CPU capabilities
|
||||
|
||||
On Linux ARM platforms, BoringSSL depends on OS APIs to query CPU capabilities.
|
||||
32-bit and 64-bit ARM both depend on the `getauxval` function. 32-bit ARM, to
|
||||
work around bugs in older Android devices, may additionally read `/proc/cpuinfo`
|
||||
and `/proc/self/auxv`.
|
||||
|
||||
If querying CPU capabilities fails, BoringSSL will still function, but may not
|
||||
perform as well.
|
||||
|
||||
### Entropy
|
||||
|
||||
On Linux systems without a working `getrandom`, drawing entropy from the OS
|
||||
additionally requires opening `/dev/urandom`. If this fails, BoringSSL will
|
||||
abort the process. BoringSSL retains the resulting file descriptor, even across
|
||||
privilege transitions.
|
||||
|
||||
### Fork protection
|
||||
|
||||
On Linux, BoringSSL allocates a page and calls `madvise` with `MADV_WIPEONFORK`
|
||||
to protect single-use state from `fork`. This operation must not crash, but if
|
||||
it fails, BoringSSL will use alternate fork-safety strategies, potentially at a
|
||||
performance cost. If it succeeds, BoringSSL assumes `MADV_WIPEONFORK` is
|
||||
functional and relies on it for fork-safety. Sandboxes must not report success
|
||||
if they ignore the `MADV_WIPEONFORK` flag. As of writing, QEMU will ignore
|
||||
`madvise` calls and report success, so BoringSSL detects this by calling
|
||||
`madvise` with -1. Sandboxes must cleanly report an error instead of crashing.
|
||||
|
||||
Once initialized, this mechanism does not require system calls in the steady
|
||||
state, though note the configured page will be inherited across privilege
|
||||
transitions.
|
||||
|
||||
## C and C++ standard library
|
||||
|
||||
BoringSSL depends on the C and C++ standard libraries which, themselves, do not
|
||||
make any guarantees about sandboxes. If it produces the correct answer and has
|
||||
no observable invalid side effects, it is possible, though unreasonable, for
|
||||
`memcmp` to create and close a socket.
|
||||
|
||||
BoringSSL assumes that functions in the C and C++ library only have the platform
|
||||
dependencies which would be "reasonable". For instance, a function in BoringSSL
|
||||
which aims not to open files will still freely call any libc memory and
|
||||
string functions.
|
||||
|
||||
Note some C functions, such as `strerror`, may read files relating to the user's
|
||||
locale. BoringSSL may trigger these paths and assumes the sandbox environment
|
||||
will tolerate this. BoringSSL additionally cannot make guarantees about which
|
||||
system calls are used by standard library's syscall wrappers. In some cases, the
|
||||
compiler may add dependencies. (Some C++ language features emit locking code.)
|
||||
Syscall-filtering sandboxes may need updates as these dependencies change.
|
||||
+12
-34
@@ -115,14 +115,7 @@ if(${ARCH} STREQUAL "aarch64")
|
||||
|
||||
chacha/chacha-armv8.${ASM_EXT}
|
||||
test/trampoline-armv8.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(${ARCH} STREQUAL "ppc64le")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
test/trampoline-ppc.${ASM_EXT}
|
||||
third_party/sike/asm/fp-armv8.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -144,6 +137,7 @@ if(${ARCH} STREQUAL "x86_64")
|
||||
cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT}
|
||||
hrss/asm/poly_rq_mul.S
|
||||
test/trampoline-x86_64.${ASM_EXT}
|
||||
third_party/sike/asm/fp-x86_64.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -153,9 +147,10 @@ perlasm(chacha/chacha-x86.${ASM_EXT} chacha/asm/chacha-x86.pl)
|
||||
perlasm(chacha/chacha-x86_64.${ASM_EXT} chacha/asm/chacha-x86_64.pl)
|
||||
perlasm(cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT} cipher_extra/asm/aes128gcmsiv-x86_64.pl)
|
||||
perlasm(cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT} cipher_extra/asm/chacha20_poly1305_x86_64.pl)
|
||||
perlasm(third_party/sike/asm/fp-x86_64.${ASM_EXT} ../third_party/sike/asm/fp-x86_64.pl)
|
||||
perlasm(third_party/sike/asm/fp-armv8.${ASM_EXT} ../third_party/sike/asm/fp-armv8.pl)
|
||||
perlasm(test/trampoline-armv4.${ASM_EXT} test/asm/trampoline-armv4.pl)
|
||||
perlasm(test/trampoline-armv8.${ASM_EXT} test/asm/trampoline-armv8.pl)
|
||||
perlasm(test/trampoline-ppc.${ASM_EXT} test/asm/trampoline-ppc.pl)
|
||||
perlasm(test/trampoline-x86.${ASM_EXT} test/asm/trampoline-x86.pl)
|
||||
perlasm(test/trampoline-x86_64.${ASM_EXT} test/asm/trampoline-x86_64.pl)
|
||||
|
||||
@@ -184,7 +179,6 @@ add_custom_command(
|
||||
err/pkcs8.errordata
|
||||
err/rsa.errordata
|
||||
err/ssl.errordata
|
||||
err/trust_token.errordata
|
||||
err/x509.errordata
|
||||
err/x509v3.errordata
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/err
|
||||
@@ -263,7 +257,6 @@ add_library(
|
||||
cpu-intel.c
|
||||
cpu-ppc64le.c
|
||||
crypto.c
|
||||
curve25519/curve25519.c
|
||||
curve25519/spake25519.c
|
||||
dh/dh.c
|
||||
dh/params.c
|
||||
@@ -275,8 +268,6 @@ add_library(
|
||||
ecdh_extra/ecdh_extra.c
|
||||
ecdsa_extra/ecdsa_asn1.c
|
||||
ec_extra/ec_asn1.c
|
||||
ec_extra/ec_derive.c
|
||||
ec_extra/hash_to_curve.c
|
||||
err/err.c
|
||||
err_data.c
|
||||
engine/engine.c
|
||||
@@ -299,7 +290,6 @@ add_library(
|
||||
evp/sign.c
|
||||
ex_data.c
|
||||
hkdf/hkdf.c
|
||||
hpke/hpke.c
|
||||
hrss/hrss.c
|
||||
lhash/lhash.c
|
||||
mem.c
|
||||
@@ -338,8 +328,6 @@ add_library(
|
||||
thread_none.c
|
||||
thread_pthread.c
|
||||
thread_win.c
|
||||
trust_token/pmbtoken.c
|
||||
trust_token/trust_token.c
|
||||
x509/a_digest.c
|
||||
x509/a_sign.c
|
||||
x509/a_strex.c
|
||||
@@ -422,6 +410,12 @@ add_library(
|
||||
x509v3/v3_skey.c
|
||||
x509v3/v3_sxnet.c
|
||||
x509v3/v3_utl.c
|
||||
../third_party/fiat/curve25519.c
|
||||
../third_party/sike/fpx.c
|
||||
../third_party/sike/isogeny.c
|
||||
../third_party/sike/curve_params.c
|
||||
../third_party/sike/sike.c
|
||||
../third_party/sike/asm/fp_generic.c
|
||||
|
||||
$<TARGET_OBJECTS:fipsmodule>
|
||||
|
||||
@@ -457,7 +451,7 @@ endif()
|
||||
|
||||
SET_TARGET_PROPERTIES(crypto PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(NOT WIN32 AND NOT ANDROID)
|
||||
if(NOT MSVC AND NOT ANDROID)
|
||||
target_link_libraries(crypto pthread)
|
||||
endif()
|
||||
|
||||
@@ -467,20 +461,6 @@ if(USE_CUSTOM_LIBCXX)
|
||||
target_link_libraries(crypto libcxx)
|
||||
endif()
|
||||
|
||||
# urandom_test is a separate binary because it needs to be able to observe the
|
||||
# PRNG initialisation, which means that it can't have other tests running before
|
||||
# it does.
|
||||
add_executable(
|
||||
urandom_test
|
||||
|
||||
fipsmodule/rand/urandom_test.cc
|
||||
)
|
||||
|
||||
target_link_libraries(urandom_test test_support_lib boringssl_gtest crypto)
|
||||
|
||||
add_dependencies(urandom_test global_target)
|
||||
add_dependencies(all_tests urandom_test)
|
||||
|
||||
add_executable(
|
||||
crypto_test
|
||||
|
||||
@@ -517,10 +497,8 @@ add_executable(
|
||||
fipsmodule/md5/md5_test.cc
|
||||
fipsmodule/modes/gcm_test.cc
|
||||
fipsmodule/rand/ctrdrbg_test.cc
|
||||
fipsmodule/rand/fork_detect_test.cc
|
||||
fipsmodule/sha/sha_test.cc
|
||||
hkdf/hkdf_test.cc
|
||||
hpke/hpke_test.cc
|
||||
hmac_extra/hmac_test.cc
|
||||
hrss/hrss_test.cc
|
||||
impl_dispatch_test.cc
|
||||
@@ -540,11 +518,11 @@ add_executable(
|
||||
siphash/siphash_test.cc
|
||||
test/file_test_gtest.cc
|
||||
thread_test.cc
|
||||
trust_token/trust_token_test.cc
|
||||
x509/x509_test.cc
|
||||
x509/x509_time_test.cc
|
||||
x509v3/tab_test.cc
|
||||
x509v3/v3name_test.cc
|
||||
../third_party/sike/sike_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:crypto_test_data>
|
||||
$<TARGET_OBJECTS:boringssl_gtest_main>
|
||||
|
||||
+1
-286
@@ -341,6 +341,7 @@ TEST(ABITest, ARM) {
|
||||
}
|
||||
#endif // OPENSSL_ARM && SUPPORTS_ABI_TEST
|
||||
|
||||
|
||||
#if defined(OPENSSL_AARCH64) && defined(SUPPORTS_ABI_TEST)
|
||||
extern "C" {
|
||||
void abi_test_clobber_x0(void);
|
||||
@@ -520,289 +521,3 @@ TEST(ABITest, AArch64) {
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v15_upper);
|
||||
}
|
||||
#endif // OPENSSL_AARCH64 && SUPPORTS_ABI_TEST
|
||||
|
||||
#if defined(OPENSSL_PPC64LE) && defined(SUPPORTS_ABI_TEST)
|
||||
extern "C" {
|
||||
void abi_test_clobber_r0(void);
|
||||
// r1 is the stack pointer.
|
||||
void abi_test_clobber_r2(void);
|
||||
void abi_test_clobber_r3(void);
|
||||
void abi_test_clobber_r4(void);
|
||||
void abi_test_clobber_r5(void);
|
||||
void abi_test_clobber_r6(void);
|
||||
void abi_test_clobber_r7(void);
|
||||
void abi_test_clobber_r8(void);
|
||||
void abi_test_clobber_r9(void);
|
||||
void abi_test_clobber_r10(void);
|
||||
void abi_test_clobber_r11(void);
|
||||
void abi_test_clobber_r12(void);
|
||||
// r13 is the thread pointer.
|
||||
void abi_test_clobber_r14(void);
|
||||
void abi_test_clobber_r15(void);
|
||||
void abi_test_clobber_r16(void);
|
||||
void abi_test_clobber_r17(void);
|
||||
void abi_test_clobber_r18(void);
|
||||
void abi_test_clobber_r19(void);
|
||||
void abi_test_clobber_r20(void);
|
||||
void abi_test_clobber_r21(void);
|
||||
void abi_test_clobber_r22(void);
|
||||
void abi_test_clobber_r23(void);
|
||||
void abi_test_clobber_r24(void);
|
||||
void abi_test_clobber_r25(void);
|
||||
void abi_test_clobber_r26(void);
|
||||
void abi_test_clobber_r27(void);
|
||||
void abi_test_clobber_r28(void);
|
||||
void abi_test_clobber_r29(void);
|
||||
void abi_test_clobber_r30(void);
|
||||
void abi_test_clobber_r31(void);
|
||||
|
||||
void abi_test_clobber_f0(void);
|
||||
void abi_test_clobber_f1(void);
|
||||
void abi_test_clobber_f2(void);
|
||||
void abi_test_clobber_f3(void);
|
||||
void abi_test_clobber_f4(void);
|
||||
void abi_test_clobber_f5(void);
|
||||
void abi_test_clobber_f6(void);
|
||||
void abi_test_clobber_f7(void);
|
||||
void abi_test_clobber_f8(void);
|
||||
void abi_test_clobber_f9(void);
|
||||
void abi_test_clobber_f10(void);
|
||||
void abi_test_clobber_f11(void);
|
||||
void abi_test_clobber_f12(void);
|
||||
void abi_test_clobber_f13(void);
|
||||
void abi_test_clobber_f14(void);
|
||||
void abi_test_clobber_f15(void);
|
||||
void abi_test_clobber_f16(void);
|
||||
void abi_test_clobber_f17(void);
|
||||
void abi_test_clobber_f18(void);
|
||||
void abi_test_clobber_f19(void);
|
||||
void abi_test_clobber_f20(void);
|
||||
void abi_test_clobber_f21(void);
|
||||
void abi_test_clobber_f22(void);
|
||||
void abi_test_clobber_f23(void);
|
||||
void abi_test_clobber_f24(void);
|
||||
void abi_test_clobber_f25(void);
|
||||
void abi_test_clobber_f26(void);
|
||||
void abi_test_clobber_f27(void);
|
||||
void abi_test_clobber_f28(void);
|
||||
void abi_test_clobber_f29(void);
|
||||
void abi_test_clobber_f30(void);
|
||||
void abi_test_clobber_f31(void);
|
||||
|
||||
void abi_test_clobber_v0(void);
|
||||
void abi_test_clobber_v1(void);
|
||||
void abi_test_clobber_v2(void);
|
||||
void abi_test_clobber_v3(void);
|
||||
void abi_test_clobber_v4(void);
|
||||
void abi_test_clobber_v5(void);
|
||||
void abi_test_clobber_v6(void);
|
||||
void abi_test_clobber_v7(void);
|
||||
void abi_test_clobber_v8(void);
|
||||
void abi_test_clobber_v9(void);
|
||||
void abi_test_clobber_v10(void);
|
||||
void abi_test_clobber_v11(void);
|
||||
void abi_test_clobber_v12(void);
|
||||
void abi_test_clobber_v13(void);
|
||||
void abi_test_clobber_v14(void);
|
||||
void abi_test_clobber_v15(void);
|
||||
void abi_test_clobber_v16(void);
|
||||
void abi_test_clobber_v17(void);
|
||||
void abi_test_clobber_v18(void);
|
||||
void abi_test_clobber_v19(void);
|
||||
void abi_test_clobber_v20(void);
|
||||
void abi_test_clobber_v21(void);
|
||||
void abi_test_clobber_v22(void);
|
||||
void abi_test_clobber_v23(void);
|
||||
void abi_test_clobber_v24(void);
|
||||
void abi_test_clobber_v25(void);
|
||||
void abi_test_clobber_v26(void);
|
||||
void abi_test_clobber_v27(void);
|
||||
void abi_test_clobber_v28(void);
|
||||
void abi_test_clobber_v29(void);
|
||||
void abi_test_clobber_v30(void);
|
||||
void abi_test_clobber_v31(void);
|
||||
|
||||
void abi_test_clobber_cr0(void);
|
||||
void abi_test_clobber_cr1(void);
|
||||
void abi_test_clobber_cr2(void);
|
||||
void abi_test_clobber_cr3(void);
|
||||
void abi_test_clobber_cr4(void);
|
||||
void abi_test_clobber_cr5(void);
|
||||
void abi_test_clobber_cr6(void);
|
||||
void abi_test_clobber_cr7(void);
|
||||
|
||||
void abi_test_clobber_ctr(void);
|
||||
void abi_test_clobber_lr(void);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
TEST(ABITest, PPC64LE) {
|
||||
// abi_test_trampoline hides unsaved registers from the caller, so we can
|
||||
// safely call the abi_test_clobber_* functions below.
|
||||
abi_test::internal::CallerState state;
|
||||
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state));
|
||||
CHECK_ABI_NO_UNWIND(abi_test_trampoline,
|
||||
reinterpret_cast<crypto_word_t>(abi_test_clobber_r14),
|
||||
&state, nullptr, 0, 0 /* no breakpoint */);
|
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r0);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r2);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r3);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r4);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r5);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r6);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r7);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r8);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r9);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r10);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r11);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r12);
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r14),
|
||||
"r14 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r15),
|
||||
"r15 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r16),
|
||||
"r16 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r17),
|
||||
"r17 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r18),
|
||||
"r18 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r19),
|
||||
"r19 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r20),
|
||||
"r20 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r21),
|
||||
"r21 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r22),
|
||||
"r22 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r23),
|
||||
"r23 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r24),
|
||||
"r24 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r25),
|
||||
"r25 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r26),
|
||||
"r26 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r27),
|
||||
"r27 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r28),
|
||||
"r28 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r29),
|
||||
"r29 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r30),
|
||||
"r30 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r31),
|
||||
"r31 was not restored after return");
|
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f0);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f1);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f2);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f3);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f4);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f5);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f6);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f7);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f8);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f9);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f10);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f11);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f12);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_f13);
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f14),
|
||||
"f14 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f15),
|
||||
"f15 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f16),
|
||||
"f16 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f17),
|
||||
"f17 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f18),
|
||||
"f18 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f19),
|
||||
"f19 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f20),
|
||||
"f20 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f21),
|
||||
"f21 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f22),
|
||||
"f22 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f23),
|
||||
"f23 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f24),
|
||||
"f24 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f25),
|
||||
"f25 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f26),
|
||||
"f26 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f27),
|
||||
"f27 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f28),
|
||||
"f28 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f29),
|
||||
"f29 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f30),
|
||||
"f30 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f31),
|
||||
"f31 was not restored after return");
|
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v0);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v1);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v2);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v3);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v4);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v5);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v6);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v7);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v8);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v9);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v10);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v11);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v12);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v13);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v14);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v15);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v16);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v17);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v18);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v19);
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v20),
|
||||
"v20 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v21),
|
||||
"v21 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v22),
|
||||
"v22 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v23),
|
||||
"v23 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v24),
|
||||
"v24 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v25),
|
||||
"v25 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v26),
|
||||
"v26 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v27),
|
||||
"v27 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v28),
|
||||
"v28 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v29),
|
||||
"v29 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v30),
|
||||
"v30 was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v31),
|
||||
"v31 was not restored after return");
|
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr0);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr1);
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr2),
|
||||
"cr was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr3),
|
||||
"cr was not restored after return");
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr4),
|
||||
"cr was not restored after return");
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr5);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr6);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_cr7);
|
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_ctr);
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_lr);
|
||||
}
|
||||
#endif // OPENSSL_PPC64LE && SUPPORTS_ABI_TEST
|
||||
|
||||
@@ -70,7 +70,7 @@ int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
return M_ASN1_BIT_STRING_set(x, d, len);
|
||||
}
|
||||
|
||||
int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
{
|
||||
int ret, j, bits, len;
|
||||
unsigned char *p, *d;
|
||||
@@ -233,7 +233,7 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
|
||||
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
int w, v;
|
||||
|
||||
@@ -250,7 +250,7 @@ int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
|
||||
* which is not specified in 'flags', 1 otherwise.
|
||||
* 'len' is the length of 'flags'.
|
||||
*/
|
||||
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a,
|
||||
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
|
||||
unsigned char *flags, int flags_len)
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
@@ -108,7 +108,7 @@ int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
return (1);
|
||||
}
|
||||
|
||||
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a)
|
||||
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
|
||||
@@ -147,7 +147,7 @@ long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a)
|
||||
return r;
|
||||
}
|
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len, j;
|
||||
@@ -183,7 +183,7 @@ ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
|
||||
* followed by optional zeros isn't padded.
|
||||
*/
|
||||
|
||||
int i2c_ASN1_INTEGER(const ASN1_INTEGER *a, unsigned char **pp)
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
|
||||
{
|
||||
int pad = 0, ret, i, neg;
|
||||
unsigned char *p, *n, pb = 0;
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p, *allocated = NULL;
|
||||
int objsize;
|
||||
@@ -98,12 +98,12 @@ int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
|
||||
return objsize;
|
||||
}
|
||||
|
||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
|
||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
||||
{
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
}
|
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
|
||||
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -100,7 +101,7 @@ ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
|
||||
int ASN1_TIME_check(const ASN1_TIME *t)
|
||||
int ASN1_TIME_check(ASN1_TIME *t)
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
@@ -110,7 +111,7 @@ int ASN1_TIME_check(const ASN1_TIME *t)
|
||||
}
|
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
@@ -142,11 +143,11 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5')
|
||||
OPENSSL_strlcpy(str, "19", newlen);
|
||||
BUF_strlcpy(str, "19", newlen);
|
||||
else
|
||||
OPENSSL_strlcpy(str, "20", newlen);
|
||||
BUF_strlcpy(str, "20", newlen);
|
||||
|
||||
OPENSSL_strlcat(str, (char *)t->data, newlen);
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
done:
|
||||
if (out != NULL && *out == NULL)
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
int ASN1_TYPE_get(const ASN1_TYPE *a)
|
||||
int ASN1_TYPE_get(ASN1_TYPE *a)
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return (a->type);
|
||||
|
||||
@@ -430,7 +430,7 @@ void ASN1_STRING_length_set(ASN1_STRING *x, int len)
|
||||
return;
|
||||
}
|
||||
|
||||
int ASN1_STRING_type(const ASN1_STRING *x)
|
||||
int ASN1_STRING_type(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_type(x);
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ TEST(ASN1Test, SerializeObject) {
|
||||
static const uint8_t kDER[] = {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x01, 0x01, 0x01};
|
||||
const ASN1_OBJECT *obj = OBJ_nid2obj(NID_rsaEncryption);
|
||||
TestSerialize(obj, i2d_ASN1_OBJECT, kDER);
|
||||
TestSerialize(const_cast<ASN1_OBJECT *>(obj), i2d_ASN1_OBJECT, kDER);
|
||||
}
|
||||
|
||||
TEST(ASN1Test, SerializeBoolean) {
|
||||
|
||||
@@ -93,7 +93,7 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
|
||||
/* Extract an ASN1 object from an ASN1_STRING */
|
||||
|
||||
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
{
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
/* Based on a_int.c: equivalent ENUMERATED functions */
|
||||
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
|
||||
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
|
||||
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
|
||||
@@ -74,6 +74,7 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -148,7 +149,7 @@ static int split_host_and_port(char **out_host, char **out_port, const char *nam
|
||||
}
|
||||
}
|
||||
|
||||
*out_host = OPENSSL_strndup(host, host_len);
|
||||
*out_host = BUF_strndup(host, host_len);
|
||||
if (*out_host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -428,13 +429,13 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
bio->init = 1;
|
||||
if (num == 0) {
|
||||
OPENSSL_free(data->param_hostname);
|
||||
data->param_hostname = OPENSSL_strdup(ptr);
|
||||
data->param_hostname = BUF_strdup(ptr);
|
||||
if (data->param_hostname == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
} else if (num == 1) {
|
||||
OPENSSL_free(data->param_port);
|
||||
data->param_port = OPENSSL_strdup(ptr);
|
||||
data->param_port = BUF_strdup(ptr);
|
||||
if (data->param_port == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
+6
-5
@@ -79,6 +79,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -207,16 +208,16 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
b->shutdown = (int)num & BIO_CLOSE;
|
||||
if (num & BIO_FP_APPEND) {
|
||||
if (num & BIO_FP_READ) {
|
||||
OPENSSL_strlcpy(p, "a+", sizeof(p));
|
||||
BUF_strlcpy(p, "a+", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_strlcpy(p, "a", sizeof(p));
|
||||
BUF_strlcpy(p, "a", sizeof(p));
|
||||
}
|
||||
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
|
||||
OPENSSL_strlcpy(p, "r+", sizeof(p));
|
||||
BUF_strlcpy(p, "r+", sizeof(p));
|
||||
} else if (num & BIO_FP_WRITE) {
|
||||
OPENSSL_strlcpy(p, "w", sizeof(p));
|
||||
BUF_strlcpy(p, "w", sizeof(p));
|
||||
} else if (num & BIO_FP_READ) {
|
||||
OPENSSL_strlcpy(p, "r", sizeof(p));
|
||||
BUF_strlcpy(p, "r", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
|
||||
ret = 0;
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
+69
-10
@@ -132,10 +132,6 @@ size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
|
||||
}
|
||||
|
||||
int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
|
||||
// Work around a C language bug. See https://crbug.com/1019588.
|
||||
if (len == 0) {
|
||||
return 1;
|
||||
}
|
||||
size_t new_len = buf->length + len;
|
||||
if (new_len < len) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_OVERFLOW);
|
||||
@@ -149,24 +145,87 @@ int BUF_MEM_append(BUF_MEM *buf, const void *in, size_t len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *BUF_strdup(const char *str) { return OPENSSL_strdup(str); }
|
||||
char *BUF_strdup(const char *str) {
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return BUF_strndup(str, strlen(str));
|
||||
}
|
||||
|
||||
size_t BUF_strnlen(const char *str, size_t max_len) {
|
||||
return OPENSSL_strnlen(str, max_len);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < max_len; i++) {
|
||||
if (str[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
char *BUF_strndup(const char *str, size_t size) {
|
||||
return OPENSSL_strndup(str, size);
|
||||
char *ret;
|
||||
size_t alloc_size;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = BUF_strnlen(str, size);
|
||||
|
||||
alloc_size = size + 1;
|
||||
if (alloc_size < size) {
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ret = OPENSSL_malloc(alloc_size);
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(ret, str, size);
|
||||
ret[size] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t BUF_strlcpy(char *dst, const char *src, size_t dst_size) {
|
||||
return OPENSSL_strlcpy(dst, src, dst_size);
|
||||
size_t l = 0;
|
||||
|
||||
for (; dst_size > 1 && *src; dst_size--) {
|
||||
*dst++ = *src++;
|
||||
l++;
|
||||
}
|
||||
|
||||
if (dst_size) {
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
return l + strlen(src);
|
||||
}
|
||||
|
||||
size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
|
||||
return OPENSSL_strlcat(dst, src, dst_size);
|
||||
size_t l = 0;
|
||||
for (; dst_size > 0 && *dst; dst_size--, dst++) {
|
||||
l++;
|
||||
}
|
||||
return l + BUF_strlcpy(dst, src, dst_size);
|
||||
}
|
||||
|
||||
void *BUF_memdup(const void *data, size_t size) {
|
||||
return OPENSSL_memdup(data, size);
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *ret = OPENSSL_malloc(size);
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(ret, data, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -67,14 +67,6 @@ TEST(CBSTest, GetUint) {
|
||||
EXPECT_EQ(0x13u, u8);
|
||||
EXPECT_FALSE(CBS_get_u8(&data, &u8));
|
||||
EXPECT_FALSE(CBS_get_last_u8(&data, &u8));
|
||||
|
||||
CBS_init(&data, kData, sizeof(kData));
|
||||
ASSERT_TRUE(CBS_get_u16le(&data, &u16));
|
||||
EXPECT_EQ(0x0201u, u16);
|
||||
ASSERT_TRUE(CBS_get_u32le(&data, &u32));
|
||||
EXPECT_EQ(0x06050403u, u32);
|
||||
ASSERT_TRUE(CBS_get_u64le(&data, &u64));
|
||||
EXPECT_EQ(0x0e0d0c0b0a090807u, u64);
|
||||
}
|
||||
|
||||
TEST(CBSTest, GetPrefixed) {
|
||||
@@ -324,9 +316,7 @@ TEST(CBBTest, InitUninitialized) {
|
||||
TEST(CBBTest, Basic) {
|
||||
static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0xa, 0xb, 0xc, 0xd, 0xe,
|
||||
0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 3, 2,
|
||||
10, 9, 8, 7, 0x12, 0x11, 0x10,
|
||||
0xf, 0xe, 0xd, 0xc, 0xb};
|
||||
0xf, 0x10, 0x11, 0x12, 0x13, 0x14};
|
||||
uint8_t *buf;
|
||||
size_t buf_len;
|
||||
|
||||
@@ -341,9 +331,6 @@ TEST(CBBTest, Basic) {
|
||||
ASSERT_TRUE(CBB_add_u32(cbb.get(), 0x708090a));
|
||||
ASSERT_TRUE(CBB_add_u64(cbb.get(), 0xb0c0d0e0f101112));
|
||||
ASSERT_TRUE(CBB_add_bytes(cbb.get(), (const uint8_t *)"\x13\x14", 2));
|
||||
ASSERT_TRUE(CBB_add_u16le(cbb.get(), 0x203));
|
||||
ASSERT_TRUE(CBB_add_u32le(cbb.get(), 0x708090a));
|
||||
ASSERT_TRUE(CBB_add_u64le(cbb.get(), 0xb0c0d0e0f101112));
|
||||
ASSERT_TRUE(CBB_finish(cbb.get(), &buf, &buf_len));
|
||||
|
||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||
@@ -767,79 +754,6 @@ TEST(CBSTest, ASN1Uint64) {
|
||||
}
|
||||
}
|
||||
|
||||
struct ASN1Int64Test {
|
||||
int64_t value;
|
||||
const char *encoding;
|
||||
size_t encoding_len;
|
||||
};
|
||||
|
||||
static const ASN1Int64Test kASN1Int64Tests[] = {
|
||||
{0, "\x02\x01\x00", 3},
|
||||
{1, "\x02\x01\x01", 3},
|
||||
{-1, "\x02\x01\xff", 3},
|
||||
{127, "\x02\x01\x7f", 3},
|
||||
{-127, "\x02\x01\x81", 3},
|
||||
{128, "\x02\x02\x00\x80", 4},
|
||||
{-128, "\x02\x01\x80", 3},
|
||||
{129, "\x02\x02\x00\x81", 4},
|
||||
{-129, "\x02\x02\xff\x7f", 4},
|
||||
{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
|
||||
{INT64_C(0x0102030405060708), "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08",
|
||||
10},
|
||||
{INT64_MIN, "\x02\x08\x80\x00\x00\x00\x00\x00\x00\x00", 10},
|
||||
{INT64_MAX, "\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff", 10},
|
||||
};
|
||||
|
||||
struct ASN1InvalidInt64Test {
|
||||
const char *encoding;
|
||||
size_t encoding_len;
|
||||
};
|
||||
|
||||
static const ASN1InvalidInt64Test kASN1InvalidInt64Tests[] = {
|
||||
// Bad tag.
|
||||
{"\x03\x01\x00", 3},
|
||||
// Empty contents.
|
||||
{"\x02\x00", 2},
|
||||
// Overflow.
|
||||
{"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
|
||||
// Leading zeros.
|
||||
{"\x02\x02\x00\x01", 4},
|
||||
// Leading 0xff.
|
||||
{"\x02\x02\xff\xff", 4},
|
||||
};
|
||||
|
||||
TEST(CBSTest, ASN1Int64) {
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Int64Tests); i++) {
|
||||
SCOPED_TRACE(i);
|
||||
const ASN1Int64Test *test = &kASN1Int64Tests[i];
|
||||
CBS cbs;
|
||||
int64_t value;
|
||||
uint8_t *out;
|
||||
size_t len;
|
||||
|
||||
CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
|
||||
ASSERT_TRUE(CBS_get_asn1_int64(&cbs, &value));
|
||||
EXPECT_EQ(0u, CBS_len(&cbs));
|
||||
EXPECT_EQ(test->value, value);
|
||||
|
||||
bssl::ScopedCBB cbb;
|
||||
ASSERT_TRUE(CBB_init(cbb.get(), 0));
|
||||
ASSERT_TRUE(CBB_add_asn1_int64(cbb.get(), test->value));
|
||||
ASSERT_TRUE(CBB_finish(cbb.get(), &out, &len));
|
||||
bssl::UniquePtr<uint8_t> scoper(out);
|
||||
EXPECT_EQ(Bytes(test->encoding, test->encoding_len), Bytes(out, len));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1InvalidInt64Tests); i++) {
|
||||
const ASN1InvalidInt64Test *test = &kASN1InvalidInt64Tests[i];
|
||||
CBS cbs;
|
||||
int64_t value;
|
||||
|
||||
CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
|
||||
EXPECT_FALSE(CBS_get_asn1_int64(&cbs, &value));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CBBTest, Zero) {
|
||||
CBB cbb;
|
||||
CBB_zero(&cbb);
|
||||
|
||||
+2
-41
@@ -18,6 +18,7 @@
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
@@ -447,10 +448,6 @@ int CBB_add_u16(CBB *cbb, uint16_t value) {
|
||||
return cbb_buffer_add_u(cbb->base, value, 2);
|
||||
}
|
||||
|
||||
int CBB_add_u16le(CBB *cbb, uint16_t value) {
|
||||
return CBB_add_u16(cbb, CRYPTO_bswap2(value));
|
||||
}
|
||||
|
||||
int CBB_add_u24(CBB *cbb, uint32_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
@@ -467,10 +464,6 @@ int CBB_add_u32(CBB *cbb, uint32_t value) {
|
||||
return cbb_buffer_add_u(cbb->base, value, 4);
|
||||
}
|
||||
|
||||
int CBB_add_u32le(CBB *cbb, uint32_t value) {
|
||||
return CBB_add_u32(cbb, CRYPTO_bswap4(value));
|
||||
}
|
||||
|
||||
int CBB_add_u64(CBB *cbb, uint64_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
@@ -478,10 +471,6 @@ int CBB_add_u64(CBB *cbb, uint64_t value) {
|
||||
return cbb_buffer_add_u(cbb->base, value, 8);
|
||||
}
|
||||
|
||||
int CBB_add_u64le(CBB *cbb, uint64_t value) {
|
||||
return CBB_add_u64(cbb, CRYPTO_bswap8(value));
|
||||
}
|
||||
|
||||
void CBB_discard_child(CBB *cbb) {
|
||||
if (cbb->child == NULL) {
|
||||
return;
|
||||
@@ -528,34 +517,6 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
|
||||
return CBB_flush(cbb);
|
||||
}
|
||||
|
||||
int CBB_add_asn1_int64(CBB *cbb, int64_t value) {
|
||||
if (value >= 0) {
|
||||
return CBB_add_asn1_uint64(cbb, value);
|
||||
}
|
||||
|
||||
union {
|
||||
int64_t i;
|
||||
uint8_t bytes[sizeof(int64_t)];
|
||||
} u;
|
||||
u.i = value;
|
||||
int start = 7;
|
||||
// Skip leading sign-extension bytes unless they are necessary.
|
||||
while (start > 0 && (u.bytes[start] == 0xff && (u.bytes[start - 1] & 0x80))) {
|
||||
start--;
|
||||
}
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = start; i >= 0; i--) {
|
||||
if (!CBB_add_u8(&child, u.bytes[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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) ||
|
||||
@@ -688,7 +649,7 @@ int CBB_flush_asn1_set_of(CBB *cbb) {
|
||||
// remain valid as we rewrite |cbb|.
|
||||
int ret = 0;
|
||||
size_t buf_len = CBB_len(cbb);
|
||||
uint8_t *buf = OPENSSL_memdup(CBB_data(cbb), buf_len);
|
||||
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;
|
||||
|
||||
+3
-60
@@ -12,6 +12,7 @@
|
||||
* 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 <openssl/mem.h>
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
@@ -60,7 +61,7 @@ int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
|
||||
if (cbs->len == 0) {
|
||||
return 1;
|
||||
}
|
||||
*out_ptr = OPENSSL_memdup(cbs->data, cbs->len);
|
||||
*out_ptr = BUF_memdup(cbs->data, cbs->len);
|
||||
if (*out_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -72,7 +73,7 @@ int CBS_strdup(const CBS *cbs, char **out_ptr) {
|
||||
if (*out_ptr != NULL) {
|
||||
OPENSSL_free(*out_ptr);
|
||||
}
|
||||
*out_ptr = OPENSSL_strndup((const char*)cbs->data, cbs->len);
|
||||
*out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
|
||||
return (*out_ptr != NULL);
|
||||
}
|
||||
|
||||
@@ -120,14 +121,6 @@ int CBS_get_u16(CBS *cbs, uint16_t *out) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u16le(CBS *cbs, uint16_t *out) {
|
||||
if (!CBS_get_u16(cbs, out)) {
|
||||
return 0;
|
||||
}
|
||||
*out = CRYPTO_bswap2(*out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u24(CBS *cbs, uint32_t *out) {
|
||||
uint64_t v;
|
||||
if (!cbs_get_u(cbs, &v, 3)) {
|
||||
@@ -146,26 +139,10 @@ int CBS_get_u32(CBS *cbs, uint32_t *out) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u32le(CBS *cbs, uint32_t *out) {
|
||||
if (!CBS_get_u32(cbs, out)) {
|
||||
return 0;
|
||||
}
|
||||
*out = CRYPTO_bswap4(*out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u64(CBS *cbs, uint64_t *out) {
|
||||
return cbs_get_u(cbs, out, 8);
|
||||
}
|
||||
|
||||
int CBS_get_u64le(CBS *cbs, uint64_t *out) {
|
||||
if (!cbs_get_u(cbs, out, 8)) {
|
||||
return 0;
|
||||
}
|
||||
*out = CRYPTO_bswap8(*out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
|
||||
if (cbs->len == 0) {
|
||||
return 0;
|
||||
@@ -461,40 +438,6 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_int64(CBS *cbs, int64_t *out) {
|
||||
CBS bytes;
|
||||
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
const uint8_t *data = CBS_data(&bytes);
|
||||
const size_t len = CBS_len(&bytes);
|
||||
|
||||
if (len == 0 || len > sizeof(int64_t)) {
|
||||
// An INTEGER is encoded with at least one octet.
|
||||
return 0;
|
||||
}
|
||||
if (len > 1) {
|
||||
if (data[0] == 0 && (data[1] & 0x80) == 0) {
|
||||
return 0; // Extra leading zeros.
|
||||
}
|
||||
if (data[0] == 0xff && (data[1] & 0x80) != 0) {
|
||||
return 0; // Extra leading 0xff.
|
||||
}
|
||||
}
|
||||
|
||||
union {
|
||||
int64_t i;
|
||||
uint8_t bytes[sizeof(int64_t)];
|
||||
} u;
|
||||
const int is_negative = (data[0] & 0x80);
|
||||
memset(u.bytes, is_negative ? 0xff : 0, sizeof(u.bytes)); // Sign-extend.
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
u.bytes[i] = data[len - i - 1];
|
||||
}
|
||||
*out = u.i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_bool(CBS *cbs, int *out) {
|
||||
CBS bytes;
|
||||
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "../fipsmodule/cipher/internal.h"
|
||||
#include "../internal.h"
|
||||
#include "../test/abi_test.h"
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
#include "../test/wycheproof_util.h"
|
||||
@@ -543,10 +542,10 @@ TEST_P(PerAEADTest, AliasedBuffers) {
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, UnalignedInput) {
|
||||
alignas(16) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
|
||||
alignas(16) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
|
||||
alignas(16) uint8_t plaintext[32 + 1];
|
||||
alignas(16) uint8_t ad[32 + 1];
|
||||
alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
|
||||
alignas(64) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
|
||||
alignas(64) uint8_t plaintext[32 + 1];
|
||||
alignas(64) uint8_t ad[32 + 1];
|
||||
OPENSSL_memset(key, 'K', sizeof(key));
|
||||
OPENSSL_memset(nonce, 'N', sizeof(nonce));
|
||||
OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
|
||||
@@ -564,7 +563,7 @@ TEST_P(PerAEADTest, UnalignedInput) {
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
|
||||
evp_aead_seal));
|
||||
alignas(16) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
|
||||
alignas(64) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
|
||||
size_t ciphertext_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext + 1, &ciphertext_len,
|
||||
sizeof(ciphertext) - 1, nonce + 1, nonce_len,
|
||||
@@ -572,7 +571,7 @@ TEST_P(PerAEADTest, UnalignedInput) {
|
||||
ad_len));
|
||||
|
||||
// It must successfully decrypt.
|
||||
alignas(16) uint8_t out[sizeof(ciphertext)];
|
||||
alignas(64) uint8_t out[sizeof(ciphertext)];
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
|
||||
@@ -586,7 +585,7 @@ TEST_P(PerAEADTest, UnalignedInput) {
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, Overflow) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 'K', sizeof(key));
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
@@ -665,91 +664,6 @@ TEST_P(PerAEADTest, InvalidNonceLength) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SUPPORTS_ABI_TEST)
|
||||
// CHECK_ABI can't pass enums, i.e. |evp_aead_seal| and |evp_aead_open|. Thus
|
||||
// these two wrappers.
|
||||
static int aead_ctx_init_for_seal(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
|
||||
const uint8_t *key, size_t key_len) {
|
||||
return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, 0,
|
||||
evp_aead_seal);
|
||||
}
|
||||
|
||||
static int aead_ctx_init_for_open(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
|
||||
const uint8_t *key, size_t key_len) {
|
||||
return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, 0,
|
||||
evp_aead_open);
|
||||
}
|
||||
|
||||
// CHECK_ABI can pass, at most, eight arguments. Thus these wrappers that
|
||||
// figure out the output length from the input length, and take the nonce length
|
||||
// from the configuration of the AEAD.
|
||||
static int aead_ctx_seal(EVP_AEAD_CTX *ctx, uint8_t *out_ciphertext,
|
||||
size_t *out_ciphertext_len, const uint8_t *nonce,
|
||||
const uint8_t *plaintext, size_t plaintext_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(ctx));
|
||||
return EVP_AEAD_CTX_seal(ctx, out_ciphertext, out_ciphertext_len,
|
||||
plaintext_len + EVP_AEAD_MAX_OVERHEAD, nonce,
|
||||
nonce_len, plaintext, plaintext_len, ad, ad_len);
|
||||
}
|
||||
|
||||
static int aead_ctx_open(EVP_AEAD_CTX *ctx, uint8_t *out_plaintext,
|
||||
size_t *out_plaintext_len, const uint8_t *nonce,
|
||||
const uint8_t *ciphertext, size_t ciphertext_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(ctx));
|
||||
return EVP_AEAD_CTX_open(ctx, out_plaintext, out_plaintext_len,
|
||||
ciphertext_len, nonce, nonce_len, ciphertext,
|
||||
ciphertext_len, ad, ad_len);
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, ABI) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 'K', sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
ASSERT_LE(key_len, sizeof(key));
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx_seal;
|
||||
ASSERT_TRUE(
|
||||
CHECK_ABI(aead_ctx_init_for_seal, ctx_seal.get(), aead(), key, key_len));
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx_open;
|
||||
ASSERT_TRUE(
|
||||
CHECK_ABI(aead_ctx_init_for_open, ctx_open.get(), aead(), key, key_len));
|
||||
|
||||
alignas(2) uint8_t plaintext[512];
|
||||
OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
|
||||
|
||||
alignas(2) uint8_t ad_buf[512];
|
||||
OPENSSL_memset(ad_buf, 'A', sizeof(ad_buf));
|
||||
const uint8_t *const ad = ad_buf + 1;
|
||||
ASSERT_LE(GetParam().ad_len, sizeof(ad_buf) - 1);
|
||||
const size_t ad_len =
|
||||
GetParam().ad_len != 0 ? GetParam().ad_len : sizeof(ad_buf) - 1;
|
||||
|
||||
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
ASSERT_LE(nonce_len, sizeof(nonce));
|
||||
|
||||
alignas(2) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD + 1];
|
||||
size_t ciphertext_len;
|
||||
// Knock plaintext, ciphertext, and AD off alignment and give odd lengths for
|
||||
// plaintext and AD. This hopefully triggers any edge-cases in the assembly.
|
||||
ASSERT_TRUE(CHECK_ABI(aead_ctx_seal, ctx_seal.get(), ciphertext + 1,
|
||||
&ciphertext_len, nonce, plaintext + 1,
|
||||
sizeof(plaintext) - 1, ad, ad_len));
|
||||
|
||||
alignas(2) uint8_t plaintext2[sizeof(ciphertext) + 1];
|
||||
size_t plaintext2_len;
|
||||
ASSERT_TRUE(CHECK_ABI(aead_ctx_open, ctx_open.get(), plaintext2 + 1,
|
||||
&plaintext2_len, nonce, ciphertext + 1, ciphertext_len,
|
||||
ad, ad_len));
|
||||
|
||||
EXPECT_EQ(Bytes(plaintext + 1, sizeof(plaintext) - 1),
|
||||
Bytes(plaintext2 + 1, plaintext2_len));
|
||||
}
|
||||
#endif // SUPPORTS_ABI_TEST
|
||||
|
||||
TEST(AEADTest, AESCCMLargeAD) {
|
||||
static const std::vector<uint8_t> kKey(16, 'A');
|
||||
static const std::vector<uint8_t> kNonce(13, 'N');
|
||||
@@ -814,8 +728,8 @@ static void RunWycheproofTestCase(FileTest *t, const EVP_AEAD *aead) {
|
||||
size_t out_len;
|
||||
// Wycheproof tags small AES-GCM IVs as "acceptable" and otherwise does not
|
||||
// use it in AEADs. Any AES-GCM IV that isn't 96 bits is absurd, but our API
|
||||
// supports those, so we treat SmallIv tests as valid.
|
||||
if (result.IsValid({"SmallIv"})) {
|
||||
// supports those, so we treat "acceptable" as "valid" here.
|
||||
if (result != WycheproofResult::kInvalid) {
|
||||
// Decryption should succeed.
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
|
||||
iv.data(), iv.size(), ct_and_tag.data(),
|
||||
@@ -909,12 +823,3 @@ TEST(AEADTest, WycheproofChaCha20Poly1305) {
|
||||
RunWycheproofTestCase(t, EVP_aead_chacha20_poly1305());
|
||||
});
|
||||
}
|
||||
|
||||
TEST(AEADTest, WycheproofXChaCha20Poly1305) {
|
||||
FileTestGTest(
|
||||
"third_party/wycheproof_testvectors/xchacha20_poly1305_test.txt",
|
||||
[](FileTest *t) {
|
||||
t->IgnoreInstruction("keySize");
|
||||
RunWycheproofTestCase(t, EVP_aead_xchacha20_poly1305());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1273,7 +1273,7 @@ do_length_block:\n";
|
||||
pop %rbp
|
||||
.cfi_adjust_cfa_offset -8
|
||||
ret
|
||||
.cfi_adjust_cfa_offset (8 * 7) + 288 + 32
|
||||
.cfi_adjust_cfa_offset (8 * 6) + 288 + 32
|
||||
################################################################################
|
||||
seal_sse_128:
|
||||
movdqu .chacha20_consts(%rip), $A0\nmovdqa $A0, $A1\nmovdqa $A0, $A2
|
||||
|
||||
@@ -61,10 +61,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/span.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
@@ -120,8 +118,7 @@ static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
}
|
||||
|
||||
static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
|
||||
bssl::Span<const uint8_t> in, size_t chunk,
|
||||
bool in_place) {
|
||||
bssl::Span<const uint8_t> in, size_t chunk) {
|
||||
size_t max_out = in.size();
|
||||
if ((EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_NO_PADDING) == 0 &&
|
||||
EVP_CIPHER_CTX_encrypting(ctx)) {
|
||||
@@ -129,10 +126,6 @@ static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
|
||||
max_out += block_size - (max_out % block_size);
|
||||
}
|
||||
out->resize(max_out);
|
||||
if (in_place) {
|
||||
std::copy(in.begin(), in.end(), out->begin());
|
||||
in = bssl::MakeConstSpan(out->data(), in.size());
|
||||
}
|
||||
|
||||
size_t total = 0;
|
||||
int len;
|
||||
@@ -157,7 +150,7 @@ static bool DoCipher(EVP_CIPHER_CTX *ctx, std::vector<uint8_t> *out,
|
||||
}
|
||||
|
||||
static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
|
||||
bool copy, bool in_place, size_t chunk_size,
|
||||
bool copy, size_t chunk_size,
|
||||
const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &iv,
|
||||
const std::vector<uint8_t> &plaintext,
|
||||
@@ -214,7 +207,7 @@ static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
|
||||
}
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx, 0));
|
||||
std::vector<uint8_t> result;
|
||||
ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size, in_place));
|
||||
ASSERT_TRUE(DoCipher(ctx, &result, *in, chunk_size));
|
||||
EXPECT_EQ(Bytes(*out), Bytes(result));
|
||||
if (encrypt && is_aead) {
|
||||
uint8_t rtag[16];
|
||||
@@ -223,91 +216,6 @@ static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag.size(), rtag));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size()));
|
||||
}
|
||||
|
||||
// Additionally test low-level AES mode APIs. Skip runs where |copy| because
|
||||
// it does not apply.
|
||||
if (!copy) {
|
||||
int nid = EVP_CIPHER_nid(cipher);
|
||||
bool is_ctr = nid == NID_aes_128_ctr || nid == NID_aes_192_ctr ||
|
||||
nid == NID_aes_256_ctr;
|
||||
bool is_cbc = nid == NID_aes_128_cbc || nid == NID_aes_192_cbc ||
|
||||
nid == NID_aes_256_cbc;
|
||||
bool is_ofb = nid == NID_aes_128_ofb128 || nid == NID_aes_192_ofb128 ||
|
||||
nid == NID_aes_256_ofb128;
|
||||
if (is_ctr || is_cbc || is_ofb) {
|
||||
AES_KEY aes;
|
||||
if (encrypt || !is_cbc) {
|
||||
ASSERT_EQ(0, AES_set_encrypt_key(key.data(), key.size() * 8, &aes));
|
||||
} else {
|
||||
ASSERT_EQ(0, AES_set_decrypt_key(key.data(), key.size() * 8, &aes));
|
||||
}
|
||||
|
||||
// The low-level APIs all work in-place.
|
||||
bssl::Span<const uint8_t> input = *in;
|
||||
result.clear();
|
||||
if (in_place) {
|
||||
result = *in;
|
||||
input = result;
|
||||
} else {
|
||||
result.resize(out->size());
|
||||
}
|
||||
bssl::Span<uint8_t> output = bssl::MakeSpan(result);
|
||||
ASSERT_EQ(input.size(), output.size());
|
||||
|
||||
// The low-level APIs all use block-size IVs.
|
||||
ASSERT_EQ(iv.size(), size_t{AES_BLOCK_SIZE});
|
||||
uint8_t ivec[AES_BLOCK_SIZE];
|
||||
OPENSSL_memcpy(ivec, iv.data(), iv.size());
|
||||
|
||||
if (is_ctr) {
|
||||
unsigned num = 0;
|
||||
uint8_t ecount_buf[AES_BLOCK_SIZE];
|
||||
if (chunk_size == 0) {
|
||||
AES_ctr128_encrypt(input.data(), output.data(), input.size(), &aes,
|
||||
ivec, ecount_buf, &num);
|
||||
} else {
|
||||
do {
|
||||
size_t todo = std::min(input.size(), chunk_size);
|
||||
AES_ctr128_encrypt(input.data(), output.data(), todo, &aes, ivec,
|
||||
ecount_buf, &num);
|
||||
input = input.subspan(todo);
|
||||
output = output.subspan(todo);
|
||||
} while (!input.empty());
|
||||
}
|
||||
EXPECT_EQ(Bytes(*out), Bytes(result));
|
||||
} else if (is_cbc && chunk_size % AES_BLOCK_SIZE == 0) {
|
||||
// Note |AES_cbc_encrypt| requires block-aligned chunks.
|
||||
if (chunk_size == 0) {
|
||||
AES_cbc_encrypt(input.data(), output.data(), input.size(), &aes, ivec,
|
||||
encrypt);
|
||||
} else {
|
||||
do {
|
||||
size_t todo = std::min(input.size(), chunk_size);
|
||||
AES_cbc_encrypt(input.data(), output.data(), todo, &aes, ivec,
|
||||
encrypt);
|
||||
input = input.subspan(todo);
|
||||
output = output.subspan(todo);
|
||||
} while (!input.empty());
|
||||
}
|
||||
EXPECT_EQ(Bytes(*out), Bytes(result));
|
||||
} else if (is_ofb) {
|
||||
int num = 0;
|
||||
if (chunk_size == 0) {
|
||||
AES_ofb128_encrypt(input.data(), output.data(), input.size(), &aes,
|
||||
ivec, &num);
|
||||
} else {
|
||||
do {
|
||||
size_t todo = std::min(input.size(), chunk_size);
|
||||
AES_ofb128_encrypt(input.data(), output.data(), todo, &aes, ivec,
|
||||
&num);
|
||||
input = input.subspan(todo);
|
||||
output = output.subspan(todo);
|
||||
} while (!input.empty());
|
||||
}
|
||||
EXPECT_EQ(Bytes(*out), Bytes(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TestCipher(FileTest *t) {
|
||||
@@ -349,24 +257,21 @@ static void TestCipher(FileTest *t) {
|
||||
|
||||
for (size_t chunk_size : chunk_sizes) {
|
||||
SCOPED_TRACE(chunk_size);
|
||||
for (bool copy : {false, true}) {
|
||||
SCOPED_TRACE(copy);
|
||||
for (bool in_place : {false, true}) {
|
||||
SCOPED_TRACE(in_place);
|
||||
// By default, both directions are run, unless overridden by the
|
||||
// operation.
|
||||
if (operation != kDecrypt) {
|
||||
SCOPED_TRACE("encrypt");
|
||||
TestOperation(t, cipher, true /* encrypt */, copy, in_place,
|
||||
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt) {
|
||||
SCOPED_TRACE("encrypt");
|
||||
TestOperation(t, cipher, true /* encrypt */, false /* no copy */,
|
||||
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
|
||||
TestOperation(t, cipher, true /* encrypt */, true /* copy */, chunk_size,
|
||||
key, iv, plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
|
||||
if (operation != kEncrypt) {
|
||||
SCOPED_TRACE("decrypt");
|
||||
TestOperation(t, cipher, false /* decrypt */, copy, in_place,
|
||||
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
}
|
||||
if (operation != kEncrypt) {
|
||||
SCOPED_TRACE("decrypt");
|
||||
TestOperation(t, cipher, false /* decrypt */, false /* no copy */,
|
||||
chunk_size, key, iv, plaintext, ciphertext, aad, tag);
|
||||
TestOperation(t, cipher, false /* decrypt */, true /* copy */, chunk_size,
|
||||
key, iv, plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,63 +319,59 @@ TEST(CipherTest, CAVP_TDES_ECB) {
|
||||
}
|
||||
|
||||
TEST(CipherTest, WycheproofAESCBC) {
|
||||
FileTestGTest(
|
||||
"third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
|
||||
[](FileTest *t) {
|
||||
t->IgnoreInstruction("type");
|
||||
t->IgnoreInstruction("ivSize");
|
||||
FileTestGTest("third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
|
||||
[](FileTest *t) {
|
||||
t->IgnoreInstruction("type");
|
||||
t->IgnoreInstruction("ivSize");
|
||||
|
||||
std::string key_size;
|
||||
ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
|
||||
const EVP_CIPHER *cipher;
|
||||
switch (atoi(key_size.c_str())) {
|
||||
case 128:
|
||||
cipher = EVP_aes_128_cbc();
|
||||
break;
|
||||
case 192:
|
||||
cipher = EVP_aes_192_cbc();
|
||||
break;
|
||||
case 256:
|
||||
cipher = EVP_aes_256_cbc();
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Unsupported key size: " << key_size;
|
||||
}
|
||||
std::string key_size;
|
||||
ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
|
||||
const EVP_CIPHER *cipher;
|
||||
switch (atoi(key_size.c_str())) {
|
||||
case 128:
|
||||
cipher = EVP_aes_128_cbc();
|
||||
break;
|
||||
case 192:
|
||||
cipher = EVP_aes_192_cbc();
|
||||
break;
|
||||
case 256:
|
||||
cipher = EVP_aes_256_cbc();
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Unsupported key size: " << key_size;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> key, iv, msg, ct;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "key"));
|
||||
ASSERT_TRUE(t->GetBytes(&iv, "iv"));
|
||||
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "ct"));
|
||||
ASSERT_EQ(EVP_CIPHER_key_length(cipher), key.size());
|
||||
ASSERT_EQ(EVP_CIPHER_iv_length(cipher), iv.size());
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
std::vector<uint8_t> key, iv, msg, ct;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "key"));
|
||||
ASSERT_TRUE(t->GetBytes(&iv, "iv"));
|
||||
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "ct"));
|
||||
ASSERT_EQ(EVP_CIPHER_key_length(cipher), key.size());
|
||||
ASSERT_EQ(EVP_CIPHER_iv_length(cipher), iv.size());
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
|
||||
bssl::ScopedEVP_CIPHER_CTX ctx;
|
||||
std::vector<uint8_t> out;
|
||||
const std::vector<size_t> chunk_sizes = {
|
||||
0, 1, 2, 5, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 512};
|
||||
for (size_t chunk : chunk_sizes) {
|
||||
SCOPED_TRACE(chunk);
|
||||
for (bool in_place : {false, true}) {
|
||||
SCOPED_TRACE(in_place);
|
||||
if (result.IsValid()) {
|
||||
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr,
|
||||
key.data(), iv.data()));
|
||||
ASSERT_TRUE(DoCipher(ctx.get(), &out, ct, chunk, in_place));
|
||||
EXPECT_EQ(Bytes(msg), Bytes(out));
|
||||
bssl::ScopedEVP_CIPHER_CTX ctx;
|
||||
std::vector<uint8_t> out;
|
||||
const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
|
||||
17, 31, 32, 33, 63, 64, 65, 512};
|
||||
for (size_t chunk : chunk_sizes) {
|
||||
SCOPED_TRACE(chunk);
|
||||
if (result == WycheproofResult::kValid) {
|
||||
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
|
||||
iv.data()));
|
||||
ASSERT_TRUE(DoCipher(ctx.get(), &out, ct, chunk));
|
||||
EXPECT_EQ(Bytes(msg), Bytes(out));
|
||||
|
||||
ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr,
|
||||
key.data(), iv.data()));
|
||||
ASSERT_TRUE(DoCipher(ctx.get(), &out, msg, chunk, in_place));
|
||||
EXPECT_EQ(Bytes(ct), Bytes(out));
|
||||
} else {
|
||||
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr,
|
||||
key.data(), iv.data()));
|
||||
EXPECT_FALSE(DoCipher(ctx.get(), &out, ct, chunk, in_place));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
|
||||
iv.data()));
|
||||
ASSERT_TRUE(DoCipher(ctx.get(), &out, msg, chunk));
|
||||
EXPECT_EQ(Bytes(ct), Bytes(out));
|
||||
} else {
|
||||
ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(),
|
||||
iv.data()));
|
||||
EXPECT_FALSE(DoCipher(ctx.get(), &out, ct, chunk));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
|
||||
EVP_MD_CTX_init(&c);
|
||||
for (;;) {
|
||||
if (!EVP_DigestInit_ex(&c, md, NULL)) {
|
||||
goto err;
|
||||
return 0;
|
||||
}
|
||||
if (addmd++) {
|
||||
if (!EVP_DigestUpdate(&c, md_buf, mds)) {
|
||||
|
||||
@@ -723,14 +723,6 @@ static void gcm_siv_keys(
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
|
||||
// Note the |ctr128_f| function uses a big-endian couner, while AES-GCM-SIV
|
||||
// uses a little-endian counter. We ignore the return value and only use
|
||||
// |block128_f|. This has a significant performance cost for the fallback
|
||||
// bitsliced AES implementations (bsaes and aes_nohw).
|
||||
//
|
||||
// We currently do not consider AES-GCM-SIV to be performance-sensitive on
|
||||
// client hardware. If this changes, we can write little-endian |ctr128_f|
|
||||
// functions.
|
||||
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
|
||||
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
|
||||
}
|
||||
|
||||
@@ -133,7 +133,6 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
|
||||
assert(orig_len >= in_len);
|
||||
assert(in_len >= md_size);
|
||||
assert(md_size <= EVP_MAX_MD_SIZE);
|
||||
assert(md_size > 0);
|
||||
|
||||
// scan_start contains the number of bytes that we can ignore because
|
||||
// the MAC's position can only vary by 255 bytes.
|
||||
|
||||
@@ -148,7 +148,7 @@ TEST(CMACTest, Wycheproof) {
|
||||
// Some test vectors intentionally give the wrong key size. Our API
|
||||
// requires the caller pick the sized CBC primitive, so these tests
|
||||
// aren't useful for us.
|
||||
EXPECT_FALSE(result.IsValid());
|
||||
EXPECT_EQ(WycheproofResult::kInvalid, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ TEST(CMACTest, Wycheproof) {
|
||||
// Truncate the tag, if requested.
|
||||
out_len = std::min(out_len, tag_len);
|
||||
|
||||
if (result.IsValid()) {
|
||||
if (result == WycheproofResult::kValid) {
|
||||
EXPECT_EQ(Bytes(tag), Bytes(out, out_len));
|
||||
|
||||
// Test the streaming API as well.
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/arm_arch.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "cpu-arm-linux.h"
|
||||
@@ -146,13 +147,11 @@ extern uint32_t OPENSSL_armcap_P;
|
||||
static int g_has_broken_neon, g_needs_hwcap2_workaround;
|
||||
|
||||
void OPENSSL_cpuid_setup(void) {
|
||||
// We ignore the return value of |read_file| and proceed with an empty
|
||||
// /proc/cpuinfo on error. If |getauxval| works, we will still detect
|
||||
// capabilities. There may be a false positive due to
|
||||
// |crypto_cpuinfo_has_broken_neon|, but this is now rare.
|
||||
char *cpuinfo_data = NULL;
|
||||
size_t cpuinfo_len = 0;
|
||||
read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo");
|
||||
char *cpuinfo_data;
|
||||
size_t cpuinfo_len;
|
||||
if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) {
|
||||
return;
|
||||
}
|
||||
STRING_PIECE cpuinfo;
|
||||
cpuinfo.data = cpuinfo_data;
|
||||
cpuinfo.len = cpuinfo_len;
|
||||
|
||||
@@ -220,13 +220,6 @@ TEST(ARMLinuxTest, CPUInfo) {
|
||||
0,
|
||||
false,
|
||||
},
|
||||
// If opening /proc/cpuinfo fails, we process the empty string.
|
||||
{
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto &t : kTests) {
|
||||
|
||||
+4
-21
@@ -123,28 +123,15 @@ static uint64_t OPENSSL_xgetbv(uint32_t xcr) {
|
||||
// and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this.
|
||||
static void handle_cpu_env(uint32_t *out, const char *in) {
|
||||
const int invert = in[0] == '~';
|
||||
const int or = in[0] == '|';
|
||||
const int skip_first_byte = invert || or;
|
||||
const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x';
|
||||
|
||||
int sscanf_result;
|
||||
uint64_t v;
|
||||
if (hex) {
|
||||
sscanf_result = sscanf(in + invert + 2, "%" PRIx64, &v);
|
||||
} else {
|
||||
sscanf_result = sscanf(in + invert, "%" PRIu64, &v);
|
||||
}
|
||||
|
||||
if (!sscanf_result) {
|
||||
if (!sscanf(in + invert, "%" PRIu64, &v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (invert) {
|
||||
out[0] &= ~v;
|
||||
out[1] &= ~(v >> 32);
|
||||
} else if (or) {
|
||||
out[0] |= v;
|
||||
out[1] |= (v >> 32);
|
||||
} else {
|
||||
out[0] = v;
|
||||
out[1] = v >> 32;
|
||||
@@ -269,14 +256,10 @@ void OPENSSL_cpuid_setup(void) {
|
||||
|
||||
// OPENSSL_ia32cap can contain zero, one or two values, separated with a ':'.
|
||||
// Each value is a 64-bit, unsigned value which may start with "0x" to
|
||||
// indicate a hex value. Prior to the 64-bit value, a '~' or '|' may be given.
|
||||
// indicate a hex value. Prior to the 64-bit value, a '~' may be given.
|
||||
//
|
||||
// If the '~' prefix is present:
|
||||
// the value is inverted and ANDed with the probed CPUID result
|
||||
// If the '|' prefix is present:
|
||||
// the value is ORed with the probed CPUID result
|
||||
// Otherwise:
|
||||
// the value is taken as the result of the CPUID
|
||||
// If '~' isn't present, then the value is taken as the result of the CPUID.
|
||||
// Otherwise the value is inverted and ANDed with the probed CPUID result.
|
||||
//
|
||||
// The first value determines OPENSSL_ia32cap_P[0] and [1]. The second [2]
|
||||
// and [3].
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
#include <openssl/cpu.h>
|
||||
|
||||
#include "fipsmodule/rand/fork_detect.h"
|
||||
#include "fipsmodule/rand/internal.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
@@ -176,15 +174,6 @@ int CRYPTO_has_asm(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void CRYPTO_pre_sandbox_init(void) {
|
||||
// Read from /proc/cpuinfo if needed.
|
||||
CRYPTO_library_init();
|
||||
// Open /dev/urandom if needed.
|
||||
CRYPTO_init_sysrand();
|
||||
// Set up MADV_WIPEONFORK state if needed.
|
||||
CRYPTO_get_fork_generation();
|
||||
}
|
||||
|
||||
const char *SSLeay_version(int which) { return OpenSSL_version(which); }
|
||||
|
||||
const char *OpenSSL_version(int which) {
|
||||
|
||||
@@ -2129,8 +2129,8 @@ mov sp,r12
|
||||
vpop {q4,q5,q6,q7}
|
||||
bx lr
|
||||
|
||||
#endif /* !OPENSSL_NO_ASM && __arm__ && !__APPLE__ */
|
||||
|
||||
#if defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
#endif /* !OPENSSL_NO_ASM && __arm__ && !__APPLE__ */
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "./internal.h"
|
||||
#include "../../third_party/fiat/internal.h"
|
||||
|
||||
|
||||
// The following precomputation tables are for the following
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "./internal.h"
|
||||
#include "../../third_party/fiat/internal.h"
|
||||
|
||||
|
||||
// TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down.
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
#include "../test/wycheproof_util.h"
|
||||
|
||||
|
||||
TEST(X25519Test, TestVector) {
|
||||
@@ -133,8 +132,11 @@ TEST(X25519Test, Wycheproof) {
|
||||
t->IgnoreInstruction("curve");
|
||||
t->IgnoreAttribute("curve");
|
||||
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
// Our implementation tolerates the Wycheproof "acceptable"
|
||||
// inputs. Wycheproof's valid vs. acceptable criteria does not match our
|
||||
// X25519 return value, so we test only the overall output.
|
||||
t->IgnoreAttribute("result");
|
||||
|
||||
std::vector<uint8_t> priv, pub, shared;
|
||||
ASSERT_TRUE(t->GetBytes(&priv, "private"));
|
||||
ASSERT_TRUE(t->GetBytes(&pub, "public"));
|
||||
@@ -142,8 +144,7 @@ TEST(X25519Test, Wycheproof) {
|
||||
ASSERT_EQ(32u, priv.size());
|
||||
ASSERT_EQ(32u, pub.size());
|
||||
uint8_t secret[32];
|
||||
int ret = X25519(secret, priv.data(), pub.data());
|
||||
EXPECT_EQ(ret, result.IsValid({"NonCanonicalPublic", "Twist"}) ? 1 : 0);
|
||||
X25519(secret, priv.data(), pub.data());
|
||||
EXPECT_EQ(Bytes(secret), Bytes(shared));
|
||||
});
|
||||
}
|
||||
|
||||
+3
-3
@@ -151,7 +151,7 @@ int DH_check(const DH *dh, int *out_flags) {
|
||||
*out_flags |= DH_CHECK_NOT_SUITABLE_GENERATOR;
|
||||
}
|
||||
}
|
||||
r = BN_is_prime_ex(dh->q, BN_prime_checks_for_validation, ctx, NULL);
|
||||
r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
|
||||
if (r < 0) {
|
||||
goto err;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ int DH_check(const DH *dh, int *out_flags) {
|
||||
*out_flags |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR;
|
||||
}
|
||||
|
||||
r = BN_is_prime_ex(dh->p, BN_prime_checks_for_validation, ctx, NULL);
|
||||
r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
|
||||
if (r < 0) {
|
||||
goto err;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ int DH_check(const DH *dh, int *out_flags) {
|
||||
if (!BN_rshift1(t1, dh->p)) {
|
||||
goto err;
|
||||
}
|
||||
r = BN_is_prime_ex(t1, BN_prime_checks_for_validation, ctx, NULL);
|
||||
r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
|
||||
if (r < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
+2
-16
@@ -59,6 +59,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ex_data.h>
|
||||
#include <openssl/mem.h>
|
||||
@@ -113,16 +114,6 @@ void DH_free(DH *dh) {
|
||||
OPENSSL_free(dh);
|
||||
}
|
||||
|
||||
const BIGNUM *DH_get0_pub_key(const DH *dh) { return dh->pub_key; }
|
||||
|
||||
const BIGNUM *DH_get0_priv_key(const DH *dh) { return dh->priv_key; }
|
||||
|
||||
const BIGNUM *DH_get0_p(const DH *dh) { return dh->p; }
|
||||
|
||||
const BIGNUM *DH_get0_q(const DH *dh) { return dh->q; }
|
||||
|
||||
const BIGNUM *DH_get0_g(const DH *dh) { return dh->g; }
|
||||
|
||||
void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
|
||||
const BIGNUM **out_priv_key) {
|
||||
if (out_pub_key != NULL) {
|
||||
@@ -184,11 +175,6 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DH_set_length(DH *dh, unsigned priv_length) {
|
||||
dh->priv_length = priv_length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
|
||||
// We generate DH parameters as follows
|
||||
// find a prime q which is prime_bits/2 bits long.
|
||||
@@ -490,7 +476,7 @@ static int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
|
||||
to->seedlen = 0;
|
||||
|
||||
if (from->seed) {
|
||||
to->seed = OPENSSL_memdup(from->seed, from->seedlen);
|
||||
to->seed = BUF_memdup(from->seed, from->seedlen);
|
||||
if (!to->seed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224 };
|
||||
static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 };
|
||||
static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 };
|
||||
static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 };
|
||||
static const MD sha512_256 = { "SHA512-256", &EVP_sha512_256, &SHA512_256 };
|
||||
static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr };
|
||||
|
||||
struct DigestTestVector {
|
||||
@@ -70,88 +69,94 @@ struct DigestTestVector {
|
||||
static const DigestTestVector kTestVectors[] = {
|
||||
// MD4 tests, from RFC 1320. (crypto/md4 does not provide a
|
||||
// one-shot MD4 function.)
|
||||
{md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0"},
|
||||
{md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24"},
|
||||
{md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d"},
|
||||
{md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b"},
|
||||
{md4, "abcdefghijklmnopqrstuvwxyz", 1, "d79e1c308aa5bbcdeea8ed63df412da9"},
|
||||
{md4, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
|
||||
"043f8582f241db351ce627e153e7f0e4"},
|
||||
{md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536"},
|
||||
{ md4, "", 1, "31d6cfe0d16ae931b73c59d7e0c089c0" },
|
||||
{ md4, "a", 1, "bde52cb31de33e46245e05fbdbd6fb24" },
|
||||
{ md4, "abc", 1, "a448017aaf21d8525fc10ae87aa6729d" },
|
||||
{ md4, "message digest", 1, "d9130a8164549fe818874806e1c7014b" },
|
||||
{ md4, "abcdefghijklmnopqrstuvwxyz", 1,
|
||||
"d79e1c308aa5bbcdeea8ed63df412da9" },
|
||||
{ md4,
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
|
||||
"043f8582f241db351ce627e153e7f0e4" },
|
||||
{ md4, "1234567890", 8, "e33b4ddc9c38f2199c3e7b164fcc0536" },
|
||||
|
||||
// MD5 tests, from RFC 1321.
|
||||
{md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661"},
|
||||
{md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72"},
|
||||
{md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0"},
|
||||
{md5, "abcdefghijklmnopqrstuvwxyz", 1, "c3fcd3d76192e4007dfb496cca67e13b"},
|
||||
{md5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
|
||||
"d174ab98d277d9f5a5611c2c9f419d9f"},
|
||||
{md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a"},
|
||||
{ md5, "", 1, "d41d8cd98f00b204e9800998ecf8427e" },
|
||||
{ md5, "a", 1, "0cc175b9c0f1b6a831c399e269772661" },
|
||||
{ md5, "abc", 1, "900150983cd24fb0d6963f7d28e17f72" },
|
||||
{ md5, "message digest", 1, "f96b697d7cb7938d525a2f31aaf161d0" },
|
||||
{ md5, "abcdefghijklmnopqrstuvwxyz", 1,
|
||||
"c3fcd3d76192e4007dfb496cca67e13b" },
|
||||
{ md5,
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1,
|
||||
"d174ab98d277d9f5a5611c2c9f419d9f" },
|
||||
{ md5, "1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a" },
|
||||
|
||||
// SHA-1 tests, from RFC 3174.
|
||||
{sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d"},
|
||||
{sha1, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"84983e441c3bd26ebaae4aa1f95129e5e54670f1"},
|
||||
{sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"},
|
||||
{sha1, "0123456701234567012345670123456701234567012345670123456701234567",
|
||||
10, "dea356a2cddd90c7a7ecedc5ebb563934f460452"},
|
||||
{ sha1, "abc", 1, "a9993e364706816aba3e25717850c26c9cd0d89d" },
|
||||
{ sha1,
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"84983e441c3bd26ebaae4aa1f95129e5e54670f1" },
|
||||
{ sha1, "a", 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f" },
|
||||
{ sha1,
|
||||
"0123456701234567012345670123456701234567012345670123456701234567", 10,
|
||||
"dea356a2cddd90c7a7ecedc5ebb563934f460452" },
|
||||
|
||||
// SHA-224 tests, from RFC 3874.
|
||||
{sha224, "abc", 1,
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"},
|
||||
{sha224, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"},
|
||||
{sha224, "a", 1000000,
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"},
|
||||
{ sha224, "abc", 1,
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
|
||||
{ sha224,
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" },
|
||||
{ sha224,
|
||||
"a", 1000000,
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67" },
|
||||
|
||||
// SHA-256 tests, from NIST.
|
||||
{sha256, "abc", 1,
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"},
|
||||
{sha256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"},
|
||||
{ sha256, "abc", 1,
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
|
||||
{ sha256,
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
|
||||
|
||||
// SHA-384 tests, from NIST.
|
||||
{sha384, "abc", 1,
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
|
||||
"8086072ba1e7cc2358baeca134c825a7"},
|
||||
{sha384,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
1,
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
|
||||
"fcc7c71a557e2db966c3e9fa91746039"},
|
||||
{ sha384, "abc", 1,
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
|
||||
"8086072ba1e7cc2358baeca134c825a7" },
|
||||
{ sha384,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
|
||||
"fcc7c71a557e2db966c3e9fa91746039" },
|
||||
|
||||
// SHA-512 tests, from NIST.
|
||||
{sha512, "abc", 1,
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"},
|
||||
{sha512,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
1,
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"},
|
||||
|
||||
// SHA-512-256 tests, from
|
||||
// https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha512_256.pdf
|
||||
{sha512_256, "abc", 1,
|
||||
"53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"},
|
||||
{sha512_256,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopj"
|
||||
"klmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
1, "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"},
|
||||
{ sha512, "abc", 1,
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
|
||||
{ sha512,
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" },
|
||||
|
||||
// MD5-SHA1 tests.
|
||||
{md5_sha1, "abc", 1,
|
||||
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d"},
|
||||
{ md5_sha1, "abc", 1,
|
||||
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d" },
|
||||
};
|
||||
|
||||
static void CompareDigest(const DigestTestVector *test,
|
||||
const uint8_t *digest,
|
||||
size_t digest_len) {
|
||||
EXPECT_EQ(test->expected_hex,
|
||||
EncodeHex(bssl::MakeConstSpan(digest, digest_len)));
|
||||
static const char kHexTable[] = "0123456789abcdef";
|
||||
char digest_hex[2*EVP_MAX_MD_SIZE + 1];
|
||||
|
||||
for (size_t i = 0; i < digest_len; i++) {
|
||||
digest_hex[2*i] = kHexTable[digest[i] >> 4];
|
||||
digest_hex[2*i + 1] = kHexTable[digest[i] & 0xf];
|
||||
}
|
||||
digest_hex[2*digest_len] = '\0';
|
||||
|
||||
EXPECT_STREQ(test->expected_hex, digest_hex);
|
||||
}
|
||||
|
||||
static void TestDigest(const DigestTestVector *test) {
|
||||
|
||||
+2
-12
@@ -131,16 +131,6 @@ int DSA_up_ref(DSA *dsa) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const BIGNUM *DSA_get0_pub_key(const DSA *dsa) { return dsa->pub_key; }
|
||||
|
||||
const BIGNUM *DSA_get0_priv_key(const DSA *dsa) { return dsa->priv_key; }
|
||||
|
||||
const BIGNUM *DSA_get0_p(const DSA *dsa) { return dsa->p; }
|
||||
|
||||
const BIGNUM *DSA_get0_q(const DSA *dsa) { return dsa->q; }
|
||||
|
||||
const BIGNUM *DSA_get0_g(const DSA *dsa) { return dsa->g; }
|
||||
|
||||
void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key,
|
||||
const BIGNUM **out_priv_key) {
|
||||
if (out_pub_key != NULL) {
|
||||
@@ -266,7 +256,7 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
|
||||
// Find q.
|
||||
for (;;) {
|
||||
// step 1
|
||||
if (!BN_GENCB_call(cb, BN_GENCB_GENERATED, m++)) {
|
||||
if (!BN_GENCB_call(cb, 0, m++)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -329,7 +319,7 @@ int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
|
||||
n = (bits - 1) / 160;
|
||||
|
||||
for (;;) {
|
||||
if ((counter != 0) && !BN_GENCB_call(cb, BN_GENCB_GENERATED, counter)) {
|
||||
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/* Copyright (c) 2019, 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/ec_key.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../fipsmodule/ec/internal.h"
|
||||
|
||||
|
||||
EC_KEY *EC_KEY_derive_from_secret(const EC_GROUP *group, const uint8_t *secret,
|
||||
size_t secret_len) {
|
||||
#define EC_KEY_DERIVE_MAX_NAME_LEN 16
|
||||
const char *name = EC_curve_nid2nist(EC_GROUP_get_curve_name(group));
|
||||
if (name == NULL || strlen(name) > EC_KEY_DERIVE_MAX_NAME_LEN) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Assemble a label string to provide some key separation in case |secret| is
|
||||
// misused, but ultimately it's on the caller to ensure |secret| is suitably
|
||||
// separated.
|
||||
static const char kLabel[] = "derive EC key ";
|
||||
char info[sizeof(kLabel) + EC_KEY_DERIVE_MAX_NAME_LEN];
|
||||
OPENSSL_strlcpy(info, kLabel, sizeof(info));
|
||||
OPENSSL_strlcat(info, name, sizeof(info));
|
||||
|
||||
// Generate 128 bits beyond the group order so the bias is at most 2^-128.
|
||||
#define EC_KEY_DERIVE_EXTRA_BITS 128
|
||||
#define EC_KEY_DERIVE_EXTRA_BYTES (EC_KEY_DERIVE_EXTRA_BITS / 8)
|
||||
|
||||
if (EC_GROUP_order_bits(group) <= EC_KEY_DERIVE_EXTRA_BITS + 8) {
|
||||
// The reduction strategy below requires the group order be large enough.
|
||||
// (The actual bound is a bit tighter, but our curves are much larger than
|
||||
// 128-bit.)
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t derived[EC_KEY_DERIVE_EXTRA_BYTES + EC_MAX_BYTES];
|
||||
size_t derived_len = BN_num_bytes(&group->order) + EC_KEY_DERIVE_EXTRA_BYTES;
|
||||
assert(derived_len <= sizeof(derived));
|
||||
if (!HKDF(derived, derived_len, EVP_sha256(), secret, secret_len,
|
||||
/*salt=*/NULL, /*salt_len=*/0, (const uint8_t *)info,
|
||||
strlen(info))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EC_KEY *key = EC_KEY_new();
|
||||
BN_CTX *ctx = BN_CTX_new();
|
||||
BIGNUM *priv = BN_bin2bn(derived, derived_len, NULL);
|
||||
EC_POINT *pub = EC_POINT_new(group);
|
||||
if (key == NULL || ctx == NULL || priv == NULL || pub == NULL ||
|
||||
// Reduce |priv| with Montgomery reduction. First, convert "from"
|
||||
// Montgomery form to compute |priv| * R^-1 mod |order|. This requires
|
||||
// |priv| be under order * R, which is true if the group order is large
|
||||
// enough. 2^(num_bytes(order)) < 2^8 * order, so:
|
||||
//
|
||||
// priv < 2^8 * order * 2^128 < order * order < order * R
|
||||
!BN_from_montgomery(priv, priv, group->order_mont, ctx) ||
|
||||
// Multiply by R^2 and do another Montgomery reduction to compute
|
||||
// priv * R^-1 * R^2 * R^-1 = priv mod order.
|
||||
!BN_to_montgomery(priv, priv, group->order_mont, ctx) ||
|
||||
!EC_POINT_mul(group, pub, priv, NULL, NULL, ctx) ||
|
||||
!EC_KEY_set_group(key, group) || !EC_KEY_set_public_key(key, pub) ||
|
||||
!EC_KEY_set_private_key(key, priv)) {
|
||||
EC_KEY_free(key);
|
||||
key = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
OPENSSL_cleanse(derived, sizeof(derived));
|
||||
BN_CTX_free(ctx);
|
||||
BN_free(priv);
|
||||
EC_POINT_free(pub);
|
||||
return key;
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
/* Copyright (c) 2020, 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/ec.h>
|
||||
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../fipsmodule/bn/internal.h"
|
||||
#include "../fipsmodule/ec/internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
// This file implements hash-to-curve, as described in
|
||||
// draft-irtf-cfrg-hash-to-curve-07.
|
||||
//
|
||||
// This hash-to-curve implementation is written generically with the
|
||||
// expectation that we will eventually wish to support other curves. If it
|
||||
// becomes a performance bottleneck, some possible optimizations by
|
||||
// specializing it to the curve:
|
||||
//
|
||||
// - Rather than using a generic |felem_exp|, specialize the exponentation to
|
||||
// c2 with a faster addition chain.
|
||||
//
|
||||
// - |felem_mul| and |felem_sqr| are indirect calls to generic Montgomery
|
||||
// code. Given the few curves, we could specialize
|
||||
// |map_to_curve_simple_swu|. But doing this reasonably without duplicating
|
||||
// code in C is difficult. (C++ templates would be useful here.)
|
||||
//
|
||||
// - P-521's Z and c2 have small power-of-two absolute values. We could save
|
||||
// two multiplications in SSWU. (Other curves have reasonable values of Z
|
||||
// and inconvenient c2.) This is unlikely to be worthwhile without C++
|
||||
// templates to make specializing more convenient.
|
||||
|
||||
// expand_message_xmd implements the operation described in section 5.3.1 of
|
||||
// draft-irtf-cfrg-hash-to-curve-07. It returns one on success and zero on
|
||||
// allocation failure or if |out_len| was too large.
|
||||
static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
|
||||
const uint8_t *msg, size_t msg_len,
|
||||
const uint8_t *dst, size_t dst_len) {
|
||||
int ret = 0;
|
||||
const size_t block_size = EVP_MD_block_size(md);
|
||||
const size_t md_size = EVP_MD_size(md);
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
// Long DSTs are hashed down to size. See section 5.3.3.
|
||||
OPENSSL_STATIC_ASSERT(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
|
||||
uint8_t dst_buf[EVP_MAX_MD_SIZE];
|
||||
if (dst_len >= 256) {
|
||||
static const char kPrefix[] = "H2C-OVERSIZE-DST-";
|
||||
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(&ctx, kPrefix, sizeof(kPrefix) - 1) ||
|
||||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
|
||||
!EVP_DigestFinal_ex(&ctx, dst_buf, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
dst = dst_buf;
|
||||
dst_len = md_size;
|
||||
}
|
||||
uint8_t dst_len_u8 = (uint8_t)dst_len;
|
||||
|
||||
// Compute b_0.
|
||||
static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
|
||||
// If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
|
||||
// be returned. This depends on the static assert above.
|
||||
uint8_t l_i_b_str_zero[3] = {out_len >> 8, out_len, 0};
|
||||
uint8_t b_0[EVP_MAX_MD_SIZE];
|
||||
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(&ctx, kZeros, block_size) ||
|
||||
!EVP_DigestUpdate(&ctx, msg, msg_len) ||
|
||||
!EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
|
||||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
|
||||
!EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
|
||||
!EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
uint8_t b_i[EVP_MAX_MD_SIZE];
|
||||
uint8_t i = 1;
|
||||
while (out_len > 0) {
|
||||
if (i == 0) {
|
||||
// Input was too large.
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (i > 1) {
|
||||
for (size_t j = 0; j < md_size; j++) {
|
||||
b_i[j] ^= b_0[j];
|
||||
}
|
||||
} else {
|
||||
OPENSSL_memcpy(b_i, b_0, md_size);
|
||||
}
|
||||
|
||||
if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(&ctx, b_i, md_size) ||
|
||||
!EVP_DigestUpdate(&ctx, &i, 1) ||
|
||||
!EVP_DigestUpdate(&ctx, dst, dst_len) ||
|
||||
!EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
|
||||
!EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
size_t todo = out_len >= md_size ? md_size : out_len;
|
||||
OPENSSL_memcpy(out, b_i, todo);
|
||||
out += todo;
|
||||
out_len -= todo;
|
||||
i++;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// num_bytes_to_derive determines the number of bytes to derive when hashing to
|
||||
// a number modulo |modulus|. See the hash_to_field operation defined in
|
||||
// section 5.2 of draft-irtf-cfrg-hash-to-curve-07.
|
||||
static int num_bytes_to_derive(size_t *out, const BIGNUM *modulus, unsigned k) {
|
||||
size_t bits = BN_num_bits(modulus);
|
||||
size_t L = (bits + k + 7) / 8;
|
||||
// We require 2^(8*L) < 2^(2*bits - 2) <= n^2 so to fit in bounds for
|
||||
// |felem_reduce| and |ec_scalar_reduce|. All defined hash-to-curve suites
|
||||
// define |k| to be well under this bound. (|k| is usually around half of
|
||||
// |p_bits|.)
|
||||
if (L * 8 >= 2 * bits - 2 ||
|
||||
L > 2 * EC_MAX_BYTES) {
|
||||
assert(0);
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out = L;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// big_endian_to_words decodes |in| as a big-endian integer and writes the
|
||||
// result to |out|. |num_words| must be large enough to contain the output.
|
||||
static void big_endian_to_words(BN_ULONG *out, size_t num_words,
|
||||
const uint8_t *in, size_t len) {
|
||||
assert(len <= num_words * sizeof(BN_ULONG));
|
||||
// Ensure any excess bytes are zeroed.
|
||||
OPENSSL_memset(out, 0, num_words * sizeof(BN_ULONG));
|
||||
uint8_t *out_u8 = (uint8_t *)out;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
out_u8[len - 1 - i] = in[i];
|
||||
}
|
||||
}
|
||||
|
||||
// hash_to_field implements the operation described in section 5.2
|
||||
// of draft-irtf-cfrg-hash-to-curve-07, with count = 2. |k| is the security
|
||||
// factor.
|
||||
static int hash_to_field2(const EC_GROUP *group, const EVP_MD *md,
|
||||
EC_FELEM *out1, EC_FELEM *out2, const uint8_t *dst,
|
||||
size_t dst_len, unsigned k, const uint8_t *msg,
|
||||
size_t msg_len) {
|
||||
size_t L;
|
||||
uint8_t buf[4 * EC_MAX_BYTES];
|
||||
if (!num_bytes_to_derive(&L, &group->field, k) ||
|
||||
!expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len)) {
|
||||
return 0;
|
||||
}
|
||||
BN_ULONG words[2 * EC_MAX_WORDS];
|
||||
size_t num_words = 2 * group->field.width;
|
||||
big_endian_to_words(words, num_words, buf, L);
|
||||
group->meth->felem_reduce(group, out1, words, num_words);
|
||||
big_endian_to_words(words, num_words, buf + L, L);
|
||||
group->meth->felem_reduce(group, out2, words, num_words);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// hash_to_scalar behaves like |hash_to_field2| but returns a value modulo the
|
||||
// group order rather than a field element. |k| is the security factor.
|
||||
static int hash_to_scalar(const EC_GROUP *group, const EVP_MD *md,
|
||||
EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
|
||||
unsigned k, const uint8_t *msg, size_t msg_len) {
|
||||
size_t L;
|
||||
uint8_t buf[EC_MAX_BYTES * 2];
|
||||
if (!num_bytes_to_derive(&L, &group->order, k) ||
|
||||
!expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_ULONG words[2 * EC_MAX_WORDS];
|
||||
size_t num_words = 2 * group->order.width;
|
||||
big_endian_to_words(words, num_words, buf, L);
|
||||
ec_scalar_reduce(group, out, words, num_words);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void mul_A(const EC_GROUP *group, EC_FELEM *out,
|
||||
const EC_FELEM *in) {
|
||||
assert(group->a_is_minus3);
|
||||
EC_FELEM tmp;
|
||||
ec_felem_add(group, &tmp, in, in); // tmp = 2*in
|
||||
ec_felem_add(group, &tmp, &tmp, &tmp); // tmp = 4*in
|
||||
ec_felem_sub(group, out, in, &tmp); // out = -3*in
|
||||
}
|
||||
|
||||
static inline void mul_minus_A(const EC_GROUP *group, EC_FELEM *out,
|
||||
const EC_FELEM *in) {
|
||||
assert(group->a_is_minus3);
|
||||
EC_FELEM tmp;
|
||||
ec_felem_add(group, &tmp, in, in); // tmp = 2*in
|
||||
ec_felem_add(group, out, &tmp, in); // out = 3*in
|
||||
}
|
||||
|
||||
// sgn0_le implements the operation described in section 4.1.2 of
|
||||
// draft-irtf-cfrg-hash-to-curve-07.
|
||||
static BN_ULONG sgn0_le(const EC_GROUP *group, const EC_FELEM *a) {
|
||||
uint8_t buf[EC_MAX_BYTES];
|
||||
size_t len;
|
||||
ec_felem_to_bytes(group, buf, &len, a);
|
||||
return buf[len - 1] & 1;
|
||||
}
|
||||
|
||||
// map_to_curve_simple_swu implements the operation described in section 6.6.2
|
||||
// of draft-irtf-cfrg-hash-to-curve-07, using the optimization in appendix
|
||||
// D.2.1. It returns one on success and zero on error.
|
||||
static int map_to_curve_simple_swu(const EC_GROUP *group, const EC_FELEM *Z,
|
||||
const BN_ULONG *c1, size_t num_c1,
|
||||
const EC_FELEM *c2, EC_RAW_POINT *out,
|
||||
const EC_FELEM *u) {
|
||||
void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
|
||||
const EC_FELEM *b) = group->meth->felem_mul;
|
||||
void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
|
||||
group->meth->felem_sqr;
|
||||
|
||||
// This function requires the prime be 3 mod 4, and that A = -3.
|
||||
if (group->field.width == 0 || (group->field.d[0] & 3) != 3 ||
|
||||
!group->a_is_minus3) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_FELEM tv1, tv2, tv3, tv4, xd, x1n, x2n, tmp, gxd, gx1, y1, y2;
|
||||
felem_sqr(group, &tv1, u); // tv1 = u^2
|
||||
felem_mul(group, &tv3, Z, &tv1); // tv3 = Z * tv1
|
||||
felem_sqr(group, &tv2, &tv3); // tv2 = tv3^2
|
||||
ec_felem_add(group, &xd, &tv2, &tv3); // xd = tv2 + tv3
|
||||
ec_felem_add(group, &x1n, &xd, &group->one); // x1n = xd + 1
|
||||
felem_mul(group, &x1n, &x1n, &group->b); // x1n = x1n * B
|
||||
mul_minus_A(group, &xd, &xd); // xd = -A * xd
|
||||
BN_ULONG e1 = ec_felem_non_zero_mask(group, &xd); // e1 = xd == 0 [flipped]
|
||||
mul_A(group, &tmp, Z);
|
||||
ec_felem_select(group, &xd, e1, &xd, &tmp); // xd = CMOV(xd, Z * A, e1)
|
||||
felem_sqr(group, &tv2, &xd); // tv2 = xd^2
|
||||
felem_mul(group, &gxd, &tv2, &xd); // gxd = tv2 * xd = xd^3
|
||||
mul_A(group, &tv2, &tv2); // tv2 = A * tv2
|
||||
felem_sqr(group, &gx1, &x1n); // gx1 = x1n^2
|
||||
ec_felem_add(group, &gx1, &gx1, &tv2); // gx1 = gx1 + tv2
|
||||
felem_mul(group, &gx1, &gx1, &x1n); // gx1 = gx1 * x1n
|
||||
felem_mul(group, &tv2, &group->b, &gxd); // tv2 = B * gxd
|
||||
ec_felem_add(group, &gx1, &gx1, &tv2); // gx1 = gx1 + tv2
|
||||
felem_sqr(group, &tv4, &gxd); // tv4 = gxd^2
|
||||
felem_mul(group, &tv2, &gx1, &gxd); // tv2 = gx1 * gxd
|
||||
felem_mul(group, &tv4, &tv4, &tv2); // tv4 = tv4 * tv2
|
||||
group->meth->felem_exp(group, &y1, &tv4, c1, num_c1); // y1 = tv4^c1
|
||||
felem_mul(group, &y1, &y1, &tv2); // y1 = y1 * tv2
|
||||
felem_mul(group, &x2n, &tv3, &x1n); // x2n = tv3 * x1n
|
||||
felem_mul(group, &y2, &y1, c2); // y2 = y1 * c2
|
||||
felem_mul(group, &y2, &y2, &tv1); // y2 = y2 * tv1
|
||||
felem_mul(group, &y2, &y2, u); // y2 = y2 * u
|
||||
felem_sqr(group, &tv2, &y1); // tv2 = y1^2
|
||||
felem_mul(group, &tv2, &tv2, &gxd); // tv2 = tv2 * gxd
|
||||
ec_felem_sub(group, &tv3, &tv2, &gx1);
|
||||
BN_ULONG e2 =
|
||||
ec_felem_non_zero_mask(group, &tv3); // e2 = tv2 == gx1 [flipped]
|
||||
ec_felem_select(group, &x1n, e2, &x2n, &x1n); // xn = CMOV(x2n, x1n, e2)
|
||||
ec_felem_select(group, &y1, e2, &y2, &y1); // y = CMOV(y2, y1, e2)
|
||||
BN_ULONG sgn0_u = sgn0_le(group, u);
|
||||
BN_ULONG sgn0_y = sgn0_le(group, &y1);
|
||||
BN_ULONG e3 = sgn0_u ^ sgn0_y;
|
||||
e3 = ((BN_ULONG)0) - e3; // e3 = sgn0(u) == sgn0(y) [flipped]
|
||||
ec_felem_neg(group, &y2, &y1);
|
||||
ec_felem_select(group, &y1, e3, &y2, &y1); // y = CMOV(-y, y, e3)
|
||||
|
||||
// Appendix D.1 describes how to convert (x1n, xd, y1, 1) to Jacobian
|
||||
// coordinates. Note yd = 1. Also note that gxd computed above is xd^3.
|
||||
felem_mul(group, &out->X, &x1n, &xd); // X = xn * xd
|
||||
felem_mul(group, &out->Y, &y1, &gxd); // Y = yn * gxd = yn * xd^3
|
||||
out->Z = xd; // Z = xd
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hash_to_curve(const EC_GROUP *group, const EVP_MD *md,
|
||||
const EC_FELEM *Z, const EC_FELEM *c2, unsigned k,
|
||||
EC_RAW_POINT *out, const uint8_t *dst, size_t dst_len,
|
||||
const uint8_t *msg, size_t msg_len) {
|
||||
EC_FELEM u0, u1;
|
||||
if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compute |c1| = (p - 3) / 4.
|
||||
BN_ULONG c1[EC_MAX_WORDS];
|
||||
size_t num_c1 = group->field.width;
|
||||
if (!bn_copy_words(c1, num_c1, &group->field)) {
|
||||
return 0;
|
||||
}
|
||||
bn_rshift_words(c1, c1, /*shift=*/2, /*num=*/num_c1);
|
||||
|
||||
EC_RAW_POINT Q0, Q1;
|
||||
if (!map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q0, &u0) ||
|
||||
!map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q1, &u1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
group->meth->add(group, out, &Q0, &Q1); // R = Q0 + Q1
|
||||
// All our curves have cofactor one, so |clear_cofactor| is a no-op.
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int felem_from_u8(const EC_GROUP *group, EC_FELEM *out, uint8_t a) {
|
||||
uint8_t bytes[EC_MAX_BYTES] = {0};
|
||||
size_t len = BN_num_bytes(&group->field);
|
||||
bytes[len - 1] = a;
|
||||
return ec_felem_from_bytes(group, out, bytes, len);
|
||||
}
|
||||
|
||||
int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
|
||||
const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
|
||||
size_t dst_len, const uint8_t *msg, size_t msg_len) {
|
||||
// See section 8.3 of draft-irtf-cfrg-hash-to-curve-07.
|
||||
if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// kSqrt1728 was computed as follows in python3:
|
||||
//
|
||||
// p = 2**384 - 2**128 - 2**96 + 2**32 - 1
|
||||
// z3 = 12**3
|
||||
// c2 = pow(z3, (p+1)//4, p)
|
||||
// assert z3 == pow(c2, 2, p)
|
||||
// ", ".join("0x%02x" % b for b in c2.to_bytes(384//8, 'big')
|
||||
|
||||
static const uint8_t kSqrt1728[] = {
|
||||
0x01, 0x98, 0x77, 0xcc, 0x10, 0x41, 0xb7, 0x55, 0x57, 0x43, 0xc0, 0xae,
|
||||
0x2e, 0x3a, 0x3e, 0x61, 0xfb, 0x2a, 0xaa, 0x2e, 0x0e, 0x87, 0xea, 0x55,
|
||||
0x7a, 0x56, 0x3d, 0x8b, 0x59, 0x8a, 0x09, 0x40, 0xd0, 0xa6, 0x97, 0xa9,
|
||||
0xe0, 0xb9, 0xe9, 0x2c, 0xfa, 0xa3, 0x14, 0xf5, 0x83, 0xc9, 0xd0, 0x66
|
||||
};
|
||||
|
||||
// Z = -12, c2 = sqrt(1728)
|
||||
EC_FELEM Z, c2;
|
||||
if (!felem_from_u8(group, &Z, 12) ||
|
||||
!ec_felem_from_bytes(group, &c2, kSqrt1728, sizeof(kSqrt1728))) {
|
||||
return 0;
|
||||
}
|
||||
ec_felem_neg(group, &Z, &Z);
|
||||
|
||||
return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/192, out, dst,
|
||||
dst_len, msg, msg_len);
|
||||
}
|
||||
|
||||
int ec_hash_to_scalar_p384_xmd_sha512_draft07(
|
||||
const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
|
||||
const uint8_t *msg, size_t msg_len) {
|
||||
if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/192, msg,
|
||||
msg_len);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/* Copyright (c) 2020, 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_EC_EXTRA_INTERNAL_H
|
||||
#define OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
|
||||
|
||||
#include <openssl/ec.h>
|
||||
|
||||
#include "../fipsmodule/ec/internal.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// Hash-to-curve.
|
||||
//
|
||||
// The following functions implement primitives from
|
||||
// draft-irtf-cfrg-hash-to-curve. The |dst| parameter in each function is the
|
||||
// domain separation tag and must be unique for each protocol and between the
|
||||
// |hash_to_curve| and |hash_to_scalar| variants. See section 3.1 of the spec
|
||||
// for additional guidance on this parameter.
|
||||
|
||||
// ec_hash_to_curve_p384_xmd_sha512_sswu_draft07 hashes |msg| to a point on
|
||||
// |group| and writes the result to |out|, implementing the
|
||||
// P384_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-07. It
|
||||
// returns one on success and zero on error.
|
||||
OPENSSL_EXPORT int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
|
||||
const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
|
||||
size_t dst_len, const uint8_t *msg, size_t msg_len);
|
||||
|
||||
// ec_hash_to_scalar_p384_xmd_sha512_draft07 hashes |msg| to a scalar on |group|
|
||||
// and writes the result to |out|, using the hash_to_field operation from the
|
||||
// P384_XMD:SHA-512_SSWU_RO_ suite from draft-irtf-cfrg-hash-to-curve-07, but
|
||||
// generating a value modulo the group order rather than a field element.
|
||||
OPENSSL_EXPORT int ec_hash_to_scalar_p384_xmd_sha512_draft07(
|
||||
const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
|
||||
const uint8_t *msg, size_t msg_len);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif // OPENSSL_HEADER_EC_EXTRA_INTERNAL_H
|
||||
@@ -96,8 +96,8 @@ int ECDH_compute_key(void *out, size_t out_len, const EC_POINT *pub_key,
|
||||
uint8_t buf[EC_MAX_BYTES];
|
||||
size_t buf_len;
|
||||
if (!ec_point_mul_scalar(group, &shared_point, &pub_key->raw, priv) ||
|
||||
!ec_get_x_coordinate_as_bytes(group, buf, &buf_len, sizeof(buf),
|
||||
&shared_point)) {
|
||||
!ec_point_get_affine_coordinate_bytes(group, buf, NULL, &buf_len,
|
||||
sizeof(buf), &shared_point)) {
|
||||
OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -140,16 +140,22 @@ static void RunWycheproofTest(FileTest *t) {
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
std::vector<uint8_t> shared;
|
||||
ASSERT_TRUE(t->GetBytes(&shared, "shared"));
|
||||
// BoringSSL supports compressed coordinates.
|
||||
bool is_valid = result.IsValid({"CompressedPoint"});
|
||||
|
||||
// Wycheproof stores the peer key in an SPKI to mimic a Java API mistake.
|
||||
// This is non-standard and error-prone.
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, peer_spki.data(), peer_spki.size());
|
||||
bssl::UniquePtr<EVP_PKEY> peer_evp(EVP_parse_public_key(&cbs));
|
||||
if (!peer_evp || CBS_len(&cbs) != 0) {
|
||||
EXPECT_FALSE(is_valid);
|
||||
if (!peer_evp) {
|
||||
// Note some of Wycheproof's "acceptable" entries are unsupported by
|
||||
// BoringSSL because they test explicit curves (forbidden by RFC 5480),
|
||||
// while others are supported because they used compressed coordinates. If
|
||||
// the peer key fails to parse, we consider it to match "acceptable", but if
|
||||
// the resulting shared secret matches below, it too matches "acceptable".
|
||||
//
|
||||
// TODO(davidben): Use the flags field to disambiguate these. Possibly
|
||||
// first get the Wycheproof folks to use flags more consistently.
|
||||
EXPECT_NE(WycheproofResult::kValid, result);
|
||||
return;
|
||||
}
|
||||
EC_KEY *peer_ec = EVP_PKEY_get0_EC_KEY(peer_evp.get());
|
||||
@@ -164,11 +170,11 @@ static void RunWycheproofTest(FileTest *t) {
|
||||
int ret =
|
||||
ECDH_compute_key(actual.data(), actual.size(),
|
||||
EC_KEY_get0_public_key(peer_ec), key.get(), nullptr);
|
||||
if (is_valid) {
|
||||
if (result == WycheproofResult::kInvalid) {
|
||||
EXPECT_EQ(-1, ret);
|
||||
} else {
|
||||
EXPECT_EQ(static_cast<int>(actual.size()), ret);
|
||||
EXPECT_EQ(Bytes(shared), Bytes(actual.data(), static_cast<size_t>(ret)));
|
||||
} else {
|
||||
EXPECT_EQ(-1, ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+38
-39
@@ -382,16 +382,18 @@ char *ERR_error_string(uint32_t packed_error, char *ret) {
|
||||
OPENSSL_memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
|
||||
#endif
|
||||
|
||||
return ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
|
||||
ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
|
||||
void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
|
||||
char lib_buf[64], reason_buf[64];
|
||||
const char *lib_str, *reason_str;
|
||||
unsigned lib, reason;
|
||||
|
||||
if (len == 0) {
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
lib = ERR_GET_LIB(packed_error);
|
||||
@@ -423,7 +425,7 @@ char *ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
|
||||
if (len <= num_colons) {
|
||||
// In this situation it's not possible to ensure that the correct number
|
||||
// of colons are included in the output.
|
||||
return buf;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_colons; i++) {
|
||||
@@ -442,8 +444,6 @@ char *ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) {
|
||||
s = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// err_string_cmp is a compare function for searching error values with
|
||||
@@ -495,39 +495,38 @@ static const char *err_string_lookup(uint32_t lib, uint32_t key,
|
||||
|
||||
static const char *const kLibraryNames[ERR_NUM_LIBS] = {
|
||||
"invalid library (0)",
|
||||
"unknown library", // ERR_LIB_NONE
|
||||
"system library", // ERR_LIB_SYS
|
||||
"bignum routines", // ERR_LIB_BN
|
||||
"RSA routines", // ERR_LIB_RSA
|
||||
"Diffie-Hellman routines", // ERR_LIB_DH
|
||||
"public key routines", // ERR_LIB_EVP
|
||||
"memory buffer routines", // ERR_LIB_BUF
|
||||
"object identifier routines", // ERR_LIB_OBJ
|
||||
"PEM routines", // ERR_LIB_PEM
|
||||
"DSA routines", // ERR_LIB_DSA
|
||||
"X.509 certificate routines", // ERR_LIB_X509
|
||||
"ASN.1 encoding routines", // ERR_LIB_ASN1
|
||||
"configuration file routines", // ERR_LIB_CONF
|
||||
"common libcrypto routines", // ERR_LIB_CRYPTO
|
||||
"elliptic curve routines", // ERR_LIB_EC
|
||||
"SSL routines", // ERR_LIB_SSL
|
||||
"BIO routines", // ERR_LIB_BIO
|
||||
"PKCS7 routines", // ERR_LIB_PKCS7
|
||||
"PKCS8 routines", // ERR_LIB_PKCS8
|
||||
"X509 V3 routines", // ERR_LIB_X509V3
|
||||
"random number generator", // ERR_LIB_RAND
|
||||
"ENGINE routines", // ERR_LIB_ENGINE
|
||||
"OCSP routines", // ERR_LIB_OCSP
|
||||
"UI routines", // ERR_LIB_UI
|
||||
"COMP routines", // ERR_LIB_COMP
|
||||
"ECDSA routines", // ERR_LIB_ECDSA
|
||||
"ECDH routines", // ERR_LIB_ECDH
|
||||
"HMAC routines", // ERR_LIB_HMAC
|
||||
"Digest functions", // ERR_LIB_DIGEST
|
||||
"Cipher functions", // ERR_LIB_CIPHER
|
||||
"HKDF functions", // ERR_LIB_HKDF
|
||||
"Trust Token functions", // ERR_LIB_TRUST_TOKEN
|
||||
"User defined functions", // ERR_LIB_USER
|
||||
"unknown library", // ERR_LIB_NONE
|
||||
"system library", // ERR_LIB_SYS
|
||||
"bignum routines", // ERR_LIB_BN
|
||||
"RSA routines", // ERR_LIB_RSA
|
||||
"Diffie-Hellman routines", // ERR_LIB_DH
|
||||
"public key routines", // ERR_LIB_EVP
|
||||
"memory buffer routines", // ERR_LIB_BUF
|
||||
"object identifier routines", // ERR_LIB_OBJ
|
||||
"PEM routines", // ERR_LIB_PEM
|
||||
"DSA routines", // ERR_LIB_DSA
|
||||
"X.509 certificate routines", // ERR_LIB_X509
|
||||
"ASN.1 encoding routines", // ERR_LIB_ASN1
|
||||
"configuration file routines", // ERR_LIB_CONF
|
||||
"common libcrypto routines", // ERR_LIB_CRYPTO
|
||||
"elliptic curve routines", // ERR_LIB_EC
|
||||
"SSL routines", // ERR_LIB_SSL
|
||||
"BIO routines", // ERR_LIB_BIO
|
||||
"PKCS7 routines", // ERR_LIB_PKCS7
|
||||
"PKCS8 routines", // ERR_LIB_PKCS8
|
||||
"X509 V3 routines", // ERR_LIB_X509V3
|
||||
"random number generator", // ERR_LIB_RAND
|
||||
"ENGINE routines", // ERR_LIB_ENGINE
|
||||
"OCSP routines", // ERR_LIB_OCSP
|
||||
"UI routines", // ERR_LIB_UI
|
||||
"COMP routines", // ERR_LIB_COMP
|
||||
"ECDSA routines", // ERR_LIB_ECDSA
|
||||
"ECDH routines", // ERR_LIB_ECDH
|
||||
"HMAC routines", // ERR_LIB_HMAC
|
||||
"Digest functions", // ERR_LIB_DIGEST
|
||||
"Cipher functions", // ERR_LIB_CIPHER
|
||||
"HKDF functions", // ERR_LIB_HKDF
|
||||
"User defined functions", // ERR_LIB_USER
|
||||
};
|
||||
|
||||
const char *ERR_lib_error_string(uint32_t packed_error) {
|
||||
|
||||
@@ -63,7 +63,6 @@ var libraryNames = []string{
|
||||
"DIGEST",
|
||||
"CIPHER",
|
||||
"HKDF",
|
||||
"TRUST_TOKEN",
|
||||
"USER",
|
||||
}
|
||||
|
||||
|
||||
@@ -235,51 +235,3 @@ TEST(ErrTest, PreservesErrno) {
|
||||
EXPECT_EQ(EINVAL, errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(ErrTest, String) {
|
||||
char buf[128];
|
||||
const uint32_t err = ERR_PACK(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
|
||||
|
||||
EXPECT_STREQ(
|
||||
"error:0e000044:common libcrypto routines:OPENSSL_internal:internal "
|
||||
"error",
|
||||
ERR_error_string_n(err, buf, sizeof(buf)));
|
||||
|
||||
// The buffer is exactly the right size.
|
||||
EXPECT_STREQ(
|
||||
"error:0e000044:common libcrypto routines:OPENSSL_internal:internal "
|
||||
"error",
|
||||
ERR_error_string_n(err, buf, 73));
|
||||
|
||||
// If the buffer is too short, the string is truncated.
|
||||
EXPECT_STREQ(
|
||||
"error:0e000044:common libcrypto routines:OPENSSL_internal:internal "
|
||||
"erro",
|
||||
ERR_error_string_n(err, buf, 72));
|
||||
EXPECT_STREQ("error:0e000044:common libcrypto routines:OPENSSL_internal:",
|
||||
ERR_error_string_n(err, buf, 59));
|
||||
|
||||
// Truncated log lines always have the right number of colons.
|
||||
EXPECT_STREQ("error:0e000044:common libcrypto routines:OPENSSL_interna:",
|
||||
ERR_error_string_n(err, buf, 58));
|
||||
EXPECT_STREQ("error:0e000044:common libcrypto routines:OPENSSL_intern:",
|
||||
ERR_error_string_n(err, buf, 57));
|
||||
EXPECT_STREQ("error:0e000044:common libcryp::",
|
||||
ERR_error_string_n(err, buf, 32));
|
||||
EXPECT_STREQ("error:0e0000:::",
|
||||
ERR_error_string_n(err, buf, 16));
|
||||
EXPECT_STREQ("err::::",
|
||||
ERR_error_string_n(err, buf, 8));
|
||||
EXPECT_STREQ("::::",
|
||||
ERR_error_string_n(err, buf, 5));
|
||||
|
||||
// If the buffer is too short for even four colons, |ERR_error_string_n| does
|
||||
// not bother trying to preserve the format.
|
||||
EXPECT_STREQ("err", ERR_error_string_n(err, buf, 4));
|
||||
EXPECT_STREQ("er", ERR_error_string_n(err, buf, 3));
|
||||
EXPECT_STREQ("e", ERR_error_string_n(err, buf, 2));
|
||||
EXPECT_STREQ("", ERR_error_string_n(err, buf, 1));
|
||||
|
||||
// A buffer length of zero should not touch the buffer.
|
||||
ERR_error_string_n(err, nullptr, 0);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ SSL,118,BAD_WRITE_RETRY
|
||||
SSL,119,BIO_NOT_SET
|
||||
SSL,261,BLOCK_CIPHER_PAD_IS_WRONG
|
||||
SSL,120,BN_LIB
|
||||
SSL,255,BUFFERED_MESSAGES_ON_CIPHER_CHANGE
|
||||
SSL,121,BUFFER_TOO_SMALL
|
||||
SSL,275,CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD
|
||||
SSL,272,CANNOT_PARSE_LEAF_CERT
|
||||
@@ -36,7 +37,6 @@ SSL,292,CERT_DECOMPRESSION_FAILED
|
||||
SSL,127,CERT_LENGTH_MISMATCH
|
||||
SSL,128,CHANNEL_ID_NOT_P256
|
||||
SSL,129,CHANNEL_ID_SIGNATURE_INVALID
|
||||
SSL,304,CIPHER_MISMATCH_ON_EARLY_DATA
|
||||
SSL,130,CIPHER_OR_HASH_UNAVAILABLE
|
||||
SSL,131,CLIENTHELLO_PARSE_FAILED
|
||||
SSL,132,CLIENTHELLO_TLSEXT
|
||||
@@ -64,7 +64,6 @@ SSL,147,ERROR_ADDING_EXTENSION
|
||||
SSL,148,ERROR_IN_RECEIVED_CIPHER_LIST
|
||||
SSL,149,ERROR_PARSING_EXTENSION
|
||||
SSL,150,EXCESSIVE_MESSAGE_SIZE
|
||||
SSL,255,EXCESS_HANDSHAKE_DATA
|
||||
SSL,151,EXTRA_DATA_IN_MESSAGE
|
||||
SSL,152,FRAGMENT_MISMATCH
|
||||
SSL,153,GOT_NEXT_PROTO_WITHOUT_EXTENSION
|
||||
@@ -86,7 +85,6 @@ SSL,160,INVALID_SSL_SESSION
|
||||
SSL,161,INVALID_TICKET_KEYS_LENGTH
|
||||
SSL,302,KEY_USAGE_BIT_INCORRECT
|
||||
SSL,162,LENGTH_MISMATCH
|
||||
SSL,307,MISSING_ALPN
|
||||
SSL,164,MISSING_EXTENSION
|
||||
SSL,258,MISSING_KEY_SHARE
|
||||
SSL,165,MISSING_RSA_CERTIFICATE
|
||||
@@ -134,7 +132,6 @@ SSL,195,PSK_IDENTITY_NOT_FOUND
|
||||
SSL,196,PSK_NO_CLIENT_CB
|
||||
SSL,197,PSK_NO_SERVER_CB
|
||||
SSL,298,QUIC_INTERNAL_ERROR
|
||||
SSL,305,QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED
|
||||
SSL,198,READ_TIMEOUT_EXPIRED
|
||||
SSL,199,RECORD_LENGTH_MISMATCH
|
||||
SSL,200,RECORD_TOO_LARGE
|
||||
@@ -175,10 +172,6 @@ SSL,290,SSL_SESSION_ID_TOO_LONG
|
||||
SSL,276,TICKET_ENCRYPTION_FAILED
|
||||
SSL,297,TLS13_DOWNGRADE
|
||||
SSL,1049,TLSV1_ALERT_ACCESS_DENIED
|
||||
SSL,1114,TLSV1_ALERT_BAD_CERTIFICATE_HASH_VALUE
|
||||
SSL,1113,TLSV1_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE
|
||||
SSL,1116,TLSV1_ALERT_CERTIFICATE_REQUIRED
|
||||
SSL,1111,TLSV1_ALERT_CERTIFICATE_UNOBTAINABLE
|
||||
SSL,1050,TLSV1_ALERT_DECODE_ERROR
|
||||
SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED
|
||||
SSL,1051,TLSV1_ALERT_DECRYPT_ERROR
|
||||
@@ -186,15 +179,18 @@ SSL,1060,TLSV1_ALERT_EXPORT_RESTRICTION
|
||||
SSL,1086,TLSV1_ALERT_INAPPROPRIATE_FALLBACK
|
||||
SSL,1071,TLSV1_ALERT_INSUFFICIENT_SECURITY
|
||||
SSL,1080,TLSV1_ALERT_INTERNAL_ERROR
|
||||
SSL,1120,TLSV1_ALERT_NO_APPLICATION_PROTOCOL
|
||||
SSL,1100,TLSV1_ALERT_NO_RENEGOTIATION
|
||||
SSL,1070,TLSV1_ALERT_PROTOCOL_VERSION
|
||||
SSL,1022,TLSV1_ALERT_RECORD_OVERFLOW
|
||||
SSL,1048,TLSV1_ALERT_UNKNOWN_CA
|
||||
SSL,1115,TLSV1_ALERT_UNKNOWN_PSK_IDENTITY
|
||||
SSL,1112,TLSV1_ALERT_UNRECOGNIZED_NAME
|
||||
SSL,1110,TLSV1_ALERT_UNSUPPORTED_EXTENSION
|
||||
SSL,1090,TLSV1_ALERT_USER_CANCELLED
|
||||
SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE
|
||||
SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE
|
||||
SSL,1116,TLSV1_CERTIFICATE_REQUIRED
|
||||
SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE
|
||||
SSL,1115,TLSV1_UNKNOWN_PSK_IDENTITY
|
||||
SSL,1112,TLSV1_UNRECOGNIZED_NAME
|
||||
SSL,1110,TLSV1_UNSUPPORTED_EXTENSION
|
||||
SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST
|
||||
SSL,218,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
|
||||
SSL,219,TOO_MANY_EMPTY_FRAGMENTS
|
||||
@@ -204,7 +200,6 @@ SSL,300,TOO_MUCH_READ_EARLY_DATA
|
||||
SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
|
||||
SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
|
||||
SSL,293,UNCOMPRESSED_CERT_TOO_LARGE
|
||||
SSL,306,UNEXPECTED_COMPATIBILITY_MODE
|
||||
SSL,222,UNEXPECTED_EXTENSION
|
||||
SSL,279,UNEXPECTED_EXTENSION_ON_EARLY_DATA
|
||||
SSL,223,UNEXPECTED_MESSAGE
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
TRUST_TOKEN,111,BAD_VALIDITY_CHECK
|
||||
TRUST_TOKEN,101,BUFFER_TOO_SMALL
|
||||
TRUST_TOKEN,103,DECODE_ERROR
|
||||
TRUST_TOKEN,105,DECODE_FAILURE
|
||||
TRUST_TOKEN,109,INVALID_KEY_ID
|
||||
TRUST_TOKEN,106,INVALID_METADATA
|
||||
TRUST_TOKEN,113,INVALID_METADATA_KEY
|
||||
TRUST_TOKEN,114,INVALID_PROOF
|
||||
TRUST_TOKEN,110,INVALID_TOKEN
|
||||
TRUST_TOKEN,100,KEYGEN_FAILURE
|
||||
TRUST_TOKEN,108,NO_KEYS_CONFIGURED
|
||||
TRUST_TOKEN,112,NO_SRR_KEY_CONFIGURED
|
||||
TRUST_TOKEN,102,OVER_BATCHSIZE
|
||||
TRUST_TOKEN,104,SRR_SIGNATURE_ERROR
|
||||
TRUST_TOKEN,107,TOO_MANY_KEYS
|
||||
@@ -6,16 +6,13 @@ X509,104,CANT_CHECK_DH_KEY
|
||||
X509,105,CERT_ALREADY_IN_HASH_TABLE
|
||||
X509,106,CRL_ALREADY_DELTA
|
||||
X509,107,CRL_VERIFY_FAILURE
|
||||
X509,138,DELTA_CRL_WITHOUT_CRL_NUMBER
|
||||
X509,108,IDP_MISMATCH
|
||||
X509,109,INVALID_BIT_STRING_BITS_LEFT
|
||||
X509,110,INVALID_DIRECTORY
|
||||
X509,139,INVALID_FIELD_FOR_VERSION
|
||||
X509,111,INVALID_FIELD_NAME
|
||||
X509,136,INVALID_PARAMETER
|
||||
X509,112,INVALID_PSS_PARAMETERS
|
||||
X509,113,INVALID_TRUST
|
||||
X509,140,INVALID_VERSION
|
||||
X509,114,ISSUER_MISMATCH
|
||||
X509,115,KEY_TYPE_MISMATCH
|
||||
X509,116,KEY_VALUES_MISMATCH
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../bytestring/internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
@@ -387,145 +386,3 @@ err:
|
||||
EVP_PKEY_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **out, const uint8_t **inp, long len) {
|
||||
if (len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, *inp, (size_t)len);
|
||||
EVP_PKEY *ret = EVP_parse_public_key(&cbs);
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (out != NULL) {
|
||||
EVP_PKEY_free(*out);
|
||||
*out = ret;
|
||||
}
|
||||
*inp = CBS_data(&cbs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2d_PUBKEY(const EVP_PKEY *pkey, uint8_t **outp) {
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 128) ||
|
||||
!EVP_marshal_public_key(&cbb, pkey)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return -1;
|
||||
}
|
||||
return CBB_finish_i2d(&cbb, outp);
|
||||
}
|
||||
|
||||
RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len) {
|
||||
if (len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, *inp, (size_t)len);
|
||||
EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
|
||||
if (pkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
RSA *rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
if (rsa == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (out != NULL) {
|
||||
RSA_free(*out);
|
||||
*out = rsa;
|
||||
}
|
||||
*inp = CBS_data(&cbs);
|
||||
return rsa;
|
||||
}
|
||||
|
||||
int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp) {
|
||||
int ret = -1;
|
||||
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL ||
|
||||
!EVP_PKEY_set1_RSA(pkey, (RSA *)rsa)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = i2d_PUBKEY(pkey, outp);
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DSA *d2i_DSA_PUBKEY(DSA **out, const uint8_t **inp, long len) {
|
||||
if (len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, *inp, (size_t)len);
|
||||
EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
|
||||
if (pkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
DSA *dsa = EVP_PKEY_get1_DSA(pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
if (dsa == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (out != NULL) {
|
||||
DSA_free(*out);
|
||||
*out = dsa;
|
||||
}
|
||||
*inp = CBS_data(&cbs);
|
||||
return dsa;
|
||||
}
|
||||
|
||||
int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp) {
|
||||
int ret = -1;
|
||||
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL ||
|
||||
!EVP_PKEY_set1_DSA(pkey, (DSA *)dsa)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = i2d_PUBKEY(pkey, outp);
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp, long len) {
|
||||
if (len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, *inp, (size_t)len);
|
||||
EVP_PKEY *pkey = EVP_parse_public_key(&cbs);
|
||||
if (pkey == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
if (ec_key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (out != NULL) {
|
||||
EC_KEY_free(*out);
|
||||
*out = ec_key;
|
||||
}
|
||||
*inp = CBS_data(&cbs);
|
||||
return ec_key;
|
||||
}
|
||||
|
||||
int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp) {
|
||||
int ret = -1;
|
||||
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL ||
|
||||
!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY *)ec_key)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = i2d_PUBKEY(pkey, outp);
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+68
-231
@@ -70,6 +70,7 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
@@ -279,8 +280,8 @@ static bool SetupContext(FileTest *t, KeyMap *key_map, EVP_PKEY_CTX *ctx) {
|
||||
}
|
||||
// For historical reasons, |EVP_PKEY_CTX_set0_rsa_oaep_label| expects to be
|
||||
// take ownership of the input.
|
||||
bssl::UniquePtr<uint8_t> buf(reinterpret_cast<uint8_t *>(
|
||||
OPENSSL_memdup(label.data(), label.size())));
|
||||
bssl::UniquePtr<uint8_t> buf(
|
||||
reinterpret_cast<uint8_t *>(BUF_memdup(label.data(), label.size())));
|
||||
if (!buf ||
|
||||
!EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, buf.get(), label.size())) {
|
||||
return false;
|
||||
@@ -567,10 +568,40 @@ TEST(EVPTest, TestVectors) {
|
||||
});
|
||||
}
|
||||
|
||||
static void RunWycheproofVerifyTest(const char *path) {
|
||||
static void RunWycheproofTest(const char *path) {
|
||||
SCOPED_TRACE(path);
|
||||
FileTestGTest(path, [](FileTest *t) {
|
||||
t->IgnoreAllUnusedInstructions();
|
||||
t->IgnoreInstruction("key.type");
|
||||
// Extra ECDSA fields.
|
||||
t->IgnoreInstruction("key.curve");
|
||||
t->IgnoreInstruction("key.keySize");
|
||||
t->IgnoreInstruction("key.wx");
|
||||
t->IgnoreInstruction("key.wy");
|
||||
t->IgnoreInstruction("key.uncompressed");
|
||||
// Extra RSA fields.
|
||||
t->IgnoreInstruction("e");
|
||||
t->IgnoreInstruction("keyAsn");
|
||||
t->IgnoreInstruction("keysize");
|
||||
t->IgnoreInstruction("n");
|
||||
t->IgnoreAttribute("padding");
|
||||
t->IgnoreInstruction("keyJwk.alg");
|
||||
t->IgnoreInstruction("keyJwk.e");
|
||||
t->IgnoreInstruction("keyJwk.kid");
|
||||
t->IgnoreInstruction("keyJwk.kty");
|
||||
t->IgnoreInstruction("keyJwk.n");
|
||||
// Extra EdDSA fields.
|
||||
t->IgnoreInstruction("key.pk");
|
||||
t->IgnoreInstruction("key.sk");
|
||||
t->IgnoreInstruction("jwk.crv");
|
||||
t->IgnoreInstruction("jwk.d");
|
||||
t->IgnoreInstruction("jwk.kid");
|
||||
t->IgnoreInstruction("jwk.kty");
|
||||
t->IgnoreInstruction("jwk.x");
|
||||
// Extra DSA fields.
|
||||
t->IgnoreInstruction("key.g");
|
||||
t->IgnoreInstruction("key.p");
|
||||
t->IgnoreInstruction("key.q");
|
||||
t->IgnoreInstruction("key.y");
|
||||
|
||||
std::vector<uint8_t> der;
|
||||
ASSERT_TRUE(t->GetInstructionBytes(&der, "keyDer"));
|
||||
@@ -615,7 +646,13 @@ static void RunWycheproofVerifyTest(const char *path) {
|
||||
bool sig_ok = DSA_check_signature(&valid, digest, digest_len, sig.data(),
|
||||
sig.size(), dsa) &&
|
||||
valid;
|
||||
EXPECT_EQ(sig_ok, result.IsValid());
|
||||
if (result == WycheproofResult::kValid) {
|
||||
EXPECT_TRUE(sig_ok);
|
||||
} else if (result == WycheproofResult::kInvalid) {
|
||||
EXPECT_FALSE(sig_ok);
|
||||
} else {
|
||||
// this is a legacy signature, which may or may not be accepted.
|
||||
}
|
||||
} else {
|
||||
bssl::ScopedEVP_MD_CTX ctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
@@ -628,275 +665,75 @@ static void RunWycheproofVerifyTest(const char *path) {
|
||||
}
|
||||
int ret = EVP_DigestVerify(ctx.get(), sig.data(), sig.size(), msg.data(),
|
||||
msg.size());
|
||||
// BoringSSL does not enforce policies on weak keys and leaves it to the
|
||||
// caller.
|
||||
EXPECT_EQ(ret,
|
||||
result.IsValid({"SmallModulus", "SmallPublicKey", "WeakHash"})
|
||||
? 1
|
||||
: 0);
|
||||
if (result == WycheproofResult::kValid) {
|
||||
EXPECT_EQ(1, ret);
|
||||
} else if (result == WycheproofResult::kInvalid) {
|
||||
EXPECT_EQ(0, ret);
|
||||
} else {
|
||||
// this is a legacy signature, which may or may not be accepted.
|
||||
EXPECT_TRUE(ret == 1 || ret == 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofDSA) {
|
||||
RunWycheproofVerifyTest("third_party/wycheproof_testvectors/dsa_test.txt");
|
||||
RunWycheproofTest("third_party/wycheproof_testvectors/dsa_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofECDSAP224) {
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofECDSAP256) {
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofECDSAP384) {
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofECDSAP521) {
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofEdDSA) {
|
||||
RunWycheproofVerifyTest("third_party/wycheproof_testvectors/eddsa_test.txt");
|
||||
RunWycheproofTest("third_party/wycheproof_testvectors/eddsa_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAPKCS1) {
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt");
|
||||
// TODO(davidben): Is this file redundant with the tests above?
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/rsa_signature_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAPKCS1Sign) {
|
||||
FileTestGTest(
|
||||
"third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt",
|
||||
[](FileTest *t) {
|
||||
t->IgnoreAllUnusedInstructions();
|
||||
|
||||
std::vector<uint8_t> pkcs8;
|
||||
ASSERT_TRUE(t->GetInstructionBytes(&pkcs8, "privateKeyPkcs8"));
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, pkcs8.data(), pkcs8.size());
|
||||
bssl::UniquePtr<EVP_PKEY> key(EVP_parse_private_key(&cbs));
|
||||
ASSERT_TRUE(key);
|
||||
|
||||
const EVP_MD *md = GetWycheproofDigest(t, "sha", true);
|
||||
ASSERT_TRUE(md);
|
||||
|
||||
std::vector<uint8_t> msg, sig;
|
||||
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
|
||||
ASSERT_TRUE(t->GetBytes(&sig, "sig"));
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
|
||||
bssl::ScopedEVP_MD_CTX ctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr, key.get()));
|
||||
std::vector<uint8_t> out(EVP_PKEY_size(key.get()));
|
||||
size_t len = out.size();
|
||||
int ret =
|
||||
EVP_DigestSign(ctx.get(), out.data(), &len, msg.data(), msg.size());
|
||||
// BoringSSL does not enforce policies on weak keys and leaves it to the
|
||||
// caller.
|
||||
bool is_valid =
|
||||
result.IsValid({"SmallModulus", "SmallPublicKey", "WeakHash"});
|
||||
EXPECT_EQ(ret, is_valid ? 1 : 0);
|
||||
if (is_valid) {
|
||||
out.resize(len);
|
||||
EXPECT_EQ(Bytes(sig), Bytes(out));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAPSS) {
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_pss_2048_sha256_mgf1_32_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_pss_3072_sha256_mgf1_32_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_pss_4096_sha256_mgf1_32_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
RunWycheproofTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_pss_4096_sha512_mgf1_32_test.txt");
|
||||
RunWycheproofVerifyTest(
|
||||
"third_party/wycheproof_testvectors/rsa_pss_misc_test.txt");
|
||||
}
|
||||
|
||||
static void RunWycheproofDecryptTest(
|
||||
const char *path,
|
||||
std::function<void(FileTest *, EVP_PKEY_CTX *)> setup_cb) {
|
||||
FileTestGTest(path, [&](FileTest *t) {
|
||||
t->IgnoreAllUnusedInstructions();
|
||||
|
||||
std::vector<uint8_t> pkcs8;
|
||||
ASSERT_TRUE(t->GetInstructionBytes(&pkcs8, "privateKeyPkcs8"));
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, pkcs8.data(), pkcs8.size());
|
||||
bssl::UniquePtr<EVP_PKEY> key(EVP_parse_private_key(&cbs));
|
||||
ASSERT_TRUE(key);
|
||||
|
||||
std::vector<uint8_t> ct, msg;
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "ct"));
|
||||
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key.get(), nullptr));
|
||||
ASSERT_TRUE(ctx);
|
||||
ASSERT_TRUE(EVP_PKEY_decrypt_init(ctx.get()));
|
||||
ASSERT_NO_FATAL_FAILURE(setup_cb(t, ctx.get()));
|
||||
std::vector<uint8_t> out(EVP_PKEY_size(key.get()));
|
||||
size_t len = out.size();
|
||||
int ret =
|
||||
EVP_PKEY_decrypt(ctx.get(), out.data(), &len, ct.data(), ct.size());
|
||||
// BoringSSL does not enforce policies on weak keys and leaves it to the
|
||||
// caller.
|
||||
bool is_valid = result.IsValid({"SmallModulus"});
|
||||
EXPECT_EQ(ret, is_valid ? 1 : 0);
|
||||
if (is_valid) {
|
||||
out.resize(len);
|
||||
EXPECT_EQ(Bytes(msg), Bytes(out));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void RunWycheproofOAEPTest(const char *path) {
|
||||
RunWycheproofDecryptTest(path, [](FileTest *t, EVP_PKEY_CTX *ctx) {
|
||||
const EVP_MD *md = GetWycheproofDigest(t, "sha", true);
|
||||
ASSERT_TRUE(md);
|
||||
const EVP_MD *mgf1_md = GetWycheproofDigest(t, "mgfSha", true);
|
||||
ASSERT_TRUE(mgf1_md);
|
||||
std::vector<uint8_t> label;
|
||||
ASSERT_TRUE(t->GetBytes(&label, "label"));
|
||||
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md));
|
||||
ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1_md));
|
||||
bssl::UniquePtr<uint8_t> label_copy(
|
||||
static_cast<uint8_t *>(OPENSSL_memdup(label.data(), label.size())));
|
||||
ASSERT_TRUE(label_copy || label.empty());
|
||||
ASSERT_TRUE(
|
||||
EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy.get(), label.size()));
|
||||
// |EVP_PKEY_CTX_set0_rsa_oaep_label| takes ownership on success.
|
||||
label_copy.release();
|
||||
});
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAOAEP2048) {
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha1_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha224_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha224_mgf1sha224_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha256_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha256_mgf1sha256_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha384_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha384_mgf1sha384_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha512_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_2048_sha512_mgf1sha512_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAOAEP3072) {
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_3072_sha256_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_3072_sha256_mgf1sha256_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_3072_sha512_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_3072_sha512_mgf1sha512_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAOAEP4096) {
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_4096_sha256_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_4096_sha256_mgf1sha256_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_4096_sha512_mgf1sha1_test.txt");
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/"
|
||||
"rsa_oaep_4096_sha512_mgf1sha512_test.txt");
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAOAEPMisc) {
|
||||
RunWycheproofOAEPTest(
|
||||
"third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt");
|
||||
}
|
||||
|
||||
static void RunWycheproofPKCS1DecryptTest(const char *path) {
|
||||
RunWycheproofDecryptTest(path, [](FileTest *t, EVP_PKEY_CTX *ctx) {
|
||||
// No setup needed. PKCS#1 is, sadly, the default.
|
||||
});
|
||||
}
|
||||
|
||||
TEST(EVPTest, WycheproofRSAPKCS1Decrypt) {
|
||||
RunWycheproofPKCS1DecryptTest(
|
||||
"third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt");
|
||||
RunWycheproofPKCS1DecryptTest(
|
||||
"third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt");
|
||||
RunWycheproofPKCS1DecryptTest(
|
||||
"third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt");
|
||||
RunWycheproofTest("third_party/wycheproof_testvectors/rsa_pss_misc_test.txt");
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ec_key.h>
|
||||
|
||||
+2
-14
@@ -59,6 +59,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -134,7 +135,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
|
||||
dctx->saltlen = sctx->saltlen;
|
||||
if (sctx->oaep_label) {
|
||||
OPENSSL_free(dctx->oaep_label);
|
||||
dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
|
||||
dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
|
||||
if (!dctx->oaep_label) {
|
||||
return 0;
|
||||
}
|
||||
@@ -568,19 +569,6 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) {
|
||||
0, out_padding);
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx,
|
||||
const EVP_MD *md) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
|
||||
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
|
||||
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/curve25519.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -243,6 +244,6 @@ size_t EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY *pkey, uint8_t **out_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_ptr = OPENSSL_memdup(key->pub, 32);
|
||||
*out_ptr = BUF_memdup(key->pub, 32);
|
||||
return *out_ptr == NULL ? 0 : 32;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ if(${ARCH} STREQUAL "x86_64")
|
||||
|
||||
aesni-gcm-x86_64.${ASM_EXT}
|
||||
aesni-x86_64.${ASM_EXT}
|
||||
aes-x86_64.${ASM_EXT}
|
||||
ghash-ssse3-x86_64.${ASM_EXT}
|
||||
ghash-x86_64.${ASM_EXT}
|
||||
md5-x86_64.${ASM_EXT}
|
||||
@@ -26,6 +27,7 @@ if(${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
BCM_ASM_SOURCES
|
||||
|
||||
aes-586.${ASM_EXT}
|
||||
aesni-x86.${ASM_EXT}
|
||||
bn-586.${ASM_EXT}
|
||||
co-586.${ASM_EXT}
|
||||
@@ -44,6 +46,7 @@ if(${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
BCM_ASM_SOURCES
|
||||
|
||||
aes-armv4.${ASM_EXT}
|
||||
aesv8-armx.${ASM_EXT}
|
||||
armv4-mont.${ASM_EXT}
|
||||
bsaes-armv7.${ASM_EXT}
|
||||
@@ -80,11 +83,14 @@ if(${ARCH} STREQUAL "ppc64le")
|
||||
)
|
||||
endif()
|
||||
|
||||
perlasm(aes-586.${ASM_EXT} aes/asm/aes-586.pl)
|
||||
perlasm(aes-armv4.${ASM_EXT} aes/asm/aes-armv4.pl)
|
||||
perlasm(aesni-gcm-x86_64.${ASM_EXT} modes/asm/aesni-gcm-x86_64.pl)
|
||||
perlasm(aesni-x86_64.${ASM_EXT} aes/asm/aesni-x86_64.pl)
|
||||
perlasm(aesni-x86.${ASM_EXT} aes/asm/aesni-x86.pl)
|
||||
perlasm(aesp8-ppc.${ASM_EXT} aes/asm/aesp8-ppc.pl)
|
||||
perlasm(aesv8-armx.${ASM_EXT} aes/asm/aesv8-armx.pl)
|
||||
perlasm(aes-x86_64.${ASM_EXT} aes/asm/aes-x86_64.pl)
|
||||
perlasm(armv4-mont.${ASM_EXT} bn/asm/armv4-mont.pl)
|
||||
perlasm(armv8-mont.${ASM_EXT} bn/asm/armv8-mont.pl)
|
||||
perlasm(bn-586.${ASM_EXT} bn/asm/bn-586.pl)
|
||||
|
||||
@@ -10,7 +10,6 @@ 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. 2018-07-30: certificate [#3318](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3318), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx) (in docx format).
|
||||
1. 2019-08-08: certificate [#3678](https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3678), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20190808.docx) (in docx format).
|
||||
|
||||
## Running CAVP tests
|
||||
|
||||
@@ -47,10 +46,6 @@ The DRBG state is kept in a thread-local structure and is seeded from one of the
|
||||
|
||||
In FIPS mode, each of those entropy sources is subject to a 10× overread. That is, when *n* bytes of entropy are needed, *10n* bytes will be read from the entropy source and XORed down to *n* bytes. Reads from the entropy source are also processed in blocks of 16 bytes and if two consecutive chunks are equal the process will abort.
|
||||
|
||||
In the case that the seed is taken from RDRAND, getrandom will also be queried with `GRND_NONBLOCK` to attempt to obtain additional entropy from the operating system. If available, that extra entropy will be XORed into the whitened seed.
|
||||
|
||||
On Android, only `getrandom` is supported and, when seeding for the first time, the system property `ro.boringcrypto.hwrand` is queried. If set to `true` then `getrandom` will be called with the `GRND_RANDOM` flag. Only entropy draws destined for DRBG seeds are affected by this. We are not suggesting that there is any security advantage at all to doing this, and thus recommend that Android vendors do _not_ set this flag.
|
||||
|
||||
The CTR-DRBG is reseeded every 4096 calls to `RAND_bytes`. Thus the process will randomly crash about every 2¹³⁵ calls.
|
||||
|
||||
The FIPS PRNGs allow “additional input” to be fed into a given call. We use this feature to be as robust as possible to state duplication from process forks and VM copies: for every call we read 32 bytes of “additional data” from the entropy source (without overread) which means that cloned states will diverge at the next call to `RAND_bytes`. This is called “prediction resistance” by FIPS, but we do *not* claim this property in a FIPS context because we don't implement it the way they want.
|
||||
@@ -59,12 +54,6 @@ There is a second interface to the RNG which allows the caller to supply bytes t
|
||||
|
||||
FIPS requires that RNG state be zeroed when the process exits. In order to implement this, all per-thread RNG states are tracked in a linked list and a destructor function is included which clears them. In order for this to be safe in the presence of threads, a lock is used to stop all other threads from using the RNG once this process has begun. Thus the main thread exiting may cause other threads to deadlock, and drawing on entropy in a destructor function may also deadlock.
|
||||
|
||||
## Self-test optimisation
|
||||
|
||||
On Android, the self-tests are optimised in line with [IG](https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/fips140-2/fips1402ig.pdf) section 9.11. The module will always perform the integrity test at power-on, but the self-tests will test for the presence of a file named after the hex encoded, HMAC-SHA-256 hash of the module in `/dev/boringssl/selftest/`. If such a file is found then the self-tests are skipped. Otherwise, after the self-tests complete successfully, that file will be written. Any I/O errors are ignored and, if they occur when testing for the presence of the file, the module acts as if it's not present.
|
||||
|
||||
It is intended that a `tmpfs` be mounted at that location in order to skip running the self tests for every process once they have already passed in a given instance of the operating system.
|
||||
|
||||
## Integrity Test
|
||||
|
||||
FIPS-140 mandates that a module calculate an HMAC of its own code in a constructor function and compare the result to a known-good value. Typical code produced by a C compiler includes large numbers of relocations: places in the machine code where the linker needs to resolve and inject the final value of a symbolic expression. These relocations mean that the bytes that make up any specific bit of code generally aren't known until the final link has completed.
|
||||
|
||||
@@ -56,6 +56,758 @@
|
||||
#include "../modes/internal.h"
|
||||
|
||||
|
||||
#if defined(OPENSSL_NO_ASM) || \
|
||||
(!defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && !defined(OPENSSL_ARM))
|
||||
|
||||
// Te0[x] = S [x].[02, 01, 01, 03];
|
||||
// Te1[x] = S [x].[03, 02, 01, 01];
|
||||
// Te2[x] = S [x].[01, 03, 02, 01];
|
||||
// Te3[x] = S [x].[01, 01, 03, 02];
|
||||
//
|
||||
// Td0[x] = Si[x].[0e, 09, 0d, 0b];
|
||||
// Td1[x] = Si[x].[0b, 0e, 09, 0d];
|
||||
// Td2[x] = Si[x].[0d, 0b, 0e, 09];
|
||||
// Td3[x] = Si[x].[09, 0d, 0b, 0e];
|
||||
// Td4[x] = Si[x].[01];
|
||||
|
||||
static const uint32_t Te0[256] = {
|
||||
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU,
|
||||
0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U,
|
||||
0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U,
|
||||
0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
|
||||
0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU,
|
||||
0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U,
|
||||
0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU,
|
||||
0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
|
||||
0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U,
|
||||
0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U,
|
||||
0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU,
|
||||
0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
|
||||
0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU,
|
||||
0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U,
|
||||
0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U,
|
||||
0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
|
||||
0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U,
|
||||
0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U,
|
||||
0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U,
|
||||
0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
|
||||
0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU,
|
||||
0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U,
|
||||
0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U,
|
||||
0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
|
||||
0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U,
|
||||
0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U,
|
||||
0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU,
|
||||
0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
|
||||
0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U,
|
||||
0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU,
|
||||
0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U,
|
||||
0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
|
||||
0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU,
|
||||
0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU,
|
||||
0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U,
|
||||
0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
|
||||
0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U,
|
||||
0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU,
|
||||
0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU,
|
||||
0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
|
||||
0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU,
|
||||
0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U,
|
||||
0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U,
|
||||
0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
|
||||
0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U,
|
||||
0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U,
|
||||
0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U,
|
||||
0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
|
||||
0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU,
|
||||
0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U,
|
||||
0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U,
|
||||
0x2c16163aU, };
|
||||
|
||||
static const uint32_t Te1[256] = {
|
||||
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U,
|
||||
0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U,
|
||||
0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU,
|
||||
0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
|
||||
0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU,
|
||||
0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U,
|
||||
0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U,
|
||||
0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
|
||||
0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U,
|
||||
0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U,
|
||||
0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U,
|
||||
0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
|
||||
0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U,
|
||||
0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU,
|
||||
0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U,
|
||||
0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
|
||||
0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U,
|
||||
0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU,
|
||||
0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U,
|
||||
0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
|
||||
0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U,
|
||||
0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU,
|
||||
0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U,
|
||||
0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
|
||||
0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U,
|
||||
0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU,
|
||||
0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U,
|
||||
0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
|
||||
0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U,
|
||||
0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU,
|
||||
0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U,
|
||||
0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
|
||||
0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U,
|
||||
0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U,
|
||||
0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U,
|
||||
0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
|
||||
0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU,
|
||||
0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU,
|
||||
0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U,
|
||||
0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
|
||||
0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU,
|
||||
0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU,
|
||||
0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U,
|
||||
0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
|
||||
0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U,
|
||||
0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U,
|
||||
0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U,
|
||||
0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
|
||||
0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU,
|
||||
0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U,
|
||||
0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU,
|
||||
0x3a2c1616U, };
|
||||
|
||||
static const uint32_t Te2[256] = {
|
||||
0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U,
|
||||
0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U,
|
||||
0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU,
|
||||
0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
|
||||
0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU,
|
||||
0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U,
|
||||
0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U,
|
||||
0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
|
||||
0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U,
|
||||
0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U,
|
||||
0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U,
|
||||
0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
|
||||
0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U,
|
||||
0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU,
|
||||
0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U,
|
||||
0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
|
||||
0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U,
|
||||
0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU,
|
||||
0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U,
|
||||
0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
|
||||
0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U,
|
||||
0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU,
|
||||
0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U,
|
||||
0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
|
||||
0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U,
|
||||
0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU,
|
||||
0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U,
|
||||
0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
|
||||
0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U,
|
||||
0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU,
|
||||
0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U,
|
||||
0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
|
||||
0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U,
|
||||
0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U,
|
||||
0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U,
|
||||
0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
|
||||
0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU,
|
||||
0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU,
|
||||
0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U,
|
||||
0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
|
||||
0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU,
|
||||
0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU,
|
||||
0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U,
|
||||
0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
|
||||
0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U,
|
||||
0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U,
|
||||
0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U,
|
||||
0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
|
||||
0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU,
|
||||
0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U,
|
||||
0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU,
|
||||
0x163a2c16U, };
|
||||
|
||||
static const uint32_t Te3[256] = {
|
||||
0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU,
|
||||
0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U,
|
||||
0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU,
|
||||
0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
|
||||
0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U,
|
||||
0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U,
|
||||
0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU,
|
||||
0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
|
||||
0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U,
|
||||
0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U,
|
||||
0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU,
|
||||
0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
|
||||
0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U,
|
||||
0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU,
|
||||
0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U,
|
||||
0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
|
||||
0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U,
|
||||
0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU,
|
||||
0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U,
|
||||
0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
|
||||
0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU,
|
||||
0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U,
|
||||
0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U,
|
||||
0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
|
||||
0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U,
|
||||
0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U,
|
||||
0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U,
|
||||
0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
|
||||
0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U,
|
||||
0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U,
|
||||
0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU,
|
||||
0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
|
||||
0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U,
|
||||
0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU,
|
||||
0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U,
|
||||
0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
|
||||
0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U,
|
||||
0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U,
|
||||
0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU,
|
||||
0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
|
||||
0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U,
|
||||
0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU,
|
||||
0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U,
|
||||
0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
|
||||
0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U,
|
||||
0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U,
|
||||
0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U,
|
||||
0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
|
||||
0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U,
|
||||
0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U,
|
||||
0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU,
|
||||
0x16163a2cU, };
|
||||
|
||||
static const uint32_t Td0[256] = {
|
||||
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU,
|
||||
0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U,
|
||||
0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U,
|
||||
0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
|
||||
0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U,
|
||||
0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U,
|
||||
0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU,
|
||||
0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
|
||||
0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U,
|
||||
0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U,
|
||||
0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U,
|
||||
0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
|
||||
0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU,
|
||||
0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U,
|
||||
0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U,
|
||||
0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
|
||||
0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U,
|
||||
0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U,
|
||||
0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U,
|
||||
0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
|
||||
0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU,
|
||||
0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U,
|
||||
0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U,
|
||||
0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
|
||||
0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU,
|
||||
0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU,
|
||||
0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U,
|
||||
0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
|
||||
0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU,
|
||||
0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U,
|
||||
0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU,
|
||||
0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
|
||||
0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU,
|
||||
0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU,
|
||||
0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU,
|
||||
0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
|
||||
0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U,
|
||||
0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU,
|
||||
0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U,
|
||||
0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
|
||||
0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU,
|
||||
0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU,
|
||||
0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U,
|
||||
0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
|
||||
0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU,
|
||||
0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U,
|
||||
0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U,
|
||||
0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
|
||||
0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U,
|
||||
0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU,
|
||||
0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U,
|
||||
0xd0b85742U, };
|
||||
|
||||
static const uint32_t Td1[256] = {
|
||||
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU,
|
||||
0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU,
|
||||
0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U,
|
||||
0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
|
||||
0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU,
|
||||
0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U,
|
||||
0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU,
|
||||
0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
|
||||
0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U,
|
||||
0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU,
|
||||
0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU,
|
||||
0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
|
||||
0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU,
|
||||
0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU,
|
||||
0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U,
|
||||
0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
|
||||
0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU,
|
||||
0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U,
|
||||
0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU,
|
||||
0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
|
||||
0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU,
|
||||
0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U,
|
||||
0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U,
|
||||
0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
|
||||
0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU,
|
||||
0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U,
|
||||
0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU,
|
||||
0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
|
||||
0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U,
|
||||
0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U,
|
||||
0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U,
|
||||
0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
|
||||
0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U,
|
||||
0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U,
|
||||
0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U,
|
||||
0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
|
||||
0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U,
|
||||
0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U,
|
||||
0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U,
|
||||
0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
|
||||
0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U,
|
||||
0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U,
|
||||
0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU,
|
||||
0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
|
||||
0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U,
|
||||
0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U,
|
||||
0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU,
|
||||
0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
|
||||
0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U,
|
||||
0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U,
|
||||
0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU,
|
||||
0x42d0b857U, };
|
||||
|
||||
static const uint32_t Td2[256] = {
|
||||
0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU,
|
||||
0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U,
|
||||
0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U,
|
||||
0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
|
||||
0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU,
|
||||
0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U,
|
||||
0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U,
|
||||
0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
|
||||
0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U,
|
||||
0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U,
|
||||
0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU,
|
||||
0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
|
||||
0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU,
|
||||
0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U,
|
||||
0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU,
|
||||
0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
|
||||
0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U,
|
||||
0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU,
|
||||
0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U,
|
||||
0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
|
||||
0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU,
|
||||
0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU,
|
||||
0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU,
|
||||
0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
|
||||
0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U,
|
||||
0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U,
|
||||
0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U,
|
||||
0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
|
||||
0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU,
|
||||
0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U,
|
||||
0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U,
|
||||
0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
|
||||
0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U,
|
||||
0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U,
|
||||
0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U,
|
||||
0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
|
||||
0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U,
|
||||
0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU,
|
||||
0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU,
|
||||
0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
|
||||
0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U,
|
||||
0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU,
|
||||
0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU,
|
||||
0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
|
||||
0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U,
|
||||
0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U,
|
||||
0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U,
|
||||
0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
|
||||
0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU,
|
||||
0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU,
|
||||
0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU,
|
||||
0x5742d0b8U, };
|
||||
|
||||
static const uint32_t Td3[256] = {
|
||||
0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU,
|
||||
0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU,
|
||||
0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U,
|
||||
0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
|
||||
0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U,
|
||||
0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U,
|
||||
0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U,
|
||||
0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
|
||||
0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U,
|
||||
0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU,
|
||||
0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U,
|
||||
0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
|
||||
0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU,
|
||||
0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U,
|
||||
0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U,
|
||||
0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
|
||||
0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U,
|
||||
0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U,
|
||||
0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U,
|
||||
0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
|
||||
0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU,
|
||||
0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U,
|
||||
0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U,
|
||||
0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
|
||||
0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU,
|
||||
0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU,
|
||||
0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U,
|
||||
0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
|
||||
0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U,
|
||||
0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU,
|
||||
0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U,
|
||||
0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
|
||||
0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U,
|
||||
0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U,
|
||||
0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU,
|
||||
0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
|
||||
0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU,
|
||||
0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU,
|
||||
0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU,
|
||||
0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
|
||||
0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U,
|
||||
0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U,
|
||||
0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U,
|
||||
0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
|
||||
0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU,
|
||||
0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U,
|
||||
0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U,
|
||||
0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
|
||||
0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U,
|
||||
0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U,
|
||||
0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U,
|
||||
0xb85742d0U, };
|
||||
|
||||
static const uint8_t Td4[256] = {
|
||||
0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U,
|
||||
0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU,
|
||||
0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U,
|
||||
0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU,
|
||||
0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U,
|
||||
0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U,
|
||||
0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU,
|
||||
0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
|
||||
0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU,
|
||||
0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U,
|
||||
0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U,
|
||||
0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U,
|
||||
0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U,
|
||||
0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U,
|
||||
0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU,
|
||||
0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
|
||||
0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U,
|
||||
0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U,
|
||||
0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U,
|
||||
0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU,
|
||||
0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U,
|
||||
0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU,
|
||||
0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U,
|
||||
0x21U, 0x0cU, 0x7dU, };
|
||||
|
||||
static const uint32_t rcon[] = {
|
||||
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
||||
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
|
||||
// for 128-bit blocks, Rijndael never uses more than 10 rcon values
|
||||
};
|
||||
|
||||
int aes_nohw_set_encrypt_key(const uint8_t *key, unsigned bits,
|
||||
AES_KEY *aeskey) {
|
||||
uint32_t *rk;
|
||||
int i = 0;
|
||||
uint32_t temp;
|
||||
|
||||
if (!key || !aeskey) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (bits) {
|
||||
case 128:
|
||||
aeskey->rounds = 10;
|
||||
break;
|
||||
case 192:
|
||||
aeskey->rounds = 12;
|
||||
break;
|
||||
case 256:
|
||||
aeskey->rounds = 14;
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
rk = aeskey->rd_key;
|
||||
|
||||
rk[0] = GETU32(key);
|
||||
rk[1] = GETU32(key + 4);
|
||||
rk[2] = GETU32(key + 8);
|
||||
rk[3] = GETU32(key + 12);
|
||||
if (bits == 128) {
|
||||
while (1) {
|
||||
temp = rk[3];
|
||||
rk[4] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
|
||||
(Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(temp) & 0xff] & 0x0000ff00) ^
|
||||
(Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
|
||||
rk[5] = rk[1] ^ rk[4];
|
||||
rk[6] = rk[2] ^ rk[5];
|
||||
rk[7] = rk[3] ^ rk[6];
|
||||
if (++i == 10) {
|
||||
return 0;
|
||||
}
|
||||
rk += 4;
|
||||
}
|
||||
}
|
||||
rk[4] = GETU32(key + 16);
|
||||
rk[5] = GETU32(key + 20);
|
||||
if (bits == 192) {
|
||||
while (1) {
|
||||
temp = rk[5];
|
||||
rk[6] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
|
||||
(Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(temp) & 0xff] & 0x0000ff00) ^
|
||||
(Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
|
||||
rk[7] = rk[1] ^ rk[6];
|
||||
rk[8] = rk[2] ^ rk[7];
|
||||
rk[9] = rk[3] ^ rk[8];
|
||||
if (++i == 8) {
|
||||
return 0;
|
||||
}
|
||||
rk[10] = rk[4] ^ rk[9];
|
||||
rk[11] = rk[5] ^ rk[10];
|
||||
rk += 6;
|
||||
}
|
||||
}
|
||||
rk[6] = GETU32(key + 24);
|
||||
rk[7] = GETU32(key + 28);
|
||||
if (bits == 256) {
|
||||
while (1) {
|
||||
temp = rk[7];
|
||||
rk[8] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
|
||||
(Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(temp) & 0xff] & 0x0000ff00) ^
|
||||
(Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
|
||||
rk[9] = rk[1] ^ rk[8];
|
||||
rk[10] = rk[2] ^ rk[9];
|
||||
rk[11] = rk[3] ^ rk[10];
|
||||
if (++i == 7) {
|
||||
return 0;
|
||||
}
|
||||
temp = rk[11];
|
||||
rk[12] = rk[4] ^ (Te2[(temp >> 24)] & 0xff000000) ^
|
||||
(Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^
|
||||
(Te1[(temp) & 0xff] & 0x000000ff);
|
||||
rk[13] = rk[5] ^ rk[12];
|
||||
rk[14] = rk[6] ^ rk[13];
|
||||
rk[15] = rk[7] ^ rk[14];
|
||||
|
||||
rk += 8;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aes_nohw_set_decrypt_key(const uint8_t *key, unsigned bits,
|
||||
AES_KEY *aeskey) {
|
||||
uint32_t *rk;
|
||||
int i, j, status;
|
||||
uint32_t temp;
|
||||
|
||||
// first, start with an encryption schedule
|
||||
status = AES_set_encrypt_key(key, bits, aeskey);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
rk = aeskey->rd_key;
|
||||
|
||||
// invert the order of the round keys:
|
||||
for (i = 0, j = 4 * aeskey->rounds; i < j; i += 4, j -= 4) {
|
||||
temp = rk[i];
|
||||
rk[i] = rk[j];
|
||||
rk[j] = temp;
|
||||
temp = rk[i + 1];
|
||||
rk[i + 1] = rk[j + 1];
|
||||
rk[j + 1] = temp;
|
||||
temp = rk[i + 2];
|
||||
rk[i + 2] = rk[j + 2];
|
||||
rk[j + 2] = temp;
|
||||
temp = rk[i + 3];
|
||||
rk[i + 3] = rk[j + 3];
|
||||
rk[j + 3] = temp;
|
||||
}
|
||||
// apply the inverse MixColumn transform to all round keys but the first and
|
||||
// the last:
|
||||
for (i = 1; i < (int)aeskey->rounds; i++) {
|
||||
rk += 4;
|
||||
rk[0] =
|
||||
Td0[Te1[(rk[0] >> 24)] & 0xff] ^ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^
|
||||
Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[0]) & 0xff] & 0xff];
|
||||
rk[1] =
|
||||
Td0[Te1[(rk[1] >> 24)] & 0xff] ^ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^
|
||||
Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[1]) & 0xff] & 0xff];
|
||||
rk[2] =
|
||||
Td0[Te1[(rk[2] >> 24)] & 0xff] ^ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^
|
||||
Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[2]) & 0xff] & 0xff];
|
||||
rk[3] =
|
||||
Td0[Te1[(rk[3] >> 24)] & 0xff] ^ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^
|
||||
Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[3]) & 0xff] & 0xff];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void aes_nohw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
const uint32_t *rk;
|
||||
uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
|
||||
int r;
|
||||
|
||||
assert(in && out && key);
|
||||
rk = key->rd_key;
|
||||
|
||||
// map byte array block to cipher state
|
||||
// and add initial round key:
|
||||
s0 = GETU32(in) ^ rk[0];
|
||||
s1 = GETU32(in + 4) ^ rk[1];
|
||||
s2 = GETU32(in + 8) ^ rk[2];
|
||||
s3 = GETU32(in + 12) ^ rk[3];
|
||||
|
||||
// Nr - 1 full rounds:
|
||||
r = key->rounds >> 1;
|
||||
for (;;) {
|
||||
t0 = Te0[(s0 >> 24)] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^
|
||||
Te3[(s3) & 0xff] ^ rk[4];
|
||||
t1 = Te0[(s1 >> 24)] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^
|
||||
Te3[(s0) & 0xff] ^ rk[5];
|
||||
t2 = Te0[(s2 >> 24)] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^
|
||||
Te3[(s1) & 0xff] ^ rk[6];
|
||||
t3 = Te0[(s3 >> 24)] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^
|
||||
Te3[(s2) & 0xff] ^ rk[7];
|
||||
|
||||
rk += 8;
|
||||
if (--r == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
s0 = Te0[(t0 >> 24)] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^
|
||||
Te3[(t3) & 0xff] ^ rk[0];
|
||||
s1 = Te0[(t1 >> 24)] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^
|
||||
Te3[(t0) & 0xff] ^ rk[1];
|
||||
s2 = Te0[(t2 >> 24)] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^
|
||||
Te3[(t1) & 0xff] ^ rk[2];
|
||||
s3 = Te0[(t3 >> 24)] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^
|
||||
Te3[(t2) & 0xff] ^ rk[3];
|
||||
}
|
||||
|
||||
// apply last round and map cipher state to byte array block:
|
||||
s0 = (Te2[(t0 >> 24)] & 0xff000000) ^ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t3) & 0xff] & 0x000000ff) ^
|
||||
rk[0];
|
||||
PUTU32(out, s0);
|
||||
s1 = (Te2[(t1 >> 24)] & 0xff000000) ^ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t0) & 0xff] & 0x000000ff) ^
|
||||
rk[1];
|
||||
PUTU32(out + 4, s1);
|
||||
s2 = (Te2[(t2 >> 24)] & 0xff000000) ^ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t1) & 0xff] & 0x000000ff) ^
|
||||
rk[2];
|
||||
PUTU32(out + 8, s2);
|
||||
s3 = (Te2[(t3 >> 24)] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^
|
||||
(Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2) & 0xff] & 0x000000ff) ^
|
||||
rk[3];
|
||||
PUTU32(out + 12, s3);
|
||||
}
|
||||
|
||||
void aes_nohw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
const uint32_t *rk;
|
||||
uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
|
||||
int r;
|
||||
|
||||
assert(in && out && key);
|
||||
rk = key->rd_key;
|
||||
|
||||
// map byte array block to cipher state
|
||||
// and add initial round key:
|
||||
s0 = GETU32(in) ^ rk[0];
|
||||
s1 = GETU32(in + 4) ^ rk[1];
|
||||
s2 = GETU32(in + 8) ^ rk[2];
|
||||
s3 = GETU32(in + 12) ^ rk[3];
|
||||
|
||||
// Nr - 1 full rounds:
|
||||
r = key->rounds >> 1;
|
||||
for (;;) {
|
||||
t0 = Td0[(s0 >> 24)] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^
|
||||
Td3[(s1) & 0xff] ^ rk[4];
|
||||
t1 = Td0[(s1 >> 24)] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^
|
||||
Td3[(s2) & 0xff] ^ rk[5];
|
||||
t2 = Td0[(s2 >> 24)] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^
|
||||
Td3[(s3) & 0xff] ^ rk[6];
|
||||
t3 = Td0[(s3 >> 24)] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^
|
||||
Td3[(s0) & 0xff] ^ rk[7];
|
||||
|
||||
rk += 8;
|
||||
if (--r == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
s0 = Td0[(t0 >> 24)] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^
|
||||
Td3[(t1) & 0xff] ^ rk[0];
|
||||
s1 = Td0[(t1 >> 24)] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^
|
||||
Td3[(t2) & 0xff] ^ rk[1];
|
||||
s2 = Td0[(t2 >> 24)] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^
|
||||
Td3[(t3) & 0xff] ^ rk[2];
|
||||
s3 = Td0[(t3 >> 24)] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^
|
||||
Td3[(t0) & 0xff] ^ rk[3];
|
||||
}
|
||||
|
||||
// apply last round and
|
||||
// map cipher state to byte array block:
|
||||
s0 = ((uint32_t)Td4[(t0 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t3 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t2 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t1) & 0xff]) ^ rk[0];
|
||||
PUTU32(out, s0);
|
||||
s1 = ((uint32_t)Td4[(t1 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t0 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t3 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t2) & 0xff]) ^ rk[1];
|
||||
PUTU32(out + 4, s1);
|
||||
s2 = ((uint32_t)Td4[(t2 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t1 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t0 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t3) & 0xff]) ^ rk[2];
|
||||
PUTU32(out + 8, s2);
|
||||
s3 = ((uint32_t)Td4[(t3 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t2 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t1 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t0) & 0xff]) ^ rk[3];
|
||||
PUTU32(out + 12, s3);
|
||||
}
|
||||
|
||||
#endif // NO_ASM || (!X86 && !X86_64 && !ARM)
|
||||
|
||||
// Be aware that different sets of AES functions use incompatible key
|
||||
// representations, varying in format of the key schedule, the |AES_KEY.rounds|
|
||||
// value, or both. Therefore they cannot mix. Also, on AArch64, the plain-C
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
@@ -177,7 +176,7 @@ TEST(AESTest, WycheproofKeyWrap) {
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
|
||||
if (result.IsValid()) {
|
||||
if (result != WycheproofResult::kInvalid) {
|
||||
ASSERT_GE(ct.size(), 8u);
|
||||
|
||||
AES_KEY aes;
|
||||
@@ -219,10 +218,7 @@ TEST(AESTest, WycheproofKeyWrapWithPadding) {
|
||||
// should pass. However, both RFC 5649 and SP 800-38F section 5.3.1 say that
|
||||
// the minimum length is one. Therefore we consider test cases with an empty
|
||||
// message to be invalid.
|
||||
//
|
||||
// Wycheproof marks various weak parameters as acceptable. We do not enforce
|
||||
// policy in the library, so we map those flags to valid.
|
||||
if (result.IsValid({"SmallKey", "WeakWrapping"}) && !msg.empty()) {
|
||||
if (result != WycheproofResult::kInvalid && !msg.empty()) {
|
||||
AES_KEY aes;
|
||||
ASSERT_EQ(0, AES_set_decrypt_key(key.data(), 8 * key.size(), &aes));
|
||||
std::vector<uint8_t> out(ct.size() - 8);
|
||||
@@ -288,6 +284,26 @@ TEST(AESTest, ABI) {
|
||||
block_counts = {0, 1, 8};
|
||||
}
|
||||
|
||||
CHECK_ABI(aes_nohw_set_encrypt_key, kKey, bits, &key);
|
||||
CHECK_ABI(aes_nohw_encrypt, block, block, &key);
|
||||
#if defined(AES_NOHW_CBC)
|
||||
for (size_t blocks : block_counts) {
|
||||
SCOPED_TRACE(blocks);
|
||||
CHECK_ABI(aes_nohw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
|
||||
block, AES_ENCRYPT);
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_ABI(aes_nohw_set_decrypt_key, kKey, bits, &key);
|
||||
CHECK_ABI(aes_nohw_decrypt, block, block, &key);
|
||||
#if defined(AES_NOHW_CBC)
|
||||
for (size_t blocks : block_counts) {
|
||||
SCOPED_TRACE(blocks);
|
||||
CHECK_ABI(aes_nohw_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
|
||||
block, AES_DECRYPT);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bsaes_capable()) {
|
||||
vpaes_set_encrypt_key(kKey, bits, &key);
|
||||
CHECK_ABI(vpaes_encrypt_key_to_bsaes, &key, &key);
|
||||
@@ -367,201 +383,6 @@ static Bytes AESKeyToBytes(const AES_KEY *key) {
|
||||
return Bytes(reinterpret_cast<const uint8_t *>(key), sizeof(*key));
|
||||
}
|
||||
|
||||
static uint8_t aes_ref_sub_byte(uint8_t b) {
|
||||
static const uint8_t kSBox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
|
||||
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
|
||||
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
|
||||
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
|
||||
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
|
||||
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
return kSBox[b];
|
||||
}
|
||||
|
||||
static uint32_t aes_ref_sub_word(uint32_t in) {
|
||||
uint32_t a0 = aes_ref_sub_byte(in);
|
||||
uint32_t a1 = aes_ref_sub_byte(in >> 8);
|
||||
uint32_t a2 = aes_ref_sub_byte(in >> 16);
|
||||
uint32_t a3 = aes_ref_sub_byte(in >> 24);
|
||||
return a0 | (a1 << 8) | (a2 << 16) | (a3 << 24);
|
||||
}
|
||||
|
||||
static uint32_t aes_ref_rot_word(uint32_t in, uint32_t n) {
|
||||
return (in >> n) | (in << (32 - n));
|
||||
}
|
||||
|
||||
static int aes_ref_set_encrypt_key(const uint8_t *key, int key_bits,
|
||||
AES_KEY *out) {
|
||||
static const uint32_t kRCon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
|
||||
0x20, 0x40, 0x80, 0x1b, 0x36};
|
||||
switch (key_bits) {
|
||||
case 128:
|
||||
out->rounds = 10;
|
||||
break;
|
||||
case 192:
|
||||
out->rounds = 12;
|
||||
break;
|
||||
case 256:
|
||||
out->rounds = 14;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t words = key_bits / 32;
|
||||
size_t num_subkey_words = (out->rounds + 1) * 4;
|
||||
OPENSSL_memcpy(out->rd_key, key, words * sizeof(uint32_t));
|
||||
for (size_t i = words; i < num_subkey_words; i++) {
|
||||
uint32_t tmp = out->rd_key[i - 1];
|
||||
if (i % words == 0) {
|
||||
tmp = aes_ref_sub_word(aes_ref_rot_word(tmp, 8)) ^ kRCon[(i / words) - 1];
|
||||
} else if (key_bits == 256 && i % 4 == 0) {
|
||||
tmp = aes_ref_sub_word(tmp);
|
||||
}
|
||||
out->rd_key[i] = tmp ^ out->rd_key[i - words];
|
||||
}
|
||||
|
||||
// The ARM bsaes implementation expects all the keys to be byteswapped.
|
||||
for (size_t i = 0; i < num_subkey_words; i++) {
|
||||
out->rd_key[i] = CRYPTO_bswap4(out->rd_key[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aes_ref_inv_mix_columns(uint32_t block[4]) {
|
||||
// This tables was generated with the following Python script:
|
||||
// clang-format off
|
||||
/*
|
||||
def mul_unreduced(a, b):
|
||||
c = 0
|
||||
for i in range(8):
|
||||
if b & (1 << i):
|
||||
c ^= a << i
|
||||
return c
|
||||
|
||||
def mul(a, b):
|
||||
c = mul_unreduced(a, b)
|
||||
# c's highest term is at most x^14.
|
||||
c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
|
||||
# c's highest term is at most x^10.
|
||||
c = (c & 0xff) ^ mul_unreduced(c >> 8, 0b00011011)
|
||||
# c's highest term is at most x^7.
|
||||
assert (c >> 8) == 0
|
||||
return c
|
||||
|
||||
def inv_mix_column(a):
|
||||
ret = 0
|
||||
for b in [0x0e, 0x09, 0x0d, 0x0b]:
|
||||
ret <<= 8
|
||||
ret |= mul(a, b)
|
||||
return ret
|
||||
|
||||
body = ", ".join("0x%08x" % inv_mix_column(a) for a in range(256))
|
||||
print("static const uint32_t kTable[256] = {%s};\n" % body)
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
// kInvMixColumn[i] is the result of InvMixColumns applied to a column
|
||||
// containing [i, 0, 0, 0]. (The contributions of the other positions are
|
||||
// computed by rotating bytes.)
|
||||
static const uint32_t kInvMixColumn[256] = {
|
||||
0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
|
||||
0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
|
||||
0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
|
||||
0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
|
||||
0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
|
||||
0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
|
||||
0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
|
||||
0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
|
||||
0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
|
||||
0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
|
||||
0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
|
||||
0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
|
||||
0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
|
||||
0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
|
||||
0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
|
||||
0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
|
||||
0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
|
||||
0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
|
||||
0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
|
||||
0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
|
||||
0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
|
||||
0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
|
||||
0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
|
||||
0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
|
||||
0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
|
||||
0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
|
||||
0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
|
||||
0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
|
||||
0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
|
||||
0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
|
||||
0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
|
||||
0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
|
||||
0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
|
||||
0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
|
||||
0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
|
||||
0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
|
||||
0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
|
||||
0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
|
||||
0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
|
||||
0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
|
||||
0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
|
||||
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
|
||||
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3};
|
||||
|
||||
// Note |block| is byte-swapped so block[i] >> 24 is the first element of
|
||||
// block[i]. (See |aes_ref_set_encrypt_key|).
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
uint32_t in = block[i];
|
||||
block[i] = kInvMixColumn[in >> 24];
|
||||
block[i] ^= aes_ref_rot_word(kInvMixColumn[(in >> 16) & 0xff], 8);
|
||||
block[i] ^= aes_ref_rot_word(kInvMixColumn[(in >> 8) & 0xff], 16);
|
||||
block[i] ^= aes_ref_rot_word(kInvMixColumn[in & 0xff], 24);
|
||||
}
|
||||
}
|
||||
|
||||
static int aes_ref_set_decrypt_key(const uint8_t *key, int bits, AES_KEY *out) {
|
||||
if (aes_ref_set_encrypt_key(key, bits, out) != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// bsaes expects the decryption round keys in reverse order. Note there are
|
||||
// |out->rounds + 1| round keys.
|
||||
for (size_t i = 0; i < out->rounds / 2; i++) {
|
||||
std::swap(out->rd_key[4 * i], out->rd_key[4 * (out->rounds - i)]);
|
||||
std::swap(out->rd_key[4 * i + 1], out->rd_key[4 * (out->rounds - i) + 1]);
|
||||
std::swap(out->rd_key[4 * i + 2], out->rd_key[4 * (out->rounds - i) + 2]);
|
||||
std::swap(out->rd_key[4 * i + 3], out->rd_key[4 * (out->rounds - i) + 3]);
|
||||
}
|
||||
|
||||
// bsaes expects round keys other than the first and last to have
|
||||
// InvMixColumns applied.
|
||||
for (size_t i = 1; i < out->rounds; i++) {
|
||||
aes_ref_inv_mix_columns(out->rd_key + 4 * i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST(AESTest, VPAESToBSAESConvert) {
|
||||
const int kNumIterations = 1000;
|
||||
for (int i = 0; i < kNumIterations; i++) {
|
||||
@@ -572,36 +393,36 @@ TEST(AESTest, VPAESToBSAESConvert) {
|
||||
SCOPED_TRACE(bits);
|
||||
for (bool enc : {false, true}) {
|
||||
SCOPED_TRACE(enc);
|
||||
AES_KEY ref, vpaes, bsaes;
|
||||
OPENSSL_memset(&ref, 0xaa, sizeof(ref));
|
||||
AES_KEY nohw, vpaes, bsaes;
|
||||
OPENSSL_memset(&nohw, 0xaa, sizeof(nohw));
|
||||
OPENSSL_memset(&vpaes, 0xaa, sizeof(vpaes));
|
||||
OPENSSL_memset(&bsaes, 0xaa, sizeof(bsaes));
|
||||
|
||||
if (enc) {
|
||||
ASSERT_EQ(0, aes_ref_set_encrypt_key(key, bits, &ref));
|
||||
ASSERT_EQ(0, vpaes_set_encrypt_key(key, bits, &vpaes));
|
||||
aes_nohw_set_encrypt_key(key, bits, &nohw);
|
||||
vpaes_set_encrypt_key(key, bits, &vpaes);
|
||||
vpaes_encrypt_key_to_bsaes(&bsaes, &vpaes);
|
||||
} else {
|
||||
ASSERT_EQ(0, aes_ref_set_decrypt_key(key, bits, &ref));
|
||||
ASSERT_EQ(0, vpaes_set_decrypt_key(key, bits, &vpaes));
|
||||
aes_nohw_set_decrypt_key(key, bits, &nohw);
|
||||
vpaes_set_decrypt_key(key, bits, &vpaes);
|
||||
vpaes_decrypt_key_to_bsaes(&bsaes, &vpaes);
|
||||
}
|
||||
|
||||
// Although not fatal, stop running if this fails, otherwise we'll spam
|
||||
// the user's console.
|
||||
ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
|
||||
ASSERT_EQ(AESKeyToBytes(&nohw), AESKeyToBytes(&bsaes));
|
||||
|
||||
// Repeat the test in-place.
|
||||
OPENSSL_memcpy(&bsaes, &vpaes, sizeof(AES_KEY));
|
||||
if (enc) {
|
||||
vpaes_encrypt_key_to_bsaes(&bsaes, &bsaes);
|
||||
vpaes_encrypt_key_to_bsaes(&bsaes, &vpaes);
|
||||
} else {
|
||||
vpaes_decrypt_key_to_bsaes(&bsaes, &bsaes);
|
||||
vpaes_decrypt_key_to_bsaes(&bsaes, &vpaes);
|
||||
}
|
||||
|
||||
ASSERT_EQ(AESKeyToBytes(&ref), AESKeyToBytes(&bsaes));
|
||||
ASSERT_EQ(AESKeyToBytes(&nohw), AESKeyToBytes(&bsaes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // BSAES && !SHARED_LIBRARY
|
||||
#endif // !NO_ASM && X86_64 && !SHARED_LIBRARY
|
||||
|
||||
Executable
+3000
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable
+2909
File diff suppressed because it is too large
Load Diff
@@ -218,17 +218,19 @@ OPENSSL_INLINE void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out,
|
||||
#endif // !VPAES
|
||||
|
||||
|
||||
void aes_nohw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aes_nohw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
int aes_nohw_set_encrypt_key(const uint8_t *key, unsigned bits,
|
||||
AES_KEY *aeskey);
|
||||
int aes_nohw_set_decrypt_key(const uint8_t *key, unsigned bits,
|
||||
AES_KEY *aeskey);
|
||||
void aes_nohw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aes_nohw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aes_nohw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
const uint8_t ivec[16]);
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && \
|
||||
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
||||
#define AES_NOHW_CBC
|
||||
void aes_nohw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const AES_KEY *key, uint8_t *ivec, const int enc);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@@ -57,23 +57,7 @@
|
||||
void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE],
|
||||
uint8_t ecount_buf[AES_BLOCK_SIZE], unsigned int *num) {
|
||||
if (hwaes_capable()) {
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
|
||||
aes_hw_ctr32_encrypt_blocks);
|
||||
} else if (vpaes_capable()) {
|
||||
#if defined(VPAES_CTR32)
|
||||
// TODO(davidben): On ARM, where |BSAES| is additionally defined, this could
|
||||
// use |vpaes_ctr32_encrypt_blocks_with_bsaes|.
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
|
||||
vpaes_ctr32_encrypt_blocks);
|
||||
#else
|
||||
CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num,
|
||||
vpaes_encrypt);
|
||||
#endif
|
||||
} else {
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
|
||||
aes_nohw_ctr32_encrypt_blocks);
|
||||
}
|
||||
CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num, AES_encrypt);
|
||||
}
|
||||
|
||||
void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key,
|
||||
@@ -95,10 +79,12 @@ void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(AES_NOHW_CBC)
|
||||
if (!vpaes_capable()) {
|
||||
aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (enc) {
|
||||
CRYPTO_cbc128_encrypt(in, out, len, key, ivec, AES_encrypt);
|
||||
} else {
|
||||
|
||||
+1
-42
@@ -31,7 +31,6 @@
|
||||
#include "../internal.h"
|
||||
|
||||
#include "aes/aes.c"
|
||||
#include "aes/aes_nohw.c"
|
||||
#include "aes/key_wrap.c"
|
||||
#include "aes/mode_wrappers.c"
|
||||
#include "bn/add.c"
|
||||
@@ -70,7 +69,7 @@
|
||||
#include "ec/felem.c"
|
||||
#include "ec/oct.c"
|
||||
#include "ec/p224-64.c"
|
||||
#include "ec/p256.c"
|
||||
#include "../../third_party/fiat/p256.c"
|
||||
#include "ec/p256-x86_64.c"
|
||||
#include "ec/scalar.c"
|
||||
#include "ec/simple.c"
|
||||
@@ -84,11 +83,9 @@
|
||||
#include "modes/cfb.c"
|
||||
#include "modes/ctr.c"
|
||||
#include "modes/gcm.c"
|
||||
#include "modes/gcm_nohw.c"
|
||||
#include "modes/ofb.c"
|
||||
#include "modes/polyval.c"
|
||||
#include "rand/ctrdrbg.c"
|
||||
#include "rand/fork_detect.c"
|
||||
#include "rand/rand.c"
|
||||
#include "rand/urandom.c"
|
||||
#include "rsa/blinding.c"
|
||||
@@ -118,26 +115,6 @@ extern const uint8_t BORINGSSL_bcm_rodata_start[];
|
||||
extern const uint8_t BORINGSSL_bcm_rodata_end[];
|
||||
#endif
|
||||
|
||||
// assert_within is used to sanity check that certain symbols are within the
|
||||
// bounds of the integrity check. It checks that start <= symbol < end and
|
||||
// aborts otherwise.
|
||||
static void assert_within(const void *start, const void *symbol,
|
||||
const void *end) {
|
||||
const uintptr_t start_val = (uintptr_t) start;
|
||||
const uintptr_t symbol_val = (uintptr_t) symbol;
|
||||
const uintptr_t end_val = (uintptr_t) end;
|
||||
|
||||
if (start_val <= symbol_val && symbol_val < end_val) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
"FIPS module doesn't span expected symbol. Expected %p <= %p < %p\n",
|
||||
start, symbol, end);
|
||||
BORINGSSL_FIPS_abort();
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_ANDROID) && defined(OPENSSL_AARCH64)
|
||||
static void BORINGSSL_maybe_set_module_text_permissions(int permission) {
|
||||
// Android may be compiled in execute-only-memory mode, in which case the
|
||||
@@ -170,29 +147,11 @@ BORINGSSL_bcm_power_on_self_test(void) {
|
||||
// .text section, which triggers the global-buffer overflow detection.
|
||||
const uint8_t *const start = BORINGSSL_bcm_text_start;
|
||||
const uint8_t *const end = BORINGSSL_bcm_text_end;
|
||||
|
||||
assert_within(start, AES_encrypt, end);
|
||||
assert_within(start, RSA_sign, end);
|
||||
assert_within(start, RAND_bytes, end);
|
||||
assert_within(start, EC_GROUP_cmp, end);
|
||||
assert_within(start, SHA256_Update, end);
|
||||
assert_within(start, ECDSA_do_verify, end);
|
||||
assert_within(start, EVP_AEAD_CTX_seal, end);
|
||||
|
||||
#if defined(BORINGSSL_SHARED_LIBRARY)
|
||||
const uint8_t *const rodata_start = BORINGSSL_bcm_rodata_start;
|
||||
const uint8_t *const rodata_end = BORINGSSL_bcm_rodata_end;
|
||||
#else
|
||||
// In the static build, read-only data is placed within the .text segment.
|
||||
const uint8_t *const rodata_start = BORINGSSL_bcm_text_start;
|
||||
const uint8_t *const rodata_end = BORINGSSL_bcm_text_end;
|
||||
#endif
|
||||
|
||||
assert_within(rodata_start, kPrimes, rodata_end);
|
||||
assert_within(rodata_start, des_skb, rodata_end);
|
||||
assert_within(rodata_start, kP256Params, rodata_end);
|
||||
assert_within(rodata_start, kPKCS1SigPrefixes, rodata_end);
|
||||
|
||||
#if defined(OPENSSL_ANDROID)
|
||||
uint8_t result[SHA256_DIGEST_LENGTH];
|
||||
const EVP_MD *const kHashFunction = EVP_sha256();
|
||||
|
||||
@@ -27,6 +27,7 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
|
||||
&bn_div_words("bn_div_words");
|
||||
&bn_add_words("bn_add_words");
|
||||
&bn_sub_words("bn_sub_words");
|
||||
&bn_sub_part_words("bn_sub_part_words");
|
||||
|
||||
&asm_finish();
|
||||
|
||||
@@ -574,3 +575,211 @@ sub bn_sub_words
|
||||
|
||||
&function_end($name);
|
||||
}
|
||||
|
||||
sub bn_sub_part_words
|
||||
{
|
||||
local($name)=@_;
|
||||
|
||||
&function_begin($name,"");
|
||||
|
||||
&comment("");
|
||||
$a="esi";
|
||||
$b="edi";
|
||||
$c="eax";
|
||||
$r="ebx";
|
||||
$tmp1="ecx";
|
||||
$tmp2="edx";
|
||||
$num="ebp";
|
||||
|
||||
&mov($r,&wparam(0)); # get r
|
||||
&mov($a,&wparam(1)); # get a
|
||||
&mov($b,&wparam(2)); # get b
|
||||
&mov($num,&wparam(3)); # get num
|
||||
&xor($c,$c); # clear carry
|
||||
&and($num,0xfffffff8); # num / 8
|
||||
|
||||
&jz(&label("aw_finish"));
|
||||
|
||||
&set_label("aw_loop",0);
|
||||
for ($i=0; $i<8; $i++)
|
||||
{
|
||||
&comment("Round $i");
|
||||
|
||||
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
|
||||
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
|
||||
&sub($tmp1,$c);
|
||||
&mov($c,0);
|
||||
&adc($c,$c);
|
||||
&sub($tmp1,$tmp2);
|
||||
&adc($c,0);
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
}
|
||||
|
||||
&comment("");
|
||||
&add($a,32);
|
||||
&add($b,32);
|
||||
&add($r,32);
|
||||
&sub($num,8);
|
||||
&jnz(&label("aw_loop"));
|
||||
|
||||
&set_label("aw_finish",0);
|
||||
&mov($num,&wparam(3)); # get num
|
||||
&and($num,7);
|
||||
&jz(&label("aw_end"));
|
||||
|
||||
for ($i=0; $i<7; $i++)
|
||||
{
|
||||
&comment("Tail Round $i");
|
||||
&mov($tmp1,&DWP(0,$a,"",0)); # *a
|
||||
&mov($tmp2,&DWP(0,$b,"",0));# *b
|
||||
&sub($tmp1,$c);
|
||||
&mov($c,0);
|
||||
&adc($c,$c);
|
||||
&sub($tmp1,$tmp2);
|
||||
&adc($c,0);
|
||||
&mov(&DWP(0,$r,"",0),$tmp1); # *r
|
||||
&add($a, 4);
|
||||
&add($b, 4);
|
||||
&add($r, 4);
|
||||
&dec($num) if ($i != 6);
|
||||
&jz(&label("aw_end")) if ($i != 6);
|
||||
}
|
||||
&set_label("aw_end",0);
|
||||
|
||||
&cmp(&wparam(4),0);
|
||||
&je(&label("pw_end"));
|
||||
|
||||
&mov($num,&wparam(4)); # get dl
|
||||
&cmp($num,0);
|
||||
&je(&label("pw_end"));
|
||||
&jge(&label("pw_pos"));
|
||||
|
||||
&comment("pw_neg");
|
||||
&mov($tmp2,0);
|
||||
&sub($tmp2,$num);
|
||||
&mov($num,$tmp2);
|
||||
&and($num,0xfffffff8); # num / 8
|
||||
&jz(&label("pw_neg_finish"));
|
||||
|
||||
&set_label("pw_neg_loop",0);
|
||||
for ($i=0; $i<8; $i++)
|
||||
{
|
||||
&comment("dl<0 Round $i");
|
||||
|
||||
&mov($tmp1,0);
|
||||
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
|
||||
&sub($tmp1,$c);
|
||||
&mov($c,0);
|
||||
&adc($c,$c);
|
||||
&sub($tmp1,$tmp2);
|
||||
&adc($c,0);
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
}
|
||||
|
||||
&comment("");
|
||||
&add($b,32);
|
||||
&add($r,32);
|
||||
&sub($num,8);
|
||||
&jnz(&label("pw_neg_loop"));
|
||||
|
||||
&set_label("pw_neg_finish",0);
|
||||
&mov($tmp2,&wparam(4)); # get dl
|
||||
&mov($num,0);
|
||||
&sub($num,$tmp2);
|
||||
&and($num,7);
|
||||
&jz(&label("pw_end"));
|
||||
|
||||
for ($i=0; $i<7; $i++)
|
||||
{
|
||||
&comment("dl<0 Tail Round $i");
|
||||
&mov($tmp1,0);
|
||||
&mov($tmp2,&DWP($i*4,$b,"",0));# *b
|
||||
&sub($tmp1,$c);
|
||||
&mov($c,0);
|
||||
&adc($c,$c);
|
||||
&sub($tmp1,$tmp2);
|
||||
&adc($c,0);
|
||||
&dec($num) if ($i != 6);
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
&jz(&label("pw_end")) if ($i != 6);
|
||||
}
|
||||
|
||||
&jmp(&label("pw_end"));
|
||||
|
||||
&set_label("pw_pos",0);
|
||||
|
||||
&and($num,0xfffffff8); # num / 8
|
||||
&jz(&label("pw_pos_finish"));
|
||||
|
||||
&set_label("pw_pos_loop",0);
|
||||
|
||||
for ($i=0; $i<8; $i++)
|
||||
{
|
||||
&comment("dl>0 Round $i");
|
||||
|
||||
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
|
||||
&sub($tmp1,$c);
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
&jnc(&label("pw_nc".$i));
|
||||
}
|
||||
|
||||
&comment("");
|
||||
&add($a,32);
|
||||
&add($r,32);
|
||||
&sub($num,8);
|
||||
&jnz(&label("pw_pos_loop"));
|
||||
|
||||
&set_label("pw_pos_finish",0);
|
||||
&mov($num,&wparam(4)); # get dl
|
||||
&and($num,7);
|
||||
&jz(&label("pw_end"));
|
||||
|
||||
for ($i=0; $i<7; $i++)
|
||||
{
|
||||
&comment("dl>0 Tail Round $i");
|
||||
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
|
||||
&sub($tmp1,$c);
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
&jnc(&label("pw_tail_nc".$i));
|
||||
&dec($num) if ($i != 6);
|
||||
&jz(&label("pw_end")) if ($i != 6);
|
||||
}
|
||||
&mov($c,1);
|
||||
&jmp(&label("pw_end"));
|
||||
|
||||
&set_label("pw_nc_loop",0);
|
||||
for ($i=0; $i<8; $i++)
|
||||
{
|
||||
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
&set_label("pw_nc".$i,0);
|
||||
}
|
||||
|
||||
&comment("");
|
||||
&add($a,32);
|
||||
&add($r,32);
|
||||
&sub($num,8);
|
||||
&jnz(&label("pw_nc_loop"));
|
||||
|
||||
&mov($num,&wparam(4)); # get dl
|
||||
&and($num,7);
|
||||
&jz(&label("pw_nc_end"));
|
||||
|
||||
for ($i=0; $i<7; $i++)
|
||||
{
|
||||
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
|
||||
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
|
||||
&set_label("pw_tail_nc".$i,0);
|
||||
&dec($num) if ($i != 6);
|
||||
&jz(&label("pw_nc_end")) if ($i != 6);
|
||||
}
|
||||
|
||||
&set_label("pw_nc_end",0);
|
||||
&mov($c,0);
|
||||
|
||||
&set_label("pw_end",0);
|
||||
|
||||
# &mov("eax",$c); # $c is "eax"
|
||||
|
||||
&function_end($name);
|
||||
}
|
||||
|
||||
+22
-108
@@ -73,7 +73,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -92,7 +91,6 @@
|
||||
#include "../../test/abi_test.h"
|
||||
#include "../../test/file_test.h"
|
||||
#include "../../test/test_util.h"
|
||||
#include "../../test/wycheproof_util.h"
|
||||
|
||||
|
||||
static int HexToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
|
||||
@@ -659,26 +657,11 @@ static void TestModMul(BIGNUMFileTest *t, BN_CTX *ctx) {
|
||||
bn_mod_mul_montgomery_small(r_words.get(), a_words.get(), b_words.get(),
|
||||
m_width, mont.get());
|
||||
// Use the second half of |tmp| so ASan will catch out-of-bounds writes.
|
||||
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
|
||||
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width,
|
||||
mont.get());
|
||||
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
|
||||
EXPECT_BIGNUMS_EQUAL("A * B (mod M) (Montgomery, words)", mod_mul.get(),
|
||||
ret.get());
|
||||
|
||||
// |bn_from_montgomery_small| must additionally work on double-width
|
||||
// inputs. Test this by running |bn_from_montgomery_small| on the result
|
||||
// of a product. Note |a_words| * |b_words| has an extra factor of R^2, so
|
||||
// we must reduce twice.
|
||||
std::unique_ptr<BN_ULONG[]> prod_words(new BN_ULONG[m_width * 2]);
|
||||
bn_mul_small(prod_words.get(), m_width * 2, a_words.get(), m_width,
|
||||
b_words.get(), m_width);
|
||||
bn_from_montgomery_small(r_words.get(), m_width, prod_words.get(),
|
||||
m_width * 2, mont.get());
|
||||
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
|
||||
mont.get());
|
||||
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
|
||||
EXPECT_BIGNUMS_EQUAL("A * B (mod M) (Montgomery, words)",
|
||||
mod_mul.get(), ret.get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -736,8 +719,7 @@ static void TestModSquare(BIGNUMFileTest *t, BN_CTX *ctx) {
|
||||
bn_to_montgomery_small(a_words.get(), a_words.get(), m_width, mont.get());
|
||||
bn_mod_mul_montgomery_small(r_words.get(), a_words.get(), a_words.get(),
|
||||
m_width, mont.get());
|
||||
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
|
||||
mont.get());
|
||||
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width, mont.get());
|
||||
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
|
||||
EXPECT_BIGNUMS_EQUAL("A * A (mod M) (Montgomery, words)",
|
||||
mod_square.get(), ret.get());
|
||||
@@ -748,7 +730,7 @@ static void TestModSquare(BIGNUMFileTest *t, BN_CTX *ctx) {
|
||||
bn_mod_mul_montgomery_small(r_words.get(), a_words.get(),
|
||||
a_copy_words.get(), m_width, mont.get());
|
||||
// Use the second half of |tmp| so ASan will catch out-of-bounds writes.
|
||||
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
|
||||
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width,
|
||||
mont.get());
|
||||
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
|
||||
EXPECT_BIGNUMS_EQUAL("A * A_copy (mod M) (Montgomery, words)",
|
||||
@@ -799,7 +781,7 @@ static void TestModExp(BIGNUMFileTest *t, BN_CTX *ctx) {
|
||||
bn_to_montgomery_small(a_words.get(), a_words.get(), m_width, mont.get());
|
||||
bn_mod_exp_mont_small(r_words.get(), a_words.get(), m_width, e->d,
|
||||
e->width, mont.get());
|
||||
bn_from_montgomery_small(r_words.get(), m_width, r_words.get(), m_width,
|
||||
bn_from_montgomery_small(r_words.get(), r_words.get(), m_width,
|
||||
mont.get());
|
||||
ASSERT_TRUE(bn_set_words(ret.get(), r_words.get(), m_width));
|
||||
EXPECT_BIGNUMS_EQUAL("A ^ E (mod M) (Montgomery, words)", mod_exp.get(),
|
||||
@@ -2004,17 +1986,16 @@ TEST_F(BNTest, PrimeChecking) {
|
||||
|
||||
ASSERT_TRUE(BN_set_word(p.get(), i));
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks, ctx(),
|
||||
false /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(is_prime ? 1 : 0, is_probably_prime_1);
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks, ctx(),
|
||||
true /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(is_prime ? 1 : 0, is_probably_prime_2);
|
||||
if (i > 3 && i % 2 == 1) {
|
||||
ASSERT_TRUE(BN_enhanced_miller_rabin_primality_test(
|
||||
&result_3, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
nullptr /* callback */));
|
||||
&result_3, p.get(), BN_prime_checks, ctx(), nullptr /* callback */));
|
||||
EXPECT_EQ(is_prime, result_3 == bn_probably_prime);
|
||||
}
|
||||
}
|
||||
@@ -2022,13 +2003,13 @@ TEST_F(BNTest, PrimeChecking) {
|
||||
// Negative numbers are not prime.
|
||||
ASSERT_TRUE(BN_set_word(p.get(), 7));
|
||||
BN_set_negative(p.get(), 1);
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
false /* do_trial_division */, nullptr /* callback */));
|
||||
ASSERT_TRUE(BN_primality_test(&is_probably_prime_1, p.get(), BN_prime_checks,
|
||||
ctx(), false /* do_trial_division */,
|
||||
nullptr /* callback */));
|
||||
EXPECT_EQ(0, is_probably_prime_1);
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
true /* do_trial_division */, nullptr /* callback */));
|
||||
ASSERT_TRUE(BN_primality_test(&is_probably_prime_2, p.get(), BN_prime_checks,
|
||||
ctx(), true /* do_trial_division */,
|
||||
nullptr /* callback */));
|
||||
EXPECT_EQ(0, is_probably_prime_2);
|
||||
|
||||
static const char *kComposites[] = {
|
||||
@@ -2087,18 +2068,17 @@ TEST_F(BNTest, PrimeChecking) {
|
||||
EXPECT_NE(0, DecimalToBIGNUM(&p, str));
|
||||
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks, ctx(),
|
||||
false /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(0, is_probably_prime_1);
|
||||
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks, ctx(),
|
||||
true /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(0, is_probably_prime_2);
|
||||
|
||||
ASSERT_TRUE(BN_enhanced_miller_rabin_primality_test(
|
||||
&result_3, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
nullptr /* callback */));
|
||||
&result_3, p.get(), BN_prime_checks, ctx(), nullptr /* callback */));
|
||||
EXPECT_EQ(bn_composite, result_3);
|
||||
}
|
||||
|
||||
@@ -2277,94 +2257,28 @@ TEST_F(BNTest, PrimeChecking) {
|
||||
EXPECT_NE(0, HexToBIGNUM(&p, str));
|
||||
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks, ctx(),
|
||||
false /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(1, is_probably_prime_1);
|
||||
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
&is_probably_prime_2, p.get(), BN_prime_checks, ctx(),
|
||||
true /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(1, is_probably_prime_2);
|
||||
|
||||
ASSERT_TRUE(BN_enhanced_miller_rabin_primality_test(
|
||||
&result_3, p.get(), BN_prime_checks_for_generation, ctx(),
|
||||
nullptr /* callback */));
|
||||
&result_3, p.get(), BN_prime_checks, ctx(), nullptr /* callback */));
|
||||
EXPECT_EQ(bn_probably_prime, result_3);
|
||||
}
|
||||
|
||||
// BN_primality_test works with null |BN_CTX|.
|
||||
ASSERT_TRUE(BN_set_word(p.get(), 5));
|
||||
ASSERT_TRUE(
|
||||
BN_primality_test(&is_probably_prime_1, p.get(),
|
||||
BN_prime_checks_for_generation, nullptr /* ctx */,
|
||||
false /* do_trial_division */, nullptr /* callback */));
|
||||
ASSERT_TRUE(BN_primality_test(
|
||||
&is_probably_prime_1, p.get(), BN_prime_checks, nullptr /* ctx */,
|
||||
false /* do_trial_division */, nullptr /* callback */));
|
||||
EXPECT_EQ(1, is_probably_prime_1);
|
||||
}
|
||||
|
||||
TEST_F(BNTest, MillerRabinIteration) {
|
||||
FileTestGTest(
|
||||
"crypto/fipsmodule/bn/miller_rabin_tests.txt", [&](FileTest *t) {
|
||||
BIGNUMFileTest bn_test(t, /*large_mask=*/0);
|
||||
|
||||
bssl::UniquePtr<BIGNUM> w = bn_test.GetBIGNUM("W");
|
||||
ASSERT_TRUE(w);
|
||||
bssl::UniquePtr<BIGNUM> b = bn_test.GetBIGNUM("B");
|
||||
ASSERT_TRUE(b);
|
||||
bssl::UniquePtr<BN_MONT_CTX> mont(
|
||||
BN_MONT_CTX_new_consttime(w.get(), ctx()));
|
||||
ASSERT_TRUE(mont);
|
||||
|
||||
bssl::BN_CTXScope scope(ctx());
|
||||
BN_MILLER_RABIN miller_rabin;
|
||||
ASSERT_TRUE(bn_miller_rabin_init(&miller_rabin, mont.get(), ctx()));
|
||||
int possibly_prime;
|
||||
ASSERT_TRUE(bn_miller_rabin_iteration(&miller_rabin, &possibly_prime,
|
||||
b.get(), mont.get(), ctx()));
|
||||
|
||||
std::string result;
|
||||
ASSERT_TRUE(t->GetAttribute(&result, "Result"));
|
||||
EXPECT_EQ(result, possibly_prime ? "PossiblyPrime" : "Composite");
|
||||
});
|
||||
}
|
||||
|
||||
// These tests are very slow, so we disable them by default to avoid timing out
|
||||
// downstream consumers. They are enabled when running tests standalone via
|
||||
// all_tests.go.
|
||||
TEST_F(BNTest, DISABLED_WycheproofPrimality) {
|
||||
FileTestGTest(
|
||||
"third_party/wycheproof_testvectors/primality_test.txt",
|
||||
[&](FileTest *t) {
|
||||
WycheproofResult result;
|
||||
ASSERT_TRUE(GetWycheproofResult(t, &result));
|
||||
bssl::UniquePtr<BIGNUM> value = GetWycheproofBIGNUM(t, "value", false);
|
||||
ASSERT_TRUE(value);
|
||||
|
||||
for (int checks :
|
||||
{BN_prime_checks_for_validation, BN_prime_checks_for_generation}) {
|
||||
SCOPED_TRACE(checks);
|
||||
if (checks == BN_prime_checks_for_generation &&
|
||||
std::find(result.flags.begin(), result.flags.end(),
|
||||
"WorstCaseMillerRabin") != result.flags.end()) {
|
||||
// Skip the worst case Miller-Rabin cases.
|
||||
// |BN_prime_checks_for_generation| relies on such values being rare
|
||||
// when generating primes.
|
||||
continue;
|
||||
}
|
||||
|
||||
int is_probably_prime;
|
||||
ASSERT_TRUE(BN_primality_test(&is_probably_prime, value.get(), checks,
|
||||
ctx(),
|
||||
/*do_trial_division=*/false, nullptr));
|
||||
EXPECT_EQ(result.IsValid() ? 1 : 0, is_probably_prime);
|
||||
|
||||
ASSERT_TRUE(BN_primality_test(&is_probably_prime, value.get(), checks,
|
||||
ctx(),
|
||||
/*do_trial_division=*/true, nullptr));
|
||||
EXPECT_EQ(result.IsValid() ? 1 : 0, is_probably_prime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(BNTest, NumBitsWord) {
|
||||
constexpr BN_ULONG kOne = 1;
|
||||
|
||||
|
||||
@@ -10673,108 +10673,6 @@ A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
E = 2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020FF2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2020202020ff
|
||||
|
||||
# Test vectors for CVE-2019-1551. (We do not carry the assembly file with the
|
||||
# bug, but we use the test vectors anyway.)
|
||||
|
||||
# Original test vectors by OSS-Fuzz.
|
||||
ModExp = 9d675d188a07e9bd1b32638cc8cfd5002ef89bd1a9648f806567b87939140a67977dc8da17323b8e4c6bc53875cda8b656df8f54cc32e44fd9c21d122ea3c0d6
|
||||
A = dea9b3e0b44ae67b2ac9b7c2b18eeb4dab206b014981a46ac409f195eeb6896f132cf8497c87d1188008ee511054ebb426203355b7d515dce9501cb759ac1373
|
||||
E = b01ae745b101e9e45ec05dcff72e7f8fc04c79ffe324301fda0b4f7be81d85c4e875c73fc6c5cb40000000000000000000000000000000000
|
||||
M = ffffffff01ffffffffffffffffffffffffffe2000000000000000000000000000010fab8d960706cd4c21818115650cad61d4f10da325dffffffff00ffff00ff
|
||||
|
||||
ModExp = 651f811b62ee8770e3598c340864dd6b0be9bb6376b6f933ab216fd55538e6ad1000cb2b3c64f54d554e004b6eec8138e6ecff00452d443a42041b72e6cd9ead
|
||||
A = 3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e
|
||||
E = 3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e09003e3e3e3e3e3e3e3e3e3e3e3e3e3e010900230a01230a2100ffffff0000adf300a58700000000ffffff00
|
||||
M = ffffff0b00000000000000000000000000ffffffff0000ffffffff00000a0000000a00000000000000000000ffffffff000000000000ffffffffffff000000ff
|
||||
|
||||
# Test vectors for rsaz_512_sqr bug, with rcx/rbx=1
|
||||
|
||||
# between first and second iteration
|
||||
ModExp = 1
|
||||
A = 624e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d973b6
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between second and third iteration
|
||||
ModExp = 1
|
||||
A = 11024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d97360800000000000000f
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between third and fourth iteration
|
||||
ModExp = 1
|
||||
A = 4171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d9736080000000000000000000000000000039
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between fourth and fifth iteration
|
||||
ModExp = 1
|
||||
A = 6a171024e6a171024e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d97360800000000000000000000000000000000000000000000006
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between fifth and sixth iteration
|
||||
ModExp = 1
|
||||
A = 44e6a171024e6a171024e6a171024e6a14ce297f2873536f959d8c3390d97360800000000000000000000000000000000000000000000000000000000000003c
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between sixth and seventh iteration
|
||||
ModExp = 1
|
||||
A = 1024e6a171024e6a14ce297f2873536f959d8c3390d973608000000000000000000000000000000000000000000000000000000000000000000000000000000e
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between seventh and eighth iteration
|
||||
ModExp = 1
|
||||
A = 626eee5e3c8653be47ed15e84b97cc7f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000187
|
||||
E = c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f8
|
||||
M = c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f9
|
||||
|
||||
# Test vectors for rsaz_512_srq bug, with rcx/rbx=2
|
||||
|
||||
# between first and second iteration
|
||||
ModExp = 1
|
||||
A = 3c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf7c
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between second and third iteration
|
||||
ModExp = 1
|
||||
A = 485c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf47800000000000003f
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between third and forth iteration
|
||||
ModExp = 1
|
||||
A = 59a85c40939a85c40939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf478000000000000000000000000000004e
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between forth and fifth iteration
|
||||
ModExp = 1
|
||||
A = 2939a85c40939a85c40939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf47800000000000000000000000000000000000000000000024
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between fifth and sixth iteration
|
||||
ModExp = 1
|
||||
A = 640939a85c40939a85c40939a85c4093995e8efdb195e8efd8caf477ed8caf478000000000000000000000000000000000000000000000000000000000000057
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between sixth and seventh iteration
|
||||
ModExp = 1
|
||||
A = 25c40939a85c4093995e8efdb195e8efd8caf477ed8caf4780000000000000000000000000000000000000000000000000000000000000000000000000000021
|
||||
E = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006e
|
||||
M = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f
|
||||
|
||||
# between seventh and eighth iteration
|
||||
ModExp = 1
|
||||
A = 7b4919849931b28a14fcace213f2b3884fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84b6e67b66ce4d9c
|
||||
E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000004c
|
||||
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000004d
|
||||
|
||||
|
||||
# Exp tests.
|
||||
#
|
||||
|
||||
@@ -228,8 +228,8 @@ func main() {
|
||||
checkResult(test, "A ^ E", "Exp", r)
|
||||
}
|
||||
case "ModSqrt":
|
||||
bigOne := big.NewInt(1)
|
||||
bigTwo := big.NewInt(2)
|
||||
bigOne := new(big.Int).SetInt64(1)
|
||||
bigTwo := new(big.Int).SetInt64(2)
|
||||
|
||||
if checkKeys(test, "A", "P", "ModSqrt") {
|
||||
test.Values["A"].Mod(test.Values["A"], test.Values["P"])
|
||||
@@ -249,21 +249,8 @@ func main() {
|
||||
}
|
||||
case "ModInv":
|
||||
if checkKeys(test, "A", "M", "ModInv") {
|
||||
a := test.Values["A"]
|
||||
m := test.Values["M"]
|
||||
var r *big.Int
|
||||
if a.Sign() == 0 && m.IsInt64() && m.Int64() == 1 {
|
||||
// OpenSSL says 0^(-1) mod (1) is 0, while Go says the
|
||||
// inverse does not exist.
|
||||
r = big.NewInt(0)
|
||||
} else {
|
||||
r = new(big.Int).ModInverse(a, m)
|
||||
}
|
||||
if r == nil {
|
||||
fmt.Fprintf(os.Stderr, "Line %d: A has no inverse mod M.\n", test.LineNumber)
|
||||
} else {
|
||||
checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
|
||||
}
|
||||
r := new(big.Int).ModInverse(test.Values["A"], test.Values["M"])
|
||||
checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
|
||||
}
|
||||
case "ModSquare":
|
||||
if checkKeys(test, "A", "M", "ModSquare") {
|
||||
|
||||
@@ -732,7 +732,7 @@ void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
num_p--;
|
||||
}
|
||||
if (num_p == 0) {
|
||||
bn_from_montgomery_small(r, num, mont->RR.d, num, mont);
|
||||
bn_from_montgomery_small(r, mont->RR.d, num, mont);
|
||||
return;
|
||||
}
|
||||
unsigned bits = BN_num_bits_word(p[num_p - 1]) + (num_p - 1) * BN_BITS2;
|
||||
@@ -809,8 +809,8 @@ void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
OPENSSL_cleanse(val, sizeof(val));
|
||||
}
|
||||
|
||||
void bn_mod_inverse0_prime_mont_small(BN_ULONG *r, const BN_ULONG *a,
|
||||
size_t num, const BN_MONT_CTX *mont) {
|
||||
void bn_mod_inverse_prime_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
const BN_MONT_CTX *mont) {
|
||||
if (num != (size_t)mont->N.width || num > BN_SMALL_MAX_WORDS) {
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -404,19 +404,9 @@ uint64_t bn_mont_n0(const BIGNUM *n);
|
||||
int bn_mod_exp_base_2_consttime(BIGNUM *r, unsigned p, const BIGNUM *n,
|
||||
BN_CTX *ctx);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(OPENSSL_X86_64)
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
#elif defined(OPENSSL_AARCH64)
|
||||
#define BN_UMULT_LOHI(low, high, a, b) \
|
||||
do { \
|
||||
const BN_ULONG _a = (a); \
|
||||
const BN_ULONG _b = (b); \
|
||||
(low) = _a * _b; \
|
||||
(high) = __umulh(_a, _b); \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
|
||||
#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
|
||||
@@ -447,40 +437,6 @@ OPENSSL_EXPORT uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d);
|
||||
// of the first several odd primes and zero otherwise.
|
||||
int bn_odd_number_is_obviously_composite(const BIGNUM *bn);
|
||||
|
||||
// A BN_MILLER_RABIN stores state common to each Miller-Rabin iteration. It is
|
||||
// initialized within an existing |BN_CTX| scope and may not be used after
|
||||
// that scope is released with |BN_CTX_end|. Field names match those in FIPS
|
||||
// 186-4, section C.3.1.
|
||||
typedef struct {
|
||||
// w1 is w-1.
|
||||
BIGNUM *w1;
|
||||
// m is (w-1)/2^a.
|
||||
BIGNUM *m;
|
||||
// one_mont is 1 (mod w) in Montgomery form.
|
||||
BIGNUM *one_mont;
|
||||
// w1_mont is w-1 (mod w) in Montgomery form.
|
||||
BIGNUM *w1_mont;
|
||||
// w_bits is BN_num_bits(w).
|
||||
int w_bits;
|
||||
// a is the largest integer such that 2^a divides w-1.
|
||||
int a;
|
||||
} BN_MILLER_RABIN;
|
||||
|
||||
// bn_miller_rabin_init initializes |miller_rabin| for testing if |mont->N| is
|
||||
// prime. It returns one on success and zero on error.
|
||||
OPENSSL_EXPORT int bn_miller_rabin_init(BN_MILLER_RABIN *miller_rabin,
|
||||
const BN_MONT_CTX *mont, BN_CTX *ctx);
|
||||
|
||||
// bn_miller_rabin_iteration performs one Miller-Rabin iteration, checking if
|
||||
// |b| is a composite witness for |mont->N|. |miller_rabin| must have been
|
||||
// initialized with |bn_miller_rabin_setup|. On success, it returns one and sets
|
||||
// |*out_is_possibly_prime| to one if |mont->N| may still be prime or zero if
|
||||
// |b| shows it is composite. On allocation or internal failure, it returns
|
||||
// zero.
|
||||
OPENSSL_EXPORT int bn_miller_rabin_iteration(
|
||||
const BN_MILLER_RABIN *miller_rabin, int *out_is_possibly_prime,
|
||||
const BIGNUM *b, const BN_MONT_CTX *mont, BN_CTX *ctx);
|
||||
|
||||
// bn_rshift1_words sets |r| to |a| >> 1, where both arrays are |num| bits wide.
|
||||
void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num);
|
||||
|
||||
@@ -657,13 +613,10 @@ void bn_to_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
const BN_MONT_CTX *mont);
|
||||
|
||||
// bn_from_montgomery_small sets |r| to |a| translated out of the Montgomery
|
||||
// domain. |r| and |a| are |num_r| and |num_a| words long, respectively. |num_r|
|
||||
// must be |mont->N.width|. |a| must be at most |mont->N|^2 and may alias |r|.
|
||||
//
|
||||
// Unlike most of these functions, only |num_r| is bounded by
|
||||
// |BN_SMALL_MAX_WORDS|. |num_a| may exceed it, but must be at most 2 * |num_r|.
|
||||
void bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
|
||||
size_t num_a, const BN_MONT_CTX *mont);
|
||||
// domain. |r| and |a| are |num| words long, which must be |mont->N.width|. |a|
|
||||
// must be fully-reduced and may alias |r|.
|
||||
void bn_from_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
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. Each array is |num| words long,
|
||||
@@ -688,13 +641,13 @@ void bn_mod_exp_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
const BN_ULONG *p, size_t num_p,
|
||||
const BN_MONT_CTX *mont);
|
||||
|
||||
// bn_mod_inverse0_prime_mont_small sets |r| to |a|^-1 mod |mont->N|. If |a| is
|
||||
// zero, |r| is set to zero. |mont->N| must be a prime. |r| and |a| are |num|
|
||||
// words long, which must be |mont->N.width| and at most |BN_SMALL_MAX_WORDS|.
|
||||
// |a| must be fully-reduced and may alias |r|. This function runs in time
|
||||
// independent of |a|, but |mont->N| is a public value.
|
||||
void bn_mod_inverse0_prime_mont_small(BN_ULONG *r, const BN_ULONG *a,
|
||||
size_t num, 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. |r| and |a| are |num| words long, which must be
|
||||
// |mont->N.width| and at most |BN_SMALL_MAX_WORDS|. |a| must be fully-reduced
|
||||
// and may alias |r|. This function runs in time independent of |a|, but
|
||||
// |mont->N| is a public value.
|
||||
void bn_mod_inverse_prime_mont_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
const BN_MONT_CTX *mont);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@@ -1,406 +0,0 @@
|
||||
# This file contains test vectors for whether B is a Miller-Rabin composite
|
||||
# witness for W. W must be odd and B must satisfy 1 <= B <= W-1.
|
||||
#
|
||||
# The following Python function may be used to check values.
|
||||
#
|
||||
# def is_miller_rabin_witness(w, b):
|
||||
# # Variable names taken from FIPS 186-4 C.3.1 but the algorithm skips a
|
||||
# # couple of optimizations in the FIPS formulation.
|
||||
# m = w - 1
|
||||
# a = 0
|
||||
# while m&1 == 0:
|
||||
# a += 1
|
||||
# m //= 2
|
||||
# # b is a composite witness for w iff the following are true:
|
||||
# # - b^m != 1 (mod w)
|
||||
# # - b^(m*2^j) != -1 (mod w), for 0 <= j < a
|
||||
# z = pow(b, m, w)
|
||||
# if z == 1:
|
||||
# # b^m = 1 (mod w)
|
||||
# return False
|
||||
# for j in range(a):
|
||||
# if z == w-1:
|
||||
# # b^(m*2^j) = -1 (mod w)
|
||||
# return False
|
||||
# z = (z * z) % w
|
||||
# # At this point, z is b^(w-1) (mod w). If z is not 1, w has failed the
|
||||
# # Fermat test and is composite. If z is 1, the value of z immediately
|
||||
# # before it became 1 is a non-trivial root of unity and w is composite.
|
||||
# return True
|
||||
|
||||
# Exhaustively test a small prime.
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 7
|
||||
B = 1
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 7
|
||||
B = 2
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 7
|
||||
B = 3
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 7
|
||||
B = 4
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 7
|
||||
B = 5
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 7
|
||||
B = 6
|
||||
|
||||
|
||||
# Random large inputs which try to cover a few cases. The nontrivial square root
|
||||
# case appears to be difficult to hit randomly.
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = d6b4ffc7cf70b2a2fc5d6023015875504d40e3dcce7c2e6b762c3de7bb806a5074144e7054198dabf53d23108679ccc541d5a99efeb1d1abaf89e0dbcead2a8b
|
||||
B = fabbafdbec6494ddb5ea4bf458536e87082369b0e53a200ed413f3e64b2fddc7c57c565710fbe73fae5b188fce97d8dcca74c2b5d90906c96d3c2c358a735cd
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 52cc61c42b341ad56dc11495e7cb2fe31e506b9e99522efbf44cd7c28468d3833c5e360f3c77b0aa43c0495c4e14665ab0d7cee9294c722f0de47d4401828401
|
||||
B = 3bdc9639c0fc2e77ab48d46e0b4ac6529c11c900e8fe4d82d75767c0556feb23d3f42d4924d16876a743feb386b7b84c7fd16a6c252f662faf0024d19972e62f
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = cff9897aa7dce0f2afad262b2de57d301305de717f3539c537c4ce062f8cb70df13fbc1eb4a3b9f0958a8810d1ca9042b4f23334b285a15fee3fc66498761d4b
|
||||
B = 9ceb43132fddf9ee4104ea1cb3eb2253c1d7f803f05f0305de9e31a17dd75832f47b8bf189a9b7ca0905f2a7470d9c6349080f481ff1708696fa12d972e7d7ba
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 67d1825dad5344170e65247a87aef1634a1b32bdc22f2f04d9d2959767bb5a27610fba55cd607e0f9fdd9fbb0f7f98e40d5e1eb2f52318fb5be4dbfd30d38861
|
||||
B = 260fb14724ff80984736859d8755ee98b25bcb56db9fde1db001a1e1273374034c5b75fd60b3710c7a08ce7d390776f010f384d4e32943cf0c477497d53e9e05
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = ad0bc85b58aaa204177aa9431a40929beb1cbea2dd6f66a25cc54600013213b225ba881805661df43f4208965ada7aacc8095d07d3cbef1a7bbfaae8b745f731
|
||||
B = 3d9310f20e9c80269fa6830c7e1a6f02fc5c58646001a9ef6b8b3e496602ff22c3dcb2ddb6a221723fc1722ce237fb46f7a7bb2945e415c8839b15a972f076c9
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = b25c917f55f6c7b596921daba919f35039e5d805119c1587e99849dd7104460c86214f162a6f17aea847bc7f3859e59f2991d457059511972ef373d4bc75e309
|
||||
B = a1f10b261dee84619b0423201d46af19eef9ec0612cf947c4d5c36c0c4b28207f75967e69452eabad0a5dcd28f27f7a8a7ed9c8b3e5026c6e0ba5634d94c2d44
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = d3eeb0eff05b6992e9fa61b02755e155f4aae28c6e45ddb874edd86acdd2d83d18a20e0e00d8b8bc94b92d14fc3f41ced6ababe8ac98c7730c075dbe0f699369
|
||||
B = 6b7717269c6225203681a1cacec87cacd83003ec6e9e3f04effcc4f86634770c0860e1f2770b8f303719a44949664a1094205a99d95a0856758fed66d690105e
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 64561b8d9aa50340c3a01ccb3e6e17f5023513661c012be288f3900a3ca76890e67290b9560fa1d480f9d2aacccca581b5690636665f243fa13aff5d0bff12d3
|
||||
B = 1f5ff70d3d60671ebc5fbfca731898a04438053dbc3c841e6335f487e457d92d9efb5d506d5bef6872d58d12b9a41c950bfc38d12ed977c90eacdd6535b811a0
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 69c63fbf44df21b0ed0ee929a740c12d1f3f064da0dcd9d509f31fa45fa27d1a759ab5a9f6f1040d7ee90a0b1e68f779273c41ea1c1198fd547ff6bd70c7e787
|
||||
B = 5f7996a9bbfd8fd88e472220b70077bfdacdd63d88885134431f024c2acb7126827b174eb093eb5313f07bb5461de9b0feb7d77ca2c39c2a323a150f33ea525f
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 28cc3e08c44571c6dcb98a9ab8b4f3e2b16e1f884997d94a3188bcbb7f1b7cdaecdae8329c013ec8f75dc00004da0039943e4262cd080b16a42910102e00dddb
|
||||
B = 512061ab1c69931c2fa0bb89d8d09f3c9209230bf927ddd6fb6a72075f967ed3c4dbb5f437bf4d31ca7344782b22011ad56609dc19aed65319bababfc13dd7
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 4eeb7b4d371c45fe8586fee3b1efd792176b70f6cc2698dfa1dd028366626febe0199c3c5f77a5c3cad0057a04767383051d41965255d03681b2a37edad34a9b
|
||||
B = 4afc2e85f84017b3fd6967a227eb74c8297b40ea02733d9513bff9b3f01081963f25872f4254afc4e9321eea35b2a1e42eadb186fcc84f2f30f4a994350b93b8
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 8e35a959555dd2eb66c65cee3c264071d20671f159e1f9896f1d0ceb041905fcf053eacc189de317c3ee6f93901223cbf30d5b7ddbbdab981790e2f6397e6803
|
||||
B = 44c0153759309ec4e5b1e59d57c1b126545ef7ea302b6e43561df4d16068b922389d6924f01c945d9080d1f93a0732599bdedae72d6d590839dc0884dd860441
|
||||
|
||||
|
||||
# 0x6c1 = 1729 = 7 * 13 * 19 is a Fermat pseudoprime.
|
||||
|
||||
# Found non-trivial square root
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = b8
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = 111
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = 11d
|
||||
|
||||
# Found non-trivial square root
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = 19c
|
||||
|
||||
# Found non-trivial square root
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = 223
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = 3aa
|
||||
|
||||
# Found non-trivial square root
|
||||
Result = Composite
|
||||
W = 6c1
|
||||
B = 653
|
||||
|
||||
|
||||
# 1729 has a number of false witnesses.
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 78
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = eb
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 178
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 178
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 1aa
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 271
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 2b2
|
||||
|
||||
|
||||
# 1 and W-1 are always nonwitnesses.
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 1
|
||||
|
||||
Result = PossiblyPrime
|
||||
W = 6c1
|
||||
B = 6c0
|
||||
|
||||
|
||||
# https://kconrad.math.uconn.edu/blurbs/ugradnumthy/millerrabin.pdf, examples
|
||||
# 3.1 and 3.2 has a complete list of false witnesses for 65 = 0x41 and
|
||||
# 85 = 0x55.
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 41
|
||||
B = 1
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 41
|
||||
B = 8
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 41
|
||||
B = 12
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 41
|
||||
B = 2f
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 41
|
||||
B = 39
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 41
|
||||
B = 40
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 55
|
||||
B = 1
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 55
|
||||
B = d
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 55
|
||||
B = 26
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 55
|
||||
B = 2f
|
||||
|
||||
# Some b^(m*2^j) = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 55
|
||||
B = 48
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 55
|
||||
B = 54
|
||||
|
||||
# Other witnesses for 65 and 85 will report composite:
|
||||
|
||||
# Found non-trivial square root
|
||||
Result = Composite
|
||||
W = 41
|
||||
B = 2c
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 41
|
||||
B = 16
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 41
|
||||
B = 14
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 41
|
||||
B = 2
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 41
|
||||
B = 3a
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 55
|
||||
B = 40
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 55
|
||||
B = 7
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 55
|
||||
B = 23
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 55
|
||||
B = 2e
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 55
|
||||
B = 2a
|
||||
|
||||
# W below is composite, but it is one of the worst case scenarios for
|
||||
# Miller-Rabin, from Wycheproof tests. 1/4 of witnesses report the value is
|
||||
# prime. Test that we correctly classify false and true witnesses.
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 379c6027f818b5164bc13dff5e996ec7210976f33570d5c60275918b8988d97a63bb6582af85682c45667a8b94b7acab4d919ede00f5bd2ba7abc8634d66f8875fd930f35ec8013d37b958e65f07de015c0574e64198d73aab5466f3a971b74830b7f1671cb9277fbc95c1ba8c29dc903d8cea1b74c22ab9164f9c438ab9ba7d9919f832e40c3e36faca7343e2314669b0104d9c4f2e1b011cdbd9c686baef0
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 3cc4b644965b2133caffc2bb6258b1ecd5b586b900a09b010382fcef709e4cd37ee3e3182bf8d393c1ab6f9a933d46338b3d960923d8c9607c2b2763d5680230a2bc0c91138e9d0ecb35e7154a06aaa902d34b9b14964b81f4d8232641492d83b22cd805a115e75ddd8e63b864c00e4c90ba36a41e7966e97e063a60a6a6cfd53e1f62a57852c7443e88dcf6245557a4b65494c3e88e466ad75316aaa9727def
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 40c03b6ba22bd62c0379b1c36dfccd34d61e3d15f7af1d5f6a60ab972a9d0e956e2bb9e275294e0f1c879eb7a4555443429c99a8d74f7bd359a1046ac30072c04b0e2cbd005be15ff4ce0c93276de2c513fbc5771b5059904a87f180530f6773498114b5aaf70da01967d8294742e451df6377dd5e64b2a8968f4ba61b51a154317d63958ff3788defbeeebee21af5027c2291e8c5df8c0b66770d91b683cffe
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 3c7c71b84f0c6c3817f57511946315cec7d0120a9c30ceabda801fbaec329a8f10c7b9f0ae90a3dada9885bf73a3cabed86784af9682f3dea50a7817f65cfc9190cf997f12784223c4965ed6e52a1be26d4dde31741cd3d1a2e2f3a74040d0f3868eef849727aa855f66c94791194ad5d360298364e2de9ca9288e6423f644b01d52e1bd66a9f7f00bd7995a9ca2ed16f40e902852c6250a3b52bbbf5bfd33e8
|
||||
|
||||
# b^m = w-1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 36e6aa9acb399a50f52be0324dcef05f3cff3117f94538f6d0952b7d7be88ba4dc75d843ff7ff775e11f55c86ba6b2a6ddebd8850c33424b4d35c66321af426662e7074f0a2409a9ccf1c66ef7d823efc8240b8f3c7e9e8dd65a64e8a3ca5b26695ef17171ffe136c0593b179414c5b5ad0d66f2a25146c38b2f97e60b0472ed72de34bff1b6ac186f23645a1bbe909cdfc2b2d861eb44931568f1bb117d8a0c
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 278f2215d3ab836043fbfa472216bbdcedb775a6a0ed711754d05aa75089a9e5d8201e113d68656f37381e44483cd365f5d383bdca5ae8d1f2e6575d7873851cfff0e12b1cfe100a04cb300cbd924353fcbd3307d01242cf6a5e86e752c6f4586bcabf48b018bb97e65c3ed409fd6f67f98987517356d88344b3c8945ccd753148a37b648dd2db44d19522a69a9ad8eb23edc55340e85a198abf179ad731db41
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = afa1478bebbfe1157568f4ae53549b4c3a6a8771b816970bfac6ce5c8b962231db7a41da4d5f1d8bf504dcfe440325b54e1888bdae344eb969436a35e5c6ce5300d46313cb2fcb57fc83305f65f53d392de400e9231cbbc2ac8243defcaf7063c632b9601a81d83138274702ff336d727d3e82ccacce069843ac9c1c590c772c8c586b65c7085a1df5a47fc960d4098a22418b41f0062c77b5d55d17149d167
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 10f7030590b629e0313a61bdf46936a1f25db91b2b421f7ebb671f7844c22561b44b2f7699db61e5228ebb5817afad416325f9439eff7a82d8a630c504de12eaa44d97c79ee56e726ae74ee0b472f0d5fa8f20aee426e689cd33dd084f96bf4d928a21e815f7e8aaca4a5752f39c4a76bdfaa8227dc05d0dfa885d8b26d46fbcbf0d2e0d999d2c31ad84c306c9126539dbdf447f8dc707d29c7fa8021a767668
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 97dbb6a55c039ec926aaa5ff15a2917a2b4cafc3ca07c4c6b05f931d86c9bf60ee05cbbace194e5ca97682ec67c36394018d68c3536fbf13b50f8a7e31eaed87307759a0a48c6c58d21bc7c38b878c53db5d7a8e1fdd81abefc50470a3800852e74d76fdd1933e45f39ee97b8efb68837721890d867b32a894dd0ceb4c5844a05d384145865c10973ce748ccdd8fee73f1bf8611ce0535430b6b98fb36cad7a
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 225f58add44ed2b0a64a1d8452866d0f3c0cd45c8375e1bb33c188915c77fa11b81250b920245dda7f6126e5e0c79e6f98f89dc15db86394cf81b44f0d801e613fa4d5c6fef66fa31f26cfe6153f2e8159aad6b0351dcc0e93f9a68f649b2a77cff747b605b542d22419166befebec6cde3201e3c0cacaa2bc9d87073b8d1f1aa2b114d61de45ac8b0ad2141b43434a629ef284cd999fd82b310db7c57cf5c81
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 2780926c9cf7c1eb2aaa935d90b6d4dea44eeefdfcf9ccd4a33feb215e3a1cb2d358136a490fed18403947f3d98807819737c66e12d42c3cc8c0e246b96b3c3b0795ab875fbaf668b81b5b05bf23e258ea00a0a140a790f76e04ab619800b7597f614ffc1a1c94be2f3f1a71d64eb47d98e4653d76eabedacff3a97ecf590e6a1fd55096b7bc9314629f698d0fbe9b01a1f2bc0bf3a2c097f99f1fd222b52ed2
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 129cc5b0d9f8001b3895f1fcb4833779763636aeeeb3f980e63ea506202e6bde868444b6a58ff1dca08625f025a7e95a5eaaf1a8899eee640e3f05fbdb2867e2483bdc27c87b58684416e521c107f3667ed8dd23f0381edab767c5205a4378118bc011947cb6bdfe3fa4af50b8de876b555c9a0b2b0dae01261847f63e1e0cac2d032530bf19d5da60a04dfe22ce6343f60defbb94ccf0bdf010f89a4029720
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 4e2a47cf67c3331b1e9976f583f6339cf76a8d48682d01355c25b2aed90c5544e737ecfa849c17d27a64fad7e659ef48df9a3ac0410e5c7ca8d087fc3a3ba23e5a3f000be009fcc8227ead28158c5b5d66f2efb47111638ef61cea4984de42fbd476bc2236ad02154d3ce85805c45e49d16b496e313a4052a37d4b88a3b13e598d2074a3e36a37e90278601f2b2305e034f9bf3aea8e939c3ba274e8ff4d8a14
|
||||
|
||||
# b^m = 1
|
||||
Result = PossiblyPrime
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 2455c4ab826e2ae72708a8ff51348ce4821cb86fa89e298c751c1754211c63b2e9a712d40f0235f310606fcf296726a86973f19f890d571f5b90f026e8d24d07bc0478a3c1333171587387f1f7fe4a770b593216f2743318aabacb3320c40a4e52b9f409e1176fe8db099e93a7991eb8568168e2e486fa5aa228bb1dce9df3290ef13fd21c331479bb0f8b7a7e7f03c5211ae8cc46fa4d0f46e86b2dadeddd5b
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 9951c2c02dd7deedce29bd0c78dd80066b1d69c0e6fe4a17f7d03c6a640d866d01fc8214bafb6737efd93d80a35b8993f5367ce287459b07954e9771ffbc72ccdd812d26a9bf4be0292a24eb5c3b56f09619b1c1b481f7566f7e50e65f69f5feb591bd107fec72a783429dbde6e2607f3db2c58d4b070a45b4d6b43537e19942ce890b04ae1e91069c04a96ed03ddb2f4fc456f136b98102c70a15700dbd911
|
||||
|
||||
# End of iteration
|
||||
Result = Composite
|
||||
W = 550fda19f97cdfbd13930911ef6e9e1cb2b7b5215a35c215d51ebffeb435642174cbe998f4451bde2d4bd2ce92ab5b9493b657f1d77d9ad4d348550247b903906109c608ecba7f88c239c76f0afc231e7f1ac1cee87b4c34448a16f7979ff4c18e65e05d5a86909615fe56587576962a2cb3ba467d9806445a0f039907601af77ba7d07578eff612364fbcac11d35e243734aa6d9a6cdcf912a2dd0a12ba7e87
|
||||
B = 4cb8217d229d5f95f6d94807a99363823655d6bba6bdafa4f0dbfe7a5c538aa79c918710aad4f55caaee5ab405ebdcef29dfb76cae99fca8d5a955b6315f71a3cb2d69a217ff45aed66ba87cdc5c0de5d512c6dd12e641e9fe6a2557dd2f03bf3a18650ff139efa179f0fbe69cbb4b54e50d13177bfe7bb90de36b548d5ccfef74b05d3c08a7e2a3bb4dc8d7eb338a7a1b068c433ea204d171eda5e7c6b6722c
|
||||
@@ -455,18 +455,18 @@ void bn_to_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
bn_mod_mul_montgomery_small(r, a, mont->RR.d, num, mont);
|
||||
}
|
||||
|
||||
void bn_from_montgomery_small(BN_ULONG *r, size_t num_r, const BN_ULONG *a,
|
||||
size_t num_a, const BN_MONT_CTX *mont) {
|
||||
if (num_r != (size_t)mont->N.width || num_r > BN_SMALL_MAX_WORDS ||
|
||||
num_a > 2 * num_r) {
|
||||
void bn_from_montgomery_small(BN_ULONG *r, const BN_ULONG *a, size_t num,
|
||||
const BN_MONT_CTX *mont) {
|
||||
if (num != (size_t)mont->N.width || num > BN_SMALL_MAX_WORDS) {
|
||||
abort();
|
||||
}
|
||||
BN_ULONG tmp[BN_SMALL_MAX_WORDS * 2] = {0};
|
||||
OPENSSL_memcpy(tmp, a, num_a * sizeof(BN_ULONG));
|
||||
if (!bn_from_montgomery_in_place(r, num_r, tmp, 2 * num_r, mont)) {
|
||||
BN_ULONG tmp[BN_SMALL_MAX_WORDS * 2];
|
||||
OPENSSL_memcpy(tmp, a, num * sizeof(BN_ULONG));
|
||||
OPENSSL_memset(tmp + num, 0, num * sizeof(BN_ULONG));
|
||||
if (!bn_from_montgomery_in_place(r, num, tmp, 2 * num, mont)) {
|
||||
abort();
|
||||
}
|
||||
OPENSSL_cleanse(tmp, 2 * num_r * sizeof(BN_ULONG));
|
||||
OPENSSL_cleanse(tmp, 2 * num * sizeof(BN_ULONG));
|
||||
}
|
||||
|
||||
void bn_mod_mul_montgomery_small(BN_ULONG *r, const BN_ULONG *a,
|
||||
|
||||
+154
-30
@@ -119,20 +119,26 @@ static void bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, size_t na,
|
||||
}
|
||||
}
|
||||
|
||||
// bn_sub_part_words sets |r| to |a| - |b|. It returns the borrow bit, which is
|
||||
// one if the operation underflowed and zero otherwise. |cl| is the common
|
||||
// length, that is, the shorter of len(a) or len(b). |dl| is the delta length,
|
||||
// that is, len(a) - len(b). |r|'s length matches the larger of |a| and |b|, or
|
||||
// cl + abs(dl).
|
||||
//
|
||||
// TODO(davidben): Make this take |size_t|. The |cl| + |dl| calling convention
|
||||
// is confusing.
|
||||
#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
|
||||
// Here follows specialised variants of bn_add_words() and bn_sub_words(). They
|
||||
// have the property performing operations on arrays of different sizes. The
|
||||
// sizes of those arrays is expressed through cl, which is the common length (
|
||||
// basicall, min(len(a),len(b)) ), and dl, which is the delta between the two
|
||||
// lengths, calculated as len(a)-len(b). All lengths are the number of
|
||||
// BN_ULONGs... For the operations that require a result array as parameter,
|
||||
// it must have the length cl+abs(dl). These functions should probably end up
|
||||
// in bn_asm.c as soon as there are assembler counterparts for the systems that
|
||||
// use assembler files.
|
||||
|
||||
static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
|
||||
const BN_ULONG *b, int cl, int dl) {
|
||||
BN_ULONG c, t;
|
||||
|
||||
assert(cl >= 0);
|
||||
BN_ULONG borrow = bn_sub_words(r, a, b, cl);
|
||||
c = bn_sub_words(r, a, b, cl);
|
||||
|
||||
if (dl == 0) {
|
||||
return borrow;
|
||||
return c;
|
||||
}
|
||||
|
||||
r += cl;
|
||||
@@ -140,26 +146,147 @@ static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
|
||||
b += cl;
|
||||
|
||||
if (dl < 0) {
|
||||
// |a| is shorter than |b|. Complete the subtraction as if the excess words
|
||||
// in |a| were zeros.
|
||||
dl = -dl;
|
||||
for (int i = 0; i < dl; i++) {
|
||||
r[i] = 0u - b[i] - borrow;
|
||||
borrow |= r[i] != 0;
|
||||
for (;;) {
|
||||
t = b[0];
|
||||
r[0] = 0 - t - c;
|
||||
if (t != 0) {
|
||||
c = 1;
|
||||
}
|
||||
if (++dl >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t = b[1];
|
||||
r[1] = 0 - t - c;
|
||||
if (t != 0) {
|
||||
c = 1;
|
||||
}
|
||||
if (++dl >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t = b[2];
|
||||
r[2] = 0 - t - c;
|
||||
if (t != 0) {
|
||||
c = 1;
|
||||
}
|
||||
if (++dl >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t = b[3];
|
||||
r[3] = 0 - t - c;
|
||||
if (t != 0) {
|
||||
c = 1;
|
||||
}
|
||||
if (++dl >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
} else {
|
||||
// |b| is shorter than |a|. Complete the subtraction as if the excess words
|
||||
// in |b| were zeros.
|
||||
for (int i = 0; i < dl; i++) {
|
||||
// |r| and |a| may alias, so use a temporary.
|
||||
BN_ULONG tmp = a[i];
|
||||
r[i] = a[i] - borrow;
|
||||
borrow = tmp < r[i];
|
||||
int save_dl = dl;
|
||||
while (c) {
|
||||
t = a[0];
|
||||
r[0] = t - c;
|
||||
if (t != 0) {
|
||||
c = 0;
|
||||
}
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t = a[1];
|
||||
r[1] = t - c;
|
||||
if (t != 0) {
|
||||
c = 0;
|
||||
}
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t = a[2];
|
||||
r[2] = t - c;
|
||||
if (t != 0) {
|
||||
c = 0;
|
||||
}
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t = a[3];
|
||||
r[3] = t - c;
|
||||
if (t != 0) {
|
||||
c = 0;
|
||||
}
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
save_dl = dl;
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
if (dl > 0) {
|
||||
if (save_dl > dl) {
|
||||
switch (save_dl - dl) {
|
||||
case 1:
|
||||
r[1] = a[1];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
OPENSSL_FALLTHROUGH;
|
||||
case 2:
|
||||
r[2] = a[2];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
OPENSSL_FALLTHROUGH;
|
||||
case 3:
|
||||
r[3] = a[3];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (dl > 0) {
|
||||
for (;;) {
|
||||
r[0] = a[0];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
r[1] = a[1];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
r[2] = a[2];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
r[3] = a[3];
|
||||
if (--dl <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
a += 4;
|
||||
r += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return borrow;
|
||||
return c;
|
||||
}
|
||||
#else
|
||||
// On other platforms the function is defined in asm.
|
||||
BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int cl, int dl);
|
||||
#endif
|
||||
|
||||
// bn_abs_sub_part_words computes |r| = |a| - |b|, storing the absolute value
|
||||
// and returning a mask of all ones if the result was negative and all zeros if
|
||||
@@ -167,7 +294,8 @@ static BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
|
||||
// convention.
|
||||
//
|
||||
// TODO(davidben): Make this take |size_t|. The |cl| + |dl| calling convention
|
||||
// is confusing.
|
||||
// is confusing. The trouble is 32-bit x86 implements |bn_sub_part_words| in
|
||||
// assembly, but we can probably just delete it?
|
||||
static BN_ULONG bn_abs_sub_part_words(BN_ULONG *r, const BN_ULONG *a,
|
||||
const BN_ULONG *b, int cl, int dl,
|
||||
BN_ULONG *tmp) {
|
||||
@@ -455,7 +583,7 @@ static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
static const int kMulNormalSize = 16;
|
||||
if (al >= kMulNormalSize && bl >= kMulNormalSize) {
|
||||
if (-1 <= i && i <= 1) {
|
||||
// Find the largest power of two less than or equal to the larger length.
|
||||
// Find the larger power of two less than or equal to the larger length.
|
||||
int j;
|
||||
if (i >= 0) {
|
||||
j = BN_num_bits_word((BN_ULONG)al);
|
||||
@@ -471,10 +599,6 @@ static int bn_mul_impl(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
if (al > j || bl > j) {
|
||||
// We know |al| and |bl| are at most one from each other, so if al > j,
|
||||
// bl >= j, and vice versa. Thus we can use |bn_mul_part_recursive|.
|
||||
//
|
||||
// TODO(davidben): This codepath is almost unused in standard
|
||||
// algorithms. Is this optimization necessary? See notes in
|
||||
// https://boringssl-review.googlesource.com/q/I0bd604e2cd6a75c266f64476c23a730ca1721ea6
|
||||
assert(al >= j && bl >= j);
|
||||
if (!bn_wexpand(t, j * 8) ||
|
||||
!bn_wexpand(rr, j * 4)) {
|
||||
|
||||
+360
-273
@@ -119,98 +119,199 @@
|
||||
// Zimmermann's, as implemented in PGP. I have had a read of his comments and
|
||||
// implemented my own version.
|
||||
|
||||
// kPrimes contains the first 1024 primes.
|
||||
// kPrimes contains the first 2048 primes.
|
||||
static const uint16_t kPrimes[] = {
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
|
||||
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
|
||||
97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
|
||||
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
|
||||
227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
||||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
|
||||
367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433,
|
||||
439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
|
||||
509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,
|
||||
599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
|
||||
751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
|
||||
829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
|
||||
919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
|
||||
1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
|
||||
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
|
||||
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249,
|
||||
1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
|
||||
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439,
|
||||
1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
|
||||
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
|
||||
1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
|
||||
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783,
|
||||
1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
|
||||
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
|
||||
1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
|
||||
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143,
|
||||
2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
|
||||
2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347,
|
||||
2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
|
||||
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543,
|
||||
2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
|
||||
2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713,
|
||||
2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
|
||||
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
|
||||
2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
|
||||
3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119,
|
||||
3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
|
||||
3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323,
|
||||
3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
|
||||
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527,
|
||||
3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
|
||||
3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697,
|
||||
3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
|
||||
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
|
||||
3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
|
||||
4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093,
|
||||
4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
|
||||
4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283,
|
||||
4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
|
||||
4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513,
|
||||
4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
|
||||
4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721,
|
||||
4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
|
||||
4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
|
||||
4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
|
||||
5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113,
|
||||
5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
|
||||
5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
|
||||
5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
|
||||
5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531,
|
||||
5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
|
||||
5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
|
||||
5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
|
||||
5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
|
||||
5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
|
||||
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173,
|
||||
6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
|
||||
6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359,
|
||||
6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
|
||||
6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581,
|
||||
6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
|
||||
6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803,
|
||||
6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
|
||||
6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
|
||||
7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
|
||||
7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
|
||||
7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
|
||||
7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487,
|
||||
7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
|
||||
7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669,
|
||||
7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
|
||||
7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879,
|
||||
7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
|
||||
8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
|
||||
8117, 8123, 8147, 8161,
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
|
||||
37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
|
||||
83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
|
||||
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
|
||||
197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257,
|
||||
263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
|
||||
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
|
||||
397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457,
|
||||
461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
|
||||
541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
||||
607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
|
||||
673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
|
||||
751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823,
|
||||
827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,
|
||||
907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977,
|
||||
983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
|
||||
1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117,
|
||||
1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
|
||||
1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289,
|
||||
1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
|
||||
1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
|
||||
1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531,
|
||||
1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607,
|
||||
1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
|
||||
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777,
|
||||
1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
|
||||
1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951,
|
||||
1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029,
|
||||
2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113,
|
||||
2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
|
||||
2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293,
|
||||
2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
|
||||
2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447,
|
||||
2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
|
||||
2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659,
|
||||
2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713,
|
||||
2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
|
||||
2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887,
|
||||
2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971,
|
||||
2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
|
||||
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187,
|
||||
3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
|
||||
3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359,
|
||||
3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461,
|
||||
3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
|
||||
3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617,
|
||||
3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701,
|
||||
3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
|
||||
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889,
|
||||
3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
|
||||
4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073,
|
||||
4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157,
|
||||
4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253,
|
||||
4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349,
|
||||
4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451,
|
||||
4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
|
||||
4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643,
|
||||
4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
|
||||
4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817,
|
||||
4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
|
||||
4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009,
|
||||
5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
|
||||
5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209,
|
||||
5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
|
||||
5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417,
|
||||
5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501,
|
||||
5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581,
|
||||
5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683,
|
||||
5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783,
|
||||
5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
|
||||
5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953,
|
||||
5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
|
||||
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163,
|
||||
6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263,
|
||||
6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337,
|
||||
6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427,
|
||||
6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553,
|
||||
6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659,
|
||||
6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737,
|
||||
6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
|
||||
6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947,
|
||||
6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013,
|
||||
7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127,
|
||||
7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
|
||||
7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333,
|
||||
7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477,
|
||||
7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547,
|
||||
7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621,
|
||||
7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717,
|
||||
7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
|
||||
7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927,
|
||||
7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053,
|
||||
8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147,
|
||||
8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237,
|
||||
8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329,
|
||||
8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443,
|
||||
8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563,
|
||||
8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663,
|
||||
8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737,
|
||||
8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
|
||||
8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933,
|
||||
8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029,
|
||||
9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137,
|
||||
9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227,
|
||||
9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337,
|
||||
9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421,
|
||||
9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497,
|
||||
9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623,
|
||||
9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721,
|
||||
9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
|
||||
9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901,
|
||||
9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037,
|
||||
10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133,
|
||||
10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223,
|
||||
10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313,
|
||||
10321, 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429,
|
||||
10433, 10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529,
|
||||
10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639,
|
||||
10651, 10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733,
|
||||
10739, 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
|
||||
10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957,
|
||||
10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071,
|
||||
11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171,
|
||||
11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279,
|
||||
11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393,
|
||||
11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491,
|
||||
11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617,
|
||||
11621, 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731,
|
||||
11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831,
|
||||
11833, 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,
|
||||
11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037,
|
||||
12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119,
|
||||
12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241,
|
||||
12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343,
|
||||
12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437,
|
||||
12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527,
|
||||
12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613,
|
||||
12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713,
|
||||
12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823,
|
||||
12829, 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,
|
||||
12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009,
|
||||
13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127,
|
||||
13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229,
|
||||
13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337,
|
||||
13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457,
|
||||
13463, 13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577,
|
||||
13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687,
|
||||
13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759,
|
||||
13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877,
|
||||
13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,
|
||||
13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083,
|
||||
14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221,
|
||||
14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347,
|
||||
14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447,
|
||||
14449, 14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551,
|
||||
14557, 14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653,
|
||||
14657, 14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747,
|
||||
14753, 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831,
|
||||
14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939,
|
||||
14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
|
||||
15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161,
|
||||
15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269,
|
||||
15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349,
|
||||
15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443,
|
||||
15451, 15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559,
|
||||
15569, 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649,
|
||||
15661, 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749,
|
||||
15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859,
|
||||
15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959,
|
||||
15971, 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,
|
||||
16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187,
|
||||
16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301,
|
||||
16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421,
|
||||
16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529,
|
||||
16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649,
|
||||
16651, 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747,
|
||||
16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883,
|
||||
16889, 16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981,
|
||||
16987, 16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077,
|
||||
17093, 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
|
||||
17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321,
|
||||
17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401,
|
||||
17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491,
|
||||
17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599,
|
||||
17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729,
|
||||
17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839,
|
||||
17851, 17863,
|
||||
};
|
||||
|
||||
// BN_prime_checks_for_size returns the number of Miller-Rabin iterations
|
||||
// necessary for generating a 'bits'-bit candidate prime.
|
||||
// necessary for a 'bits'-bit prime.
|
||||
//
|
||||
//
|
||||
// This table is generated using the algorithm of FIPS PUB 186-4
|
||||
@@ -293,7 +394,7 @@ static size_t num_trial_division_primes(const BIGNUM *n) {
|
||||
if (n->width * BN_BITS2 > 1024) {
|
||||
return OPENSSL_ARRAY_SIZE(kPrimes);
|
||||
}
|
||||
return OPENSSL_ARRAY_SIZE(kPrimes) / 2;
|
||||
return OPENSSL_ARRAY_SIZE(kPrimes) / 4;
|
||||
}
|
||||
|
||||
// BN_PRIME_CHECKS_BLINDED is the iteration count for blinding the constant-time
|
||||
@@ -443,11 +544,6 @@ loop:
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Interleave |ret| and |t|'s primality tests to avoid paying the full
|
||||
// iteration count on |ret| only to quickly discover |t| is composite.
|
||||
//
|
||||
// TODO(davidben): This doesn't quite work because an iteration count of 1
|
||||
// still runs the blinding mechanism.
|
||||
for (i = 0; i < checks; i++) {
|
||||
j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, NULL);
|
||||
if (j == -1) {
|
||||
@@ -463,7 +559,7 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i)) {
|
||||
if (!BN_GENCB_call(cb, i, c1 - 1)) {
|
||||
goto err;
|
||||
}
|
||||
// We have a safe prime test pass
|
||||
@@ -498,158 +594,15 @@ int bn_odd_number_is_obviously_composite(const BIGNUM *bn) {
|
||||
return bn_trial_division(&prime, bn) && !BN_is_word(bn, prime);
|
||||
}
|
||||
|
||||
int bn_miller_rabin_init(BN_MILLER_RABIN *miller_rabin, const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
// This function corresponds to steps 1 through 3 of FIPS 186-4, C.3.1.
|
||||
const BIGNUM *w = &mont->N;
|
||||
// Note we do not call |BN_CTX_start| in this function. We intentionally
|
||||
// allocate values in the containing scope so they outlive this function.
|
||||
miller_rabin->w1 = BN_CTX_get(ctx);
|
||||
miller_rabin->m = BN_CTX_get(ctx);
|
||||
miller_rabin->one_mont = BN_CTX_get(ctx);
|
||||
miller_rabin->w1_mont = BN_CTX_get(ctx);
|
||||
if (miller_rabin->w1 == NULL ||
|
||||
miller_rabin->m == NULL ||
|
||||
miller_rabin->one_mont == NULL ||
|
||||
miller_rabin->w1_mont == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// See FIPS 186-4, C.3.1, steps 1 through 3.
|
||||
if (!bn_usub_consttime(miller_rabin->w1, w, BN_value_one())) {
|
||||
return 0;
|
||||
}
|
||||
miller_rabin->a = BN_count_low_zero_bits(miller_rabin->w1);
|
||||
if (!bn_rshift_secret_shift(miller_rabin->m, miller_rabin->w1,
|
||||
miller_rabin->a, ctx)) {
|
||||
return 0;
|
||||
}
|
||||
miller_rabin->w_bits = BN_num_bits(w);
|
||||
|
||||
// Precompute some values in Montgomery form.
|
||||
if (!bn_one_to_montgomery(miller_rabin->one_mont, mont, ctx) ||
|
||||
// w - 1 is -1 mod w, so we can compute it in the Montgomery domain, -R,
|
||||
// with a subtraction. (|one_mont| cannot be zero.)
|
||||
!bn_usub_consttime(miller_rabin->w1_mont, w, miller_rabin->one_mont)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bn_miller_rabin_iteration(const BN_MILLER_RABIN *miller_rabin,
|
||||
int *out_is_possibly_prime, const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont, BN_CTX *ctx) {
|
||||
// This function corresponds to steps 4.3 through 4.5 of FIPS 186-4, C.3.1.
|
||||
int ret = 0;
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
// Step 4.3. We use Montgomery-encoding for better performance and to avoid
|
||||
// timing leaks.
|
||||
const BIGNUM *w = &mont->N;
|
||||
BIGNUM *z = BN_CTX_get(ctx);
|
||||
if (z == NULL ||
|
||||
!BN_mod_exp_mont_consttime(z, b, miller_rabin->m, w, ctx, mont) ||
|
||||
!BN_to_montgomery(z, z, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// is_possibly_prime is all ones if we have determined |b| is not a composite
|
||||
// witness for |w|. This is equivalent to going to step 4.7 in the original
|
||||
// algorithm. To avoid timing leaks, we run the algorithm to the end for prime
|
||||
// inputs.
|
||||
crypto_word_t is_possibly_prime = 0;
|
||||
|
||||
// Step 4.4. If z = 1 or z = w-1, b is not a composite witness and w is still
|
||||
// possibly prime.
|
||||
is_possibly_prime = BN_equal_consttime(z, miller_rabin->one_mont) |
|
||||
BN_equal_consttime(z, miller_rabin->w1_mont);
|
||||
is_possibly_prime = 0 - is_possibly_prime; // Make it all zeros or all ones.
|
||||
|
||||
// Step 4.5.
|
||||
//
|
||||
// To avoid leaking |a|, we run the loop to |w_bits| and mask off all
|
||||
// iterations once |j| = |a|.
|
||||
for (int j = 1; j < miller_rabin->w_bits; j++) {
|
||||
if (constant_time_eq_int(j, miller_rabin->a) & ~is_possibly_prime) {
|
||||
// If the loop is done and we haven't seen z = 1 or z = w-1 yet, the
|
||||
// value is composite and we can break in variable time.
|
||||
break;
|
||||
}
|
||||
|
||||
// Step 4.5.1.
|
||||
if (!BN_mod_mul_montgomery(z, z, z, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Step 4.5.2. If z = w-1 and the loop is not done, this is not a composite
|
||||
// witness.
|
||||
crypto_word_t z_is_w1_mont = BN_equal_consttime(z, miller_rabin->w1_mont);
|
||||
z_is_w1_mont = 0 - z_is_w1_mont; // Make it all zeros or all ones.
|
||||
is_possibly_prime |= z_is_w1_mont; // Go to step 4.7 if |z_is_w1_mont|.
|
||||
|
||||
// Step 4.5.3. If z = 1 and the loop is not done, the previous value of z
|
||||
// was not -1. There are no non-trivial square roots of 1 modulo a prime, so
|
||||
// w is composite and we may exit in variable time.
|
||||
if (BN_equal_consttime(z, miller_rabin->one_mont) & ~is_possibly_prime) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*out_is_possibly_prime = is_possibly_prime & 1;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w, int checks,
|
||||
BN_CTX *ctx, int do_trial_division, BN_GENCB *cb) {
|
||||
// This function's secrecy and performance requirements come from RSA key
|
||||
// generation. We generate RSA keys by selecting two large, secret primes with
|
||||
// rejection sampling.
|
||||
//
|
||||
// We thus treat |w| as secret if turns out to be a large prime. However, if
|
||||
// |w| is composite, we treat this and |w| itself as public. (Conversely, if
|
||||
// |w| is prime, that it is prime is public. Only the value is secret.) This
|
||||
// is fine for RSA key generation, but note it is important that we use
|
||||
// rejection sampling, with each candidate prime chosen independently. This
|
||||
// would not work for, e.g., an algorithm which looked for primes in
|
||||
// consecutive integers. These assumptions allow us to discard composites
|
||||
// quickly. We additionally treat |w| as public when it is a small prime to
|
||||
// simplify trial decryption and some edge cases.
|
||||
//
|
||||
// One RSA key generation will call this function on exactly two primes and
|
||||
// many more composites. The overall cost is a combination of several factors:
|
||||
//
|
||||
// 1. Checking if |w| is divisible by a small prime is much faster than
|
||||
// learning it is composite by Miller-Rabin (see below for details on that
|
||||
// cost). Trial division by p saves 1/p of Miller-Rabin calls, so this is
|
||||
// worthwhile until p exceeds the ratio of the two costs.
|
||||
//
|
||||
// 2. For a random (i.e. non-adversarial) candidate large prime and candidate
|
||||
// witness, the probability of false witness is very low. (This is why FIPS
|
||||
// 186-4 only requires a few iterations.) Thus composites not discarded by
|
||||
// trial decryption, in practice, cost one Miller-Rabin iteration. Only the
|
||||
// two actual primes cost the full iteration count.
|
||||
//
|
||||
// 3. A Miller-Rabin iteration is a modular exponentiation plus |a| additional
|
||||
// modular squares, where |a| is the number of factors of two in |w-1|. |a|
|
||||
// is likely small (the distribution falls exponentially), but it is also
|
||||
// potentially secret, so we loop up to its log(w) upper bound when |w| is
|
||||
// prime. When |w| is composite, we break early, so only two calls pay this
|
||||
// cost. (Note that all calls pay the modular exponentiation which is,
|
||||
// itself, log(w) modular multiplications and squares.)
|
||||
//
|
||||
// 4. While there are only two prime calls, they multiplicatively pay the full
|
||||
// costs of (2) and (3).
|
||||
//
|
||||
// 5. After the primes are chosen, RSA keys derive some values from the
|
||||
// primes, but this cost is negligible in comparison.
|
||||
|
||||
int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w,
|
||||
int iterations, BN_CTX *ctx, int do_trial_division,
|
||||
BN_GENCB *cb) {
|
||||
*out_is_probably_prime = 0;
|
||||
|
||||
// To support RSA key generation, this function should treat |w| as secret if
|
||||
// it is a large prime. Composite numbers are discarded, so they may return
|
||||
// early.
|
||||
|
||||
if (BN_cmp(w, BN_value_one()) <= 0) {
|
||||
return 1;
|
||||
}
|
||||
@@ -673,13 +626,13 @@ int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w, int checks,
|
||||
*out_is_probably_prime = BN_is_word(w, prime);
|
||||
return 1;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, -1)) {
|
||||
if (!BN_GENCB_call(cb, 1, -1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (checks == BN_prime_checks_for_generation) {
|
||||
checks = BN_prime_checks_for_size(BN_num_bits(w));
|
||||
if (iterations == BN_prime_checks) {
|
||||
iterations = BN_prime_checks_for_size(BN_num_bits(w));
|
||||
}
|
||||
|
||||
BN_CTX *new_ctx = NULL;
|
||||
@@ -693,13 +646,36 @@ int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w, int checks,
|
||||
|
||||
// See C.3.1 from FIPS 186-4.
|
||||
int ret = 0;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
BN_CTX_start(ctx);
|
||||
BIGNUM *w1 = BN_CTX_get(ctx);
|
||||
if (w1 == NULL ||
|
||||
!bn_usub_consttime(w1, w, BN_value_one())) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Write w1 as m * 2^a (Steps 1 and 2).
|
||||
int w_len = BN_num_bits(w);
|
||||
int a = BN_count_low_zero_bits(w1);
|
||||
BIGNUM *m = BN_CTX_get(ctx);
|
||||
if (m == NULL ||
|
||||
!bn_rshift_secret_shift(m, w1, a, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Montgomery setup for computations mod w. Additionally, compute 1 and w - 1
|
||||
// in the Montgomery domain for later comparisons.
|
||||
BIGNUM *b = BN_CTX_get(ctx);
|
||||
BN_MONT_CTX *mont = BN_MONT_CTX_new_consttime(w, ctx);
|
||||
BN_MILLER_RABIN miller_rabin;
|
||||
if (b == NULL || mont == NULL ||
|
||||
// Steps 1-3.
|
||||
!bn_miller_rabin_init(&miller_rabin, mont, ctx)) {
|
||||
BIGNUM *z = BN_CTX_get(ctx);
|
||||
BIGNUM *one_mont = BN_CTX_get(ctx);
|
||||
BIGNUM *w1_mont = BN_CTX_get(ctx);
|
||||
mont = BN_MONT_CTX_new_consttime(w, ctx);
|
||||
if (b == NULL || z == NULL || one_mont == NULL || w1_mont == NULL ||
|
||||
mont == NULL ||
|
||||
!bn_one_to_montgomery(one_mont, mont, ctx) ||
|
||||
// w - 1 is -1 mod w, so we can compute it in the Montgomery domain, -R,
|
||||
// with a subtraction. (|one_mont| cannot be zero.)
|
||||
!bn_usub_consttime(w1_mont, w, one_mont)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -735,36 +711,78 @@ int BN_primality_test(int *out_is_probably_prime, const BIGNUM *w, int checks,
|
||||
// Using |constant_time_lt_w| seems to prevent the compiler from optimizing
|
||||
// this into two jumps.
|
||||
for (int i = 1; (i <= BN_PRIME_CHECKS_BLINDED) |
|
||||
constant_time_lt_w(uniform_iterations, checks);
|
||||
constant_time_lt_w(uniform_iterations, iterations);
|
||||
i++) {
|
||||
// Step 4.1-4.2
|
||||
int is_uniform;
|
||||
if (!bn_rand_secret_range(b, &is_uniform, 2, miller_rabin.w1)) {
|
||||
goto err;
|
||||
if (// Step 4.1-4.2
|
||||
!bn_rand_secret_range(b, &is_uniform, 2, w1) ||
|
||||
// Step 4.3
|
||||
!BN_mod_exp_mont_consttime(z, b, m, w, ctx, mont)) {
|
||||
goto err;
|
||||
}
|
||||
uniform_iterations += is_uniform;
|
||||
|
||||
// Steps 4.3-4.5
|
||||
int is_possibly_prime = 0;
|
||||
if (!bn_miller_rabin_iteration(&miller_rabin, &is_possibly_prime, b, mont,
|
||||
ctx)) {
|
||||
// loop_done is all ones if the loop has completed and all zeros otherwise.
|
||||
crypto_word_t loop_done = 0;
|
||||
// next_iteration is all ones if we should continue to the next iteration
|
||||
// (|b| is not a composite witness for |w|). This is equivalent to going to
|
||||
// step 4.7 in the original algorithm.
|
||||
crypto_word_t next_iteration = 0;
|
||||
|
||||
// Step 4.4. If z = 1 or z = w-1, mask off the loop and continue to the next
|
||||
// iteration (go to step 4.7).
|
||||
loop_done = BN_equal_consttime(z, BN_value_one()) |
|
||||
BN_equal_consttime(z, w1);
|
||||
loop_done = 0 - loop_done; // Make it all zeros or all ones.
|
||||
next_iteration = loop_done; // Go to step 4.7 if |loop_done|.
|
||||
|
||||
// Step 4.5. We use Montgomery-encoding for better performance and to avoid
|
||||
// timing leaks.
|
||||
if (!BN_to_montgomery(z, z, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!is_possibly_prime) {
|
||||
// To avoid leaking |a|, we run the loop to |w_len| and mask off all
|
||||
// iterations once |j| = |a|.
|
||||
for (int j = 1; j < w_len; j++) {
|
||||
loop_done |= constant_time_eq_int(j, a);
|
||||
|
||||
// Step 4.5.1.
|
||||
if (!BN_mod_mul_montgomery(z, z, z, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Step 4.5.2. If z = w-1 and the loop is not done, run through the next
|
||||
// iteration.
|
||||
crypto_word_t z_is_w1_mont = BN_equal_consttime(z, w1_mont) & ~loop_done;
|
||||
z_is_w1_mont = 0 - z_is_w1_mont; // Make it all zeros or all ones.
|
||||
loop_done |= z_is_w1_mont;
|
||||
next_iteration |= z_is_w1_mont; // Go to step 4.7 if |z_is_w1_mont|.
|
||||
|
||||
// Step 4.5.3. If z = 1 and the loop is not done, w is composite and we
|
||||
// may exit in variable time.
|
||||
if (BN_equal_consttime(z, one_mont) & ~loop_done) {
|
||||
assert(!next_iteration);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!next_iteration) {
|
||||
// Step 4.6. We did not see z = w-1 before z = 1, so w must be composite.
|
||||
// (For any prime, the value of z immediately preceding 1 must be -1.
|
||||
// There are no non-trivial square roots of 1 modulo a prime.)
|
||||
*out_is_probably_prime = 0;
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Step 4.7
|
||||
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i - 1)) {
|
||||
if (!BN_GENCB_call(cb, 1, i)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
assert(uniform_iterations >= (crypto_word_t)checks);
|
||||
assert(uniform_iterations >= (crypto_word_t)iterations);
|
||||
*out_is_probably_prime = 1;
|
||||
ret = 1;
|
||||
|
||||
@@ -791,7 +809,7 @@ int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx,
|
||||
}
|
||||
|
||||
int BN_enhanced_miller_rabin_primality_test(
|
||||
enum bn_primality_result_t *out_result, const BIGNUM *w, int checks,
|
||||
enum bn_primality_result_t *out_result, const BIGNUM *w, int iterations,
|
||||
BN_CTX *ctx, BN_GENCB *cb) {
|
||||
// Enhanced Miller-Rabin is only valid on odd integers greater than 3.
|
||||
if (!BN_is_odd(w) || BN_cmp_word(w, 3) <= 0) {
|
||||
@@ -799,8 +817,8 @@ int BN_enhanced_miller_rabin_primality_test(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (checks == BN_prime_checks_for_generation) {
|
||||
checks = BN_prime_checks_for_size(BN_num_bits(w));
|
||||
if (iterations == BN_prime_checks) {
|
||||
iterations = BN_prime_checks_for_size(BN_num_bits(w));
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
@@ -847,7 +865,7 @@ int BN_enhanced_miller_rabin_primality_test(
|
||||
|
||||
// The following loop performs in inner iteration of the Enhanced Miller-Rabin
|
||||
// Primality test (Step 4).
|
||||
for (int i = 1; i <= checks; i++) {
|
||||
for (int i = 1; i <= iterations; i++) {
|
||||
// Step 4.1-4.2
|
||||
if (!BN_rand_range_ex(b, 2, w1)) {
|
||||
goto err;
|
||||
@@ -914,7 +932,7 @@ int BN_enhanced_miller_rabin_primality_test(
|
||||
|
||||
loop:
|
||||
// Step 4.15
|
||||
if (!BN_GENCB_call(cb, BN_GENCB_PRIME_TEST, i - 1)) {
|
||||
if (!BN_GENCB_call(cb, 1, i)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -930,11 +948,80 @@ err:
|
||||
}
|
||||
|
||||
static int probable_prime(BIGNUM *rnd, int bits) {
|
||||
do {
|
||||
if (!BN_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) {
|
||||
return 0;
|
||||
uint16_t mods[OPENSSL_ARRAY_SIZE(kPrimes)];
|
||||
const size_t num_primes = num_trial_division_primes(rnd);
|
||||
BN_ULONG delta;
|
||||
BN_ULONG maxdelta = BN_MASK2 - kPrimes[num_primes - 1];
|
||||
char is_single_word = bits <= BN_BITS2;
|
||||
|
||||
again:
|
||||
if (!BN_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// we now have a random number 'rnd' to test.
|
||||
for (size_t i = 1; i < num_primes; i++) {
|
||||
mods[i] = bn_mod_u16_consttime(rnd, kPrimes[i]);
|
||||
}
|
||||
// If bits is so small that it fits into a single word then we
|
||||
// additionally don't want to exceed that many bits.
|
||||
if (is_single_word) {
|
||||
BN_ULONG size_limit;
|
||||
if (bits == BN_BITS2) {
|
||||
// Avoid undefined behavior.
|
||||
size_limit = ~((BN_ULONG)0) - BN_get_word(rnd);
|
||||
} else {
|
||||
size_limit = (((BN_ULONG)1) << bits) - BN_get_word(rnd) - 1;
|
||||
}
|
||||
} while (bn_odd_number_is_obviously_composite(rnd));
|
||||
if (size_limit < maxdelta) {
|
||||
maxdelta = size_limit;
|
||||
}
|
||||
}
|
||||
delta = 0;
|
||||
|
||||
loop:
|
||||
if (is_single_word) {
|
||||
BN_ULONG rnd_word = BN_get_word(rnd);
|
||||
|
||||
// In the case that the candidate prime is a single word then
|
||||
// we check that:
|
||||
// 1) It's greater than kPrimes[i] because we shouldn't reject
|
||||
// 3 as being a prime number because it's a multiple of
|
||||
// three.
|
||||
// 2) That it's not a multiple of a known prime. We don't
|
||||
// check that rnd-1 is also coprime to all the known
|
||||
// primes because there aren't many small primes where
|
||||
// that's true.
|
||||
for (size_t i = 1; i < num_primes && kPrimes[i] < rnd_word; i++) {
|
||||
if ((mods[i] + delta) % kPrimes[i] == 0) {
|
||||
delta += 2;
|
||||
if (delta > maxdelta) {
|
||||
goto again;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 1; i < num_primes; i++) {
|
||||
// check that rnd is not a prime and also
|
||||
// that gcd(rnd-1,primes) == 1 (except for 2)
|
||||
if (((mods[i] + delta) % kPrimes[i]) <= 1) {
|
||||
delta += 2;
|
||||
if (delta > maxdelta) {
|
||||
goto again;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!BN_add_word(rnd, delta)) {
|
||||
return 0;
|
||||
}
|
||||
if (BN_num_bits(rnd) != (unsigned)bits) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -173,9 +173,11 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
ret = aes_nohw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = aes_nohw_decrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
#if defined(AES_NOHW_CBC)
|
||||
if (mode == EVP_CIPH_CBC_MODE) {
|
||||
dat->stream.cbc = aes_nohw_cbc_encrypt;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (hwaes_capable()) {
|
||||
ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
@@ -207,9 +209,11 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
ret = aes_nohw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = aes_nohw_encrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
#if defined(AES_NOHW_CBC)
|
||||
if (mode == EVP_CIPH_CBC_MODE) {
|
||||
dat->stream.cbc = aes_nohw_cbc_encrypt;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
@@ -314,7 +318,7 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
|
||||
if (out_block) {
|
||||
*out_block = aes_nohw_encrypt;
|
||||
}
|
||||
return aes_nohw_ctr32_encrypt_blocks;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_32_BIT)
|
||||
@@ -1292,8 +1296,6 @@ int EVP_has_aes_hardware(void) {
|
||||
return hwaes_capable() && crypto_gcm_clmul_enabled();
|
||||
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
|
||||
return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable();
|
||||
#elif defined(OPENSSL_PPC64LE)
|
||||
return CRYPTO_is_PPC64LE_vcrypto_capable();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@@ -243,22 +243,6 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512) {
|
||||
}
|
||||
|
||||
|
||||
static void sha512_256_init(EVP_MD_CTX *ctx) {
|
||||
CHECK(SHA512_256_Init(ctx->md_data));
|
||||
}
|
||||
|
||||
DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) {
|
||||
out->type = NID_sha512_256;
|
||||
out->md_size = SHA512_256_DIGEST_LENGTH;
|
||||
out->flags = 0;
|
||||
out->init = sha512_256_init;
|
||||
out->update = sha512_update;
|
||||
out->final = sha512_final;
|
||||
out->block_size = 128;
|
||||
out->ctx_size = sizeof(SHA512_CTX);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
MD5_CTX md5;
|
||||
SHA_CTX sha1;
|
||||
|
||||
+118
-290
@@ -84,7 +84,7 @@
|
||||
static void ec_point_free(EC_POINT *point, int free_group);
|
||||
|
||||
static const uint8_t kP224Params[6 * 28] = {
|
||||
// p = 2^224 - 2^96 + 1
|
||||
// p
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
@@ -111,7 +111,7 @@ static const uint8_t kP224Params[6 * 28] = {
|
||||
};
|
||||
|
||||
static const uint8_t kP256Params[6 * 32] = {
|
||||
// p = 2^256 - 2^224 + 2^192 + 2^96 - 1
|
||||
// p
|
||||
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,
|
||||
@@ -138,7 +138,7 @@ static const uint8_t kP256Params[6 * 32] = {
|
||||
};
|
||||
|
||||
static const uint8_t kP384Params[6 * 48] = {
|
||||
// p = 2^384 - 2^128 - 2^96 + 2^32 - 1
|
||||
// p
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
@@ -171,7 +171,7 @@ static const uint8_t kP384Params[6 * 48] = {
|
||||
};
|
||||
|
||||
static const uint8_t kP521Params[6 * 66] = {
|
||||
// p = 2^521 - 1
|
||||
// p
|
||||
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
@@ -301,49 +301,17 @@ EC_GROUP *ec_group_new(const EC_METHOD *meth) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ec_group_set_generator(EC_GROUP *group, const EC_AFFINE *generator,
|
||||
const BIGNUM *order) {
|
||||
static void ec_group_set0_generator(EC_GROUP *group, EC_POINT *generator) {
|
||||
assert(group->generator == NULL);
|
||||
|
||||
if (!BN_copy(&group->order, order)) {
|
||||
return 0;
|
||||
}
|
||||
// Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
|
||||
bn_set_minimal_width(&group->order);
|
||||
|
||||
BN_MONT_CTX_free(group->order_mont);
|
||||
group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
|
||||
if (group->order_mont == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
group->field_greater_than_order = BN_cmp(&group->field, order) > 0;
|
||||
if (group->field_greater_than_order) {
|
||||
BIGNUM tmp;
|
||||
BN_init(&tmp);
|
||||
int ok =
|
||||
BN_sub(&tmp, &group->field, order) &&
|
||||
bn_copy_words(group->field_minus_order.words, group->field.width, &tmp);
|
||||
BN_free(&tmp);
|
||||
if (!ok) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
group->generator = EC_POINT_new(group);
|
||||
if (group->generator == NULL) {
|
||||
return 0;
|
||||
}
|
||||
ec_affine_to_jacobian(group, &group->generator->raw, generator);
|
||||
assert(ec_felem_equal(group, &group->one, &group->generator->raw.Z));
|
||||
assert(group == generator->group);
|
||||
|
||||
// Avoid a reference cycle. |group->generator| does not maintain an owning
|
||||
// pointer to |group|.
|
||||
group->generator = generator;
|
||||
int is_zero = CRYPTO_refcount_dec_and_test_zero(&group->references);
|
||||
|
||||
assert(!is_zero);
|
||||
(void)is_zero;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
|
||||
@@ -353,37 +321,20 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BN_CTX *new_ctx = NULL;
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
EC_GROUP *ret = ec_group_new(EC_GFp_mont_method());
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Historically, |a| and |b| were not required to be fully reduced.
|
||||
// TODO(davidben): Can this be removed?
|
||||
EC_GROUP *ret = NULL;
|
||||
BN_CTX_start(ctx);
|
||||
BIGNUM *a_reduced = BN_CTX_get(ctx);
|
||||
BIGNUM *b_reduced = BN_CTX_get(ctx);
|
||||
if (a_reduced == NULL || b_reduced == NULL ||
|
||||
!BN_nnmod(a_reduced, a, p, ctx) ||
|
||||
!BN_nnmod(b_reduced, b, p, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ec_group_new(EC_GFp_mont_method());
|
||||
if (ret == NULL ||
|
||||
!ret->meth->group_set_curve(ret, p, a_reduced, b_reduced, ctx)) {
|
||||
if (ret->meth->group_set_curve == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
EC_GROUP_free(ret);
|
||||
ret = NULL;
|
||||
goto err;
|
||||
return NULL;
|
||||
}
|
||||
if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
|
||||
EC_GROUP_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -416,6 +367,7 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
|
||||
// tiny prime (less than 17). See the proof in |field_element_to_scalar| in
|
||||
// the ECDSA implementation.
|
||||
int ret = 0;
|
||||
EC_POINT *copy = NULL;
|
||||
BIGNUM *tmp = BN_new();
|
||||
if (tmp == NULL ||
|
||||
!BN_lshift1(tmp, order)) {
|
||||
@@ -426,22 +378,44 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
|
||||
goto err;
|
||||
}
|
||||
|
||||
EC_AFFINE affine;
|
||||
if (!ec_jacobian_to_affine(group, &affine, &generator->raw) ||
|
||||
!ec_group_set_generator(group, &affine, order)) {
|
||||
copy = EC_POINT_new(group);
|
||||
if (copy == NULL ||
|
||||
!EC_POINT_copy(copy, generator) ||
|
||||
!BN_copy(&group->order, order)) {
|
||||
goto err;
|
||||
}
|
||||
// Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
|
||||
bn_set_minimal_width(&group->order);
|
||||
|
||||
BN_MONT_CTX_free(group->order_mont);
|
||||
group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
|
||||
if (group->order_mont == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
|
||||
if (group->field_greater_than_order) {
|
||||
if (!BN_sub(tmp, &group->field, &group->order) ||
|
||||
!bn_copy_words(group->field_minus_order.words, group->field.width,
|
||||
tmp)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ec_group_set0_generator(group, copy);
|
||||
copy = NULL;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EC_POINT_free(copy);
|
||||
BN_free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
|
||||
EC_GROUP *group = NULL;
|
||||
BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL;
|
||||
EC_POINT *P = NULL;
|
||||
BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
|
||||
int ok = 0;
|
||||
|
||||
BN_CTX *ctx = BN_CTX_new();
|
||||
@@ -455,8 +429,7 @@ static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
|
||||
|
||||
if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
|
||||
!(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
|
||||
!(b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) ||
|
||||
!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL))) {
|
||||
!(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
@@ -468,18 +441,42 @@ static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
EC_AFFINE G;
|
||||
EC_FELEM x, y;
|
||||
if (!ec_felem_from_bytes(group, &x, params + 3 * param_len, param_len) ||
|
||||
!ec_felem_from_bytes(group, &y, params + 4 * param_len, param_len) ||
|
||||
!ec_point_set_affine_coordinates(group, &G, &x, &y)) {
|
||||
if ((P = EC_POINT_new(group)) == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ec_group_set_generator(group, &G, order)) {
|
||||
if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
|
||||
!(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
|
||||
if (group->field_greater_than_order) {
|
||||
if (!BN_sub(p, &group->field, &group->order) ||
|
||||
!bn_copy_words(group->field_minus_order.words, group->field.width, p)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
|
||||
if (group->order_mont == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ec_group_set0_generator(group, P);
|
||||
P = NULL;
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
@@ -487,11 +484,13 @@ err:
|
||||
EC_GROUP_free(group);
|
||||
group = NULL;
|
||||
}
|
||||
EC_POINT_free(P);
|
||||
BN_CTX_free(ctx);
|
||||
BN_free(p);
|
||||
BN_free(a);
|
||||
BN_free(b);
|
||||
BN_free(order);
|
||||
BN_free(x);
|
||||
BN_free(y);
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -607,7 +606,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
|
||||
BN_cmp(&a->field, &b->field) != 0 ||
|
||||
!ec_felem_equal(a, &a->a, &b->a) ||
|
||||
!ec_felem_equal(a, &a->b, &b->b) ||
|
||||
!ec_GFp_simple_points_equal(a, &a->generator->raw, &b->generator->raw);
|
||||
ec_GFp_simple_cmp(a, &a->generator->raw, &b->generator->raw) != 0;
|
||||
}
|
||||
|
||||
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
|
||||
@@ -770,9 +769,7 @@ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Note |EC_POINT_cmp| returns zero for equality and non-zero for inequality.
|
||||
return ec_GFp_simple_points_equal(group, &a->raw, &b->raw) ? 0 : 1;
|
||||
return ec_GFp_simple_cmp(group, &a->raw, &b->raw);
|
||||
}
|
||||
|
||||
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
|
||||
@@ -790,67 +787,13 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
|
||||
if (!group->meth->point_get_affine_coordinates(group, &point->raw,
|
||||
x == NULL ? NULL : &x_felem,
|
||||
y == NULL ? NULL : &y_felem) ||
|
||||
(x != NULL && !ec_felem_to_bignum(group, x, &x_felem)) ||
|
||||
(y != NULL && !ec_felem_to_bignum(group, y, &y_felem))) {
|
||||
(x != NULL && !bn_set_words(x, x_felem.words, group->field.width)) ||
|
||||
(y != NULL && !bn_set_words(y, y_felem.words, group->field.width))) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ec_affine_to_jacobian(const EC_GROUP *group, EC_RAW_POINT *out,
|
||||
const EC_AFFINE *p) {
|
||||
out->X = p->X;
|
||||
out->Y = p->Y;
|
||||
out->Z = group->one;
|
||||
}
|
||||
|
||||
int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_RAW_POINT *p) {
|
||||
return group->meth->point_get_affine_coordinates(group, p, &out->X, &out->Y);
|
||||
}
|
||||
|
||||
int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_RAW_POINT *in, size_t num) {
|
||||
if (group->meth->jacobian_to_affine_batch == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
return group->meth->jacobian_to_affine_batch(group, out, in, num);
|
||||
}
|
||||
|
||||
int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_FELEM *x, const EC_FELEM *y) {
|
||||
void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
|
||||
const EC_FELEM *b) = group->meth->felem_mul;
|
||||
void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
|
||||
group->meth->felem_sqr;
|
||||
|
||||
// Check if the point is on the curve.
|
||||
EC_FELEM lhs, rhs;
|
||||
felem_sqr(group, &lhs, y); // lhs = y^2
|
||||
felem_sqr(group, &rhs, x); // rhs = x^2
|
||||
ec_felem_add(group, &rhs, &rhs, &group->a); // rhs = x^2 + a
|
||||
felem_mul(group, &rhs, &rhs, x); // rhs = x^3 + ax
|
||||
ec_felem_add(group, &rhs, &rhs, &group->b); // rhs = x^3 + ax + b
|
||||
if (!ec_felem_equal(group, &lhs, &rhs)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
|
||||
// In the event of an error, defend against the caller not checking the
|
||||
// return value by setting a known safe value. Note this may not be possible
|
||||
// if the caller is in the process of constructing an arbitrary group and
|
||||
// the generator is missing.
|
||||
if (group->generator != NULL) {
|
||||
assert(ec_felem_equal(group, &group->one, &group->generator->raw.Z));
|
||||
out->X = group->generator->raw.X;
|
||||
out->Y = group->generator->raw.Y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
out->X = *x;
|
||||
out->Y = *y;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
|
||||
const BIGNUM *x, const BIGNUM *y,
|
||||
BN_CTX *ctx) {
|
||||
@@ -858,24 +801,24 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x == NULL || y == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
|
||||
if (!ec_GFp_simple_point_set_affine_coordinates(group, &point->raw, x, y)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_FELEM x_felem, y_felem;
|
||||
EC_AFFINE affine;
|
||||
if (!ec_bignum_to_felem(group, &x_felem, x) ||
|
||||
!ec_bignum_to_felem(group, &y_felem, y) ||
|
||||
!ec_point_set_affine_coordinates(group, &affine, &x_felem, &y_felem)) {
|
||||
if (!EC_POINT_is_on_curve(group, point, ctx)) {
|
||||
// In the event of an error, defend against the caller not checking the
|
||||
// return value by setting a known safe value.
|
||||
ec_set_to_safe_point(group, &point->raw);
|
||||
// return value by setting a known safe value: the base point.
|
||||
const EC_POINT *generator = EC_GROUP_get0_generator(group);
|
||||
// The generator can be missing if the caller is in the process of
|
||||
// constructing an arbitrary group. In this, we give up and hope they're
|
||||
// checking the return value.
|
||||
if (generator) {
|
||||
ec_GFp_simple_point_copy(&point->raw, &generator->raw);
|
||||
}
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ec_affine_to_jacobian(group, &point->raw, &affine);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1006,27 +949,10 @@ int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (group->meth->mul_public == NULL) {
|
||||
return group->meth->mul_public_batch(group, r, g_scalar, p, p_scalar, 1);
|
||||
}
|
||||
|
||||
group->meth->mul_public(group, r, g_scalar, p, p_scalar);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num) {
|
||||
if (group->meth->mul_public_batch == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return group->meth->mul_public_batch(group, r, g_scalar, points, scalars,
|
||||
num);
|
||||
}
|
||||
|
||||
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p, const EC_SCALAR *scalar) {
|
||||
if (p == NULL || scalar == NULL) {
|
||||
@@ -1035,14 +961,6 @@ int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
}
|
||||
|
||||
group->meth->mul(group, r, p, scalar);
|
||||
|
||||
// Check the result is on the curve to defend against fault attacks or bugs.
|
||||
// This has negligible cost compared to the multiplication.
|
||||
if (!ec_GFp_simple_is_on_curve(group, r)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1054,93 +972,9 @@ int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
}
|
||||
|
||||
group->meth->mul_base(group, r, scalar);
|
||||
|
||||
// Check the result is on the curve to defend against fault attacks or bugs.
|
||||
// This has negligible cost compared to the multiplication.
|
||||
if (!ec_GFp_simple_is_on_curve(group, r)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_point_mul_scalar_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
|
||||
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
|
||||
const EC_RAW_POINT *p2,
|
||||
const EC_SCALAR *scalar2) {
|
||||
if (group->meth->mul_batch == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
group->meth->mul_batch(group, r, p0, scalar0, p1, scalar1, p2, scalar2);
|
||||
|
||||
// Check the result is on the curve to defend against fault attacks or bugs.
|
||||
// This has negligible cost compared to the multiplication.
|
||||
if (!ec_GFp_simple_is_on_curve(group, r)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
|
||||
const EC_RAW_POINT *p) {
|
||||
if (group->meth->init_precomp == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return group->meth->init_precomp(group, out, p);
|
||||
}
|
||||
|
||||
int ec_point_mul_scalar_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
|
||||
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
|
||||
const EC_PRECOMP *p2,
|
||||
const EC_SCALAR *scalar2) {
|
||||
if (group->meth->mul_precomp == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
group->meth->mul_precomp(group, r, p0, scalar0, p1, scalar1, p2, scalar2);
|
||||
|
||||
// Check the result is on the curve to defend against fault attacks or bugs.
|
||||
// This has negligible cost compared to the multiplication.
|
||||
if (!ec_GFp_simple_is_on_curve(group, r)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ec_point_select(const EC_GROUP *group, EC_RAW_POINT *out, BN_ULONG mask,
|
||||
const EC_RAW_POINT *a, const EC_RAW_POINT *b) {
|
||||
ec_felem_select(group, &out->X, mask, &a->X, &b->X);
|
||||
ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
|
||||
ec_felem_select(group, &out->Z, mask, &a->Z, &b->Z);
|
||||
}
|
||||
|
||||
void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask,
|
||||
const EC_AFFINE *a, const EC_AFFINE *b) {
|
||||
ec_felem_select(group, &out->X, mask, &a->X, &b->X);
|
||||
ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
|
||||
}
|
||||
|
||||
void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask,
|
||||
const EC_PRECOMP *a, const EC_PRECOMP *b) {
|
||||
OPENSSL_STATIC_ASSERT(sizeof(out->comb) == sizeof(*out),
|
||||
"out->comb does not span the entire structure");
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(out->comb); i++) {
|
||||
ec_affine_select(group, &out->comb[i], mask, &a->comb[i], &b->comb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *r) {
|
||||
return group->meth->cmp_x_coordinate(group, p, r);
|
||||
@@ -1148,17 +982,12 @@ int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
|
||||
|
||||
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_RAW_POINT *p) {
|
||||
uint8_t bytes[EC_MAX_BYTES];
|
||||
size_t len;
|
||||
if (!ec_get_x_coordinate_as_bytes(group, bytes, &len, sizeof(bytes), p)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_FELEM x;
|
||||
// For simplicity, in case of width mismatches between |group->field| and
|
||||
// |group->order|, zero any untouched words in |out|.
|
||||
OPENSSL_memset(out, 0, sizeof(EC_SCALAR));
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
out->bytes[len - i - 1] = bytes[i];
|
||||
// |group->order|, zero any untouched words in |x|.
|
||||
OPENSSL_memset(&x, 0, sizeof(x));
|
||||
if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
|
||||
@@ -1179,17 +1008,17 @@ int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
|
||||
// The above does not guarantee |group->field| is not one word larger than
|
||||
// |group->order|, so read one extra carry word.
|
||||
BN_ULONG tmp[EC_MAX_WORDS];
|
||||
BN_ULONG carry =
|
||||
group->order.width < EC_MAX_WORDS ? out->words[group->order.width] : 0;
|
||||
bn_reduce_once_in_place(out->words, carry, group->order.d, tmp,
|
||||
group->order.width);
|
||||
group->order.width < EC_MAX_WORDS ? x.words[group->order.width] : 0;
|
||||
bn_reduce_once(out->words, x.words, carry, group->order.d,
|
||||
group->order.width);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
size_t *out_len, size_t max_out,
|
||||
const EC_RAW_POINT *p) {
|
||||
int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
|
||||
uint8_t *out_y, size_t *out_len,
|
||||
size_t max_out,
|
||||
const EC_RAW_POINT *p) {
|
||||
size_t len = BN_num_bytes(&group->field);
|
||||
assert(len <= EC_MAX_BYTES);
|
||||
if (max_out < len) {
|
||||
@@ -1197,27 +1026,26 @@ int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_FELEM x;
|
||||
if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
|
||||
EC_FELEM x, y;
|
||||
if (!group->meth->point_get_affine_coordinates(
|
||||
group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ec_felem_to_bytes(group, out, out_len, &x);
|
||||
if (out_x != NULL) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
out_x[i] = x.bytes[len - i - 1];
|
||||
}
|
||||
}
|
||||
if (out_y != NULL) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
out_y[i] = y.bytes[len - i - 1];
|
||||
}
|
||||
}
|
||||
*out_len = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ec_set_to_safe_point(const EC_GROUP *group, EC_RAW_POINT *out) {
|
||||
if (group->generator != NULL) {
|
||||
ec_GFp_simple_point_copy(out, &group->generator->raw);
|
||||
} else {
|
||||
// The generator can be missing if the caller is in the process of
|
||||
// constructing an arbitrary group. In this case, we give up and use the
|
||||
// point at infinity.
|
||||
ec_GFp_simple_point_set_to_infinity(group, out);
|
||||
}
|
||||
}
|
||||
|
||||
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
|
||||
|
||||
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
|
||||
|
||||
@@ -292,6 +292,10 @@ void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) {
|
||||
}
|
||||
|
||||
int EC_KEY_check_key(const EC_KEY *eckey) {
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
EC_POINT *point = NULL;
|
||||
|
||||
if (!eckey || !eckey->group || !eckey->pub_key) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
@@ -299,31 +303,41 @@ int EC_KEY_check_key(const EC_KEY *eckey) {
|
||||
|
||||
if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Test whether the public key is on the elliptic curve.
|
||||
if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, NULL)) {
|
||||
ctx = BN_CTX_new();
|
||||
|
||||
if (ctx == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
// testing whether the pub_key is on the elliptic curve
|
||||
if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Check the public and private keys match.
|
||||
// in case the priv_key is present :
|
||||
// check if generator * priv_key == pub_key
|
||||
if (eckey->priv_key != NULL) {
|
||||
EC_RAW_POINT point;
|
||||
if (!ec_point_mul_scalar_base(eckey->group, &point,
|
||||
point = EC_POINT_new(eckey->group);
|
||||
if (point == NULL ||
|
||||
!ec_point_mul_scalar_base(eckey->group, &point->raw,
|
||||
&eckey->priv_key->scalar)) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
if (!ec_GFp_simple_points_equal(eckey->group, &point,
|
||||
&eckey->pub_key->raw)) {
|
||||
if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
BN_CTX_free(ctx);
|
||||
EC_POINT_free(point);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int EC_KEY_check_fips(const EC_KEY *key) {
|
||||
@@ -380,7 +394,7 @@ err:
|
||||
return ok;
|
||||
}
|
||||
|
||||
size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form,
|
||||
size_t EC_KEY_key2buf(EC_KEY *key, point_conversion_form_t form,
|
||||
unsigned char **out_buf, BN_CTX *ctx) {
|
||||
if (key == NULL || key->pub_key == NULL || key->group == NULL) {
|
||||
return 0;
|
||||
|
||||
@@ -92,20 +92,35 @@ void ec_GFp_mont_group_finish(EC_GROUP *group) {
|
||||
|
||||
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int ret = 0;
|
||||
|
||||
BN_MONT_CTX_free(group->mont);
|
||||
group->mont = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
group->mont = BN_MONT_CTX_new_for_modulus(p, ctx);
|
||||
if (group->mont == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ec_GFp_simple_group_set_curve(group, p, a, b, ctx)) {
|
||||
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
|
||||
|
||||
if (!ret) {
|
||||
BN_MONT_CTX_free(group->mont);
|
||||
group->mont = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ec_GFp_mont_felem_to_montgomery(const EC_GROUP *group,
|
||||
@@ -117,14 +132,14 @@ static void ec_GFp_mont_felem_to_montgomery(const EC_GROUP *group,
|
||||
static void ec_GFp_mont_felem_from_montgomery(const EC_GROUP *group,
|
||||
EC_FELEM *out,
|
||||
const EC_FELEM *in) {
|
||||
bn_from_montgomery_small(out->words, group->field.width, in->words,
|
||||
group->field.width, group->mont);
|
||||
bn_from_montgomery_small(out->words, in->words, group->field.width,
|
||||
group->mont);
|
||||
}
|
||||
|
||||
static void ec_GFp_mont_felem_inv0(const EC_GROUP *group, EC_FELEM *out,
|
||||
const EC_FELEM *a) {
|
||||
bn_mod_inverse0_prime_mont_small(out->words, a->words, group->field.width,
|
||||
group->mont);
|
||||
static void ec_GFp_mont_felem_inv(const EC_GROUP *group, EC_FELEM *out,
|
||||
const EC_FELEM *a) {
|
||||
bn_mod_inverse_prime_mont_small(out->words, a->words, group->field.width,
|
||||
group->mont);
|
||||
}
|
||||
|
||||
void ec_GFp_mont_felem_mul(const EC_GROUP *group, EC_FELEM *r,
|
||||
@@ -139,39 +154,30 @@ void ec_GFp_mont_felem_sqr(const EC_GROUP *group, EC_FELEM *r,
|
||||
group->mont);
|
||||
}
|
||||
|
||||
void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
size_t *out_len, const EC_FELEM *in) {
|
||||
EC_FELEM tmp;
|
||||
ec_GFp_mont_felem_from_montgomery(group, &tmp, in);
|
||||
ec_GFp_simple_felem_to_bytes(group, out, out_len, &tmp);
|
||||
}
|
||||
|
||||
int ec_GFp_mont_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out,
|
||||
const uint8_t *in, size_t len) {
|
||||
if (!ec_GFp_simple_felem_from_bytes(group, out, in, len)) {
|
||||
int ec_GFp_mont_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out,
|
||||
const BIGNUM *in) {
|
||||
if (group->mont == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bn_copy_words(out->words, group->field.width, in)) {
|
||||
return 0;
|
||||
}
|
||||
ec_GFp_mont_felem_to_montgomery(group, out, out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ec_GFp_mont_felem_reduce(const EC_GROUP *group, EC_FELEM *out,
|
||||
const BN_ULONG *words, size_t num) {
|
||||
// Convert "from" Montgomery form so the value is reduced mod p.
|
||||
bn_from_montgomery_small(out->words, group->field.width, words, num,
|
||||
group->mont);
|
||||
// Convert "to" Montgomery form to remove the R^-1 factor added.
|
||||
ec_GFp_mont_felem_to_montgomery(group, out, out);
|
||||
// Convert to Montgomery form to match this implementation's representation.
|
||||
ec_GFp_mont_felem_to_montgomery(group, out, out);
|
||||
}
|
||||
int ec_GFp_mont_felem_to_bignum(const EC_GROUP *group, BIGNUM *out,
|
||||
const EC_FELEM *in) {
|
||||
if (group->mont == NULL) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ec_GFp_mont_felem_exp(const EC_GROUP *group, EC_FELEM *out,
|
||||
const EC_FELEM *a, const BN_ULONG *exp,
|
||||
size_t num_exp) {
|
||||
bn_mod_exp_mont_small(out->words, a->words, group->field.width, exp, num_exp,
|
||||
group->mont);
|
||||
EC_FELEM tmp;
|
||||
ec_GFp_mont_felem_from_montgomery(group, &tmp, in);
|
||||
return bn_set_words(out, tmp.words, group->field.width);
|
||||
}
|
||||
|
||||
static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
@@ -182,12 +188,18 @@ static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3). Note the check above
|
||||
// ensures |point->Z| is non-zero, so the inverse always exists.
|
||||
// Transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3).
|
||||
|
||||
EC_FELEM z1, z2;
|
||||
ec_GFp_mont_felem_inv0(group, &z2, &point->Z);
|
||||
ec_GFp_mont_felem_inv(group, &z2, &point->Z);
|
||||
ec_GFp_mont_felem_sqr(group, &z1, &z2);
|
||||
|
||||
// Instead of using |ec_GFp_mont_felem_from_montgomery| to convert the |x|
|
||||
// coordinate and then calling |ec_GFp_mont_felem_from_montgomery| again to
|
||||
// convert the |y| coordinate below, convert the common factor |z1| once now,
|
||||
// saving one reduction.
|
||||
ec_GFp_mont_felem_from_montgomery(group, &z1, &z1);
|
||||
|
||||
if (x != NULL) {
|
||||
ec_GFp_mont_felem_mul(group, x, &point->X, &z1);
|
||||
}
|
||||
@@ -200,52 +212,6 @@ static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ec_GFp_mont_jacobian_to_affine_batch(const EC_GROUP *group,
|
||||
EC_AFFINE *out,
|
||||
const EC_RAW_POINT *in,
|
||||
size_t num) {
|
||||
if (num == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Compute prefix products of all Zs. Use |out[i].X| as scratch space
|
||||
// to store these values.
|
||||
out[0].X = in[0].Z;
|
||||
for (size_t i = 1; i < num; i++) {
|
||||
ec_GFp_mont_felem_mul(group, &out[i].X, &out[i - 1].X, &in[i].Z);
|
||||
}
|
||||
|
||||
// Some input was infinity iff the product of all Zs is zero.
|
||||
if (ec_felem_non_zero_mask(group, &out[num - 1].X) == 0) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Invert the product of all Zs.
|
||||
EC_FELEM zinvprod;
|
||||
ec_GFp_mont_felem_inv0(group, &zinvprod, &out[num - 1].X);
|
||||
for (size_t i = num - 1; i < num; i--) {
|
||||
// Our loop invariant is that |zinvprod| is Z0^-1 * Z1^-1 * ... * Zi^-1.
|
||||
// Recover Zi^-1 by multiplying by the previous product.
|
||||
EC_FELEM zinv, zinv2;
|
||||
if (i == 0) {
|
||||
zinv = zinvprod;
|
||||
} else {
|
||||
ec_GFp_mont_felem_mul(group, &zinv, &zinvprod, &out[i - 1].X);
|
||||
// Maintain the loop invariant for the next iteration.
|
||||
ec_GFp_mont_felem_mul(group, &zinvprod, &zinvprod, &in[i].Z);
|
||||
}
|
||||
|
||||
// Compute affine coordinates: x = X * Z^-2 and y = Y * Z^-3.
|
||||
ec_GFp_mont_felem_sqr(group, &zinv2, &zinv);
|
||||
ec_GFp_mont_felem_mul(group, &out[i].X, &in[i].X, &zinv2);
|
||||
ec_GFp_mont_felem_mul(group, &out[i].Y, &in[i].Y, &zinv2);
|
||||
ec_GFp_mont_felem_mul(group, &out[i].Y, &out[i].Y, &zinv);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ec_GFp_mont_add(const EC_GROUP *group, EC_RAW_POINT *out,
|
||||
const EC_RAW_POINT *a, const EC_RAW_POINT *b) {
|
||||
if (a == b) {
|
||||
@@ -502,23 +468,16 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) {
|
||||
out->group_finish = ec_GFp_mont_group_finish;
|
||||
out->group_set_curve = ec_GFp_mont_group_set_curve;
|
||||
out->point_get_affine_coordinates = ec_GFp_mont_point_get_affine_coordinates;
|
||||
out->jacobian_to_affine_batch = ec_GFp_mont_jacobian_to_affine_batch;
|
||||
out->add = ec_GFp_mont_add;
|
||||
out->dbl = ec_GFp_mont_dbl;
|
||||
out->mul = ec_GFp_mont_mul;
|
||||
out->mul_base = ec_GFp_mont_mul_base;
|
||||
out->mul_batch = ec_GFp_mont_mul_batch;
|
||||
out->mul_public_batch = ec_GFp_mont_mul_public_batch;
|
||||
out->init_precomp = ec_GFp_mont_init_precomp;
|
||||
out->mul_precomp = ec_GFp_mont_mul_precomp;
|
||||
out->mul_public = ec_GFp_mont_mul_public;
|
||||
out->felem_mul = ec_GFp_mont_felem_mul;
|
||||
out->felem_sqr = ec_GFp_mont_felem_sqr;
|
||||
out->felem_to_bytes = ec_GFp_mont_felem_to_bytes;
|
||||
out->felem_from_bytes = ec_GFp_mont_felem_from_bytes;
|
||||
out->felem_reduce = ec_GFp_mont_felem_reduce;
|
||||
out->felem_exp = ec_GFp_mont_felem_exp;
|
||||
out->scalar_inv0_montgomery = ec_simple_scalar_inv0_montgomery;
|
||||
out->scalar_to_montgomery_inv_vartime =
|
||||
ec_simple_scalar_to_montgomery_inv_vartime;
|
||||
out->bignum_to_felem = ec_GFp_mont_bignum_to_felem;
|
||||
out->felem_to_bignum = ec_GFp_mont_felem_to_bignum;
|
||||
out->scalar_inv_montgomery = ec_simple_scalar_inv_montgomery;
|
||||
out->scalar_inv_montgomery_vartime = ec_GFp_simple_mont_inv_mod_ord_vartime;
|
||||
out->cmp_x_coordinate = ec_GFp_mont_cmp_x_coordinate;
|
||||
}
|
||||
|
||||
+20
-374
@@ -28,9 +28,7 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/span.h>
|
||||
|
||||
#include "../../ec_extra/internal.h"
|
||||
#include "../../test/file_test.h"
|
||||
#include "../../test/test_util.h"
|
||||
#include "../bn/internal.h"
|
||||
@@ -134,22 +132,6 @@ static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool EncodeECPoint(std::vector<uint8_t> *out, const EC_GROUP *group,
|
||||
const EC_POINT *p, point_conversion_form_t form) {
|
||||
size_t len = EC_POINT_point2oct(group, p, form, nullptr, 0, nullptr);
|
||||
if (len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
out->resize(len);
|
||||
len = EC_POINT_point2oct(group, p, form, out->data(), out->size(), nullptr);
|
||||
if (len != out->size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(ECTest, Encoding) {
|
||||
bssl::UniquePtr<EC_KEY> key =
|
||||
DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
|
||||
@@ -348,23 +330,6 @@ TEST(ECTest, ArbitraryCurve) {
|
||||
|
||||
EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
|
||||
#endif
|
||||
|
||||
// group5 is the same group, but the curve coefficients are passed in
|
||||
// unreduced and the caller does not pass in a |BN_CTX|.
|
||||
ASSERT_TRUE(BN_sub(a.get(), a.get(), p.get()));
|
||||
ASSERT_TRUE(BN_add(b.get(), b.get(), p.get()));
|
||||
bssl::UniquePtr<EC_GROUP> group5(
|
||||
EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), NULL));
|
||||
ASSERT_TRUE(group5);
|
||||
bssl::UniquePtr<EC_POINT> generator5(EC_POINT_new(group5.get()));
|
||||
ASSERT_TRUE(generator5);
|
||||
ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
|
||||
group5.get(), generator5.get(), gx.get(), gy.get(), ctx.get()));
|
||||
ASSERT_TRUE(EC_GROUP_set_generator(group5.get(), generator5.get(),
|
||||
order.get(), BN_value_one()));
|
||||
|
||||
EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
|
||||
EXPECT_EQ(0, EC_GROUP_cmp(group5.get(), group.get(), NULL));
|
||||
}
|
||||
|
||||
TEST(ECTest, SetKeyWithoutGroup) {
|
||||
@@ -493,6 +458,9 @@ TEST_P(ECCurveTest, SetAffine) {
|
||||
ASSERT_TRUE(key);
|
||||
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
|
||||
|
||||
EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
|
||||
nullptr));
|
||||
|
||||
// Get the public key's coordinates.
|
||||
bssl::UniquePtr<BIGNUM> x(BN_new());
|
||||
ASSERT_TRUE(x);
|
||||
@@ -530,84 +498,6 @@ TEST_P(ECCurveTest, SetAffine) {
|
||||
EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
|
||||
}
|
||||
|
||||
TEST_P(ECCurveTest, IsOnCurve) {
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
|
||||
ASSERT_TRUE(key);
|
||||
ASSERT_TRUE(EC_KEY_generate_key(key.get()));
|
||||
|
||||
// The generated point is on the curve.
|
||||
EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
|
||||
nullptr));
|
||||
|
||||
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
|
||||
|
||||
// This should never happen outside of a bug, but |EC_POINT_is_on_curve|
|
||||
// rejects points not on the curve.
|
||||
OPENSSL_memset(&p->raw.X, 0, sizeof(p->raw.X));
|
||||
EXPECT_FALSE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
|
||||
|
||||
// The point at infinity is always on the curve.
|
||||
ASSERT_TRUE(EC_POINT_copy(p.get(), EC_KEY_get0_public_key(key.get())));
|
||||
OPENSSL_memset(&p->raw.Z, 0, sizeof(p->raw.Z));
|
||||
EXPECT_TRUE(EC_POINT_is_on_curve(group(), p.get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_P(ECCurveTest, Compare) {
|
||||
bssl::UniquePtr<EC_KEY> key1(EC_KEY_new_by_curve_name(GetParam().nid));
|
||||
ASSERT_TRUE(key1);
|
||||
ASSERT_TRUE(EC_KEY_generate_key(key1.get()));
|
||||
const EC_POINT *pub1 = EC_KEY_get0_public_key(key1.get());
|
||||
|
||||
bssl::UniquePtr<EC_KEY> key2(EC_KEY_new_by_curve_name(GetParam().nid));
|
||||
ASSERT_TRUE(key2);
|
||||
ASSERT_TRUE(EC_KEY_generate_key(key2.get()));
|
||||
const EC_POINT *pub2 = EC_KEY_get0_public_key(key2.get());
|
||||
|
||||
// Two different points should not compare as equal.
|
||||
EXPECT_EQ(1, EC_POINT_cmp(group(), pub1, pub2, nullptr));
|
||||
|
||||
// Serialize |pub1| and parse it back out. This gives a point in affine
|
||||
// coordinates.
|
||||
std::vector<uint8_t> serialized;
|
||||
ASSERT_TRUE(
|
||||
EncodeECPoint(&serialized, group(), pub1, POINT_CONVERSION_UNCOMPRESSED));
|
||||
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_TRUE(EC_POINT_oct2point(group(), p.get(), serialized.data(),
|
||||
serialized.size(), nullptr));
|
||||
|
||||
// The points should be equal.
|
||||
EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
|
||||
|
||||
// Add something to the point. It no longer compares as equal.
|
||||
ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), pub2, nullptr));
|
||||
EXPECT_EQ(1, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
|
||||
|
||||
// Negate |pub2|. It should no longer compare as equal. This tests that we
|
||||
// check both x and y coordinate.
|
||||
bssl::UniquePtr<EC_POINT> q(EC_POINT_new(group()));
|
||||
ASSERT_TRUE(q);
|
||||
ASSERT_TRUE(EC_POINT_copy(q.get(), pub2));
|
||||
ASSERT_TRUE(EC_POINT_invert(group(), q.get(), nullptr));
|
||||
EXPECT_EQ(1, EC_POINT_cmp(group(), q.get(), pub2, nullptr));
|
||||
|
||||
// Return |p| to the original value. It should be equal to |pub1| again.
|
||||
ASSERT_TRUE(EC_POINT_add(group(), p.get(), p.get(), q.get(), nullptr));
|
||||
EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), pub1, nullptr));
|
||||
|
||||
// Infinity compares as equal to itself, but not other points.
|
||||
bssl::UniquePtr<EC_POINT> inf1(EC_POINT_new(group())),
|
||||
inf2(EC_POINT_new(group()));
|
||||
ASSERT_TRUE(inf1);
|
||||
ASSERT_TRUE(EC_POINT_set_to_infinity(group(), inf1.get()));
|
||||
// |q| is currently -|pub2|.
|
||||
ASSERT_TRUE(EC_POINT_add(group(), inf2.get(), pub2, q.get(), nullptr));
|
||||
EXPECT_EQ(0, EC_POINT_cmp(group(), inf1.get(), inf2.get(), nullptr));
|
||||
EXPECT_EQ(1, EC_POINT_cmp(group(), inf1.get(), p.get(), nullptr));
|
||||
}
|
||||
|
||||
TEST_P(ECCurveTest, GenerateFIPS) {
|
||||
// Generate an EC_KEY.
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
|
||||
@@ -814,12 +704,18 @@ TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
|
||||
nullptr, nullptr));
|
||||
|
||||
// Serialize the point.
|
||||
std::vector<uint8_t> serialized;
|
||||
ASSERT_TRUE(EncodeECPoint(&serialized, group(), point.get(),
|
||||
POINT_CONVERSION_UNCOMPRESSED));
|
||||
size_t serialized_len = EC_POINT_point2oct(
|
||||
group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
|
||||
ASSERT_NE(0u, serialized_len);
|
||||
|
||||
std::vector<uint8_t> serialized(serialized_len);
|
||||
ASSERT_EQ(
|
||||
serialized_len,
|
||||
EC_POINT_point2oct(group(), point.get(), POINT_CONVERSION_UNCOMPRESSED,
|
||||
serialized.data(), serialized_len, nullptr));
|
||||
|
||||
// Create a serialized point that is not on the curve.
|
||||
serialized[serialized.size() - 1]++;
|
||||
serialized[serialized_len - 1]++;
|
||||
|
||||
ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
|
||||
serialized.size(), nullptr));
|
||||
@@ -983,45 +879,11 @@ TEST(ECTest, ScalarBaseMultVectors) {
|
||||
ASSERT_TRUE(
|
||||
EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get()));
|
||||
check_point(p.get());
|
||||
});
|
||||
}
|
||||
|
||||
// These tests take a very long time, but are worth running when we make
|
||||
// non-trivial changes to the EC code.
|
||||
TEST(ECTest, DISABLED_ScalarBaseMultVectorsTwoPoint) {
|
||||
bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
|
||||
ASSERT_TRUE(ctx);
|
||||
|
||||
FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
|
||||
[&](FileTest *t) {
|
||||
bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
|
||||
ASSERT_TRUE(group);
|
||||
bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
|
||||
ASSERT_TRUE(n);
|
||||
bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
|
||||
ASSERT_TRUE(x);
|
||||
bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
|
||||
ASSERT_TRUE(y);
|
||||
bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
|
||||
|
||||
bssl::UniquePtr<BIGNUM> px(BN_new());
|
||||
ASSERT_TRUE(px);
|
||||
bssl::UniquePtr<BIGNUM> py(BN_new());
|
||||
ASSERT_TRUE(py);
|
||||
auto check_point = [&](const EC_POINT *p) {
|
||||
if (is_infinity) {
|
||||
EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
|
||||
} else {
|
||||
ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
|
||||
group.get(), p, px.get(), py.get(), ctx.get()));
|
||||
EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
|
||||
EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
|
||||
}
|
||||
};
|
||||
|
||||
const EC_POINT *g = EC_GROUP_get0_generator(group.get());
|
||||
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
|
||||
ASSERT_TRUE(p);
|
||||
// These tests take a very long time, but are worth running when we make
|
||||
// non-trivial changes to the EC code.
|
||||
#if 0
|
||||
// Test two-point multiplication.
|
||||
bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
|
||||
for (int i = -64; i < 64; i++) {
|
||||
SCOPED_TRACE(i);
|
||||
@@ -1043,226 +905,10 @@ TEST(ECTest, DISABLED_ScalarBaseMultVectorsTwoPoint) {
|
||||
EC_SCALAR a_scalar, b_scalar;
|
||||
ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get()));
|
||||
ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get()));
|
||||
ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar,
|
||||
&g->raw, &b_scalar));
|
||||
ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), &p->raw, &a_scalar, &g->raw,
|
||||
&b_scalar));
|
||||
check_point(p.get());
|
||||
}
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> HexToBytes(const char *str) {
|
||||
std::vector<uint8_t> ret;
|
||||
if (!DecodeHex(&ret, str)) {
|
||||
abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEST(ECTest, DeriveFromSecret) {
|
||||
struct DeriveTest {
|
||||
int curve;
|
||||
std::vector<uint8_t> secret;
|
||||
std::vector<uint8_t> expected_priv;
|
||||
std::vector<uint8_t> expected_pub;
|
||||
};
|
||||
const DeriveTest kDeriveTests[] = {
|
||||
{NID_X9_62_prime256v1, HexToBytes(""),
|
||||
HexToBytes(
|
||||
"b98a86a71efb51ebdac4759937b977e9b0c05224675bb2b6a58ba306e237f4b8"),
|
||||
HexToBytes(
|
||||
"04fbe6cab439918e00231a2ff073cdc25823998864a9eb36f809095a1a919ece875"
|
||||
"a145803fbe89a6cde53936e3c6d9c253ed3d38f5f58cae455c27e95645ceda9")},
|
||||
{NID_X9_62_prime256v1, HexToBytes("123456"),
|
||||
HexToBytes(
|
||||
"44a72bc62087b88e5ab7126766177ed0d8f1ed09ad066cd746527fc201105a7e"),
|
||||
HexToBytes(
|
||||
"04ec0555cd76e991fef7f5504343937d0f38696db3360a4854052cb0d84a377a5a0"
|
||||
"ff64c352755c28692b4ae085c2b817db9a1eddbd22e9cf39c12751e0870791b")},
|
||||
{NID_X9_62_prime256v1, HexToBytes("00000000000000000000000000000000"),
|
||||
HexToBytes(
|
||||
"7ca1e2c83e6a5f2c1b3e7d58180226f269930c4b9fbe2a275096079630b7c57d"),
|
||||
HexToBytes(
|
||||
"0442ef70c8fc0fbe383ed0a0da36f39f9a590f3feebc07863cc858c9a8ef0465731"
|
||||
"0408c249bd4d61929c54b71ffe056e6b4fa1eb537039b43d1c175f0ceab0f89")},
|
||||
{NID_X9_62_prime256v1,
|
||||
HexToBytes(
|
||||
"de9c9b35543aaa0fba039e34e8ca9695da3225c7161c9e3a8c70356cac28c780"),
|
||||
HexToBytes(
|
||||
"659f5abf3b62b9931c29d6ed0722efd2349fa56f54e708cf3272f620f1bc44d0"),
|
||||
HexToBytes(
|
||||
"046741f806b593bf3a3d4a9d76bdcb9b0d7874633cbea8f42c05e78561f7e8ec362"
|
||||
"b9b6f1913ded796fbdafe7f210cea897ac22a4e580c06a60f2659fd09f1830f")},
|
||||
{NID_secp384r1, HexToBytes("123456"),
|
||||
HexToBytes("95cd90d548997de090c7622708eccb7edc1b1bd78d2422235ad97406dada"
|
||||
"076555309da200096f6e4b36c46002beee89"),
|
||||
HexToBytes(
|
||||
"04007b2d026aa7636fa912c3f970d62bb6c10fa81c8f3290ed90b2d701696d1c6b9"
|
||||
"5af88ce13e962996a7ac37e16527cb5d69bd081b8641d07634cf84b438600ec9434"
|
||||
"15ac6bd7a0236f7ab0ea31ece67df03fa11646ea2b75e73d1b5e45b75c18")},
|
||||
};
|
||||
|
||||
for (const auto &test : kDeriveTests) {
|
||||
SCOPED_TRACE(Bytes(test.secret));
|
||||
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve));
|
||||
ASSERT_TRUE(group);
|
||||
bssl::UniquePtr<EC_KEY> key(EC_KEY_derive_from_secret(
|
||||
group.get(), test.secret.data(), test.secret.size()));
|
||||
ASSERT_TRUE(key);
|
||||
|
||||
std::vector<uint8_t> priv(BN_num_bytes(EC_GROUP_get0_order(group.get())));
|
||||
ASSERT_TRUE(BN_bn2bin_padded(priv.data(), priv.size(),
|
||||
EC_KEY_get0_private_key(key.get())));
|
||||
EXPECT_EQ(Bytes(priv), Bytes(test.expected_priv));
|
||||
|
||||
uint8_t *pub = nullptr;
|
||||
size_t pub_len =
|
||||
EC_KEY_key2buf(key.get(), POINT_CONVERSION_UNCOMPRESSED, &pub, nullptr);
|
||||
bssl::UniquePtr<uint8_t> free_pub(pub);
|
||||
EXPECT_NE(pub_len, 0u);
|
||||
EXPECT_EQ(Bytes(pub, pub_len), Bytes(test.expected_pub));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ECTest, HashToCurve) {
|
||||
struct HashToCurveTest {
|
||||
int (*hash_to_curve)(const EC_GROUP *group, EC_RAW_POINT *out,
|
||||
const uint8_t *dst, size_t dst_len, const uint8_t *msg,
|
||||
size_t msg_len);
|
||||
int curve_nid;
|
||||
const char *dst;
|
||||
const char *msg;
|
||||
const char *x_hex;
|
||||
const char *y_hex;
|
||||
};
|
||||
static const HashToCurveTest kTests[] = {
|
||||
// See draft-irtf-cfrg-hash-to-curve-07, appendix G.2.1.
|
||||
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SSWU_RO_TESTGEN", "",
|
||||
"2fc0b9efdd63a8e43b4db88dc12f03c798f6fd91bccac0c9096185"
|
||||
"4386e58fdc54fc2a01f0f358759054ce1f9b762025",
|
||||
"949b936fabb72cdb02cd7980b86cb6a3adf286658e81301648851d"
|
||||
"b8a49d9bec00ccb57698d559fc5960fa5030a8e54b"},
|
||||
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abc",
|
||||
"4f3338035391e8ce8ce40c974136f0edc97f392ffd44a643338741"
|
||||
"8ed1b8c2603487e1688ec151f048fbc6b2c138c92f",
|
||||
"152b90aef6558be328a3168855fb1906452e7167b0f7c8a56ff9d4"
|
||||
"fa87d6fb522cdf8e409db54418b2c764fd26260757"},
|
||||
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SSWU_RO_TESTGEN", "abcdef0123456789",
|
||||
"e9e5d7ac397e123d060ad44301cbc8eb972f6e64ebcff29dcc9b9a"
|
||||
"10357902aace2240c580fec85e5b427d98b4e80703",
|
||||
"916cb8963521ad75105be43cc4148e5a5bbb4fcf107f1577e4f7fa"
|
||||
"3ca58cd786aa76890c8e687d2353393bc16c78ec4d"},
|
||||
{&ec_hash_to_curve_p384_xmd_sha512_sswu_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SSWU_RO_TESTGEN",
|
||||
"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"41941db59a7b8b633bd5bfa462f1e29a9f18e5a341445d90fc6eb9"
|
||||
"37f2913224287b9dfb64742851f760eb14ca115ff9",
|
||||
"1510e764f1be968d661b7aaecb26a6d38c98e5205ca150f0ae426d"
|
||||
"2c3983c68e3a9ffb283c6ae4891d891b5705500475"},
|
||||
};
|
||||
|
||||
for (const auto &test : kTests) {
|
||||
SCOPED_TRACE(test.dst);
|
||||
SCOPED_TRACE(test.msg);
|
||||
|
||||
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve_nid));
|
||||
ASSERT_TRUE(group);
|
||||
bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_TRUE(test.hash_to_curve(
|
||||
group.get(), &p->raw, reinterpret_cast<const uint8_t *>(test.dst),
|
||||
strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
|
||||
strlen(test.msg)));
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
ASSERT_TRUE(EncodeECPoint(&buf, group.get(), p.get(),
|
||||
POINT_CONVERSION_UNCOMPRESSED));
|
||||
size_t field_len = (buf.size() - 1) / 2;
|
||||
EXPECT_EQ(test.x_hex,
|
||||
EncodeHex(bssl::MakeConstSpan(buf).subspan(1, field_len)));
|
||||
EXPECT_EQ(test.y_hex, EncodeHex(bssl::MakeConstSpan(buf).subspan(
|
||||
1 + field_len, field_len)));
|
||||
}
|
||||
|
||||
// hash-to-curve functions should check for the wrong group.
|
||||
bssl::UniquePtr<EC_GROUP> p224(EC_GROUP_new_by_curve_name(NID_secp224r1));
|
||||
ASSERT_TRUE(p224);
|
||||
EC_RAW_POINT p;
|
||||
static const uint8_t kDST[] = {0, 1, 2, 3};
|
||||
static const uint8_t kMessage[] = {4, 5, 6, 7};
|
||||
EXPECT_FALSE(ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
|
||||
p224.get(), &p, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
|
||||
}
|
||||
|
||||
TEST(ECTest, HashToScalar) {
|
||||
struct HashToScalarTest {
|
||||
int (*hash_to_scalar)(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const uint8_t *dst, size_t dst_len,
|
||||
const uint8_t *msg, size_t msg_len);
|
||||
int curve_nid;
|
||||
const char *dst;
|
||||
const char *msg;
|
||||
const char *result_hex;
|
||||
};
|
||||
static const HashToScalarTest kTests[] = {
|
||||
{&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SCALAR_TEST", "",
|
||||
"9687acc2de56c3cf94c0e05b6811a21aa480092254ec0532bdce63"
|
||||
"140ecd340f09dc2d45d77e21fb0aa76f7707b8a676"},
|
||||
{&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SCALAR_TEST", "abcdef0123456789",
|
||||
"8f8076022a68233cbcecaceae68c2068f132724f001caa78619eff"
|
||||
"1ffc58fa871db73fe9034fc9cf853c384ed34b5666"},
|
||||
{&ec_hash_to_scalar_p384_xmd_sha512_draft07, NID_secp384r1,
|
||||
"P384_XMD:SHA-512_SCALAR_TEST",
|
||||
"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"750f2fae7d2b2f41ac737d180c1d4363d85a1504798b4976d40921"
|
||||
"1ddb3651c13a5b4daba9975cdfce18336791131915"},
|
||||
};
|
||||
|
||||
for (const auto &test : kTests) {
|
||||
SCOPED_TRACE(test.dst);
|
||||
SCOPED_TRACE(test.msg);
|
||||
|
||||
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(test.curve_nid));
|
||||
ASSERT_TRUE(group);
|
||||
EC_SCALAR scalar;
|
||||
ASSERT_TRUE(test.hash_to_scalar(
|
||||
group.get(), &scalar, reinterpret_cast<const uint8_t *>(test.dst),
|
||||
strlen(test.dst), reinterpret_cast<const uint8_t *>(test.msg),
|
||||
strlen(test.msg)));
|
||||
uint8_t buf[EC_MAX_BYTES];
|
||||
size_t len;
|
||||
ec_scalar_to_bytes(group.get(), buf, &len, &scalar);
|
||||
EXPECT_EQ(test.result_hex, EncodeHex(bssl::MakeConstSpan(buf, len)));
|
||||
}
|
||||
|
||||
// hash-to-scalar functions should check for the wrong group.
|
||||
bssl::UniquePtr<EC_GROUP> p224(EC_GROUP_new_by_curve_name(NID_secp224r1));
|
||||
ASSERT_TRUE(p224);
|
||||
EC_SCALAR scalar;
|
||||
static const uint8_t kDST[] = {0, 1, 2, 3};
|
||||
static const uint8_t kMessage[] = {4, 5, 6, 7};
|
||||
EXPECT_FALSE(ec_hash_to_scalar_p384_xmd_sha512_draft07(
|
||||
p224.get(), &scalar, kDST, sizeof(kDST), kMessage, sizeof(kMessage)));
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -24,34 +23,15 @@
|
||||
|
||||
|
||||
int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in) {
|
||||
uint8_t bytes[EC_MAX_BYTES];
|
||||
size_t len = BN_num_bytes(&group->field);
|
||||
assert(sizeof(bytes) >= len);
|
||||
if (BN_is_negative(in) ||
|
||||
BN_cmp(in, &group->field) >= 0 ||
|
||||
!BN_bn2bin_padded(bytes, len, in)) {
|
||||
if (BN_is_negative(in) || BN_cmp(in, &group->field) >= 0) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ec_felem_from_bytes(group, out, bytes, len);
|
||||
return group->meth->bignum_to_felem(group, out, in);
|
||||
}
|
||||
|
||||
int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in) {
|
||||
uint8_t bytes[EC_MAX_BYTES];
|
||||
size_t len;
|
||||
ec_felem_to_bytes(group, bytes, &len, in);
|
||||
return BN_bin2bn(bytes, len, out) != NULL;
|
||||
}
|
||||
|
||||
void ec_felem_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len,
|
||||
const EC_FELEM *in) {
|
||||
group->meth->felem_to_bytes(group, out, out_len, in);
|
||||
}
|
||||
|
||||
int ec_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out, const uint8_t *in,
|
||||
size_t len) {
|
||||
return group->meth->felem_from_bytes(group, out, in, len);
|
||||
return group->meth->felem_to_bignum(group, out, in);
|
||||
}
|
||||
|
||||
void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a) {
|
||||
@@ -95,6 +75,8 @@ void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask,
|
||||
|
||||
int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a,
|
||||
const EC_FELEM *b) {
|
||||
return CRYPTO_memcmp(a->words, b->words,
|
||||
group->field.width * sizeof(BN_ULONG)) == 0;
|
||||
// Note this function is variable-time. Constant-time operations should use
|
||||
// |ec_felem_non_zero_mask|.
|
||||
return OPENSSL_memcmp(a->words, b->words,
|
||||
group->field.width * sizeof(BN_ULONG)) == 0;
|
||||
}
|
||||
|
||||
+161
-434
@@ -71,8 +71,8 @@
|
||||
#include <openssl/base.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ex_data.h>
|
||||
#include <openssl/thread.h>
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include "../bn/internal.h"
|
||||
@@ -82,9 +82,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// EC internals.
|
||||
|
||||
|
||||
// Cap the size of all field elements and scalars, including custom curves, to
|
||||
// 66 bytes, large enough to fit secp521r1 and brainpoolP512r1, which appear to
|
||||
// be the largest fields anyone plausibly uses.
|
||||
@@ -94,9 +91,6 @@ extern "C" {
|
||||
OPENSSL_STATIC_ASSERT(EC_MAX_WORDS <= BN_SMALL_MAX_WORDS,
|
||||
"bn_*_small functions not usable");
|
||||
|
||||
|
||||
// Scalars.
|
||||
|
||||
// An EC_SCALAR is an integer fully reduced modulo the order. Only the first
|
||||
// |order->width| words are used. An |EC_SCALAR| is specific to an |EC_GROUP|
|
||||
// and must not be mixed between groups.
|
||||
@@ -106,88 +100,6 @@ typedef union {
|
||||
BN_ULONG words[EC_MAX_WORDS];
|
||||
} EC_SCALAR;
|
||||
|
||||
// ec_bignum_to_scalar converts |in| to an |EC_SCALAR| and writes it to
|
||||
// |*out|. It returns one on success and zero if |in| is out of range.
|
||||
OPENSSL_EXPORT int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const BIGNUM *in);
|
||||
|
||||
// ec_scalar_to_bytes serializes |in| as a big-endian bytestring to |out| and
|
||||
// sets |*out_len| to the number of bytes written. The number of bytes written
|
||||
// is |BN_num_bytes(&group->order)|, which is at most |EC_MAX_BYTES|.
|
||||
OPENSSL_EXPORT void ec_scalar_to_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
size_t *out_len, const EC_SCALAR *in);
|
||||
|
||||
// ec_scalar_from_bytes deserializes |in| and stores the resulting scalar over
|
||||
// group |group| to |out|. It returns one on success and zero if |in| is
|
||||
// invalid.
|
||||
int ec_scalar_from_bytes(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const uint8_t *in, size_t len);
|
||||
|
||||
// ec_scalar_reduce sets |out| to |words|, reduced modulo the group order.
|
||||
// |words| must be less than order^2. |num| must be at most twice the width of
|
||||
// group order. This function treats |words| as secret.
|
||||
void ec_scalar_reduce(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const BN_ULONG *words, size_t num);
|
||||
|
||||
// ec_random_nonzero_scalar sets |out| to a uniformly selected random value from
|
||||
// 1 to |group->order| - 1. It returns one on success and zero on error.
|
||||
int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const uint8_t additional_data[32]);
|
||||
|
||||
// ec_scalar_equal_vartime returns one if |a| and |b| are equal and zero
|
||||
// otherwise. Both values are treated as public.
|
||||
int ec_scalar_equal_vartime(const EC_GROUP *group, const EC_SCALAR *a,
|
||||
const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_is_zero returns one if |a| is zero and zero otherwise.
|
||||
int ec_scalar_is_zero(const EC_GROUP *group, const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_add sets |r| to |a| + |b|.
|
||||
void ec_scalar_add(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
|
||||
const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_sub sets |r| to |a| - |b|.
|
||||
void ec_scalar_sub(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
|
||||
const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_neg sets |r| to -|a|.
|
||||
void ec_scalar_neg(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_to_montgomery sets |r| to |a| in Montgomery form.
|
||||
void ec_scalar_to_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_to_montgomery sets |r| to |a| converted from Montgomery form.
|
||||
void ec_scalar_from_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_mul_montgomery sets |r| to |a| * |b| where inputs and outputs are
|
||||
// in Montgomery form.
|
||||
void ec_scalar_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a, const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_inv0_montgomery sets |r| to |a|^-1 where inputs and outputs are in
|
||||
// Montgomery form. If |a| is zero, |r| is set to zero.
|
||||
void ec_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_to_montgomery_inv_vartime sets |r| to |a|^-1 R. That is, it takes
|
||||
// in |a| not in Montgomery form and computes the inverse in Montgomery form. It
|
||||
// returns one on success and zero if |a| has no inverse. This function assumes
|
||||
// |a| is public and may leak information about it via timing.
|
||||
//
|
||||
// Note this is not the same operation as |ec_scalar_inv0_montgomery|.
|
||||
int ec_scalar_to_montgomery_inv_vartime(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_select, in constant time, sets |out| to |a| if |mask| is all ones
|
||||
// and |b| if |mask| is all zeros.
|
||||
void ec_scalar_select(const EC_GROUP *group, EC_SCALAR *out, BN_ULONG mask,
|
||||
const EC_SCALAR *a, const EC_SCALAR *b);
|
||||
|
||||
|
||||
// Field elements.
|
||||
|
||||
// An EC_FELEM represents a field element. Only the first |field->width| words
|
||||
// are used. An |EC_FELEM| is specific to an |EC_GROUP| and must not be mixed
|
||||
// between groups. Additionally, the representation (whether or not elements are
|
||||
@@ -198,268 +110,15 @@ typedef union {
|
||||
BN_ULONG words[EC_MAX_WORDS];
|
||||
} EC_FELEM;
|
||||
|
||||
// ec_bignum_to_felem converts |in| to an |EC_FELEM|. It returns one on success
|
||||
// and zero if |in| is out of range.
|
||||
int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in);
|
||||
|
||||
// ec_felem_to_bignum converts |in| to a |BIGNUM|. It returns one on success and
|
||||
// zero on allocation failure.
|
||||
int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in);
|
||||
|
||||
// ec_felem_to_bytes serializes |in| as a big-endian bytestring to |out| and
|
||||
// sets |*out_len| to the number of bytes written. The number of bytes written
|
||||
// is |BN_num_bytes(&group->order)|, which is at most |EC_MAX_BYTES|.
|
||||
void ec_felem_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len,
|
||||
const EC_FELEM *in);
|
||||
|
||||
// ec_felem_from_bytes deserializes |in| and stores the resulting field element
|
||||
// to |out|. It returns one on success and zero if |in| is invalid.
|
||||
int ec_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out, const uint8_t *in,
|
||||
size_t len);
|
||||
|
||||
// ec_felem_neg sets |out| to -|a|.
|
||||
void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a);
|
||||
|
||||
// ec_felem_add sets |out| to |a| + |b|.
|
||||
void ec_felem_add(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
|
||||
const EC_FELEM *b);
|
||||
|
||||
// ec_felem_add sets |out| to |a| - |b|.
|
||||
void ec_felem_sub(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
|
||||
const EC_FELEM *b);
|
||||
|
||||
// ec_felem_non_zero_mask returns all ones if |a| is non-zero and all zeros
|
||||
// otherwise.
|
||||
BN_ULONG ec_felem_non_zero_mask(const EC_GROUP *group, const EC_FELEM *a);
|
||||
|
||||
// ec_felem_select, in constant time, sets |out| to |a| if |mask| is all ones
|
||||
// and |b| if |mask| is all zeros.
|
||||
void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask,
|
||||
const EC_FELEM *a, const EC_FELEM *b);
|
||||
|
||||
// ec_felem_equal returns one if |a| and |b| are equal and zero otherwise.
|
||||
int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a, const EC_FELEM *b);
|
||||
|
||||
|
||||
// Points.
|
||||
//
|
||||
// Points may represented in affine coordinates as |EC_AFFINE| or Jacobian
|
||||
// coordinates as |EC_RAW_POINT|. Affine coordinates directly represent a
|
||||
// point on the curve, but point addition over affine coordinates requires
|
||||
// costly field inversions, so arithmetic is done in Jacobian coordinates.
|
||||
// Converting from affine to Jacobian is cheap, while converting from Jacobian
|
||||
// to affine costs a field inversion. (Jacobian coordinates amortize the field
|
||||
// inversions needed in a sequence of point operations.)
|
||||
//
|
||||
// TODO(davidben): Rename |EC_RAW_POINT| to |EC_JACOBIAN|.
|
||||
|
||||
// An EC_RAW_POINT represents an elliptic curve point in Jacobian coordinates.
|
||||
// Unlike |EC_POINT|, it is a plain struct which can be stack-allocated and
|
||||
// needs no cleanup. It is specific to an |EC_GROUP| and must not be mixed
|
||||
// between groups.
|
||||
// An EC_RAW_POINT represents an elliptic curve point. Unlike |EC_POINT|, it is
|
||||
// a plain struct which can be stack-allocated and needs no cleanup. It is
|
||||
// specific to an |EC_GROUP| and must not be mixed between groups.
|
||||
typedef struct {
|
||||
EC_FELEM X, Y, Z;
|
||||
// X, Y, and Z are Jacobian projective coordinates. They represent
|
||||
// (X/Z^2, Y/Z^3) if Z != 0 and the point at infinity otherwise.
|
||||
EC_FELEM X, Y, Z;
|
||||
} EC_RAW_POINT;
|
||||
|
||||
// An EC_AFFINE represents an elliptic curve point in affine coordinates.
|
||||
// coordinates. Note the point at infinity cannot be represented in affine
|
||||
// coordinates.
|
||||
typedef struct {
|
||||
EC_FELEM X, Y;
|
||||
} EC_AFFINE;
|
||||
|
||||
// ec_affine_to_jacobian converts |p| to Jacobian form and writes the result to
|
||||
// |*out|. This operation is very cheap and only costs a few copies.
|
||||
void ec_affine_to_jacobian(const EC_GROUP *group, EC_RAW_POINT *out,
|
||||
const EC_AFFINE *p);
|
||||
|
||||
// ec_jacobian_to_affine converts |p| to affine form and writes the result to
|
||||
// |*out|. It returns one on success and zero if |p| was the point at infinity.
|
||||
// This operation performs a field inversion and should only be done once per
|
||||
// point.
|
||||
//
|
||||
// If only extracting the x-coordinate, use |ec_get_x_coordinate_*| which is
|
||||
// slightly faster.
|
||||
int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_RAW_POINT *p);
|
||||
|
||||
// ec_jacobian_to_affine_batch converts |num| points in |in| from Jacobian
|
||||
// coordinates to affine coordinates and writes the results to |out|. It returns
|
||||
// one on success and zero if any of the input points were infinity.
|
||||
//
|
||||
// This function is not implemented for all curves. Add implementations as
|
||||
// needed.
|
||||
int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_RAW_POINT *in, size_t num);
|
||||
|
||||
// ec_point_set_affine_coordinates sets |out|'s to a point with affine
|
||||
// coordinates |x| and |y|. It returns one if the point is on the curve and
|
||||
// zero otherwise. If the point is not on the curve, the value of |out| is
|
||||
// undefined.
|
||||
int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_FELEM *x, const EC_FELEM *y);
|
||||
|
||||
// ec_point_mul_scalar sets |r| to |p| * |scalar|. Both inputs are considered
|
||||
// secret.
|
||||
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p, const EC_SCALAR *scalar);
|
||||
|
||||
// ec_point_mul_scalar_base sets |r| to generator * |scalar|. |scalar| is
|
||||
// treated as secret.
|
||||
int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *scalar);
|
||||
|
||||
// ec_point_mul_scalar_batch sets |r| to |p0| * |scalar0| + |p1| * |scalar1| +
|
||||
// |p2| * |scalar2|. |p2| may be NULL to skip that term.
|
||||
//
|
||||
// The inputs are treated as secret, however, this function leaks information
|
||||
// about whether intermediate computations add a point to itself. Callers must
|
||||
// ensure that discrete logs between |p0|, |p1|, and |p2| are uniformly
|
||||
// distributed and independent of the scalars, which should be uniformly
|
||||
// selected and not under the attackers control. This ensures the doubling case
|
||||
// will occur with negligible probability.
|
||||
//
|
||||
// This function is not implemented for all curves. Add implementations as
|
||||
// needed.
|
||||
//
|
||||
// TODO(davidben): This function does not use base point tables. For now, it is
|
||||
// only used with the generic |EC_GFp_mont_method| implementation which has
|
||||
// none. If generalizing to tuned curves, this may be useful. However, we still
|
||||
// must double up to the least efficient input, so precomputed tables can only
|
||||
// save table setup and allow a wider window size.
|
||||
int ec_point_mul_scalar_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
|
||||
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
|
||||
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2);
|
||||
|
||||
#define EC_MONT_PRECOMP_COMB_SIZE 5
|
||||
|
||||
// An |EC_PRECOMP| stores precomputed information about a point, to optimize
|
||||
// repeated multiplications involving it. It is a union so different
|
||||
// |EC_METHOD|s can store different information in it.
|
||||
typedef union {
|
||||
EC_AFFINE comb[(1 << EC_MONT_PRECOMP_COMB_SIZE) - 1];
|
||||
} EC_PRECOMP;
|
||||
|
||||
// ec_init_precomp precomputes multiples of |p| and writes the result to |out|.
|
||||
// It returns one on success and zero on error. The resulting table may be used
|
||||
// with |ec_point_mul_scalar_precomp|. This function will fail if |p| is the
|
||||
// point at infinity.
|
||||
//
|
||||
// This function is not implemented for all curves. Add implementations as
|
||||
// needed.
|
||||
int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
|
||||
const EC_RAW_POINT *p);
|
||||
|
||||
// ec_point_mul_scalar_precomp sets |r| to |p0| * |scalar0| + |p1| * |scalar1| +
|
||||
// |p2| * |scalar2|. |p1| or |p2| may be NULL to skip the corresponding term.
|
||||
// The points are represented as |EC_PRECOMP| and must be initialized with
|
||||
// |ec_init_precomp|. This function runs faster than |ec_point_mul_scalar_batch|
|
||||
// but requires setup work per input point, so it is only appropriate for points
|
||||
// which are used frequently.
|
||||
//
|
||||
// The inputs are treated as secret, however, this function leaks information
|
||||
// about whether intermediate computations add a point to itself. Callers must
|
||||
// ensure that discrete logs between |p0|, |p1|, and |p2| are uniformly
|
||||
// distributed and independent of the scalars, which should be uniformly
|
||||
// selected and not under the attackers control. This ensures the doubling case
|
||||
// will occur with negligible probability.
|
||||
//
|
||||
// This function is not implemented for all curves. Add implementations as
|
||||
// needed.
|
||||
//
|
||||
// TODO(davidben): This function does not use base point tables. For now, it is
|
||||
// only used with the generic |EC_GFp_mont_method| implementation which has
|
||||
// none. If generalizing to tuned curves, we should add a parameter for the base
|
||||
// point and arrange for the generic implementation to have base point tables
|
||||
// available.
|
||||
int ec_point_mul_scalar_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
|
||||
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
|
||||
const EC_PRECOMP *p2, const EC_SCALAR *scalar2);
|
||||
|
||||
// ec_point_mul_scalar_public sets |r| to
|
||||
// generator * |g_scalar| + |p| * |p_scalar|. It assumes that the inputs are
|
||||
// public so there is no concern about leaking their values through timing.
|
||||
OPENSSL_EXPORT int ec_point_mul_scalar_public(const EC_GROUP *group,
|
||||
EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
|
||||
// ec_point_mul_scalar_public_batch sets |r| to the sum of generator *
|
||||
// |g_scalar| and |points[i]| * |scalars[i]| where |points| and |scalars| have
|
||||
// |num| elements. It assumes that the inputs are public so there is no concern
|
||||
// about leaking their values through timing. |g_scalar| may be NULL to skip
|
||||
// that term.
|
||||
//
|
||||
// This function is not implemented for all curves. Add implementations as
|
||||
// needed.
|
||||
int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num);
|
||||
|
||||
// ec_point_select, in constant time, sets |out| to |a| if |mask| is all ones
|
||||
// and |b| if |mask| is all zeros.
|
||||
void ec_point_select(const EC_GROUP *group, EC_RAW_POINT *out, BN_ULONG mask,
|
||||
const EC_RAW_POINT *a, const EC_RAW_POINT *b);
|
||||
|
||||
// ec_affine_select behaves like |ec_point_select| but acts on affine points.
|
||||
void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask,
|
||||
const EC_AFFINE *a, const EC_AFFINE *b);
|
||||
|
||||
// ec_precomp_select behaves like |ec_point_select| but acts on |EC_PRECOMP|.
|
||||
void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask,
|
||||
const EC_PRECOMP *a, const EC_PRECOMP *b);
|
||||
|
||||
// ec_cmp_x_coordinate compares the x (affine) coordinate of |p|, mod the group
|
||||
// order, with |r|. It returns one if the values match and zero if |p| is the
|
||||
// point at infinity of the values do not match.
|
||||
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *r);
|
||||
|
||||
// ec_get_x_coordinate_as_scalar sets |*out| to |p|'s x-coordinate, modulo
|
||||
// |group->order|. It returns one on success and zero if |p| is the point at
|
||||
// infinity.
|
||||
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_RAW_POINT *p);
|
||||
|
||||
// ec_get_x_coordinate_as_bytes writes |p|'s affine x-coordinate to |out|, which
|
||||
// must have at must |max_out| bytes. It sets |*out_len| to the number of bytes
|
||||
// written. The value is written big-endian and zero-padded to the size of the
|
||||
// field. This function returns one on success and zero on failure.
|
||||
int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
size_t *out_len, size_t max_out,
|
||||
const EC_RAW_POINT *p);
|
||||
|
||||
// ec_point_to_bytes behaves like |EC_POINT_point2oct| but takes an
|
||||
// |EC_AFFINE|.
|
||||
size_t ec_point_to_bytes(const EC_GROUP *group, const EC_AFFINE *point,
|
||||
point_conversion_form_t form, uint8_t *buf,
|
||||
size_t len);
|
||||
|
||||
// ec_point_from_uncompressed parses |in| as a point in uncompressed form and
|
||||
// sets the result to |out|. It returns one on success and zero if the input was
|
||||
// invalid.
|
||||
int ec_point_from_uncompressed(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const uint8_t *in, size_t len);
|
||||
|
||||
// ec_set_to_safe_point sets |out| to an arbitrary point on |group|, either the
|
||||
// generator or the point at infinity. This is used to guard against callers of
|
||||
// external APIs not checking the return value.
|
||||
void ec_set_to_safe_point(const EC_GROUP *group, EC_RAW_POINT *out);
|
||||
|
||||
// ec_affine_jacobian_equal returns one if |a| and |b| represent the same point
|
||||
// and zero otherwise. It treats both inputs as secret.
|
||||
int ec_affine_jacobian_equal(const EC_GROUP *group, const EC_AFFINE *a,
|
||||
const EC_RAW_POINT *b);
|
||||
|
||||
|
||||
// Implementation details.
|
||||
|
||||
struct ec_method_st {
|
||||
int (*group_init)(EC_GROUP *);
|
||||
void (*group_finish)(EC_GROUP *);
|
||||
@@ -469,13 +128,12 @@ struct ec_method_st {
|
||||
// point_get_affine_coordinates sets |*x| and |*y| to the affine coordinates
|
||||
// of |p|. Either |x| or |y| may be NULL to omit it. It returns one on success
|
||||
// and zero if |p| is the point at infinity.
|
||||
//
|
||||
// Note: unlike |EC_FELEM|s used as intermediate values internal to the
|
||||
// |EC_METHOD|, |*x| and |*y| are not encoded in Montgomery form.
|
||||
int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_RAW_POINT *p,
|
||||
EC_FELEM *x, EC_FELEM *y);
|
||||
|
||||
// jacobian_to_affine_batch implements |ec_jacobian_to_affine_batch|.
|
||||
int (*jacobian_to_affine_batch)(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const EC_RAW_POINT *in, size_t num);
|
||||
|
||||
// add sets |r| to |a| + |b|.
|
||||
void (*add)(const EC_GROUP *group, EC_RAW_POINT *r, const EC_RAW_POINT *a,
|
||||
const EC_RAW_POINT *b);
|
||||
@@ -488,32 +146,12 @@ struct ec_method_st {
|
||||
// mul_base sets |r| to |scalar|*generator.
|
||||
void (*mul_base)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *scalar);
|
||||
// mul_batch implements |ec_mul_scalar_batch|.
|
||||
void (*mul_batch)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
|
||||
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
|
||||
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2);
|
||||
// mul_public sets |r| to |g_scalar|*generator + |p_scalar|*|p|. It assumes
|
||||
// that the inputs are public so there is no concern about leaking their
|
||||
// values through timing.
|
||||
//
|
||||
// This function may be omitted if |mul_public_batch| is provided.
|
||||
void (*mul_public)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
// mul_public_batch implements |ec_point_mul_scalar_public_batch|.
|
||||
int (*mul_public_batch)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num);
|
||||
|
||||
// init_precomp implements |ec_init_precomp|.
|
||||
int (*init_precomp)(const EC_GROUP *group, EC_PRECOMP *out,
|
||||
const EC_RAW_POINT *p);
|
||||
// mul_precomp implements |ec_point_mul_scalar_precomp|.
|
||||
void (*mul_precomp)(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
|
||||
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
|
||||
const EC_PRECOMP *p2, const EC_SCALAR *scalar2);
|
||||
|
||||
// felem_mul and felem_sqr implement multiplication and squaring,
|
||||
// respectively, so that the generic |EC_POINT_add| and |EC_POINT_dbl|
|
||||
@@ -530,36 +168,21 @@ struct ec_method_st {
|
||||
const EC_FELEM *b);
|
||||
void (*felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a);
|
||||
|
||||
void (*felem_to_bytes)(const EC_GROUP *group, uint8_t *out, size_t *out_len,
|
||||
int (*bignum_to_felem)(const EC_GROUP *group, EC_FELEM *out,
|
||||
const BIGNUM *in);
|
||||
int (*felem_to_bignum)(const EC_GROUP *group, BIGNUM *out,
|
||||
const EC_FELEM *in);
|
||||
int (*felem_from_bytes)(const EC_GROUP *group, EC_FELEM *out,
|
||||
const uint8_t *in, size_t len);
|
||||
|
||||
// felem_reduce sets |out| to |words|, reduced modulo the field size, p.
|
||||
// |words| must be less than p^2. |num| must be at most twice the width of p.
|
||||
// This function treats |words| as secret.
|
||||
//
|
||||
// This function is only used in hash-to-curve and may be omitted in curves
|
||||
// that do not support it.
|
||||
void (*felem_reduce)(const EC_GROUP *group, EC_FELEM *out,
|
||||
const BN_ULONG *words, size_t num);
|
||||
// scalar_inv_montgomery sets |out| to |in|^-1, where both input and output
|
||||
// are in Montgomery form.
|
||||
void (*scalar_inv_montgomery)(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_SCALAR *in);
|
||||
|
||||
// felem_exp sets |out| to |a|^|exp|. It treats |a| is secret but |exp| as
|
||||
// public.
|
||||
//
|
||||
// This function is used in hash-to-curve and may be NULL in curves not used
|
||||
// with hash-to-curve.
|
||||
void (*felem_exp)(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
|
||||
const BN_ULONG *exp, size_t num_exp);
|
||||
|
||||
// scalar_inv0_montgomery implements |ec_scalar_inv0_montgomery|.
|
||||
void (*scalar_inv0_montgomery)(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_SCALAR *in);
|
||||
|
||||
// scalar_to_montgomery_inv_vartime implements
|
||||
// |ec_scalar_to_montgomery_inv_vartime|.
|
||||
int (*scalar_to_montgomery_inv_vartime)(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_SCALAR *in);
|
||||
// scalar_inv_montgomery_vartime performs the same computation as
|
||||
// |scalar_inv_montgomery|. It further assumes that the inputs are public so
|
||||
// there is no concern about leaking their values through timing.
|
||||
int (*scalar_inv_montgomery_vartime)(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_SCALAR *in);
|
||||
|
||||
// cmp_x_coordinate compares the x (affine) coordinate of |p|, mod the group
|
||||
// order, with |r|. It returns one if the values match and zero if |p| is the
|
||||
@@ -574,8 +197,7 @@ struct ec_group_st {
|
||||
const EC_METHOD *meth;
|
||||
|
||||
// Unlike all other |EC_POINT|s, |generator| does not own |generator->group|
|
||||
// to avoid a reference cycle. Additionally, Z is guaranteed to be one, so X
|
||||
// and Y are suitable for use as an |EC_AFFINE|.
|
||||
// to avoid a reference cycle.
|
||||
EC_POINT *generator;
|
||||
BIGNUM order;
|
||||
|
||||
@@ -625,20 +247,133 @@ struct ec_point_st {
|
||||
|
||||
EC_GROUP *ec_group_new(const EC_METHOD *meth);
|
||||
|
||||
// ec_bignum_to_felem converts |in| to an |EC_FELEM|. It returns one on success
|
||||
// and zero if |in| is out of range.
|
||||
int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in);
|
||||
|
||||
// ec_felem_to_bignum converts |in| to a |BIGNUM|. It returns one on success and
|
||||
// zero on allocation failure.
|
||||
int ec_felem_to_bignum(const EC_GROUP *group, BIGNUM *out, const EC_FELEM *in);
|
||||
|
||||
// ec_felem_neg sets |out| to -|a|.
|
||||
void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a);
|
||||
|
||||
// ec_felem_add sets |out| to |a| + |b|.
|
||||
void ec_felem_add(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
|
||||
const EC_FELEM *b);
|
||||
|
||||
// ec_felem_add sets |out| to |a| - |b|.
|
||||
void ec_felem_sub(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a,
|
||||
const EC_FELEM *b);
|
||||
|
||||
// ec_felem_non_zero_mask returns all ones if |a| is non-zero and all zeros
|
||||
// otherwise.
|
||||
BN_ULONG ec_felem_non_zero_mask(const EC_GROUP *group, const EC_FELEM *a);
|
||||
|
||||
// ec_felem_select, in constant time, sets |out| to |a| if |mask| is all ones
|
||||
// and |b| if |mask| is all zeros.
|
||||
void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask,
|
||||
const EC_FELEM *a, const EC_FELEM *b);
|
||||
|
||||
// ec_felem_equal returns one if |a| and |b| are equal and zero otherwise. It
|
||||
// treats |a| and |b| as public and does *not* run in constant time.
|
||||
int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a, const EC_FELEM *b);
|
||||
|
||||
// ec_bignum_to_scalar converts |in| to an |EC_SCALAR| and writes it to
|
||||
// |*out|. It returns one on success and zero if |in| is out of range.
|
||||
OPENSSL_EXPORT int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const BIGNUM *in);
|
||||
|
||||
// ec_random_nonzero_scalar sets |out| to a uniformly selected random value from
|
||||
// 1 to |group->order| - 1. It returns one on success and zero on error.
|
||||
int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const uint8_t additional_data[32]);
|
||||
|
||||
// ec_scalar_equal_vartime returns one if |a| and |b| are equal and zero
|
||||
// otherwise. Both values are treated as public.
|
||||
int ec_scalar_equal_vartime(const EC_GROUP *group, const EC_SCALAR *a,
|
||||
const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_is_zero returns one if |a| is zero and zero otherwise.
|
||||
int ec_scalar_is_zero(const EC_GROUP *group, const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_add sets |r| to |a| + |b|.
|
||||
void ec_scalar_add(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
|
||||
const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_to_montgomery sets |r| to |a| in Montgomery form.
|
||||
void ec_scalar_to_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_to_montgomery sets |r| to |a| converted from Montgomery form.
|
||||
void ec_scalar_from_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_mul_montgomery sets |r| to |a| * |b| where inputs and outputs are
|
||||
// in Montgomery form.
|
||||
void ec_scalar_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a, const EC_SCALAR *b);
|
||||
|
||||
// ec_scalar_mul_montgomery sets |r| to |a|^-1 where inputs and outputs are in
|
||||
// Montgomery form.
|
||||
void ec_scalar_inv_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_scalar_inv_montgomery_vartime performs the same actions as
|
||||
// |ec_scalar_inv_montgomery|, but in variable time.
|
||||
int ec_scalar_inv_montgomery_vartime(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
// ec_point_mul_scalar sets |r| to |p| * |scalar|. Both inputs are considered
|
||||
// secret.
|
||||
int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p, const EC_SCALAR *scalar);
|
||||
|
||||
// ec_point_mul_scalar_base sets |r| to generator * |scalar|. |scalar| is
|
||||
// treated as secret.
|
||||
int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *scalar);
|
||||
|
||||
// ec_point_mul_scalar_public performs the same computation as
|
||||
// ec_point_mul_scalar. It further assumes that the inputs are public so
|
||||
// there is no concern about leaking their values through timing.
|
||||
OPENSSL_EXPORT int ec_point_mul_scalar_public(const EC_GROUP *group,
|
||||
EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
|
||||
// ec_cmp_x_coordinate compares the x (affine) coordinate of |p|, mod the group
|
||||
// order, with |r|. It returns one if the values match and zero if |p| is the
|
||||
// point at infinity of the values do not match.
|
||||
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *r);
|
||||
|
||||
// ec_get_x_coordinate_as_scalar sets |*out| to |p|'s x-coordinate, modulo
|
||||
// |group->order|. It returns one on success and zero if |p| is the point at
|
||||
// infinity.
|
||||
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_RAW_POINT *p);
|
||||
|
||||
// ec_point_get_affine_coordinate_bytes writes |p|'s affine coordinates to
|
||||
// |out_x| and |out_y|, each of which must have at must |max_out| bytes. It sets
|
||||
// |*out_len| to the number of bytes written in each buffer. Coordinates are
|
||||
// written big-endian and zero-padded to the size of the field.
|
||||
//
|
||||
// Either of |out_x| or |out_y| may be NULL to omit that coordinate. This
|
||||
// function returns one on success and zero on failure.
|
||||
int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
|
||||
uint8_t *out_y, size_t *out_len,
|
||||
size_t max_out, const EC_RAW_POINT *p);
|
||||
|
||||
// ec_field_element_to_scalar reduces |r| modulo |group->order|. |r| must
|
||||
// previously have been reduced modulo |group->field|.
|
||||
int ec_field_element_to_scalar(const EC_GROUP *group, BIGNUM *r);
|
||||
|
||||
void ec_GFp_mont_mul(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p, const EC_SCALAR *scalar);
|
||||
void ec_GFp_mont_mul_base(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *scalar);
|
||||
void ec_GFp_mont_mul_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p0, const EC_SCALAR *scalar0,
|
||||
const EC_RAW_POINT *p1, const EC_SCALAR *scalar1,
|
||||
const EC_RAW_POINT *p2, const EC_SCALAR *scalar2);
|
||||
int ec_GFp_mont_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
|
||||
const EC_RAW_POINT *p);
|
||||
void ec_GFp_mont_mul_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
|
||||
const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
|
||||
const EC_PRECOMP *p2, const EC_SCALAR *scalar2);
|
||||
|
||||
// ec_compute_wNAF writes the modified width-(w+1) Non-Adjacent Form (wNAF) of
|
||||
// |scalar| to |out|. |out| must have room for |bits| + 1 elements, each of
|
||||
@@ -651,10 +386,9 @@ void ec_GFp_mont_mul_precomp(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
void ec_compute_wNAF(const EC_GROUP *group, int8_t *out,
|
||||
const EC_SCALAR *scalar, size_t bits, int w);
|
||||
|
||||
int ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *points,
|
||||
const EC_SCALAR *scalars, size_t num);
|
||||
void ec_GFp_mont_mul_public(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar);
|
||||
|
||||
// method functions in simple.c
|
||||
int ec_GFp_simple_group_init(EC_GROUP *);
|
||||
@@ -666,29 +400,26 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
|
||||
void ec_GFp_simple_point_init(EC_RAW_POINT *);
|
||||
void ec_GFp_simple_point_copy(EC_RAW_POINT *, const EC_RAW_POINT *);
|
||||
void ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_RAW_POINT *);
|
||||
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_RAW_POINT *,
|
||||
const BIGNUM *x,
|
||||
const BIGNUM *y);
|
||||
void ec_GFp_mont_add(const EC_GROUP *, EC_RAW_POINT *r, const EC_RAW_POINT *a,
|
||||
const EC_RAW_POINT *b);
|
||||
void ec_GFp_mont_dbl(const EC_GROUP *, EC_RAW_POINT *r, const EC_RAW_POINT *a);
|
||||
void ec_GFp_simple_invert(const EC_GROUP *, EC_RAW_POINT *);
|
||||
int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_RAW_POINT *);
|
||||
int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_RAW_POINT *);
|
||||
int ec_GFp_simple_points_equal(const EC_GROUP *, const EC_RAW_POINT *a,
|
||||
const EC_RAW_POINT *b);
|
||||
void ec_simple_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
int ec_GFp_simple_cmp(const EC_GROUP *, const EC_RAW_POINT *a,
|
||||
const EC_RAW_POINT *b);
|
||||
void ec_simple_scalar_inv_montgomery(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
int ec_simple_scalar_to_montgomery_inv_vartime(const EC_GROUP *group,
|
||||
EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
int ec_GFp_simple_mont_inv_mod_ord_vartime(const EC_GROUP *group, EC_SCALAR *r,
|
||||
const EC_SCALAR *a);
|
||||
|
||||
int ec_GFp_simple_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *r);
|
||||
|
||||
void ec_GFp_simple_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
size_t *out_len, const EC_FELEM *in);
|
||||
int ec_GFp_simple_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out,
|
||||
const uint8_t *in, size_t len);
|
||||
|
||||
// method functions in montgomery.c
|
||||
int ec_GFp_mont_group_init(EC_GROUP *);
|
||||
int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
|
||||
@@ -698,13 +429,12 @@ void ec_GFp_mont_felem_mul(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
|
||||
const EC_FELEM *b);
|
||||
void ec_GFp_mont_felem_sqr(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a);
|
||||
|
||||
void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
|
||||
size_t *out_len, const EC_FELEM *in);
|
||||
int ec_GFp_mont_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out,
|
||||
const uint8_t *in, size_t len);
|
||||
int ec_GFp_mont_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out,
|
||||
const BIGNUM *in);
|
||||
int ec_GFp_mont_felem_to_bignum(const EC_GROUP *group, BIGNUM *out,
|
||||
const EC_FELEM *in);
|
||||
|
||||
void ec_GFp_nistp_recode_scalar_bits(crypto_word_t *sign, crypto_word_t *digit,
|
||||
crypto_word_t in);
|
||||
void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
|
||||
|
||||
const EC_METHOD *EC_GFp_nistp224_method(void);
|
||||
const EC_METHOD *EC_GFp_nistp256_method(void);
|
||||
@@ -723,9 +453,6 @@ typedef struct {
|
||||
struct ec_key_st {
|
||||
EC_GROUP *group;
|
||||
|
||||
// Ideally |pub_key| would be an |EC_AFFINE| so serializing it does not pay an
|
||||
// inversion each time, but the |EC_KEY_get0_public_key| API implies public
|
||||
// keys are stored in an |EC_POINT|-compatible form.
|
||||
EC_POINT *pub_key;
|
||||
EC_WRAPPED_SCALAR *priv_key;
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/* 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. */
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
const fileHeader = `/* Copyright (c) 2015, Intel 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 is the precomputed constant time access table for the code in
|
||||
// p256-x86_64.c, for the default generator. The table consists of 37
|
||||
// subtables, each subtable contains 64 affine points. The affine points are
|
||||
// encoded as eight uint64's, four for the x coordinate and four for the y.
|
||||
// Both values are in little-endian order. There are 37 tables because a
|
||||
// signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37.
|
||||
// Within each table there are 64 values because the 6-bit wNAF value can take
|
||||
// 64 values, ignoring the sign bit, which is implemented by performing a
|
||||
// negation of the affine point when required. We would like to align it to 2MB
|
||||
// in order to increase the chances of using a large page but that appears to
|
||||
// lead to invalid ELF files being produced.
|
||||
|
||||
// This file is generated by make_p256-x86_64-table.go.
|
||||
|
||||
static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = {
|
||||
`
|
||||
|
||||
func main() {
|
||||
os.Stdout.WriteString(fileHeader)
|
||||
|
||||
scalar, tmp := new(big.Int), new(big.Int)
|
||||
p256 := elliptic.P256()
|
||||
p := p256.Params().P
|
||||
|
||||
// The wNAF windows are 7 bits wide, so advance across the 256-bit scalar
|
||||
// space in 7-bit increments.
|
||||
for shift := uint(0); shift < 256; shift += 7 {
|
||||
// For each window, encode 64 multiples of the base point.
|
||||
for multiple := 1; multiple <= 64; multiple++ {
|
||||
scalar.SetInt64(int64(multiple))
|
||||
scalar.Lsh(scalar, shift)
|
||||
|
||||
x, y := p256.ScalarBaseMult(scalar.Bytes())
|
||||
|
||||
toMontgomery(x, p)
|
||||
toMontgomery(y, p)
|
||||
|
||||
if multiple == 1 {
|
||||
os.Stdout.WriteString(" {{")
|
||||
} else {
|
||||
os.Stdout.WriteString(" {")
|
||||
}
|
||||
printNum(x, tmp)
|
||||
|
||||
os.Stdout.WriteString(",\n ")
|
||||
printNum(y, tmp)
|
||||
|
||||
if multiple == 64 {
|
||||
os.Stdout.WriteString("}}")
|
||||
} else {
|
||||
os.Stdout.WriteString("},\n")
|
||||
}
|
||||
}
|
||||
|
||||
if shift+7 < 256 {
|
||||
os.Stdout.WriteString(",\n")
|
||||
} else {
|
||||
os.Stdout.WriteString("};\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mask, R *big.Int
|
||||
|
||||
func init() {
|
||||
mask = new(big.Int).SetUint64(0xffffffffffffffff)
|
||||
R = new(big.Int).SetInt64(1)
|
||||
R.Lsh(R, 256)
|
||||
}
|
||||
|
||||
func printNum(n, tmp *big.Int) {
|
||||
fmt.Printf("{")
|
||||
for i := 0; i < 4; i++ {
|
||||
tmp.And(n, mask)
|
||||
limb := tmp.Uint64()
|
||||
fmt.Printf("TOBN(0x%08x, 0x%08x)", uint32(limb>>32), uint32(limb))
|
||||
n.Rsh(n, 64)
|
||||
|
||||
switch i {
|
||||
case 0, 2:
|
||||
os.Stdout.WriteString(", ")
|
||||
case 1:
|
||||
os.Stdout.WriteString(",\n ")
|
||||
}
|
||||
}
|
||||
fmt.Printf("}")
|
||||
}
|
||||
|
||||
// toMontgomery sets n to be n×R mod p
|
||||
func toMontgomery(n, p *big.Int) {
|
||||
n.Mul(n, R)
|
||||
n.Mod(n, p)
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
/* Copyright (c) 2020, 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 (
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := writeP256X86_64Table("p256-x86_64-table.h"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing p256-x86_64-table.h: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := writeP256Table("p256_table.h"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing p256_table.h: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func writeP256X86_64Table(path string) error {
|
||||
curve := elliptic.P256()
|
||||
tables := make([][][2]*big.Int, 0, 37)
|
||||
for shift := 0; shift < 256; shift += 7 {
|
||||
row := makeMultiples(curve, 64, shift)
|
||||
tables = append(tables, row)
|
||||
}
|
||||
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
const fileHeader = `/*
|
||||
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2015, Intel Inc.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
// This is the precomputed constant time access table for the code in
|
||||
// p256-x86_64.c, for the default generator. The table consists of 37
|
||||
// subtables, each subtable contains 64 affine points. The affine points are
|
||||
// encoded as eight uint64's, four for the x coordinate and four for the y.
|
||||
// Both values are in little-endian order. There are 37 tables because a
|
||||
// signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37.
|
||||
// Within each table there are 64 values because the 6-bit wNAF value can take
|
||||
// 64 values, ignoring the sign bit, which is implemented by performing a
|
||||
// negation of the affine point when required. We would like to align it to 2MB
|
||||
// in order to increase the chances of using a large page but that appears to
|
||||
// lead to invalid ELF files being produced.
|
||||
|
||||
// This file is generated by make_tables.go.
|
||||
|
||||
static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = `
|
||||
if _, err := f.WriteString(fileHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeTables(f, curve, tables, true, 4, writeBNMont); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.WriteString(";\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeP256Table(path string) error {
|
||||
curve := elliptic.P256()
|
||||
tables := [][][2]*big.Int{
|
||||
makeComb(curve, 64, 4, 0),
|
||||
makeComb(curve, 64, 4, 32),
|
||||
}
|
||||
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
const fileHeader = `/* Copyright (c) 2020, 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 file is generated by make_tables.go.
|
||||
|
||||
// Base point pre computation
|
||||
// --------------------------
|
||||
//
|
||||
// Two different sorts of precomputed tables are used in the following code.
|
||||
// Each contain various points on the curve, where each point is three field
|
||||
// elements (x, y, z).
|
||||
//
|
||||
// For the base point table, z is usually 1 (0 for the point at infinity).
|
||||
// This table has 2 * 16 elements, starting with the following:
|
||||
// index | bits | point
|
||||
// ------+---------+------------------------------
|
||||
// 0 | 0 0 0 0 | 0G
|
||||
// 1 | 0 0 0 1 | 1G
|
||||
// 2 | 0 0 1 0 | 2^64G
|
||||
// 3 | 0 0 1 1 | (2^64 + 1)G
|
||||
// 4 | 0 1 0 0 | 2^128G
|
||||
// 5 | 0 1 0 1 | (2^128 + 1)G
|
||||
// 6 | 0 1 1 0 | (2^128 + 2^64)G
|
||||
// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
|
||||
// 8 | 1 0 0 0 | 2^192G
|
||||
// 9 | 1 0 0 1 | (2^192 + 1)G
|
||||
// 10 | 1 0 1 0 | (2^192 + 2^64)G
|
||||
// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
|
||||
// 12 | 1 1 0 0 | (2^192 + 2^128)G
|
||||
// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
|
||||
// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
|
||||
// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
|
||||
// followed by a copy of this with each element multiplied by 2^32.
|
||||
//
|
||||
// The reason for this is so that we can clock bits into four different
|
||||
// locations when doing simple scalar multiplies against the base point,
|
||||
// and then another four locations using the second 16 elements.
|
||||
//
|
||||
// Tables for other points have table[i] = iG for i in 0 .. 16.
|
||||
|
||||
// fiat_p256_g_pre_comp is the table of precomputed base points
|
||||
#if defined(BORINGSSL_NISTP256_64BIT)
|
||||
static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = `
|
||||
if _, err := f.WriteString(fileHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeTables(f, curve, tables, true, 4, writeU64Mont); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.WriteString(";\n#else\nstatic const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = "); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeTables(f, curve, tables, true, 4, writeU32Mont); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.WriteString(";\n#endif\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeMultiples returns a table of the first n multiples of 2^shift * G,
|
||||
// starting from 1 * 2^shift * G.
|
||||
func makeMultiples(curve elliptic.Curve, n, shift int) [][2]*big.Int {
|
||||
ret := make([][2]*big.Int, n)
|
||||
x, y := curve.Params().Gx, curve.Params().Gy
|
||||
for j := 0; j < shift; j++ {
|
||||
x, y = curve.Double(x, y)
|
||||
}
|
||||
ret[1-1] = [2]*big.Int{x, y}
|
||||
for i := 2; i <= n; i++ {
|
||||
if i&1 == 0 {
|
||||
x, y := curve.Double(ret[i/2-1][0], ret[i/2-1][1])
|
||||
ret[i-1] = [2]*big.Int{x, y}
|
||||
} else {
|
||||
x, y := curve.Add(ret[i-1-1][0], ret[i-1-1][1], ret[1-1][0], ret[1-1][1])
|
||||
ret[i-1] = [2]*big.Int{x, y}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// makeComb returns a table of 2^size - 1 points. The i-1th entry is k*G.
|
||||
// If i is represented in binary by b0*2^0 + b1*2^1 + ... bn*2^n, k is
|
||||
// b0*2^(shift + 0*stride) + b1*2^(shift + 1*stride) + ... + bn*2^(shift + n*stride).
|
||||
// The entry for i = 0 is omitted because it is always the point at infinity.
|
||||
func makeComb(curve elliptic.Curve, stride, size, shift int) [][2]*big.Int {
|
||||
ret := make([][2]*big.Int, 1<<size-1)
|
||||
x, y := curve.Params().Gx, curve.Params().Gy
|
||||
for j := 0; j < shift; j++ {
|
||||
x, y = curve.Double(x, y)
|
||||
}
|
||||
ret[1<<0-1] = [2]*big.Int{x, y}
|
||||
for i := 1; i < size; i++ {
|
||||
// Entry 2^i is entry 2^(i-1) doubled stride times.
|
||||
x, y = ret[1<<(i-1)-1][0], ret[1<<(i-1)-1][1]
|
||||
for j := 0; j < stride; j++ {
|
||||
x, y = curve.Double(x, y)
|
||||
}
|
||||
ret[1<<i-1] = [2]*big.Int{x, y}
|
||||
// The remaining entries with MSB 2^i are computed by adding entry 2^i
|
||||
// to the corresponding previous entry.
|
||||
for j := 1; j < 1<<i; j++ {
|
||||
x, y = curve.Add(ret[1<<i-1][0], ret[1<<i-1][1], ret[j-1][0], ret[j-1][1])
|
||||
ret[1<<i+j-1] = [2]*big.Int{x, y}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// toMontgomery sets n to be n×R mod p, where R is the Montgomery factor.
|
||||
func toMontgomery(curve elliptic.Curve, n *big.Int) *big.Int {
|
||||
params := curve.Params()
|
||||
// R is the bit width of p, rounded up to word size.
|
||||
rounded64 := 64 * ((params.BitSize + 63) / 64)
|
||||
rounded32 := 32 * ((params.BitSize + 31) / 32)
|
||||
if rounded64 != rounded32 {
|
||||
panic(fmt.Sprintf("Montgomery form for %s is inconsistent between 32-bit and 64-bit", params.Name))
|
||||
}
|
||||
R := new(big.Int).SetInt64(1)
|
||||
R.Lsh(R, uint(rounded64))
|
||||
|
||||
ret := new(big.Int).Mul(n, R)
|
||||
ret.Mod(ret, params.P)
|
||||
return ret
|
||||
}
|
||||
|
||||
func bigIntToU64s(curve elliptic.Curve, n *big.Int) []uint64 {
|
||||
words := (curve.Params().BitSize + 63) / 64
|
||||
ret := make([]uint64, words)
|
||||
bytes := n.Bytes()
|
||||
for i, b := range bytes {
|
||||
i = len(bytes) - i - 1
|
||||
ret[i/8] |= uint64(b) << (8 * (i % 8))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func bigIntToU32s(curve elliptic.Curve, n *big.Int) []uint64 {
|
||||
words := (curve.Params().BitSize + 31) / 32
|
||||
ret := make([]uint64, words)
|
||||
bytes := n.Bytes()
|
||||
for i, b := range bytes {
|
||||
i = len(bytes) - i - 1
|
||||
ret[i/4] |= uint64(b) << (8 * (i % 4))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func writeIndent(w io.Writer, indent int) error {
|
||||
for i := 0; i < indent; i++ {
|
||||
if _, err := io.WriteString(w, " "); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeWords(w io.Writer, words []uint64, wrap, indent int, format func(uint64) string) error {
|
||||
if _, err := io.WriteString(w, "{"); err != nil {
|
||||
return err
|
||||
}
|
||||
for i, word := range words {
|
||||
if i > 0 {
|
||||
if i%wrap == 0 {
|
||||
if _, err := io.WriteString(w, ",\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeIndent(w, indent+1); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err := io.WriteString(w, ", "); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, err := io.WriteString(w, format(word)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := io.WriteString(w, "}"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeBNMont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error {
|
||||
n = toMontgomery(curve, n)
|
||||
return writeWords(w, bigIntToU64s(curve, n), 2, indent, func(word uint64) string {
|
||||
return fmt.Sprintf("TOBN(0x%08x, 0x%08x)", uint32(word>>32), uint32(word))
|
||||
})
|
||||
}
|
||||
|
||||
func writeU64Mont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error {
|
||||
n = toMontgomery(curve, n)
|
||||
return writeWords(w, bigIntToU64s(curve, n), 3, indent, func(word uint64) string {
|
||||
return fmt.Sprintf("0x%016x", word)
|
||||
})
|
||||
}
|
||||
|
||||
func writeU32Mont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error {
|
||||
n = toMontgomery(curve, n)
|
||||
return writeWords(w, bigIntToU32s(curve, n), 6, indent, func(word uint64) string {
|
||||
if word >= 1<<32 {
|
||||
panic(fmt.Sprintf("word too large: 0x%x", word))
|
||||
}
|
||||
return fmt.Sprintf("0x%08x", word)
|
||||
})
|
||||
}
|
||||
|
||||
type writeBigIntFunc func(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error
|
||||
|
||||
func writeTable(w io.Writer, curve elliptic.Curve, table [][2]*big.Int, isRoot bool, indent int, writeBigInt writeBigIntFunc) error {
|
||||
if _, err := io.WriteString(w, "{"); err != nil {
|
||||
return err
|
||||
}
|
||||
if isRoot {
|
||||
if _, err := io.WriteString(w, "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeIndent(w, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
indent++
|
||||
}
|
||||
for i, point := range table {
|
||||
if i != 0 {
|
||||
if _, err := io.WriteString(w, ",\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeIndent(w, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := io.WriteString(w, "{"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeBigInt(w, curve, point[0], indent+1); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.WriteString(w, ",\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeIndent(w, indent+1); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeBigInt(w, curve, point[1], indent+1); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.WriteString(w, "}"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := io.WriteString(w, "}"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeTables(w io.Writer, curve elliptic.Curve, tables [][][2]*big.Int, isRoot bool, indent int, writeBigInt writeBigIntFunc) error {
|
||||
if _, err := io.WriteString(w, "{"); err != nil {
|
||||
return err
|
||||
}
|
||||
if isRoot {
|
||||
if _, err := io.WriteString(w, "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeIndent(w, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
indent++
|
||||
}
|
||||
for i, table := range tables {
|
||||
if i != 0 {
|
||||
if _, err := io.WriteString(w, ",\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeIndent(w, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := writeTable(w, curve, table, false, indent, writeBigInt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := io.WriteString(w, "}"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+73
-65
@@ -73,15 +73,21 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
size_t ec_point_to_bytes(const EC_GROUP *group, const EC_AFFINE *point,
|
||||
point_conversion_form_t form, uint8_t *buf,
|
||||
size_t len) {
|
||||
static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
|
||||
const EC_RAW_POINT *point,
|
||||
point_conversion_form_t form,
|
||||
uint8_t *buf, size_t len) {
|
||||
if (form != POINT_CONVERSION_COMPRESSED &&
|
||||
form != POINT_CONVERSION_UNCOMPRESSED) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ec_GFp_simple_is_at_infinity(group, point)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t field_len = BN_num_bytes(&group->field);
|
||||
size_t output_len = 1 /* type byte */ + field_len;
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
||||
@@ -96,89 +102,79 @@ size_t ec_point_to_bytes(const EC_GROUP *group, const EC_AFFINE *point,
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t y_buf[EC_MAX_BYTES];
|
||||
size_t field_len_out;
|
||||
ec_felem_to_bytes(group, buf + 1, &field_len_out, &point->X);
|
||||
assert(field_len_out == field_len);
|
||||
if (!ec_point_get_affine_coordinate_bytes(
|
||||
group, buf + 1 /* x */,
|
||||
form == POINT_CONVERSION_COMPRESSED ? y_buf : buf + 1 + field_len,
|
||||
&field_len_out, field_len, point)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
||||
ec_felem_to_bytes(group, buf + 1 + field_len, &field_len_out, &point->Y);
|
||||
assert(field_len_out == field_len);
|
||||
buf[0] = form;
|
||||
if (field_len_out != field_len) {
|
||||
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (form == POINT_CONVERSION_COMPRESSED) {
|
||||
buf[0] = form + (y_buf[field_len - 1] & 1);
|
||||
} else {
|
||||
uint8_t y_buf[EC_MAX_BYTES];
|
||||
ec_felem_to_bytes(group, y_buf, &field_len_out, &point->Y);
|
||||
buf[0] = form + (y_buf[field_len_out - 1] & 1);
|
||||
buf[0] = form;
|
||||
}
|
||||
}
|
||||
|
||||
return output_len;
|
||||
}
|
||||
|
||||
int ec_point_from_uncompressed(const EC_GROUP *group, EC_AFFINE *out,
|
||||
const uint8_t *in, size_t len) {
|
||||
const size_t field_len = BN_num_bytes(&group->field);
|
||||
if (len != 1 + 2 * field_len || in[0] != POINT_CONVERSION_UNCOMPRESSED) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EC_FELEM x, y;
|
||||
if (!ec_felem_from_bytes(group, &x, in + 1, field_len) ||
|
||||
!ec_felem_from_bytes(group, &y, in + 1 + field_len, field_len) ||
|
||||
!ec_point_set_affine_coordinates(group, out, &x, &y)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
const uint8_t *buf, size_t len,
|
||||
BN_CTX *ctx) {
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int ret = 0, used_ctx = 0;
|
||||
|
||||
if (len == 0) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
point_conversion_form_t form = buf[0];
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
||||
EC_AFFINE affine;
|
||||
if (!ec_point_from_uncompressed(group, &affine, buf, len)) {
|
||||
// In the event of an error, defend against the caller not checking the
|
||||
// return value by setting a known safe value.
|
||||
ec_set_to_safe_point(group, &point->raw);
|
||||
return 0;
|
||||
}
|
||||
ec_affine_to_jacobian(group, &point->raw, &affine);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int y_bit = form & 1;
|
||||
const size_t field_len = BN_num_bytes(&group->field);
|
||||
form = form & ~1u;
|
||||
if (form != POINT_CONVERSION_COMPRESSED ||
|
||||
len != 1 /* type byte */ + field_len) {
|
||||
form = form & ~1U;
|
||||
if ((form != POINT_CONVERSION_COMPRESSED &&
|
||||
form != POINT_CONVERSION_UNCOMPRESSED) ||
|
||||
(form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
const size_t field_len = BN_num_bytes(&group->field);
|
||||
size_t enc_len = 1 /* type byte */ + field_len;
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
||||
// Uncompressed points have a second coordinate.
|
||||
enc_len += field_len;
|
||||
}
|
||||
|
||||
if (len != enc_len) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
|
||||
// TODO(davidben): Integrate compressed coordinates with the lower-level EC
|
||||
// abstractions. This requires a way to compute square roots, which is tricky
|
||||
// for primes which are not 3 (mod 4), namely P-224 and custom curves. P-224's
|
||||
// prime is particularly inconvenient for compressed coordinates. See
|
||||
// https://cr.yp.to/papers/sqroot.pdf
|
||||
BN_CTX *new_ctx = NULL;
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
BN_CTX_start(ctx);
|
||||
used_ctx = 1;
|
||||
BIGNUM *x = BN_CTX_get(ctx);
|
||||
if (x == NULL || !BN_bin2bn(buf + 1, field_len, x)) {
|
||||
BIGNUM *y = BN_CTX_get(ctx);
|
||||
if (x == NULL || y == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_bin2bn(buf + 1, field_len, x)) {
|
||||
goto err;
|
||||
}
|
||||
if (BN_ucmp(x, &group->field) >= 0) {
|
||||
@@ -186,14 +182,30 @@ static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
|
||||
goto err;
|
||||
if (form == POINT_CONVERSION_COMPRESSED) {
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) {
|
||||
goto err;
|
||||
}
|
||||
if (BN_ucmp(y, &group->field) >= 0) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (used_ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
}
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
@@ -214,11 +226,7 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
EC_AFFINE affine;
|
||||
if (!ec_jacobian_to_affine(group, &affine, &point->raw)) {
|
||||
return 0;
|
||||
}
|
||||
return ec_point_to_bytes(group, &affine, form, buf, len);
|
||||
return ec_GFp_simple_point2oct(group, &point->raw, form, buf, len);
|
||||
}
|
||||
|
||||
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
|
||||
|
||||
@@ -866,7 +866,7 @@ static void p224_select_point(const uint64_t idx, size_t size,
|
||||
}
|
||||
|
||||
// p224_get_bit returns the |i|th bit in |in|
|
||||
static crypto_word_t p224_get_bit(const p224_felem_bytearray in, size_t i) {
|
||||
static char p224_get_bit(const p224_felem_bytearray in, size_t i) {
|
||||
if (i >= 224) {
|
||||
return 0;
|
||||
}
|
||||
@@ -977,13 +977,13 @@ static void ec_GFp_nistp224_point_mul(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
|
||||
// Add every 5 doublings.
|
||||
if (i % 5 == 0) {
|
||||
crypto_word_t bits = p224_get_bit(scalar->bytes, i + 4) << 5;
|
||||
uint64_t bits = p224_get_bit(scalar->bytes, i + 4) << 5;
|
||||
bits |= p224_get_bit(scalar->bytes, i + 3) << 4;
|
||||
bits |= p224_get_bit(scalar->bytes, i + 2) << 3;
|
||||
bits |= p224_get_bit(scalar->bytes, i + 1) << 2;
|
||||
bits |= p224_get_bit(scalar->bytes, i) << 1;
|
||||
bits |= p224_get_bit(scalar->bytes, i - 1);
|
||||
crypto_word_t sign, digit;
|
||||
uint8_t sign, digit;
|
||||
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
|
||||
|
||||
// Select the point to add or subtract.
|
||||
@@ -1022,7 +1022,7 @@ static void ec_GFp_nistp224_point_mul_base(const EC_GROUP *group,
|
||||
}
|
||||
|
||||
// First, look 28 bits upwards.
|
||||
crypto_word_t bits = p224_get_bit(scalar->bytes, i + 196) << 3;
|
||||
uint64_t bits = p224_get_bit(scalar->bytes, i + 196) << 3;
|
||||
bits |= p224_get_bit(scalar->bytes, i + 140) << 2;
|
||||
bits |= p224_get_bit(scalar->bytes, i + 84) << 1;
|
||||
bits |= p224_get_bit(scalar->bytes, i + 28);
|
||||
@@ -1080,15 +1080,14 @@ static void ec_GFp_nistp224_point_mul_public(const EC_GROUP *group,
|
||||
// Add multiples of the generator.
|
||||
if (i <= 27) {
|
||||
// First, look 28 bits upwards.
|
||||
crypto_word_t bits = p224_get_bit(g_scalar->bytes, i + 196) << 3;
|
||||
uint64_t bits = p224_get_bit(g_scalar->bytes, i + 196) << 3;
|
||||
bits |= p224_get_bit(g_scalar->bytes, i + 140) << 2;
|
||||
bits |= p224_get_bit(g_scalar->bytes, i + 84) << 1;
|
||||
bits |= p224_get_bit(g_scalar->bytes, i + 28);
|
||||
|
||||
size_t index = (size_t)bits;
|
||||
p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
|
||||
g_p224_pre_comp[1][index][0], g_p224_pre_comp[1][index][1],
|
||||
g_p224_pre_comp[1][index][2]);
|
||||
g_p224_pre_comp[1][bits][0], g_p224_pre_comp[1][bits][1],
|
||||
g_p224_pre_comp[1][bits][2]);
|
||||
assert(!skip);
|
||||
|
||||
// Second, look at the current position.
|
||||
@@ -1096,21 +1095,20 @@ static void ec_GFp_nistp224_point_mul_public(const EC_GROUP *group,
|
||||
bits |= p224_get_bit(g_scalar->bytes, i + 112) << 2;
|
||||
bits |= p224_get_bit(g_scalar->bytes, i + 56) << 1;
|
||||
bits |= p224_get_bit(g_scalar->bytes, i);
|
||||
index = (size_t)bits;
|
||||
p224_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
|
||||
g_p224_pre_comp[0][index][0], g_p224_pre_comp[0][index][1],
|
||||
g_p224_pre_comp[0][index][2]);
|
||||
g_p224_pre_comp[0][bits][0], g_p224_pre_comp[0][bits][1],
|
||||
g_p224_pre_comp[0][bits][2]);
|
||||
}
|
||||
|
||||
// Incorporate |p_scalar| every 5 doublings.
|
||||
if (i % 5 == 0) {
|
||||
crypto_word_t bits = p224_get_bit(p_scalar->bytes, i + 4) << 5;
|
||||
uint64_t bits = p224_get_bit(p_scalar->bytes, i + 4) << 5;
|
||||
bits |= p224_get_bit(p_scalar->bytes, i + 3) << 4;
|
||||
bits |= p224_get_bit(p_scalar->bytes, i + 2) << 3;
|
||||
bits |= p224_get_bit(p_scalar->bytes, i + 1) << 2;
|
||||
bits |= p224_get_bit(p_scalar->bytes, i) << 1;
|
||||
bits |= p224_get_bit(p_scalar->bytes, i - 1);
|
||||
crypto_word_t sign, digit;
|
||||
uint8_t sign, digit;
|
||||
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
|
||||
|
||||
// Select the point to add or subtract.
|
||||
@@ -1156,6 +1154,16 @@ static void ec_GFp_nistp224_felem_sqr(const EC_GROUP *group, EC_FELEM *r,
|
||||
p224_felem_to_generic(r, felem);
|
||||
}
|
||||
|
||||
static int ec_GFp_nistp224_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out,
|
||||
const BIGNUM *in) {
|
||||
return bn_copy_words(out->words, group->field.width, in);
|
||||
}
|
||||
|
||||
static int ec_GFp_nistp224_felem_to_bignum(const EC_GROUP *group, BIGNUM *out,
|
||||
const EC_FELEM *in) {
|
||||
return bn_set_words(out, in->words, group->field.width);
|
||||
}
|
||||
|
||||
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
|
||||
out->group_init = ec_GFp_simple_group_init;
|
||||
out->group_finish = ec_GFp_simple_group_finish;
|
||||
@@ -1169,11 +1177,10 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
|
||||
out->mul_public = ec_GFp_nistp224_point_mul_public;
|
||||
out->felem_mul = ec_GFp_nistp224_felem_mul;
|
||||
out->felem_sqr = ec_GFp_nistp224_felem_sqr;
|
||||
out->felem_to_bytes = ec_GFp_simple_felem_to_bytes;
|
||||
out->felem_from_bytes = ec_GFp_simple_felem_from_bytes;
|
||||
out->scalar_inv0_montgomery = ec_simple_scalar_inv0_montgomery;
|
||||
out->scalar_to_montgomery_inv_vartime =
|
||||
ec_simple_scalar_to_montgomery_inv_vartime;
|
||||
out->bignum_to_felem = ec_GFp_nistp224_bignum_to_felem;
|
||||
out->felem_to_bignum = ec_GFp_nistp224_felem_to_bignum;
|
||||
out->scalar_inv_montgomery = ec_simple_scalar_inv_montgomery;
|
||||
out->scalar_inv_montgomery_vartime = ec_GFp_simple_mont_inv_mod_ord_vartime;
|
||||
out->cmp_x_coordinate = ec_GFp_simple_cmp_x_coordinate;
|
||||
}
|
||||
|
||||
|
||||
+9485
-9481
File diff suppressed because it is too large
Load Diff
@@ -50,8 +50,8 @@ static const BN_ULONG ONE[P256_LIMBS] = {
|
||||
|
||||
// Recode window to a signed digit, see |ec_GFp_nistp_recode_scalar_bits| in
|
||||
// util.c for details
|
||||
static crypto_word_t booth_recode_w5(crypto_word_t in) {
|
||||
crypto_word_t s, d;
|
||||
static unsigned booth_recode_w5(unsigned in) {
|
||||
unsigned s, d;
|
||||
|
||||
s = ~((in >> 5) - 1);
|
||||
d = (1 << 6) - in - 1;
|
||||
@@ -61,8 +61,8 @@ static crypto_word_t booth_recode_w5(crypto_word_t in) {
|
||||
return (d << 1) + (s & 1);
|
||||
}
|
||||
|
||||
static crypto_word_t booth_recode_w7(crypto_word_t in) {
|
||||
crypto_word_t s, d;
|
||||
static unsigned booth_recode_w7(unsigned in) {
|
||||
unsigned s, d;
|
||||
|
||||
s = ~((in >> 7) - 1);
|
||||
d = (1 << 8) - in - 1;
|
||||
@@ -117,73 +117,86 @@ static BN_ULONG is_not_zero(BN_ULONG in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
// ecp_nistz256_mod_inverse_sqr_mont sets |r| to (|in| * 2^-256)^-2 * 2^256 mod
|
||||
// p. That is, |r| is the modular inverse square of |in| for input and output in
|
||||
// the Montgomery domain.
|
||||
static void ecp_nistz256_mod_inverse_sqr_mont(BN_ULONG r[P256_LIMBS],
|
||||
const BN_ULONG in[P256_LIMBS]) {
|
||||
// This implements the addition chain described in
|
||||
// https://briansmith.org/ecc-inversion-addition-chains-01#p256_field_inversion
|
||||
BN_ULONG x2[P256_LIMBS], x3[P256_LIMBS], x6[P256_LIMBS], x12[P256_LIMBS],
|
||||
x15[P256_LIMBS], x30[P256_LIMBS], x32[P256_LIMBS];
|
||||
ecp_nistz256_sqr_mont(x2, in); // 2^2 - 2^1
|
||||
ecp_nistz256_mul_mont(x2, x2, in); // 2^2 - 2^0
|
||||
// ecp_nistz256_mod_inverse_mont sets |r| to (|in| * 2^-256)^-1 * 2^256 mod p.
|
||||
// That is, |r| is the modular inverse of |in| for input and output in the
|
||||
// Montgomery domain.
|
||||
static void ecp_nistz256_mod_inverse_mont(BN_ULONG r[P256_LIMBS],
|
||||
const BN_ULONG in[P256_LIMBS]) {
|
||||
/* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff
|
||||
ffffffff
|
||||
We use FLT and used poly-2 as exponent */
|
||||
BN_ULONG p2[P256_LIMBS];
|
||||
BN_ULONG p4[P256_LIMBS];
|
||||
BN_ULONG p8[P256_LIMBS];
|
||||
BN_ULONG p16[P256_LIMBS];
|
||||
BN_ULONG p32[P256_LIMBS];
|
||||
BN_ULONG res[P256_LIMBS];
|
||||
int i;
|
||||
|
||||
ecp_nistz256_sqr_mont(x3, x2); // 2^3 - 2^1
|
||||
ecp_nistz256_mul_mont(x3, x3, in); // 2^3 - 2^0
|
||||
ecp_nistz256_sqr_mont(res, in);
|
||||
ecp_nistz256_mul_mont(p2, res, in); // 3*p
|
||||
|
||||
ecp_nistz256_sqr_mont(x6, x3);
|
||||
for (int i = 1; i < 3; i++) {
|
||||
ecp_nistz256_sqr_mont(x6, x6);
|
||||
} // 2^6 - 2^3
|
||||
ecp_nistz256_mul_mont(x6, x6, x3); // 2^6 - 2^0
|
||||
ecp_nistz256_sqr_mont(res, p2);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_mul_mont(p4, res, p2); // f*p
|
||||
|
||||
ecp_nistz256_sqr_mont(x12, x6);
|
||||
for (int i = 1; i < 6; i++) {
|
||||
ecp_nistz256_sqr_mont(x12, x12);
|
||||
} // 2^12 - 2^6
|
||||
ecp_nistz256_mul_mont(x12, x12, x6); // 2^12 - 2^0
|
||||
ecp_nistz256_sqr_mont(res, p4);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_mul_mont(p8, res, p4); // ff*p
|
||||
|
||||
ecp_nistz256_sqr_mont(x15, x12);
|
||||
for (int i = 1; i < 3; i++) {
|
||||
ecp_nistz256_sqr_mont(x15, x15);
|
||||
} // 2^15 - 2^3
|
||||
ecp_nistz256_mul_mont(x15, x15, x3); // 2^15 - 2^0
|
||||
ecp_nistz256_sqr_mont(res, p8);
|
||||
for (i = 0; i < 7; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(p16, res, p8); // ffff*p
|
||||
|
||||
ecp_nistz256_sqr_mont(x30, x15);
|
||||
for (int i = 1; i < 15; i++) {
|
||||
ecp_nistz256_sqr_mont(x30, x30);
|
||||
} // 2^30 - 2^15
|
||||
ecp_nistz256_mul_mont(x30, x30, x15); // 2^30 - 2^0
|
||||
ecp_nistz256_sqr_mont(res, p16);
|
||||
for (i = 0; i < 15; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(p32, res, p16); // ffffffff*p
|
||||
|
||||
ecp_nistz256_sqr_mont(x32, x30);
|
||||
ecp_nistz256_sqr_mont(x32, x32); // 2^32 - 2^2
|
||||
ecp_nistz256_mul_mont(x32, x32, x2); // 2^32 - 2^0
|
||||
ecp_nistz256_sqr_mont(res, p32);
|
||||
for (i = 0; i < 31; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(res, res, in);
|
||||
|
||||
BN_ULONG ret[P256_LIMBS];
|
||||
ecp_nistz256_sqr_mont(ret, x32);
|
||||
for (int i = 1; i < 31 + 1; i++) {
|
||||
ecp_nistz256_sqr_mont(ret, ret);
|
||||
} // 2^64 - 2^32
|
||||
ecp_nistz256_mul_mont(ret, ret, in); // 2^64 - 2^32 + 2^0
|
||||
for (i = 0; i < 32 * 4; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(res, res, p32);
|
||||
|
||||
for (int i = 0; i < 96 + 32; i++) {
|
||||
ecp_nistz256_sqr_mont(ret, ret);
|
||||
} // 2^192 - 2^160 + 2^128
|
||||
ecp_nistz256_mul_mont(ret, ret, x32); // 2^192 - 2^160 + 2^128 + 2^32 - 2^0
|
||||
for (i = 0; i < 32; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(res, res, p32);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ecp_nistz256_sqr_mont(ret, ret);
|
||||
} // 2^224 - 2^192 + 2^160 + 2^64 - 2^32
|
||||
ecp_nistz256_mul_mont(ret, ret, x32); // 2^224 - 2^192 + 2^160 + 2^64 - 2^0
|
||||
for (i = 0; i < 16; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(res, res, p16);
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
ecp_nistz256_sqr_mont(ret, ret);
|
||||
} // 2^254 - 2^222 + 2^190 + 2^94 - 2^30
|
||||
ecp_nistz256_mul_mont(ret, ret, x30); // 2^254 - 2^222 + 2^190 + 2^94 - 2^0
|
||||
for (i = 0; i < 8; i++) {
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
}
|
||||
ecp_nistz256_mul_mont(res, res, p8);
|
||||
|
||||
ecp_nistz256_sqr_mont(ret, ret);
|
||||
ecp_nistz256_sqr_mont(r, ret); // 2^256 - 2^224 + 2^192 + 2^96 - 2^2
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_mul_mont(res, res, p4);
|
||||
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_mul_mont(res, res, p2);
|
||||
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_sqr_mont(res, res);
|
||||
ecp_nistz256_mul_mont(r, res, in);
|
||||
}
|
||||
|
||||
// r = p * p_scalar
|
||||
@@ -194,8 +207,8 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
|
||||
assert(p_scalar != NULL);
|
||||
assert(group->field.width == P256_LIMBS);
|
||||
|
||||
static const size_t kWindowSize = 5;
|
||||
static const crypto_word_t kMask = (1 << (5 /* kWindowSize */ + 1)) - 1;
|
||||
static const unsigned kWindowSize = 5;
|
||||
static const unsigned kMask = (1 << (5 /* kWindowSize */ + 1)) - 1;
|
||||
|
||||
// A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should
|
||||
// add no more than 63 bytes of overhead. Thus, |table| should require
|
||||
@@ -232,17 +245,17 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
|
||||
|
||||
BN_ULONG tmp[P256_LIMBS];
|
||||
alignas(32) P256_POINT h;
|
||||
size_t index = 255;
|
||||
crypto_word_t wvalue = p_str[(index - 1) / 8];
|
||||
unsigned index = 255;
|
||||
unsigned wvalue = p_str[(index - 1) / 8];
|
||||
wvalue = (wvalue >> ((index - 1) % 8)) & kMask;
|
||||
|
||||
ecp_nistz256_select_w5(r, table, booth_recode_w5(wvalue) >> 1);
|
||||
|
||||
while (index >= 5) {
|
||||
if (index != 255) {
|
||||
size_t off = (index - 1) / 8;
|
||||
unsigned off = (index - 1) / 8;
|
||||
|
||||
wvalue = (crypto_word_t)p_str[off] | (crypto_word_t)p_str[off + 1] << 8;
|
||||
wvalue = p_str[off] | p_str[off + 1] << 8;
|
||||
wvalue = (wvalue >> ((index - 1) % 8)) & kMask;
|
||||
|
||||
wvalue = booth_recode_w5(wvalue);
|
||||
@@ -283,22 +296,21 @@ typedef union {
|
||||
P256_POINT_AFFINE a;
|
||||
} p256_point_union_t;
|
||||
|
||||
static crypto_word_t calc_first_wvalue(size_t *index, const uint8_t p_str[33]) {
|
||||
static const size_t kWindowSize = 7;
|
||||
static const crypto_word_t kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
|
||||
static unsigned calc_first_wvalue(unsigned *index, const uint8_t p_str[33]) {
|
||||
static const unsigned kWindowSize = 7;
|
||||
static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
|
||||
*index = kWindowSize;
|
||||
|
||||
crypto_word_t wvalue = (p_str[0] << 1) & kMask;
|
||||
unsigned wvalue = (p_str[0] << 1) & kMask;
|
||||
return booth_recode_w7(wvalue);
|
||||
}
|
||||
|
||||
static crypto_word_t calc_wvalue(size_t *index, const uint8_t p_str[33]) {
|
||||
static const size_t kWindowSize = 7;
|
||||
static const crypto_word_t kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
|
||||
static unsigned calc_wvalue(unsigned *index, const uint8_t p_str[33]) {
|
||||
static const unsigned kWindowSize = 7;
|
||||
static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
|
||||
|
||||
const size_t off = (*index - 1) / 8;
|
||||
crypto_word_t wvalue =
|
||||
(crypto_word_t)p_str[off] | (crypto_word_t)p_str[off + 1] << 8;
|
||||
const unsigned off = (*index - 1) / 8;
|
||||
unsigned wvalue = p_str[off] | p_str[off + 1] << 8;
|
||||
wvalue = (wvalue >> ((*index - 1) % 8)) & kMask;
|
||||
*index += kWindowSize;
|
||||
|
||||
@@ -326,8 +338,8 @@ static void ecp_nistz256_point_mul_base(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
p_str[32] = 0;
|
||||
|
||||
// First window
|
||||
size_t index = 0;
|
||||
crypto_word_t wvalue = calc_first_wvalue(&index, p_str);
|
||||
unsigned index = 0;
|
||||
unsigned wvalue = calc_first_wvalue(&index, p_str);
|
||||
|
||||
ecp_nistz256_select_w7(&p.a, ecp_nistz256_precomputed[0], wvalue >> 1);
|
||||
ecp_nistz256_neg(p.p.Z, p.p.Y);
|
||||
@@ -371,8 +383,8 @@ static void ecp_nistz256_points_mul_public(const EC_GROUP *group,
|
||||
p_str[32] = 0;
|
||||
|
||||
// First window
|
||||
size_t index = 0;
|
||||
size_t wvalue = calc_first_wvalue(&index, p_str);
|
||||
unsigned index = 0;
|
||||
unsigned wvalue = calc_first_wvalue(&index, p_str);
|
||||
|
||||
// Convert |p| from affine to Jacobian coordinates. We set Z to zero if |p|
|
||||
// is infinity and |ONE| otherwise. |p| was computed from the table, so it
|
||||
@@ -428,17 +440,24 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group,
|
||||
}
|
||||
|
||||
BN_ULONG z_inv2[P256_LIMBS];
|
||||
BN_ULONG z_inv3[P256_LIMBS];
|
||||
assert(group->field.width == P256_LIMBS);
|
||||
ecp_nistz256_mod_inverse_sqr_mont(z_inv2, point->Z.words);
|
||||
ecp_nistz256_mod_inverse_mont(z_inv3, point->Z.words);
|
||||
ecp_nistz256_sqr_mont(z_inv2, z_inv3);
|
||||
|
||||
// Instead of using |ecp_nistz256_from_mont| to convert the |x| coordinate
|
||||
// and then calling |ecp_nistz256_from_mont| again to convert the |y|
|
||||
// coordinate below, convert the common factor |z_inv2| once now, saving one
|
||||
// reduction.
|
||||
ecp_nistz256_from_mont(z_inv2, z_inv2);
|
||||
|
||||
if (x != NULL) {
|
||||
ecp_nistz256_mul_mont(x->words, z_inv2, point->X.words);
|
||||
}
|
||||
|
||||
if (y != NULL) {
|
||||
ecp_nistz256_sqr_mont(z_inv2, z_inv2); // z^-4
|
||||
ecp_nistz256_mul_mont(y->words, point->Y.words, point->Z.words); // y * z
|
||||
ecp_nistz256_mul_mont(y->words, y->words, z_inv2); // y * z^-3
|
||||
ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
|
||||
ecp_nistz256_mul_mont(y->words, z_inv3, point->Y.words);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -471,8 +490,8 @@ static void ecp_nistz256_dbl(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
OPENSSL_memcpy(r->Z.words, a.Z, P256_LIMBS * sizeof(BN_ULONG));
|
||||
}
|
||||
|
||||
static void ecp_nistz256_inv0_mod_ord(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_SCALAR *in) {
|
||||
static void ecp_nistz256_inv_mod_ord(const EC_GROUP *group, EC_SCALAR *out,
|
||||
const EC_SCALAR *in) {
|
||||
// table[i] stores a power of |in| corresponding to the matching enum value.
|
||||
enum {
|
||||
// The following indices specify the power in binary.
|
||||
@@ -552,12 +571,12 @@ static void ecp_nistz256_inv0_mod_ord(const EC_GROUP *group, EC_SCALAR *out,
|
||||
}
|
||||
}
|
||||
|
||||
static int ecp_nistz256_scalar_to_montgomery_inv_vartime(const EC_GROUP *group,
|
||||
static int ecp_nistz256_mont_inv_mod_ord_vartime(const EC_GROUP *group,
|
||||
EC_SCALAR *out,
|
||||
const EC_SCALAR *in) {
|
||||
if ((OPENSSL_ia32cap_get()[1] & (1 << 28)) == 0) {
|
||||
// No AVX support; fallback to generic code.
|
||||
return ec_simple_scalar_to_montgomery_inv_vartime(group, out, in);
|
||||
return ec_GFp_simple_mont_inv_mod_ord_vartime(group, out, in);
|
||||
}
|
||||
|
||||
assert(group->order.width == P256_LIMBS);
|
||||
@@ -621,11 +640,10 @@ DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistz256_method) {
|
||||
out->mul_public = ecp_nistz256_points_mul_public;
|
||||
out->felem_mul = ec_GFp_mont_felem_mul;
|
||||
out->felem_sqr = ec_GFp_mont_felem_sqr;
|
||||
out->felem_to_bytes = ec_GFp_mont_felem_to_bytes;
|
||||
out->felem_from_bytes = ec_GFp_mont_felem_from_bytes;
|
||||
out->scalar_inv0_montgomery = ecp_nistz256_inv0_mod_ord;
|
||||
out->scalar_to_montgomery_inv_vartime =
|
||||
ecp_nistz256_scalar_to_montgomery_inv_vartime;
|
||||
out->bignum_to_felem = ec_GFp_mont_bignum_to_felem;
|
||||
out->felem_to_bignum = ec_GFp_mont_felem_to_bignum;
|
||||
out->scalar_inv_montgomery = ecp_nistz256_inv_mod_ord;
|
||||
out->scalar_inv_montgomery_vartime = ecp_nistz256_mont_inv_mod_ord_vartime;
|
||||
out->cmp_x_coordinate = ecp_nistz256_cmp_x_coordinate;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,740 +0,0 @@
|
||||
/* Copyright (c) 2020, 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. */
|
||||
|
||||
// An implementation of the NIST P-256 elliptic curve point multiplication.
|
||||
// 256-bit Montgomery form for 64 and 32-bit. Field operations are generated by
|
||||
// Fiat, which lives in //third_party/fiat.
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../internal.h"
|
||||
#include "../delocate.h"
|
||||
#include "./internal.h"
|
||||
|
||||
|
||||
// MSVC does not implement uint128_t, and crashes with intrinsics
|
||||
#if defined(BORINGSSL_HAS_UINT128)
|
||||
#define BORINGSSL_NISTP256_64BIT 1
|
||||
#include "../../../third_party/fiat/p256_64.h"
|
||||
#else
|
||||
#include "../../../third_party/fiat/p256_32.h"
|
||||
#endif
|
||||
|
||||
|
||||
// utility functions, handwritten
|
||||
|
||||
#if defined(BORINGSSL_NISTP256_64BIT)
|
||||
#define FIAT_P256_NLIMBS 4
|
||||
typedef uint64_t fiat_p256_limb_t;
|
||||
typedef uint64_t fiat_p256_felem[FIAT_P256_NLIMBS];
|
||||
static const fiat_p256_felem fiat_p256_one = {0x1, 0xffffffff00000000,
|
||||
0xffffffffffffffff, 0xfffffffe};
|
||||
#else // 64BIT; else 32BIT
|
||||
#define FIAT_P256_NLIMBS 8
|
||||
typedef uint32_t fiat_p256_limb_t;
|
||||
typedef uint32_t fiat_p256_felem[FIAT_P256_NLIMBS];
|
||||
static const fiat_p256_felem fiat_p256_one = {
|
||||
0x1, 0x0, 0x0, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0x0};
|
||||
#endif // 64BIT
|
||||
|
||||
|
||||
static fiat_p256_limb_t fiat_p256_nz(
|
||||
const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) {
|
||||
fiat_p256_limb_t ret;
|
||||
fiat_p256_nonzero(&ret, in1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fiat_p256_copy(fiat_p256_limb_t out[FIAT_P256_NLIMBS],
|
||||
const fiat_p256_limb_t in1[FIAT_P256_NLIMBS]) {
|
||||
for (size_t i = 0; i < FIAT_P256_NLIMBS; i++) {
|
||||
out[i] = in1[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void fiat_p256_cmovznz(fiat_p256_limb_t out[FIAT_P256_NLIMBS],
|
||||
fiat_p256_limb_t t,
|
||||
const fiat_p256_limb_t z[FIAT_P256_NLIMBS],
|
||||
const fiat_p256_limb_t nz[FIAT_P256_NLIMBS]) {
|
||||
fiat_p256_selectznz(out, !!t, z, nz);
|
||||
}
|
||||
|
||||
static void fiat_p256_from_generic(fiat_p256_felem out, const EC_FELEM *in) {
|
||||
fiat_p256_from_bytes(out, in->bytes);
|
||||
}
|
||||
|
||||
static void fiat_p256_to_generic(EC_FELEM *out, const fiat_p256_felem in) {
|
||||
// This works because 256 is a multiple of 64, so there are no excess bytes to
|
||||
// zero when rounding up to |BN_ULONG|s.
|
||||
OPENSSL_STATIC_ASSERT(
|
||||
256 / 8 == sizeof(BN_ULONG) * ((256 + BN_BITS2 - 1) / BN_BITS2),
|
||||
"fiat_p256_to_bytes leaves bytes uninitialized");
|
||||
fiat_p256_to_bytes(out->bytes, in);
|
||||
}
|
||||
|
||||
// fiat_p256_inv_square calculates |out| = |in|^{-2}
|
||||
//
|
||||
// Based on Fermat's Little Theorem:
|
||||
// a^p = a (mod p)
|
||||
// a^{p-1} = 1 (mod p)
|
||||
// a^{p-3} = a^{-2} (mod p)
|
||||
static void fiat_p256_inv_square(fiat_p256_felem out,
|
||||
const fiat_p256_felem in) {
|
||||
// This implements the addition chain described in
|
||||
// https://briansmith.org/ecc-inversion-addition-chains-01#p256_field_inversion
|
||||
fiat_p256_felem x2, x3, x6, x12, x15, x30, x32;
|
||||
fiat_p256_square(x2, in); // 2^2 - 2^1
|
||||
fiat_p256_mul(x2, x2, in); // 2^2 - 2^0
|
||||
|
||||
fiat_p256_square(x3, x2); // 2^3 - 2^1
|
||||
fiat_p256_mul(x3, x3, in); // 2^3 - 2^0
|
||||
|
||||
fiat_p256_square(x6, x3);
|
||||
for (int i = 1; i < 3; i++) {
|
||||
fiat_p256_square(x6, x6);
|
||||
} // 2^6 - 2^3
|
||||
fiat_p256_mul(x6, x6, x3); // 2^6 - 2^0
|
||||
|
||||
fiat_p256_square(x12, x6);
|
||||
for (int i = 1; i < 6; i++) {
|
||||
fiat_p256_square(x12, x12);
|
||||
} // 2^12 - 2^6
|
||||
fiat_p256_mul(x12, x12, x6); // 2^12 - 2^0
|
||||
|
||||
fiat_p256_square(x15, x12);
|
||||
for (int i = 1; i < 3; i++) {
|
||||
fiat_p256_square(x15, x15);
|
||||
} // 2^15 - 2^3
|
||||
fiat_p256_mul(x15, x15, x3); // 2^15 - 2^0
|
||||
|
||||
fiat_p256_square(x30, x15);
|
||||
for (int i = 1; i < 15; i++) {
|
||||
fiat_p256_square(x30, x30);
|
||||
} // 2^30 - 2^15
|
||||
fiat_p256_mul(x30, x30, x15); // 2^30 - 2^0
|
||||
|
||||
fiat_p256_square(x32, x30);
|
||||
fiat_p256_square(x32, x32); // 2^32 - 2^2
|
||||
fiat_p256_mul(x32, x32, x2); // 2^32 - 2^0
|
||||
|
||||
fiat_p256_felem ret;
|
||||
fiat_p256_square(ret, x32);
|
||||
for (int i = 1; i < 31 + 1; i++) {
|
||||
fiat_p256_square(ret, ret);
|
||||
} // 2^64 - 2^32
|
||||
fiat_p256_mul(ret, ret, in); // 2^64 - 2^32 + 2^0
|
||||
|
||||
for (int i = 0; i < 96 + 32; i++) {
|
||||
fiat_p256_square(ret, ret);
|
||||
} // 2^192 - 2^160 + 2^128
|
||||
fiat_p256_mul(ret, ret, x32); // 2^192 - 2^160 + 2^128 + 2^32 - 2^0
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
fiat_p256_square(ret, ret);
|
||||
} // 2^224 - 2^192 + 2^160 + 2^64 - 2^32
|
||||
fiat_p256_mul(ret, ret, x32); // 2^224 - 2^192 + 2^160 + 2^64 - 2^0
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
fiat_p256_square(ret, ret);
|
||||
} // 2^254 - 2^222 + 2^190 + 2^94 - 2^30
|
||||
fiat_p256_mul(ret, ret, x30); // 2^254 - 2^222 + 2^190 + 2^94 - 2^0
|
||||
|
||||
fiat_p256_square(ret, ret);
|
||||
fiat_p256_square(out, ret); // 2^256 - 2^224 + 2^192 + 2^96 - 2^2
|
||||
}
|
||||
|
||||
// Group operations
|
||||
// ----------------
|
||||
//
|
||||
// Building on top of the field operations we have the operations on the
|
||||
// elliptic curve group itself. Points on the curve are represented in Jacobian
|
||||
// coordinates.
|
||||
//
|
||||
// Both operations were transcribed to Coq and proven to correspond to naive
|
||||
// implementations using Affine coordinates, for all suitable fields. In the
|
||||
// Coq proofs, issues of constant-time execution and memory layout (aliasing)
|
||||
// conventions were not considered. Specification of affine coordinates:
|
||||
// <https://github.com/mit-plv/fiat-crypto/blob/79f8b5f39ed609339f0233098dee1a3c4e6b3080/src/Spec/WeierstrassCurve.v#L28>
|
||||
// As a sanity check, a proof that these points form a commutative group:
|
||||
// <https://github.com/mit-plv/fiat-crypto/blob/79f8b5f39ed609339f0233098dee1a3c4e6b3080/src/Curves/Weierstrass/AffineProofs.v#L33>
|
||||
|
||||
// fiat_p256_point_double calculates 2*(x_in, y_in, z_in)
|
||||
//
|
||||
// The method is taken from:
|
||||
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
|
||||
//
|
||||
// Coq transcription and correctness proof:
|
||||
// <https://github.com/mit-plv/fiat-crypto/blob/79f8b5f39ed609339f0233098dee1a3c4e6b3080/src/Curves/Weierstrass/Jacobian.v#L93>
|
||||
// <https://github.com/mit-plv/fiat-crypto/blob/79f8b5f39ed609339f0233098dee1a3c4e6b3080/src/Curves/Weierstrass/Jacobian.v#L201>
|
||||
//
|
||||
// Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
|
||||
// while x_out == y_in is not (maybe this works, but it's not tested).
|
||||
static void fiat_p256_point_double(fiat_p256_felem x_out, fiat_p256_felem y_out,
|
||||
fiat_p256_felem z_out,
|
||||
const fiat_p256_felem x_in,
|
||||
const fiat_p256_felem y_in,
|
||||
const fiat_p256_felem z_in) {
|
||||
fiat_p256_felem delta, gamma, beta, ftmp, ftmp2, tmptmp, alpha, fourbeta;
|
||||
// delta = z^2
|
||||
fiat_p256_square(delta, z_in);
|
||||
// gamma = y^2
|
||||
fiat_p256_square(gamma, y_in);
|
||||
// beta = x*gamma
|
||||
fiat_p256_mul(beta, x_in, gamma);
|
||||
|
||||
// alpha = 3*(x-delta)*(x+delta)
|
||||
fiat_p256_sub(ftmp, x_in, delta);
|
||||
fiat_p256_add(ftmp2, x_in, delta);
|
||||
|
||||
fiat_p256_add(tmptmp, ftmp2, ftmp2);
|
||||
fiat_p256_add(ftmp2, ftmp2, tmptmp);
|
||||
fiat_p256_mul(alpha, ftmp, ftmp2);
|
||||
|
||||
// x' = alpha^2 - 8*beta
|
||||
fiat_p256_square(x_out, alpha);
|
||||
fiat_p256_add(fourbeta, beta, beta);
|
||||
fiat_p256_add(fourbeta, fourbeta, fourbeta);
|
||||
fiat_p256_add(tmptmp, fourbeta, fourbeta);
|
||||
fiat_p256_sub(x_out, x_out, tmptmp);
|
||||
|
||||
// z' = (y + z)^2 - gamma - delta
|
||||
fiat_p256_add(delta, gamma, delta);
|
||||
fiat_p256_add(ftmp, y_in, z_in);
|
||||
fiat_p256_square(z_out, ftmp);
|
||||
fiat_p256_sub(z_out, z_out, delta);
|
||||
|
||||
// y' = alpha*(4*beta - x') - 8*gamma^2
|
||||
fiat_p256_sub(y_out, fourbeta, x_out);
|
||||
fiat_p256_add(gamma, gamma, gamma);
|
||||
fiat_p256_square(gamma, gamma);
|
||||
fiat_p256_mul(y_out, alpha, y_out);
|
||||
fiat_p256_add(gamma, gamma, gamma);
|
||||
fiat_p256_sub(y_out, y_out, gamma);
|
||||
}
|
||||
|
||||
// fiat_p256_point_add calculates (x1, y1, z1) + (x2, y2, z2)
|
||||
//
|
||||
// The method is taken from:
|
||||
// http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
|
||||
// adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
|
||||
//
|
||||
// Coq transcription and correctness proof:
|
||||
// <https://github.com/mit-plv/fiat-crypto/blob/79f8b5f39ed609339f0233098dee1a3c4e6b3080/src/Curves/Weierstrass/Jacobian.v#L135>
|
||||
// <https://github.com/mit-plv/fiat-crypto/blob/79f8b5f39ed609339f0233098dee1a3c4e6b3080/src/Curves/Weierstrass/Jacobian.v#L205>
|
||||
//
|
||||
// This function includes a branch for checking whether the two input points
|
||||
// are equal, (while not equal to the point at infinity). This case never
|
||||
// happens during single point multiplication, so there is no timing leak for
|
||||
// ECDH or ECDSA signing.
|
||||
static void fiat_p256_point_add(fiat_p256_felem x3, fiat_p256_felem y3,
|
||||
fiat_p256_felem z3, const fiat_p256_felem x1,
|
||||
const fiat_p256_felem y1,
|
||||
const fiat_p256_felem z1, const int mixed,
|
||||
const fiat_p256_felem x2,
|
||||
const fiat_p256_felem y2,
|
||||
const fiat_p256_felem z2) {
|
||||
fiat_p256_felem x_out, y_out, z_out;
|
||||
fiat_p256_limb_t z1nz = fiat_p256_nz(z1);
|
||||
fiat_p256_limb_t z2nz = fiat_p256_nz(z2);
|
||||
|
||||
// z1z1 = z1z1 = z1**2
|
||||
fiat_p256_felem z1z1;
|
||||
fiat_p256_square(z1z1, z1);
|
||||
|
||||
fiat_p256_felem u1, s1, two_z1z2;
|
||||
if (!mixed) {
|
||||
// z2z2 = z2**2
|
||||
fiat_p256_felem z2z2;
|
||||
fiat_p256_square(z2z2, z2);
|
||||
|
||||
// u1 = x1*z2z2
|
||||
fiat_p256_mul(u1, x1, z2z2);
|
||||
|
||||
// two_z1z2 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2
|
||||
fiat_p256_add(two_z1z2, z1, z2);
|
||||
fiat_p256_square(two_z1z2, two_z1z2);
|
||||
fiat_p256_sub(two_z1z2, two_z1z2, z1z1);
|
||||
fiat_p256_sub(two_z1z2, two_z1z2, z2z2);
|
||||
|
||||
// s1 = y1 * z2**3
|
||||
fiat_p256_mul(s1, z2, z2z2);
|
||||
fiat_p256_mul(s1, s1, y1);
|
||||
} else {
|
||||
// We'll assume z2 = 1 (special case z2 = 0 is handled later).
|
||||
|
||||
// u1 = x1*z2z2
|
||||
fiat_p256_copy(u1, x1);
|
||||
// two_z1z2 = 2z1z2
|
||||
fiat_p256_add(two_z1z2, z1, z1);
|
||||
// s1 = y1 * z2**3
|
||||
fiat_p256_copy(s1, y1);
|
||||
}
|
||||
|
||||
// u2 = x2*z1z1
|
||||
fiat_p256_felem u2;
|
||||
fiat_p256_mul(u2, x2, z1z1);
|
||||
|
||||
// h = u2 - u1
|
||||
fiat_p256_felem h;
|
||||
fiat_p256_sub(h, u2, u1);
|
||||
|
||||
fiat_p256_limb_t xneq = fiat_p256_nz(h);
|
||||
|
||||
// z_out = two_z1z2 * h
|
||||
fiat_p256_mul(z_out, h, two_z1z2);
|
||||
|
||||
// z1z1z1 = z1 * z1z1
|
||||
fiat_p256_felem z1z1z1;
|
||||
fiat_p256_mul(z1z1z1, z1, z1z1);
|
||||
|
||||
// s2 = y2 * z1**3
|
||||
fiat_p256_felem s2;
|
||||
fiat_p256_mul(s2, y2, z1z1z1);
|
||||
|
||||
// r = (s2 - s1)*2
|
||||
fiat_p256_felem r;
|
||||
fiat_p256_sub(r, s2, s1);
|
||||
fiat_p256_add(r, r, r);
|
||||
|
||||
fiat_p256_limb_t yneq = fiat_p256_nz(r);
|
||||
|
||||
fiat_p256_limb_t is_nontrivial_double = constant_time_is_zero_w(xneq | yneq) &
|
||||
~constant_time_is_zero_w(z1nz) &
|
||||
~constant_time_is_zero_w(z2nz);
|
||||
if (is_nontrivial_double) {
|
||||
fiat_p256_point_double(x3, y3, z3, x1, y1, z1);
|
||||
return;
|
||||
}
|
||||
|
||||
// I = (2h)**2
|
||||
fiat_p256_felem i;
|
||||
fiat_p256_add(i, h, h);
|
||||
fiat_p256_square(i, i);
|
||||
|
||||
// J = h * I
|
||||
fiat_p256_felem j;
|
||||
fiat_p256_mul(j, h, i);
|
||||
|
||||
// V = U1 * I
|
||||
fiat_p256_felem v;
|
||||
fiat_p256_mul(v, u1, i);
|
||||
|
||||
// x_out = r**2 - J - 2V
|
||||
fiat_p256_square(x_out, r);
|
||||
fiat_p256_sub(x_out, x_out, j);
|
||||
fiat_p256_sub(x_out, x_out, v);
|
||||
fiat_p256_sub(x_out, x_out, v);
|
||||
|
||||
// y_out = r(V-x_out) - 2 * s1 * J
|
||||
fiat_p256_sub(y_out, v, x_out);
|
||||
fiat_p256_mul(y_out, y_out, r);
|
||||
fiat_p256_felem s1j;
|
||||
fiat_p256_mul(s1j, s1, j);
|
||||
fiat_p256_sub(y_out, y_out, s1j);
|
||||
fiat_p256_sub(y_out, y_out, s1j);
|
||||
|
||||
fiat_p256_cmovznz(x_out, z1nz, x2, x_out);
|
||||
fiat_p256_cmovznz(x3, z2nz, x1, x_out);
|
||||
fiat_p256_cmovznz(y_out, z1nz, y2, y_out);
|
||||
fiat_p256_cmovznz(y3, z2nz, y1, y_out);
|
||||
fiat_p256_cmovznz(z_out, z1nz, z2, z_out);
|
||||
fiat_p256_cmovznz(z3, z2nz, z1, z_out);
|
||||
}
|
||||
|
||||
#include "./p256_table.h"
|
||||
|
||||
// fiat_p256_select_point_affine selects the |idx-1|th point from a
|
||||
// precomputation table and copies it to out. If |idx| is zero, the output is
|
||||
// the point at infinity.
|
||||
static void fiat_p256_select_point_affine(
|
||||
const fiat_p256_limb_t idx, size_t size,
|
||||
const fiat_p256_felem pre_comp[/*size*/][2], fiat_p256_felem out[3]) {
|
||||
OPENSSL_memset(out, 0, sizeof(fiat_p256_felem) * 3);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
fiat_p256_limb_t mismatch = i ^ (idx - 1);
|
||||
fiat_p256_cmovznz(out[0], mismatch, pre_comp[i][0], out[0]);
|
||||
fiat_p256_cmovznz(out[1], mismatch, pre_comp[i][1], out[1]);
|
||||
}
|
||||
fiat_p256_cmovznz(out[2], idx, out[2], fiat_p256_one);
|
||||
}
|
||||
|
||||
// fiat_p256_select_point selects the |idx|th point from a precomputation table
|
||||
// and copies it to out.
|
||||
static void fiat_p256_select_point(const fiat_p256_limb_t idx, size_t size,
|
||||
const fiat_p256_felem pre_comp[/*size*/][3],
|
||||
fiat_p256_felem out[3]) {
|
||||
OPENSSL_memset(out, 0, sizeof(fiat_p256_felem) * 3);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
fiat_p256_limb_t mismatch = i ^ idx;
|
||||
fiat_p256_cmovznz(out[0], mismatch, pre_comp[i][0], out[0]);
|
||||
fiat_p256_cmovznz(out[1], mismatch, pre_comp[i][1], out[1]);
|
||||
fiat_p256_cmovznz(out[2], mismatch, pre_comp[i][2], out[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// fiat_p256_get_bit returns the |i|th bit in |in|
|
||||
static crypto_word_t fiat_p256_get_bit(const uint8_t *in, int i) {
|
||||
if (i < 0 || i >= 256) {
|
||||
return 0;
|
||||
}
|
||||
return (in[i >> 3] >> (i & 7)) & 1;
|
||||
}
|
||||
|
||||
// OPENSSL EC_METHOD FUNCTIONS
|
||||
|
||||
// Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
|
||||
// (X/Z^2, Y/Z^3).
|
||||
static int ec_GFp_nistp256_point_get_affine_coordinates(
|
||||
const EC_GROUP *group, const EC_RAW_POINT *point, EC_FELEM *x_out,
|
||||
EC_FELEM *y_out) {
|
||||
if (ec_GFp_simple_is_at_infinity(group, point)) {
|
||||
OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fiat_p256_felem z1, z2;
|
||||
fiat_p256_from_generic(z1, &point->Z);
|
||||
fiat_p256_inv_square(z2, z1);
|
||||
|
||||
if (x_out != NULL) {
|
||||
fiat_p256_felem x;
|
||||
fiat_p256_from_generic(x, &point->X);
|
||||
fiat_p256_mul(x, x, z2);
|
||||
fiat_p256_to_generic(x_out, x);
|
||||
}
|
||||
|
||||
if (y_out != NULL) {
|
||||
fiat_p256_felem y;
|
||||
fiat_p256_from_generic(y, &point->Y);
|
||||
fiat_p256_square(z2, z2); // z^-4
|
||||
fiat_p256_mul(y, y, z1); // y * z
|
||||
fiat_p256_mul(y, y, z2); // y * z^-3
|
||||
fiat_p256_to_generic(y_out, y);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ec_GFp_nistp256_add(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *a, const EC_RAW_POINT *b) {
|
||||
fiat_p256_felem x1, y1, z1, x2, y2, z2;
|
||||
fiat_p256_from_generic(x1, &a->X);
|
||||
fiat_p256_from_generic(y1, &a->Y);
|
||||
fiat_p256_from_generic(z1, &a->Z);
|
||||
fiat_p256_from_generic(x2, &b->X);
|
||||
fiat_p256_from_generic(y2, &b->Y);
|
||||
fiat_p256_from_generic(z2, &b->Z);
|
||||
fiat_p256_point_add(x1, y1, z1, x1, y1, z1, 0 /* both Jacobian */, x2, y2,
|
||||
z2);
|
||||
fiat_p256_to_generic(&r->X, x1);
|
||||
fiat_p256_to_generic(&r->Y, y1);
|
||||
fiat_p256_to_generic(&r->Z, z1);
|
||||
}
|
||||
|
||||
static void ec_GFp_nistp256_dbl(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *a) {
|
||||
fiat_p256_felem x, y, z;
|
||||
fiat_p256_from_generic(x, &a->X);
|
||||
fiat_p256_from_generic(y, &a->Y);
|
||||
fiat_p256_from_generic(z, &a->Z);
|
||||
fiat_p256_point_double(x, y, z, x, y, z);
|
||||
fiat_p256_to_generic(&r->X, x);
|
||||
fiat_p256_to_generic(&r->Y, y);
|
||||
fiat_p256_to_generic(&r->Z, z);
|
||||
}
|
||||
|
||||
static void ec_GFp_nistp256_point_mul(const EC_GROUP *group, EC_RAW_POINT *r,
|
||||
const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *scalar) {
|
||||
fiat_p256_felem p_pre_comp[17][3];
|
||||
OPENSSL_memset(&p_pre_comp, 0, sizeof(p_pre_comp));
|
||||
// Precompute multiples.
|
||||
fiat_p256_from_generic(p_pre_comp[1][0], &p->X);
|
||||
fiat_p256_from_generic(p_pre_comp[1][1], &p->Y);
|
||||
fiat_p256_from_generic(p_pre_comp[1][2], &p->Z);
|
||||
for (size_t j = 2; j <= 16; ++j) {
|
||||
if (j & 1) {
|
||||
fiat_p256_point_add(p_pre_comp[j][0], p_pre_comp[j][1], p_pre_comp[j][2],
|
||||
p_pre_comp[1][0], p_pre_comp[1][1], p_pre_comp[1][2],
|
||||
0, p_pre_comp[j - 1][0], p_pre_comp[j - 1][1],
|
||||
p_pre_comp[j - 1][2]);
|
||||
} else {
|
||||
fiat_p256_point_double(p_pre_comp[j][0], p_pre_comp[j][1],
|
||||
p_pre_comp[j][2], p_pre_comp[j / 2][0],
|
||||
p_pre_comp[j / 2][1], p_pre_comp[j / 2][2]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set nq to the point at infinity.
|
||||
fiat_p256_felem nq[3] = {{0}, {0}, {0}}, ftmp, tmp[3];
|
||||
|
||||
// Loop over |scalar| msb-to-lsb, incorporating |p_pre_comp| every 5th round.
|
||||
int skip = 1; // Save two point operations in the first round.
|
||||
for (size_t i = 255; i < 256; i--) {
|
||||
// double
|
||||
if (!skip) {
|
||||
fiat_p256_point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
|
||||
}
|
||||
|
||||
// do other additions every 5 doublings
|
||||
if (i % 5 == 0) {
|
||||
crypto_word_t bits = fiat_p256_get_bit(scalar->bytes, i + 4) << 5;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 3) << 4;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 2) << 3;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 1) << 2;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i) << 1;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i - 1);
|
||||
crypto_word_t sign, digit;
|
||||
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
|
||||
|
||||
// select the point to add or subtract, in constant time.
|
||||
fiat_p256_select_point((fiat_p256_limb_t)digit, 17,
|
||||
(const fiat_p256_felem(*)[3])p_pre_comp, tmp);
|
||||
fiat_p256_opp(ftmp, tmp[1]); // (X, -Y, Z) is the negative point.
|
||||
fiat_p256_cmovznz(tmp[1], (fiat_p256_limb_t)sign, tmp[1], ftmp);
|
||||
|
||||
if (!skip) {
|
||||
fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2],
|
||||
0 /* mixed */, tmp[0], tmp[1], tmp[2]);
|
||||
} else {
|
||||
fiat_p256_copy(nq[0], tmp[0]);
|
||||
fiat_p256_copy(nq[1], tmp[1]);
|
||||
fiat_p256_copy(nq[2], tmp[2]);
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fiat_p256_to_generic(&r->X, nq[0]);
|
||||
fiat_p256_to_generic(&r->Y, nq[1]);
|
||||
fiat_p256_to_generic(&r->Z, nq[2]);
|
||||
}
|
||||
|
||||
static void ec_GFp_nistp256_point_mul_base(const EC_GROUP *group,
|
||||
EC_RAW_POINT *r,
|
||||
const EC_SCALAR *scalar) {
|
||||
// Set nq to the point at infinity.
|
||||
fiat_p256_felem nq[3] = {{0}, {0}, {0}}, tmp[3];
|
||||
|
||||
int skip = 1; // Save two point operations in the first round.
|
||||
for (size_t i = 31; i < 32; i--) {
|
||||
if (!skip) {
|
||||
fiat_p256_point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
|
||||
}
|
||||
|
||||
// First, look 32 bits upwards.
|
||||
crypto_word_t bits = fiat_p256_get_bit(scalar->bytes, i + 224) << 3;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 160) << 2;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 96) << 1;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 32);
|
||||
// Select the point to add, in constant time.
|
||||
fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15,
|
||||
fiat_p256_g_pre_comp[1], tmp);
|
||||
|
||||
if (!skip) {
|
||||
fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2],
|
||||
1 /* mixed */, tmp[0], tmp[1], tmp[2]);
|
||||
} else {
|
||||
fiat_p256_copy(nq[0], tmp[0]);
|
||||
fiat_p256_copy(nq[1], tmp[1]);
|
||||
fiat_p256_copy(nq[2], tmp[2]);
|
||||
skip = 0;
|
||||
}
|
||||
|
||||
// Second, look at the current position.
|
||||
bits = fiat_p256_get_bit(scalar->bytes, i + 192) << 3;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 128) << 2;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i + 64) << 1;
|
||||
bits |= fiat_p256_get_bit(scalar->bytes, i);
|
||||
// Select the point to add, in constant time.
|
||||
fiat_p256_select_point_affine((fiat_p256_limb_t)bits, 15,
|
||||
fiat_p256_g_pre_comp[0], tmp);
|
||||
fiat_p256_point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
|
||||
tmp[0], tmp[1], tmp[2]);
|
||||
}
|
||||
|
||||
fiat_p256_to_generic(&r->X, nq[0]);
|
||||
fiat_p256_to_generic(&r->Y, nq[1]);
|
||||
fiat_p256_to_generic(&r->Z, nq[2]);
|
||||
}
|
||||
|
||||
static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group,
|
||||
EC_RAW_POINT *r,
|
||||
const EC_SCALAR *g_scalar,
|
||||
const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *p_scalar) {
|
||||
#define P256_WSIZE_PUBLIC 4
|
||||
// Precompute multiples of |p|. p_pre_comp[i] is (2*i+1) * |p|.
|
||||
fiat_p256_felem p_pre_comp[1 << (P256_WSIZE_PUBLIC - 1)][3];
|
||||
fiat_p256_from_generic(p_pre_comp[0][0], &p->X);
|
||||
fiat_p256_from_generic(p_pre_comp[0][1], &p->Y);
|
||||
fiat_p256_from_generic(p_pre_comp[0][2], &p->Z);
|
||||
fiat_p256_felem p2[3];
|
||||
fiat_p256_point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0],
|
||||
p_pre_comp[0][1], p_pre_comp[0][2]);
|
||||
for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) {
|
||||
fiat_p256_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2],
|
||||
p_pre_comp[i - 1][0], p_pre_comp[i - 1][1],
|
||||
p_pre_comp[i - 1][2], 0 /* not mixed */, p2[0], p2[1],
|
||||
p2[2]);
|
||||
}
|
||||
|
||||
// Set up the coefficients for |p_scalar|.
|
||||
int8_t p_wNAF[257];
|
||||
ec_compute_wNAF(group, p_wNAF, p_scalar, 256, P256_WSIZE_PUBLIC);
|
||||
|
||||
// Set |ret| to the point at infinity.
|
||||
int skip = 1; // Save some point operations.
|
||||
fiat_p256_felem ret[3] = {{0}, {0}, {0}};
|
||||
for (int i = 256; i >= 0; i--) {
|
||||
if (!skip) {
|
||||
fiat_p256_point_double(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2]);
|
||||
}
|
||||
|
||||
// For the |g_scalar|, we use the precomputed table without the
|
||||
// constant-time lookup.
|
||||
if (i <= 31) {
|
||||
// First, look 32 bits upwards.
|
||||
crypto_word_t bits = fiat_p256_get_bit(g_scalar->bytes, i + 224) << 3;
|
||||
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 160) << 2;
|
||||
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 96) << 1;
|
||||
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 32);
|
||||
if (bits != 0) {
|
||||
size_t index = (size_t)(bits - 1);
|
||||
fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2],
|
||||
1 /* mixed */, fiat_p256_g_pre_comp[1][index][0],
|
||||
fiat_p256_g_pre_comp[1][index][1],
|
||||
fiat_p256_one);
|
||||
skip = 0;
|
||||
}
|
||||
|
||||
// Second, look at the current position.
|
||||
bits = fiat_p256_get_bit(g_scalar->bytes, i + 192) << 3;
|
||||
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 128) << 2;
|
||||
bits |= fiat_p256_get_bit(g_scalar->bytes, i + 64) << 1;
|
||||
bits |= fiat_p256_get_bit(g_scalar->bytes, i);
|
||||
if (bits != 0) {
|
||||
size_t index = (size_t)(bits - 1);
|
||||
fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2],
|
||||
1 /* mixed */, fiat_p256_g_pre_comp[0][index][0],
|
||||
fiat_p256_g_pre_comp[0][index][1],
|
||||
fiat_p256_one);
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int digit = p_wNAF[i];
|
||||
if (digit != 0) {
|
||||
assert(digit & 1);
|
||||
size_t idx = (size_t)(digit < 0 ? (-digit) >> 1 : digit >> 1);
|
||||
fiat_p256_felem *y = &p_pre_comp[idx][1], tmp;
|
||||
if (digit < 0) {
|
||||
fiat_p256_opp(tmp, p_pre_comp[idx][1]);
|
||||
y = &tmp;
|
||||
}
|
||||
if (!skip) {
|
||||
fiat_p256_point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2],
|
||||
0 /* not mixed */, p_pre_comp[idx][0], *y,
|
||||
p_pre_comp[idx][2]);
|
||||
} else {
|
||||
fiat_p256_copy(ret[0], p_pre_comp[idx][0]);
|
||||
fiat_p256_copy(ret[1], *y);
|
||||
fiat_p256_copy(ret[2], p_pre_comp[idx][2]);
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fiat_p256_to_generic(&r->X, ret[0]);
|
||||
fiat_p256_to_generic(&r->Y, ret[1]);
|
||||
fiat_p256_to_generic(&r->Z, ret[2]);
|
||||
}
|
||||
|
||||
static int ec_GFp_nistp256_cmp_x_coordinate(const EC_GROUP *group,
|
||||
const EC_RAW_POINT *p,
|
||||
const EC_SCALAR *r) {
|
||||
if (ec_GFp_simple_is_at_infinity(group, p)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We wish to compare X/Z^2 with r. This is equivalent to comparing X with
|
||||
// r*Z^2. Note that X and Z are represented in Montgomery form, while r is
|
||||
// not.
|
||||
fiat_p256_felem Z2_mont;
|
||||
fiat_p256_from_generic(Z2_mont, &p->Z);
|
||||
fiat_p256_mul(Z2_mont, Z2_mont, Z2_mont);
|
||||
|
||||
fiat_p256_felem r_Z2;
|
||||
fiat_p256_from_bytes(r_Z2, r->bytes); // r < order < p, so this is valid.
|
||||
fiat_p256_mul(r_Z2, r_Z2, Z2_mont);
|
||||
|
||||
fiat_p256_felem X;
|
||||
fiat_p256_from_generic(X, &p->X);
|
||||
fiat_p256_from_montgomery(X, X);
|
||||
|
||||
if (OPENSSL_memcmp(&r_Z2, &X, sizeof(r_Z2)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// During signing the x coefficient is reduced modulo the group order.
|
||||
// Therefore there is a small possibility, less than 1/2^128, that group_order
|
||||
// < p.x < P. in that case we need not only to compare against |r| but also to
|
||||
// compare against r+group_order.
|
||||
assert(group->field.width == group->order.width);
|
||||
if (bn_less_than_words(r->words, group->field_minus_order.words,
|
||||
group->field.width)) {
|
||||
// We can ignore the carry because: r + group_order < p < 2^256.
|
||||
EC_FELEM tmp;
|
||||
bn_add_words(tmp.words, r->words, group->order.d, group->order.width);
|
||||
fiat_p256_from_generic(r_Z2, &tmp);
|
||||
fiat_p256_mul(r_Z2, r_Z2, Z2_mont);
|
||||
if (OPENSSL_memcmp(&r_Z2, &X, sizeof(r_Z2)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp256_method) {
|
||||
out->group_init = ec_GFp_mont_group_init;
|
||||
out->group_finish = ec_GFp_mont_group_finish;
|
||||
out->group_set_curve = ec_GFp_mont_group_set_curve;
|
||||
out->point_get_affine_coordinates =
|
||||
ec_GFp_nistp256_point_get_affine_coordinates;
|
||||
out->add = ec_GFp_nistp256_add;
|
||||
out->dbl = ec_GFp_nistp256_dbl;
|
||||
out->mul = ec_GFp_nistp256_point_mul;
|
||||
out->mul_base = ec_GFp_nistp256_point_mul_base;
|
||||
out->mul_public = ec_GFp_nistp256_point_mul_public;
|
||||
out->felem_mul = ec_GFp_mont_felem_mul;
|
||||
out->felem_sqr = ec_GFp_mont_felem_sqr;
|
||||
out->felem_to_bytes = ec_GFp_mont_felem_to_bytes;
|
||||
out->felem_from_bytes = ec_GFp_mont_felem_from_bytes;
|
||||
out->scalar_inv0_montgomery = ec_simple_scalar_inv0_montgomery;
|
||||
out->scalar_to_montgomery_inv_vartime =
|
||||
ec_simple_scalar_to_montgomery_inv_vartime;
|
||||
out->cmp_x_coordinate = ec_GFp_nistp256_cmp_x_coordinate;
|
||||
}
|
||||
|
||||
#undef BORINGSSL_NISTP256_64BIT
|
||||
@@ -1,297 +0,0 @@
|
||||
/* Copyright (c) 2020, 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 file is generated by make_tables.go.
|
||||
|
||||
// Base point pre computation
|
||||
// --------------------------
|
||||
//
|
||||
// Two different sorts of precomputed tables are used in the following code.
|
||||
// Each contain various points on the curve, where each point is three field
|
||||
// elements (x, y, z).
|
||||
//
|
||||
// For the base point table, z is usually 1 (0 for the point at infinity).
|
||||
// This table has 2 * 16 elements, starting with the following:
|
||||
// index | bits | point
|
||||
// ------+---------+------------------------------
|
||||
// 0 | 0 0 0 0 | 0G
|
||||
// 1 | 0 0 0 1 | 1G
|
||||
// 2 | 0 0 1 0 | 2^64G
|
||||
// 3 | 0 0 1 1 | (2^64 + 1)G
|
||||
// 4 | 0 1 0 0 | 2^128G
|
||||
// 5 | 0 1 0 1 | (2^128 + 1)G
|
||||
// 6 | 0 1 1 0 | (2^128 + 2^64)G
|
||||
// 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
|
||||
// 8 | 1 0 0 0 | 2^192G
|
||||
// 9 | 1 0 0 1 | (2^192 + 1)G
|
||||
// 10 | 1 0 1 0 | (2^192 + 2^64)G
|
||||
// 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
|
||||
// 12 | 1 1 0 0 | (2^192 + 2^128)G
|
||||
// 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
|
||||
// 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
|
||||
// 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
|
||||
// followed by a copy of this with each element multiplied by 2^32.
|
||||
//
|
||||
// The reason for this is so that we can clock bits into four different
|
||||
// locations when doing simple scalar multiplies against the base point,
|
||||
// and then another four locations using the second 16 elements.
|
||||
//
|
||||
// Tables for other points have table[i] = iG for i in 0 .. 16.
|
||||
|
||||
// fiat_p256_g_pre_comp is the table of precomputed base points
|
||||
#if defined(BORINGSSL_NISTP256_64BIT)
|
||||
static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = {
|
||||
{{{0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510,
|
||||
0x18905f76a53755c6},
|
||||
{0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325,
|
||||
0x8571ff1825885d85}},
|
||||
{{0x4f922fc516a0d2bb, 0x0d5cc16c1a623499, 0x9241cf3a57c62c8b,
|
||||
0x2f5e6961fd1b667f},
|
||||
{0x5c15c70bf5a01797, 0x3d20b44d60956192, 0x04911b37071fdb52,
|
||||
0xf648f9168d6f0f7b}},
|
||||
{{0x9e566847e137bbbc, 0xe434469e8a6a0bec, 0xb1c4276179d73463,
|
||||
0x5abe0285133d0015},
|
||||
{0x92aa837cc04c7dab, 0x573d9f4c43260c07, 0x0c93156278e6cc37,
|
||||
0x94bb725b6b6f7383}},
|
||||
{{0x62a8c244bfe20925, 0x91c19ac38fdce867, 0x5a96a5d5dd387063,
|
||||
0x61d587d421d324f6},
|
||||
{0xe87673a2a37173ea, 0x2384800853778b65, 0x10f8441e05bab43e,
|
||||
0xfa11fe124621efbe}},
|
||||
{{0x1c891f2b2cb19ffd, 0x01ba8d5bb1923c23, 0xb6d03d678ac5ca8e,
|
||||
0x586eb04c1f13bedc},
|
||||
{0x0c35c6e527e8ed09, 0x1e81a33c1819ede2, 0x278fd6c056c652fa,
|
||||
0x19d5ac0870864f11}},
|
||||
{{0x62577734d2b533d5, 0x673b8af6a1bdddc0, 0x577e7c9aa79ec293,
|
||||
0xbb6de651c3b266b1},
|
||||
{0xe7e9303ab65259b3, 0xd6a0afd3d03a7480, 0xc5ac83d19b3cfc27,
|
||||
0x60b4619a5d18b99b}},
|
||||
{{0xbd6a38e11ae5aa1c, 0xb8b7652b49e73658, 0x0b130014ee5f87ed,
|
||||
0x9d0f27b2aeebffcd},
|
||||
{0xca9246317a730a55, 0x9c955b2fddbbc83a, 0x07c1dfe0ac019a71,
|
||||
0x244a566d356ec48d}},
|
||||
{{0x56f8410ef4f8b16a, 0x97241afec47b266a, 0x0a406b8e6d9c87c1,
|
||||
0x803f3e02cd42ab1b},
|
||||
{0x7f0309a804dbec69, 0xa83b85f73bbad05f, 0xc6097273ad8e197f,
|
||||
0xc097440e5067adc1}},
|
||||
{{0x846a56f2c379ab34, 0xa8ee068b841df8d1, 0x20314459176c68ef,
|
||||
0xf1af32d5915f1f30},
|
||||
{0x99c375315d75bd50, 0x837cffbaf72f67bc, 0x0613a41848d7723f,
|
||||
0x23d0f130e2d41c8b}},
|
||||
{{0xed93e225d5be5a2b, 0x6fe799835934f3c6, 0x4314092622626ffc,
|
||||
0x50bbb4d97990216a},
|
||||
{0x378191c6e57ec63e, 0x65422c40181dcdb2, 0x41a8099b0236e0f6,
|
||||
0x2b10011801fe49c3}},
|
||||
{{0xfc68b5c59b391593, 0xc385f5a2598270fc, 0x7144f3aad19adcbb,
|
||||
0xdd55899983fbae0c},
|
||||
{0x93b88b8e74b82ff4, 0xd2e03c4071e734c9, 0x9a7a9eaf43c0322a,
|
||||
0xe6e4c551149d6041}},
|
||||
{{0x5fe14bfe80ec21fe, 0xf6ce116ac255be82, 0x98bc5a072f4a5d67,
|
||||
0xfad27148db7e63af},
|
||||
{0x90c0b6ac29ab05b3, 0x37a9a83c4e251ae6, 0x0a7dc875c2aade7d,
|
||||
0x77387de39f0e1a84}},
|
||||
{{0x1e9ecc49a56c0dd7, 0xa5cffcd846086c74, 0x8f7a1408f505aece,
|
||||
0xb37b85c0bef0c47e},
|
||||
{0x3596b6e4cc0e6a8f, 0xfd6d4bbf6b388f23, 0xaba453fac39cef4e,
|
||||
0x9c135ac8f9f628d5}},
|
||||
{{0x0a1c729495c8f8be, 0x2961c4803bf362bf, 0x9e418403df63d4ac,
|
||||
0xc109f9cb91ece900},
|
||||
{0xc2d095d058945705, 0xb9083d96ddeb85c0, 0x84692b8d7a40449b,
|
||||
0x9bc3344f2eee1ee1}},
|
||||
{{0x0d5ae35642913074, 0x55491b2748a542b1, 0x469ca665b310732a,
|
||||
0x29591d525f1a4cc1},
|
||||
{0xe76f5b6bb84f983f, 0xbe7eef419f5f84e1, 0x1200d49680baa189,
|
||||
0x6376551f18ef332c}}},
|
||||
{{{0x202886024147519a, 0xd0981eac26b372f0, 0xa9d4a7caa785ebc8,
|
||||
0xd953c50ddbdf58e9},
|
||||
{0x9d6361ccfd590f8f, 0x72e9626b44e6c917, 0x7fd9611022eb64cf,
|
||||
0x863ebb7e9eb288f3}},
|
||||
{{0x4fe7ee31b0e63d34, 0xf4600572a9e54fab, 0xc0493334d5e7b5a4,
|
||||
0x8589fb9206d54831},
|
||||
{0xaa70f5cc6583553a, 0x0879094ae25649e5, 0xcc90450710044652,
|
||||
0xebb0696d02541c4f}},
|
||||
{{0xabbaa0c03b89da99, 0xa6f2d79eb8284022, 0x27847862b81c05e8,
|
||||
0x337a4b5905e54d63},
|
||||
{0x3c67500d21f7794a, 0x207005b77d6d7f61, 0x0a5a378104cfd6e8,
|
||||
0x0d65e0d5f4c2fbd6}},
|
||||
{{0xd433e50f6d3549cf, 0x6f33696ffacd665e, 0x695bfdacce11fcb4,
|
||||
0x810ee252af7c9860},
|
||||
{0x65450fe17159bb2c, 0xf7dfbebe758b357b, 0x2b057e74d69fea72,
|
||||
0xd485717a92731745}},
|
||||
{{0xce1f69bbe83f7669, 0x09f8ae8272877d6b, 0x9548ae543244278d,
|
||||
0x207755dee3c2c19c},
|
||||
{0x87bd61d96fef1945, 0x18813cefb12d28c3, 0x9fbcd1d672df64aa,
|
||||
0x48dc5ee57154b00d}},
|
||||
{{0xef0f469ef49a3154, 0x3e85a5956e2b2e9a, 0x45aaec1eaa924a9c,
|
||||
0xaa12dfc8a09e4719},
|
||||
{0x26f272274df69f1d, 0xe0e4c82ca2ff5e73, 0xb9d8ce73b7a9dd44,
|
||||
0x6c036e73e48ca901}},
|
||||
{{0xe1e421e1a47153f0, 0xb86c3b79920418c9, 0x93bdce87705d7672,
|
||||
0xf25ae793cab79a77},
|
||||
{0x1f3194a36d869d0c, 0x9d55c8824986c264, 0x49fb5ea3096e945e,
|
||||
0x39b8e65313db0a3e}},
|
||||
{{0xe3417bc035d0b34a, 0x440b386b8327c0a7, 0x8fb7262dac0362d1,
|
||||
0x2c41114ce0cdf943},
|
||||
{0x2ba5cef1ad95a0b1, 0xc09b37a867d54362, 0x26d6cdd201e486c9,
|
||||
0x20477abf42ff9297}},
|
||||
{{0x0f121b41bc0a67d2, 0x62d4760a444d248a, 0x0e044f1d659b4737,
|
||||
0x08fde365250bb4a8},
|
||||
{0xaceec3da848bf287, 0xc2a62182d3369d6e, 0x3582dfdc92449482,
|
||||
0x2f7e2fd2565d6cd7}},
|
||||
{{0x0a0122b5178a876b, 0x51ff96ff085104b4, 0x050b31ab14f29f76,
|
||||
0x84abb28b5f87d4e6},
|
||||
{0xd5ed439f8270790a, 0x2d6cb59d85e3f46b, 0x75f55c1b6c1e2212,
|
||||
0xe5436f6717655640}},
|
||||
{{0xc2965ecc9aeb596d, 0x01ea03e7023c92b4, 0x4704b4b62e013961,
|
||||
0x0ca8fd3f905ea367},
|
||||
{0x92523a42551b2b61, 0x1eb7a89c390fcd06, 0xe7f1d2be0392a63e,
|
||||
0x96dca2644ddb0c33}},
|
||||
{{0x231c210e15339848, 0xe87a28e870778c8d, 0x9d1de6616956e170,
|
||||
0x4ac3c9382bb09c0b},
|
||||
{0x19be05516998987d, 0x8b2376c4ae09f4d6, 0x1de0b7651a3f933d,
|
||||
0x380d94c7e39705f4}},
|
||||
{{0x3685954b8c31c31d, 0x68533d005bf21a0c, 0x0bd7626e75c79ec9,
|
||||
0xca17754742c69d54},
|
||||
{0xcc6edafff6d2dbb2, 0xfd0d8cbd174a9d18, 0x875e8793aa4578e8,
|
||||
0xa976a7139cab2ce6}},
|
||||
{{0xce37ab11b43ea1db, 0x0a7ff1a95259d292, 0x851b02218f84f186,
|
||||
0xa7222beadefaad13},
|
||||
{0xa2ac78ec2b0a9144, 0x5a024051f2fa59c5, 0x91d1eca56147ce38,
|
||||
0xbe94d523bc2ac690}},
|
||||
{{0x2d8daefd79ec1a0f, 0x3bbcd6fdceb39c97, 0xf5575ffc58f61a95,
|
||||
0xdbd986c4adf7b420},
|
||||
{0x81aa881415f39eb7, 0x6ee2fcf5b98d976c, 0x5465475dcf2f717d,
|
||||
0x8e24d3c46860bbd0}}}};
|
||||
#else
|
||||
static const fiat_p256_felem fiat_p256_g_pre_comp[2][15][2] = {
|
||||
{{{0x18a9143c, 0x79e730d4, 0x5fedb601, 0x75ba95fc, 0x77622510, 0x79fb732b,
|
||||
0xa53755c6, 0x18905f76},
|
||||
{0xce95560a, 0xddf25357, 0xba19e45c, 0x8b4ab8e4, 0xdd21f325, 0xd2e88688,
|
||||
0x25885d85, 0x8571ff18}},
|
||||
{{0x16a0d2bb, 0x4f922fc5, 0x1a623499, 0x0d5cc16c, 0x57c62c8b, 0x9241cf3a,
|
||||
0xfd1b667f, 0x2f5e6961},
|
||||
{0xf5a01797, 0x5c15c70b, 0x60956192, 0x3d20b44d, 0x071fdb52, 0x04911b37,
|
||||
0x8d6f0f7b, 0xf648f916}},
|
||||
{{0xe137bbbc, 0x9e566847, 0x8a6a0bec, 0xe434469e, 0x79d73463, 0xb1c42761,
|
||||
0x133d0015, 0x5abe0285},
|
||||
{0xc04c7dab, 0x92aa837c, 0x43260c07, 0x573d9f4c, 0x78e6cc37, 0x0c931562,
|
||||
0x6b6f7383, 0x94bb725b}},
|
||||
{{0xbfe20925, 0x62a8c244, 0x8fdce867, 0x91c19ac3, 0xdd387063, 0x5a96a5d5,
|
||||
0x21d324f6, 0x61d587d4},
|
||||
{0xa37173ea, 0xe87673a2, 0x53778b65, 0x23848008, 0x05bab43e, 0x10f8441e,
|
||||
0x4621efbe, 0xfa11fe12}},
|
||||
{{0x2cb19ffd, 0x1c891f2b, 0xb1923c23, 0x01ba8d5b, 0x8ac5ca8e, 0xb6d03d67,
|
||||
0x1f13bedc, 0x586eb04c},
|
||||
{0x27e8ed09, 0x0c35c6e5, 0x1819ede2, 0x1e81a33c, 0x56c652fa, 0x278fd6c0,
|
||||
0x70864f11, 0x19d5ac08}},
|
||||
{{0xd2b533d5, 0x62577734, 0xa1bdddc0, 0x673b8af6, 0xa79ec293, 0x577e7c9a,
|
||||
0xc3b266b1, 0xbb6de651},
|
||||
{0xb65259b3, 0xe7e9303a, 0xd03a7480, 0xd6a0afd3, 0x9b3cfc27, 0xc5ac83d1,
|
||||
0x5d18b99b, 0x60b4619a}},
|
||||
{{0x1ae5aa1c, 0xbd6a38e1, 0x49e73658, 0xb8b7652b, 0xee5f87ed, 0x0b130014,
|
||||
0xaeebffcd, 0x9d0f27b2},
|
||||
{0x7a730a55, 0xca924631, 0xddbbc83a, 0x9c955b2f, 0xac019a71, 0x07c1dfe0,
|
||||
0x356ec48d, 0x244a566d}},
|
||||
{{0xf4f8b16a, 0x56f8410e, 0xc47b266a, 0x97241afe, 0x6d9c87c1, 0x0a406b8e,
|
||||
0xcd42ab1b, 0x803f3e02},
|
||||
{0x04dbec69, 0x7f0309a8, 0x3bbad05f, 0xa83b85f7, 0xad8e197f, 0xc6097273,
|
||||
0x5067adc1, 0xc097440e}},
|
||||
{{0xc379ab34, 0x846a56f2, 0x841df8d1, 0xa8ee068b, 0x176c68ef, 0x20314459,
|
||||
0x915f1f30, 0xf1af32d5},
|
||||
{0x5d75bd50, 0x99c37531, 0xf72f67bc, 0x837cffba, 0x48d7723f, 0x0613a418,
|
||||
0xe2d41c8b, 0x23d0f130}},
|
||||
{{0xd5be5a2b, 0xed93e225, 0x5934f3c6, 0x6fe79983, 0x22626ffc, 0x43140926,
|
||||
0x7990216a, 0x50bbb4d9},
|
||||
{0xe57ec63e, 0x378191c6, 0x181dcdb2, 0x65422c40, 0x0236e0f6, 0x41a8099b,
|
||||
0x01fe49c3, 0x2b100118}},
|
||||
{{0x9b391593, 0xfc68b5c5, 0x598270fc, 0xc385f5a2, 0xd19adcbb, 0x7144f3aa,
|
||||
0x83fbae0c, 0xdd558999},
|
||||
{0x74b82ff4, 0x93b88b8e, 0x71e734c9, 0xd2e03c40, 0x43c0322a, 0x9a7a9eaf,
|
||||
0x149d6041, 0xe6e4c551}},
|
||||
{{0x80ec21fe, 0x5fe14bfe, 0xc255be82, 0xf6ce116a, 0x2f4a5d67, 0x98bc5a07,
|
||||
0xdb7e63af, 0xfad27148},
|
||||
{0x29ab05b3, 0x90c0b6ac, 0x4e251ae6, 0x37a9a83c, 0xc2aade7d, 0x0a7dc875,
|
||||
0x9f0e1a84, 0x77387de3}},
|
||||
{{0xa56c0dd7, 0x1e9ecc49, 0x46086c74, 0xa5cffcd8, 0xf505aece, 0x8f7a1408,
|
||||
0xbef0c47e, 0xb37b85c0},
|
||||
{0xcc0e6a8f, 0x3596b6e4, 0x6b388f23, 0xfd6d4bbf, 0xc39cef4e, 0xaba453fa,
|
||||
0xf9f628d5, 0x9c135ac8}},
|
||||
{{0x95c8f8be, 0x0a1c7294, 0x3bf362bf, 0x2961c480, 0xdf63d4ac, 0x9e418403,
|
||||
0x91ece900, 0xc109f9cb},
|
||||
{0x58945705, 0xc2d095d0, 0xddeb85c0, 0xb9083d96, 0x7a40449b, 0x84692b8d,
|
||||
0x2eee1ee1, 0x9bc3344f}},
|
||||
{{0x42913074, 0x0d5ae356, 0x48a542b1, 0x55491b27, 0xb310732a, 0x469ca665,
|
||||
0x5f1a4cc1, 0x29591d52},
|
||||
{0xb84f983f, 0xe76f5b6b, 0x9f5f84e1, 0xbe7eef41, 0x80baa189, 0x1200d496,
|
||||
0x18ef332c, 0x6376551f}}},
|
||||
{{{0x4147519a, 0x20288602, 0x26b372f0, 0xd0981eac, 0xa785ebc8, 0xa9d4a7ca,
|
||||
0xdbdf58e9, 0xd953c50d},
|
||||
{0xfd590f8f, 0x9d6361cc, 0x44e6c917, 0x72e9626b, 0x22eb64cf, 0x7fd96110,
|
||||
0x9eb288f3, 0x863ebb7e}},
|
||||
{{0xb0e63d34, 0x4fe7ee31, 0xa9e54fab, 0xf4600572, 0xd5e7b5a4, 0xc0493334,
|
||||
0x06d54831, 0x8589fb92},
|
||||
{0x6583553a, 0xaa70f5cc, 0xe25649e5, 0x0879094a, 0x10044652, 0xcc904507,
|
||||
0x02541c4f, 0xebb0696d}},
|
||||
{{0x3b89da99, 0xabbaa0c0, 0xb8284022, 0xa6f2d79e, 0xb81c05e8, 0x27847862,
|
||||
0x05e54d63, 0x337a4b59},
|
||||
{0x21f7794a, 0x3c67500d, 0x7d6d7f61, 0x207005b7, 0x04cfd6e8, 0x0a5a3781,
|
||||
0xf4c2fbd6, 0x0d65e0d5}},
|
||||
{{0x6d3549cf, 0xd433e50f, 0xfacd665e, 0x6f33696f, 0xce11fcb4, 0x695bfdac,
|
||||
0xaf7c9860, 0x810ee252},
|
||||
{0x7159bb2c, 0x65450fe1, 0x758b357b, 0xf7dfbebe, 0xd69fea72, 0x2b057e74,
|
||||
0x92731745, 0xd485717a}},
|
||||
{{0xe83f7669, 0xce1f69bb, 0x72877d6b, 0x09f8ae82, 0x3244278d, 0x9548ae54,
|
||||
0xe3c2c19c, 0x207755de},
|
||||
{0x6fef1945, 0x87bd61d9, 0xb12d28c3, 0x18813cef, 0x72df64aa, 0x9fbcd1d6,
|
||||
0x7154b00d, 0x48dc5ee5}},
|
||||
{{0xf49a3154, 0xef0f469e, 0x6e2b2e9a, 0x3e85a595, 0xaa924a9c, 0x45aaec1e,
|
||||
0xa09e4719, 0xaa12dfc8},
|
||||
{0x4df69f1d, 0x26f27227, 0xa2ff5e73, 0xe0e4c82c, 0xb7a9dd44, 0xb9d8ce73,
|
||||
0xe48ca901, 0x6c036e73}},
|
||||
{{0xa47153f0, 0xe1e421e1, 0x920418c9, 0xb86c3b79, 0x705d7672, 0x93bdce87,
|
||||
0xcab79a77, 0xf25ae793},
|
||||
{0x6d869d0c, 0x1f3194a3, 0x4986c264, 0x9d55c882, 0x096e945e, 0x49fb5ea3,
|
||||
0x13db0a3e, 0x39b8e653}},
|
||||
{{0x35d0b34a, 0xe3417bc0, 0x8327c0a7, 0x440b386b, 0xac0362d1, 0x8fb7262d,
|
||||
0xe0cdf943, 0x2c41114c},
|
||||
{0xad95a0b1, 0x2ba5cef1, 0x67d54362, 0xc09b37a8, 0x01e486c9, 0x26d6cdd2,
|
||||
0x42ff9297, 0x20477abf}},
|
||||
{{0xbc0a67d2, 0x0f121b41, 0x444d248a, 0x62d4760a, 0x659b4737, 0x0e044f1d,
|
||||
0x250bb4a8, 0x08fde365},
|
||||
{0x848bf287, 0xaceec3da, 0xd3369d6e, 0xc2a62182, 0x92449482, 0x3582dfdc,
|
||||
0x565d6cd7, 0x2f7e2fd2}},
|
||||
{{0x178a876b, 0x0a0122b5, 0x085104b4, 0x51ff96ff, 0x14f29f76, 0x050b31ab,
|
||||
0x5f87d4e6, 0x84abb28b},
|
||||
{0x8270790a, 0xd5ed439f, 0x85e3f46b, 0x2d6cb59d, 0x6c1e2212, 0x75f55c1b,
|
||||
0x17655640, 0xe5436f67}},
|
||||
{{0x9aeb596d, 0xc2965ecc, 0x023c92b4, 0x01ea03e7, 0x2e013961, 0x4704b4b6,
|
||||
0x905ea367, 0x0ca8fd3f},
|
||||
{0x551b2b61, 0x92523a42, 0x390fcd06, 0x1eb7a89c, 0x0392a63e, 0xe7f1d2be,
|
||||
0x4ddb0c33, 0x96dca264}},
|
||||
{{0x15339848, 0x231c210e, 0x70778c8d, 0xe87a28e8, 0x6956e170, 0x9d1de661,
|
||||
0x2bb09c0b, 0x4ac3c938},
|
||||
{0x6998987d, 0x19be0551, 0xae09f4d6, 0x8b2376c4, 0x1a3f933d, 0x1de0b765,
|
||||
0xe39705f4, 0x380d94c7}},
|
||||
{{0x8c31c31d, 0x3685954b, 0x5bf21a0c, 0x68533d00, 0x75c79ec9, 0x0bd7626e,
|
||||
0x42c69d54, 0xca177547},
|
||||
{0xf6d2dbb2, 0xcc6edaff, 0x174a9d18, 0xfd0d8cbd, 0xaa4578e8, 0x875e8793,
|
||||
0x9cab2ce6, 0xa976a713}},
|
||||
{{0xb43ea1db, 0xce37ab11, 0x5259d292, 0x0a7ff1a9, 0x8f84f186, 0x851b0221,
|
||||
0xdefaad13, 0xa7222bea},
|
||||
{0x2b0a9144, 0xa2ac78ec, 0xf2fa59c5, 0x5a024051, 0x6147ce38, 0x91d1eca5,
|
||||
0xbc2ac690, 0xbe94d523}},
|
||||
{{0x79ec1a0f, 0x2d8daefd, 0xceb39c97, 0x3bbcd6fd, 0x58f61a95, 0xf5575ffc,
|
||||
0xadf7b420, 0xdbd986c4},
|
||||
{0x15f39eb7, 0x81aa8814, 0xb98d976c, 0x6ee2fcf5, 0xcf2f717d, 0x5465475d,
|
||||
0x6860bbd0, 0x8e24d3c4}}}};
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user