Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 78684e5b22 |
-15
@@ -4,18 +4,3 @@ ssl/test/runner/runner
|
||||
*.swo
|
||||
doc/*.html
|
||||
doc/doc.css
|
||||
|
||||
util/bot/android_tools
|
||||
util/bot/cmake-linux64
|
||||
util/bot/cmake-linux64.tar.gz
|
||||
util/bot/cmake-mac
|
||||
util/bot/cmake-mac.tar.gz
|
||||
util/bot/cmake-win32
|
||||
util/bot/cmake-win32.zip
|
||||
util/bot/golang
|
||||
util/bot/gyp
|
||||
util/bot/llvm-build
|
||||
util/bot/perl-win32
|
||||
util/bot/perl-win32.zip
|
||||
util/bot/win_toolchain.json
|
||||
util/bot/yasm-win32.exe
|
||||
|
||||
+2
-2
@@ -14,10 +14,10 @@ All supported public APIs are documented in the public header files, found in
|
||||
Some headers lack documention comments. These are functions and structures from
|
||||
OpenSSL's legacy ASN.1, X.509, and PEM implementation. If possible, avoid using
|
||||
them. These are left largely unmodified from upstream and are retained only for
|
||||
compatibility with existing OpenSSL consumers.
|
||||
compatibilty with existing OpenSSL consumers.
|
||||
|
||||
|
||||
## Forward declarations
|
||||
# Forward declarations
|
||||
|
||||
Do not write `typedef struct foo_st FOO` or try otherwise to define BoringSSL's
|
||||
types. Including `openssl/base.h` (or `openssl/ossl_typ.h` for consumers who
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
## Build Prerequisites
|
||||
|
||||
* [CMake](https://cmake.org/download/) 2.8.11 or later is required.
|
||||
* [CMake](https://cmake.org/download/) 2.8.8 or later is required.
|
||||
|
||||
* Perl 5.6.1 or later is required. On Windows,
|
||||
[Active State Perl](http://www.activestate.com/activeperl/) has been
|
||||
@@ -33,7 +33,7 @@
|
||||
executable may be configured explicitly by setting `GO_EXECUTABLE`.
|
||||
|
||||
* To build the x86 and x86\_64 assembly, your assembler must support AVX2
|
||||
instructions and MOVBE. If using GNU binutils, you must have 2.22 or later.
|
||||
instructions. If using GNU binutils, you must have 2.22 or later.
|
||||
|
||||
## Building
|
||||
|
||||
|
||||
+10
-62
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required (VERSION 2.8.11)
|
||||
cmake_minimum_required (VERSION 2.8.10)
|
||||
|
||||
# Defer enabling C and CXX languages.
|
||||
project (BoringSSL NONE)
|
||||
@@ -43,16 +43,10 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
"C4061" # enumerator 'identifier' in switch of enum 'enumeration' is not
|
||||
# explicitly handled by a case label
|
||||
# Disable this because it flags even when there is a default.
|
||||
"C4100" # 'exarg' : unreferenced formal parameter
|
||||
"C4127" # conditional expression is constant
|
||||
"C4200" # nonstandard extension used : zero-sized array in
|
||||
# struct/union.
|
||||
"C4204" # nonstandard extension used: non-constant aggregate initializer
|
||||
"C4221" # nonstandard extension used : 'identifier' : cannot be
|
||||
# initialized using address of automatic variable
|
||||
"C4242" # 'function' : conversion from 'int' to 'uint8_t',
|
||||
# possible loss of data
|
||||
"C4244" # 'function' : conversion from 'int' to 'uint8_t',
|
||||
@@ -81,16 +75,12 @@ elseif(MSVC)
|
||||
# copy constructor is inaccessible or deleted
|
||||
"C4626" # assignment operator could not be generated because a base class
|
||||
# assignment operator is inaccessible or deleted
|
||||
"C4668" # 'symbol' is not defined as a preprocessor macro, replacing with
|
||||
# '0' for 'directives'
|
||||
# Disable this because GTest uses it everywhere.
|
||||
"C4706" # assignment within conditional expression
|
||||
"C4710" # 'function': function not inlined
|
||||
"C4711" # function 'function' selected for inline expansion
|
||||
"C4800" # 'int' : forcing value to bool 'true' or 'false'
|
||||
# (performance warning)
|
||||
"C4820" # 'bytes' bytes padding added after construct 'member_name'
|
||||
"C5026" # move constructor was implicitly defined as deleted
|
||||
"C5027" # move assignment operator was implicitly defined as deleted
|
||||
)
|
||||
set(MSVC_LEVEL4_WARNINGS_LIST
|
||||
@@ -131,17 +121,12 @@ if(NOT WIN32)
|
||||
endif()
|
||||
|
||||
if(FUZZ)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "You need to build with Clang for fuzzing to work")
|
||||
if(!CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message("You need to build with Clang for fuzzing to work")
|
||||
endif()
|
||||
|
||||
add_definitions(-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE)
|
||||
set(RUNNER_ARGS "-deterministic")
|
||||
|
||||
if(NOT NO_FUZZER_MODE)
|
||||
add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
|
||||
set(RUNNER_ARGS ${RUNNER_ARGS} "-fuzzer" "-shim-config" "fuzzer_mode.json")
|
||||
endif()
|
||||
add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
|
||||
set(RUNNER_ARGS "-fuzzer")
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
|
||||
@@ -175,15 +160,14 @@ elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm*")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv6")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7-a")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
set(ARCH "aarch64")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "mips")
|
||||
# Just to avoid the “unknown processor” error.
|
||||
set(ARCH "generic")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
|
||||
set(ARCH "ppc64le")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
@@ -202,47 +186,11 @@ if (${ARCH} STREQUAL "x86" AND APPLE)
|
||||
set(ARCH "x86_64")
|
||||
endif()
|
||||
|
||||
if (MSAN)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "Cannot enable MSAN unless using Clang")
|
||||
endif()
|
||||
|
||||
if (ASAN)
|
||||
message(FATAL_ERROR "ASAN and MSAN are mutually exclusive")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
if (ASAN)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
if (GCOV)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
if (OPENSSL_NO_ASM)
|
||||
add_definitions(-DOPENSSL_NO_ASM)
|
||||
set(ARCH "generic")
|
||||
endif()
|
||||
|
||||
# Add minimal googletest targets. The provided one has many side-effects, and
|
||||
# googletest has a very straightforward build.
|
||||
add_library(gtest third_party/googletest/src/gtest-all.cc)
|
||||
target_include_directories(gtest PRIVATE third_party/googletest)
|
||||
|
||||
include_directories(third_party/googletest/include)
|
||||
|
||||
# Declare a dummy target to build all unit tests. Test targets should inject
|
||||
# themselves as dependencies next to the target definition.
|
||||
add_custom_target(all_tests)
|
||||
|
||||
+30
-24
@@ -23,24 +23,22 @@ Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory.
|
||||
From the `build/` directory, you can then run the fuzzers. For example:
|
||||
|
||||
```
|
||||
./fuzz/cert -max_len=10000 -jobs=32 -workers=32 ../fuzz/cert_corpus/
|
||||
./fuzz/cert -max_len=3072 -jobs=32 -workers=32 ../fuzz/cert_corpus/
|
||||
```
|
||||
|
||||
The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing. By default, libFuzzer uses the largest test in the corpus (or 64 if empty) as the maximum test case length. The `max_len` argument overrides this.
|
||||
|
||||
The recommended values of `max_len` for each test are:
|
||||
|
||||
| Test | `max_len` value |
|
||||
|---------------|-----------------|
|
||||
| `cert` | 10000 |
|
||||
| `client` | 20000 |
|
||||
| `pkcs8` | 2048 |
|
||||
| `privkey` | 2048 |
|
||||
| `server` | 4096 |
|
||||
| `session` | 8192 |
|
||||
| `spki` | 1024 |
|
||||
| `read_pem` | 512 |
|
||||
| `ssl_ctx_api` | 256 |
|
||||
| Test | `max_len` value |
|
||||
|------------|-----------------|
|
||||
| `cert` | 3072 |
|
||||
| `client` | 20000 |
|
||||
| `pkcs8` | 2048 |
|
||||
| `privkey` | 2048 |
|
||||
| `server` | 4096 |
|
||||
| `spki` | 1024 |
|
||||
| `read_pem` | 512 |
|
||||
|
||||
These were determined by rounding up the length of the largest case in the corpus.
|
||||
|
||||
@@ -54,31 +52,39 @@ In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimis
|
||||
|
||||
## Fuzzer mode
|
||||
|
||||
When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` and `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. This modifies the library to be more friendly to fuzzers. If `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` is set, BoringSSL will:
|
||||
When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` defined. This modifies the library, particularly the TLS stack, to be more friendly to fuzzers. It will:
|
||||
|
||||
* Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state.
|
||||
|
||||
* Use a hard-coded time instead of the actual time.
|
||||
|
||||
Additionally, if `BORINGSSL_UNSAFE_FUZZER_MODE` is set, BoringSSL will:
|
||||
|
||||
* Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded.
|
||||
|
||||
* Treat every cipher as the NULL cipher.
|
||||
|
||||
* Use a hard-coded time instead of the actual time.
|
||||
|
||||
* Tickets are unencrypted and the MAC check is performed but ignored.
|
||||
|
||||
This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol.
|
||||
|
||||
## TLS transcripts
|
||||
|
||||
The `client` and `server` corpora are seeded from the test suite. The test suite has a `-fuzzer` flag which mirrors the fuzzer mode changes above and a `-deterministic` flag which removes all non-determinism on the Go side. Not all tests pass, so `ssl/test/runner/fuzzer_mode.json` contains the necessary suppressions. The `run_tests` target will pass appropriate command-line flags.
|
||||
|
||||
There are separate corpora, `client_corpus_no_fuzzer_mode` and `server_corpus_no_fuzzer_mode`. These are transcripts for fuzzers with only `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. To build in this mode, pass `-DNO_FUZZER_MODE=1` into CMake. This configuration is run in the same way but without `-fuzzer` and `-shim-path` flags.
|
||||
|
||||
If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora.sh`:
|
||||
The `client` and `server` corpora are seeded from the test suite. The test suite has a `-fuzzer` flag which mirrors the fuzzer mode changes above and a `-deterministic` flag which removes all non-determinism on the Go side. Not all tests pass, so `ssl/test/runner/fuzzer_mode.json` contains the necessary suppressions. To run the tests against a fuzzer-mode `bssl_shim`, run:
|
||||
|
||||
```
|
||||
cd fuzz
|
||||
./refresh_ssl_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
|
||||
cd ssl/test/runner
|
||||
go test -fuzzer -deterministic -shim-config fuzzer_mode.json
|
||||
```
|
||||
|
||||
For a different build directory from `build/`, pass the appropriate `-shim-path` flag. If those tests pass, record a set of transcripts with:
|
||||
|
||||
```
|
||||
go test -fuzzer -deterministic -transcript-dir /tmp/transcripts/
|
||||
```
|
||||
|
||||
Note the suppressions file is ignored so disabled tests record transcripts too. Then merge into the existing corpora:
|
||||
|
||||
```
|
||||
cd build/
|
||||
./fuzz/client -max_len=50000 -merge=1 ../fuzz/client_corpus /tmp/transcripts/tls/client
|
||||
./fuzz/server -max_len=50000 -merge=1 ../fuzz/server_corpus /tmp/transcripts/tls/server
|
||||
```
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
|
||||
## Bazel
|
||||
|
||||
If you are using [Bazel](https://bazel.build) then you can incorporate
|
||||
If you are using [Bazel](http://www.bazel.io) then you can incorporate
|
||||
BoringSSL as an external repository by using a commit from the
|
||||
`master-with-bazel` branch. That branch is maintained by a bot from `master`
|
||||
and includes the needed generated files and a top-level BUILD file.
|
||||
@@ -38,7 +38,7 @@ updating things more complex.
|
||||
BoringSSL is designed to work with many different build systems. Currently,
|
||||
different projects use [GYP](https://gyp.gsrc.io/),
|
||||
[GN](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/quick_start.md),
|
||||
[Bazel](https://bazel.build/) and [Make](https://www.gnu.org/software/make/) to
|
||||
[Bazel](http://bazel.io/) and [Make](https://www.gnu.org/software/make/) to
|
||||
build BoringSSL, without too much pain.
|
||||
|
||||
The development build system is CMake and the CMake build knows how to
|
||||
|
||||
@@ -227,7 +227,6 @@ parameter.
|
||||
`SSL_CTRL_OPTIONS` | `SSL_CTX_get_options` or `SSL_CTX_set_options`
|
||||
`SSL_CTRL_SESS_NUMBER` | `SSL_CTX_sess_number`
|
||||
`SSL_CTRL_SET_CURVES` | `SSL_CTX_set1_curves`
|
||||
`SSL_CTRL_SET_ECDH_AUTO` | `SSL_CTX_set_ecdh_auto`
|
||||
`SSL_CTRL_SET_MAX_CERT_LIST` | `SSL_CTX_set_max_cert_list`
|
||||
`SSL_CTRL_SET_MAX_SEND_FRAGMENT` | `SSL_CTX_set_max_send_fragment`
|
||||
`SSL_CTRL_SET_MSG_CALLBACK` | `SSL_set_msg_callback`
|
||||
|
||||
@@ -45,16 +45,6 @@ not
|
||||
Rather than `malloc()` and `free()`, use the wrappers `OPENSSL_malloc()`
|
||||
and `OPENSSL_free()`. Use the standard C `assert()` function freely.
|
||||
|
||||
Use the following wrappers, found in `crypto/internal.h` instead of the
|
||||
corresponding C standard library functions. They behave the same but avoid
|
||||
confusing undefined behavior.
|
||||
|
||||
* `OPENSSL_memchr`
|
||||
* `OPENSSL_memcmp`
|
||||
* `OPENSSL_memcpy`
|
||||
* `OPENSSL_memmove`
|
||||
* `OPENSSL_memset`
|
||||
|
||||
For new constants, prefer enums when the values are sequential and typed
|
||||
constants for flags. If adding values to an existing set of `#define`s,
|
||||
continue with `#define`.
|
||||
|
||||
+15
-29
@@ -64,7 +64,6 @@ add_subdirectory(err)
|
||||
add_subdirectory(buf)
|
||||
add_subdirectory(base64)
|
||||
add_subdirectory(bytestring)
|
||||
add_subdirectory(pool)
|
||||
|
||||
# Level 0.2 - depends on nothing but itself
|
||||
add_subdirectory(sha)
|
||||
@@ -78,6 +77,7 @@ add_subdirectory(conf)
|
||||
add_subdirectory(chacha)
|
||||
add_subdirectory(poly1305)
|
||||
add_subdirectory(curve25519)
|
||||
add_subdirectory(newhope)
|
||||
|
||||
# Level 1, depends only on 0.*
|
||||
add_subdirectory(digest)
|
||||
@@ -129,13 +129,13 @@ add_library(
|
||||
thread_none.c
|
||||
thread_pthread.c
|
||||
thread_win.c
|
||||
time_support.c
|
||||
|
||||
$<TARGET_OBJECTS:stack>
|
||||
$<TARGET_OBJECTS:lhash>
|
||||
$<TARGET_OBJECTS:err>
|
||||
$<TARGET_OBJECTS:base64>
|
||||
$<TARGET_OBJECTS:bytestring>
|
||||
$<TARGET_OBJECTS:pool>
|
||||
$<TARGET_OBJECTS:sha>
|
||||
$<TARGET_OBJECTS:md4>
|
||||
$<TARGET_OBJECTS:md5>
|
||||
@@ -170,12 +170,24 @@ add_library(
|
||||
$<TARGET_OBJECTS:x509>
|
||||
$<TARGET_OBJECTS:x509v3>
|
||||
$<TARGET_OBJECTS:pkcs8_lib>
|
||||
$<TARGET_OBJECTS:newhope>
|
||||
)
|
||||
|
||||
if(NOT MSVC AND NOT ANDROID)
|
||||
target_link_libraries(crypto pthread)
|
||||
endif()
|
||||
|
||||
add_executable(
|
||||
constant_time_test
|
||||
|
||||
constant_time_test.c
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(constant_time_test crypto)
|
||||
add_dependencies(all_tests constant_time_test)
|
||||
|
||||
add_executable(
|
||||
thread_test
|
||||
|
||||
@@ -190,34 +202,8 @@ add_dependencies(all_tests thread_test)
|
||||
add_executable(
|
||||
refcount_test
|
||||
|
||||
refcount_test.cc
|
||||
refcount_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(refcount_test crypto)
|
||||
add_dependencies(all_tests refcount_test)
|
||||
|
||||
# TODO(davidben): Convert the remaining tests to GTest.
|
||||
add_executable(
|
||||
crypto_test
|
||||
|
||||
asn1/asn1_test.cc
|
||||
bio/bio_test.cc
|
||||
chacha/chacha_test.cc
|
||||
constant_time_test.cc
|
||||
curve25519/x25519_test.cc
|
||||
dh/dh_test.cc
|
||||
dsa/dsa_test.cc
|
||||
ec/ec_test.cc
|
||||
err/err_test.cc
|
||||
evp/evp_extra_test.cc
|
||||
rsa/rsa_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:gtest_main>
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(crypto_test crypto gtest)
|
||||
if (WIN32)
|
||||
target_link_libraries(crypto_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests crypto_test)
|
||||
|
||||
@@ -53,7 +53,6 @@ add_library(
|
||||
OBJECT
|
||||
|
||||
aes.c
|
||||
key_wrap.c
|
||||
mode_wrappers.c
|
||||
|
||||
${AES_ARCH_SOURCES}
|
||||
|
||||
+48
-136
@@ -15,176 +15,88 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
|
||||
|
||||
static bool TestRaw(FileTest *t) {
|
||||
std::vector<uint8_t> key, plaintext, ciphertext;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plaintext.size() != AES_BLOCK_SIZE ||
|
||||
ciphertext.size() != AES_BLOCK_SIZE) {
|
||||
t->PrintLine("Plaintext or Ciphertext not a block size.");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool TestAES(const uint8_t *key, size_t key_len,
|
||||
const uint8_t plaintext[AES_BLOCK_SIZE],
|
||||
const uint8_t ciphertext[AES_BLOCK_SIZE]) {
|
||||
AES_KEY aes_key;
|
||||
if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_encrypt_key failed.");
|
||||
if (AES_set_encrypt_key(key, key_len * 8, &aes_key) != 0) {
|
||||
fprintf(stderr, "AES_set_encrypt_key failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test encryption.
|
||||
uint8_t block[AES_BLOCK_SIZE];
|
||||
AES_encrypt(plaintext.data(), block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("AES_encrypt gave the wrong output.");
|
||||
AES_encrypt(plaintext, block, &aes_key);
|
||||
if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_encrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place encryption.
|
||||
OPENSSL_memcpy(block, plaintext.data(), AES_BLOCK_SIZE);
|
||||
memcpy(block, plaintext, AES_BLOCK_SIZE);
|
||||
AES_encrypt(block, block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("In-place AES_encrypt gave the wrong output.");
|
||||
if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_encrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_decrypt_key failed.");
|
||||
if (AES_set_decrypt_key(key, key_len * 8, &aes_key) != 0) {
|
||||
fprintf(stderr, "AES_set_decrypt_key failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test decryption.
|
||||
AES_decrypt(ciphertext.data(), block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("AES_decrypt gave the wrong output.");
|
||||
AES_decrypt(ciphertext, block, &aes_key);
|
||||
if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_decrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place decryption.
|
||||
OPENSSL_memcpy(block, ciphertext.data(), AES_BLOCK_SIZE);
|
||||
memcpy(block, ciphertext, AES_BLOCK_SIZE);
|
||||
AES_decrypt(block, block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("In-place AES_decrypt gave the wrong output.");
|
||||
if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_decrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestKeyWrap(FileTest *t) {
|
||||
// All test vectors use the default IV, so test both with implicit and
|
||||
// explicit IV.
|
||||
//
|
||||
// TODO(davidben): Find test vectors that use a different IV.
|
||||
static const uint8_t kDefaultIV[] = {
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> key, plaintext, ciphertext;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plaintext.size() + 8 != ciphertext.size()) {
|
||||
t->PrintLine("Invalid Plaintext and Ciphertext lengths.");
|
||||
return false;
|
||||
}
|
||||
|
||||
AES_KEY aes_key;
|
||||
if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_encrypt_key failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[ciphertext.size()]);
|
||||
if (AES_wrap_key(&aes_key, nullptr /* iv */, buf.get(), plaintext.data(),
|
||||
plaintext.size()) != static_cast<int>(ciphertext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("AES_wrap_key with implicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf.get(), 0, ciphertext.size());
|
||||
if (AES_wrap_key(&aes_key, kDefaultIV, buf.get(), plaintext.data(),
|
||||
plaintext.size()) != static_cast<int>(ciphertext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("AES_wrap_key with explicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_decrypt_key failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
buf.reset(new uint8_t[plaintext.size()]);
|
||||
if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
|
||||
ciphertext.size()) != static_cast<int>(plaintext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("AES_unwrap_key with implicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf.get(), 0, plaintext.size());
|
||||
if (AES_unwrap_key(&aes_key, kDefaultIV, buf.get(), ciphertext.data(),
|
||||
ciphertext.size()) != static_cast<int>(plaintext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("AES_unwrap_key with explicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ciphertext[0] ^= 1;
|
||||
if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
|
||||
ciphertext.size()) != -1) {
|
||||
t->PrintLine("AES_unwrap_key with bad input unexpectedly succeeded.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestAES(FileTest *t, void *arg) {
|
||||
if (t->GetParameter() == "Raw") {
|
||||
return TestRaw(t);
|
||||
}
|
||||
if (t->GetParameter() == "KeyWrap") {
|
||||
return TestKeyWrap(t);
|
||||
}
|
||||
|
||||
t->PrintLine("Unknown mode '%s'.", t->GetParameter().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file.txt>\n", argv[0]);
|
||||
return 1;
|
||||
// Test vectors from FIPS-197, Appendix C.
|
||||
if (!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
|
||||
128 / 8,
|
||||
(const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
|
||||
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
|
||||
(const uint8_t *)"\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
|
||||
"\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a") ||
|
||||
!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17",
|
||||
192 / 8,
|
||||
(const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
|
||||
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
|
||||
(const uint8_t *)"\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
|
||||
"\x6e\xaf\x70\xa0\xec\x0d\x71\x91") ||
|
||||
!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17"
|
||||
"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
|
||||
256 / 8,
|
||||
(const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
|
||||
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
|
||||
(const uint8_t *)"\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
|
||||
"\xea\xfc\x49\x90\x4b\x49\x60\x89")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return FileTestMain(TestAES, nullptr, argv[1]);
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# Test vectors from FIPS-197, Appendix C.
|
||||
|
||||
Mode = Raw
|
||||
Key = 000102030405060708090a0b0c0d0e0f
|
||||
Plaintext = 00112233445566778899aabbccddeeff
|
||||
Ciphertext = 69c4e0d86a7b0430d8cdb78070b4c55a
|
||||
|
||||
Mode = Raw
|
||||
Key = 000102030405060708090a0b0c0d0e0f1011121314151617
|
||||
Plaintext = 00112233445566778899aabbccddeeff
|
||||
Ciphertext = dda97ca4864cdfe06eaf70a0ec0d7191
|
||||
|
||||
Mode = Raw
|
||||
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
Plaintext = 00112233445566778899aabbccddeeff
|
||||
Ciphertext = 8ea2b7ca516745bfeafc49904b496089
|
||||
|
||||
|
||||
# Test vectors from
|
||||
# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
|
||||
|
||||
Mode = KeyWrap
|
||||
Key = 000102030405060708090a0b0c0d0e0f
|
||||
Plaintext = 00112233445566778899aabbccddeeff
|
||||
Ciphertext = 1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5
|
||||
|
||||
Mode = KeyWrap
|
||||
Key = 000102030405060708090a0b0c0d0e0f1011121314151617
|
||||
Plaintext = 00112233445566778899aabbccddeeff
|
||||
Ciphertext = 96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d
|
||||
|
||||
Mode = KeyWrap
|
||||
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
Plaintext = 00112233445566778899aabbccddeeff
|
||||
Ciphertext = 64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7
|
||||
|
||||
Mode = KeyWrap
|
||||
Key = 000102030405060708090a0b0c0d0e0f1011121314151617
|
||||
Plaintext = 00112233445566778899aabbccddeeff0001020304050607
|
||||
Ciphertext = 031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2
|
||||
|
||||
Mode = KeyWrap
|
||||
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
Plaintext = 00112233445566778899aabbccddeeff0001020304050607
|
||||
Ciphertext = a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1
|
||||
|
||||
Mode = KeyWrap
|
||||
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
Plaintext = 00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f
|
||||
Ciphertext = 28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21
|
||||
@@ -116,7 +116,7 @@
|
||||
# words every cache-line is *guaranteed* to be accessed within ~50
|
||||
# cycles window. Why just SSE? Because it's needed on hyper-threading
|
||||
# CPU! Which is also why it's prefetched with 64 byte stride. Best
|
||||
# part is that it has no negative effect on performance:-)
|
||||
# part is that it has no negative effect on performance:-)
|
||||
#
|
||||
# Version 4.3 implements switch between compact and non-compact block
|
||||
# functions in AES_cbc_encrypt depending on how much data was asked
|
||||
@@ -578,7 +578,7 @@ sub enctransform()
|
||||
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
# | mm4 | mm0 |
|
||||
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
# | s3 | s2 | s1 | s0 |
|
||||
# | s3 | s2 | s1 | s0 |
|
||||
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
|
||||
# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
@@ -798,7 +798,7 @@ sub encstep()
|
||||
|
||||
if ($i==3) { $tmp=$s[3]; &mov ($s[2],$__s1); }##%ecx
|
||||
elsif($i==2){ &movz ($tmp,&HB($s[3])); }#%ebx[2]
|
||||
else { &mov ($tmp,$s[3]);
|
||||
else { &mov ($tmp,$s[3]);
|
||||
&shr ($tmp,24) }
|
||||
&xor ($out,&DWP(1,$te,$tmp,8));
|
||||
if ($i<2) { &mov (&DWP(4+4*$i,"esp"),$out); }
|
||||
@@ -1551,7 +1551,7 @@ sub sse_deccompact()
|
||||
&pxor ("mm1","mm3"); &pxor ("mm5","mm7"); # tp4
|
||||
&pshufw ("mm3","mm1",0xb1); &pshufw ("mm7","mm5",0xb1);
|
||||
&pxor ("mm0","mm1"); &pxor ("mm4","mm5"); # ^= tp4
|
||||
&pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16)
|
||||
&pxor ("mm0","mm3"); &pxor ("mm4","mm7"); # ^= ROTATE(tp4,16)
|
||||
|
||||
&pxor ("mm3","mm3"); &pxor ("mm7","mm7");
|
||||
&pcmpgtb("mm3","mm1"); &pcmpgtb("mm7","mm5");
|
||||
@@ -2021,7 +2021,7 @@ sub declast()
|
||||
{
|
||||
# stack frame layout
|
||||
# -4(%esp) # return address 0(%esp)
|
||||
# 0(%esp) # s0 backing store 4(%esp)
|
||||
# 0(%esp) # s0 backing store 4(%esp)
|
||||
# 4(%esp) # s1 backing store 8(%esp)
|
||||
# 8(%esp) # s2 backing store 12(%esp)
|
||||
# 12(%esp) # s3 backing store 16(%esp)
|
||||
@@ -2731,7 +2731,7 @@ sub enckey()
|
||||
&mov (&DWP(80,"edi"),10); # setup number of rounds
|
||||
&xor ("eax","eax");
|
||||
&jmp (&label("exit"));
|
||||
|
||||
|
||||
&set_label("12rounds");
|
||||
&mov ("eax",&DWP(0,"esi")); # copy first 6 dwords
|
||||
&mov ("ebx",&DWP(4,"esi"));
|
||||
|
||||
Executable → Regular
+24
-22
@@ -590,7 +590,6 @@ $code.=<<___;
|
||||
.type asm_AES_encrypt,\@function,3
|
||||
.hidden asm_AES_encrypt
|
||||
asm_AES_encrypt:
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
@@ -599,6 +598,7 @@ asm_AES_encrypt:
|
||||
push %r15
|
||||
|
||||
# allocate frame "above" key schedule
|
||||
mov %rsp,%r10
|
||||
lea -63(%rdx),%rcx # %rdx is key argument
|
||||
and \$-64,%rsp
|
||||
sub %rsp,%rcx
|
||||
@@ -608,7 +608,7 @@ asm_AES_encrypt:
|
||||
sub \$32,%rsp
|
||||
|
||||
mov %rsi,16(%rsp) # save out
|
||||
mov %rax,24(%rsp) # save original stack pointer
|
||||
mov %r10,24(%rsp) # save real stack pointer
|
||||
.Lenc_prologue:
|
||||
|
||||
mov %rdx,$key
|
||||
@@ -640,13 +640,13 @@ asm_AES_encrypt:
|
||||
mov $s2,8($out)
|
||||
mov $s3,12($out)
|
||||
|
||||
mov -48(%rsi),%r15
|
||||
mov -40(%rsi),%r14
|
||||
mov -32(%rsi),%r13
|
||||
mov -24(%rsi),%r12
|
||||
mov -16(%rsi),%rbp
|
||||
mov -8(%rsi),%rbx
|
||||
lea (%rsi),%rsp
|
||||
mov (%rsi),%r15
|
||||
mov 8(%rsi),%r14
|
||||
mov 16(%rsi),%r13
|
||||
mov 24(%rsi),%r12
|
||||
mov 32(%rsi),%rbp
|
||||
mov 40(%rsi),%rbx
|
||||
lea 48(%rsi),%rsp
|
||||
.Lenc_epilogue:
|
||||
ret
|
||||
.size asm_AES_encrypt,.-asm_AES_encrypt
|
||||
@@ -1186,7 +1186,6 @@ $code.=<<___;
|
||||
.type asm_AES_decrypt,\@function,3
|
||||
.hidden asm_AES_decrypt
|
||||
asm_AES_decrypt:
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
@@ -1195,6 +1194,7 @@ asm_AES_decrypt:
|
||||
push %r15
|
||||
|
||||
# allocate frame "above" key schedule
|
||||
mov %rsp,%r10
|
||||
lea -63(%rdx),%rcx # %rdx is key argument
|
||||
and \$-64,%rsp
|
||||
sub %rsp,%rcx
|
||||
@@ -1204,7 +1204,7 @@ asm_AES_decrypt:
|
||||
sub \$32,%rsp
|
||||
|
||||
mov %rsi,16(%rsp) # save out
|
||||
mov %rax,24(%rsp) # save original stack pointer
|
||||
mov %r10,24(%rsp) # save real stack pointer
|
||||
.Ldec_prologue:
|
||||
|
||||
mov %rdx,$key
|
||||
@@ -1238,13 +1238,13 @@ asm_AES_decrypt:
|
||||
mov $s2,8($out)
|
||||
mov $s3,12($out)
|
||||
|
||||
mov -48(%rsi),%r15
|
||||
mov -40(%rsi),%r14
|
||||
mov -32(%rsi),%r13
|
||||
mov -24(%rsi),%r12
|
||||
mov -16(%rsi),%rbp
|
||||
mov -8(%rsi),%rbx
|
||||
lea (%rsi),%rsp
|
||||
mov (%rsi),%r15
|
||||
mov 8(%rsi),%r14
|
||||
mov 16(%rsi),%r13
|
||||
mov 24(%rsi),%r12
|
||||
mov 32(%rsi),%rbp
|
||||
mov 40(%rsi),%rbx
|
||||
lea 48(%rsi),%rsp
|
||||
.Ldec_epilogue:
|
||||
ret
|
||||
.size asm_AES_decrypt,.-asm_AES_decrypt
|
||||
@@ -1286,7 +1286,7 @@ $code.=<<___;
|
||||
asm_AES_set_encrypt_key:
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12 # redundant, but allows to share
|
||||
push %r12 # redundant, but allows to share
|
||||
push %r13 # exception handler...
|
||||
push %r14
|
||||
push %r15
|
||||
@@ -1412,7 +1412,7 @@ $code.=<<___;
|
||||
xor %rax,%rax
|
||||
jmp .Lexit
|
||||
|
||||
.L14rounds:
|
||||
.L14rounds:
|
||||
mov 0(%rsi),%rax # copy first 8 dwords
|
||||
mov 8(%rsi),%rbx
|
||||
mov 16(%rsi),%rcx
|
||||
@@ -1660,9 +1660,10 @@ asm_AES_cbc_encrypt:
|
||||
mov %r9d,%r9d # clear upper half of enc
|
||||
|
||||
lea .LAES_Te(%rip),$sbox
|
||||
lea .LAES_Td(%rip),%r10
|
||||
cmp \$0,%r9
|
||||
cmoveq %r10,$sbox
|
||||
jne .Lcbc_picked_te
|
||||
lea .LAES_Td(%rip),$sbox
|
||||
.Lcbc_picked_te:
|
||||
|
||||
mov OPENSSL_ia32cap_P(%rip),%r10d
|
||||
cmp \$$speed_limit,%rdx
|
||||
@@ -2564,6 +2565,7 @@ block_se_handler:
|
||||
jae .Lin_block_prologue
|
||||
|
||||
mov 24(%rax),%rax # pull saved real stack pointer
|
||||
lea 48(%rax),%rax # adjust...
|
||||
|
||||
mov -8(%rax),%rbx
|
||||
mov -16(%rax),%rbp
|
||||
|
||||
@@ -51,9 +51,7 @@
|
||||
# Westmere 3.77/1.37 1.37 1.52 1.27
|
||||
# * Bridge 5.07/0.98 0.99 1.09 0.91
|
||||
# Haswell 4.44/0.80 0.97 1.03 0.72
|
||||
# Skylake 2.68/0.65 0.65 0.66 0.64
|
||||
# Silvermont 5.77/3.56 3.67 4.03 3.46
|
||||
# Goldmont 3.84/1.39 1.39 1.63 1.31
|
||||
# Bulldozer 5.80/0.98 1.05 1.24 0.93
|
||||
|
||||
$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
|
||||
@@ -1042,7 +1040,7 @@ if ($PREFIX eq "aesni") {
|
||||
&set_label("ctr32_one_shortcut",16);
|
||||
&movups ($inout0,&QWP(0,$rounds_)); # load ivec
|
||||
&mov ($rounds,&DWP(240,$key));
|
||||
|
||||
|
||||
&set_label("ctr32_one");
|
||||
if ($inline)
|
||||
{ &aesni_inline_generate1("enc"); }
|
||||
|
||||
+135
-1151
File diff suppressed because it is too large
Load Diff
@@ -3011,7 +3011,7 @@ _aesp8_xts_enc5x:
|
||||
vxor $twk0,$twk0,v31
|
||||
|
||||
vcipher $out0,$out0,v26
|
||||
lvsr $inpperm,0,$taillen # $in5 is no more
|
||||
lvsr $inpperm,r0,$taillen # $in5 is no more
|
||||
vcipher $out1,$out1,v26
|
||||
vcipher $out2,$out2,v26
|
||||
vcipher $out3,$out3,v26
|
||||
@@ -3773,7 +3773,7 @@ foreach(split("\n",$code)) {
|
||||
if ($flavour =~ /le$/o) {
|
||||
SWITCH: for($conv) {
|
||||
/\?inv/ && do { @bytes=map($_^0xf,@bytes); last; };
|
||||
/\?rev/ && do { @bytes=reverse(@bytes); last; };
|
||||
/\?rev/ && do { @bytes=reverse(@bytes); last; };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -957,21 +957,21 @@ if ($flavour =~ /64/) { ######## 64-bit code
|
||||
|
||||
$arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o &&
|
||||
sprintf "vtbl.8 d%d,{q%d},d%d\n\t".
|
||||
"vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
|
||||
"vtbl.8 d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
|
||||
}
|
||||
|
||||
sub unvdup32 {
|
||||
my $arg=shift;
|
||||
|
||||
$arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
|
||||
sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
|
||||
sprintf "vdup.32 q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
|
||||
}
|
||||
|
||||
sub unvmov32 {
|
||||
my $arg=shift;
|
||||
|
||||
$arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o &&
|
||||
sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
|
||||
sprintf "vmov.32 d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
|
||||
}
|
||||
|
||||
foreach(split("\n",$code)) {
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||
@@ -91,7 +84,7 @@ my @s=@_[12..15];
|
||||
|
||||
sub InBasisChange {
|
||||
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
|
||||
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
|
||||
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
|
||||
my @b=@_[0..7];
|
||||
$code.=<<___;
|
||||
veor @b[2], @b[2], @b[1]
|
||||
@@ -738,7 +731,6 @@ $code.=<<___;
|
||||
.thumb
|
||||
#else
|
||||
.code 32
|
||||
# undef __thumb2__
|
||||
#endif
|
||||
|
||||
.type _bsaes_decrypt8,%function
|
||||
@@ -1365,7 +1357,7 @@ bsaes_cbc_encrypt:
|
||||
vmov @XMM[4],@XMM[15] @ just in case ensure that IV
|
||||
vmov @XMM[5],@XMM[0] @ and input are preserved
|
||||
bl AES_decrypt
|
||||
vld1.8 {@XMM[0]}, [$fp] @ load result
|
||||
vld1.8 {@XMM[0]}, [$fp,:64] @ load result
|
||||
veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
|
||||
vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
|
||||
vst1.8 {@XMM[0]}, [$rounds] @ write output
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
# Nehalem(**) 7.63 6.88 +11%
|
||||
# Atom 17.1 16.4 +4%
|
||||
# Silvermont - 12.9
|
||||
# Goldmont - 8.85
|
||||
#
|
||||
# (*) Comparison is not completely fair, because "this" is ECB,
|
||||
# i.e. no extra processing such as counter values calculation
|
||||
@@ -81,7 +80,6 @@
|
||||
# Nehalem 7.80
|
||||
# Atom 17.9
|
||||
# Silvermont 14.0
|
||||
# Goldmont 10.2
|
||||
#
|
||||
# November 2011.
|
||||
#
|
||||
@@ -124,7 +122,7 @@ my @s=@_[12..15];
|
||||
|
||||
sub InBasisChange {
|
||||
# input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
|
||||
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
|
||||
# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
|
||||
my @b=@_[0..7];
|
||||
$code.=<<___;
|
||||
pxor @b[6], @b[5]
|
||||
@@ -374,7 +372,7 @@ $code.=<<___;
|
||||
pxor @s[0], @t[3]
|
||||
pxor @s[1], @t[2]
|
||||
pxor @s[2], @t[1]
|
||||
pxor @s[3], @t[0]
|
||||
pxor @s[3], @t[0]
|
||||
|
||||
#Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
|
||||
|
||||
@@ -1327,7 +1325,7 @@ $code.=<<___;
|
||||
cmp %rax, %rbp
|
||||
jb .Lecb_enc_bzero
|
||||
|
||||
lea 0x78(%rbp),%rax
|
||||
lea (%rbp),%rsp # restore %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x40(%rbp), %xmm6
|
||||
@@ -1340,17 +1338,17 @@ $code.=<<___ if ($win64);
|
||||
movaps 0xb0(%rbp), %xmm13
|
||||
movaps 0xc0(%rbp), %xmm14
|
||||
movaps 0xd0(%rbp), %xmm15
|
||||
lea 0xa0(%rax), %rax
|
||||
.Lecb_enc_tail:
|
||||
lea 0xa0(%rbp), %rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax), %r15
|
||||
mov -40(%rax), %r14
|
||||
mov -32(%rax), %r13
|
||||
mov -24(%rax), %r12
|
||||
mov -16(%rax), %rbx
|
||||
mov -8(%rax), %rbp
|
||||
lea (%rax), %rsp # restore %rsp
|
||||
mov 0x48(%rsp), %r15
|
||||
mov 0x50(%rsp), %r14
|
||||
mov 0x58(%rsp), %r13
|
||||
mov 0x60(%rsp), %r12
|
||||
mov 0x68(%rsp), %rbx
|
||||
mov 0x70(%rsp), %rax
|
||||
lea 0x78(%rsp), %rsp
|
||||
mov %rax, %rbp
|
||||
.Lecb_enc_epilogue:
|
||||
ret
|
||||
.size bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
|
||||
@@ -1529,7 +1527,7 @@ $code.=<<___;
|
||||
cmp %rax, %rbp
|
||||
jb .Lecb_dec_bzero
|
||||
|
||||
lea 0x78(%rbp),%rax
|
||||
lea (%rbp),%rsp # restore %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x40(%rbp), %xmm6
|
||||
@@ -1542,17 +1540,17 @@ $code.=<<___ if ($win64);
|
||||
movaps 0xb0(%rbp), %xmm13
|
||||
movaps 0xc0(%rbp), %xmm14
|
||||
movaps 0xd0(%rbp), %xmm15
|
||||
lea 0xa0(%rax), %rax
|
||||
.Lecb_dec_tail:
|
||||
lea 0xa0(%rbp), %rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax), %r15
|
||||
mov -40(%rax), %r14
|
||||
mov -32(%rax), %r13
|
||||
mov -24(%rax), %r12
|
||||
mov -16(%rax), %rbx
|
||||
mov -8(%rax), %rbp
|
||||
lea (%rax), %rsp # restore %rsp
|
||||
mov 0x48(%rsp), %r15
|
||||
mov 0x50(%rsp), %r14
|
||||
mov 0x58(%rsp), %r13
|
||||
mov 0x60(%rsp), %r12
|
||||
mov 0x68(%rsp), %rbx
|
||||
mov 0x70(%rsp), %rax
|
||||
lea 0x78(%rsp), %rsp
|
||||
mov %rax, %rbp
|
||||
.Lecb_dec_epilogue:
|
||||
ret
|
||||
.size bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
|
||||
@@ -1819,7 +1817,7 @@ $code.=<<___;
|
||||
cmp %rax, %rbp
|
||||
ja .Lcbc_dec_bzero
|
||||
|
||||
lea 0x78(%rbp),%rax
|
||||
lea (%rbp),%rsp # restore %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x40(%rbp), %xmm6
|
||||
@@ -1832,17 +1830,17 @@ $code.=<<___ if ($win64);
|
||||
movaps 0xb0(%rbp), %xmm13
|
||||
movaps 0xc0(%rbp), %xmm14
|
||||
movaps 0xd0(%rbp), %xmm15
|
||||
lea 0xa0(%rax), %rax
|
||||
.Lcbc_dec_tail:
|
||||
lea 0xa0(%rbp), %rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax), %r15
|
||||
mov -40(%rax), %r14
|
||||
mov -32(%rax), %r13
|
||||
mov -24(%rax), %r12
|
||||
mov -16(%rax), %rbx
|
||||
mov -8(%rax), %rbp
|
||||
lea (%rax), %rsp # restore %rsp
|
||||
mov 0x48(%rsp), %r15
|
||||
mov 0x50(%rsp), %r14
|
||||
mov 0x58(%rsp), %r13
|
||||
mov 0x60(%rsp), %r12
|
||||
mov 0x68(%rsp), %rbx
|
||||
mov 0x70(%rsp), %rax
|
||||
lea 0x78(%rsp), %rsp
|
||||
mov %rax, %rbp
|
||||
.Lcbc_dec_epilogue:
|
||||
ret
|
||||
.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
|
||||
@@ -2051,7 +2049,7 @@ $code.=<<___;
|
||||
cmp %rax, %rbp
|
||||
ja .Lctr_enc_bzero
|
||||
|
||||
lea 0x78(%rbp),%rax
|
||||
lea (%rbp),%rsp # restore %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x40(%rbp), %xmm6
|
||||
@@ -2064,17 +2062,17 @@ $code.=<<___ if ($win64);
|
||||
movaps 0xb0(%rbp), %xmm13
|
||||
movaps 0xc0(%rbp), %xmm14
|
||||
movaps 0xd0(%rbp), %xmm15
|
||||
lea 0xa0(%rax), %rax
|
||||
.Lctr_enc_tail:
|
||||
lea 0xa0(%rbp), %rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax), %r15
|
||||
mov -40(%rax), %r14
|
||||
mov -32(%rax), %r13
|
||||
mov -24(%rax), %r12
|
||||
mov -16(%rax), %rbx
|
||||
mov -8(%rax), %rbp
|
||||
lea (%rax), %rsp # restore %rsp
|
||||
mov 0x48(%rsp), %r15
|
||||
mov 0x50(%rsp), %r14
|
||||
mov 0x58(%rsp), %r13
|
||||
mov 0x60(%rsp), %r12
|
||||
mov 0x68(%rsp), %rbx
|
||||
mov 0x70(%rsp), %rax
|
||||
lea 0x78(%rsp), %rsp
|
||||
mov %rax, %rbp
|
||||
.Lctr_enc_epilogue:
|
||||
ret
|
||||
.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
|
||||
@@ -2441,7 +2439,7 @@ $code.=<<___;
|
||||
cmp %rax, %rbp
|
||||
ja .Lxts_enc_bzero
|
||||
|
||||
lea 0x78(%rbp),%rax
|
||||
lea (%rbp),%rsp # restore %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x40(%rbp), %xmm6
|
||||
@@ -2454,17 +2452,17 @@ $code.=<<___ if ($win64);
|
||||
movaps 0xb0(%rbp), %xmm13
|
||||
movaps 0xc0(%rbp), %xmm14
|
||||
movaps 0xd0(%rbp), %xmm15
|
||||
lea 0xa0(%rax), %rax
|
||||
.Lxts_enc_tail:
|
||||
lea 0xa0(%rbp), %rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax), %r15
|
||||
mov -40(%rax), %r14
|
||||
mov -32(%rax), %r13
|
||||
mov -24(%rax), %r12
|
||||
mov -16(%rax), %rbx
|
||||
mov -8(%rax), %rbp
|
||||
lea (%rax), %rsp # restore %rsp
|
||||
mov 0x48(%rsp), %r15
|
||||
mov 0x50(%rsp), %r14
|
||||
mov 0x58(%rsp), %r13
|
||||
mov 0x60(%rsp), %r12
|
||||
mov 0x68(%rsp), %rbx
|
||||
mov 0x70(%rsp), %rax
|
||||
lea 0x78(%rsp), %rsp
|
||||
mov %rax, %rbp
|
||||
.Lxts_enc_epilogue:
|
||||
ret
|
||||
.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
|
||||
@@ -2848,7 +2846,7 @@ $code.=<<___;
|
||||
cmp %rax, %rbp
|
||||
ja .Lxts_dec_bzero
|
||||
|
||||
lea 0x78(%rbp),%rax
|
||||
lea (%rbp),%rsp # restore %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x40(%rbp), %xmm6
|
||||
@@ -2861,17 +2859,17 @@ $code.=<<___ if ($win64);
|
||||
movaps 0xb0(%rbp), %xmm13
|
||||
movaps 0xc0(%rbp), %xmm14
|
||||
movaps 0xd0(%rbp), %xmm15
|
||||
lea 0xa0(%rax), %rax
|
||||
.Lxts_dec_tail:
|
||||
lea 0xa0(%rbp), %rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax), %r15
|
||||
mov -40(%rax), %r14
|
||||
mov -32(%rax), %r13
|
||||
mov -24(%rax), %r12
|
||||
mov -16(%rax), %rbx
|
||||
mov -8(%rax), %rbp
|
||||
lea (%rax), %rsp # restore %rsp
|
||||
mov 0x48(%rsp), %r15
|
||||
mov 0x50(%rsp), %r14
|
||||
mov 0x58(%rsp), %r13
|
||||
mov 0x60(%rsp), %r12
|
||||
mov 0x68(%rsp), %rbx
|
||||
mov 0x70(%rsp), %rax
|
||||
lea 0x78(%rsp), %rsp
|
||||
mov %rax, %rbp
|
||||
.Lxts_dec_epilogue:
|
||||
ret
|
||||
.size bsaes_xts_decrypt,.-bsaes_xts_decrypt
|
||||
@@ -2967,34 +2965,31 @@ se_handler:
|
||||
|
||||
mov 0(%r11),%r10d # HandlerData[0]
|
||||
lea (%rsi,%r10),%r10 # prologue label
|
||||
cmp %r10,%rbx # context->Rip<=prologue label
|
||||
jbe .Lin_prologue
|
||||
cmp %r10,%rbx # context->Rip<prologue label
|
||||
jb .Lin_prologue
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=epilogue label
|
||||
jae .Lin_prologue
|
||||
|
||||
mov 8(%r11),%r10d # HandlerData[2]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=tail label
|
||||
jae .Lin_tail
|
||||
|
||||
mov 160($context),%rax # pull context->Rbp
|
||||
|
||||
lea 0x40(%rax),%rsi # %xmm save area
|
||||
lea 512($context),%rdi # &context.Xmm6
|
||||
mov \$20,%ecx # 10*sizeof(%xmm0)/sizeof(%rax)
|
||||
.long 0xa548f3fc # cld; rep movsq
|
||||
lea 0xa0+0x78(%rax),%rax # adjust stack pointer
|
||||
lea 0xa0(%rax),%rax # adjust stack pointer
|
||||
|
||||
.Lin_tail:
|
||||
mov -48(%rax),%rbp
|
||||
mov -40(%rax),%rbx
|
||||
mov -32(%rax),%r12
|
||||
mov -24(%rax),%r13
|
||||
mov -16(%rax),%r14
|
||||
mov -8(%rax),%r15
|
||||
mov 0x70(%rax),%rbp
|
||||
mov 0x68(%rax),%rbx
|
||||
mov 0x60(%rax),%r12
|
||||
mov 0x58(%rax),%r13
|
||||
mov 0x50(%rax),%r14
|
||||
mov 0x48(%rax),%r15
|
||||
lea 0x78(%rax),%rax # adjust stack pointer
|
||||
mov %rbx,144($context) # restore context->Rbx
|
||||
mov %rbp,160($context) # restore context->Rbp
|
||||
mov %r12,216($context) # restore context->R12
|
||||
@@ -3075,40 +3070,28 @@ $code.=<<___ if ($ecb);
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lecb_enc_body,.Lecb_enc_epilogue # HandlerData[]
|
||||
.rva .Lecb_enc_tail
|
||||
.long 0
|
||||
.Lecb_dec_info:
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lecb_dec_body,.Lecb_dec_epilogue # HandlerData[]
|
||||
.rva .Lecb_dec_tail
|
||||
.long 0
|
||||
___
|
||||
$code.=<<___;
|
||||
.Lcbc_dec_info:
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lcbc_dec_body,.Lcbc_dec_epilogue # HandlerData[]
|
||||
.rva .Lcbc_dec_tail
|
||||
.long 0
|
||||
.Lctr_enc_info:
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lctr_enc_body,.Lctr_enc_epilogue # HandlerData[]
|
||||
.rva .Lctr_enc_tail
|
||||
.long 0
|
||||
.Lxts_enc_info:
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lxts_enc_body,.Lxts_enc_epilogue # HandlerData[]
|
||||
.rva .Lxts_enc_tail
|
||||
.long 0
|
||||
.Lxts_dec_info:
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lxts_dec_body,.Lxts_dec_epilogue # HandlerData[]
|
||||
.rva .Lxts_dec_tail
|
||||
.long 0
|
||||
___
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +438,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
|
||||
##
|
||||
&set_label("schedule_192",16);
|
||||
&movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned)
|
||||
&call ("_vpaes_schedule_transform"); # input transform
|
||||
&call ("_vpaes_schedule_transform"); # input transform
|
||||
&movdqa ("xmm6","xmm0"); # save short part
|
||||
&pxor ("xmm4","xmm4"); # clear 4
|
||||
&movhlps("xmm6","xmm4"); # clobber low side with zeros
|
||||
@@ -469,7 +469,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
|
||||
##
|
||||
&set_label("schedule_256",16);
|
||||
&movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned)
|
||||
&call ("_vpaes_schedule_transform"); # input transform
|
||||
&call ("_vpaes_schedule_transform"); # input transform
|
||||
&mov ($round,7);
|
||||
|
||||
&set_label("loop_schedule_256");
|
||||
@@ -480,7 +480,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
|
||||
&call ("_vpaes_schedule_round");
|
||||
&dec ($round);
|
||||
&jz (&label("schedule_mangle_last"));
|
||||
&call ("_vpaes_schedule_mangle");
|
||||
&call ("_vpaes_schedule_mangle");
|
||||
|
||||
# low round. swap xmm7 and xmm6
|
||||
&pshufd ("xmm0","xmm0",0xFF);
|
||||
@@ -603,7 +603,7 @@ $k_dsbo=0x2c0; # decryption sbox final output
|
||||
# subbyte
|
||||
&movdqa ("xmm4",&QWP($k_s0F,$const));
|
||||
&movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j
|
||||
&movdqa ("xmm1","xmm4");
|
||||
&movdqa ("xmm1","xmm4");
|
||||
&pandn ("xmm1","xmm0");
|
||||
&psrld ("xmm1",4); # 1 = i
|
||||
&pand ("xmm0","xmm4"); # 0 = k
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
# Nehalem 29.6/40.3/14.6 10.0/11.8
|
||||
# Atom 57.3/74.2/32.1 60.9/77.2(***)
|
||||
# Silvermont 52.7/64.0/19.5 48.8/60.8(***)
|
||||
# Goldmont 38.9/49.0/17.8 10.6/12.6
|
||||
#
|
||||
# (*) "Hyper-threading" in the context refers rather to cache shared
|
||||
# among multiple cores, than to specifically Intel HTT. As vast
|
||||
@@ -165,7 +164,7 @@ _vpaes_encrypt_core:
|
||||
pshufb %xmm1, %xmm0
|
||||
ret
|
||||
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
|
||||
|
||||
|
||||
##
|
||||
## Decryption core
|
||||
##
|
||||
@@ -326,7 +325,7 @@ _vpaes_schedule_core:
|
||||
##
|
||||
.Lschedule_128:
|
||||
mov \$10, %esi
|
||||
|
||||
|
||||
.Loop_schedule_128:
|
||||
call _vpaes_schedule_round
|
||||
dec %rsi
|
||||
@@ -360,7 +359,7 @@ _vpaes_schedule_core:
|
||||
|
||||
.Loop_schedule_192:
|
||||
call _vpaes_schedule_round
|
||||
palignr \$8,%xmm6,%xmm0
|
||||
palignr \$8,%xmm6,%xmm0
|
||||
call _vpaes_schedule_mangle # save key n
|
||||
call _vpaes_schedule_192_smear
|
||||
call _vpaes_schedule_mangle # save key n+1
|
||||
@@ -386,7 +385,7 @@ _vpaes_schedule_core:
|
||||
movdqu 16(%rdi),%xmm0 # load key part 2 (unaligned)
|
||||
call _vpaes_schedule_transform # input transform
|
||||
mov \$7, %esi
|
||||
|
||||
|
||||
.Loop_schedule_256:
|
||||
call _vpaes_schedule_mangle # output low result
|
||||
movdqa %xmm0, %xmm6 # save cur_lo in xmm6
|
||||
@@ -395,7 +394,7 @@ _vpaes_schedule_core:
|
||||
call _vpaes_schedule_round
|
||||
dec %rsi
|
||||
jz .Lschedule_mangle_last
|
||||
call _vpaes_schedule_mangle
|
||||
call _vpaes_schedule_mangle
|
||||
|
||||
# low round. swap xmm7 and xmm6
|
||||
pshufd \$0xFF, %xmm0, %xmm0
|
||||
@@ -403,10 +402,10 @@ _vpaes_schedule_core:
|
||||
movdqa %xmm6, %xmm7
|
||||
call _vpaes_schedule_low_round
|
||||
movdqa %xmm5, %xmm7
|
||||
|
||||
|
||||
jmp .Loop_schedule_256
|
||||
|
||||
|
||||
|
||||
##
|
||||
## .aes_schedule_mangle_last
|
||||
##
|
||||
@@ -505,9 +504,9 @@ _vpaes_schedule_round:
|
||||
# rotate
|
||||
pshufd \$0xFF, %xmm0, %xmm0
|
||||
palignr \$1, %xmm0, %xmm0
|
||||
|
||||
|
||||
# fall through...
|
||||
|
||||
|
||||
# low round: same as high round, but no rotation and no rcon.
|
||||
_vpaes_schedule_low_round:
|
||||
# smear xmm7
|
||||
@@ -546,7 +545,7 @@ _vpaes_schedule_low_round:
|
||||
pxor %xmm4, %xmm0 # 0 = sbox output
|
||||
|
||||
# add in smeared stuff
|
||||
pxor %xmm7, %xmm0
|
||||
pxor %xmm7, %xmm0
|
||||
movdqa %xmm0, %xmm7
|
||||
ret
|
||||
.size _vpaes_schedule_round,.-_vpaes_schedule_round
|
||||
|
||||
@@ -35,5 +35,17 @@ add_library(
|
||||
tasn_new.c
|
||||
tasn_typ.c
|
||||
tasn_utl.c
|
||||
time_support.c
|
||||
x_bignum.c
|
||||
x_long.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
asn1_test
|
||||
|
||||
asn1_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(asn1_test crypto)
|
||||
add_dependencies(all_tests asn1_test)
|
||||
|
||||
@@ -61,9 +61,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
{
|
||||
return M_ASN1_BIT_STRING_set(x, d, len);
|
||||
@@ -118,7 +115,7 @@ int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
|
||||
*(p++) = (unsigned char)bits;
|
||||
d = a->data;
|
||||
OPENSSL_memcpy(p, d, len);
|
||||
memcpy(p, d, len);
|
||||
p += len;
|
||||
if (len > 0)
|
||||
p[-1] &= (0xff << bits);
|
||||
@@ -165,7 +162,7 @@ ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
memcpy(s, p, (int)len);
|
||||
s[len - 1] &= (0xff << padding);
|
||||
p += len;
|
||||
} else
|
||||
@@ -218,7 +215,7 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
|
||||
return 0;
|
||||
}
|
||||
if (w + 1 - a->length > 0)
|
||||
OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
|
||||
memset(c + a->length, 0, w + 1 - a->length);
|
||||
a->data = c;
|
||||
a->length = w + 1;
|
||||
}
|
||||
|
||||
@@ -61,9 +61,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
|
||||
* for comments on encoding see a_int.c
|
||||
@@ -82,7 +79,7 @@ int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
+15
-20
@@ -61,6 +61,7 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
@@ -219,43 +220,37 @@ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
ASN1_GENERALIZEDTIME *tmps = NULL;
|
||||
|
||||
if (s == NULL)
|
||||
tmps = ASN1_GENERALIZEDTIME_new();
|
||||
else
|
||||
tmps = s;
|
||||
if (tmps == NULL)
|
||||
return NULL;
|
||||
s = M_ASN1_GENERALIZEDTIME_new();
|
||||
if (s == NULL)
|
||||
return (NULL);
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
return (NULL);
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = (char *)tmps->data;
|
||||
if ((p == NULL) || ((size_t)tmps->length < len)) {
|
||||
p = (char *)s->data;
|
||||
if ((p == NULL) || ((size_t)s->length < len)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
return (NULL);
|
||||
}
|
||||
OPENSSL_free(tmps->data);
|
||||
tmps->data = (unsigned char *)p;
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data = (unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
tmps->length = strlen(p);
|
||||
tmps->type = V_ASN1_GENERALIZEDTIME;
|
||||
return tmps;
|
||||
err:
|
||||
if (s == NULL)
|
||||
ASN1_GENERALIZEDTIME_free(tmps);
|
||||
return NULL;
|
||||
s->length = strlen(p);
|
||||
s->type = V_ASN1_GENERALIZEDTIME;
|
||||
return (s);
|
||||
}
|
||||
|
||||
+4
-7
@@ -61,9 +61,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
|
||||
{
|
||||
return M_ASN1_INTEGER_dup(x);
|
||||
@@ -160,7 +157,7 @@ int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
|
||||
if (a->length == 0)
|
||||
*(p++) = 0;
|
||||
else if (!neg)
|
||||
OPENSSL_memcpy(p, a->data, (unsigned int)a->length);
|
||||
memcpy(p, a->data, (unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n = a->data + a->length - 1;
|
||||
@@ -257,7 +254,7 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
memcpy(s, p, (int)len);
|
||||
}
|
||||
|
||||
if (ret->data != NULL)
|
||||
@@ -325,7 +322,7 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
OPENSSL_memcpy(s, p, (int)len);
|
||||
memcpy(s, p, (int)len);
|
||||
p += len;
|
||||
}
|
||||
|
||||
@@ -357,7 +354,7 @@ int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
@@ -63,9 +63,6 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p;
|
||||
@@ -80,7 +77,7 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
|
||||
p = *pp;
|
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||
OPENSSL_memcpy(p, a->data, a->length);
|
||||
memcpy(p, a->data, a->length);
|
||||
p += a->length;
|
||||
|
||||
*pp = p;
|
||||
@@ -324,7 +321,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
}
|
||||
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
OPENSSL_memcpy(data, p, length);
|
||||
memcpy(data, p, length);
|
||||
/* reattach data to object, after which it remains const */
|
||||
ret->data = data;
|
||||
ret->length = length;
|
||||
|
||||
+10
-17
@@ -63,6 +63,7 @@
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
@@ -114,7 +115,7 @@ int ASN1_TIME_check(ASN1_TIME *t)
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
@@ -123,21 +124,22 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
goto err;
|
||||
} else {
|
||||
return NULL;
|
||||
if (out)
|
||||
*out = ret;
|
||||
} else
|
||||
ret = *out;
|
||||
}
|
||||
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!ASN1_STRING_set(ret, t->data, t->length))
|
||||
goto err;
|
||||
goto done;
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
goto err;
|
||||
return NULL;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
@@ -149,18 +151,9 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
done:
|
||||
if (out != NULL && *out == NULL)
|
||||
*out = ret;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (out == NULL || *out != ret)
|
||||
ASN1_GENERALIZEDTIME_free(ret);
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
@@ -269,7 +270,7 @@ time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
|
||||
struct tm tm;
|
||||
int offset;
|
||||
|
||||
OPENSSL_memset(&tm, '\0', sizeof tm);
|
||||
memset(&tm, '\0', sizeof tm);
|
||||
|
||||
# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
|
||||
tm.tm_year = g2(s->data);
|
||||
|
||||
@@ -63,9 +63,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
|
||||
|
||||
@@ -404,7 +401,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
|
||||
}
|
||||
str->length = len;
|
||||
if (data != NULL) {
|
||||
OPENSSL_memcpy(str->data, data, len);
|
||||
memcpy(str->data, data, len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len] = '\0';
|
||||
}
|
||||
@@ -455,7 +452,7 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
|
||||
|
||||
i = (a->length - b->length);
|
||||
if (i == 0) {
|
||||
i = OPENSSL_memcmp(a->data, b->data, a->length);
|
||||
i = memcmp(a->data, b->data, a->length);
|
||||
if (i == 0)
|
||||
return (a->type - b->type);
|
||||
else
|
||||
|
||||
@@ -57,42 +57,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
|
||||
#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Wrapper functions for time functions. */
|
||||
|
||||
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
|
||||
struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
|
||||
|
||||
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
|
||||
* seconds. */
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
|
||||
|
||||
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
|
||||
* outputs the difference as a number of days and seconds in |*out_days| and
|
||||
* |*out_secs|. */
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
|
||||
const struct tm *to);
|
||||
|
||||
|
||||
/* Internal ASN1 structures and functions: not for application use */
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */
|
||||
|
||||
+29
-12
@@ -14,13 +14,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
// kTag128 is an ASN.1 structure with a universal tag with number 128.
|
||||
static const uint8_t kTag128[] = {
|
||||
@@ -41,22 +38,42 @@ static const uint8_t kTagOverflow[] = {
|
||||
0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
|
||||
};
|
||||
|
||||
TEST(ASN1Test, LargeTags) {
|
||||
static bool TestLargeTags() {
|
||||
const uint8_t *p = kTag258;
|
||||
bssl::UniquePtr<ASN1_TYPE> obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
|
||||
EXPECT_FALSE(obj) << "Parsed value with illegal tag" << obj->type;
|
||||
if (obj) {
|
||||
fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type);
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
p = kTagOverflow;
|
||||
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
|
||||
EXPECT_FALSE(obj) << "Parsed value with tag overflow" << obj->type;
|
||||
if (obj) {
|
||||
fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type);
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
p = kTag128;
|
||||
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
|
||||
ASSERT_TRUE(obj);
|
||||
EXPECT_EQ(128, obj->type);
|
||||
const uint8_t kZero = 0;
|
||||
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
|
||||
obj->value.asn1_string->length));
|
||||
if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 ||
|
||||
obj->value.asn1_string->data[0] != 0) {
|
||||
fprintf(stderr, "Failed to parse value with tag 128.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestLargeTags()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,6 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
|
||||
int ret = 0;
|
||||
ASN1_VALUE **pchptr, *ptmpval;
|
||||
int combine = aclass & ASN1_TFLG_COMBINE;
|
||||
aclass &= ~ASN1_TFLG_COMBINE;
|
||||
if (!pval)
|
||||
return 0;
|
||||
if (aux && aux->asn1_cb)
|
||||
@@ -668,7 +667,6 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
|
||||
}
|
||||
len -= p - q;
|
||||
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
|
||||
ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item));
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
@@ -1110,7 +1108,7 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(buf->data + len, *p, plen);
|
||||
memcpy(buf->data + len, *p, plen);
|
||||
}
|
||||
*p += plen;
|
||||
return 1;
|
||||
|
||||
@@ -62,9 +62,6 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
|
||||
const ASN1_ITEM *it, int tag, int aclass);
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
@@ -418,7 +415,7 @@ static int der_cmp(const void *a, const void *b)
|
||||
const DER_ENC *d1 = a, *d2 = b;
|
||||
int cmplen, i;
|
||||
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
|
||||
i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
|
||||
i = memcmp(d1->data, d2->data, cmplen);
|
||||
if (i)
|
||||
return i;
|
||||
return d1->length - d2->length;
|
||||
@@ -473,7 +470,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
|
||||
/* Output sorted DER encoding */
|
||||
p = *out;
|
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
|
||||
OPENSSL_memcpy(p, tder->data, tder->length);
|
||||
memcpy(p, tder->data, tder->length);
|
||||
p += tder->length;
|
||||
}
|
||||
*out = p;
|
||||
@@ -663,6 +660,6 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
|
||||
|
||||
}
|
||||
if (cout && len)
|
||||
OPENSSL_memcpy(cout, cont, len);
|
||||
memcpy(cout, cont, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
+7
-12
@@ -63,9 +63,6 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
@@ -156,11 +153,11 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
OPENSSL_memset(*pval, 0, it->size);
|
||||
memset(*pval, 0, it->size);
|
||||
}
|
||||
asn1_set_choice_selector(pval, -1, it);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
goto auxerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
@@ -181,17 +178,17 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
OPENSSL_memset(*pval, 0, it->size);
|
||||
memset(*pval, 0, it->size);
|
||||
asn1_refcount_set_one(pval, it);
|
||||
asn1_enc_init(pval, it);
|
||||
}
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
pseqval = asn1_get_field_ptr(pval, tt);
|
||||
if (!ASN1_template_new(pseqval, tt))
|
||||
goto memerr2;
|
||||
goto memerr;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr2;
|
||||
goto auxerr;
|
||||
break;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
@@ -200,20 +197,18 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
memerr2:
|
||||
ASN1_item_ex_free(pval, it);
|
||||
memerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ASN1_item_ex_free(pval, it);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
auxerr2:
|
||||
ASN1_item_ex_free(pval, it);
|
||||
auxerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
|
||||
ASN1_item_ex_free(pval, it);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
|
||||
+8
-22
@@ -56,7 +56,6 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
@@ -71,7 +70,7 @@
|
||||
/* Utility functions for manipulating fields and offsets */
|
||||
|
||||
/* Add 'offset' to 'addr' */
|
||||
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
|
||||
#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
|
||||
|
||||
/* Given an ASN1_ITEM CHOICE type return the selector value */
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
@@ -135,8 +134,6 @@ void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
if (enc) {
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->alias_only = 0;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
@@ -145,13 +142,11 @@ void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
ASN1_ENCODING *enc;
|
||||
enc = asn1_get_enc_ptr(pval, it);
|
||||
if (enc) {
|
||||
if (enc->enc && !enc->alias_only) {
|
||||
if (enc->enc) {
|
||||
OPENSSL_free(enc->enc);
|
||||
}
|
||||
enc->enc = NULL;
|
||||
enc->len = 0;
|
||||
enc->alias_only = 0;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
enc->modified = 1;
|
||||
}
|
||||
}
|
||||
@@ -164,23 +159,14 @@ int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!enc->alias_only) {
|
||||
if (enc->enc) {
|
||||
OPENSSL_free(enc->enc);
|
||||
}
|
||||
|
||||
enc->alias_only = enc->alias_only_on_next_parse;
|
||||
enc->alias_only_on_next_parse = 0;
|
||||
|
||||
if (enc->alias_only) {
|
||||
enc->enc = (uint8_t *) in;
|
||||
} else {
|
||||
enc->enc = OPENSSL_malloc(inlen);
|
||||
if (!enc->enc) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(enc->enc, in, inlen);
|
||||
enc->enc = OPENSSL_malloc(inlen);
|
||||
if (!enc->enc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(enc->enc, in, inlen);
|
||||
enc->len = inlen;
|
||||
enc->modified = 0;
|
||||
|
||||
@@ -195,7 +181,7 @@ int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
|
||||
return 0;
|
||||
}
|
||||
if (out) {
|
||||
OPENSSL_memcpy(*out, enc->enc, enc->len);
|
||||
memcpy(*out, enc->enc, enc->len);
|
||||
*out += enc->len;
|
||||
}
|
||||
if (len) {
|
||||
|
||||
@@ -54,23 +54,100 @@
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
|
||||
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
|
||||
* since all BIGNUMs used are non negative and anything that looks negative
|
||||
* is normally due to an encoding error.
|
||||
*/
|
||||
|
||||
/* This function has been converted to C++ to check if all of libssl's
|
||||
* consumers' toolchains are capable of handling C++11. Once all problems in
|
||||
* consumer toolchains are found and fixed, we will convert the rest of
|
||||
* libssl. */
|
||||
#define BN_SENSITIVE 1
|
||||
|
||||
int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
|
||||
bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
|
||||
if (!rsa) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
|
||||
return 0;
|
||||
}
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
return SSL_use_RSAPrivateKey(ssl, rsa.get());
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c,
|
||||
NULL /* prim_print */ ,
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(BIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||
ASN1_ITEM_end(BIGNUM)
|
||||
|
||||
ASN1_ITEM_start(CBIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
|
||||
ASN1_ITEM_end(CBIGNUM)
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*pval = (ASN1_VALUE *)BN_new();
|
||||
if (*pval)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if (!*pval)
|
||||
return;
|
||||
if (it->size & BN_SENSITIVE)
|
||||
BN_clear_free((BIGNUM *)*pval);
|
||||
else
|
||||
BN_free((BIGNUM *)*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
int pad;
|
||||
if (!*pval)
|
||||
return -1;
|
||||
bn = (BIGNUM *)*pval;
|
||||
/* If MSB set in an octet we need a padding byte */
|
||||
if (BN_num_bits(bn) & 0x7)
|
||||
pad = 0;
|
||||
else
|
||||
pad = 1;
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = 0;
|
||||
BN_bn2bin(bn, cont);
|
||||
}
|
||||
return pad + BN_num_bytes(bn);
|
||||
}
|
||||
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
if (!*pval) {
|
||||
if (!bn_new(pval, it)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if (!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
*/
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS long_pf = {
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(LONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_ITEM_end(LONG)
|
||||
|
||||
ASN1_ITEM_start(ZLONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
|
||||
ASN1_ITEM_end(ZLONG)
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
}
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
long ltmp;
|
||||
unsigned long utmp;
|
||||
int clen, pad, i;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)pval;
|
||||
|
||||
/* use memcpy, because we may not be long aligned */
|
||||
memcpy(<mp, cp, sizeof(long));
|
||||
|
||||
if (ltmp == it->size)
|
||||
return -1;
|
||||
/*
|
||||
* Convert the long to positive: we subtract one if negative so we can
|
||||
* cleanly handle the padding if only the MSB of the leading octet is
|
||||
* set.
|
||||
*/
|
||||
if (ltmp < 0)
|
||||
utmp = -ltmp - 1;
|
||||
else
|
||||
utmp = ltmp;
|
||||
clen = BN_num_bits_word(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if (!(clen & 0x7))
|
||||
pad = 1;
|
||||
else
|
||||
pad = 0;
|
||||
|
||||
/* Convert number of bits to number of octets */
|
||||
clen = (clen + 7) >> 3;
|
||||
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = (ltmp < 0) ? 0xff : 0;
|
||||
for (i = clen - 1; i >= 0; i--) {
|
||||
cont[i] = (unsigned char)(utmp & 0xff);
|
||||
if (ltmp < 0)
|
||||
cont[i] ^= 0xff;
|
||||
utmp >>= 8;
|
||||
}
|
||||
}
|
||||
return clen + pad;
|
||||
}
|
||||
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
int neg, i;
|
||||
long ltmp;
|
||||
unsigned long utmp = 0;
|
||||
char *cp = (char *)pval;
|
||||
if (len > (int)sizeof(long)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* Is it negative? */
|
||||
if (len && (cont[0] & 0x80))
|
||||
neg = 1;
|
||||
else
|
||||
neg = 0;
|
||||
utmp = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
utmp <<= 8;
|
||||
if (neg)
|
||||
utmp |= cont[i] ^ 0xff;
|
||||
else
|
||||
utmp |= cont[i];
|
||||
}
|
||||
ltmp = (long)utmp;
|
||||
if (neg) {
|
||||
ltmp++;
|
||||
ltmp = -ltmp;
|
||||
}
|
||||
if (ltmp == it->size) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
memcpy(cp, <mp, sizeof(long));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
return BIO_printf(out, "%ld\n", *(long *)pval);
|
||||
}
|
||||
@@ -62,8 +62,6 @@
|
||||
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Encoding. */
|
||||
|
||||
@@ -97,7 +95,7 @@ int EVP_EncodedLength(size_t *out_len, size_t len) {
|
||||
}
|
||||
|
||||
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
@@ -112,14 +110,14 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
assert(ctx->data_used < sizeof(ctx->data));
|
||||
|
||||
if (sizeof(ctx->data) - ctx->data_used > in_len) {
|
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len);
|
||||
memcpy(&ctx->data[ctx->data_used], in, in_len);
|
||||
ctx->data_used += (unsigned)in_len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->data_used != 0) {
|
||||
const size_t todo = sizeof(ctx->data) - ctx->data_used;
|
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo);
|
||||
memcpy(&ctx->data[ctx->data_used], in, todo);
|
||||
in += todo;
|
||||
in_len -= todo;
|
||||
|
||||
@@ -151,7 +149,7 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
}
|
||||
|
||||
if (in_len != 0) {
|
||||
OPENSSL_memcpy(ctx->data, in, in_len);
|
||||
memcpy(ctx->data, in, in_len);
|
||||
}
|
||||
|
||||
ctx->data_used = (unsigned)in_len;
|
||||
@@ -226,7 +224,7 @@ int EVP_DecodedLength(size_t *out_len, size_t len) {
|
||||
}
|
||||
|
||||
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
/* kBase64ASCIIToBinData maps characters (c < 128) to their base64 value, or
|
||||
|
||||
@@ -136,7 +136,7 @@ static bool TestEncodeBlock() {
|
||||
|
||||
std::string encoded(RemoveNewlines(t->encoded));
|
||||
if (len != encoded.size() ||
|
||||
OPENSSL_memcmp(out, encoded.data(), len) != 0) {
|
||||
memcmp(out, encoded.data(), len) != 0) {
|
||||
fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->decoded, (int)len, (const char*)out, encoded.c_str());
|
||||
return false;
|
||||
@@ -178,7 +178,7 @@ static bool TestDecodeBase64() {
|
||||
}
|
||||
|
||||
if (len != strlen(t->decoded) ||
|
||||
OPENSSL_memcmp(out, t->decoded, len) != 0) {
|
||||
memcmp(out, t->decoded, len) != 0) {
|
||||
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
encoded.c_str(), (int)len, (const char*)out, t->decoded);
|
||||
return false;
|
||||
@@ -217,7 +217,7 @@ static bool TestDecodeBlock() {
|
||||
ret -= 3 - (expected_len % 3);
|
||||
}
|
||||
if (static_cast<size_t>(ret) != strlen(t->decoded) ||
|
||||
OPENSSL_memcmp(out, t->decoded, ret) != 0) {
|
||||
memcmp(out, t->decoded, ret) != 0) {
|
||||
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->encoded, ret, (const char*)out, t->decoded);
|
||||
return false;
|
||||
@@ -258,8 +258,7 @@ static bool TestEncodeDecode() {
|
||||
EVP_EncodeFinal(&ctx, out + total, &out_len);
|
||||
total += out_len;
|
||||
|
||||
if (total != strlen(t->encoded) ||
|
||||
OPENSSL_memcmp(out, t->encoded, total) != 0) {
|
||||
if (total != strlen(t->encoded) || memcmp(out, t->encoded, total) != 0) {
|
||||
fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
|
||||
test_num, out, static_cast<unsigned>(total));
|
||||
return false;
|
||||
@@ -288,8 +287,7 @@ static bool TestEncodeDecode() {
|
||||
fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
|
||||
return false;
|
||||
}
|
||||
if (total != decoded_len ||
|
||||
OPENSSL_memcmp(out, t->decoded, decoded_len)) {
|
||||
if (total != decoded_len || memcmp(out, t->decoded, decoded_len)) {
|
||||
fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
|
||||
test_num);
|
||||
return false;
|
||||
@@ -370,7 +368,7 @@ static bool TestDecodeUpdateStreaming() {
|
||||
out_len += bytes_written;
|
||||
|
||||
if (out_len != strlen(t->decoded) ||
|
||||
OPENSSL_memcmp(out.data(), t->decoded, out_len) != 0) {
|
||||
memcmp(out.data(), t->decoded, out_len) != 0) {
|
||||
fprintf(stderr, "#%u: incorrect output\n", test_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ add_library(
|
||||
|
||||
bio.c
|
||||
bio_mem.c
|
||||
buffer.c
|
||||
connect.c
|
||||
fd.c
|
||||
file.c
|
||||
@@ -16,3 +17,17 @@ add_library(
|
||||
socket.c
|
||||
socket_helper.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
bio_test
|
||||
|
||||
bio_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(bio_test crypto)
|
||||
if (WIN32)
|
||||
target_link_libraries(bio_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests bio_test)
|
||||
|
||||
+10
-24
@@ -75,7 +75,7 @@ BIO *BIO_new(const BIO_METHOD *method) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BIO));
|
||||
memset(ret, 0, sizeof(BIO));
|
||||
ret->method = method;
|
||||
ret->shutdown = 1;
|
||||
ret->references = 1;
|
||||
@@ -336,13 +336,7 @@ long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
}
|
||||
|
||||
size_t BIO_pending(const BIO *bio) {
|
||||
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
|
||||
assert(r >= 0);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_pending(const BIO *bio) {
|
||||
@@ -350,13 +344,7 @@ size_t BIO_ctrl_pending(const BIO *bio) {
|
||||
}
|
||||
|
||||
size_t BIO_wpending(const BIO *bio) {
|
||||
const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
|
||||
assert(r >= 0);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
|
||||
}
|
||||
|
||||
int BIO_set_close(BIO *bio, int close_flag) {
|
||||
@@ -460,10 +448,14 @@ static int print_bio(const char *str, size_t len, void *bio) {
|
||||
return BIO_write((BIO *)bio, str, len);
|
||||
}
|
||||
|
||||
void ERR_print_errors(BIO *bio) {
|
||||
void BIO_print_errors(BIO *bio) {
|
||||
ERR_print_errors_cb(print_bio, bio);
|
||||
}
|
||||
|
||||
void ERR_print_errors(BIO *bio) {
|
||||
BIO_print_errors(bio);
|
||||
}
|
||||
|
||||
/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On
|
||||
* success, |*out| is set to an allocated buffer (which should be freed with
|
||||
* |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
|
||||
@@ -488,7 +480,7 @@ static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
|
||||
if (*out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(*out, prefix, prefix_len);
|
||||
memcpy(*out, prefix, prefix_len);
|
||||
size_t done = prefix_len;
|
||||
|
||||
for (;;) {
|
||||
@@ -595,7 +587,7 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
if (*out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(*out, header, header_len);
|
||||
memcpy(*out, header, header_len);
|
||||
if (BIO_read(bio, (*out) + header_len, len - header_len) !=
|
||||
(int) (len - header_len)) {
|
||||
OPENSSL_free(*out);
|
||||
@@ -604,9 +596,3 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_set_retry_special(BIO *bio) {
|
||||
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL;
|
||||
}
|
||||
|
||||
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
|
||||
|
||||
+10
-12
@@ -63,8 +63,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BIO *BIO_new_mem_buf(const void *buf, int len) {
|
||||
BIO *ret;
|
||||
@@ -146,12 +144,12 @@ static int mem_read(BIO *bio, char *out, int outl) {
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
OPENSSL_memcpy(out, b->data, ret);
|
||||
memcpy(out, b->data, ret);
|
||||
b->length -= ret;
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data += ret;
|
||||
} else {
|
||||
OPENSSL_memmove(b->data, &b->data[ret], b->length);
|
||||
memmove(b->data, &b->data[ret], b->length);
|
||||
}
|
||||
} else if (b->length == 0) {
|
||||
ret = bio->num;
|
||||
@@ -182,13 +180,17 @@ static int mem_write(BIO *bio, const char *in, int inl) {
|
||||
if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(&b->data[blen], in, inl);
|
||||
memcpy(&b->data[blen], in, inl);
|
||||
ret = inl;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_puts(BIO *bp, const char *str) {
|
||||
return mem_write(bp, str, strlen(str));
|
||||
}
|
||||
|
||||
static int mem_gets(BIO *bio, char *buf, int size) {
|
||||
int i, j;
|
||||
char *p;
|
||||
@@ -238,7 +240,7 @@ static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
b->data -= b->max - b->length;
|
||||
b->length = b->max;
|
||||
} else {
|
||||
OPENSSL_memset(b->data, 0, b->max);
|
||||
memset(b->data, 0, b->max);
|
||||
b->length = 0;
|
||||
}
|
||||
}
|
||||
@@ -291,12 +293,8 @@ static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
}
|
||||
|
||||
static const BIO_METHOD mem_method = {
|
||||
BIO_TYPE_MEM, "memory buffer",
|
||||
mem_write, mem_read,
|
||||
NULL /* puts */, mem_gets,
|
||||
mem_ctrl, mem_new,
|
||||
mem_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
BIO_TYPE_MEM, "memory buffer", mem_write, mem_read, mem_puts,
|
||||
mem_gets, mem_ctrl, mem_new, mem_free, NULL, };
|
||||
|
||||
const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
|
||||
|
||||
|
||||
+344
-217
@@ -16,18 +16,7 @@
|
||||
#define _POSIX_C_SOURCE 201410L
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <arpa/inet.h>
|
||||
@@ -44,21 +33,33 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) { return close(sock); }
|
||||
static std::string LastSocketError() { return strerror(errno); }
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
|
||||
static void PrintSocketError(const char *func) {
|
||||
perror(func);
|
||||
}
|
||||
#else
|
||||
static std::string LastSocketError() {
|
||||
char buf[DECIMAL_SIZE(int) + 1];
|
||||
BIO_snprintf(buf, sizeof(buf), "%d", WSAGetLastError());
|
||||
return buf;
|
||||
static void PrintSocketError(const char *func) {
|
||||
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
|
||||
}
|
||||
#endif
|
||||
|
||||
class ScopedSocket {
|
||||
public:
|
||||
explicit ScopedSocket(int sock) : sock_(sock) {}
|
||||
ScopedSocket(int sock) : sock_(sock) {}
|
||||
~ScopedSocket() {
|
||||
closesocket(sock_);
|
||||
}
|
||||
@@ -67,246 +68,372 @@ class ScopedSocket {
|
||||
const int sock_;
|
||||
};
|
||||
|
||||
TEST(BIOTest, SocketConnect) {
|
||||
static bool TestSocketConnect() {
|
||||
static const char kTestMessage[] = "test";
|
||||
|
||||
// Set up a listening socket on localhost.
|
||||
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
ASSERT_NE(-1, listening_sock) << LastSocketError();
|
||||
if (listening_sock == -1) {
|
||||
PrintSocketError("socket");
|
||||
return false;
|
||||
}
|
||||
ScopedSocket listening_sock_closer(listening_sock);
|
||||
|
||||
struct sockaddr_in sin;
|
||||
OPENSSL_memset(&sin, 0, sizeof(sin));
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr))
|
||||
<< LastSocketError();
|
||||
ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)))
|
||||
<< LastSocketError();
|
||||
ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
|
||||
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
|
||||
PrintSocketError("inet_pton");
|
||||
return false;
|
||||
}
|
||||
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
|
||||
PrintSocketError("bind");
|
||||
return false;
|
||||
}
|
||||
if (listen(listening_sock, 1)) {
|
||||
PrintSocketError("listen");
|
||||
return false;
|
||||
}
|
||||
socklen_t sockaddr_len = sizeof(sin);
|
||||
ASSERT_EQ(0,
|
||||
getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len))
|
||||
<< LastSocketError();
|
||||
// The Android NDK, contrary to POSIX, makes |socklen_t| signed.
|
||||
ASSERT_EQ(sizeof(sin), static_cast<size_t>(sockaddr_len));
|
||||
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
|
||||
sockaddr_len != sizeof(sin)) {
|
||||
PrintSocketError("getsockname");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect to it with a connect BIO.
|
||||
char hostname[80];
|
||||
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
|
||||
ntohs(sin.sin_port));
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
|
||||
ASSERT_TRUE(bio);
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new_connect failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write a test message to the BIO.
|
||||
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
|
||||
BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
|
||||
if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
|
||||
sizeof(kTestMessage)) {
|
||||
fprintf(stderr, "BIO_write failed.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Accept the socket.
|
||||
int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
|
||||
ASSERT_NE(-1, sock) << LastSocketError();
|
||||
if (sock == -1) {
|
||||
PrintSocketError("accept");
|
||||
return false;
|
||||
}
|
||||
ScopedSocket sock_closer(sock);
|
||||
|
||||
// Check the same message is read back out.
|
||||
char buf[sizeof(kTestMessage)];
|
||||
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
|
||||
recv(sock, buf, sizeof(buf), 0))
|
||||
<< LastSocketError();
|
||||
EXPECT_EQ(Bytes(kTestMessage, sizeof(kTestMessage)), Bytes(buf, sizeof(buf)));
|
||||
char buf[5];
|
||||
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
|
||||
PrintSocketError("read");
|
||||
return false;
|
||||
}
|
||||
if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(BIOTest, Printf) {
|
||||
|
||||
// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make
|
||||
// testing easier.
|
||||
static size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) {
|
||||
uint8_t *read_buf;
|
||||
size_t read_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t len_read = 0;
|
||||
|
||||
do {
|
||||
if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
available_bytes = std::min(available_bytes, len - len_read);
|
||||
memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
|
||||
|
||||
BIO_zero_copy_get_read_buf_done(bio, available_bytes);
|
||||
|
||||
len_read += available_bytes;
|
||||
} while (len - len_read > 0 && available_bytes > 0);
|
||||
|
||||
return len_read;
|
||||
}
|
||||
|
||||
// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make
|
||||
// testing easier.
|
||||
static size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data,
|
||||
size_t len) {
|
||||
uint8_t *write_buf;
|
||||
size_t write_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t len_written = 0;
|
||||
|
||||
do {
|
||||
if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
available_bytes = std::min(available_bytes, len - len_written);
|
||||
memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
|
||||
|
||||
BIO_zero_copy_get_write_buf_done(bio, available_bytes);
|
||||
|
||||
len_written += available_bytes;
|
||||
} while (len - len_written > 0 && available_bytes > 0);
|
||||
|
||||
return len_written;
|
||||
}
|
||||
|
||||
static bool TestZeroCopyBioPairs() {
|
||||
// Test read and write, especially triggering the ring buffer wrap-around.
|
||||
uint8_t bio1_application_send_buffer[1024];
|
||||
uint8_t bio2_application_recv_buffer[1024];
|
||||
|
||||
const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
|
||||
|
||||
// These trigger ring buffer wrap around.
|
||||
const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
|
||||
|
||||
static const size_t kBufferSize = 512;
|
||||
|
||||
srand(1);
|
||||
for (size_t i = 0; i < sizeof(bio1_application_send_buffer); i++) {
|
||||
bio1_application_send_buffer[i] = rand() & 255;
|
||||
}
|
||||
|
||||
// Transfer bytes from bio1_application_send_buffer to
|
||||
// bio2_application_recv_buffer in various ways.
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
|
||||
for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kPartialLengths); j++) {
|
||||
size_t total_write = 0;
|
||||
size_t total_read = 0;
|
||||
|
||||
BIO *bio1, *bio2;
|
||||
if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) {
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<BIO> bio1_scoper(bio1);
|
||||
bssl::UniquePtr<BIO> bio2_scoper(bio2);
|
||||
|
||||
total_write += BioWriteZeroCopyWrapper(
|
||||
bio1, bio1_application_send_buffer, kLengths[i]);
|
||||
|
||||
// This tests interleaved read/write calls. Do a read between zero copy
|
||||
// write calls.
|
||||
uint8_t *write_buf;
|
||||
size_t write_buf_offset;
|
||||
size_t available_bytes;
|
||||
if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
|
||||
&available_bytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
|
||||
// This enables ring buffer wrap around for the next write.
|
||||
total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
|
||||
kPartialLengths[j]);
|
||||
|
||||
size_t interleaved_write_len = std::min(kPartialLengths[j],
|
||||
available_bytes);
|
||||
|
||||
// Write the data for the interleaved write call. If the buffer becomes
|
||||
// empty after a read, the write offset is normally set to 0. Check that
|
||||
// this does not happen for interleaved read/write and that
|
||||
// |write_buf_offset| is still valid.
|
||||
memcpy(write_buf + write_buf_offset,
|
||||
bio1_application_send_buffer + total_write, interleaved_write_len);
|
||||
if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
|
||||
total_write += interleaved_write_len;
|
||||
}
|
||||
|
||||
// Do another write in case |write_buf_offset| was wrapped.
|
||||
total_write += BioWriteZeroCopyWrapper(
|
||||
bio1, bio1_application_send_buffer + total_write,
|
||||
kPartialLengths[j] - interleaved_write_len);
|
||||
|
||||
// Drain the rest.
|
||||
size_t bytes_left = BIO_pending(bio2);
|
||||
total_read += BioReadZeroCopyWrapper(
|
||||
bio2, bio2_application_recv_buffer + total_read, bytes_left);
|
||||
|
||||
if (total_read != total_write) {
|
||||
fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return false;
|
||||
}
|
||||
if (total_read > kLengths[i] + kPartialLengths[j]) {
|
||||
fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return false;
|
||||
}
|
||||
if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
|
||||
total_read) != 0) {
|
||||
fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestPrintf() {
|
||||
// Test a short output, a very long one, and various sizes around
|
||||
// 256 (the size of the buffer) to ensure edge cases are correct.
|
||||
static const size_t kLengths[] = {5, 250, 251, 252, 253, 254, 1023};
|
||||
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
|
||||
|
||||
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
|
||||
ASSERT_TRUE(bio);
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t length : kLengths) {
|
||||
SCOPED_TRACE(length);
|
||||
|
||||
std::string in(length, 'a');
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", in.c_str());
|
||||
ASSERT_GE(ret, 0);
|
||||
EXPECT_EQ(5 + length, static_cast<size_t>(ret));
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
|
||||
char string[1024];
|
||||
if (kLengths[i] >= sizeof(string)) {
|
||||
fprintf(stderr, "Bad test string length\n");
|
||||
return false;
|
||||
}
|
||||
memset(string, 'a', sizeof(string));
|
||||
string[kLengths[i]] = '\0';
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", string);
|
||||
if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
|
||||
fprintf(stderr, "BIO_printf failed: %d\n", ret);
|
||||
return false;
|
||||
}
|
||||
const uint8_t *contents;
|
||||
size_t len;
|
||||
ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
|
||||
EXPECT_EQ("test " + in,
|
||||
std::string(reinterpret_cast<const char *>(contents), len));
|
||||
if (!BIO_mem_contents(bio.get(), &contents, &len)) {
|
||||
fprintf(stderr, "BIO_mem_contents failed\n");
|
||||
return false;
|
||||
}
|
||||
if (len != 5 + kLengths[i] ||
|
||||
strncmp((const char *)contents, "test ", 5) != 0 ||
|
||||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
|
||||
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(BIO_reset(bio.get()));
|
||||
if (!BIO_reset(bio.get())) {
|
||||
fprintf(stderr, "BIO_reset failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const size_t kLargeASN1PayloadLen = 8000;
|
||||
|
||||
struct ASN1TestParam {
|
||||
bool should_succeed;
|
||||
std::vector<uint8_t> input;
|
||||
// suffix_len is the number of zeros to append to |input|.
|
||||
size_t suffix_len;
|
||||
// expected_len, if |should_succeed| is true, is the expected length of the
|
||||
// ASN.1 element.
|
||||
size_t expected_len;
|
||||
size_t max_len;
|
||||
} kASN1TestParams[] = {
|
||||
{true, {0x30, 2, 1, 2, 0, 0}, 0, 4, 100},
|
||||
{false /* truncated */, {0x30, 3, 1, 2}, 0, 0, 100},
|
||||
{false /* should be short len */, {0x30, 0x81, 1, 1}, 0, 0, 100},
|
||||
{false /* zero padded */, {0x30, 0x82, 0, 1, 1}, 0, 0, 100},
|
||||
|
||||
// Test a large payload.
|
||||
{true,
|
||||
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
|
||||
kLargeASN1PayloadLen,
|
||||
4 + kLargeASN1PayloadLen,
|
||||
kLargeASN1PayloadLen * 2},
|
||||
{false /* max_len too short */,
|
||||
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
|
||||
kLargeASN1PayloadLen,
|
||||
4 + kLargeASN1PayloadLen,
|
||||
3 + kLargeASN1PayloadLen},
|
||||
|
||||
// Test an indefinite-length input.
|
||||
{true,
|
||||
{0x30, 0x80},
|
||||
kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 2,
|
||||
kLargeASN1PayloadLen * 2},
|
||||
{false /* max_len too short */,
|
||||
{0x30, 0x80},
|
||||
kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 1},
|
||||
};
|
||||
|
||||
class BIOASN1Test : public testing::TestWithParam<ASN1TestParam> {};
|
||||
|
||||
TEST_P(BIOASN1Test, ReadASN1) {
|
||||
const ASN1TestParam& param = GetParam();
|
||||
std::vector<uint8_t> input = param.input;
|
||||
input.resize(input.size() + param.suffix_len, 0);
|
||||
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(input.data(), input.size()));
|
||||
ASSERT_TRUE(bio);
|
||||
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
|
||||
size_t expected_len, size_t max_len) {
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(data, data_len));
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_len;
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, param.max_len);
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
|
||||
if (!ok) {
|
||||
out = nullptr;
|
||||
}
|
||||
bssl::UniquePtr<uint8_t> out_storage(out);
|
||||
|
||||
ASSERT_EQ(param.should_succeed, (ok == 1));
|
||||
if (param.should_succeed) {
|
||||
EXPECT_EQ(Bytes(input.data(), param.expected_len), Bytes(out, out_len));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
|
||||
|
||||
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
|
||||
class BIOPairTest : public testing::TestWithParam<bool> {};
|
||||
|
||||
TEST_P(BIOPairTest, TestPair) {
|
||||
BIO *bio1, *bio2;
|
||||
ASSERT_TRUE(BIO_new_bio_pair(&bio1, 10, &bio2, 10));
|
||||
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
|
||||
|
||||
if (GetParam()) {
|
||||
std::swap(bio1, bio2);
|
||||
if (should_succeed != (ok == 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check initial states.
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
|
||||
if (should_succeed &&
|
||||
(out_len != expected_len || memcmp(data, out, expected_len) != 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data written in one end may be read out the other.
|
||||
uint8_t buf[20];
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Attempting to write more than 10 bytes will write partially.
|
||||
EXPECT_EQ(10, BIO_write(bio1, "1234567890___", 13));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(-1, BIO_write(bio1, "z", 1));
|
||||
EXPECT_TRUE(BIO_should_write(bio1));
|
||||
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("1234567890"), Bytes(buf, 10));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Unsuccessful reads update the read request.
|
||||
EXPECT_EQ(-1, BIO_read(bio2, buf, 5));
|
||||
EXPECT_TRUE(BIO_should_read(bio2));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
// The read request is clamped to the size of the buffer.
|
||||
EXPECT_EQ(-1, BIO_read(bio2, buf, 20));
|
||||
EXPECT_TRUE(BIO_should_read(bio2));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
// Data may be written and read in chunks.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(5, BIO_write(bio1, "67890___", 8));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
|
||||
EXPECT_EQ(Bytes("123"), Bytes(buf, 3));
|
||||
EXPECT_EQ(3u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(7, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("4567890"), Bytes(buf, 7));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Successful reads reset the read request.
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
// Test writes and reads starting in the middle of the ring buffer and
|
||||
// wrapping to front.
|
||||
EXPECT_EQ(8, BIO_write(bio1, "abcdefgh", 8));
|
||||
EXPECT_EQ(2u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
|
||||
EXPECT_EQ(Bytes("abc"), Bytes(buf, 3));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(5, BIO_write(bio1, "ijklm___", 8));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("defghijklm"), Bytes(buf, 10));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Data may flow from both ends in parallel.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5, BIO_write(bio2, "67890", 5));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("67890"), Bytes(buf, 5));
|
||||
|
||||
// Closing the write end causes an EOF on the read half, after draining.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_TRUE(BIO_shutdown_wr(bio1));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
EXPECT_EQ(0, BIO_read(bio2, buf, sizeof(buf)));
|
||||
|
||||
// A closed write end may not be written to.
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(-1, BIO_write(bio1, "_____", 5));
|
||||
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_BIO, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(BIO_R_BROKEN_PIPE, ERR_GET_REASON(err));
|
||||
|
||||
// The other end is still functional.
|
||||
EXPECT_EQ(5, BIO_write(bio2, "12345", 5));
|
||||
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
return true;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
|
||||
static bool TestASN1() {
|
||||
static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
|
||||
static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
|
||||
static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
|
||||
static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
|
||||
|
||||
if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
|
||||
!ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
|
||||
!ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
|
||||
!ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const size_t kLargePayloadLen = 8000;
|
||||
static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
|
||||
kLargePayloadLen & 0xff};
|
||||
bssl::UniquePtr<uint8_t> large(reinterpret_cast<uint8_t *>(
|
||||
OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
|
||||
if (!large) {
|
||||
return false;
|
||||
}
|
||||
memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
|
||||
memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
|
||||
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen * 2)) {
|
||||
fprintf(stderr, "Large payload test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen - 1)) {
|
||||
fprintf(stderr, "max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint8_t kIndefPrefix[] = {0x30, 0x80};
|
||||
memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen*2)) {
|
||||
fprintf(stderr, "indefinite length test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen-1)) {
|
||||
fprintf(stderr, "indefinite length, max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
WORD wsa_version = MAKEWORD(2, 2);
|
||||
WSADATA wsa_data;
|
||||
int wsa_err = WSAStartup(wsa_version, &wsa_data);
|
||||
if (wsa_err != 0) {
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
||||
return 1;
|
||||
}
|
||||
if (wsa_data.wVersion != wsa_version) {
|
||||
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!TestSocketConnect() ||
|
||||
!TestPrintf() ||
|
||||
!TestZeroCopyBioPairs() ||
|
||||
!TestASN1()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,496 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 4096
|
||||
|
||||
typedef struct bio_f_buffer_ctx_struct {
|
||||
/* Buffers are setup like this:
|
||||
*
|
||||
* <---------------------- size ----------------------->
|
||||
* +---------------------------------------------------+
|
||||
* | consumed | remaining | free space |
|
||||
* +---------------------------------------------------+
|
||||
* <-- off --><------- len ------->
|
||||
*/
|
||||
|
||||
int ibuf_size; /* how big is the input buffer */
|
||||
int obuf_size; /* how big is the output buffer */
|
||||
|
||||
char *ibuf; /* the char array */
|
||||
int ibuf_len; /* how many bytes are in it */
|
||||
int ibuf_off; /* write/read offset */
|
||||
|
||||
char *obuf; /* the char array */
|
||||
int obuf_len; /* how many bytes are in it */
|
||||
int obuf_off; /* write/read offset */
|
||||
} BIO_F_BUFFER_CTX;
|
||||
|
||||
static int buffer_new(BIO *bio) {
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
|
||||
if (ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX));
|
||||
|
||||
ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->ibuf == NULL) {
|
||||
goto err1;
|
||||
}
|
||||
ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->obuf == NULL) {
|
||||
goto err2;
|
||||
}
|
||||
ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
|
||||
ctx->obuf_size = DEFAULT_BUFFER_SIZE;
|
||||
|
||||
bio->init = 1;
|
||||
bio->ptr = (char *)ctx;
|
||||
return 1;
|
||||
|
||||
err2:
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
|
||||
err1:
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buffer_free(BIO *bio) {
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
if (bio == NULL || bio->ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
OPENSSL_free(ctx->obuf);
|
||||
OPENSSL_free(bio->ptr);
|
||||
|
||||
bio->ptr = NULL;
|
||||
bio->init = 0;
|
||||
bio->flags = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int buffer_read(BIO *bio, char *out, int outl) {
|
||||
int i, num = 0;
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
|
||||
|
||||
if (ctx == NULL || bio->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
num = 0;
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
for (;;) {
|
||||
i = ctx->ibuf_len;
|
||||
/* If there is stuff left over, grab it */
|
||||
if (i != 0) {
|
||||
if (i > outl) {
|
||||
i = outl;
|
||||
}
|
||||
memcpy(out, &ctx->ibuf[ctx->ibuf_off], i);
|
||||
ctx->ibuf_off += i;
|
||||
ctx->ibuf_len -= i;
|
||||
num += i;
|
||||
if (outl == i) {
|
||||
return num;
|
||||
}
|
||||
outl -= i;
|
||||
out += i;
|
||||
}
|
||||
|
||||
/* We may have done a partial read. Try to do more. We have nothing in the
|
||||
* buffer. If we get an error and have read some data, just return it and
|
||||
* let them retry to get the error again. Copy direct to parent address
|
||||
* space */
|
||||
if (outl > ctx->ibuf_size) {
|
||||
for (;;) {
|
||||
i = BIO_read(bio->next_bio, out, outl);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(bio);
|
||||
if (i < 0) {
|
||||
return (num > 0) ? num : i;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
num += i;
|
||||
if (outl == i) {
|
||||
return num;
|
||||
}
|
||||
out += i;
|
||||
outl -= i;
|
||||
}
|
||||
}
|
||||
/* else */
|
||||
|
||||
/* we are going to be doing some buffering */
|
||||
i = BIO_read(bio->next_bio, ctx->ibuf, ctx->ibuf_size);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(bio);
|
||||
if (i < 0) {
|
||||
return (num > 0) ? num : i;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = i;
|
||||
}
|
||||
}
|
||||
|
||||
static int buffer_write(BIO *b, const char *in, int inl) {
|
||||
int i, num = 0;
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
if (ctx == NULL || b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
for (;;) {
|
||||
i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len);
|
||||
/* add to buffer and return */
|
||||
if (i >= inl) {
|
||||
memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, inl);
|
||||
ctx->obuf_len += inl;
|
||||
return num + inl;
|
||||
}
|
||||
/* else */
|
||||
/* stuff already in buffer, so add to it first, then flush */
|
||||
if (ctx->obuf_len != 0) {
|
||||
if (i > 0) {
|
||||
memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, i);
|
||||
in += i;
|
||||
inl -= i;
|
||||
num += i;
|
||||
ctx->obuf_len += i;
|
||||
}
|
||||
|
||||
/* we now have a full buffer needing flushing */
|
||||
for (;;) {
|
||||
i = BIO_write(b->next_bio, &ctx->obuf[ctx->obuf_off], ctx->obuf_len);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
|
||||
if (i < 0) {
|
||||
return (num > 0) ? num : i;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
ctx->obuf_off += i;
|
||||
ctx->obuf_len -= i;
|
||||
if (ctx->obuf_len == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we only get here if the buffer has been flushed and we
|
||||
* still have stuff to write */
|
||||
ctx->obuf_off = 0;
|
||||
|
||||
/* we now have inl bytes to write */
|
||||
while (inl >= ctx->obuf_size) {
|
||||
i = BIO_write(b->next_bio, in, inl);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
if (i < 0) {
|
||||
return (num > 0) ? num : i;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
num += i;
|
||||
in += i;
|
||||
inl -= i;
|
||||
if (inl == 0) {
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy the rest into the buffer since we have only a small
|
||||
* amount left */
|
||||
}
|
||||
}
|
||||
|
||||
static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
long ret = 1;
|
||||
char *p1, *p2;
|
||||
int r, *ip;
|
||||
int ibs, obs;
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = 0;
|
||||
ctx->obuf_off = 0;
|
||||
ctx->obuf_len = 0;
|
||||
if (b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
|
||||
case BIO_CTRL_INFO:
|
||||
ret = ctx->obuf_len;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = (long)ctx->obuf_len;
|
||||
if (ret == 0) {
|
||||
if (b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = (long)ctx->ibuf_len;
|
||||
if (ret == 0) {
|
||||
if (b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_SET_BUFF_SIZE:
|
||||
ip = (int *)ptr;
|
||||
if (*ip == 0) {
|
||||
ibs = (int)num;
|
||||
obs = ctx->obuf_size;
|
||||
} else /* if (*ip == 1) */ {
|
||||
ibs = ctx->ibuf_size;
|
||||
obs = (int)num;
|
||||
}
|
||||
p1 = ctx->ibuf;
|
||||
p2 = ctx->obuf;
|
||||
if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
|
||||
p1 = OPENSSL_malloc(ibs);
|
||||
if (p1 == NULL) {
|
||||
goto malloc_error;
|
||||
}
|
||||
}
|
||||
if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
|
||||
p2 = OPENSSL_malloc(obs);
|
||||
if (p2 == NULL) {
|
||||
if (p1 != ctx->ibuf) {
|
||||
OPENSSL_free(p1);
|
||||
}
|
||||
goto malloc_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->ibuf != p1) {
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
ctx->ibuf = p1;
|
||||
ctx->ibuf_size = ibs;
|
||||
}
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = 0;
|
||||
|
||||
if (ctx->obuf != p2) {
|
||||
OPENSSL_free(ctx->obuf);
|
||||
ctx->obuf = p2;
|
||||
ctx->obuf_size = obs;
|
||||
}
|
||||
ctx->obuf_off = 0;
|
||||
ctx->obuf_len = 0;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (ctx->obuf_len > 0) {
|
||||
BIO_clear_retry_flags(b);
|
||||
r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
|
||||
ctx->obuf_len);
|
||||
BIO_copy_next_retry(b);
|
||||
if (r <= 0) {
|
||||
return r;
|
||||
}
|
||||
ctx->obuf_off += r;
|
||||
ctx->obuf_len -= r;
|
||||
}
|
||||
|
||||
ctx->obuf_len = 0;
|
||||
ctx->obuf_off = 0;
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
BIO_copy_next_retry(b);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
||||
malloc_error:
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) {
|
||||
long ret = 1;
|
||||
|
||||
if (b->next_bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int buffer_gets(BIO *b, char *buf, int size) {
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
int num = 0, i, flag;
|
||||
char *p;
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
if (buf == NULL || size <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size--; /* reserve space for a '\0' */
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
for (;;) {
|
||||
if (ctx->ibuf_len > 0) {
|
||||
p = &ctx->ibuf[ctx->ibuf_off];
|
||||
flag = 0;
|
||||
for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
|
||||
*(buf++) = p[i];
|
||||
if (p[i] == '\n') {
|
||||
flag = 1;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
size -= i;
|
||||
ctx->ibuf_len -= i;
|
||||
ctx->ibuf_off += i;
|
||||
if (flag || size == 0) {
|
||||
*buf = '\0';
|
||||
return num;
|
||||
}
|
||||
} else /* read another chunk */
|
||||
{
|
||||
i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
*buf = '\0';
|
||||
if (i < 0) {
|
||||
return (num > 0) ? num : i;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
ctx->ibuf_len = i;
|
||||
ctx->ibuf_off = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int buffer_puts(BIO *b, const char *str) {
|
||||
return buffer_write(b, str, strlen(str));
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_buffer = {
|
||||
BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read,
|
||||
buffer_puts, buffer_gets, buffer_ctrl, buffer_new,
|
||||
buffer_free, buffer_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; }
|
||||
|
||||
int BIO_set_read_buffer_size(BIO *bio, int buffer_size) {
|
||||
return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0);
|
||||
}
|
||||
|
||||
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) {
|
||||
return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1);
|
||||
}
|
||||
+18
-7
@@ -77,7 +77,6 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
enum {
|
||||
@@ -299,7 +298,7 @@ static BIO_CONNECT *BIO_CONNECT_new(void) {
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
OPENSSL_memset(ret, 0, sizeof(BIO_CONNECT));
|
||||
memset(ret, 0, sizeof(BIO_CONNECT));
|
||||
|
||||
ret->state = BIO_CONN_S_BEFORE;
|
||||
return ret;
|
||||
@@ -468,6 +467,14 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
break;
|
||||
case BIO_CTRL_SET_CALLBACK: {
|
||||
#if 0 /* FIXME: Should this be used? -- Richard Levitte */
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
ret = -1;
|
||||
#else
|
||||
ret = 0;
|
||||
#endif
|
||||
} break;
|
||||
case BIO_CTRL_GET_CALLBACK: {
|
||||
int (**fptr)(const BIO *bio, int state, int xret);
|
||||
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
|
||||
@@ -477,7 +484,7 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
@@ -487,9 +494,9 @@ static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
data = (BIO_CONNECT *)bio->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
case BIO_CTRL_SET_CALLBACK: {
|
||||
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -497,6 +504,10 @@ static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int conn_puts(BIO *bp, const char *str) {
|
||||
return conn_write(bp, str, strlen(str));
|
||||
}
|
||||
|
||||
BIO *BIO_new_connect(const char *hostname) {
|
||||
BIO *ret;
|
||||
|
||||
@@ -512,8 +523,8 @@ BIO *BIO_new_connect(const char *hostname) {
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_connectp = {
|
||||
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
|
||||
NULL /* puts */, NULL /* gets */, conn_ctrl, conn_new,
|
||||
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
|
||||
conn_puts, NULL /* connect_gets, */, conn_ctrl, conn_new,
|
||||
conn_free, conn_callback_ctrl,
|
||||
};
|
||||
|
||||
|
||||
+6
-3
@@ -241,6 +241,10 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fd_puts(BIO *bp, const char *str) {
|
||||
return fd_write(bp, str, strlen(str));
|
||||
}
|
||||
|
||||
static int fd_gets(BIO *bp, char *buf, int size) {
|
||||
char *ptr = buf;
|
||||
char *end = buf + size - 1;
|
||||
@@ -259,9 +263,8 @@ static int fd_gets(BIO *bp, char *buf, int size) {
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_fdp = {
|
||||
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, NULL /* puts */,
|
||||
fd_gets, fd_ctrl, fd_new, fd_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, fd_puts,
|
||||
fd_gets, fd_ctrl, fd_new, fd_free, NULL, };
|
||||
|
||||
const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
|
||||
|
||||
|
||||
+6
-6
@@ -273,13 +273,13 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_puts(BIO *bp, const char *str) {
|
||||
return file_write(bp, str, strlen(str));
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_filep = {
|
||||
BIO_TYPE_FILE, "FILE pointer",
|
||||
file_write, file_read,
|
||||
NULL /* puts */, file_gets,
|
||||
file_ctrl, file_new,
|
||||
file_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
BIO_TYPE_FILE, "FILE pointer", file_write, file_read, file_puts,
|
||||
file_gets, file_ctrl, file_new, file_free, NULL, };
|
||||
|
||||
const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
|
||||
|
||||
|
||||
@@ -59,8 +59,6 @@
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* hexdump_ctx contains the state of a hexdump. */
|
||||
struct hexdump_ctx {
|
||||
@@ -156,7 +154,7 @@ static int finish(struct hexdump_ctx *ctx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf, ' ', 4);
|
||||
memset(buf, ' ', 4);
|
||||
buf[4] = '|';
|
||||
|
||||
for (; ctx->used < 16; ctx->used++) {
|
||||
@@ -181,7 +179,7 @@ static int finish(struct hexdump_ctx *ctx) {
|
||||
|
||||
int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
|
||||
struct hexdump_ctx ctx;
|
||||
OPENSSL_memset(&ctx, 0, sizeof(ctx));
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.bio = bio;
|
||||
ctx.indent = indent;
|
||||
|
||||
|
||||
+344
-30
@@ -59,8 +59,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
struct bio_bio_st {
|
||||
BIO *peer; /* NULL if buf == NULL.
|
||||
@@ -74,6 +72,12 @@ struct bio_bio_st {
|
||||
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
|
||||
size_t size;
|
||||
uint8_t *buf; /* "size" elements (if != NULL) */
|
||||
char buf_externally_allocated; /* true iff buf was externally allocated. */
|
||||
|
||||
char zero_copy_read_lock; /* true iff a zero copy read operation
|
||||
* is in progress. */
|
||||
char zero_copy_write_lock; /* true iff a zero copy write operation
|
||||
* is in progress. */
|
||||
|
||||
size_t request; /* valid iff peer != NULL; 0 if len != 0,
|
||||
* otherwise set by peer to number of bytes
|
||||
@@ -88,7 +92,7 @@ static int bio_new(BIO *bio) {
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
|
||||
memset(b, 0, sizeof(struct bio_bio_st));
|
||||
|
||||
b->size = 17 * 1024; /* enough for one TLS record (just a default) */
|
||||
bio->ptr = b;
|
||||
@@ -141,12 +145,263 @@ static int bio_free(BIO *bio) {
|
||||
bio_destroy_pair(bio);
|
||||
}
|
||||
|
||||
OPENSSL_free(b->buf);
|
||||
if (!b->buf_externally_allocated) {
|
||||
OPENSSL_free(b->buf);
|
||||
}
|
||||
|
||||
OPENSSL_free(b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
|
||||
uint8_t** out_read_buf,
|
||||
size_t* out_buf_offset) {
|
||||
size_t max_available;
|
||||
if (peer_b->len > peer_b->size - peer_b->offset) {
|
||||
/* Only the first half of the ring buffer can be read. */
|
||||
max_available = peer_b->size - peer_b->offset;
|
||||
} else {
|
||||
max_available = peer_b->len;
|
||||
}
|
||||
|
||||
*out_read_buf = peer_b->buf;
|
||||
*out_buf_offset = peer_b->offset;
|
||||
return max_available;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
|
||||
size_t* out_buf_offset,
|
||||
size_t* out_available_bytes) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
*out_available_bytes = 0;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peer_b->zero_copy_read_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b->request = 0; /* Is not used by zero-copy API. */
|
||||
|
||||
max_available =
|
||||
bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
|
||||
|
||||
assert(peer_b->buf != NULL);
|
||||
if (max_available > 0) {
|
||||
peer_b->zero_copy_read_lock = 1;
|
||||
}
|
||||
|
||||
*out_available_bytes = max_available;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
size_t dummy_read_offset;
|
||||
uint8_t* dummy_read_buf;
|
||||
|
||||
assert(BIO_get_retry_flags(bio) == 0);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!peer_b->zero_copy_read_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_available =
|
||||
bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
|
||||
if (bytes_read > max_available) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(peer_b->len >= bytes_read);
|
||||
peer_b->len -= bytes_read;
|
||||
assert(peer_b->offset + bytes_read <= peer_b->size);
|
||||
|
||||
/* Move read offset. If zero_copy_write_lock == 1 we must advance the
|
||||
* offset even if buffer becomes empty, to make sure
|
||||
* write_offset = (offset + len) mod size does not change. */
|
||||
if (peer_b->offset + bytes_read == peer_b->size ||
|
||||
(!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
|
||||
peer_b->offset = 0;
|
||||
} else {
|
||||
peer_b->offset += bytes_read;
|
||||
}
|
||||
|
||||
bio->num_read += bytes_read;
|
||||
peer_b->zero_copy_read_lock = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
|
||||
uint8_t** out_write_buf,
|
||||
size_t* out_buf_offset) {
|
||||
size_t write_offset;
|
||||
size_t max_available;
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
write_offset = b->offset + b->len;
|
||||
|
||||
if (write_offset >= b->size) {
|
||||
/* Only the first half of the ring buffer can be written to. */
|
||||
write_offset -= b->size;
|
||||
/* write up to the start of the ring buffer. */
|
||||
max_available = b->offset - write_offset;
|
||||
} else {
|
||||
/* write up to the end the buffer. */
|
||||
max_available = b->size - write_offset;
|
||||
}
|
||||
|
||||
*out_write_buf = b->buf;
|
||||
*out_buf_offset = write_offset;
|
||||
return max_available;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
|
||||
size_t* out_buf_offset,
|
||||
size_t* out_available_bytes) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
|
||||
*out_available_bytes = 0;
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->buf || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(b->buf != NULL);
|
||||
|
||||
if (b->zero_copy_write_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* Bio is already closed. */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
|
||||
|
||||
if (max_available > 0) {
|
||||
b->zero_copy_write_lock = 1;
|
||||
}
|
||||
|
||||
*out_available_bytes = max_available;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
|
||||
size_t rest;
|
||||
size_t dummy_write_offset;
|
||||
uint8_t* dummy_write_buf;
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->buf || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* BIO is already closed. */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!b->zero_copy_write_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
|
||||
|
||||
if (bytes_written > rest) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio->num_write += bytes_written;
|
||||
/* Move write offset. */
|
||||
b->len += bytes_written;
|
||||
b->zero_copy_write_lock = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
size_t size = size_;
|
||||
size_t rest;
|
||||
@@ -167,7 +422,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
|
||||
peer_b->request = 0; /* will be set in "retry_read" situation */
|
||||
|
||||
if (buf == NULL || size == 0) {
|
||||
if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -209,10 +464,13 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
}
|
||||
assert(peer_b->offset + chunk <= peer_b->size);
|
||||
|
||||
OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
|
||||
peer_b->len -= chunk;
|
||||
if (peer_b->len) {
|
||||
/* If zero_copy_write_lock == 1 we must advance the offset even if buffer
|
||||
* becomes empty, to make sure write_offset = (offset + len) % size
|
||||
* does not change. */
|
||||
if (peer_b->len || peer_b->zero_copy_write_lock) {
|
||||
peer_b->offset += chunk;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size) {
|
||||
@@ -246,6 +504,10 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
if (b->zero_copy_write_lock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* we already closed */
|
||||
@@ -289,7 +551,7 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
chunk = b->size - write_offset;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
|
||||
memcpy(b->buf + write_offset, buf, chunk);
|
||||
|
||||
b->len += chunk;
|
||||
|
||||
@@ -302,8 +564,9 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
return num;
|
||||
}
|
||||
|
||||
static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
|
||||
size_t writebuf2_len) {
|
||||
static int bio_make_pair(BIO* bio1, BIO* bio2,
|
||||
size_t writebuf1_len, uint8_t* ext_writebuf1,
|
||||
size_t writebuf2_len, uint8_t* ext_writebuf2) {
|
||||
struct bio_bio_st *b1, *b2;
|
||||
|
||||
assert(bio1 != NULL);
|
||||
@@ -317,14 +580,23 @@ static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(b1->buf_externally_allocated == 0);
|
||||
assert(b2->buf_externally_allocated == 0);
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
if (writebuf1_len) {
|
||||
b1->size = writebuf1_len;
|
||||
}
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
if (!ext_writebuf1) {
|
||||
b1->buf_externally_allocated = 0;
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
b1->buf = ext_writebuf1;
|
||||
b1->buf_externally_allocated = 1;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
@@ -334,10 +606,16 @@ static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
|
||||
if (writebuf2_len) {
|
||||
b2->size = writebuf2_len;
|
||||
}
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
if (!ext_writebuf2) {
|
||||
b2->buf_externally_allocated = 0;
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
b2->buf = ext_writebuf2;
|
||||
b2->buf_externally_allocated = 1;
|
||||
}
|
||||
b2->len = 0;
|
||||
b2->offset = 0;
|
||||
@@ -346,9 +624,13 @@ static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
|
||||
b1->peer = bio2;
|
||||
b1->closed = 0;
|
||||
b1->request = 0;
|
||||
b1->zero_copy_read_lock = 0;
|
||||
b1->zero_copy_write_lock = 0;
|
||||
b2->peer = bio1;
|
||||
b2->closed = 0;
|
||||
b2->request = 0;
|
||||
b2->zero_copy_read_lock = 0;
|
||||
b2->zero_copy_write_lock = 0;
|
||||
|
||||
bio1->init = 1;
|
||||
bio2->init = 1;
|
||||
@@ -450,30 +732,62 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bio_puts(BIO *bio, const char *str) {
|
||||
return bio_write(bio, str, strlen(str));
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
|
||||
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read,
|
||||
bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new,
|
||||
bio_free, NULL /* no bio_callback_ctrl */
|
||||
};
|
||||
|
||||
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
|
||||
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
|
||||
BIO** bio2_p, size_t writebuf2_len) {
|
||||
BIO *bio1 = BIO_new(bio_s_bio());
|
||||
BIO *bio2 = BIO_new(bio_s_bio());
|
||||
if (bio1 == NULL || bio2 == NULL ||
|
||||
!bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
|
||||
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
|
||||
BIO** bio2_p, size_t writebuf2) {
|
||||
return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
|
||||
writebuf2, NULL);
|
||||
}
|
||||
|
||||
int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
|
||||
uint8_t* ext_writebuf1,
|
||||
BIO** bio2_p, size_t writebuf2_len,
|
||||
uint8_t* ext_writebuf2) {
|
||||
BIO *bio1 = NULL, *bio2 = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* External buffers must have sizes greater than 0. */
|
||||
if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bio1 = BIO_new(bio_s_bio());
|
||||
if (bio1 == NULL) {
|
||||
goto err;
|
||||
}
|
||||
bio2 = BIO_new(bio_s_bio());
|
||||
if (bio2 == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
|
||||
ext_writebuf2)) {
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ret == 0) {
|
||||
BIO_free(bio1);
|
||||
bio1 = NULL;
|
||||
BIO_free(bio2);
|
||||
*bio1_p = NULL;
|
||||
*bio2_p = NULL;
|
||||
return 0;
|
||||
bio2 = NULL;
|
||||
}
|
||||
|
||||
*bio1_p = bio1;
|
||||
*bio2_p = bio2;
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_get_read_request(BIO *bio) {
|
||||
|
||||
+7
-6
@@ -67,7 +67,7 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <winsock2.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
|
||||
OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
@@ -142,6 +142,10 @@ static int sock_write(BIO *b, const char *in, int inl) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sock_puts(BIO *bp, const char *str) {
|
||||
return sock_write(bp, str, strlen(str));
|
||||
}
|
||||
|
||||
static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
@@ -181,11 +185,8 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_sockp = {
|
||||
BIO_TYPE_SOCKET, "socket",
|
||||
sock_write, sock_read,
|
||||
NULL /* puts */, NULL /* gets, */,
|
||||
sock_ctrl, sock_new,
|
||||
sock_free, NULL /* callback_ctrl */,
|
||||
BIO_TYPE_SOCKET, "socket", sock_write, sock_read, sock_puts,
|
||||
NULL /* gets, */, sock_ctrl, sock_new, sock_free, NULL,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
|
||||
|
||||
@@ -33,7 +33,6 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
@@ -46,7 +45,7 @@ int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
|
||||
*out_sock = -1;
|
||||
|
||||
OPENSSL_memset(&hint, 0, sizeof(hint));
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
@@ -63,8 +62,8 @@ int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
|
||||
continue;
|
||||
}
|
||||
OPENSSL_memset(out_addr, 0, sizeof(struct sockaddr_storage));
|
||||
OPENSSL_memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
|
||||
memset(out_addr, 0, sizeof(struct sockaddr_storage));
|
||||
memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
|
||||
*out_addr_length = cur->ai_addrlen;
|
||||
|
||||
*out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
||||
|
||||
@@ -6,6 +6,7 @@ if (${ARCH} STREQUAL "x86_64")
|
||||
|
||||
x86_64-mont.${ASM_EXT}
|
||||
x86_64-mont5.${ASM_EXT}
|
||||
rsaz-x86_64.${ASM_EXT}
|
||||
rsaz-avx2.${ASM_EXT}
|
||||
|
||||
rsaz_exp.c
|
||||
@@ -68,6 +69,7 @@ add_library(
|
||||
|
||||
perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
|
||||
perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
|
||||
perlasm(rsaz-x86_64.${ASM_EXT} asm/rsaz-x86_64.pl)
|
||||
perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
|
||||
perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
|
||||
perlasm(co-586.${ASM_EXT} asm/co-586.pl)
|
||||
|
||||
+1
-1
@@ -314,7 +314,7 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
|
||||
}
|
||||
|
||||
if (dif > 0 && rp != ap) {
|
||||
OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif);
|
||||
memcpy(rp, ap, sizeof(*rp) * dif);
|
||||
}
|
||||
|
||||
r->top = max;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# [depending on key length, less for longer keys] on ARM920T, and
|
||||
# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
|
||||
# base and compiler generated code with in-lined umull and even umlal
|
||||
# instructions. The latter means that this code didn't really have an
|
||||
# instructions. The latter means that this code didn't really have an
|
||||
# "advantage" of utilizing some "secret" instruction.
|
||||
#
|
||||
# The code is interoperable with Thumb ISA and is rather compact, less
|
||||
|
||||
+12
-12
@@ -47,7 +47,7 @@ sub bn_mul_add_words
|
||||
&movd("mm0",&wparam(3)); # mm0 = w
|
||||
&pxor("mm1","mm1"); # mm1 = carry_in
|
||||
&jmp(&label("maw_sse2_entry"));
|
||||
|
||||
|
||||
&set_label("maw_sse2_unrolled",16);
|
||||
&movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0]
|
||||
&paddq("mm1","mm3"); # mm1 = carry_in + r[0]
|
||||
@@ -668,20 +668,20 @@ sub bn_sub_part_words
|
||||
&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");
|
||||
@@ -698,9 +698,9 @@ sub bn_sub_part_words
|
||||
}
|
||||
|
||||
&jmp(&label("pw_end"));
|
||||
|
||||
|
||||
&set_label("pw_pos",0);
|
||||
|
||||
|
||||
&and($num,0xfffffff8); # num / 8
|
||||
&jz(&label("pw_pos_finish"));
|
||||
|
||||
@@ -715,18 +715,18 @@ sub bn_sub_part_words
|
||||
&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");
|
||||
@@ -747,17 +747,17 @@ sub bn_sub_part_words
|
||||
&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
|
||||
|
||||
@@ -41,7 +41,7 @@ sub mul_add_c
|
||||
&mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b
|
||||
###
|
||||
&adc($c2,0);
|
||||
# is pos > 1, it means it is the last loop
|
||||
# is pos > 1, it means it is the last loop
|
||||
&mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[];
|
||||
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a
|
||||
}
|
||||
@@ -70,7 +70,7 @@ sub sqr_add_c
|
||||
&mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
|
||||
###
|
||||
&adc($c2,0);
|
||||
# is pos > 1, it means it is the last loop
|
||||
# is pos > 1, it means it is the last loop
|
||||
&mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[];
|
||||
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b
|
||||
}
|
||||
@@ -121,7 +121,7 @@ sub bn_mul_comba
|
||||
$c2="ebp";
|
||||
$a="esi";
|
||||
$b="edi";
|
||||
|
||||
|
||||
$as=0;
|
||||
$ae=0;
|
||||
$bs=0;
|
||||
@@ -136,9 +136,9 @@ sub bn_mul_comba
|
||||
&push("ebx");
|
||||
|
||||
&xor($c0,$c0);
|
||||
&mov("eax",&DWP(0,$a,"",0)); # load the first word
|
||||
&mov("eax",&DWP(0,$a,"",0)); # load the first word
|
||||
&xor($c1,$c1);
|
||||
&mov("edx",&DWP(0,$b,"",0)); # load the first second
|
||||
&mov("edx",&DWP(0,$b,"",0)); # load the first second
|
||||
|
||||
for ($i=0; $i<$tot; $i++)
|
||||
{
|
||||
@@ -146,7 +146,7 @@ sub bn_mul_comba
|
||||
$bi=$bs;
|
||||
$end=$be+1;
|
||||
|
||||
&comment("################## Calculate word $i");
|
||||
&comment("################## Calculate word $i");
|
||||
|
||||
for ($j=$bs; $j<$end; $j++)
|
||||
{
|
||||
|
||||
+12
-59
@@ -84,8 +84,8 @@ die "can't locate x86_64-xlate.pl";
|
||||
# output, so this isn't useful anyway.
|
||||
#
|
||||
# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1.
|
||||
$avx = 2;
|
||||
$addx = 1;
|
||||
$avx = 0;
|
||||
$addx = 0;
|
||||
|
||||
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
|
||||
*STDOUT = *OUT;
|
||||
@@ -145,21 +145,13 @@ $code.=<<___;
|
||||
.type rsaz_1024_sqr_avx2,\@function,5
|
||||
.align 64
|
||||
rsaz_1024_sqr_avx2: # 702 cycles, 14% faster than rsaz_1024_mul_avx2
|
||||
.cfi_startproc
|
||||
lea (%rsp), %rax
|
||||
.cfi_def_cfa_register %rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
vzeroupper
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
@@ -178,7 +170,6 @@ $code.=<<___ if ($win64);
|
||||
___
|
||||
$code.=<<___;
|
||||
mov %rax,%rbp
|
||||
.cfi_def_cfa_register %rbp
|
||||
mov %rdx, $np # reassigned argument
|
||||
sub \$$FrameSize, %rsp
|
||||
mov $np, $tmp
|
||||
@@ -368,7 +359,7 @@ $code.=<<___;
|
||||
vpaddq $TEMP1, $ACC1, $ACC1
|
||||
vpmuludq 32*7-128($aap), $B2, $ACC2
|
||||
vpbroadcastq 32*5-128($tpa), $B2
|
||||
vpaddq 32*11-448($tp1), $ACC2, $ACC2
|
||||
vpaddq 32*11-448($tp1), $ACC2, $ACC2
|
||||
|
||||
vmovdqu $ACC6, 32*6-192($tp0)
|
||||
vmovdqu $ACC7, 32*7-192($tp0)
|
||||
@@ -427,7 +418,7 @@ $code.=<<___;
|
||||
vmovdqu $ACC7, 32*16-448($tp1)
|
||||
lea 8($tp1), $tp1
|
||||
|
||||
dec $i
|
||||
dec $i
|
||||
jnz .LOOP_SQR_1024
|
||||
___
|
||||
$ZERO = $ACC9;
|
||||
@@ -772,7 +763,7 @@ $code.=<<___;
|
||||
vpblendd \$3, $TEMP4, $TEMP5, $TEMP4
|
||||
vpaddq $TEMP3, $ACC7, $ACC7
|
||||
vpaddq $TEMP4, $ACC8, $ACC8
|
||||
|
||||
|
||||
vpsrlq \$29, $ACC4, $TEMP1
|
||||
vpand $AND_MASK, $ACC4, $ACC4
|
||||
vpsrlq \$29, $ACC5, $TEMP2
|
||||
@@ -811,10 +802,8 @@ $code.=<<___;
|
||||
|
||||
vzeroall
|
||||
mov %rbp, %rax
|
||||
.cfi_def_cfa_register %rax
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
.Lsqr_1024_in_tail:
|
||||
movaps -0xd8(%rax),%xmm6
|
||||
movaps -0xc8(%rax),%xmm7
|
||||
movaps -0xb8(%rax),%xmm8
|
||||
@@ -828,22 +817,14 @@ $code.=<<___ if ($win64);
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rax),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rax),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rax),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rax),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rax),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rax),%rsp # restore %rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lsqr_1024_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
|
||||
___
|
||||
}
|
||||
@@ -896,21 +877,13 @@ $code.=<<___;
|
||||
.type rsaz_1024_mul_avx2,\@function,5
|
||||
.align 64
|
||||
rsaz_1024_mul_avx2:
|
||||
.cfi_startproc
|
||||
lea (%rsp), %rax
|
||||
.cfi_def_cfa_register %rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
vzeroupper
|
||||
@@ -929,7 +902,6 @@ $code.=<<___ if ($win64);
|
||||
___
|
||||
$code.=<<___;
|
||||
mov %rax,%rbp
|
||||
.cfi_def_cfa_register %rbp
|
||||
vzeroall
|
||||
mov %rdx, $bp # reassigned argument
|
||||
sub \$64,%rsp
|
||||
@@ -1456,17 +1428,15 @@ $code.=<<___;
|
||||
vpaddq $TEMP4, $ACC8, $ACC8
|
||||
|
||||
vmovdqu $ACC4, 128-128($rp)
|
||||
vmovdqu $ACC5, 160-128($rp)
|
||||
vmovdqu $ACC5, 160-128($rp)
|
||||
vmovdqu $ACC6, 192-128($rp)
|
||||
vmovdqu $ACC7, 224-128($rp)
|
||||
vmovdqu $ACC8, 256-128($rp)
|
||||
vzeroupper
|
||||
|
||||
mov %rbp, %rax
|
||||
.cfi_def_cfa_register %rax
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
.Lmul_1024_in_tail:
|
||||
movaps -0xd8(%rax),%xmm6
|
||||
movaps -0xc8(%rax),%xmm7
|
||||
movaps -0xb8(%rax),%xmm8
|
||||
@@ -1480,22 +1450,14 @@ $code.=<<___ if ($win64);
|
||||
___
|
||||
$code.=<<___;
|
||||
mov -48(%rax),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rax),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rax),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rax),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rax),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rax),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rax),%rsp # restore %rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lmul_1024_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2
|
||||
___
|
||||
}
|
||||
@@ -1614,10 +1576,8 @@ rsaz_1024_scatter5_avx2:
|
||||
.type rsaz_1024_gather5_avx2,\@abi-omnipotent
|
||||
.align 32
|
||||
rsaz_1024_gather5_avx2:
|
||||
.cfi_startproc
|
||||
vzeroupper
|
||||
mov %rsp,%r11
|
||||
.cfi_def_cfa_register %r11
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
lea -0x88(%rsp),%rax
|
||||
@@ -1755,13 +1715,11 @@ $code.=<<___ if ($win64);
|
||||
movaps -0x38(%r11),%xmm13
|
||||
movaps -0x28(%r11),%xmm14
|
||||
movaps -0x18(%r11),%xmm15
|
||||
.LSEH_end_rsaz_1024_gather5:
|
||||
___
|
||||
$code.=<<___;
|
||||
lea (%r11),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LSEH_end_rsaz_1024_gather5:
|
||||
.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
|
||||
___
|
||||
}
|
||||
@@ -1834,17 +1792,14 @@ rsaz_se_handler:
|
||||
cmp %r10,%rbx # context->Rip<prologue label
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=epilogue label
|
||||
jae .Lcommon_seh_tail
|
||||
|
||||
mov 160($context),%rbp # pull context->Rbp
|
||||
|
||||
mov 8(%r11),%r10d # HandlerData[2]
|
||||
lea (%rsi,%r10),%r10 # "in tail" label
|
||||
cmp %r10,%rbx # context->Rip>="in tail" label
|
||||
cmovc %rbp,%rax
|
||||
mov 160($context),%rax # pull context->Rbp
|
||||
|
||||
mov -48(%rax),%r15
|
||||
mov -40(%rax),%r14
|
||||
@@ -1922,13 +1877,11 @@ rsaz_se_handler:
|
||||
.LSEH_info_rsaz_1024_sqr_avx2:
|
||||
.byte 9,0,0,0
|
||||
.rva rsaz_se_handler
|
||||
.rva .Lsqr_1024_body,.Lsqr_1024_epilogue,.Lsqr_1024_in_tail
|
||||
.long 0
|
||||
.rva .Lsqr_1024_body,.Lsqr_1024_epilogue
|
||||
.LSEH_info_rsaz_1024_mul_avx2:
|
||||
.byte 9,0,0,0
|
||||
.rva rsaz_se_handler
|
||||
.rva .Lmul_1024_body,.Lmul_1024_epilogue,.Lmul_1024_in_tail
|
||||
.long 0
|
||||
.rva .Lmul_1024_body,.Lmul_1024_epilogue
|
||||
.LSEH_info_rsaz_1024_gather5:
|
||||
.byte 0x01,0x36,0x17,0x0b
|
||||
.byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
|
||||
|
||||
Executable
+2338
File diff suppressed because it is too large
Load Diff
Executable → Regular
+19
-44
@@ -32,7 +32,7 @@ require "x86asm.pl";
|
||||
|
||||
$output = pop;
|
||||
open STDOUT,">$output";
|
||||
|
||||
|
||||
&asm_init($ARGV[0],$0);
|
||||
|
||||
$sse2=0;
|
||||
@@ -66,57 +66,33 @@ $frame=32; # size of above frame rounded up to 16n
|
||||
|
||||
&lea ("esi",&wparam(0)); # put aside pointer to argument block
|
||||
&lea ("edx",&wparam(1)); # load ap
|
||||
&mov ("ebp","esp"); # saved stack pointer!
|
||||
&add ("edi",2); # extra two words on top of tp
|
||||
&neg ("edi");
|
||||
&lea ("ebp",&DWP(-$frame,"esp","edi",4)); # future alloca($frame+4*(num+2))
|
||||
&lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2))
|
||||
&neg ("edi");
|
||||
|
||||
# minimize cache contention by arraning 2K window between stack
|
||||
# pointer and ap argument [np is also position sensitive vector,
|
||||
# but it's assumed to be near ap, as it's allocated at ~same
|
||||
# time].
|
||||
&mov ("eax","ebp");
|
||||
&mov ("eax","esp");
|
||||
&sub ("eax","edx");
|
||||
&and ("eax",2047);
|
||||
&sub ("ebp","eax"); # this aligns sp and ap modulo 2048
|
||||
&sub ("esp","eax"); # this aligns sp and ap modulo 2048
|
||||
|
||||
&xor ("edx","ebp");
|
||||
&xor ("edx","esp");
|
||||
&and ("edx",2048);
|
||||
&xor ("edx",2048);
|
||||
&sub ("ebp","edx"); # this splits them apart modulo 4096
|
||||
&sub ("esp","edx"); # this splits them apart modulo 4096
|
||||
|
||||
&and ("ebp",-64); # align to cache line
|
||||
|
||||
# An OS-agnostic version of __chkstk.
|
||||
#
|
||||
# Some OSes (Windows) insist on stack being "wired" to
|
||||
# physical memory in strictly sequential manner, i.e. if stack
|
||||
# allocation spans two pages, then reference to farmost one can
|
||||
# be punishable by SEGV. But page walking can do good even on
|
||||
# other OSes, because it guarantees that villain thread hits
|
||||
# the guard page before it can make damage to innocent one...
|
||||
&mov ("eax","esp");
|
||||
&sub ("eax","ebp");
|
||||
&and ("eax",-4096);
|
||||
&mov ("edx","esp"); # saved stack pointer!
|
||||
&lea ("esp",&DWP(0,"ebp","eax"));
|
||||
&mov ("eax",&DWP(0,"esp"));
|
||||
&cmp ("esp","ebp");
|
||||
&ja (&label("page_walk"));
|
||||
&jmp (&label("page_walk_done"));
|
||||
|
||||
&set_label("page_walk",16);
|
||||
&lea ("esp",&DWP(-4096,"esp"));
|
||||
&mov ("eax",&DWP(0,"esp"));
|
||||
&cmp ("esp","ebp");
|
||||
&ja (&label("page_walk"));
|
||||
&set_label("page_walk_done");
|
||||
&and ("esp",-64); # align to cache line
|
||||
|
||||
################################# load argument block...
|
||||
&mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp
|
||||
&mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap
|
||||
&mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp
|
||||
&mov ("ebp",&DWP(3*4,"esi"));# const BN_ULONG *np
|
||||
&mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np
|
||||
&mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0
|
||||
#&mov ("edi",&DWP(5*4,"esi"));# int num
|
||||
|
||||
@@ -124,11 +100,11 @@ $frame=32; # size of above frame rounded up to 16n
|
||||
&mov ($_rp,"eax"); # ... save a copy of argument block
|
||||
&mov ($_ap,"ebx");
|
||||
&mov ($_bp,"ecx");
|
||||
&mov ($_np,"ebp");
|
||||
&mov ($_np,"edx");
|
||||
&mov ($_n0,"esi");
|
||||
&lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling
|
||||
#&mov ($_num,$num); # redundant as $num is not reused
|
||||
&mov ($_sp,"edx"); # saved stack pointer!
|
||||
&mov ($_sp,"ebp"); # saved stack pointer!
|
||||
|
||||
if($sse2) {
|
||||
$acc0="mm0"; # mmx register bank layout
|
||||
@@ -294,7 +270,7 @@ if (0) {
|
||||
&xor ("eax","eax"); # signal "not fast enough [yet]"
|
||||
&jmp (&label("just_leave"));
|
||||
# While the below code provides competitive performance for
|
||||
# all key lengths on modern Intel cores, it's still more
|
||||
# all key lengthes on modern Intel cores, it's still more
|
||||
# than 10% slower for 4096-bit key elsewhere:-( "Competitive"
|
||||
# means compared to the original integer-only assembler.
|
||||
# 512-bit RSA sign is better by ~40%, but that's about all
|
||||
@@ -597,16 +573,15 @@ $sbit=$num;
|
||||
&jge (&label("sub"));
|
||||
|
||||
&sbb ("eax",0); # handle upmost overflow bit
|
||||
&and ($tp,"eax");
|
||||
¬ ("eax");
|
||||
&mov ($np,$rp);
|
||||
&and ($np,"eax");
|
||||
&or ($tp,$np); # tp=carry?tp:rp
|
||||
|
||||
&set_label("copy",16); # copy or in-place refresh
|
||||
&mov ("eax",&DWP(0,$tp,$num,4));
|
||||
&mov (&DWP(0,$rp,$num,4),"eax"); # rp[i]=tp[i]
|
||||
&mov (&DWP($frame,"esp",$num,4),$j); # zap temporary vector
|
||||
&mov ("edx",&DWP(0,$tp,$num,4));
|
||||
&mov ($np,&DWP(0,$rp,$num,4));
|
||||
&xor ("edx",$np); # conditional select
|
||||
&and ("edx","eax");
|
||||
&xor ("edx",$np);
|
||||
&mov (&DWP(0,$tp,$num,4),$j) # zap temporary vector
|
||||
&mov (&DWP(0,$rp,$num,4),"edx"); # rp[i]=tp[i]
|
||||
&dec ($num);
|
||||
&jge (&label("copy"));
|
||||
|
||||
|
||||
+10
-11
@@ -80,7 +80,7 @@
|
||||
: "+m"(r), "+d"(high) \
|
||||
: "r"(carry), "g"(0) \
|
||||
: "cc"); \
|
||||
(carry) = high; \
|
||||
carry = high; \
|
||||
} while (0)
|
||||
|
||||
#define mul(r, a, word, carry) \
|
||||
@@ -91,8 +91,7 @@
|
||||
: "+r"(carry), "+d"(high) \
|
||||
: "a"(low), "g"(0) \
|
||||
: "cc"); \
|
||||
(r) = (carry); \
|
||||
(carry) = high; \
|
||||
(r) = carry, carry = high; \
|
||||
} while (0)
|
||||
#undef sqr
|
||||
#define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
|
||||
@@ -257,14 +256,14 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"((a)[i]) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
|
||||
+88
-231
@@ -84,10 +84,6 @@ $code=<<___;
|
||||
.type bn_mul_mont,\@function,6
|
||||
.align 16
|
||||
bn_mul_mont:
|
||||
.cfi_startproc
|
||||
mov ${num}d,${num}d
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
test \$3,${num}d
|
||||
jnz .Lmul_enter
|
||||
cmp \$8,${num}d
|
||||
@@ -106,50 +102,20 @@ $code.=<<___;
|
||||
.align 16
|
||||
.Lmul_enter:
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
|
||||
neg $num
|
||||
mov ${num}d,${num}d
|
||||
lea 2($num),%r10
|
||||
mov %rsp,%r11
|
||||
lea -16(%rsp,$num,8),%r10 # future alloca(8*(num+2))
|
||||
neg $num # restore $num
|
||||
and \$-1024,%r10 # minimize TLB usage
|
||||
neg %r10
|
||||
lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+2))
|
||||
and \$-1024,%rsp # minimize TLB usage
|
||||
|
||||
# An OS-agnostic version of __chkstk.
|
||||
#
|
||||
# Some OSes (Windows) insist on stack being "wired" to
|
||||
# physical memory in strictly sequential manner, i.e. if stack
|
||||
# allocation spans two pages, then reference to farmost one can
|
||||
# be punishable by SEGV. But page walking can do good even on
|
||||
# other OSes, because it guarantees that villain thread hits
|
||||
# the guard page before it can make damage to innocent one...
|
||||
sub %r10,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%r10,%r11),%rsp
|
||||
mov (%rsp),%r11
|
||||
cmp %r10,%rsp
|
||||
ja .Lmul_page_walk
|
||||
jmp .Lmul_page_walk_done
|
||||
|
||||
.align 16
|
||||
.Lmul_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r11
|
||||
cmp %r10,%rsp
|
||||
ja .Lmul_page_walk
|
||||
.Lmul_page_walk_done:
|
||||
|
||||
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
|
||||
.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8
|
||||
mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
|
||||
.Lmul_body:
|
||||
mov $bp,%r12 # reassign $bp
|
||||
___
|
||||
@@ -299,46 +265,36 @@ $code.=<<___;
|
||||
mov %rax,($rp,$i,8) # rp[i]=tp[i]-np[i]
|
||||
mov 8($ap,$i,8),%rax # tp[i+1]
|
||||
lea 1($i),$i # i++
|
||||
dec $j # doesnn't affect CF!
|
||||
dec $j # doesn't affect CF!
|
||||
jnz .Lsub
|
||||
|
||||
sbb \$0,%rax # handle upmost overflow bit
|
||||
xor $i,$i
|
||||
and %rax,$ap
|
||||
not %rax
|
||||
mov $rp,$np
|
||||
and %rax,$np
|
||||
mov $num,$j # j=num
|
||||
or $np,$ap # ap=borrow?tp:rp
|
||||
.align 16
|
||||
.Lcopy: # copy or in-place refresh
|
||||
mov ($ap,$i,8),%rax
|
||||
mov (%rsp,$i,8),$ap
|
||||
mov ($rp,$i,8),$np
|
||||
xor $np,$ap # conditional select:
|
||||
and %rax,$ap # ((ap ^ np) & %rax) ^ np
|
||||
xor $np,$ap # ap = borrow?tp:rp
|
||||
mov $i,(%rsp,$i,8) # zap temporary vector
|
||||
mov %rax,($rp,$i,8) # rp[i]=tp[i]
|
||||
mov $ap,($rp,$i,8) # rp[i]=tp[i]
|
||||
lea 1($i),$i
|
||||
sub \$1,$j
|
||||
jnz .Lcopy
|
||||
|
||||
mov 8(%rsp,$num,8),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
mov (%rsi),%r15
|
||||
mov 8(%rsi),%r14
|
||||
mov 16(%rsi),%r13
|
||||
mov 24(%rsi),%r12
|
||||
mov 32(%rsi),%rbp
|
||||
mov 40(%rsi),%rbx
|
||||
lea 48(%rsi),%rsp
|
||||
.Lmul_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_mul_mont,.-bn_mul_mont
|
||||
___
|
||||
{{{
|
||||
@@ -348,10 +304,6 @@ $code.=<<___;
|
||||
.type bn_mul4x_mont,\@function,6
|
||||
.align 16
|
||||
bn_mul4x_mont:
|
||||
.cfi_startproc
|
||||
mov ${num}d,${num}d
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
.Lmul4x_enter:
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
@@ -361,41 +313,20 @@ $code.=<<___ if ($addx);
|
||||
___
|
||||
$code.=<<___;
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
|
||||
neg $num
|
||||
mov ${num}d,${num}d
|
||||
lea 4($num),%r10
|
||||
mov %rsp,%r11
|
||||
lea -32(%rsp,$num,8),%r10 # future alloca(8*(num+4))
|
||||
neg $num # restore
|
||||
and \$-1024,%r10 # minimize TLB usage
|
||||
neg %r10
|
||||
lea (%rsp,%r10,8),%rsp # tp=alloca(8*(num+4))
|
||||
and \$-1024,%rsp # minimize TLB usage
|
||||
|
||||
sub %r10,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%r10,%r11),%rsp
|
||||
mov (%rsp),%r11
|
||||
cmp %r10,%rsp
|
||||
ja .Lmul4x_page_walk
|
||||
jmp .Lmul4x_page_walk_done
|
||||
|
||||
.Lmul4x_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r11
|
||||
cmp %r10,%rsp
|
||||
ja .Lmul4x_page_walk
|
||||
.Lmul4x_page_walk_done:
|
||||
|
||||
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
|
||||
.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8
|
||||
mov %r11,8(%rsp,$num,8) # tp[num+1]=%rsp
|
||||
.Lmul4x_body:
|
||||
mov $rp,16(%rsp,$num,8) # tp[num+2]=$rp
|
||||
mov %rdx,%r12 # reassign $bp
|
||||
@@ -702,11 +633,9 @@ ___
|
||||
my @ri=("%rax","%rdx",$m0,$m1);
|
||||
$code.=<<___;
|
||||
mov 16(%rsp,$num,8),$rp # restore $rp
|
||||
lea -4($num),$j
|
||||
mov 0(%rsp),@ri[0] # tp[0]
|
||||
pxor %xmm0,%xmm0
|
||||
mov 8(%rsp),@ri[1] # tp[1]
|
||||
shr \$2,$j # j=num/4-1
|
||||
shr \$2,$num # num/=4
|
||||
lea (%rsp),$ap # borrow ap for tp
|
||||
xor $i,$i # i=0 and clear CF!
|
||||
|
||||
@@ -714,6 +643,7 @@ $code.=<<___;
|
||||
mov 16($ap),@ri[2] # tp[2]
|
||||
mov 24($ap),@ri[3] # tp[3]
|
||||
sbb 8($np),@ri[1]
|
||||
lea -1($num),$j # j=num/4-1
|
||||
jmp .Lsub4x
|
||||
.align 16
|
||||
.Lsub4x:
|
||||
@@ -741,58 +671,50 @@ $code.=<<___;
|
||||
mov @ri[2],16($rp,$i,8) # rp[i]=tp[i]-np[i]
|
||||
|
||||
sbb \$0,@ri[0] # handle upmost overflow bit
|
||||
mov @ri[0],%xmm0
|
||||
punpcklqdq %xmm0,%xmm0 # extend mask to 128 bits
|
||||
mov @ri[3],24($rp,$i,8) # rp[i]=tp[i]-np[i]
|
||||
xor $i,$i # i=0
|
||||
and @ri[0],$ap
|
||||
not @ri[0]
|
||||
mov $rp,$np
|
||||
and @ri[0],$np
|
||||
lea -4($num),$j
|
||||
or $np,$ap # ap=borrow?tp:rp
|
||||
shr \$2,$j # j=num/4-1
|
||||
|
||||
movdqu ($ap),%xmm1
|
||||
movdqa %xmm0,(%rsp)
|
||||
movdqu %xmm1,($rp)
|
||||
mov $num,$j
|
||||
pxor %xmm5,%xmm5
|
||||
jmp .Lcopy4x
|
||||
.align 16
|
||||
.Lcopy4x: # copy or in-place refresh
|
||||
movdqu 16($ap,$i),%xmm2
|
||||
movdqu 32($ap,$i),%xmm1
|
||||
movdqa %xmm0,16(%rsp,$i)
|
||||
movdqu %xmm2,16($rp,$i)
|
||||
movdqa %xmm0,32(%rsp,$i)
|
||||
movdqu %xmm1,32($rp,$i)
|
||||
.Lcopy4x: # copy or in-place refresh
|
||||
movdqu (%rsp,$i),%xmm2
|
||||
movdqu 16(%rsp,$i),%xmm4
|
||||
movdqu ($rp,$i),%xmm1
|
||||
movdqu 16($rp,$i),%xmm3
|
||||
pxor %xmm1,%xmm2 # conditional select
|
||||
pxor %xmm3,%xmm4
|
||||
pand %xmm0,%xmm2
|
||||
pand %xmm0,%xmm4
|
||||
pxor %xmm1,%xmm2
|
||||
pxor %xmm3,%xmm4
|
||||
movdqu %xmm2,($rp,$i)
|
||||
movdqu %xmm4,16($rp,$i)
|
||||
movdqa %xmm5,(%rsp,$i) # zap temporary vectors
|
||||
movdqa %xmm5,16(%rsp,$i)
|
||||
|
||||
lea 32($i),$i
|
||||
dec $j
|
||||
jnz .Lcopy4x
|
||||
|
||||
movdqu 16($ap,$i),%xmm2
|
||||
movdqa %xmm0,16(%rsp,$i)
|
||||
movdqu %xmm2,16($rp,$i)
|
||||
shl \$2,$num
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
mov 8(%rsp,$num,8),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi, 8
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
mov (%rsi),%r15
|
||||
mov 8(%rsi),%r14
|
||||
mov 16(%rsi),%r13
|
||||
mov 24(%rsi),%r12
|
||||
mov 32(%rsi),%rbp
|
||||
mov 40(%rsi),%rbx
|
||||
lea 48(%rsi),%rsp
|
||||
.Lmul4x_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_mul4x_mont,.-bn_mul4x_mont
|
||||
___
|
||||
}}}
|
||||
@@ -820,23 +742,14 @@ $code.=<<___;
|
||||
.type bn_sqr8x_mont,\@function,6
|
||||
.align 32
|
||||
bn_sqr8x_mont:
|
||||
.cfi_startproc
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
.Lsqr8x_enter:
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lsqr8x_prologue:
|
||||
|
||||
mov ${num}d,%r10d
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
@@ -849,49 +762,30 @@ bn_sqr8x_mont:
|
||||
# do its job.
|
||||
#
|
||||
lea -64(%rsp,$num,2),%r11
|
||||
mov %rsp,%rbp
|
||||
mov ($n0),$n0 # *n0
|
||||
sub $aptr,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lsqr8x_sp_alt
|
||||
sub %r11,%rbp # align with $aptr
|
||||
lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num)
|
||||
sub %r11,%rsp # align with $aptr
|
||||
lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
|
||||
jmp .Lsqr8x_sp_done
|
||||
|
||||
.align 32
|
||||
.Lsqr8x_sp_alt:
|
||||
lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
|
||||
lea -64(%rbp,$num,2),%rbp # future alloca(frame+2*$num)
|
||||
lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rbp
|
||||
sub %r11,%rsp
|
||||
.Lsqr8x_sp_done:
|
||||
and \$-64,%rbp
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lsqr8x_page_walk
|
||||
jmp .Lsqr8x_page_walk_done
|
||||
|
||||
.align 16
|
||||
.Lsqr8x_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lsqr8x_page_walk
|
||||
.Lsqr8x_page_walk_done:
|
||||
|
||||
and \$-64,%rsp
|
||||
mov $num,%r10
|
||||
neg $num
|
||||
|
||||
mov $n0, 32(%rsp)
|
||||
mov %rax, 40(%rsp) # save original %rsp
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
.Lsqr8x_body:
|
||||
|
||||
movq $nptr, %xmm2 # save pointer to modulus
|
||||
@@ -961,7 +855,6 @@ $code.=<<___;
|
||||
pxor %xmm0,%xmm0
|
||||
pshufd \$0,%xmm1,%xmm1
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
jmp .Lsqr8x_cond_copy
|
||||
|
||||
.align 32
|
||||
@@ -991,22 +884,14 @@ $code.=<<___;
|
||||
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lsqr8x_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_sqr8x_mont,.-bn_sqr8x_mont
|
||||
___
|
||||
}}}
|
||||
@@ -1018,48 +903,23 @@ $code.=<<___;
|
||||
.type bn_mulx4x_mont,\@function,6
|
||||
.align 32
|
||||
bn_mulx4x_mont:
|
||||
.cfi_startproc
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
.Lmulx4x_enter:
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lmulx4x_prologue:
|
||||
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
.byte 0x67
|
||||
xor %r10,%r10
|
||||
sub $num,%r10 # -$num
|
||||
mov ($n0),$n0 # *n0
|
||||
lea -72(%rsp,%r10),%rbp # future alloca(frame+$num+8)
|
||||
and \$-128,%rbp
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lmulx4x_page_walk
|
||||
jmp .Lmulx4x_page_walk_done
|
||||
|
||||
.align 16
|
||||
.Lmulx4x_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lmulx4x_page_walk
|
||||
.Lmulx4x_page_walk_done:
|
||||
|
||||
lea -72(%rsp,%r10),%rsp # alloca(frame+$num+8)
|
||||
lea ($bp,$num),%r10
|
||||
and \$-128,%rsp
|
||||
##############################################################
|
||||
# Stack layout
|
||||
# +0 num
|
||||
@@ -1079,7 +939,6 @@ bn_mulx4x_mont:
|
||||
mov $n0, 24(%rsp) # save *n0
|
||||
mov $rp, 32(%rsp) # save $rp
|
||||
mov %rax,40(%rsp) # save original %rsp
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
mov $num,48(%rsp) # inner counter
|
||||
jmp .Lmulx4x_body
|
||||
|
||||
@@ -1200,17 +1059,18 @@ $code.=<<___;
|
||||
mulx 2*8($aptr),%r15,%r13 # ...
|
||||
adox -3*8($tptr),%r11
|
||||
adcx %r15,%r12
|
||||
adox -2*8($tptr),%r12
|
||||
adox $zero,%r12
|
||||
adcx $zero,%r13
|
||||
adox $zero,%r13
|
||||
|
||||
mov $bptr,8(%rsp) # off-load &b[i]
|
||||
.byte 0x67
|
||||
mov $mi,%r15
|
||||
imulq 24(%rsp),$mi # "t[0]"*n0
|
||||
xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0
|
||||
|
||||
mulx 3*8($aptr),%rax,%r14
|
||||
mov $mi,%rdx
|
||||
adox -2*8($tptr),%r12
|
||||
adcx %rax,%r13
|
||||
adox -1*8($tptr),%r13
|
||||
adcx $zero,%r14
|
||||
@@ -1329,7 +1189,6 @@ $code.=<<___;
|
||||
pxor %xmm0,%xmm0
|
||||
pshufd \$0,%xmm1,%xmm1
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
jmp .Lmulx4x_cond_copy
|
||||
|
||||
.align 32
|
||||
@@ -1359,22 +1218,14 @@ $code.=<<___;
|
||||
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lmulx4x_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_mulx4x_mont,.-bn_mulx4x_mont
|
||||
___
|
||||
}}}
|
||||
@@ -1427,8 +1278,22 @@ mul_handler:
|
||||
|
||||
mov 192($context),%r10 # pull $num
|
||||
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
|
||||
lea 48(%rax),%rax
|
||||
|
||||
jmp .Lcommon_pop_regs
|
||||
mov -8(%rax),%rbx
|
||||
mov -16(%rax),%rbp
|
||||
mov -24(%rax),%r12
|
||||
mov -32(%rax),%r13
|
||||
mov -40(%rax),%r14
|
||||
mov -48(%rax),%r15
|
||||
mov %rbx,144($context) # restore context->Rbx
|
||||
mov %rbp,160($context) # restore context->Rbp
|
||||
mov %r12,216($context) # restore context->R12
|
||||
mov %r13,224($context) # restore context->R13
|
||||
mov %r14,232($context) # restore context->R14
|
||||
mov %r15,240($context) # restore context->R15
|
||||
|
||||
jmp .Lcommon_seh_tail
|
||||
.size mul_handler,.-mul_handler
|
||||
|
||||
.type sqr_handler,\@abi-omnipotent
|
||||
@@ -1453,24 +1318,18 @@ sqr_handler:
|
||||
|
||||
mov 0(%r11),%r10d # HandlerData[0]
|
||||
lea (%rsi,%r10),%r10 # end of prologue label
|
||||
cmp %r10,%rbx # context->Rip<.Lsqr_prologue
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # body label
|
||||
cmp %r10,%rbx # context->Rip<.Lsqr_body
|
||||
jb .Lcommon_pop_regs
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
mov 8(%r11),%r10d # HandlerData[2]
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=.Lsqr_epilogue
|
||||
jae .Lcommon_seh_tail
|
||||
|
||||
mov 40(%rax),%rax # pull saved stack pointer
|
||||
|
||||
.Lcommon_pop_regs:
|
||||
mov -8(%rax),%rbx
|
||||
mov -16(%rax),%rbp
|
||||
mov -24(%rax),%r12
|
||||
@@ -1557,15 +1416,13 @@ $code.=<<___;
|
||||
.LSEH_info_bn_sqr8x_mont:
|
||||
.byte 9,0,0,0
|
||||
.rva sqr_handler
|
||||
.rva .Lsqr8x_prologue,.Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
|
||||
.align 8
|
||||
.rva .Lsqr8x_body,.Lsqr8x_epilogue # HandlerData[]
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
.LSEH_info_bn_mulx4x_mont:
|
||||
.byte 9,0,0,0
|
||||
.rva sqr_handler
|
||||
.rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
|
||||
.align 8
|
||||
.rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
|
||||
___
|
||||
}
|
||||
|
||||
|
||||
+77
-303
@@ -73,10 +73,6 @@ $code=<<___;
|
||||
.type bn_mul_mont_gather5,\@function,6
|
||||
.align 64
|
||||
bn_mul_mont_gather5:
|
||||
.cfi_startproc
|
||||
mov ${num}d,${num}d
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
test \$7,${num}d
|
||||
jnz .Lmul_enter
|
||||
___
|
||||
@@ -88,54 +84,24 @@ $code.=<<___;
|
||||
|
||||
.align 16
|
||||
.Lmul_enter:
|
||||
mov ${num}d,${num}d
|
||||
mov %rsp,%rax
|
||||
movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
|
||||
neg $num
|
||||
mov %rsp,%r11
|
||||
lea -280(%rsp,$num,8),%r10 # future alloca(8*(num+2)+256+8)
|
||||
neg $num # restore $num
|
||||
and \$-1024,%r10 # minimize TLB usage
|
||||
|
||||
# An OS-agnostic version of __chkstk.
|
||||
#
|
||||
# Some OSes (Windows) insist on stack being "wired" to
|
||||
# physical memory in strictly sequential manner, i.e. if stack
|
||||
# allocation spans two pages, then reference to farmost one can
|
||||
# be punishable by SEGV. But page walking can do good even on
|
||||
# other OSes, because it guarantees that villain thread hits
|
||||
# the guard page before it can make damage to innocent one...
|
||||
sub %r10,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%r10,%r11),%rsp
|
||||
mov (%rsp),%r11
|
||||
cmp %r10,%rsp
|
||||
ja .Lmul_page_walk
|
||||
jmp .Lmul_page_walk_done
|
||||
|
||||
.Lmul_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r11
|
||||
cmp %r10,%rsp
|
||||
ja .Lmul_page_walk
|
||||
.Lmul_page_walk_done:
|
||||
|
||||
lea .Linc(%rip),%r10
|
||||
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
|
||||
.cfi_cfa_expression %rsp+8,$num,8,mul,plus,deref,+8
|
||||
.Lmul_body:
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
|
||||
lea 2($num),%r11
|
||||
neg %r11
|
||||
lea -264(%rsp,%r11,8),%rsp # tp=alloca(8*(num+2)+256+8)
|
||||
and \$-1024,%rsp # minimize TLB usage
|
||||
|
||||
mov %rax,8(%rsp,$num,8) # tp[num+1]=%rsp
|
||||
.Lmul_body:
|
||||
lea 128($bp),%r12 # reassign $bp (+size optimization)
|
||||
___
|
||||
$bp="%r12";
|
||||
@@ -404,42 +370,32 @@ $code.=<<___;
|
||||
|
||||
sbb \$0,%rax # handle upmost overflow bit
|
||||
xor $i,$i
|
||||
and %rax,$ap
|
||||
not %rax
|
||||
mov $rp,$np
|
||||
and %rax,$np
|
||||
mov $num,$j # j=num
|
||||
or $np,$ap # ap=borrow?tp:rp
|
||||
.align 16
|
||||
.Lcopy: # copy or in-place refresh
|
||||
mov ($ap,$i,8),%rax
|
||||
mov (%rsp,$i,8),$ap
|
||||
mov ($rp,$i,8),$np
|
||||
xor $np,$ap # conditional select:
|
||||
and %rax,$ap # ((ap ^ np) & %rax) ^ np
|
||||
xor $np,$ap # ap = borrow?tp:rp
|
||||
mov $i,(%rsp,$i,8) # zap temporary vector
|
||||
mov %rax,($rp,$i,8) # rp[i]=tp[i]
|
||||
mov $ap,($rp,$i,8) # rp[i]=tp[i]
|
||||
lea 1($i),$i
|
||||
sub \$1,$j
|
||||
jnz .Lcopy
|
||||
|
||||
mov 8(%rsp,$num,8),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
mov \$1,%rax
|
||||
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lmul_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_mul_mont_gather5,.-bn_mul_mont_gather5
|
||||
___
|
||||
{{{
|
||||
@@ -449,10 +405,6 @@ $code.=<<___;
|
||||
.type bn_mul4x_mont_gather5,\@function,6
|
||||
.align 32
|
||||
bn_mul4x_mont_gather5:
|
||||
.cfi_startproc
|
||||
.byte 0x67
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
.Lmul4x_enter:
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
@@ -461,19 +413,14 @@ $code.=<<___ if ($addx);
|
||||
je .Lmulx4x_enter
|
||||
___
|
||||
$code.=<<___;
|
||||
.byte 0x67
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lmul4x_prologue:
|
||||
|
||||
.byte 0x67
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
@@ -490,70 +437,43 @@ $code.=<<___;
|
||||
# calculated from 7th argument, the index.]
|
||||
#
|
||||
lea -320(%rsp,$num,2),%r11
|
||||
mov %rsp,%rbp
|
||||
sub $rp,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lmul4xsp_alt
|
||||
sub %r11,%rbp # align with $rp
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
|
||||
sub %r11,%rsp # align with $rp
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
|
||||
jmp .Lmul4xsp_done
|
||||
|
||||
.align 32
|
||||
.Lmul4xsp_alt:
|
||||
lea 4096-320(,$num,2),%r10
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rbp
|
||||
sub %r11,%rsp
|
||||
.Lmul4xsp_done:
|
||||
and \$-64,%rbp
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lmul4x_page_walk
|
||||
jmp .Lmul4x_page_walk_done
|
||||
|
||||
.Lmul4x_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lmul4x_page_walk
|
||||
.Lmul4x_page_walk_done:
|
||||
|
||||
and \$-64,%rsp
|
||||
neg $num
|
||||
|
||||
mov %rax,40(%rsp)
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
.Lmul4x_body:
|
||||
|
||||
call mul4x_internal
|
||||
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
mov \$1,%rax
|
||||
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lmul4x_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
|
||||
|
||||
.type mul4x_internal,\@abi-omnipotent
|
||||
@@ -1065,7 +985,7 @@ my $bptr="%rdx"; # const void *table,
|
||||
my $nptr="%rcx"; # const BN_ULONG *nptr,
|
||||
my $n0 ="%r8"; # const BN_ULONG *n0);
|
||||
my $num ="%r9"; # int num, has to be divisible by 8
|
||||
# int pwr
|
||||
# int pwr
|
||||
|
||||
my ($i,$j,$tptr)=("%rbp","%rcx",$rptr);
|
||||
my @A0=("%r10","%r11");
|
||||
@@ -1077,9 +997,6 @@ $code.=<<___;
|
||||
.type bn_power5,\@function,6
|
||||
.align 32
|
||||
bn_power5:
|
||||
.cfi_startproc
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
mov OPENSSL_ia32cap_P+8(%rip),%r11d
|
||||
@@ -1088,19 +1005,13 @@ $code.=<<___ if ($addx);
|
||||
je .Lpowerx5_enter
|
||||
___
|
||||
$code.=<<___;
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lpower5_prologue:
|
||||
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
lea ($num,$num,2),%r10d # 3*$num
|
||||
@@ -1115,42 +1026,25 @@ $code.=<<___;
|
||||
# calculated from 7th argument, the index.]
|
||||
#
|
||||
lea -320(%rsp,$num,2),%r11
|
||||
mov %rsp,%rbp
|
||||
sub $rptr,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lpwr_sp_alt
|
||||
sub %r11,%rbp # align with $aptr
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
|
||||
sub %r11,%rsp # align with $aptr
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
|
||||
jmp .Lpwr_sp_done
|
||||
|
||||
.align 32
|
||||
.Lpwr_sp_alt:
|
||||
lea 4096-320(,$num,2),%r10
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*num*8+256)
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*num*8+256)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rbp
|
||||
sub %r11,%rsp
|
||||
.Lpwr_sp_done:
|
||||
and \$-64,%rbp
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lpwr_page_walk
|
||||
jmp .Lpwr_page_walk_done
|
||||
|
||||
.Lpwr_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lpwr_page_walk
|
||||
.Lpwr_page_walk_done:
|
||||
|
||||
mov $num,%r10
|
||||
and \$-64,%rsp
|
||||
mov $num,%r10
|
||||
neg $num
|
||||
|
||||
##############################################################
|
||||
@@ -1164,7 +1058,6 @@ $code.=<<___;
|
||||
#
|
||||
mov $n0, 32(%rsp)
|
||||
mov %rax, 40(%rsp) # save original %rsp
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
.Lpower5_body:
|
||||
movq $rptr,%xmm1 # save $rptr, used in sqr8x
|
||||
movq $nptr,%xmm2 # save $nptr
|
||||
@@ -1191,25 +1084,16 @@ $code.=<<___;
|
||||
call mul4x_internal
|
||||
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lpower5_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_power5,.-bn_power5
|
||||
|
||||
.globl bn_sqr8x_internal
|
||||
@@ -1968,7 +1852,6 @@ __bn_sqr8x_reduction:
|
||||
|
||||
.align 32
|
||||
.L8x_tail_done:
|
||||
xor %rax,%rax
|
||||
add (%rdx),%r8 # can this overflow?
|
||||
adc \$0,%r9
|
||||
adc \$0,%r10
|
||||
@@ -1976,8 +1859,10 @@ __bn_sqr8x_reduction:
|
||||
adc \$0,%r12
|
||||
adc \$0,%r13
|
||||
adc \$0,%r14
|
||||
adc \$0,%r15
|
||||
adc \$0,%rax
|
||||
adc \$0,%r15 # can't overflow, because we
|
||||
# started with "overhung" part
|
||||
# of multiplication
|
||||
xor %rax,%rax
|
||||
|
||||
neg $carry
|
||||
.L8x_no_tail:
|
||||
@@ -2069,7 +1954,7 @@ __bn_post4x_internal:
|
||||
jnz .Lsqr4x_sub
|
||||
|
||||
mov $num,%r10 # prepare for back-to-back call
|
||||
neg $num # restore $num
|
||||
neg $num # restore $num
|
||||
ret
|
||||
.size __bn_post4x_internal,.-__bn_post4x_internal
|
||||
___
|
||||
@@ -2089,23 +1974,14 @@ bn_from_montgomery:
|
||||
.type bn_from_mont8x,\@function,6
|
||||
.align 32
|
||||
bn_from_mont8x:
|
||||
.cfi_startproc
|
||||
.byte 0x67
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lfrom_prologue:
|
||||
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
lea ($num,$num,2),%r10 # 3*$num in bytes
|
||||
@@ -2120,42 +1996,25 @@ bn_from_mont8x:
|
||||
# last operation, we use the opportunity to cleanse it.
|
||||
#
|
||||
lea -320(%rsp,$num,2),%r11
|
||||
mov %rsp,%rbp
|
||||
sub $rptr,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lfrom_sp_alt
|
||||
sub %r11,%rbp # align with $aptr
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
|
||||
sub %r11,%rsp # align with $aptr
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
|
||||
jmp .Lfrom_sp_done
|
||||
|
||||
.align 32
|
||||
.Lfrom_sp_alt:
|
||||
lea 4096-320(,$num,2),%r10
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rbp
|
||||
sub %r11,%rsp
|
||||
.Lfrom_sp_done:
|
||||
and \$-64,%rbp
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lfrom_page_walk
|
||||
jmp .Lfrom_page_walk_done
|
||||
|
||||
.Lfrom_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lfrom_page_walk
|
||||
.Lfrom_page_walk_done:
|
||||
|
||||
mov $num,%r10
|
||||
and \$-64,%rsp
|
||||
mov $num,%r10
|
||||
neg $num
|
||||
|
||||
##############################################################
|
||||
@@ -2169,7 +2028,6 @@ bn_from_mont8x:
|
||||
#
|
||||
mov $n0, 32(%rsp)
|
||||
mov %rax, 40(%rsp) # save original %rsp
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
.Lfrom_body:
|
||||
mov $num,%r11
|
||||
lea 48(%rsp),%rax
|
||||
@@ -2213,6 +2071,7 @@ $code.=<<___ if ($addx);
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
lea 48(%rsp),%rax
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
jmp .Lfrom_mont_zero
|
||||
|
||||
.align 32
|
||||
@@ -2224,12 +2083,11 @@ $code.=<<___;
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
lea 48(%rsp),%rax
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
jmp .Lfrom_mont_zero
|
||||
|
||||
.align 32
|
||||
.Lfrom_mont_zero:
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
movdqa %xmm0,16*0(%rax)
|
||||
movdqa %xmm0,16*1(%rax)
|
||||
movdqa %xmm0,16*2(%rax)
|
||||
@@ -2240,22 +2098,14 @@ $code.=<<___;
|
||||
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lfrom_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_from_mont8x,.-bn_from_mont8x
|
||||
___
|
||||
}
|
||||
@@ -2268,23 +2118,14 @@ $code.=<<___;
|
||||
.type bn_mulx4x_mont_gather5,\@function,6
|
||||
.align 32
|
||||
bn_mulx4x_mont_gather5:
|
||||
.cfi_startproc
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
.Lmulx4x_enter:
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lmulx4x_prologue:
|
||||
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
lea ($num,$num,2),%r10 # 3*$num in bytes
|
||||
@@ -2301,40 +2142,23 @@ bn_mulx4x_mont_gather5:
|
||||
# calculated from 7th argument, the index.]
|
||||
#
|
||||
lea -320(%rsp,$num,2),%r11
|
||||
mov %rsp,%rbp
|
||||
sub $rp,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lmulx4xsp_alt
|
||||
sub %r11,%rbp # align with $aptr
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
|
||||
sub %r11,%rsp # align with $aptr
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
|
||||
jmp .Lmulx4xsp_done
|
||||
|
||||
.Lmulx4xsp_alt:
|
||||
lea 4096-320(,$num,2),%r10
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rbp
|
||||
.Lmulx4xsp_done:
|
||||
and \$-64,%rbp # ensure alignment
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lmulx4x_page_walk
|
||||
jmp .Lmulx4x_page_walk_done
|
||||
|
||||
.Lmulx4x_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lmulx4x_page_walk
|
||||
.Lmulx4x_page_walk_done:
|
||||
|
||||
sub %r11,%rsp
|
||||
.Lmulx4xsp_done:
|
||||
and \$-64,%rsp # ensure alignment
|
||||
##############################################################
|
||||
# Stack layout
|
||||
# +0 -num
|
||||
@@ -2349,31 +2173,21 @@ bn_mulx4x_mont_gather5:
|
||||
#
|
||||
mov $n0, 32(%rsp) # save *n0
|
||||
mov %rax,40(%rsp) # save original %rsp
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
.Lmulx4x_body:
|
||||
call mulx4x_internal
|
||||
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
mov \$1,%rax
|
||||
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lmulx4x_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_mulx4x_mont_gather5,.-bn_mulx4x_mont_gather5
|
||||
|
||||
.type mulx4x_internal,\@abi-omnipotent
|
||||
@@ -2751,23 +2565,14 @@ $code.=<<___;
|
||||
.type bn_powerx5,\@function,6
|
||||
.align 32
|
||||
bn_powerx5:
|
||||
.cfi_startproc
|
||||
mov %rsp,%rax
|
||||
.cfi_def_cfa_register %rax
|
||||
.Lpowerx5_enter:
|
||||
mov %rsp,%rax
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
.Lpowerx5_prologue:
|
||||
|
||||
shl \$3,${num}d # convert $num to bytes
|
||||
lea ($num,$num,2),%r10 # 3*$num in bytes
|
||||
@@ -2782,42 +2587,25 @@ bn_powerx5:
|
||||
# calculated from 7th argument, the index.]
|
||||
#
|
||||
lea -320(%rsp,$num,2),%r11
|
||||
mov %rsp,%rbp
|
||||
sub $rptr,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lpwrx_sp_alt
|
||||
sub %r11,%rbp # align with $aptr
|
||||
lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256)
|
||||
sub %r11,%rsp # align with $aptr
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
|
||||
jmp .Lpwrx_sp_done
|
||||
|
||||
.align 32
|
||||
.Lpwrx_sp_alt:
|
||||
lea 4096-320(,$num,2),%r10
|
||||
lea -320(%rbp,$num,2),%rbp # alloca(frame+2*$num*8+256)
|
||||
lea -320(%rsp,$num,2),%rsp # alloca(frame+2*$num*8+256)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rbp
|
||||
sub %r11,%rsp
|
||||
.Lpwrx_sp_done:
|
||||
and \$-64,%rbp
|
||||
mov %rsp,%r11
|
||||
sub %rbp,%r11
|
||||
and \$-4096,%r11
|
||||
lea (%rbp,%r11),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lpwrx_page_walk
|
||||
jmp .Lpwrx_page_walk_done
|
||||
|
||||
.Lpwrx_page_walk:
|
||||
lea -4096(%rsp),%rsp
|
||||
mov (%rsp),%r10
|
||||
cmp %rbp,%rsp
|
||||
ja .Lpwrx_page_walk
|
||||
.Lpwrx_page_walk_done:
|
||||
|
||||
mov $num,%r10
|
||||
and \$-64,%rsp
|
||||
mov $num,%r10
|
||||
neg $num
|
||||
|
||||
##############################################################
|
||||
@@ -2838,7 +2626,6 @@ bn_powerx5:
|
||||
movq $bptr,%xmm4
|
||||
mov $n0, 32(%rsp)
|
||||
mov %rax, 40(%rsp) # save original %rsp
|
||||
.cfi_cfa_expression %rsp+40,deref,+8
|
||||
.Lpowerx5_body:
|
||||
|
||||
call __bn_sqrx8x_internal
|
||||
@@ -2861,26 +2648,17 @@ bn_powerx5:
|
||||
call mulx4x_internal
|
||||
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
.cfi_def_cfa %rsi,8
|
||||
mov \$1,%rax
|
||||
|
||||
mov -48(%rsi),%r15
|
||||
.cfi_restore %r15
|
||||
mov -40(%rsi),%r14
|
||||
.cfi_restore %r14
|
||||
mov -32(%rsi),%r13
|
||||
.cfi_restore %r13
|
||||
mov -24(%rsi),%r12
|
||||
.cfi_restore %r12
|
||||
mov -16(%rsi),%rbp
|
||||
.cfi_restore %rbp
|
||||
mov -8(%rsi),%rbx
|
||||
.cfi_restore %rbx
|
||||
lea (%rsi),%rsp
|
||||
.cfi_def_cfa_register %rsp
|
||||
.Lpowerx5_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size bn_powerx5,.-bn_powerx5
|
||||
|
||||
.globl bn_sqrx8x_internal
|
||||
@@ -3470,7 +3248,6 @@ __bn_sqrx8x_reduction:
|
||||
|
||||
.align 32
|
||||
.Lsqrx8x_tail_done:
|
||||
xor %rax,%rax
|
||||
add 24+8(%rsp),%r8 # can this overflow?
|
||||
adc \$0,%r9
|
||||
adc \$0,%r10
|
||||
@@ -3478,8 +3255,10 @@ __bn_sqrx8x_reduction:
|
||||
adc \$0,%r12
|
||||
adc \$0,%r13
|
||||
adc \$0,%r14
|
||||
adc \$0,%r15
|
||||
adc \$0,%rax
|
||||
adc \$0,%r15 # can't overflow, because we
|
||||
# started with "overhung" part
|
||||
# of multiplication
|
||||
mov $carry,%rax # xor %rax,%rax
|
||||
|
||||
sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
|
||||
.Lsqrx8x_no_tail: # %cf is 0 if jumped here
|
||||
@@ -3494,7 +3273,7 @@ __bn_sqrx8x_reduction:
|
||||
adc 8*5($tptr),%r13
|
||||
adc 8*6($tptr),%r14
|
||||
adc 8*7($tptr),%r15
|
||||
adc \$0,%rax # top-most carry
|
||||
adc %rax,%rax # top-most carry
|
||||
|
||||
mov 32+8(%rsp),%rbx # n0
|
||||
mov 8*8($tptr,%rcx),%rdx # modulo-scheduled "%r8"
|
||||
@@ -3736,14 +3515,9 @@ mul_handler:
|
||||
cmp %r10,%rbx # context->Rip<end of prologue label
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # beginning of body label
|
||||
cmp %r10,%rbx # context->Rip<body label
|
||||
jb .Lcommon_pop_regs
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
mov 8(%r11),%r10d # HandlerData[2]
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=epilogue label
|
||||
jae .Lcommon_seh_tail
|
||||
@@ -3755,11 +3529,11 @@ mul_handler:
|
||||
mov 192($context),%r10 # pull $num
|
||||
mov 8(%rax,%r10,8),%rax # pull saved stack pointer
|
||||
|
||||
jmp .Lcommon_pop_regs
|
||||
jmp .Lbody_proceed
|
||||
|
||||
.Lbody_40:
|
||||
mov 40(%rax),%rax # pull saved stack pointer
|
||||
.Lcommon_pop_regs:
|
||||
.Lbody_proceed:
|
||||
mov -8(%rax),%rbx
|
||||
mov -16(%rax),%rbp
|
||||
mov -24(%rax),%r12
|
||||
@@ -3850,34 +3624,34 @@ $code.=<<___;
|
||||
.LSEH_info_bn_mul_mont_gather5:
|
||||
.byte 9,0,0,0
|
||||
.rva mul_handler
|
||||
.rva .Lmul_body,.Lmul_body,.Lmul_epilogue # HandlerData[]
|
||||
.rva .Lmul_body,.Lmul_epilogue # HandlerData[]
|
||||
.align 8
|
||||
.LSEH_info_bn_mul4x_mont_gather5:
|
||||
.byte 9,0,0,0
|
||||
.rva mul_handler
|
||||
.rva .Lmul4x_prologue,.Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
|
||||
.rva .Lmul4x_body,.Lmul4x_epilogue # HandlerData[]
|
||||
.align 8
|
||||
.LSEH_info_bn_power5:
|
||||
.byte 9,0,0,0
|
||||
.rva mul_handler
|
||||
.rva .Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue # HandlerData[]
|
||||
.rva .Lpower5_body,.Lpower5_epilogue # HandlerData[]
|
||||
.align 8
|
||||
.LSEH_info_bn_from_mont8x:
|
||||
.byte 9,0,0,0
|
||||
.rva mul_handler
|
||||
.rva .Lfrom_prologue,.Lfrom_body,.Lfrom_epilogue # HandlerData[]
|
||||
.rva .Lfrom_body,.Lfrom_epilogue # HandlerData[]
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
.align 8
|
||||
.LSEH_info_bn_mulx4x_mont_gather5:
|
||||
.byte 9,0,0,0
|
||||
.rva mul_handler
|
||||
.rva .Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
|
||||
.rva .Lmulx4x_body,.Lmulx4x_epilogue # HandlerData[]
|
||||
.align 8
|
||||
.LSEH_info_bn_powerx5:
|
||||
.byte 9,0,0,0
|
||||
.rva mul_handler
|
||||
.rva .Lpowerx5_prologue,.Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
|
||||
.rva .Lpowerx5_body,.Lpowerx5_epilogue # HandlerData[]
|
||||
___
|
||||
$code.=<<___;
|
||||
.align 8
|
||||
|
||||
+20
-6
@@ -73,14 +73,14 @@ BIGNUM *BN_new(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(bn, 0, sizeof(BIGNUM));
|
||||
memset(bn, 0, sizeof(BIGNUM));
|
||||
bn->flags = BN_FLG_MALLOCED;
|
||||
|
||||
return bn;
|
||||
}
|
||||
|
||||
void BN_init(BIGNUM *bn) {
|
||||
OPENSSL_memset(bn, 0, sizeof(BIGNUM));
|
||||
memset(bn, 0, sizeof(BIGNUM));
|
||||
}
|
||||
|
||||
void BN_free(BIGNUM *bn) {
|
||||
@@ -149,7 +149,7 @@ BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top);
|
||||
memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top);
|
||||
|
||||
dest->top = src->top;
|
||||
dest->neg = src->neg;
|
||||
@@ -158,7 +158,7 @@ BIGNUM *BN_copy(BIGNUM *dest, const BIGNUM *src) {
|
||||
|
||||
void BN_clear(BIGNUM *bn) {
|
||||
if (bn->d != NULL) {
|
||||
OPENSSL_memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
|
||||
memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
|
||||
}
|
||||
|
||||
bn->top = 0;
|
||||
@@ -172,6 +172,12 @@ const BIGNUM *BN_value_one(void) {
|
||||
return &kOne;
|
||||
}
|
||||
|
||||
void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
|
||||
memcpy(out, in, sizeof(BIGNUM));
|
||||
out->flags &= ~BN_FLG_MALLOCED;
|
||||
out->flags |= BN_FLG_STATIC_DATA | flags;
|
||||
}
|
||||
|
||||
/* BN_num_bits_word returns the minimum number of bits needed to represent the
|
||||
* value in |l|. */
|
||||
unsigned BN_num_bits_word(BN_ULONG l) {
|
||||
@@ -286,7 +292,7 @@ int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
|
||||
if (bn_wexpand(bn, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memmove(bn->d, words, num * sizeof(BN_ULONG));
|
||||
memmove(bn->d, words, num * sizeof(BN_ULONG));
|
||||
/* |bn_wexpand| verified that |num| isn't too large. */
|
||||
bn->top = (int)num;
|
||||
bn_correct_top(bn);
|
||||
@@ -329,7 +335,7 @@ BIGNUM *bn_wexpand(BIGNUM *bn, size_t words) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
|
||||
memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
|
||||
|
||||
OPENSSL_free(bn->d);
|
||||
bn->d = a;
|
||||
@@ -363,3 +369,11 @@ void bn_correct_top(BIGNUM *bn) {
|
||||
bn->neg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int BN_get_flags(const BIGNUM *bn, int flags) {
|
||||
return bn->flags & flags;
|
||||
}
|
||||
|
||||
void BN_set_flags(BIGNUM *bn, int flags) {
|
||||
bn->flags |= flags;
|
||||
}
|
||||
|
||||
+74
-362
@@ -340,7 +340,7 @@ static bool TestSquare(FileTest *t, BN_CTX *ctx) {
|
||||
BN_zero(zero.get());
|
||||
|
||||
bssl::UniquePtr<BIGNUM> ret(BN_new()), remainder(BN_new());
|
||||
if (!ret || !remainder ||
|
||||
if (!ret ||
|
||||
!BN_sqr(ret.get(), a.get(), ctx) ||
|
||||
!ExpectBIGNUMsEqual(t, "A^2", square.get(), ret.get()) ||
|
||||
!BN_mul(ret.get(), a.get(), a.get(), ctx) ||
|
||||
@@ -515,54 +515,6 @@ static bool TestModMul(FileTest *t, BN_CTX *ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestModSquare(FileTest *t, BN_CTX *ctx) {
|
||||
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
|
||||
bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
|
||||
bssl::UniquePtr<BIGNUM> mod_square = GetBIGNUM(t, "ModSquare");
|
||||
if (!a || !m || !mod_square) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<BIGNUM> a_copy(BN_new());
|
||||
bssl::UniquePtr<BIGNUM> ret(BN_new());
|
||||
if (!ret || !a_copy ||
|
||||
!BN_mod_mul(ret.get(), a.get(), a.get(), m.get(), ctx) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * A (mod M)", mod_square.get(), ret.get()) ||
|
||||
// Repeat the operation with |a_copy|.
|
||||
!BN_copy(a_copy.get(), a.get()) ||
|
||||
!BN_mod_mul(ret.get(), a.get(), a_copy.get(), m.get(), ctx) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * A_copy (mod M)", mod_square.get(),
|
||||
ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BN_is_odd(m.get())) {
|
||||
// Reduce |a| and test the Montgomery version.
|
||||
bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
|
||||
bssl::UniquePtr<BIGNUM> a_tmp(BN_new());
|
||||
if (!mont || !a_tmp ||
|
||||
!BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
|
||||
!BN_nnmod(a_tmp.get(), a.get(), m.get(), ctx) ||
|
||||
!BN_to_montgomery(a_tmp.get(), a_tmp.get(), mont.get(), ctx) ||
|
||||
!BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_tmp.get(), mont.get(),
|
||||
ctx) ||
|
||||
!BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * A (mod M) (Montgomery)",
|
||||
mod_square.get(), ret.get()) ||
|
||||
// Repeat the operation with |a_copy|.
|
||||
!BN_copy(a_copy.get(), a_tmp.get()) ||
|
||||
!BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_copy.get(), mont.get(),
|
||||
ctx) ||
|
||||
!BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * A_copy (mod M) (Montgomery)",
|
||||
mod_square.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestModExp(FileTest *t, BN_CTX *ctx) {
|
||||
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
|
||||
bssl::UniquePtr<BIGNUM> e = GetBIGNUM(t, "E");
|
||||
@@ -616,25 +568,21 @@ static bool TestModSqrt(FileTest *t, BN_CTX *ctx) {
|
||||
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
|
||||
bssl::UniquePtr<BIGNUM> p = GetBIGNUM(t, "P");
|
||||
bssl::UniquePtr<BIGNUM> mod_sqrt = GetBIGNUM(t, "ModSqrt");
|
||||
bssl::UniquePtr<BIGNUM> mod_sqrt2(BN_new());
|
||||
if (!a || !p || !mod_sqrt || !mod_sqrt2 ||
|
||||
// There are two possible answers.
|
||||
!BN_sub(mod_sqrt2.get(), p.get(), mod_sqrt.get())) {
|
||||
if (!a || !p || !mod_sqrt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// -0 is 0, not P.
|
||||
if (BN_is_zero(mod_sqrt.get())) {
|
||||
BN_zero(mod_sqrt2.get());
|
||||
}
|
||||
|
||||
bssl::UniquePtr<BIGNUM> ret(BN_new());
|
||||
bssl::UniquePtr<BIGNUM> ret2(BN_new());
|
||||
if (!ret ||
|
||||
!BN_mod_sqrt(ret.get(), a.get(), p.get(), ctx)) {
|
||||
!ret2 ||
|
||||
!BN_mod_sqrt(ret.get(), a.get(), p.get(), ctx) ||
|
||||
// There are two possible answers.
|
||||
!BN_sub(ret2.get(), p.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BN_cmp(ret.get(), mod_sqrt2.get()) != 0 &&
|
||||
if (BN_cmp(ret2.get(), mod_sqrt.get()) != 0 &&
|
||||
!ExpectBIGNUMsEqual(t, "sqrt(A) (mod P)", mod_sqrt.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
@@ -642,29 +590,6 @@ static bool TestModSqrt(FileTest *t, BN_CTX *ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestNotModSquare(FileTest *t, BN_CTX *ctx) {
|
||||
bssl::UniquePtr<BIGNUM> not_mod_square = GetBIGNUM(t, "NotModSquare");
|
||||
bssl::UniquePtr<BIGNUM> p = GetBIGNUM(t, "P");
|
||||
bssl::UniquePtr<BIGNUM> ret(BN_new());
|
||||
if (!not_mod_square || !p || !ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BN_mod_sqrt(ret.get(), not_mod_square.get(), p.get(), ctx)) {
|
||||
t->PrintLine("BN_mod_sqrt unexpectedly succeeded.");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t err = ERR_peek_error();
|
||||
if (ERR_GET_LIB(err) == ERR_LIB_BN &&
|
||||
ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
|
||||
ERR_clear_error();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool TestModInv(FileTest *t, BN_CTX *ctx) {
|
||||
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
|
||||
bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
|
||||
@@ -680,6 +605,15 @@ static bool TestModInv(FileTest *t, BN_CTX *ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BN_set_flags(a.get(), BN_FLG_CONSTTIME);
|
||||
|
||||
if (!ret ||
|
||||
!BN_mod_inverse(ret.get(), a.get(), m.get(), ctx) ||
|
||||
!ExpectBIGNUMsEqual(t, "inv(A) (mod M) (constant-time)", mod_inv.get(),
|
||||
ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -697,11 +631,9 @@ static const Test kTests[] = {
|
||||
{"Product", TestProduct},
|
||||
{"Quotient", TestQuotient},
|
||||
{"ModMul", TestModMul},
|
||||
{"ModSquare", TestModSquare},
|
||||
{"ModExp", TestModExp},
|
||||
{"Exp", TestExp},
|
||||
{"ModSqrt", TestModSqrt},
|
||||
{"NotModSquare", TestNotModSquare},
|
||||
{"ModInv", TestModInv},
|
||||
};
|
||||
|
||||
@@ -720,7 +652,7 @@ static bool RunTest(FileTest *t, void *arg) {
|
||||
static bool TestBN2BinPadded(BN_CTX *ctx) {
|
||||
uint8_t zeros[256], out[256], reference[128];
|
||||
|
||||
OPENSSL_memset(zeros, 0, sizeof(zeros));
|
||||
memset(zeros, 0, sizeof(zeros));
|
||||
|
||||
// Test edge case at 0.
|
||||
bssl::UniquePtr<BIGNUM> n(BN_new());
|
||||
@@ -729,13 +661,13 @@ static bool TestBN2BinPadded(BN_CTX *ctx) {
|
||||
"BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
|
||||
return false;
|
||||
}
|
||||
OPENSSL_memset(out, -1, sizeof(out));
|
||||
memset(out, -1, sizeof(out));
|
||||
if (!BN_bn2bin_padded(out, sizeof(out), n.get())) {
|
||||
fprintf(stderr,
|
||||
"BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
|
||||
return false;
|
||||
}
|
||||
if (OPENSSL_memcmp(zeros, out, sizeof(out))) {
|
||||
if (memcmp(zeros, out, sizeof(out))) {
|
||||
fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -764,21 +696,20 @@ static bool TestBN2BinPadded(BN_CTX *ctx) {
|
||||
}
|
||||
// Exactly right size should encode.
|
||||
if (!BN_bn2bin_padded(out, bytes, n.get()) ||
|
||||
OPENSSL_memcmp(out, reference, bytes) != 0) {
|
||||
memcmp(out, reference, bytes) != 0) {
|
||||
fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
// Pad up one byte extra.
|
||||
if (!BN_bn2bin_padded(out, bytes + 1, n.get()) ||
|
||||
OPENSSL_memcmp(out + 1, reference, bytes) ||
|
||||
OPENSSL_memcmp(out, zeros, 1)) {
|
||||
memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
|
||||
fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
// Pad up to 256.
|
||||
if (!BN_bn2bin_padded(out, sizeof(out), n.get()) ||
|
||||
OPENSSL_memcmp(out + sizeof(out) - bytes, reference, bytes) ||
|
||||
OPENSSL_memcmp(out, zeros, sizeof(out) - bytes)) {
|
||||
memcmp(out + sizeof(out) - bytes, reference, bytes) ||
|
||||
memcmp(out, zeros, sizeof(out) - bytes)) {
|
||||
fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -787,82 +718,6 @@ static bool TestBN2BinPadded(BN_CTX *ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestLittleEndian() {
|
||||
bssl::UniquePtr<BIGNUM> x(BN_new());
|
||||
bssl::UniquePtr<BIGNUM> y(BN_new());
|
||||
if (!x || !y) {
|
||||
fprintf(stderr, "BN_new failed to malloc.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test edge case at 0. Fill |out| with garbage to ensure |BN_bn2le_padded|
|
||||
// wrote the result.
|
||||
uint8_t out[256], zeros[256];
|
||||
OPENSSL_memset(out, -1, sizeof(out));
|
||||
OPENSSL_memset(zeros, 0, sizeof(zeros));
|
||||
if (!BN_bn2le_padded(out, sizeof(out), x.get()) ||
|
||||
OPENSSL_memcmp(zeros, out, sizeof(out))) {
|
||||
fprintf(stderr, "BN_bn2le_padded failed to encode 0.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BN_le2bn(out, sizeof(out), y.get()) ||
|
||||
BN_cmp(x.get(), y.get()) != 0) {
|
||||
fprintf(stderr, "BN_le2bn failed to decode 0 correctly.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test random numbers at various byte lengths.
|
||||
for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
|
||||
if (!BN_rand(x.get(), bytes * 8, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill |out| with garbage to ensure |BN_bn2le_padded| wrote the result.
|
||||
OPENSSL_memset(out, -1, sizeof(out));
|
||||
if (!BN_bn2le_padded(out, sizeof(out), x.get())) {
|
||||
fprintf(stderr, "BN_bn2le_padded failed to encode random value.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute the expected value by reversing the big-endian output.
|
||||
uint8_t expected[sizeof(out)];
|
||||
if (!BN_bn2bin_padded(expected, sizeof(expected), x.get())) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < sizeof(expected) / 2; i++) {
|
||||
uint8_t tmp = expected[i];
|
||||
expected[i] = expected[sizeof(expected) - 1 - i];
|
||||
expected[sizeof(expected) - 1 - i] = tmp;
|
||||
}
|
||||
|
||||
if (OPENSSL_memcmp(expected, out, sizeof(out))) {
|
||||
fprintf(stderr, "BN_bn2le_padded failed to encode value correctly.\n");
|
||||
hexdump(stderr, "Expected: ", expected, sizeof(expected));
|
||||
hexdump(stderr, "Got: ", out, sizeof(out));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the decoding produces the same BIGNUM.
|
||||
if (!BN_le2bn(out, bytes, y.get()) ||
|
||||
BN_cmp(x.get(), y.get()) != 0) {
|
||||
bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get())),
|
||||
y_hex(BN_bn2hex(y.get()));
|
||||
if (!x_hex || !y_hex) {
|
||||
return false;
|
||||
}
|
||||
fprintf(stderr, "BN_le2bn failed to decode value correctly.\n");
|
||||
fprintf(stderr, "Expected: %s\n", x_hex.get());
|
||||
hexdump(stderr, "Encoding: ", out, bytes);
|
||||
fprintf(stderr, "Got: %s\n", y_hex.get());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int DecimalToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
|
||||
BIGNUM *raw = NULL;
|
||||
int ret = BN_dec2bn(&raw, in);
|
||||
@@ -1021,10 +876,6 @@ static bool TestMPI() {
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMPITests); i++) {
|
||||
const MPITest &test = kMPITests[i];
|
||||
bssl::UniquePtr<BIGNUM> bn(ASCIIToBIGNUM(test.base10));
|
||||
if (!bn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t mpi_len = BN_bn2mpi(bn.get(), NULL);
|
||||
if (mpi_len > sizeof(scratch)) {
|
||||
fprintf(stderr, "MPI test #%u: MPI size is too large to test.\n",
|
||||
@@ -1039,7 +890,7 @@ static bool TestMPI() {
|
||||
}
|
||||
|
||||
if (mpi_len != test.mpi_len ||
|
||||
OPENSSL_memcmp(test.mpi, scratch, mpi_len) != 0) {
|
||||
memcmp(test.mpi, scratch, mpi_len) != 0) {
|
||||
fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i);
|
||||
hexdump(stderr, "Expected: ", test.mpi, test.mpi_len);
|
||||
hexdump(stderr, "Got: ", scratch, mpi_len);
|
||||
@@ -1169,18 +1020,19 @@ static bool TestASN1() {
|
||||
}
|
||||
|
||||
// Test the value serializes correctly.
|
||||
bssl::ScopedCBB cbb;
|
||||
CBB cbb;
|
||||
uint8_t *der;
|
||||
size_t der_len;
|
||||
if (!CBB_init(cbb.get(), 0) ||
|
||||
!BN_marshal_asn1(cbb.get(), bn.get()) ||
|
||||
!CBB_finish(cbb.get(), &der, &der_len)) {
|
||||
CBB_zero(&cbb);
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
!BN_marshal_asn1(&cbb, bn.get()) ||
|
||||
!CBB_finish(&cbb, &der, &der_len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<uint8_t> delete_der(der);
|
||||
if (der_len != test.der_len ||
|
||||
OPENSSL_memcmp(der, reinterpret_cast<const uint8_t *>(test.der),
|
||||
der_len) != 0) {
|
||||
memcmp(der, reinterpret_cast<const uint8_t*>(test.der), der_len) != 0) {
|
||||
fprintf(stderr, "Bad serialization.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1258,13 +1110,16 @@ static bool TestASN1() {
|
||||
if (!bn) {
|
||||
return false;
|
||||
}
|
||||
bssl::ScopedCBB cbb;
|
||||
if (!CBB_init(cbb.get(), 0) ||
|
||||
BN_marshal_asn1(cbb.get(), bn.get())) {
|
||||
CBB cbb;
|
||||
CBB_zero(&cbb);
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
BN_marshal_asn1(&cbb, bn.get())) {
|
||||
fprintf(stderr, "Serialized negative number.\n");
|
||||
CBB_cleanup(&cbb);
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
CBB_cleanup(&cbb);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1291,35 +1146,42 @@ static bool TestNegativeZero(BN_CTX *ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<BIGNUM> numerator(BN_new()), denominator(BN_new());
|
||||
if (!numerator || !denominator) {
|
||||
return false;
|
||||
}
|
||||
for (int consttime = 0; consttime < 2; consttime++) {
|
||||
bssl::UniquePtr<BIGNUM> numerator(BN_new()), denominator(BN_new());
|
||||
if (!numerator || !denominator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test that BN_div never gives negative zero in the quotient.
|
||||
if (!BN_set_word(numerator.get(), 1) ||
|
||||
!BN_set_word(denominator.get(), 2)) {
|
||||
return false;
|
||||
}
|
||||
BN_set_negative(numerator.get(), 1);
|
||||
if (!BN_div(a.get(), b.get(), numerator.get(), denominator.get(), ctx)) {
|
||||
return false;
|
||||
}
|
||||
if (!BN_is_zero(a.get()) || BN_is_negative(a.get())) {
|
||||
fprintf(stderr, "Incorrect quotient.\n");
|
||||
return false;
|
||||
}
|
||||
if (consttime) {
|
||||
BN_set_flags(numerator.get(), BN_FLG_CONSTTIME);
|
||||
BN_set_flags(denominator.get(), BN_FLG_CONSTTIME);
|
||||
}
|
||||
|
||||
// Test that BN_div never gives negative zero in the remainder.
|
||||
if (!BN_set_word(denominator.get(), 1)) {
|
||||
return false;
|
||||
}
|
||||
if (!BN_div(a.get(), b.get(), numerator.get(), denominator.get(), ctx)) {
|
||||
return false;
|
||||
}
|
||||
if (!BN_is_zero(b.get()) || BN_is_negative(b.get())) {
|
||||
fprintf(stderr, "Incorrect remainder.\n");
|
||||
return false;
|
||||
// Test that BN_div never gives negative zero in the quotient.
|
||||
if (!BN_set_word(numerator.get(), 1) ||
|
||||
!BN_set_word(denominator.get(), 2)) {
|
||||
return false;
|
||||
}
|
||||
BN_set_negative(numerator.get(), 1);
|
||||
if (!BN_div(a.get(), b.get(), numerator.get(), denominator.get(), ctx)) {
|
||||
return false;
|
||||
}
|
||||
if (!BN_is_zero(a.get()) || BN_is_negative(a.get())) {
|
||||
fprintf(stderr, "Incorrect quotient (consttime = %d).\n", consttime);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test that BN_div never gives negative zero in the remainder.
|
||||
if (!BN_set_word(denominator.get(), 1)) {
|
||||
return false;
|
||||
}
|
||||
if (!BN_div(a.get(), b.get(), numerator.get(), denominator.get(), ctx)) {
|
||||
return false;
|
||||
}
|
||||
if (!BN_is_zero(b.get()) || BN_is_negative(b.get())) {
|
||||
fprintf(stderr, "Incorrect remainder (consttime = %d).\n", consttime);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test that BN_set_negative will not produce a negative zero.
|
||||
@@ -1342,37 +1204,6 @@ static bool TestNegativeZero(BN_CTX *ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test that |BN_rshift| and |BN_rshift1| will not produce a negative zero.
|
||||
if (!BN_set_word(a.get(), 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BN_set_negative(a.get(), 1);
|
||||
if (!BN_rshift(b.get(), a.get(), 1) ||
|
||||
!BN_rshift1(c.get(), a.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BN_is_zero(b.get()) || BN_is_negative(b.get())) {
|
||||
fprintf(stderr, "BN_rshift(-1, 1) produced the wrong result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
|
||||
fprintf(stderr, "BN_rshift1(-1) produced the wrong result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test that |BN_div_word| will not produce a negative zero.
|
||||
if (BN_div_word(a.get(), 2) == (BN_ULONG)-1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BN_is_zero(a.get()) || BN_is_negative(a.get())) {
|
||||
fprintf(stderr, "BN_div_word(-1, 2) produced the wrong result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1611,7 +1442,7 @@ static bool TestBN2Dec() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestBNSetGetU64() {
|
||||
static bool TestBNSetU64() {
|
||||
static const struct {
|
||||
const char *hex;
|
||||
uint64_t value;
|
||||
@@ -1633,123 +1464,6 @@ static bool TestBNSetGetU64() {
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t tmp;
|
||||
if (!BN_get_u64(bn.get(), &tmp) || tmp != test.value) {
|
||||
fprintf(stderr, "BN_get_u64 test failed for 0x%s.\n", test.hex);
|
||||
return false;
|
||||
}
|
||||
|
||||
BN_set_negative(bn.get(), 1);
|
||||
if (!BN_get_u64(bn.get(), &tmp) || tmp != test.value) {
|
||||
fprintf(stderr, "BN_get_u64 test failed for -0x%s.\n", test.hex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test that BN_get_u64 fails on large numbers.
|
||||
bssl::UniquePtr<BIGNUM> bn(BN_new());
|
||||
if (!BN_lshift(bn.get(), BN_value_one(), 64)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t tmp;
|
||||
if (BN_get_u64(bn.get(), &tmp)) {
|
||||
fprintf(stderr, "BN_get_u64 of 2^64 unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
BN_set_negative(bn.get(), 1);
|
||||
if (BN_get_u64(bn.get(), &tmp)) {
|
||||
fprintf(stderr, "BN_get_u64 of -2^64 unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestBNPow2(BN_CTX *ctx) {
|
||||
bssl::UniquePtr<BIGNUM>
|
||||
power_of_two(BN_new()),
|
||||
random(BN_new()),
|
||||
expected(BN_new()),
|
||||
actual(BN_new());
|
||||
|
||||
if (!power_of_two.get() ||
|
||||
!random.get() ||
|
||||
!expected.get() ||
|
||||
!actual.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Choose an exponent.
|
||||
for (size_t e = 3; e < 512; e += 11) {
|
||||
// Choose a bit length for our randoms.
|
||||
for (int len = 3; len < 512; len += 23) {
|
||||
// Set power_of_two = 2^e.
|
||||
if (!BN_lshift(power_of_two.get(), BN_value_one(), (int) e)) {
|
||||
fprintf(stderr, "Failed to shiftl.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test BN_is_pow2 on power_of_two.
|
||||
if (!BN_is_pow2(power_of_two.get())) {
|
||||
fprintf(stderr, "BN_is_pow2 returned false for a power of two.\n");
|
||||
hexdump(stderr, "Arg: ", power_of_two->d,
|
||||
power_of_two->top * sizeof(BN_ULONG));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pick a large random value, ensuring it isn't a power of two.
|
||||
if (!BN_rand(random.get(), len, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) {
|
||||
fprintf(stderr, "Failed to generate random in TestBNPow2.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test BN_is_pow2 on |r|.
|
||||
if (BN_is_pow2(random.get())) {
|
||||
fprintf(stderr, "BN_is_pow2 returned true for a non-power of two.\n");
|
||||
hexdump(stderr, "Arg: ", random->d, random->top * sizeof(BN_ULONG));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test BN_mod_pow2 on |r|.
|
||||
if (!BN_mod(expected.get(), random.get(), power_of_two.get(), ctx) ||
|
||||
!BN_mod_pow2(actual.get(), random.get(), e) ||
|
||||
BN_cmp(actual.get(), expected.get())) {
|
||||
fprintf(stderr, "BN_mod_pow2 returned the wrong value:\n");
|
||||
hexdump(stderr, "Expected: ", expected->d,
|
||||
expected->top * sizeof(BN_ULONG));
|
||||
hexdump(stderr, "Got: ", actual->d,
|
||||
actual->top * sizeof(BN_ULONG));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test BN_nnmod_pow2 on |r|.
|
||||
if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
|
||||
!BN_nnmod_pow2(actual.get(), random.get(), e) ||
|
||||
BN_cmp(actual.get(), expected.get())) {
|
||||
fprintf(stderr, "BN_nnmod_pow2 failed on positive input:\n");
|
||||
hexdump(stderr, "Expected: ", expected->d,
|
||||
expected->top * sizeof(BN_ULONG));
|
||||
hexdump(stderr, "Got: ", actual->d,
|
||||
actual->top * sizeof(BN_ULONG));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test BN_nnmod_pow2 on -|r|.
|
||||
BN_set_negative(random.get(), 1);
|
||||
if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
|
||||
!BN_nnmod_pow2(actual.get(), random.get(), e) ||
|
||||
BN_cmp(actual.get(), expected.get())) {
|
||||
fprintf(stderr, "BN_nnmod_pow2 failed on negative input:\n");
|
||||
hexdump(stderr, "Expected: ", expected->d,
|
||||
expected->top * sizeof(BN_ULONG));
|
||||
hexdump(stderr, "Got: ", actual->d,
|
||||
actual->top * sizeof(BN_ULONG));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1772,7 +1486,6 @@ int main(int argc, char *argv[]) {
|
||||
!TestDec2BN(ctx.get()) ||
|
||||
!TestHex2BN(ctx.get()) ||
|
||||
!TestASC2BN(ctx.get()) ||
|
||||
!TestLittleEndian() ||
|
||||
!TestMPI() ||
|
||||
!TestRand() ||
|
||||
!TestASN1() ||
|
||||
@@ -1782,8 +1495,7 @@ int main(int argc, char *argv[]) {
|
||||
!TestSmallPrime(ctx.get()) ||
|
||||
!TestCmpWord() ||
|
||||
!TestBN2Dec() ||
|
||||
!TestBNSetGetU64() ||
|
||||
!TestBNPow2(ctx.get())) {
|
||||
!TestBNSetU64()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -9875,28 +9875,6 @@ A = 1c08cec52d96136fbd9078b7b8db36ab63b86e19dd3dba7b2e3190ff566180e89dfee9423fa4
|
||||
B = a8b4bc9647d8df9b7c76cc6d0f2248cdbc41f5da9c061f9864aa8415c9557582cada456cf23cc32d47d1fc1caf19d36b398019aac4734e10f55ce3cad419e5e7
|
||||
M = 7eacffe21f88413af94155a2a8e37f70a431a59653738afda04a1bec72d0d9ed
|
||||
|
||||
# Regression tests for CVE-2016-7055.
|
||||
|
||||
ModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9
|
||||
A = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878
|
||||
B = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81
|
||||
M = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf
|
||||
|
||||
ModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9
|
||||
A = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81
|
||||
B = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878
|
||||
M = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf
|
||||
|
||||
|
||||
# ModSquare tests.
|
||||
#
|
||||
# These test vectors satisfy A * A = ModSquare (mod M) and 0 <= ModSquare < M.
|
||||
|
||||
# Regression test for CVE-2017-3732.
|
||||
ModSquare = fffffffdfffffd01000009000002f6fffdf403000312000402f3fff5f602fe080a0005fdfafffa00010001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000002000002fefffff7fffffd07000109fdfffef3fffdfd06000405ff00fdfbfffe00010001
|
||||
A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff00000000
|
||||
M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff
|
||||
|
||||
|
||||
# ModExp tests.
|
||||
#
|
||||
@@ -10397,89 +10375,6 @@ E = d7e6df5d755284929b986cd9b61c9c2c8843f24c711fbdbae1a468edcae15940094372557072
|
||||
M = e4e784aa1fa88625a43ba0185a153a929663920be7fe674a4d33c943d3b898cff051482e7050a070cede53be5e89f31515772c7aea637576f99f82708f89d9e244f6ad3a24a02cbe5c0ff7bcf2dad5491f53db7c3f2698a7c41b44f086652f17bb05fe4c5c0a92433c34086b49d7e1825b28bab6c5a9bd0bc95b53d659afa0d7
|
||||
|
||||
|
||||
# RSAZ 512-bit.
|
||||
#
|
||||
# These are regression tests for code which historically reached the RSAZ-512
|
||||
# code. That has since been removed, but the test vectors remain. Note that the
|
||||
# lengths of the inputs, especially the *bit* length of |M|, matter a lot.
|
||||
|
||||
# Control: No relationship between A and M except that A < M and they're the same number of limbs.
|
||||
ModExp = 7f34c1cd63377bc3abf2bb5b2d1bf5f06454e1e8040fe19a72245ce9731cbee1bf9e84532300776c8021ed4f3a8de508d85b4cf320bd82065a013754857b50c4
|
||||
A = 8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364
|
||||
E = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
|
||||
M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
|
||||
# Same as above except A is negative.
|
||||
ModExp = 71fa6a4c8ae75368eda8cc6282c26afa69e2af12a97fb9444f16b7dd6c99e0a5d6034cab4248cae4357346b211039f4a2bc4c5a20a297372094162417af703cd
|
||||
A = -8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364
|
||||
E = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
|
||||
M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
|
||||
# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.
|
||||
ModExp = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490
|
||||
A = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490
|
||||
E = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
|
||||
M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
|
||||
# Same inputs as above except A is negative. Note that A mod M with a "correct top" isn't the right length for RSAZ.
|
||||
ModExp = 1
|
||||
A = -f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490
|
||||
E = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
|
||||
M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
|
||||
# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a "correct top" isn't the right length for RSAZ.
|
||||
ModExp = 0
|
||||
A = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
E = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
|
||||
M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
|
||||
# A is negative, and A (mod M) is the right length for RSAZ.
|
||||
ModExp = 8d76eb0f8c7bc3160cc8bb0e0c3590fbed26c5932f5f525b48045c0bd46dda287ba5483f97c851fb7c12c2e858ee7a4a4d1af745cbfb3eb311fa54bea12cde25
|
||||
A = -80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
E = be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
|
||||
M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
|
||||
|
||||
|
||||
# RSAZ 1024-bit.
|
||||
# Note that the lengths of the inputs, especially the *bit* length of |M|, matter a lot.
|
||||
|
||||
# Control: No relationship between A and M except that A < M and they're the same number of limbs.
|
||||
ModExp = 8984f8c16044f9c0ad7bd72347af90f58e6e003acda92b76e3c7c4a56ea8e918409d8e9b34884d4c89d0b17cb40fe898f2627c084a0f1698e46beccbf6f48eecc281e11ea9e5135adba460ddae157f2c655b5f589ce29b254d43a960a71cede8a08dbb86be4dac22458da232fb1ec2470856827302ed772c9ddafa408c931aa7
|
||||
A = 21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8
|
||||
E = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575
|
||||
M = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7
|
||||
|
||||
# Same as above except A is negative.
|
||||
ModExp = 75b54540dd6ec1e87c4e77bb93fd50477ea463fdadb5cab05119b34585d18f971617fc1194240ffa6bdfb53e4785f0a451e03f8c3c444aa6080a96af5906eaa508862a4de15b2c55c023b6f278cd04c1e24fd0711244afeda8e3444256e51261ed99fe66beedb52c43c825b4c7a1adc7d4b111e2208ecd495df91e175573ca10
|
||||
A = -21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8
|
||||
E = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575
|
||||
M = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7
|
||||
|
||||
# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.
|
||||
ModExp = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964
|
||||
A = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964
|
||||
E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
|
||||
M = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
|
||||
|
||||
# Same inputs as above except A is negative. Note that A mod M with a "correct top" isn't the right length for RSAZ.
|
||||
ModExp = 1
|
||||
A = -b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964
|
||||
E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
|
||||
M = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
|
||||
|
||||
# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a "correct top" isn't the right length for RSAZ.
|
||||
ModExp = 0
|
||||
A = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
|
||||
E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
|
||||
M = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
|
||||
|
||||
# A is negative, and A (mod M) is the right length for RSAZ.
|
||||
ModExp = 9cf810b9e89d5cbc4b79ae64e123ea06d92965e2bab077df97a1b906dc2e1ddcf96a9c4ed14e2cd96309b829ea9cc2a74a7d4b43c5f34d792a7c583201427754b8f78b783608070a84b61f18913e3ced7f7f530972de7764667c54e29d756eea38a93cd1703c676a4587231b0ebfeadddf908e2877a7a84b5bfc370ecf0d158d
|
||||
A = -8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
|
||||
M = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
|
||||
|
||||
|
||||
# Exp tests.
|
||||
#
|
||||
# These test vectors satisfy A ^ E = Exp.
|
||||
@@ -10830,28 +10725,6 @@ ModSqrt = a1d52989f12f204d3d2167d9b1e6c8a6174c0c786a979a5952383b7b8bd186
|
||||
A = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81
|
||||
P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
|
||||
|
||||
|
||||
# NotModSquare tests.
|
||||
#
|
||||
# These test vectors are such that NotModSquare is not a square modulo P.
|
||||
|
||||
NotModSquare = 03
|
||||
P = 07
|
||||
|
||||
NotModSquare = 05
|
||||
P = 07
|
||||
|
||||
NotModSquare = 06
|
||||
P = 07
|
||||
|
||||
NotModSquare = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951e
|
||||
P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
|
||||
|
||||
|
||||
# ModInv tests.
|
||||
#
|
||||
# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.
|
||||
|
||||
ModInv = 00
|
||||
A = 00
|
||||
M = 01
|
||||
|
||||
@@ -212,20 +212,6 @@ int BN_is_odd(const BIGNUM *bn) {
|
||||
return bn->top > 0 && (bn->d[0] & 1) == 1;
|
||||
}
|
||||
|
||||
int BN_is_pow2(const BIGNUM *bn) {
|
||||
if (bn->top == 0 || bn->neg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < bn->top - 1; i++) {
|
||||
if (bn->d[i] != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1));
|
||||
}
|
||||
|
||||
int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
|
||||
if (a->top != b->top) {
|
||||
return 0;
|
||||
|
||||
+2
-73
@@ -118,42 +118,6 @@ BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
|
||||
BIGNUM *bn = NULL;
|
||||
if (ret == NULL) {
|
||||
bn = BN_new();
|
||||
ret = bn;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
ret->top = 0;
|
||||
ret->neg = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reserve enough space in |ret|. */
|
||||
size_t num_words = ((len - 1) / BN_BYTES) + 1;
|
||||
if (!bn_wexpand(ret, num_words)) {
|
||||
BN_free(bn);
|
||||
return NULL;
|
||||
}
|
||||
ret->top = num_words;
|
||||
|
||||
/* Make sure the top bytes will be zeroed. */
|
||||
ret->d[num_words - 1] = 0;
|
||||
|
||||
/* We only support little-endian platforms, so we can simply memcpy the
|
||||
* internal representation. */
|
||||
OPENSSL_memcpy(ret->d, in, len);
|
||||
|
||||
bn_correct_top(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
|
||||
size_t n, i;
|
||||
BN_ULONG l;
|
||||
@@ -166,23 +130,6 @@ size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
|
||||
return n;
|
||||
}
|
||||
|
||||
int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
|
||||
/* If we don't have enough space, fail out. */
|
||||
size_t num_bytes = BN_num_bytes(in);
|
||||
if (len < num_bytes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We only support little-endian platforms, so we can simply memcpy into the
|
||||
* internal representation. */
|
||||
OPENSSL_memcpy(out, in->d, num_bytes);
|
||||
|
||||
/* Pad out the rest of the buffer with zeroes. */
|
||||
OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
|
||||
* behavior is undefined if |v| takes any other value. */
|
||||
static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
|
||||
@@ -215,7 +162,7 @@ static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
|
||||
int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
|
||||
/* Special case for |in| = 0. Just branch as the probability is negligible. */
|
||||
if (BN_is_zero(in)) {
|
||||
OPENSSL_memset(out, 0, len);
|
||||
memset(out, 0, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -568,24 +515,6 @@ BN_ULONG BN_get_word(const BIGNUM *bn) {
|
||||
}
|
||||
}
|
||||
|
||||
int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
|
||||
switch (bn->top) {
|
||||
case 0:
|
||||
*out = 0;
|
||||
return 1;
|
||||
case 1:
|
||||
*out = bn->d[0];
|
||||
return 1;
|
||||
#if defined(OPENSSL_32_BIT)
|
||||
case 2:
|
||||
*out = (uint64_t) bn->d[0] | (((uint64_t) bn->d[1]) << 32);
|
||||
return 1;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
|
||||
const size_t bits = BN_num_bits(in);
|
||||
const size_t bytes = (bits + 7) / 8;
|
||||
@@ -603,7 +532,7 @@ size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
|
||||
/* If we cannot represent the number then we emit zero as the interface
|
||||
* doesn't allow an error to be signalled. */
|
||||
if (out) {
|
||||
OPENSSL_memset(out, 0, 4);
|
||||
memset(out, 0, 4);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
+1
-3
@@ -59,8 +59,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* How many bignums are in each "pool item"; */
|
||||
#define BN_CTX_POOL_SIZE 16
|
||||
@@ -220,7 +218,7 @@ static int BN_STACK_push(BN_STACK *st, unsigned int idx) {
|
||||
return 0;
|
||||
}
|
||||
if (st->depth) {
|
||||
OPENSSL_memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
|
||||
memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
|
||||
}
|
||||
OPENSSL_free(st->indexes);
|
||||
st->indexes = newitems;
|
||||
|
||||
+51
-108
@@ -58,7 +58,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
@@ -183,12 +182,7 @@ static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
|
||||
* Thus:
|
||||
* dv->neg == num->neg ^ divisor->neg (unless the result is zero)
|
||||
* rm->neg == num->neg (unless the remainder is zero)
|
||||
* If 'dv' or 'rm' is NULL, the respective value is not returned.
|
||||
*
|
||||
* This was specifically designed to contain fewer branches that may leak
|
||||
* sensitive information; see "New Branch Prediction Vulnerabilities in OpenSSL
|
||||
* and Necessary Software Countermeasures" by Onur Acıçmez, Shay Gueron, and
|
||||
* Jean-Pierre Seifert. */
|
||||
* If 'dv' or 'rm' is NULL, the respective value is not returned. */
|
||||
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
BN_CTX *ctx) {
|
||||
int norm_shift, i, loop;
|
||||
@@ -196,6 +190,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
BN_ULONG *resp, *wnump;
|
||||
BN_ULONG d0, d1;
|
||||
int num_n, div_n;
|
||||
int no_branch = 0;
|
||||
|
||||
/* Invalid zero-padding would have particularly bad consequences
|
||||
* so don't just rely on bn_check_top() here */
|
||||
@@ -205,11 +200,28 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((num->flags & BN_FLG_CONSTTIME) != 0 ||
|
||||
(divisor->flags & BN_FLG_CONSTTIME) != 0) {
|
||||
no_branch = 1;
|
||||
}
|
||||
|
||||
if (BN_is_zero(divisor)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!no_branch && BN_ucmp(num, divisor) < 0) {
|
||||
if (rm != NULL) {
|
||||
if (BN_copy(rm, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (dv != NULL) {
|
||||
BN_zero(dv);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
snum = BN_CTX_get(ctx);
|
||||
@@ -235,23 +247,26 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
}
|
||||
snum->neg = 0;
|
||||
|
||||
/* Since we don't want to have special-case logic for the case where snum is
|
||||
* larger than sdiv, we pad snum with enough zeroes without changing its
|
||||
* value. */
|
||||
if (snum->top <= sdiv->top + 1) {
|
||||
if (bn_wexpand(snum, sdiv->top + 2) == NULL) {
|
||||
goto err;
|
||||
if (no_branch) {
|
||||
/* Since we don't know whether snum is larger than sdiv,
|
||||
* we pad snum with enough zeroes without changing its
|
||||
* value.
|
||||
*/
|
||||
if (snum->top <= sdiv->top + 1) {
|
||||
if (bn_wexpand(snum, sdiv->top + 2) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
for (i = snum->top; i < sdiv->top + 2; i++) {
|
||||
snum->d[i] = 0;
|
||||
}
|
||||
snum->top = sdiv->top + 2;
|
||||
} else {
|
||||
if (bn_wexpand(snum, snum->top + 1) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
snum->d[snum->top] = 0;
|
||||
snum->top++;
|
||||
}
|
||||
for (i = snum->top; i < sdiv->top + 2; i++) {
|
||||
snum->d[i] = 0;
|
||||
}
|
||||
snum->top = sdiv->top + 2;
|
||||
} else {
|
||||
if (bn_wexpand(snum, snum->top + 1) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
snum->d[snum->top] = 0;
|
||||
snum->top++;
|
||||
}
|
||||
|
||||
div_n = sdiv->top;
|
||||
@@ -279,7 +294,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
if (!bn_wexpand(res, (loop + 1))) {
|
||||
goto err;
|
||||
}
|
||||
res->top = loop - 1;
|
||||
res->top = loop - no_branch;
|
||||
resp = &(res->d[loop - 1]);
|
||||
|
||||
/* space for temp */
|
||||
@@ -287,6 +302,15 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!no_branch) {
|
||||
if (BN_ucmp(&wnum, sdiv) >= 0) {
|
||||
bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
|
||||
*resp = 1;
|
||||
} else {
|
||||
res->top--;
|
||||
}
|
||||
}
|
||||
|
||||
/* if res->top == 0 then clear the neg value otherwise decrease
|
||||
* the resp pointer */
|
||||
if (res->top == 0) {
|
||||
@@ -377,7 +401,9 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
rm->neg = neg;
|
||||
}
|
||||
}
|
||||
bn_correct_top(res);
|
||||
if (no_branch) {
|
||||
bn_correct_top(res);
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
return 1;
|
||||
|
||||
@@ -602,10 +628,6 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
|
||||
a->top--;
|
||||
}
|
||||
|
||||
if (a->top == 0) {
|
||||
a->neg = 0;
|
||||
}
|
||||
|
||||
ret >>= j;
|
||||
return ret;
|
||||
}
|
||||
@@ -647,82 +669,3 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
|
||||
}
|
||||
return (BN_ULONG)ret;
|
||||
}
|
||||
|
||||
int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
|
||||
if (e == 0 || a->top == 0) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t num_words = 1 + ((e - 1) / BN_BITS2);
|
||||
|
||||
/* If |a| definitely has less than |e| bits, just BN_copy. */
|
||||
if ((size_t) a->top < num_words) {
|
||||
return BN_copy(r, a) != NULL;
|
||||
}
|
||||
|
||||
/* Otherwise, first make sure we have enough space in |r|.
|
||||
* Note that this will fail if num_words > INT_MAX. */
|
||||
if (bn_wexpand(r, num_words) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the content of |a| into |r|. */
|
||||
OPENSSL_memcpy(r->d, a->d, num_words * sizeof(BN_ULONG));
|
||||
|
||||
/* If |e| isn't word-aligned, we have to mask off some of our bits. */
|
||||
size_t top_word_exponent = e % (sizeof(BN_ULONG) * 8);
|
||||
if (top_word_exponent != 0) {
|
||||
r->d[num_words - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
|
||||
}
|
||||
|
||||
/* Fill in the remaining fields of |r|. */
|
||||
r->neg = a->neg;
|
||||
r->top = (int) num_words;
|
||||
bn_correct_top(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
|
||||
if (!BN_mod_pow2(r, a, e)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the returned value was non-negative, we're done. */
|
||||
if (BN_is_zero(r) || !r->neg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t num_words = 1 + (e - 1) / BN_BITS2;
|
||||
|
||||
/* Expand |r| to the size of our modulus. */
|
||||
if (bn_wexpand(r, num_words) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clear the upper words of |r|. */
|
||||
OPENSSL_memset(&r->d[r->top], 0, (num_words - r->top) * BN_BYTES);
|
||||
|
||||
/* Set parameters of |r|. */
|
||||
r->neg = 0;
|
||||
r->top = (int) num_words;
|
||||
|
||||
/* Now, invert every word. The idea here is that we want to compute 2^e-|x|,
|
||||
* which is actually equivalent to the twos-complement representation of |x|
|
||||
* in |e| bits, which is -x = ~x + 1. */
|
||||
for (int i = 0; i < r->top; i++) {
|
||||
r->d[i] = ~r->d[i];
|
||||
}
|
||||
|
||||
/* If our exponent doesn't span the top word, we have to mask the rest. */
|
||||
size_t top_word_exponent = e % BN_BITS2;
|
||||
if (top_word_exponent != 0) {
|
||||
r->d[r->top - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
|
||||
}
|
||||
|
||||
/* Keep the correct_top invariant for BN_add. */
|
||||
bn_correct_top(r);
|
||||
|
||||
/* Finally, add one, for the reason described above. */
|
||||
return BN_add(r, r, BN_value_one());
|
||||
}
|
||||
|
||||
+33
-15
@@ -140,6 +140,12 @@ int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
int i, bits, ret = 0;
|
||||
BIGNUM *v, *rr;
|
||||
|
||||
if ((p->flags & BN_FLG_CONSTTIME) != 0) {
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if (r == a || r == p) {
|
||||
rr = BN_CTX_get(ctx);
|
||||
@@ -431,6 +437,12 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
BIGNUM *val[TABLE_SIZE];
|
||||
BN_RECP_CTX recp;
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bits = BN_num_bits(p);
|
||||
|
||||
if (bits == 0) {
|
||||
@@ -581,6 +593,10 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
BIGNUM *val[TABLE_SIZE];
|
||||
BN_MONT_CTX *new_mont = NULL;
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
|
||||
return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, mont);
|
||||
}
|
||||
|
||||
if (!BN_is_odd(m)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return 0;
|
||||
@@ -860,7 +876,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
int powerbufLen = 0;
|
||||
unsigned char *powerbuf = NULL;
|
||||
BIGNUM tmp, am;
|
||||
BIGNUM *new_a = NULL;
|
||||
|
||||
if (!BN_is_odd(m)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
@@ -888,15 +903,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
mont = new_mont;
|
||||
}
|
||||
|
||||
if (a->neg || BN_ucmp(a, m) >= 0) {
|
||||
new_a = BN_new();
|
||||
if (new_a == NULL ||
|
||||
!BN_nnmod(new_a, a, m, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
a = new_a;
|
||||
}
|
||||
|
||||
#ifdef RSAZ_ENABLED
|
||||
/* If the size of the operands allow it, perform the optimized
|
||||
* RSAZ exponentiation. For further information see
|
||||
@@ -912,6 +918,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
bn_correct_top(rr);
|
||||
ret = 1;
|
||||
goto err;
|
||||
} else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) {
|
||||
if (NULL == bn_wexpand(rr, 8)) {
|
||||
goto err;
|
||||
}
|
||||
RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);
|
||||
rr->top = 8;
|
||||
rr->neg = 0;
|
||||
bn_correct_top(rr);
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -945,7 +961,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
|
||||
powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
|
||||
OPENSSL_memset(powerbuf, 0, powerbufLen);
|
||||
memset(powerbuf, 0, powerbufLen);
|
||||
|
||||
#ifdef alloca
|
||||
if (powerbufLen < 3072) {
|
||||
@@ -975,9 +991,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
|
||||
/* prepare a^1 in Montgomery domain */
|
||||
assert(!a->neg);
|
||||
assert(BN_ucmp(a, m) < 0);
|
||||
if (!BN_to_montgomery(&am, a, mont, ctx)) {
|
||||
if (a->neg || BN_ucmp(a, m) >= 0) {
|
||||
if (!BN_nnmod(&am, a, m, ctx) ||
|
||||
!BN_to_montgomery(&am, &am, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
} else if (!BN_to_montgomery(&am, a, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1171,7 +1190,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
|
||||
err:
|
||||
BN_MONT_CTX_free(new_mont);
|
||||
BN_clear_free(new_a);
|
||||
if (powerbuf != NULL) {
|
||||
OPENSSL_cleanse(powerbuf, powerbufLen);
|
||||
OPENSSL_free(powerbufFree);
|
||||
|
||||
+22
-29
@@ -399,6 +399,10 @@ err:
|
||||
|
||||
BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
|
||||
BN_CTX *ctx) {
|
||||
int no_inverse;
|
||||
|
||||
BIGNUM *a_reduced = NULL;
|
||||
|
||||
BIGNUM *new_out = NULL;
|
||||
if (out == NULL) {
|
||||
new_out = BN_new();
|
||||
@@ -410,20 +414,25 @@ BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
|
||||
}
|
||||
|
||||
int ok = 0;
|
||||
BIGNUM *a_reduced = NULL;
|
||||
|
||||
int no_branch =
|
||||
(a->flags & BN_FLG_CONSTTIME) != 0 || (n->flags & BN_FLG_CONSTTIME) != 0;
|
||||
|
||||
if (a->neg || BN_ucmp(a, n) >= 0) {
|
||||
a_reduced = BN_dup(a);
|
||||
if (a_reduced == NULL) {
|
||||
goto err;
|
||||
}
|
||||
if (no_branch) {
|
||||
BN_set_flags(a_reduced, BN_FLG_CONSTTIME);
|
||||
}
|
||||
if (!BN_nnmod(a_reduced, a_reduced, n, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
a = a_reduced;
|
||||
}
|
||||
|
||||
int no_inverse;
|
||||
if (!BN_is_odd(n)) {
|
||||
if (no_branch || !BN_is_odd(n)) {
|
||||
if (!bn_mod_inverse_general(out, &no_inverse, a, n, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
@@ -472,13 +481,15 @@ err:
|
||||
|
||||
/* bn_mod_inverse_general is the general inversion algorithm that works for
|
||||
* both even and odd |n|. It was specifically designed to contain fewer
|
||||
* branches that may leak sensitive information; see "New Branch Prediction
|
||||
* branches that may leak sensitive information. See "New Branch Prediction
|
||||
* Vulnerabilities in OpenSSL and Necessary Software Countermeasures" by
|
||||
* Onur Acıçmez, Shay Gueron, and Jean-Pierre Seifert. */
|
||||
static int bn_mod_inverse_general(BIGNUM *out, int *out_no_inverse,
|
||||
const BIGNUM *a, const BIGNUM *n,
|
||||
BN_CTX *ctx) {
|
||||
BIGNUM *A, *B, *X, *Y, *M, *D, *T;
|
||||
BIGNUM local_A;
|
||||
BIGNUM *pA;
|
||||
int ret = 0;
|
||||
int sign;
|
||||
|
||||
@@ -521,8 +532,14 @@ static int bn_mod_inverse_general(BIGNUM *out, int *out_no_inverse,
|
||||
* sign*Y*a == A (mod |n|)
|
||||
*/
|
||||
|
||||
/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
|
||||
* BN_div_no_branch will be called eventually.
|
||||
*/
|
||||
pA = &local_A;
|
||||
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
|
||||
|
||||
/* (D, M) := (A/B, A%B) ... */
|
||||
if (!BN_div(D, M, A, B, ctx)) {
|
||||
if (!BN_div(D, M, pA, B, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -609,27 +626,3 @@ err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
|
||||
BN_CTX *ctx, const BN_MONT_CTX *mont_p) {
|
||||
BN_CTX_start(ctx);
|
||||
BIGNUM *p_minus_2 = BN_CTX_get(ctx);
|
||||
int ok = p_minus_2 != NULL &&
|
||||
BN_copy(p_minus_2, p) &&
|
||||
BN_sub_word(p_minus_2, 2) &&
|
||||
BN_mod_exp_mont(out, a, p_minus_2, p, ctx, mont_p);
|
||||
BN_CTX_end(ctx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
|
||||
BN_CTX *ctx, const BN_MONT_CTX *mont_p) {
|
||||
BN_CTX_start(ctx);
|
||||
BIGNUM *p_minus_2 = BN_CTX_get(ctx);
|
||||
int ok = p_minus_2 != NULL &&
|
||||
BN_copy(p_minus_2, p) &&
|
||||
BN_sub_word(p_minus_2, 2) &&
|
||||
BN_mod_exp_mont_consttime(out, a, p_minus_2, p, ctx, mont_p);
|
||||
BN_CTX_end(ctx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
+67
-71
@@ -67,34 +67,34 @@
|
||||
!(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
|
||||
|
||||
#ifdef BN_ULLONG
|
||||
#define mul_add(r, a, w, c) \
|
||||
do { \
|
||||
BN_ULLONG t; \
|
||||
t = (BN_ULLONG)(w) * (a) + (r) + (c); \
|
||||
(r) = Lw(t); \
|
||||
(c) = Hw(t); \
|
||||
} while (0)
|
||||
#define mul_add(r, a, w, c) \
|
||||
{ \
|
||||
BN_ULLONG t; \
|
||||
t = (BN_ULLONG)w * (a) + (r) + (c); \
|
||||
(r) = Lw(t); \
|
||||
(c) = Hw(t); \
|
||||
}
|
||||
|
||||
#define mul(r, a, w, c) \
|
||||
do { \
|
||||
BN_ULLONG t; \
|
||||
t = (BN_ULLONG)(w) * (a) + (c); \
|
||||
(r) = Lw(t); \
|
||||
(c) = Hw(t); \
|
||||
} while (0)
|
||||
#define mul(r, a, w, c) \
|
||||
{ \
|
||||
BN_ULLONG t; \
|
||||
t = (BN_ULLONG)w * (a) + (c); \
|
||||
(r) = Lw(t); \
|
||||
(c) = Hw(t); \
|
||||
}
|
||||
|
||||
#define sqr(r0, r1, a) \
|
||||
do { \
|
||||
{ \
|
||||
BN_ULLONG t; \
|
||||
t = (BN_ULLONG)(a) * (a); \
|
||||
(r0) = Lw(t); \
|
||||
(r1) = Hw(t); \
|
||||
} while (0)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define mul_add(r, a, w, c) \
|
||||
do { \
|
||||
{ \
|
||||
BN_ULONG high, low, ret, tmp = (a); \
|
||||
ret = (r); \
|
||||
BN_UMULT_LOHI(low, high, w, tmp); \
|
||||
@@ -104,23 +104,23 @@
|
||||
ret += low; \
|
||||
(c) += (ret < low) ? 1 : 0; \
|
||||
(r) = ret; \
|
||||
} while (0)
|
||||
}
|
||||
|
||||
#define mul(r, a, w, c) \
|
||||
do { \
|
||||
{ \
|
||||
BN_ULONG high, low, ret, ta = (a); \
|
||||
BN_UMULT_LOHI(low, high, w, ta); \
|
||||
ret = low + (c); \
|
||||
(c) = high; \
|
||||
(c) += (ret < low) ? 1 : 0; \
|
||||
(r) = ret; \
|
||||
} while (0)
|
||||
}
|
||||
|
||||
#define sqr(r0, r1, a) \
|
||||
do { \
|
||||
{ \
|
||||
BN_ULONG tmp = (a); \
|
||||
BN_UMULT_LOHI(r0, r1, tmp, tmp); \
|
||||
} while (0)
|
||||
}
|
||||
|
||||
#endif /* !BN_ULLONG */
|
||||
|
||||
@@ -369,46 +369,42 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
|
||||
t += (c0); /* no carry */ \
|
||||
(c0) = (BN_ULONG)Lw(t); \
|
||||
t += c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
(c1) = ((c1) + (hi)) & BN_MASK2; \
|
||||
if ((c1) < hi) { \
|
||||
(c2)++; \
|
||||
} \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
|
||||
BN_ULLONG tt = t + (c0); /* no carry */ \
|
||||
(c0) = (BN_ULONG)Lw(tt); \
|
||||
hi = (BN_ULONG)Hw(tt); \
|
||||
(c1) = ((c1) + hi) & BN_MASK2; \
|
||||
if ((c1) < hi) { \
|
||||
(c2)++; \
|
||||
} \
|
||||
t += (c0); /* no carry */ \
|
||||
(c0) = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
(c1) = ((c1) + hi) & BN_MASK2; \
|
||||
if ((c1) < hi) { \
|
||||
(c2)++; \
|
||||
} \
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
|
||||
BN_ULLONG tt = t + c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(tt); \
|
||||
hi = (BN_ULONG)Hw(tt); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
t += c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)(a)[i] * (a)[i]; \
|
||||
t += (c0); /* no carry */ \
|
||||
(c0) = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
(c1) = ((c1) + hi) & BN_MASK2; \
|
||||
if ((c1) < hi) { \
|
||||
(c2)++; \
|
||||
} \
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG hi; \
|
||||
BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \
|
||||
t += c0; /* no carry */ \
|
||||
c0 = (BN_ULONG)Lw(t); \
|
||||
hi = (BN_ULONG)Hw(t); \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
@@ -422,10 +418,10 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
BN_ULONG lo, hi; \
|
||||
BN_UMULT_LOHI(lo, hi, ta, tb); \
|
||||
(c0) += lo; \
|
||||
hi += ((c0) < lo) ? 1 : 0; \
|
||||
(c1) += hi; \
|
||||
(c2) += ((c1) < hi) ? 1 : 0; \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
@@ -433,14 +429,14 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
BN_ULONG lo, hi, tt; \
|
||||
BN_UMULT_LOHI(lo, hi, ta, tb); \
|
||||
(c0) += lo; \
|
||||
tt = hi + (((c0) < lo) ? 1 : 0); \
|
||||
(c1) += tt; \
|
||||
(c2) += ((c1) < tt) ? 1 : 0; \
|
||||
(c0) += lo; \
|
||||
c0 += lo; \
|
||||
tt = hi + ((c0 < lo) ? 1 : 0); \
|
||||
c1 += tt; \
|
||||
c2 += (c1 < tt) ? 1 : 0; \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
(c1) += hi; \
|
||||
(c2) += ((c1) < hi) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
@@ -448,10 +444,10 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
BN_ULONG ta = (a)[i]; \
|
||||
BN_ULONG lo, hi; \
|
||||
BN_UMULT_LOHI(lo, hi, ta, ta); \
|
||||
(c0) += lo; \
|
||||
c0 += lo; \
|
||||
hi += (c0 < lo) ? 1 : 0; \
|
||||
(c1) += hi; \
|
||||
(c2) += ((c1) < hi) ? 1 : 0; \
|
||||
c1 += hi; \
|
||||
c2 += (c1 < hi) ? 1 : 0; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
+6
-19
@@ -160,7 +160,7 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
#define BN_TBIT (0x8000000000000000UL)
|
||||
#define BN_DEC_CONV (10000000000000000000UL)
|
||||
#define BN_DEC_NUM 19
|
||||
#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo))
|
||||
#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo)
|
||||
|
||||
#elif defined(OPENSSL_32_BIT)
|
||||
|
||||
@@ -181,17 +181,17 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
#define BN_TBIT (0x80000000UL)
|
||||
#define BN_DEC_CONV (1000000000UL)
|
||||
#define BN_DEC_NUM 9
|
||||
#define TOBN(hi, lo) (lo), (hi)
|
||||
#define TOBN(hi, lo) lo, hi
|
||||
|
||||
#else
|
||||
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
|
||||
#endif
|
||||
|
||||
|
||||
#define STATIC_BIGNUM(x) \
|
||||
{ \
|
||||
(BN_ULONG *)(x), sizeof(x) / sizeof(BN_ULONG), \
|
||||
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
|
||||
#define STATIC_BIGNUM(x) \
|
||||
{ \
|
||||
(BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \
|
||||
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
|
||||
}
|
||||
|
||||
#if defined(BN_ULLONG)
|
||||
@@ -228,7 +228,6 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
const BN_ULONG *np, const BN_ULONG *n0, int num);
|
||||
|
||||
uint64_t bn_mont_n0(const BIGNUM *n);
|
||||
int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n);
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
@@ -238,18 +237,6 @@ int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n);
|
||||
#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
|
||||
#endif
|
||||
|
||||
/* bn_mod_inverse_prime sets |out| to the modular inverse of |a| modulo |p|,
|
||||
* computed with Fermat's Little Theorem. It returns one on success and zero on
|
||||
* error. If |mont_p| is NULL, one will be computed temporarily. */
|
||||
int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
|
||||
BN_CTX *ctx, const BN_MONT_CTX *mont_p);
|
||||
|
||||
/* bn_mod_inverse_secret_prime behaves like |bn_mod_inverse_prime| but uses
|
||||
* |BN_mod_exp_mont_consttime| instead of |BN_mod_exp_mont| in hopes of
|
||||
* protecting the exponent. */
|
||||
int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
|
||||
BN_CTX *ctx, const BN_MONT_CTX *mont_p);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
|
||||
@@ -144,7 +144,6 @@ int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
|
||||
i++;
|
||||
}
|
||||
if (!BN_rshift(A, A, i)) {
|
||||
ret = -2;
|
||||
goto end;
|
||||
}
|
||||
if (i & 1) {
|
||||
|
||||
+28
-48
@@ -108,7 +108,6 @@
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
@@ -125,11 +124,6 @@
|
||||
#define OPENSSL_BN_ASM_MONT
|
||||
#endif
|
||||
|
||||
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont, BN_CTX *ctx);
|
||||
|
||||
|
||||
BN_MONT_CTX *BN_MONT_CTX_new(void) {
|
||||
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
|
||||
|
||||
@@ -137,7 +131,7 @@ BN_MONT_CTX *BN_MONT_CTX_new(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BN_MONT_CTX));
|
||||
memset(ret, 0, sizeof(BN_MONT_CTX));
|
||||
BN_init(&ret->RR);
|
||||
BN_init(&ret->N);
|
||||
|
||||
@@ -192,6 +186,9 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (BN_get_flags(mod, BN_FLG_CONSTTIME)) {
|
||||
BN_set_flags(&mont->N, BN_FLG_CONSTTIME);
|
||||
}
|
||||
|
||||
/* Find n0 such that n0 * N == -1 (mod r).
|
||||
*
|
||||
@@ -210,13 +207,12 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
|
||||
/* Save RR = R**2 (mod N). R is the smallest power of 2**BN_BITS such that R
|
||||
* > mod. Even though the assembly on some 32-bit platforms works with 64-bit
|
||||
* values, using |BN_BITS2| here, rather than |BN_MONT_CTX_N0_LIMBS *
|
||||
* BN_BITS2|, is correct because R**2 will still be a multiple of the latter
|
||||
* as |BN_MONT_CTX_N0_LIMBS| is either one or two.
|
||||
*
|
||||
* XXX: This is not constant time with respect to |mont->N|, but it should
|
||||
* be. */
|
||||
* BN_BITS2|, is correct because because R^2 will still be a multiple of the
|
||||
* latter as |BN_MONT_CTX_N0_LIMBS| is either one or two. */
|
||||
unsigned lgBigR = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
|
||||
if (!bn_mod_exp_base_2_vartime(&mont->RR, lgBigR * 2, &mont->N)) {
|
||||
BN_zero(&mont->RR);
|
||||
if (!BN_set_bit(&mont->RR, lgBigR * 2) ||
|
||||
!BN_mod(&mont->RR, &mont->RR, &mont->N, ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -283,7 +279,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
|
||||
|
||||
/* clear the top words of T */
|
||||
if (max > r->top) {
|
||||
OPENSSL_memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
|
||||
memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
|
||||
}
|
||||
|
||||
r->top = max;
|
||||
@@ -366,43 +362,27 @@ err:
|
||||
|
||||
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont, BN_CTX *ctx) {
|
||||
#if !defined(OPENSSL_BN_ASM_MONT)
|
||||
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
|
||||
#else
|
||||
int num = mont->N.top;
|
||||
|
||||
/* |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. */
|
||||
if (num < (128 / BN_BITS2) ||
|
||||
a->top != num ||
|
||||
b->top != num) {
|
||||
return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
|
||||
}
|
||||
|
||||
if (bn_wexpand(r, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
|
||||
/* The check above ensures this won't happen. */
|
||||
assert(0);
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
r->neg = a->neg ^ b->neg;
|
||||
r->top = num;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b,
|
||||
const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
BIGNUM *tmp;
|
||||
int ret = 0;
|
||||
|
||||
#if defined(OPENSSL_BN_ASM_MONT)
|
||||
int num = mont->N.top;
|
||||
|
||||
if (num > 1 && a->top == num && b->top == num) {
|
||||
if (bn_wexpand(r, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
|
||||
r->neg = a->neg ^ b->neg;
|
||||
r->top = num;
|
||||
bn_correct_top(r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
BIGNUM *tmp = BN_CTX_get(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
if (tmp == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -158,50 +158,3 @@ static uint64_t bn_neg_inv_mod_r_u64(uint64_t n) {
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/* bn_mod_exp_base_2_vartime calculates r = 2**p (mod n). |p| must be larger
|
||||
* than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and
|
||||
* odd. */
|
||||
int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n) {
|
||||
assert(!BN_is_zero(n));
|
||||
assert(!BN_is_negative(n));
|
||||
assert(BN_is_odd(n));
|
||||
|
||||
BN_zero(r);
|
||||
|
||||
unsigned n_bits = BN_num_bits(n);
|
||||
assert(n_bits != 0);
|
||||
if (n_bits == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set |r| to the smallest power of two larger than |n|. */
|
||||
assert(p > n_bits);
|
||||
if (!BN_set_bit(r, n_bits)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unconditionally reduce |r|. */
|
||||
assert(BN_cmp(r, n) > 0);
|
||||
if (!BN_usub(r, r, n)) {
|
||||
return 0;
|
||||
}
|
||||
assert(BN_cmp(r, n) < 0);
|
||||
|
||||
for (unsigned i = n_bits; i < p; ++i) {
|
||||
/* This is like |BN_mod_lshift1_quick| except using |BN_usub|.
|
||||
*
|
||||
* TODO: Replace this with the use of a constant-time variant of
|
||||
* |BN_mod_lshift1_quick|. */
|
||||
if (!BN_lshift1(r, r)) {
|
||||
return 0;
|
||||
}
|
||||
if (BN_cmp(r, n) >= 0) {
|
||||
if (!BN_usub(r, r, n)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
+9
-11
@@ -312,8 +312,7 @@ static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
|
||||
if ((dna + dnb) < 0) {
|
||||
OPENSSL_memset(&r[2 * n2 + dna + dnb], 0,
|
||||
sizeof(BN_ULONG) * -(dna + dnb));
|
||||
memset(&r[2 * n2 + dna + dnb], 0, sizeof(BN_ULONG) * -(dna + dnb));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -359,7 +358,7 @@ static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
if (!zero) {
|
||||
bn_mul_comba4(&(t[n2]), t, &(t[n]));
|
||||
} else {
|
||||
OPENSSL_memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
|
||||
memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
|
||||
}
|
||||
|
||||
bn_mul_comba4(r, a, b);
|
||||
@@ -369,7 +368,7 @@ static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
if (!zero) {
|
||||
bn_mul_comba8(&(t[n2]), t, &(t[n]));
|
||||
} else {
|
||||
OPENSSL_memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
|
||||
memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
|
||||
}
|
||||
|
||||
bn_mul_comba8(r, a, b);
|
||||
@@ -379,7 +378,7 @@ static void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
if (!zero) {
|
||||
bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
|
||||
} else {
|
||||
OPENSSL_memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
|
||||
memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
|
||||
}
|
||||
bn_mul_recursive(r, a, b, n, 0, 0, p);
|
||||
bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
|
||||
@@ -474,7 +473,7 @@ static void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
|
||||
bn_mul_comba8(&(t[n2]), t, &(t[n]));
|
||||
bn_mul_comba8(r, a, b);
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
|
||||
OPENSSL_memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
|
||||
memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
|
||||
} else {
|
||||
p = &(t[n2 * 2]);
|
||||
bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
|
||||
@@ -490,15 +489,14 @@ static void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
|
||||
|
||||
if (j == 0) {
|
||||
bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p);
|
||||
OPENSSL_memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2));
|
||||
memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2));
|
||||
} else if (j > 0) {
|
||||
/* eg, n == 16, i == 8 and tn == 11 */
|
||||
bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p);
|
||||
OPENSSL_memset(&(r[n2 + tna + tnb]), 0,
|
||||
sizeof(BN_ULONG) * (n2 - tna - tnb));
|
||||
memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
|
||||
} else {
|
||||
/* (j < 0) eg, n == 16, i == 8 and tn == 5 */
|
||||
OPENSSL_memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
|
||||
memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
|
||||
if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL &&
|
||||
tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
|
||||
@@ -737,7 +735,7 @@ static void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t
|
||||
if (!zero) {
|
||||
bn_sqr_recursive(&(t[n2]), t, n, p);
|
||||
} else {
|
||||
OPENSSL_memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
|
||||
memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
|
||||
}
|
||||
bn_sqr_recursive(r, a, n, p);
|
||||
bn_sqr_recursive(&(r[n2]), &(a[n]), n, p);
|
||||
|
||||
+3
-6
@@ -115,9 +115,6 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
|
||||
uint8_t *buf = NULL;
|
||||
int ret = 0, bit, bytes, mask;
|
||||
@@ -301,8 +298,8 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_PRIVATE_KEY_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(private_bytes, priv->d, todo);
|
||||
OPENSSL_memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
|
||||
memcpy(private_bytes, priv->d, todo);
|
||||
memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
|
||||
|
||||
for (attempt = 0;; attempt++) {
|
||||
for (done = 0; done < num_k_bytes;) {
|
||||
@@ -321,7 +318,7 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
|
||||
if (todo > SHA512_DIGEST_LENGTH) {
|
||||
todo = SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
OPENSSL_memcpy(k_bytes + done, digest, todo);
|
||||
memcpy(k_bytes + done, digest, todo);
|
||||
done += todo;
|
||||
}
|
||||
|
||||
|
||||
@@ -251,4 +251,69 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
OPENSSL_cleanse(storage,sizeof(storage));
|
||||
}
|
||||
|
||||
/*
|
||||
* See crypto/bn/rsaz-x86_64.pl for further details.
|
||||
*/
|
||||
void rsaz_512_mul(void *ret,const void *a,const void *b,const void *n,BN_ULONG k);
|
||||
void rsaz_512_mul_scatter4(void *ret,const void *a,const void *n,BN_ULONG k,const void *tbl,unsigned int power);
|
||||
void rsaz_512_mul_gather4(void *ret,const void *a,const void *tbl,const void *n,BN_ULONG k,unsigned int power);
|
||||
void rsaz_512_mul_by_one(void *ret,const void *a,const void *n,BN_ULONG k);
|
||||
void rsaz_512_sqr(void *ret,const void *a,const void *n,BN_ULONG k,int cnt);
|
||||
void rsaz_512_scatter4(void *tbl, const BN_ULONG *val, int power);
|
||||
void rsaz_512_gather4(BN_ULONG *val, const void *tbl, int power);
|
||||
|
||||
void RSAZ_512_mod_exp(BN_ULONG result[8],
|
||||
const BN_ULONG base[8], const BN_ULONG exponent[8],
|
||||
const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8])
|
||||
{
|
||||
alignas(64) uint8_t storage[(16*8*8) + (64 * 2)]; /* 1.2KB */
|
||||
unsigned char *table = storage;
|
||||
BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8),
|
||||
*temp = (BN_ULONG *)(table+16*8*8+8*8);
|
||||
int index;
|
||||
unsigned int wvalue;
|
||||
|
||||
/* table[0] = 1_inv */
|
||||
temp[0] = 0-m[0]; temp[1] = ~m[1];
|
||||
temp[2] = ~m[2]; temp[3] = ~m[3];
|
||||
temp[4] = ~m[4]; temp[5] = ~m[5];
|
||||
temp[6] = ~m[6]; temp[7] = ~m[7];
|
||||
rsaz_512_scatter4(table, temp, 0);
|
||||
|
||||
/* table [1] = a_inv^1 */
|
||||
rsaz_512_mul(a_inv, base, RR, m, k0);
|
||||
rsaz_512_scatter4(table, a_inv, 1);
|
||||
|
||||
/* table [2] = a_inv^2 */
|
||||
rsaz_512_sqr(temp, a_inv, m, k0, 1);
|
||||
rsaz_512_scatter4(table, temp, 2);
|
||||
|
||||
for (index=3; index<16; index++)
|
||||
rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index);
|
||||
|
||||
const uint8_t *p_str = (const uint8_t *)exponent;
|
||||
|
||||
/* load first window */
|
||||
wvalue = p_str[63];
|
||||
|
||||
rsaz_512_gather4(temp, table, wvalue>>4);
|
||||
rsaz_512_sqr(temp, temp, m, k0, 4);
|
||||
rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0xf);
|
||||
|
||||
for (index=62; index>=0; index--) {
|
||||
wvalue = p_str[index];
|
||||
|
||||
rsaz_512_sqr(temp, temp, m, k0, 4);
|
||||
rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue>>4);
|
||||
|
||||
rsaz_512_sqr(temp, temp, m, k0, 4);
|
||||
rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0x0f);
|
||||
}
|
||||
|
||||
/* from Montgomery */
|
||||
rsaz_512_mul_by_one(result, temp, m, k0);
|
||||
|
||||
OPENSSL_cleanse(storage,sizeof(storage));
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_X86_64 */
|
||||
|
||||
@@ -50,4 +50,7 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16],
|
||||
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0);
|
||||
int rsaz_avx2_eligible(void);
|
||||
|
||||
void RSAZ_512_mod_exp(BN_ULONG result[8],
|
||||
const BN_ULONG base_norm[8], const BN_ULONG exponent[8],
|
||||
const BN_ULONG m_norm[8], BN_ULONG k0, const BN_ULONG RR[8]);
|
||||
#endif
|
||||
|
||||
+1
-9
@@ -94,7 +94,7 @@ int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) {
|
||||
t[nw + i] = (l << lb) & BN_MASK2;
|
||||
}
|
||||
}
|
||||
OPENSSL_memset(t, 0, nw * sizeof(t[0]));
|
||||
memset(t, 0, nw * sizeof(t[0]));
|
||||
r->top = a->top + nw + 1;
|
||||
bn_correct_top(r);
|
||||
|
||||
@@ -182,10 +182,6 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) {
|
||||
}
|
||||
}
|
||||
|
||||
if (r->top == 0) {
|
||||
r->neg = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -219,10 +215,6 @@ int BN_rshift1(BIGNUM *r, const BIGNUM *a) {
|
||||
}
|
||||
r->top = j;
|
||||
|
||||
if (r->top == 0) {
|
||||
r->neg = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+5
-7
@@ -148,7 +148,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
}
|
||||
q->neg = 0;
|
||||
if (!BN_add_word(q, 1) ||
|
||||
!BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) {
|
||||
!BN_mod_exp(ret, A, q, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
err = 0;
|
||||
@@ -193,7 +193,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
goto end;
|
||||
}
|
||||
q->neg = 0;
|
||||
if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) {
|
||||
if (!BN_mod_exp(b, t, q, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
|
||||
/* Now that we have some non-square, we can find an element
|
||||
* of order 2^e by computing its q'th power. */
|
||||
if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) {
|
||||
if (!BN_mod_exp(y, y, q, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_one(y)) {
|
||||
@@ -327,7 +327,7 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) {
|
||||
if (!BN_mod_exp(x, A, t, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_zero(x)) {
|
||||
@@ -456,9 +456,7 @@ int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) {
|
||||
}
|
||||
|
||||
/* We estimate that the square root of an n-bit number is 2^{n/2}. */
|
||||
if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) {
|
||||
goto err;
|
||||
}
|
||||
BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2);
|
||||
|
||||
/* This is Newton's method for finding a root of the equation |estimate|^2 -
|
||||
* |in| = 0. */
|
||||
|
||||
+4
-6
@@ -61,8 +61,6 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
BUF_MEM *BUF_MEM_new(void) {
|
||||
BUF_MEM *ret;
|
||||
@@ -73,7 +71,7 @@ BUF_MEM *BUF_MEM_new(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memset(ret, 0, sizeof(BUF_MEM));
|
||||
memset(ret, 0, sizeof(BUF_MEM));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -139,7 +137,7 @@ static size_t buf_mem_grow(BUF_MEM *buf, size_t len, int clean) {
|
||||
return 0;
|
||||
}
|
||||
if (buf->length < len) {
|
||||
OPENSSL_memset(&buf->data[buf->length], 0, len - buf->length);
|
||||
memset(&buf->data[buf->length], 0, len - buf->length);
|
||||
}
|
||||
buf->length = len;
|
||||
return len;
|
||||
@@ -195,7 +193,7 @@ char *BUF_strndup(const char *buf, size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(ret, buf, size);
|
||||
memcpy(ret, buf, size);
|
||||
ret[size] = '\0';
|
||||
return ret;
|
||||
}
|
||||
@@ -236,6 +234,6 @@ void *BUF_memdup(const void *data, size_t dst_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(ret, data, dst_size);
|
||||
memcpy(ret, data, dst_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
@@ -43,7 +42,7 @@ int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
*outp = der;
|
||||
der = NULL;
|
||||
} else {
|
||||
OPENSSL_memcpy(*outp, der, der_len);
|
||||
memcpy(*outp, der, der_len);
|
||||
*outp += der_len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* kMaxDepth is a just a sanity limit. The code should be such that the length
|
||||
@@ -38,7 +37,7 @@ static int is_string_type(unsigned tag) {
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T61STRING:
|
||||
case CBS_ASN1_T16STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
@@ -101,7 +100,7 @@ static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
* |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
return header_len == 2 && CBS_len(contents) == 2 &&
|
||||
OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
|
||||
memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
|
||||
}
|
||||
|
||||
/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
namespace bssl {
|
||||
|
||||
static bool TestSkip() {
|
||||
static const uint8_t kData[] = {1, 2, 3};
|
||||
@@ -132,7 +133,7 @@ static bool TestGetASN1() {
|
||||
}
|
||||
if (!CBS_get_asn1(&data, &contents, 0x30) ||
|
||||
CBS_len(&contents) != 2 ||
|
||||
OPENSSL_memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
|
||||
memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -193,7 +194,7 @@ static bool TestGetASN1() {
|
||||
!CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
|
||||
!present ||
|
||||
CBS_len(&contents) != 3 ||
|
||||
OPENSSL_memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
|
||||
memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -230,25 +231,6 @@ static bool TestGetASN1() {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned tag;
|
||||
CBS_init(&data, kData1, sizeof(kData1));
|
||||
if (!CBS_get_any_asn1(&data, &contents, &tag) ||
|
||||
tag != CBS_ASN1_SEQUENCE ||
|
||||
CBS_len(&contents) != 2 ||
|
||||
OPENSSL_memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t header_len;
|
||||
CBS_init(&data, kData1, sizeof(kData1));
|
||||
if (!CBS_get_any_asn1_element(&data, &contents, &tag, &header_len) ||
|
||||
tag != CBS_ASN1_SEQUENCE ||
|
||||
header_len != 2 ||
|
||||
CBS_len(&contents) != 4 ||
|
||||
OPENSSL_memcmp(CBS_data(&contents), "\x30\x02\x01\x02", 2) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -312,12 +294,11 @@ static bool TestCBBBasic() {
|
||||
}
|
||||
|
||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||
return buf_len == sizeof(kExpected) &&
|
||||
OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
|
||||
return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
|
||||
}
|
||||
|
||||
static bool TestCBBFixed() {
|
||||
bssl::ScopedCBB cbb;
|
||||
ScopedCBB cbb;
|
||||
uint8_t buf[1];
|
||||
uint8_t *out_buf;
|
||||
size_t out_size;
|
||||
@@ -397,12 +378,11 @@ static bool TestCBBPrefixed() {
|
||||
}
|
||||
|
||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||
return buf_len == sizeof(kExpected) &&
|
||||
OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
|
||||
return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
|
||||
}
|
||||
|
||||
static bool TestCBBDiscardChild() {
|
||||
bssl::ScopedCBB cbb;
|
||||
ScopedCBB cbb;
|
||||
CBB contents, inner_contents, inner_inner_contents;
|
||||
|
||||
if (!CBB_init(cbb.get(), 0) ||
|
||||
@@ -447,8 +427,7 @@ static bool TestCBBDiscardChild() {
|
||||
0, 0, 3, 0xdd, 0xdd, 0xdd,
|
||||
1, 0xff,
|
||||
};
|
||||
return buf_len == sizeof(kExpected) &&
|
||||
OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
|
||||
return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
|
||||
}
|
||||
|
||||
static bool TestCBBMisuse() {
|
||||
@@ -487,7 +466,7 @@ static bool TestCBBMisuse() {
|
||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||
|
||||
if (buf_len != 3 ||
|
||||
OPENSSL_memcmp(buf, "\x01\x01\x02", 3) != 0) {
|
||||
memcmp(buf, "\x01\x01\x02", 3) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -510,8 +489,7 @@ static bool TestCBBASN1() {
|
||||
}
|
||||
bssl::UniquePtr<uint8_t> scoper(buf);
|
||||
|
||||
if (buf_len != sizeof(kExpected) ||
|
||||
OPENSSL_memcmp(buf, kExpected, buf_len) != 0) {
|
||||
if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -529,8 +507,8 @@ static bool TestCBBASN1() {
|
||||
scoper.reset(buf);
|
||||
|
||||
if (buf_len != 3 + 130 ||
|
||||
OPENSSL_memcmp(buf, "\x30\x81\x82", 3) != 0 ||
|
||||
OPENSSL_memcmp(buf + 3, test_data.data(), 130) != 0) {
|
||||
memcmp(buf, "\x30\x81\x82", 3) != 0 ||
|
||||
memcmp(buf + 3, test_data.data(), 130) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -546,8 +524,8 @@ static bool TestCBBASN1() {
|
||||
scoper.reset(buf);
|
||||
|
||||
if (buf_len != 4 + 1000 ||
|
||||
OPENSSL_memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
|
||||
OPENSSL_memcmp(buf + 4, test_data.data(), 1000)) {
|
||||
memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
|
||||
memcmp(buf + 4, test_data.data(), 1000)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -564,9 +542,8 @@ static bool TestCBBASN1() {
|
||||
scoper.reset(buf);
|
||||
|
||||
if (buf_len != 5 + 5 + 100000 ||
|
||||
OPENSSL_memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) !=
|
||||
0 ||
|
||||
OPENSSL_memcmp(buf + 10, test_data.data(), 100000)) {
|
||||
memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
|
||||
memcmp(buf + 10, test_data.data(), 100000)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -589,7 +566,7 @@ static bool DoBerConvert(const char *name,
|
||||
|
||||
if (out == NULL) {
|
||||
if (ber_len != der_len ||
|
||||
OPENSSL_memcmp(der_expected, ber, ber_len) != 0) {
|
||||
memcmp(der_expected, ber, ber_len) != 0) {
|
||||
fprintf(stderr, "%s: incorrect unconverted result.\n", name);
|
||||
return false;
|
||||
}
|
||||
@@ -598,7 +575,7 @@ static bool DoBerConvert(const char *name,
|
||||
}
|
||||
|
||||
if (out_len != der_len ||
|
||||
OPENSSL_memcmp(out, der_expected, der_len) != 0) {
|
||||
memcmp(out, der_expected, der_len) != 0) {
|
||||
fprintf(stderr, "%s: incorrect converted result.\n", name);
|
||||
return false;
|
||||
}
|
||||
@@ -707,7 +684,7 @@ static bool TestImplicitString() {
|
||||
}
|
||||
|
||||
if (ok && (CBS_len(&out) != test.out_len ||
|
||||
OPENSSL_memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
|
||||
memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
|
||||
fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
@@ -777,8 +754,7 @@ static bool TestASN1Uint64() {
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<uint8_t> scoper(out);
|
||||
if (len != test->encoding_len ||
|
||||
OPENSSL_memcmp(out, test->encoding, len) != 0) {
|
||||
if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -809,7 +785,7 @@ static bool TestCBBReserve() {
|
||||
uint8_t buf[10];
|
||||
uint8_t *ptr;
|
||||
size_t len;
|
||||
bssl::ScopedCBB cbb;
|
||||
ScopedCBB cbb;
|
||||
if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
|
||||
// Too large.
|
||||
CBB_reserve(cbb.get(), &ptr, 11)) {
|
||||
@@ -832,7 +808,7 @@ static bool TestCBBReserve() {
|
||||
|
||||
static bool TestStickyError() {
|
||||
// Write an input that exceeds the limit for its length prefix.
|
||||
bssl::ScopedCBB cbb;
|
||||
ScopedCBB cbb;
|
||||
CBB child;
|
||||
static const uint8_t kZeros[256] = {0};
|
||||
if (!CBB_init(cbb.get(), 0) ||
|
||||
@@ -895,83 +871,7 @@ static bool TestStickyError() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestBitString() {
|
||||
static const std::vector<uint8_t> kValidBitStrings[] = {
|
||||
{0x00}, // 0 bits
|
||||
{0x07, 0x80}, // 1 bit
|
||||
{0x04, 0xf0}, // 4 bits
|
||||
{0x00, 0xff}, // 8 bits
|
||||
{0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0}, // 42 bits
|
||||
};
|
||||
for (const auto& test : kValidBitStrings) {
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, test.data(), test.size());
|
||||
if (!CBS_is_valid_asn1_bitstring(&cbs)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const std::vector<uint8_t> kInvalidBitStrings[] = {
|
||||
// BIT STRINGs always have a leading byte.
|
||||
std::vector<uint8_t>{},
|
||||
// It's not possible to take an unused bit off the empty string.
|
||||
{0x01},
|
||||
// There can be at most 7 unused bits.
|
||||
{0x08, 0xff},
|
||||
{0xff, 0xff},
|
||||
// All unused bits must be cleared.
|
||||
{0x06, 0xff, 0xc1},
|
||||
};
|
||||
for (const auto& test : kInvalidBitStrings) {
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, test.data(), test.size());
|
||||
if (CBS_is_valid_asn1_bitstring(&cbs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// CBS_asn1_bitstring_has_bit returns false on invalid inputs.
|
||||
if (CBS_asn1_bitstring_has_bit(&cbs, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
std::vector<uint8_t> in;
|
||||
unsigned bit;
|
||||
bool bit_set;
|
||||
} kBitTests[] = {
|
||||
// Basic tests.
|
||||
{{0x00}, 0, false},
|
||||
{{0x07, 0x80}, 0, true},
|
||||
{{0x06, 0x0f, 0x40}, 0, false},
|
||||
{{0x06, 0x0f, 0x40}, 1, false},
|
||||
{{0x06, 0x0f, 0x40}, 2, false},
|
||||
{{0x06, 0x0f, 0x40}, 3, false},
|
||||
{{0x06, 0x0f, 0x40}, 4, true},
|
||||
{{0x06, 0x0f, 0x40}, 5, true},
|
||||
{{0x06, 0x0f, 0x40}, 6, true},
|
||||
{{0x06, 0x0f, 0x40}, 7, true},
|
||||
{{0x06, 0x0f, 0x40}, 8, false},
|
||||
{{0x06, 0x0f, 0x40}, 9, true},
|
||||
// Out-of-bounds bits return 0.
|
||||
{{0x06, 0x0f, 0x40}, 10, false},
|
||||
{{0x06, 0x0f, 0x40}, 15, false},
|
||||
{{0x06, 0x0f, 0x40}, 16, false},
|
||||
{{0x06, 0x0f, 0x40}, 1000, false},
|
||||
};
|
||||
for (const auto& test : kBitTests) {
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, test.in.data(), test.in.size());
|
||||
if (CBS_asn1_bitstring_has_bit(&cbs, test.bit) !=
|
||||
static_cast<int>(test.bit_set)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
static int Main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestSkip() ||
|
||||
@@ -992,11 +892,16 @@ int main() {
|
||||
!TestGetOptionalASN1Bool() ||
|
||||
!TestZero() ||
|
||||
!TestCBBReserve() ||
|
||||
!TestStickyError() ||
|
||||
!TestBitString()) {
|
||||
!TestStickyError()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace bssl
|
||||
|
||||
int main() {
|
||||
return bssl::Main();
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
void CBB_zero(CBB *cbb) {
|
||||
OPENSSL_memset(cbb, 0, sizeof(CBB));
|
||||
memset(cbb, 0, sizeof(CBB));
|
||||
}
|
||||
|
||||
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
|
||||
@@ -254,8 +252,8 @@ int CBB_flush(CBB *cbb) {
|
||||
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes,
|
||||
cbb->base->buf + child_start, len);
|
||||
memmove(cbb->base->buf + child_start + extra_bytes,
|
||||
cbb->base->buf + child_start, len);
|
||||
}
|
||||
cbb->base->buf[cbb->child->offset++] = initial_length_byte;
|
||||
cbb->child->pending_len_len = len_len - 1;
|
||||
@@ -305,8 +303,8 @@ static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memset(prefix_bytes, 0, len_len);
|
||||
OPENSSL_memset(out_contents, 0, sizeof(CBB));
|
||||
memset(prefix_bytes, 0, len_len);
|
||||
memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
cbb->child = out_contents;
|
||||
cbb->child->offset = offset;
|
||||
@@ -348,7 +346,7 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memset(out_contents, 0, sizeof(CBB));
|
||||
memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
cbb->child = out_contents;
|
||||
cbb->child->offset = offset;
|
||||
@@ -365,7 +363,7 @@ int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
|
||||
!cbb_buffer_add(cbb->base, &dest, len)) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(dest, data, len);
|
||||
memcpy(dest, data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+2
-54
@@ -20,7 +20,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
|
||||
@@ -77,7 +76,7 @@ int CBS_strdup(const CBS *cbs, char **out_ptr) {
|
||||
}
|
||||
|
||||
int CBS_contains_zero_byte(const CBS *cbs) {
|
||||
return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
|
||||
return memchr(cbs->data, 0, cbs->len) != NULL;
|
||||
}
|
||||
|
||||
int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
|
||||
@@ -151,7 +150,7 @@ int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
|
||||
if (!cbs_get(cbs, &v, len)) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(out, v, len);
|
||||
memcpy(out, v, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -263,20 +262,6 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
return CBS_get_bytes(cbs, out, len);
|
||||
}
|
||||
|
||||
int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag) {
|
||||
size_t header_len;
|
||||
if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CBS_skip(out, header_len)) {
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
size_t *out_header_len) {
|
||||
return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
|
||||
@@ -452,40 +437,3 @@ int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
|
||||
CBS in = *cbs;
|
||||
uint8_t num_unused_bits;
|
||||
if (!CBS_get_u8(&in, &num_unused_bits) ||
|
||||
num_unused_bits > 7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (num_unused_bits == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* All num_unused_bits bits must exist and be zeros. */
|
||||
uint8_t last;
|
||||
if (!CBS_get_last_u8(&in, &last) ||
|
||||
(last & ((1 << num_unused_bits) - 1)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
|
||||
if (!CBS_is_valid_asn1_bitstring(cbs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned byte_num = (bit >> 3) + 1;
|
||||
const unsigned bit_num = 7 - (bit & 7);
|
||||
|
||||
/* Unused bits are zero, and this function does not distinguish between
|
||||
* missing and unset bits. Thus it is sufficient to do a byte-level length
|
||||
* check. */
|
||||
return byte_num < CBS_len(cbs) &&
|
||||
(CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,17 @@ add_library(
|
||||
${CHACHA_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
add_executable(
|
||||
chacha_test
|
||||
|
||||
chacha_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(chacha_test crypto)
|
||||
add_dependencies(all_tests chacha_test)
|
||||
|
||||
perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl)
|
||||
perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl)
|
||||
perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl)
|
||||
perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl)
|
||||
perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl)
|
||||
@@ -8,7 +8,7 @@
|
||||
# ====================================================================
|
||||
#
|
||||
# December 2014
|
||||
#
|
||||
#
|
||||
# ChaCha20 for ARMv4.
|
||||
#
|
||||
# Performance in cycles per byte out of large buffer.
|
||||
@@ -713,7 +713,7 @@ ChaCha20_neon:
|
||||
vadd.i32 $d2,$d1,$t0 @ counter+2
|
||||
str @t[3], [sp,#4*(16+15)]
|
||||
mov @t[3],#10
|
||||
add @x[12],@x[12],#3 @ counter+3
|
||||
add @x[12],@x[12],#3 @ counter+3
|
||||
b .Loop_neon
|
||||
|
||||
.align 4
|
||||
@@ -1127,7 +1127,7 @@ $code.=<<___;
|
||||
ldrb @t[1],[r12],#1 @ read input
|
||||
subs @t[3],@t[3],#1
|
||||
eor @t[0],@t[0],@t[1]
|
||||
strb @t[0],[r14],#1 @ store output
|
||||
strb @t[0],[r14],#1 @ store ouput
|
||||
bne .Loop_tail_neon
|
||||
|
||||
.Ldone_neon:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# ====================================================================
|
||||
#
|
||||
# June 2015
|
||||
#
|
||||
#
|
||||
# ChaCha20 for ARMv8.
|
||||
#
|
||||
# Performance in cycles per byte out of large buffer.
|
||||
@@ -193,7 +193,7 @@ ChaCha20_ctr32:
|
||||
mov $ctr,#10
|
||||
subs $len,$len,#64
|
||||
.Loop:
|
||||
sub $ctr,$ctr,#1
|
||||
sub $ctr,$ctr,#1
|
||||
___
|
||||
foreach (&ROUND(0, 4, 8,12)) { eval; }
|
||||
foreach (&ROUND(0, 5,10,15)) { eval; }
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
# Westmere 9.50/+45% 3.35
|
||||
# Sandy Bridge 10.5/+47% 3.20
|
||||
# Haswell 8.15/+50% 2.83
|
||||
# Skylake 7.53/+22% 2.75
|
||||
# Silvermont 17.4/+36% 8.35
|
||||
# Goldmont 13.4/+40% 4.36
|
||||
# Sledgehammer 10.2/+54%
|
||||
# Bulldozer 13.4/+50% 4.38(*)
|
||||
#
|
||||
@@ -40,8 +38,10 @@ open STDOUT,">$output";
|
||||
|
||||
&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
|
||||
|
||||
$xmm=$ymm=1;
|
||||
$gasver=999; # enable everything
|
||||
$xmm=$ymm=0;
|
||||
for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
|
||||
|
||||
$ymm=$xmm;
|
||||
|
||||
$a="eax";
|
||||
($b,$b_)=("ebx","ebp");
|
||||
@@ -438,12 +438,6 @@ my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
|
||||
&label("pic_point"),"eax"));
|
||||
&movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce
|
||||
|
||||
if (defined($gasver) && $gasver>=2.17) { # even though we encode
|
||||
# pshufb manually, we
|
||||
# handle only register
|
||||
# operands, while this
|
||||
# segment uses memory
|
||||
# operand...
|
||||
&cmp ($len,64*4);
|
||||
&jb (&label("1x"));
|
||||
|
||||
@@ -625,7 +619,6 @@ if (defined($gasver) && $gasver>=2.17) { # even though we encode
|
||||
&paddd ("xmm2",&QWP(16*6,"eax")); # +four
|
||||
&pand ("xmm3",&QWP(16*7,"eax"));
|
||||
&por ("xmm3","xmm2"); # counter value
|
||||
}
|
||||
{
|
||||
my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7));
|
||||
|
||||
|
||||
+89
-1069
File diff suppressed because it is too large
Load Diff
@@ -96,7 +96,7 @@ static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
|
||||
uint32_t x[16];
|
||||
int i;
|
||||
|
||||
OPENSSL_memcpy(x, input, sizeof(uint32_t) * 16);
|
||||
memcpy(x, input, sizeof(uint32_t) * 16);
|
||||
for (i = 20; i > 0; i -= 2) {
|
||||
QUARTERROUND(0, 4, 8, 12)
|
||||
QUARTERROUND(1, 5, 9, 13)
|
||||
|
||||
@@ -18,14 +18,9 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/chacha.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static const uint8_t kKey[32] = {
|
||||
0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b,
|
||||
@@ -219,18 +214,35 @@ static const uint8_t kOutput[] = {
|
||||
static_assert(sizeof(kInput) == sizeof(kOutput),
|
||||
"Input and output lengths don't match.");
|
||||
|
||||
TEST(ChaChaTest, TestVector) {
|
||||
static bool TestChaCha20(size_t len) {
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
|
||||
CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
|
||||
if (memcmp(buf.get(), kOutput, len) != 0) {
|
||||
fprintf(stderr, "Mismatch at length %zu.\n", len);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place.
|
||||
memcpy(buf.get(), kInput, len);
|
||||
CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter);
|
||||
if (memcmp(buf.get(), kOutput, len) != 0) {
|
||||
fprintf(stderr, "Mismatch at length %zu, in-place.\n", len);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
// Run the test with the test vector at all lengths.
|
||||
for (size_t len = 0; len <= sizeof(kInput); len++) {
|
||||
SCOPED_TRACE(len);
|
||||
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
|
||||
CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
|
||||
EXPECT_EQ(Bytes(kOutput, len), Bytes(buf.get(), len));
|
||||
|
||||
// Test the in-place version.
|
||||
OPENSSL_memcpy(buf.get(), kInput, len);
|
||||
CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter);
|
||||
EXPECT_EQ(Bytes(kOutput, len), Bytes(buf.get(), len));
|
||||
if (!TestChaCha20(len)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
include_directories(../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CIPHER_ARCH_SOURCES
|
||||
|
||||
chacha20_poly1305_x86_64.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
cipher
|
||||
|
||||
@@ -27,8 +19,6 @@ add_library(
|
||||
tls_cbc.c
|
||||
e_tls.c
|
||||
e_ssl3.c
|
||||
|
||||
${CIPHER_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
add_executable(
|
||||
@@ -45,8 +35,6 @@ add_executable(
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
perlasm(chacha20_poly1305_x86_64.${ASM_EXT} asm/chacha20_poly1305_x86_64.pl)
|
||||
|
||||
target_link_libraries(cipher_test crypto)
|
||||
target_link_libraries(aead_test crypto)
|
||||
add_dependencies(all_tests cipher_test aead_test)
|
||||
|
||||
@@ -32,7 +32,7 @@ size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead) { return aead->overhead; }
|
||||
size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
|
||||
|
||||
void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_AEAD_CTX));
|
||||
memset(ctx, 0, sizeof(EVP_AEAD_CTX));
|
||||
}
|
||||
|
||||
int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
|
||||
@@ -116,7 +116,7 @@ int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
error:
|
||||
/* In the event of an error, clear the output buffer so that a caller
|
||||
* that doesn't check the return value doesn't send raw data. */
|
||||
OPENSSL_memset(out, 0, max_out_len);
|
||||
memset(out, 0, max_out_len);
|
||||
*out_len = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ error:
|
||||
/* In the event of an error, clear the output buffer so that a caller
|
||||
* that doesn't check the return value doesn't try and process bad
|
||||
* data. */
|
||||
OPENSSL_memset(out, 0, max_out_len);
|
||||
memset(out, 0, max_out_len);
|
||||
*out_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+48
-134
@@ -12,7 +12,6 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -22,18 +21,9 @@
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
|
||||
|
||||
#if defined(OPENSSL_SMALL)
|
||||
const EVP_AEAD* EVP_aead_aes_128_gcm_siv(void) {
|
||||
return nullptr;
|
||||
}
|
||||
const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
namespace bssl {
|
||||
|
||||
// This program tests an AEAD against a series of test vectors from a file,
|
||||
// using the FileTest format. As an example, here's a valid test case:
|
||||
@@ -58,7 +48,7 @@ static bool TestAEAD(FileTest *t, void *arg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_seal)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
@@ -88,8 +78,8 @@ static bool TestAEAD(FileTest *t, void *arg) {
|
||||
}
|
||||
} else {
|
||||
out.resize(ct.size() + tag.size());
|
||||
OPENSSL_memcpy(out.data(), ct.data(), ct.size());
|
||||
OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
|
||||
memcpy(out.data(), ct.data(), ct.size());
|
||||
memcpy(out.data() + ct.size(), tag.data(), tag.size());
|
||||
}
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
@@ -169,12 +159,16 @@ static bool TestAEAD(FileTest *t, void *arg) {
|
||||
}
|
||||
|
||||
static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
assert(sizeof(key) >= key_len);
|
||||
|
||||
EVP_AEAD_CTX ctx;
|
||||
uint8_t key[128];
|
||||
|
||||
memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
if (key_len > sizeof(key)) {
|
||||
fprintf(stderr, "Key length of AEAD too long.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */,
|
||||
NULL /* ENGINE */) != 0) {
|
||||
@@ -198,87 +192,13 @@ static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TestTruncatedTags(const EVP_AEAD *aead) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
assert(sizeof(key) >= key_len);
|
||||
|
||||
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
|
||||
OPENSSL_memset(nonce, 0, sizeof(nonce));
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
assert(sizeof(nonce) >= nonce_len);
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key, key_len, 1 /* one byte tag */,
|
||||
NULL /* ENGINE */)) {
|
||||
fprintf(stderr, "Couldn't initialise AEAD with truncated tag.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t plaintext[1] = {'A'};
|
||||
|
||||
uint8_t ciphertext[128];
|
||||
size_t ciphertext_len;
|
||||
constexpr uint8_t kSentinel = 42;
|
||||
OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
|
||||
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
|
||||
sizeof(ciphertext), nonce, nonce_len, plaintext,
|
||||
sizeof(plaintext), nullptr /* ad */, 0)) {
|
||||
fprintf(stderr, "Sealing with truncated tag didn't work.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
|
||||
// Sealing must not write past where it said it did.
|
||||
if (ciphertext[i] != kSentinel) {
|
||||
fprintf(stderr, "Sealing wrote off the end of the buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t overhead_used = ciphertext_len - sizeof(plaintext);
|
||||
if (overhead_used != 1) {
|
||||
fprintf(stderr, "AEAD is probably ignoring request to truncate tags.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t plaintext2[sizeof(plaintext) + 16];
|
||||
OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
|
||||
|
||||
size_t plaintext2_len;
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), plaintext2, &plaintext2_len,
|
||||
sizeof(plaintext2), nonce, nonce_len, ciphertext,
|
||||
ciphertext_len, nullptr /* ad */, 0)) {
|
||||
fprintf(stderr, "Opening with truncated tag didn't work.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
|
||||
// Likewise, opening should also stay within bounds.
|
||||
if (plaintext2[i] != kSentinel) {
|
||||
fprintf(stderr, "Opening wrote off the end of the buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (plaintext2_len != sizeof(plaintext) ||
|
||||
OPENSSL_memcmp(plaintext2, plaintext, sizeof(plaintext)) != 0) {
|
||||
fprintf(stderr, "Opening with truncated tag gave wrong result.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
const size_t max_overhead = EVP_AEAD_max_overhead(aead);
|
||||
|
||||
std::vector<uint8_t> key(key_len, 'a');
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
|
||||
return false;
|
||||
@@ -311,7 +231,7 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
uint8_t *out1 = buffer.data();
|
||||
uint8_t *out2 = buffer.data() + 2;
|
||||
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
size_t out_len;
|
||||
if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
@@ -324,7 +244,7 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0) ||
|
||||
@@ -337,7 +257,7 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
ERR_clear_error();
|
||||
|
||||
// Test with out == in, which we expect to work.
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
@@ -347,12 +267,12 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
}
|
||||
|
||||
if (out_len != valid_encryption_len ||
|
||||
OPENSSL_memcmp(in, valid_encryption.data(), out_len) != 0) {
|
||||
memcmp(in, valid_encryption.data(), out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0)) {
|
||||
@@ -361,7 +281,7 @@ static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
}
|
||||
|
||||
if (out_len != sizeof(kPlaintext) ||
|
||||
OPENSSL_memcmp(in, kPlaintext, out_len) != 0) {
|
||||
memcmp(in, kPlaintext, out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -377,35 +297,33 @@ struct KnownAEAD {
|
||||
// handle inputs that are a multiple of eight bytes in length and the
|
||||
// SSLv3/TLS AEADs have the concept of “direction”.
|
||||
bool limited_implementation;
|
||||
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
|
||||
// lengths.
|
||||
bool truncated_tags;
|
||||
};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false, true },
|
||||
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false, true },
|
||||
{ "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false, false },
|
||||
{ "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false, false },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false, true },
|
||||
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true, false },
|
||||
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true, false },
|
||||
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true, false },
|
||||
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true, false },
|
||||
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true, false },
|
||||
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true, false },
|
||||
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true, false },
|
||||
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true, false },
|
||||
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true, false },
|
||||
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false, true },
|
||||
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false, true },
|
||||
{ "", NULL, false, false },
|
||||
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false },
|
||||
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
|
||||
{ "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
|
||||
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
|
||||
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true },
|
||||
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true },
|
||||
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true },
|
||||
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true },
|
||||
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true },
|
||||
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true },
|
||||
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true },
|
||||
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true },
|
||||
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true },
|
||||
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true },
|
||||
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true },
|
||||
{ "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true },
|
||||
{ "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true },
|
||||
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false },
|
||||
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false },
|
||||
{ "", NULL, false },
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
static int Main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 3) {
|
||||
@@ -426,21 +344,11 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
const EVP_AEAD *const aead = known_aead->func();
|
||||
if (aead == NULL) {
|
||||
// AEAD is not compiled in this configuration.
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!TestCleanupAfterInitFailure(aead)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (known_aead->truncated_tags && !TestTruncatedTags(aead)) {
|
||||
fprintf(stderr, "Truncated tags test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
|
||||
fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
@@ -448,3 +356,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
|
||||
}
|
||||
|
||||
} // namespace bssl
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return bssl::Main(argc, argv);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user