Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 907ae62b9d | |||
| 65be20fe2f | |||
| ab441a3a39 |
@@ -1,7 +0,0 @@
|
||||
Please do not send pull requests to the BoringSSL repository.
|
||||
|
||||
We do, however, take contributions gladly.
|
||||
|
||||
See https://boringssl.googlesource.com/boringssl/+/master/CONTRIBUTING.md
|
||||
|
||||
Thanks!
|
||||
+18
-16
@@ -2,18 +2,14 @@
|
||||
|
||||
## Build Prerequisites
|
||||
|
||||
* [CMake](https://cmake.org/download/) 2.8.8 or later is required.
|
||||
* [CMake](http://www.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
|
||||
reported to work, as has MSYS Perl.
|
||||
[Strawberry Perl](http://strawberryperl.com/) also works but it adds GCC
|
||||
to `PATH`, which can confuse some build tools when identifying the compiler
|
||||
(removing `C:\Strawberry\c\bin` from `PATH` should resolve any problems).
|
||||
If Perl is not found by CMake, it may be configured explicitly by setting
|
||||
`PERL_EXECUTABLE`.
|
||||
[Strawberry Perl](http://strawberryperl.com/) and MSYS Perl have both been
|
||||
reported to work. If not found by CMake, it may be configured explicitly by
|
||||
setting `PERL_EXECUTABLE`.
|
||||
|
||||
* On Windows you currently must use [Ninja](https://ninja-build.org/)
|
||||
* On Windows you currently must use [Ninja](https://martine.github.io/ninja/)
|
||||
to build; on other platforms, it is not required, but recommended, because
|
||||
it makes builds faster.
|
||||
|
||||
@@ -25,12 +21,22 @@
|
||||
`CMAKE_ASM_NASM_COMPILER`.
|
||||
|
||||
* A C compiler is required. On Windows, MSVC 12 (Visual Studio 2013) or later
|
||||
with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+)
|
||||
and Clang should work on non-Windows platforms, and maybe on Windows too.
|
||||
with Platform SDK 8.1 or later are supported. Recent versions of GCC and
|
||||
Clang should work on non-Windows platforms, and maybe on Windows too.
|
||||
|
||||
* [Go](https://golang.org/dl/) is required. If not found by CMake, the go
|
||||
executable may be configured explicitly by setting `GO_EXECUTABLE`.
|
||||
|
||||
* If you change crypto/chacha/chacha\_vec.c, you will need the
|
||||
arm-linux-gnueabihf-gcc compiler:
|
||||
|
||||
```
|
||||
wget https://releases.linaro.org/14.11/components/toolchain/binaries/arm-linux-gnueabihf/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz && \
|
||||
echo bc4ca2ced084d2dc12424815a4442e19cb1422db87068830305d90075feb1a3b gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz | sha256sum -c && \
|
||||
tar xf gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz && \
|
||||
sudo mv gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf /opt/
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
Using Ninja (note the 'N' is capitalized in the cmake invocation):
|
||||
@@ -52,8 +58,7 @@ files because the build scripts will detect changes to them and rebuild
|
||||
themselves automatically.
|
||||
|
||||
Note that the default build flags in the top-level `CMakeLists.txt` are for
|
||||
debugging—optimisation isn't enabled. Pass `-DCMAKE_BUILD_TYPE=Release` to
|
||||
`cmake` to configure a release build.
|
||||
debugging—optimisation isn't enabled.
|
||||
|
||||
If you want to cross-compile then there is an example toolchain file for 32-bit
|
||||
Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like
|
||||
@@ -70,9 +75,6 @@ In order to serve environments where code-size is important as well as those
|
||||
where performance is the overriding concern, `OPENSSL_SMALL` can be defined to
|
||||
remove some code that is especially large.
|
||||
|
||||
See [CMake's documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-variables.7.html)
|
||||
for other variables which may be used to configure the build.
|
||||
|
||||
### Building for Android
|
||||
|
||||
It's possible to build BoringSSL with the Android NDK using CMake. This has
|
||||
|
||||
+7
-37
@@ -1,16 +1,6 @@
|
||||
cmake_minimum_required (VERSION 2.8.10)
|
||||
|
||||
# Defer enabling C and CXX languages.
|
||||
project (BoringSSL NONE)
|
||||
|
||||
if(WIN32)
|
||||
# On Windows, prefer cl over gcc if both are available. By default most of
|
||||
# the CMake generators prefer gcc, even on Windows.
|
||||
set(CMAKE_GENERATOR_CC cl)
|
||||
endif()
|
||||
|
||||
enable_language(C)
|
||||
enable_language(CXX)
|
||||
project (BoringSSL)
|
||||
|
||||
if(ANDROID)
|
||||
# Android-NDK CMake files reconfigure the path and so Go and Perl won't be
|
||||
@@ -27,9 +17,8 @@ if (NOT GO_EXECUTABLE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${C_CXX_FLAGS} -Wmissing-declarations")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -std=c++0x -fvisibility=hidden")
|
||||
elseif(MSVC)
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
"C4100" # 'exarg' : unreferenced formal parameter
|
||||
@@ -71,25 +60,10 @@ elseif(MSVC)
|
||||
"C4996" # 'read': The POSIX name for this item is deprecated. Instead,
|
||||
# use the ISO C++ conformant name: _read.
|
||||
)
|
||||
if(NOT(CMAKE_C_COMPILER_VERSION VERSION_LESS "19.0.23506"))
|
||||
# MSVC 2015 Update 1.
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
${MSVC_DISABLED_WARNINGS_LIST}
|
||||
"C4464" # relative include path contains '..'
|
||||
"C4623" # default constructor was implicitly defined as deleted
|
||||
"C5027" # move assignment operator was implicitly defined as deleted
|
||||
)
|
||||
set(MSVC_LEVEL4_WARNINGS_LIST
|
||||
# See https://connect.microsoft.com/VisualStudio/feedback/details/1217660/warning-c4265-when-using-functional-header
|
||||
"C4265" # class has virtual functions, but destructor is not virtual
|
||||
)
|
||||
string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR
|
||||
${MSVC_LEVEL4_WARNINGS_LIST})
|
||||
endif()
|
||||
string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
|
||||
${MSVC_DISABLED_WARNINGS_LIST})
|
||||
set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
|
||||
set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
|
||||
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-DNOMINMAX)
|
||||
@@ -111,11 +85,8 @@ if(FUZZ)
|
||||
message("You need to build with Clang for fuzzing to work")
|
||||
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")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||
link_directories(.)
|
||||
endif()
|
||||
@@ -202,7 +173,6 @@ add_custom_target(
|
||||
${CMAKE_BINARY_DIR}
|
||||
COMMAND cd ssl/test/runner
|
||||
COMMAND ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
|
||||
${RUNNER_ARGS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
DEPENDS all_tests bssl_shim
|
||||
${MAYBE_USES_TERMINAL})
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
Want to contribute? Great! First, read this page (including the small print at the end).
|
||||
|
||||
### Before you contribute
|
||||
Before we can use your code, you must sign the
|
||||
[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
|
||||
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
||||
copyright to your changes, even after your contribution becomes part of our
|
||||
codebase, so we need your permission to use and distribute your code. We also
|
||||
need to be sure of various other things—for instance that you'll tell us if you
|
||||
know that your code infringes on other people's patents. You don't have to sign
|
||||
the CLA until after you've submitted your code for review and a member has
|
||||
approved it, but you must do it before we can put your code into our codebase.
|
||||
Before you start working on a larger contribution, you should get in touch with
|
||||
us first via email with your idea so that we can help out and possibly guide
|
||||
you. Coordinating up front makes it much easier to avoid frustration later on.
|
||||
|
||||
### Code reviews
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use [Gerrit](https://boringssl-review.googlesource.com) for this purpose.
|
||||
|
||||
#### Setup
|
||||
If you have not done so on this machine, you will need to set up a password for
|
||||
Gerrit. Sign in with a Google account, visit
|
||||
[this link](https://boringssl.googlesource.com/), and click the "Generate
|
||||
Password" link in the top right. You will also need to prepare your checkout to
|
||||
[add Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html)
|
||||
on commit. Run:
|
||||
|
||||
curl -Lo .git/hooks/commit-msg https://boringssl-review.googlesource.com/tools/hooks/commit-msg
|
||||
chmod u+x .git/hooks/commit-msg
|
||||
|
||||
#### Uploading changes
|
||||
To upload a change, push it to the special `refs/for/master` target:
|
||||
|
||||
git push origin HEAD:refs/for/master
|
||||
|
||||
The output will then give you a link to the change. Add `agl@google.com` and
|
||||
`davidben@google.com` as reviewers.
|
||||
|
||||
Pushing a commit with the same Change-Id as an existing change will upload a new
|
||||
version of it. (Use the `git rebase` or `git commit --amend` commands.)
|
||||
|
||||
For more detailed instructions, see the
|
||||
[Gerrit User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html).
|
||||
|
||||
### The small print
|
||||
Contributions made by corporations are covered by a different agreement than
|
||||
the one above, the
|
||||
[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
|
||||
+12
-23
@@ -13,9 +13,9 @@ CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 ..
|
||||
In order for the fuzz tests to link, the linker needs to find libFuzzer. This is not commonly provided and you may need to download the [Clang source code](http://llvm.org/releases/download.html) and do the following:
|
||||
|
||||
```
|
||||
svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
|
||||
clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
|
||||
ar ruv libFuzzer.a Fuzzer*.o
|
||||
cd llvm-3.7.0.src/lib
|
||||
clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
|
||||
ar q libFuzzer.a *.o
|
||||
```
|
||||
|
||||
Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory.
|
||||
@@ -23,29 +23,18 @@ 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=3072 -jobs=32 -workers=32 ../fuzz/cert_corpus/
|
||||
./fuzz/cert -max_len=4000 -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 may be found in `.options` files alongside the test source. These were determined by rounding up the length of the largest case in the corpus. When writing a new fuzzer, configure `max_len` in a similar file.
|
||||
The `max_len` argument is often important because, without it, libFuzzer defaults to limiting all test cases to 64 bytes, which is often insufficient for the formats that we wish to fuzz. The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing.
|
||||
|
||||
There are directories in `fuzz/` for each of the fuzzing tests which contain seed files for fuzzing. Some of the seed files were generated manually but many of them are “interesting” results generated by the fuzzing itself. (Where “interesting” means that it triggered a previously unknown path in the code.)
|
||||
|
||||
## Minimising the corpuses
|
||||
Here are the recommended values of `max_len` for each test.
|
||||
|
||||
When a large number of new seeds are available, it's a good idea to minimise the corpus so that different seeds that trigger the same code paths can be deduplicated.
|
||||
|
||||
In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimise_corpuses.sh`. Note that minimisation is, oddly, often not idempotent for unknown reasons.
|
||||
|
||||
## Fuzzer mode
|
||||
|
||||
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.
|
||||
|
||||
* 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.
|
||||
|
||||
This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol.
|
||||
| Test | `max_len` value |
|
||||
|-----------|-----------------|
|
||||
| `privkey` | 2048 |
|
||||
| `cert` | 3072 |
|
||||
| `server` | 1024 |
|
||||
| `client` | 4096 |
|
||||
|
||||
@@ -14,13 +14,6 @@ for the actual license texts. Actually both licenses are BSD-style Open Source
|
||||
licenses. In case of any license issues related to OpenSSL please contact
|
||||
openssl-core@openssl.org.
|
||||
|
||||
The following are Google-internal bug numbers where explicit permission from
|
||||
some authors is recorded for use of their work. (This is purely for our own
|
||||
record keeping.)
|
||||
27287199
|
||||
27287880
|
||||
27287883
|
||||
|
||||
OpenSSL License
|
||||
---------------
|
||||
|
||||
|
||||
-23
@@ -130,23 +130,6 @@ BoringSSL's `BN_bn2hex` function uses lowercase hexadecimal digits instead of
|
||||
uppercase. Some code may require changes to avoid being sensitive to this
|
||||
difference.
|
||||
|
||||
### Legacy ASN.1 functions
|
||||
|
||||
OpenSSL's ASN.1 stack uses `d2i` functions for parsing. They have the form:
|
||||
|
||||
RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
|
||||
|
||||
In addition to returning the result, OpenSSL places it in `*out` if `out` is
|
||||
not `NULL`. On input, if `*out` is not `NULL`, OpenSSL will usually (but not
|
||||
always) reuse that object rather than allocating a new one. In BoringSSL, these
|
||||
functions are compatibility wrappers over a newer ASN.1 stack. Even if `*out`
|
||||
is not `NULL`, these wrappers will always allocate a new object and free the
|
||||
previous one.
|
||||
|
||||
Ensure that callers do not rely on this object reuse behavior. It is
|
||||
recommended to avoid the `out` parameter completely and always pass in `NULL`.
|
||||
Note that less error-prone APIs are available for BoringSSL-specific code (see
|
||||
below).
|
||||
|
||||
## Optional BoringSSL-specific simplifications
|
||||
|
||||
@@ -179,9 +162,3 @@ locks. Without initializing these, the library is not thread-safe. Configuring
|
||||
these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the
|
||||
corresponding Windows APIs internally and is always thread-safe where the API
|
||||
guarantees it.
|
||||
|
||||
### ASN.1
|
||||
|
||||
BoringSSL is in the process of deprecating OpenSSL's `d2i` and `i2d` in favor of
|
||||
new functions using the much less error-prone `CBS` and `CBB` types.
|
||||
BoringSSL-only code should use those functions where available.
|
||||
|
||||
@@ -28,4 +28,3 @@ There are other files in this directory which might be helpful:
|
||||
* [STYLE.md](/STYLE.md): rules and guidelines for coding style.
|
||||
* include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
|
||||
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
|
||||
* [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.
|
||||
|
||||
+35
-5
@@ -22,7 +22,6 @@ elseif(UNIX)
|
||||
endif()
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
|
||||
else()
|
||||
if (CMAKE_CL_64)
|
||||
message("Using nasm")
|
||||
@@ -54,6 +53,39 @@ function(perlasm dest src)
|
||||
)
|
||||
endfunction()
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-intel.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-intel.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-arm.c
|
||||
cpu-arm-asm.S
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-arm.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# Level 0.1 - depends on nothing outside this set.
|
||||
add_subdirectory(stack)
|
||||
add_subdirectory(lhash)
|
||||
@@ -111,10 +143,6 @@ add_subdirectory(test)
|
||||
add_library(
|
||||
crypto
|
||||
|
||||
cpu-aarch64-linux.c
|
||||
cpu-arm.c
|
||||
cpu-arm-linux.c
|
||||
cpu-intel.c
|
||||
crypto.c
|
||||
directory_posix.c
|
||||
directory_win.c
|
||||
@@ -128,6 +156,8 @@ add_library(
|
||||
thread_win.c
|
||||
time_support.c
|
||||
|
||||
${CRYPTO_ARCH_SOURCES}
|
||||
|
||||
$<TARGET_OBJECTS:stack>
|
||||
$<TARGET_OBJECTS:lhash>
|
||||
$<TARGET_OBJECTS:err>
|
||||
|
||||
@@ -191,6 +191,7 @@ AES_Te:
|
||||
@ void asm_AES_encrypt(const unsigned char *in, unsigned char *out,
|
||||
@ const AES_KEY *key) {
|
||||
.global asm_AES_encrypt
|
||||
.hidden asm_AES_encrypt
|
||||
.type asm_AES_encrypt,%function
|
||||
.align 5
|
||||
asm_AES_encrypt:
|
||||
@@ -440,6 +441,7 @@ _armv4_AES_encrypt:
|
||||
.size _armv4_AES_encrypt,.-_armv4_AES_encrypt
|
||||
|
||||
.global asm_AES_set_encrypt_key
|
||||
.hidden asm_AES_set_encrypt_key
|
||||
.type asm_AES_set_encrypt_key,%function
|
||||
.align 5
|
||||
asm_AES_set_encrypt_key:
|
||||
@@ -746,6 +748,7 @@ _armv4_AES_set_encrypt_key:
|
||||
.size asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
|
||||
|
||||
.global asm_AES_set_decrypt_key
|
||||
.hidden asm_AES_set_decrypt_key
|
||||
.type asm_AES_set_decrypt_key,%function
|
||||
.align 5
|
||||
asm_AES_set_decrypt_key:
|
||||
@@ -762,6 +765,7 @@ asm_AES_set_decrypt_key:
|
||||
|
||||
@ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
|
||||
.global AES_set_enc2dec_key
|
||||
.hidden AES_set_enc2dec_key
|
||||
.type AES_set_enc2dec_key,%function
|
||||
.align 5
|
||||
AES_set_enc2dec_key:
|
||||
@@ -967,6 +971,7 @@ AES_Td:
|
||||
@ void asm_AES_decrypt(const unsigned char *in, unsigned char *out,
|
||||
@ const AES_KEY *key) {
|
||||
.global asm_AES_decrypt
|
||||
.hidden asm_AES_decrypt
|
||||
.type asm_AES_decrypt,%function
|
||||
.align 5
|
||||
asm_AES_decrypt:
|
||||
|
||||
@@ -1006,6 +1006,7 @@ if (0) { # following four functions are unsupported interface
|
||||
# used for benchmarking...
|
||||
$code.=<<___;
|
||||
.globl bsaes_enc_key_convert
|
||||
.hidden bsaes_enc_key_convert
|
||||
.type bsaes_enc_key_convert,%function
|
||||
.align 4
|
||||
bsaes_enc_key_convert:
|
||||
@@ -1024,6 +1025,7 @@ bsaes_enc_key_convert:
|
||||
.size bsaes_enc_key_convert,.-bsaes_enc_key_convert
|
||||
|
||||
.globl bsaes_encrypt_128
|
||||
.hidden bsaes_encrypt_128
|
||||
.type bsaes_encrypt_128,%function
|
||||
.align 4
|
||||
bsaes_encrypt_128:
|
||||
@@ -1054,6 +1056,7 @@ bsaes_encrypt_128:
|
||||
.size bsaes_encrypt_128,.-bsaes_encrypt_128
|
||||
|
||||
.globl bsaes_dec_key_convert
|
||||
.hidden bsaes_dec_key_convert
|
||||
.type bsaes_dec_key_convert,%function
|
||||
.align 4
|
||||
bsaes_dec_key_convert:
|
||||
@@ -1074,6 +1077,7 @@ bsaes_dec_key_convert:
|
||||
.size bsaes_dec_key_convert,.-bsaes_dec_key_convert
|
||||
|
||||
.globl bsaes_decrypt_128
|
||||
.hidden bsaes_decrypt_128
|
||||
.type bsaes_decrypt_128,%function
|
||||
.align 4
|
||||
bsaes_decrypt_128:
|
||||
@@ -1113,6 +1117,7 @@ $code.=<<___;
|
||||
.extern AES_decrypt
|
||||
|
||||
.global bsaes_cbc_encrypt
|
||||
.hidden bsaes_cbc_encrypt
|
||||
.type bsaes_cbc_encrypt,%function
|
||||
.align 5
|
||||
bsaes_cbc_encrypt:
|
||||
@@ -1388,6 +1393,7 @@ my $keysched = "sp";
|
||||
$code.=<<___;
|
||||
.extern AES_encrypt
|
||||
.global bsaes_ctr32_encrypt_blocks
|
||||
.hidden bsaes_ctr32_encrypt_blocks
|
||||
.type bsaes_ctr32_encrypt_blocks,%function
|
||||
.align 5
|
||||
bsaes_ctr32_encrypt_blocks:
|
||||
@@ -1629,6 +1635,7 @@ my @T=@XMM[6..7];
|
||||
|
||||
$code.=<<___;
|
||||
.globl bsaes_xts_encrypt
|
||||
.hidden bsaes_xts_encrypt
|
||||
.type bsaes_xts_encrypt,%function
|
||||
.align 4
|
||||
bsaes_xts_encrypt:
|
||||
@@ -2043,6 +2050,7 @@ $code.=<<___;
|
||||
.size bsaes_xts_encrypt,.-bsaes_xts_encrypt
|
||||
|
||||
.globl bsaes_xts_decrypt
|
||||
.hidden bsaes_xts_decrypt
|
||||
.type bsaes_xts_decrypt,%function
|
||||
.align 4
|
||||
bsaes_xts_decrypt:
|
||||
|
||||
@@ -32,6 +32,7 @@ add_library(
|
||||
f_int.c
|
||||
f_string.c
|
||||
t_bitst.c
|
||||
t_pkey.c
|
||||
tasn_dec.c
|
||||
tasn_enc.c
|
||||
tasn_fre.c
|
||||
|
||||
+158
-166
@@ -33,7 +33,7 @@
|
||||
* 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
|
||||
* 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)"
|
||||
*
|
||||
@@ -61,203 +61,195 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
{
|
||||
return M_ASN1_BIT_STRING_set(x, d, len);
|
||||
}
|
||||
{ return M_ASN1_BIT_STRING_set(x, d, len); }
|
||||
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
{
|
||||
int ret, j, bits, len;
|
||||
unsigned char *p, *d;
|
||||
{
|
||||
int ret,j,bits,len;
|
||||
unsigned char *p,*d;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a == NULL) return(0);
|
||||
|
||||
len = a->length;
|
||||
len=a->length;
|
||||
|
||||
if (len > 0) {
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
|
||||
bits = (int)a->flags & 0x07;
|
||||
} else {
|
||||
for (; len > 0; len--) {
|
||||
if (a->data[len - 1])
|
||||
break;
|
||||
}
|
||||
j = a->data[len - 1];
|
||||
if (j & 0x01)
|
||||
bits = 0;
|
||||
else if (j & 0x02)
|
||||
bits = 1;
|
||||
else if (j & 0x04)
|
||||
bits = 2;
|
||||
else if (j & 0x08)
|
||||
bits = 3;
|
||||
else if (j & 0x10)
|
||||
bits = 4;
|
||||
else if (j & 0x20)
|
||||
bits = 5;
|
||||
else if (j & 0x40)
|
||||
bits = 6;
|
||||
else if (j & 0x80)
|
||||
bits = 7;
|
||||
else
|
||||
bits = 0; /* should not happen */
|
||||
}
|
||||
} else
|
||||
bits = 0;
|
||||
if (len > 0)
|
||||
{
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
|
||||
{
|
||||
bits=(int)a->flags&0x07;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ; len > 0; len--)
|
||||
{
|
||||
if (a->data[len-1]) break;
|
||||
}
|
||||
j=a->data[len-1];
|
||||
if (j & 0x01) bits=0;
|
||||
else if (j & 0x02) bits=1;
|
||||
else if (j & 0x04) bits=2;
|
||||
else if (j & 0x08) bits=3;
|
||||
else if (j & 0x10) bits=4;
|
||||
else if (j & 0x20) bits=5;
|
||||
else if (j & 0x40) bits=6;
|
||||
else if (j & 0x80) bits=7;
|
||||
else bits=0; /* should not happen */
|
||||
}
|
||||
}
|
||||
else
|
||||
bits=0;
|
||||
|
||||
ret = 1 + len;
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
ret=1+len;
|
||||
if (pp == NULL) return(ret);
|
||||
|
||||
p = *pp;
|
||||
p= *pp;
|
||||
|
||||
*(p++) = (unsigned char)bits;
|
||||
d = a->data;
|
||||
memcpy(p, d, len);
|
||||
p += len;
|
||||
if (len > 0)
|
||||
p[-1] &= (0xff << bits);
|
||||
*pp = p;
|
||||
return (ret);
|
||||
}
|
||||
*(p++)=(unsigned char)bits;
|
||||
d=a->data;
|
||||
memcpy(p,d,len);
|
||||
p+=len;
|
||||
if (len > 0) p[-1]&=(0xff<<bits);
|
||||
*pp=p;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
|
||||
const unsigned char **pp, long len)
|
||||
{
|
||||
ASN1_BIT_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
int padding;
|
||||
const unsigned char **pp, long len)
|
||||
{
|
||||
ASN1_BIT_STRING *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
int padding;
|
||||
|
||||
if (len < 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
if (len < 1)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL);
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
|
||||
p = *pp;
|
||||
padding = *(p++);
|
||||
if (padding > 7) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
goto err;
|
||||
}
|
||||
p= *pp;
|
||||
padding = *(p++);
|
||||
if (padding > 7)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do this to preserve the settings. If we modify the settings, via
|
||||
* the _set_bit function, we will recalculate on output
|
||||
*/
|
||||
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
|
||||
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */
|
||||
/* We do this to preserve the settings. If we modify
|
||||
* the settings, via the _set_bit function, we will recalculate
|
||||
* on output */
|
||||
ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
|
||||
ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|padding); /* set */
|
||||
|
||||
if (len-- > 1) { /* using one because of the bits left byte */
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len);
|
||||
if (s == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
s[len - 1] &= (0xff << padding);
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
if (len-- > 1) /* using one because of the bits left byte */
|
||||
{
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len);
|
||||
if (s == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
s[len-1]&=(0xff<<padding);
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
s=NULL;
|
||||
|
||||
ret->length = (int)len;
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->type = V_ASN1_BIT_STRING;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_BIT_STRING_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length=(int)len;
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->data=s;
|
||||
ret->type=V_ASN1_BIT_STRING;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_BIT_STRING_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
|
||||
/* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
|
||||
*/
|
||||
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
|
||||
{
|
||||
int w, v, iv;
|
||||
unsigned char *c;
|
||||
{
|
||||
int w,v,iv;
|
||||
unsigned char *c;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
iv = ~v;
|
||||
if (!value)
|
||||
v = 0;
|
||||
w=n/8;
|
||||
v=1<<(7-(n&0x07));
|
||||
iv= ~v;
|
||||
if (!value) v=0;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
|
||||
a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
|
||||
|
||||
if ((a->length < (w + 1)) || (a->data == NULL)) {
|
||||
if (!value)
|
||||
return (1); /* Don't need to set */
|
||||
if (a->data == NULL)
|
||||
c = (unsigned char *)OPENSSL_malloc(w + 1);
|
||||
else
|
||||
c = (unsigned char *)OPENSSL_realloc_clean(a->data,
|
||||
a->length, w + 1);
|
||||
if (c == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (w + 1 - a->length > 0)
|
||||
memset(c + a->length, 0, w + 1 - a->length);
|
||||
a->data = c;
|
||||
a->length = w + 1;
|
||||
}
|
||||
a->data[w] = ((a->data[w]) & iv) | v;
|
||||
while ((a->length > 0) && (a->data[a->length - 1] == 0))
|
||||
a->length--;
|
||||
return (1);
|
||||
}
|
||||
if ((a->length < (w+1)) || (a->data == NULL))
|
||||
{
|
||||
if (!value) return(1); /* Don't need to set */
|
||||
if (a->data == NULL)
|
||||
c=(unsigned char *)OPENSSL_malloc(w+1);
|
||||
else
|
||||
c=(unsigned char *)OPENSSL_realloc_clean(a->data,
|
||||
a->length,
|
||||
w+1);
|
||||
if (c == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (w+1-a->length > 0) memset(c+a->length, 0, w+1-a->length);
|
||||
a->data=c;
|
||||
a->length=w+1;
|
||||
}
|
||||
a->data[w]=((a->data[w])&iv)|v;
|
||||
while ((a->length > 0) && (a->data[a->length-1] == 0))
|
||||
a->length--;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
int w, v;
|
||||
{
|
||||
int w,v;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
|
||||
return (0);
|
||||
return ((a->data[w] & v) != 0);
|
||||
}
|
||||
w=n/8;
|
||||
v=1<<(7-(n&0x07));
|
||||
if ((a == NULL) || (a->length < (w+1)) || (a->data == NULL))
|
||||
return(0);
|
||||
return((a->data[w]&v) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given bit string contains only bits specified by
|
||||
* Checks if the given bit string contains only bits specified by
|
||||
* the flags vector. Returns 0 if there is at least one bit set in 'a'
|
||||
* which is not specified in 'flags', 1 otherwise.
|
||||
* 'len' is the length of 'flags'.
|
||||
*/
|
||||
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
|
||||
unsigned char *flags, int flags_len)
|
||||
{
|
||||
int i, ok;
|
||||
/* Check if there is one bit set at all. */
|
||||
if (!a || !a->data)
|
||||
return 1;
|
||||
unsigned char *flags, int flags_len)
|
||||
{
|
||||
int i, ok;
|
||||
/* Check if there is one bit set at all. */
|
||||
if (!a || !a->data) return 1;
|
||||
|
||||
/*
|
||||
* Check each byte of the internal representation of the bit string.
|
||||
*/
|
||||
ok = 1;
|
||||
for (i = 0; i < a->length && ok; ++i) {
|
||||
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
|
||||
/* We are done if there is an unneeded bit set. */
|
||||
ok = (a->data[i] & mask) == 0;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
/* Check each byte of the internal representation of the bit string. */
|
||||
ok = 1;
|
||||
for (i = 0; i < a->length && ok; ++i)
|
||||
{
|
||||
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
|
||||
/* We are done if there is an unneeded bit set. */
|
||||
ok = (a->data[i] & mask) == 0;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
+44
-42
@@ -33,7 +33,7 @@
|
||||
* 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
|
||||
* 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)"
|
||||
*
|
||||
@@ -59,52 +59,54 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
|
||||
{
|
||||
int r;
|
||||
unsigned char *p;
|
||||
{
|
||||
int r;
|
||||
unsigned char *p;
|
||||
|
||||
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
|
||||
if (pp == NULL)
|
||||
return (r);
|
||||
p = *pp;
|
||||
r=ASN1_object_size(0,1,V_ASN1_BOOLEAN);
|
||||
if (pp == NULL) return(r);
|
||||
p= *pp;
|
||||
|
||||
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
|
||||
*(p++) = (unsigned char)a;
|
||||
*pp = p;
|
||||
return (r);
|
||||
}
|
||||
ASN1_put_object(&p,0,1,V_ASN1_BOOLEAN,V_ASN1_UNIVERSAL);
|
||||
*(p++)= (unsigned char)a;
|
||||
*pp=p;
|
||||
return(r);
|
||||
}
|
||||
|
||||
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
|
||||
{
|
||||
int ret = -1;
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
{
|
||||
int ret= -1;
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i=0;
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_BOOLEAN) {
|
||||
i = ASN1_R_EXPECTING_A_BOOLEAN;
|
||||
goto err;
|
||||
}
|
||||
if (tag != V_ASN1_BOOLEAN)
|
||||
{
|
||||
i=ASN1_R_EXPECTING_A_BOOLEAN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len != 1) {
|
||||
i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
ret = (int)*(p++);
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (ret);
|
||||
}
|
||||
if (len != 1)
|
||||
{
|
||||
i=ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
ret= (int)*(p++);
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+221
-212
@@ -62,247 +62,256 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
|
||||
/*
|
||||
* type is a 'bitmap' of acceptable string types.
|
||||
/* type is a 'bitmap' of acceptable string types.
|
||||
*/
|
||||
ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||
long length, int type)
|
||||
{
|
||||
ASN1_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
long length, int type)
|
||||
{
|
||||
ASN1_STRING *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i=0;
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80)
|
||||
goto err;
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80) goto err;
|
||||
|
||||
if (tag >= 32) {
|
||||
i = ASN1_R_TAG_VALUE_TOO_HIGH;
|
||||
goto err;
|
||||
}
|
||||
if (!(ASN1_tag2bit(tag) & type)) {
|
||||
i = ASN1_R_WRONG_TYPE;
|
||||
goto err;
|
||||
}
|
||||
if (tag >= 32)
|
||||
{
|
||||
i=ASN1_R_TAG_VALUE_TOO_HIGH;
|
||||
goto err;
|
||||
}
|
||||
if (!(ASN1_tag2bit(tag) & type))
|
||||
{
|
||||
i=ASN1_R_WRONG_TYPE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If a bit-string, exit early */
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return (d2i_ASN1_BIT_STRING(a, pp, length));
|
||||
/* If a bit-string, exit early */
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return(d2i_ASN1_BIT_STRING(a,pp,length));
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = ASN1_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
|
||||
if (len != 0) {
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
s[len] = '\0';
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
if (len != 0)
|
||||
{
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len+1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
s[len]='\0';
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
s=NULL;
|
||||
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->length = (int)len;
|
||||
ret->data = s;
|
||||
ret->type = tag;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->length=(int)len;
|
||||
ret->data=s;
|
||||
ret->type=tag;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
|
||||
{
|
||||
int ret, r, constructed;
|
||||
unsigned char *p;
|
||||
{
|
||||
int ret,r,constructed;
|
||||
unsigned char *p;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a == NULL) return(0);
|
||||
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return (i2d_ASN1_BIT_STRING(a, pp));
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return(i2d_ASN1_BIT_STRING(a,pp));
|
||||
|
||||
ret=a->length;
|
||||
r=ASN1_object_size(0,ret,tag);
|
||||
if (pp == NULL) return(r);
|
||||
p= *pp;
|
||||
|
||||
ret = a->length;
|
||||
r = ASN1_object_size(0, ret, tag);
|
||||
if (pp == NULL)
|
||||
return (r);
|
||||
p = *pp;
|
||||
|
||||
if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
|
||||
constructed = 1;
|
||||
else
|
||||
constructed = 0;
|
||||
ASN1_put_object(&p, constructed, ret, tag, xclass);
|
||||
memcpy(p, a->data, a->length);
|
||||
p += a->length;
|
||||
*pp = p;
|
||||
return (r);
|
||||
}
|
||||
if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
|
||||
constructed=1;
|
||||
else
|
||||
constructed=0;
|
||||
ASN1_put_object(&p,constructed,ret,tag,xclass);
|
||||
memcpy(p,a->data,a->length);
|
||||
p+=a->length;
|
||||
*pp= p;
|
||||
return(r);
|
||||
}
|
||||
|
||||
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||
long length, int Ptag, int Pclass)
|
||||
{
|
||||
ASN1_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
long length, int Ptag, int Pclass)
|
||||
{
|
||||
ASN1_STRING *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i=0;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = ASN1_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != Ptag) {
|
||||
i = ASN1_R_WRONG_TAG;
|
||||
goto err;
|
||||
}
|
||||
if (tag != Ptag)
|
||||
{
|
||||
i=ASN1_R_WRONG_TAG;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (inf & V_ASN1_CONSTRUCTED) {
|
||||
ASN1_const_CTX c;
|
||||
if (inf & V_ASN1_CONSTRUCTED)
|
||||
{
|
||||
ASN1_const_CTX c;
|
||||
|
||||
c.pp = pp;
|
||||
c.p = p;
|
||||
c.inf = inf;
|
||||
c.slen = len;
|
||||
c.tag = Ptag;
|
||||
c.xclass = Pclass;
|
||||
c.max = (length == 0) ? 0 : (p + length);
|
||||
if (!asn1_collate_primitive(ret, &c))
|
||||
goto err;
|
||||
else {
|
||||
p = c.p;
|
||||
}
|
||||
} else {
|
||||
if (len != 0) {
|
||||
if ((ret->length < len) || (ret->data == NULL)) {
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
s = ret->data;
|
||||
memcpy(s, p, (int)len);
|
||||
s[len] = '\0';
|
||||
p += len;
|
||||
} else {
|
||||
s = NULL;
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
}
|
||||
c.pp=pp;
|
||||
c.p=p;
|
||||
c.inf=inf;
|
||||
c.slen=len;
|
||||
c.tag=Ptag;
|
||||
c.xclass=Pclass;
|
||||
c.max=(length == 0)?0:(p+length);
|
||||
if (!asn1_collate_primitive(ret,&c))
|
||||
goto err;
|
||||
else
|
||||
{
|
||||
p=c.p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len != 0)
|
||||
{
|
||||
if ((ret->length < len) || (ret->data == NULL))
|
||||
{
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
s=ret->data;
|
||||
memcpy(s,p,(int)len);
|
||||
s[len] = '\0';
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
{
|
||||
s=NULL;
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
}
|
||||
|
||||
ret->length = (int)len;
|
||||
ret->data = s;
|
||||
ret->type = Ptag;
|
||||
}
|
||||
ret->length=(int)len;
|
||||
ret->data=s;
|
||||
ret->type=Ptag;
|
||||
}
|
||||
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (NULL);
|
||||
}
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse them
|
||||
* into the one structure that is then returned
|
||||
*/
|
||||
/*
|
||||
* There have been a few bug fixes for this function from Paul Keogh
|
||||
* <paul.keogh@sse.ie>, many thanks to him
|
||||
*/
|
||||
|
||||
/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
|
||||
* them into the one structure that is then returned */
|
||||
/* There have been a few bug fixes for this function from
|
||||
* Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
|
||||
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
|
||||
{
|
||||
ASN1_STRING *os = NULL;
|
||||
BUF_MEM b;
|
||||
int num;
|
||||
{
|
||||
ASN1_STRING *os=NULL;
|
||||
BUF_MEM b;
|
||||
int num;
|
||||
|
||||
b.length = 0;
|
||||
b.max = 0;
|
||||
b.data = NULL;
|
||||
b.length=0;
|
||||
b.max=0;
|
||||
b.data=NULL;
|
||||
|
||||
if (a == NULL) {
|
||||
c->error = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
if (a == NULL)
|
||||
{
|
||||
c->error=ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
num = 0;
|
||||
for (;;) {
|
||||
if (c->inf & 1) {
|
||||
c->eos = ASN1_const_check_infinite_end(&c->p,
|
||||
(long)(c->max - c->p));
|
||||
if (c->eos)
|
||||
break;
|
||||
} else {
|
||||
if (c->slen <= 0)
|
||||
break;
|
||||
}
|
||||
num=0;
|
||||
for (;;)
|
||||
{
|
||||
if (c->inf & 1)
|
||||
{
|
||||
c->eos=ASN1_const_check_infinite_end(&c->p,
|
||||
(long)(c->max-c->p));
|
||||
if (c->eos) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c->slen <= 0) break;
|
||||
}
|
||||
|
||||
c->q = c->p;
|
||||
if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass)
|
||||
== NULL) {
|
||||
c->error = ERR_R_ASN1_LIB;
|
||||
goto err;
|
||||
}
|
||||
c->q=c->p;
|
||||
if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
|
||||
== NULL)
|
||||
{
|
||||
c->error=ERR_R_ASN1_LIB;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BUF_MEM_grow_clean(&b, num + os->length)) {
|
||||
c->error = ERR_R_BUF_LIB;
|
||||
goto err;
|
||||
}
|
||||
memcpy(&(b.data[num]), os->data, os->length);
|
||||
if (!(c->inf & 1))
|
||||
c->slen -= (c->p - c->q);
|
||||
num += os->length;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(&b,num+os->length))
|
||||
{
|
||||
c->error=ERR_R_BUF_LIB;
|
||||
goto err;
|
||||
}
|
||||
memcpy(&(b.data[num]),os->data,os->length);
|
||||
if (!(c->inf & 1))
|
||||
c->slen-=(c->p-c->q);
|
||||
num+=os->length;
|
||||
}
|
||||
|
||||
if (!asn1_const_Finish(c))
|
||||
goto err;
|
||||
if (!asn1_const_Finish(c)) goto err;
|
||||
|
||||
a->length=num;
|
||||
if (a->data != NULL) OPENSSL_free(a->data);
|
||||
a->data=(unsigned char *)b.data;
|
||||
if (os != NULL) ASN1_STRING_free(os);
|
||||
return(1);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, c->error);
|
||||
if (os != NULL) ASN1_STRING_free(os);
|
||||
if (b.data != NULL) OPENSSL_free(b.data);
|
||||
return(0);
|
||||
}
|
||||
|
||||
a->length = num;
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
a->data = (unsigned char *)b.data;
|
||||
if (os != NULL)
|
||||
ASN1_STRING_free(os);
|
||||
return (1);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, c->error);
|
||||
if (os != NULL)
|
||||
ASN1_STRING_free(os);
|
||||
if (b.data != NULL)
|
||||
OPENSSL_free(b.data);
|
||||
return (0);
|
||||
}
|
||||
|
||||
+192
-173
@@ -62,206 +62,225 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
# ifndef OPENSSL_NO_FP_API
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
|
||||
void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
|
||||
{
|
||||
BIO *b;
|
||||
void *ret;
|
||||
void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
|
||||
{
|
||||
BIO *b;
|
||||
void *ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (NULL);
|
||||
}
|
||||
BIO_set_fp(b, in, BIO_NOCLOSE);
|
||||
ret = ASN1_d2i_bio(xnew, d2i, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
# endif
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(NULL);
|
||||
}
|
||||
BIO_set_fp(b,in,BIO_NOCLOSE);
|
||||
ret=ASN1_d2i_bio(xnew,d2i,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret = NULL;
|
||||
int len;
|
||||
void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret=NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if (len < 0)
|
||||
goto err;
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if(len < 0) goto err;
|
||||
|
||||
p = (unsigned char *)b->data;
|
||||
ret = d2i(x, &p, len);
|
||||
err:
|
||||
if (b != NULL)
|
||||
BUF_MEM_free(b);
|
||||
return (ret);
|
||||
}
|
||||
p=(unsigned char *)b->data;
|
||||
ret=d2i(x,&p,len);
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret = NULL;
|
||||
int len;
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret=NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if (len < 0)
|
||||
goto err;
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if(len < 0) goto err;
|
||||
|
||||
p = (const unsigned char *)b->data;
|
||||
ret = ASN1_item_d2i(x, &p, len, it);
|
||||
err:
|
||||
if (b != NULL)
|
||||
BUF_MEM_free(b);
|
||||
return (ret);
|
||||
}
|
||||
p=(const unsigned char *)b->data;
|
||||
ret=ASN1_item_d2i(x,&p,len, it);
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
char *ret;
|
||||
{
|
||||
BIO *b;
|
||||
char *ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (NULL);
|
||||
}
|
||||
BIO_set_fp(b, in, BIO_NOCLOSE);
|
||||
ret = ASN1_item_d2i_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(NULL);
|
||||
}
|
||||
BIO_set_fp(b,in,BIO_NOCLOSE);
|
||||
ret=ASN1_item_d2i_bio(it,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
||||
{
|
||||
BUF_MEM *b;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
ASN1_const_CTX c;
|
||||
size_t want = HEADER_SIZE;
|
||||
int eos = 0;
|
||||
size_t off = 0;
|
||||
size_t len = 0;
|
||||
{
|
||||
BUF_MEM *b;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
ASN1_const_CTX c;
|
||||
size_t want=HEADER_SIZE;
|
||||
int eos=0;
|
||||
size_t off=0;
|
||||
size_t len=0;
|
||||
|
||||
b = BUF_MEM_new();
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
b=BUF_MEM_new();
|
||||
if (b == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
for (;;) {
|
||||
if (want >= (len - off)) {
|
||||
want -= (len - off);
|
||||
ERR_clear_error();
|
||||
for (;;)
|
||||
{
|
||||
if (want >= (len-off))
|
||||
{
|
||||
want-=(len-off);
|
||||
|
||||
if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i = BIO_read(in, &(b->data[len]), want);
|
||||
if ((i < 0) && ((len - off) == 0)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
if (i > 0) {
|
||||
if (len + i < len) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
len += i;
|
||||
}
|
||||
}
|
||||
/* else data already loaded */
|
||||
if (len + want < len || !BUF_MEM_grow_clean(b,len+want))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i=BIO_read(in,&(b->data[len]),want);
|
||||
if ((i < 0) && ((len-off) == 0))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
if (len+i < len)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
len+=i;
|
||||
}
|
||||
}
|
||||
/* else data already loaded */
|
||||
|
||||
p = (unsigned char *)&(b->data[off]);
|
||||
c.p = p;
|
||||
c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
|
||||
len - off);
|
||||
if (c.inf & 0x80) {
|
||||
uint32_t e;
|
||||
p=(unsigned char *)&(b->data[off]);
|
||||
c.p=p;
|
||||
c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
|
||||
len-off);
|
||||
if (c.inf & 0x80)
|
||||
{
|
||||
uint32_t e;
|
||||
|
||||
e = ERR_GET_REASON(ERR_peek_error());
|
||||
if (e != ASN1_R_TOO_LONG)
|
||||
goto err;
|
||||
else
|
||||
ERR_clear_error(); /* clear error */
|
||||
}
|
||||
i = c.p - p; /* header length */
|
||||
off += i; /* end of data */
|
||||
e=ERR_GET_REASON(ERR_peek_error());
|
||||
if (e != ASN1_R_TOO_LONG)
|
||||
goto err;
|
||||
else
|
||||
ERR_clear_error(); /* clear error */
|
||||
}
|
||||
i=c.p-p;/* header length */
|
||||
off+=i; /* end of data */
|
||||
|
||||
if (c.inf & 1) {
|
||||
/* no data body so go round again */
|
||||
eos++;
|
||||
if (eos < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
want = HEADER_SIZE;
|
||||
} else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) {
|
||||
/* eos value, so go back and read another header */
|
||||
eos--;
|
||||
if (eos <= 0)
|
||||
break;
|
||||
else
|
||||
want = HEADER_SIZE;
|
||||
} else {
|
||||
/* suck in c.slen bytes of data */
|
||||
want = c.slen;
|
||||
if (want > (len - off)) {
|
||||
want -= (len - off);
|
||||
if (want > INT_MAX /* BIO_read takes an int length */ ||
|
||||
len + want < len) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(b, len + want)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
while (want > 0) {
|
||||
i = BIO_read(in, &(b->data[len]), want);
|
||||
if (i <= 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* This can't overflow because |len+want| didn't
|
||||
* overflow.
|
||||
*/
|
||||
len += i;
|
||||
want -= i;
|
||||
}
|
||||
}
|
||||
if (off + c.slen < off) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
off += c.slen;
|
||||
if (eos <= 0) {
|
||||
break;
|
||||
} else
|
||||
want = HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
if (c.inf & 1)
|
||||
{
|
||||
/* no data body so go round again */
|
||||
eos++;
|
||||
if (eos < 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
want=HEADER_SIZE;
|
||||
}
|
||||
else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
|
||||
{
|
||||
/* eos value, so go back and read another header */
|
||||
eos--;
|
||||
if (eos <= 0)
|
||||
break;
|
||||
else
|
||||
want=HEADER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* suck in c.slen bytes of data */
|
||||
want=c.slen;
|
||||
if (want > (len-off))
|
||||
{
|
||||
want-=(len-off);
|
||||
if (want > INT_MAX /* BIO_read takes an int length */ ||
|
||||
len+want < len)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(b,len+want))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
while (want > 0)
|
||||
{
|
||||
i=BIO_read(in,&(b->data[len]),want);
|
||||
if (i <= 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
/* This can't overflow because
|
||||
* |len+want| didn't overflow. */
|
||||
len+=i;
|
||||
want-=i;
|
||||
}
|
||||
}
|
||||
if (off + c.slen < off)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
off+=c.slen;
|
||||
if (eos <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
want=HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (off > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (off > INT_MAX)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*pb = b;
|
||||
return off;
|
||||
err:
|
||||
if (b != NULL)
|
||||
BUF_MEM_free(b);
|
||||
return -1;
|
||||
}
|
||||
*pb = b;
|
||||
return off;
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return -1;
|
||||
}
|
||||
|
||||
+35
-43
@@ -59,53 +59,45 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
|
||||
{
|
||||
unsigned char *b, *p;
|
||||
const unsigned char *p2;
|
||||
int i;
|
||||
char *ret;
|
||||
{
|
||||
unsigned char *b,*p;
|
||||
const unsigned char *p2;
|
||||
int i;
|
||||
char *ret;
|
||||
|
||||
if (x == NULL)
|
||||
return (NULL);
|
||||
if (x == NULL) return(NULL);
|
||||
|
||||
i = i2d(x, NULL);
|
||||
b = OPENSSL_malloc(i + 10);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
p = b;
|
||||
i = i2d(x, &p);
|
||||
p2 = b;
|
||||
ret = d2i(NULL, &p2, i);
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
i=i2d(x,NULL);
|
||||
b=OPENSSL_malloc(i+10);
|
||||
if (b == NULL)
|
||||
{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
|
||||
p= b;
|
||||
i=i2d(x,&p);
|
||||
p2= b;
|
||||
ret=d2i(NULL,&p2,i);
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* ASN1_ITEM version of dup: this follows the model above except we don't
|
||||
* need to allocate the buffer. At some point this could be rewritten to
|
||||
* directly dup the underlying structure instead of doing and encode and
|
||||
* decode.
|
||||
*/
|
||||
/* ASN1_ITEM version of dup: this follows the model above except we don't need
|
||||
* to allocate the buffer. At some point this could be rewritten to directly dup
|
||||
* the underlying structure instead of doing and encode and decode. */
|
||||
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
const unsigned char *p;
|
||||
long i;
|
||||
void *ret;
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
const unsigned char *p;
|
||||
long i;
|
||||
void *ret;
|
||||
|
||||
if (x == NULL)
|
||||
return (NULL);
|
||||
if (x == NULL) return(NULL);
|
||||
|
||||
i = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
p = b;
|
||||
ret = ASN1_item_d2i(NULL, &p, i, it);
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
i=ASN1_item_i2d(x,&b,it);
|
||||
if (b == NULL)
|
||||
{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
|
||||
p= b;
|
||||
ret=ASN1_item_d2i(NULL,&p,i, it);
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+102
-100
@@ -61,121 +61,123 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
|
||||
* for comments on encoding see a_int.c
|
||||
*/
|
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
{
|
||||
int j, k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long) + 1];
|
||||
long d;
|
||||
{
|
||||
int j,k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long)+1];
|
||||
long d;
|
||||
|
||||
a->type = V_ASN1_ENUMERATED;
|
||||
if (a->length < (int)(sizeof(long) + 1)) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
d = v;
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
a->type = V_ASN1_NEG_ENUMERATED;
|
||||
}
|
||||
a->type=V_ASN1_ENUMERATED;
|
||||
if (a->length < (int)(sizeof(long)+1))
|
||||
{
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
|
||||
memset((char *)a->data,0,sizeof(long)+1);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
d=v;
|
||||
if (d < 0)
|
||||
{
|
||||
d= -d;
|
||||
a->type=V_ASN1_NEG_ENUMERATED;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(long); i++) {
|
||||
if (d == 0)
|
||||
break;
|
||||
buf[i] = (int)d & 0xff;
|
||||
d >>= 8;
|
||||
}
|
||||
j = 0;
|
||||
for (k = i - 1; k >= 0; k--)
|
||||
a->data[j++] = buf[k];
|
||||
a->length = j;
|
||||
return (1);
|
||||
}
|
||||
for (i=0; i<sizeof(long); i++)
|
||||
{
|
||||
if (d == 0) break;
|
||||
buf[i]=(int)d&0xff;
|
||||
d>>=8;
|
||||
}
|
||||
j=0;
|
||||
for (k=i-1; k >=0; k--)
|
||||
a->data[j++]=buf[k];
|
||||
a->length=j;
|
||||
return(1);
|
||||
}
|
||||
|
||||
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
long r = 0;
|
||||
{
|
||||
int neg=0,i;
|
||||
long r=0;
|
||||
|
||||
if (a == NULL)
|
||||
return (0L);
|
||||
i = a->type;
|
||||
if (i == V_ASN1_NEG_ENUMERATED)
|
||||
neg = 1;
|
||||
else if (i != V_ASN1_ENUMERATED)
|
||||
return -1;
|
||||
if (a == NULL) return(0L);
|
||||
i=a->type;
|
||||
if (i == V_ASN1_NEG_ENUMERATED)
|
||||
neg=1;
|
||||
else if (i != V_ASN1_ENUMERATED)
|
||||
return -1;
|
||||
|
||||
if (a->length > (int)sizeof(long))
|
||||
{
|
||||
/* hmm... a bit ugly */
|
||||
return(0xffffffffL);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
return 0;
|
||||
|
||||
if (a->length > (int)sizeof(long)) {
|
||||
/* hmm... a bit ugly */
|
||||
return (0xffffffffL);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < a->length; i++) {
|
||||
r <<= 8;
|
||||
r |= (unsigned char)a->data[i];
|
||||
}
|
||||
if (neg)
|
||||
r = -r;
|
||||
return (r);
|
||||
}
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
r<<=8;
|
||||
r|=(unsigned char)a->data[i];
|
||||
}
|
||||
if (neg) r= -r;
|
||||
return(r);
|
||||
}
|
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len, j;
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len,j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_ENUMERATED_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn))
|
||||
ret->type = V_ASN1_NEG_ENUMERATED;
|
||||
else
|
||||
ret->type = V_ASN1_ENUMERATED;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
if (ai == NULL)
|
||||
ret=M_ASN1_ENUMERATED_new();
|
||||
else
|
||||
ret=ai;
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if(BN_is_negative(bn)) ret->type = V_ASN1_NEG_ENUMERATED;
|
||||
else ret->type=V_ASN1_ENUMERATED;
|
||||
j=BN_num_bits(bn);
|
||||
len=((j == 0)?0:((j/8)+1));
|
||||
if (ret->length < len+4)
|
||||
{
|
||||
unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
|
||||
if (!new_data)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data=new_data;
|
||||
}
|
||||
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_ENUMERATED_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length=BN_bn2bin(bn,ret->data);
|
||||
return(ret);
|
||||
err:
|
||||
if (ret != ai) M_ASN1_ENUMERATED_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_ENUMERATED)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+170
-171
@@ -63,194 +63,193 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
{
|
||||
static const int min[9]={ 0, 0, 1, 1, 0, 0, 0, 0, 0};
|
||||
static const int max[9]={99, 99,12,31,23,59,59,12,59};
|
||||
char *a;
|
||||
int n,i,l,o;
|
||||
|
||||
if (d->type != V_ASN1_GENERALIZEDTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
/*
|
||||
* GENERALIZEDTIME is similar to UTCTIME except the year is represented
|
||||
* as YYYY. This stuff treats everything as a two digit field so make
|
||||
* first two fields 00 to 99
|
||||
*/
|
||||
if (l < 13)
|
||||
goto err;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
if (d->type != V_ASN1_GENERALIZEDTIME) return(0);
|
||||
l=d->length;
|
||||
a=(char *)d->data;
|
||||
o=0;
|
||||
/* GENERALIZEDTIME is similar to UTCTIME except the year is
|
||||
* represented as YYYY. This stuff treats everything as a two digit
|
||||
* field so make first two fields 00 to 99
|
||||
*/
|
||||
if (l < 13) goto err;
|
||||
for (i=0; i<7; i++)
|
||||
{
|
||||
if ((i == 6) && ((a[o] == 'Z') ||
|
||||
(a[o] == '+') || (a[o] == '-')))
|
||||
{
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n= a[o]-'0';
|
||||
if (++o > l) goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n=(n*10)+ a[o]-'0';
|
||||
if (++o > l) goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n * 100 - 1900;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_year += n;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 6:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Optional fractional seconds: decimal point followed by one or more
|
||||
* digits.
|
||||
*/
|
||||
if (a[o] == '.') {
|
||||
if (++o > l)
|
||||
goto err;
|
||||
i = o;
|
||||
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
|
||||
o++;
|
||||
/* Must have at least one digit after decimal point */
|
||||
if (i == o)
|
||||
goto err;
|
||||
}
|
||||
if ((n < min[i]) || (n > max[i])) goto err;
|
||||
if (tm)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
tm->tm_year = n * 100 - 1900;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_year += n;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 6:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Optional fractional seconds: decimal point followed by one
|
||||
* or more digits.
|
||||
*/
|
||||
if (a[o] == '.')
|
||||
{
|
||||
if (++o > l) goto err;
|
||||
i = o;
|
||||
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
|
||||
o++;
|
||||
/* Must have at least one digit after decimal point */
|
||||
if (i == o) goto err;
|
||||
}
|
||||
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 7; i < 9; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 7)
|
||||
offset = n * 3600;
|
||||
else if (i == 8)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
} else if (a[o]) {
|
||||
/* Missing time zone information. */
|
||||
goto err;
|
||||
}
|
||||
return (o == l);
|
||||
err:
|
||||
return (0);
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-'))
|
||||
{
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
o++;
|
||||
if (o+4 > l) goto err;
|
||||
for (i=7; i<9; i++)
|
||||
{
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n= a[o]-'0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n=(n*10)+ a[o]-'0';
|
||||
if ((n < min[i]) || (n > max[i])) goto err;
|
||||
if (tm)
|
||||
{
|
||||
if (i == 7)
|
||||
offset = n * 3600;
|
||||
else if (i == 8)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
else if (a[o])
|
||||
{
|
||||
/* Missing time zone information. */
|
||||
goto err;
|
||||
}
|
||||
return(o == l);
|
||||
err:
|
||||
return(0);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
|
||||
{
|
||||
return asn1_generalizedtime_to_tm(NULL, d);
|
||||
}
|
||||
{
|
||||
return asn1_generalizedtime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME t;
|
||||
{
|
||||
ASN1_GENERALIZEDTIME t;
|
||||
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_GENERALIZEDTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_GENERALIZEDTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
t.type=V_ASN1_GENERALIZEDTIME;
|
||||
t.length=strlen(str);
|
||||
t.data=(unsigned char *)str;
|
||||
if (ASN1_GENERALIZEDTIME_check(&t))
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str,t.length))
|
||||
return 0;
|
||||
s->type=V_ASN1_GENERALIZEDTIME;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t)
|
||||
{
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
time_t t)
|
||||
{
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
|
||||
time_t t, int offset_day,
|
||||
long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
time_t t, int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
|
||||
if (s == NULL)
|
||||
s = M_ASN1_GENERALIZEDTIME_new();
|
||||
if (s == NULL)
|
||||
return (NULL);
|
||||
if (s == NULL)
|
||||
s=M_ASN1_GENERALIZEDTIME_new();
|
||||
if (s == NULL)
|
||||
return(NULL);
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
return (NULL);
|
||||
ts=OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
return(NULL);
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec)
|
||||
{
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
return (NULL);
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data = (unsigned char *)p;
|
||||
}
|
||||
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);
|
||||
return(NULL);
|
||||
}
|
||||
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);
|
||||
s->length = strlen(p);
|
||||
s->type = V_ASN1_GENERALIZEDTIME;
|
||||
return (s);
|
||||
}
|
||||
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);
|
||||
s->length=strlen(p);
|
||||
s->type=V_ASN1_GENERALIZEDTIME;
|
||||
return(s);
|
||||
}
|
||||
|
||||
+81
-74
@@ -59,89 +59,96 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, out, BIO_NOCLOSE);
|
||||
ret = ASN1_i2d_bio(i2d, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(0);
|
||||
}
|
||||
BIO_set_fp(b,out,BIO_NOCLOSE);
|
||||
ret=ASN1_i2d_bio(i2d,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x)
|
||||
{
|
||||
char *b;
|
||||
unsigned char *p;
|
||||
int i, j = 0, n, ret = 1;
|
||||
{
|
||||
char *b;
|
||||
unsigned char *p;
|
||||
int i,j=0,n,ret=1;
|
||||
|
||||
n = i2d(x, NULL);
|
||||
b = (char *)OPENSSL_malloc(n);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
n=i2d(x,NULL);
|
||||
b=(char *)OPENSSL_malloc(n);
|
||||
if (b == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
p = (unsigned char *)b;
|
||||
i2d(x, &p);
|
||||
|
||||
for (;;) {
|
||||
i = BIO_write(out, &(b[j]), n);
|
||||
if (i == n)
|
||||
break;
|
||||
if (i <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
p=(unsigned char *)b;
|
||||
i2d(x,&p);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
i=BIO_write(out,&(b[j]),n);
|
||||
if (i == n) break;
|
||||
if (i <= 0)
|
||||
{
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
j+=i;
|
||||
n-=i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, out, BIO_NOCLOSE);
|
||||
ret = ASN1_item_i2d_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(0);
|
||||
}
|
||||
BIO_set_fp(b,out,BIO_NOCLOSE);
|
||||
ret=ASN1_item_i2d_bio(it,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int i, j = 0, n, ret = 1;
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int i,j=0,n,ret=1;
|
||||
|
||||
n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
i = BIO_write(out, &(b[j]), n);
|
||||
if (i == n)
|
||||
break;
|
||||
if (i <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
i=BIO_write(out,&(b[j]),n);
|
||||
if (i == n) break;
|
||||
if (i <= 0)
|
||||
{
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
j+=i;
|
||||
n-=i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+333
-335
@@ -61,46 +61,47 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
|
||||
{
|
||||
return M_ASN1_INTEGER_dup(x);
|
||||
}
|
||||
{ return M_ASN1_INTEGER_dup(x);}
|
||||
|
||||
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
|
||||
{
|
||||
int neg, ret;
|
||||
/* Compare signs */
|
||||
neg = x->type & V_ASN1_NEG;
|
||||
if (neg != (y->type & V_ASN1_NEG)) {
|
||||
if (neg)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
int neg, ret;
|
||||
/* Compare signs */
|
||||
neg = x->type & V_ASN1_NEG;
|
||||
if (neg != (y->type & V_ASN1_NEG))
|
||||
{
|
||||
if (neg)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ASN1_STRING_cmp(x, y);
|
||||
ret = ASN1_STRING_cmp(x, y);
|
||||
|
||||
if (neg)
|
||||
return -ret;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
if (neg)
|
||||
return -ret;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
* This converts an ASN1 INTEGER into its content encoding.
|
||||
* The internal representation is an ASN1_STRING whose data is a big endian
|
||||
* representation of the value, ignoring the sign. The sign is determined by
|
||||
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
|
||||
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
|
||||
*
|
||||
* Positive integers are no problem: they are almost the same as the DER
|
||||
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
|
||||
*
|
||||
* Negative integers are a bit trickier...
|
||||
* The DER representation of negative integers is in 2s complement form.
|
||||
* The internal form is converted by complementing each octet and finally
|
||||
* The internal form is converted by complementing each octet and finally
|
||||
* adding one to the result. This can be done less messily with a little trick.
|
||||
* If the internal form has trailing zeroes then they will become FF by the
|
||||
* complement and 0 by the add one (due to carry) so just copy as many trailing
|
||||
* complement and 0 by the add one (due to carry) so just copy as many trailing
|
||||
* zeros to the destination as there are in the source. The carry will add one
|
||||
* to the last none zero octet: so complement this octet and add one and finally
|
||||
* complement any left over until you get to the start of the string.
|
||||
@@ -112,349 +113,346 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
|
||||
*/
|
||||
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
|
||||
{
|
||||
int pad = 0, ret, i, neg;
|
||||
unsigned char *p, *n, pb = 0;
|
||||
{
|
||||
int pad=0,ret,i,neg;
|
||||
unsigned char *p,*n,pb=0;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
neg = a->type & V_ASN1_NEG;
|
||||
if (a->length == 0)
|
||||
ret = 1;
|
||||
else {
|
||||
ret = a->length;
|
||||
i = a->data[0];
|
||||
if (ret == 1 && i == 0)
|
||||
neg = 0;
|
||||
if (!neg && (i > 127)) {
|
||||
pad = 1;
|
||||
pb = 0;
|
||||
} else if (neg) {
|
||||
if (i > 128) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
} else if (i == 128) {
|
||||
/*
|
||||
* Special case: if any other bytes non zero we pad:
|
||||
* otherwise we don't.
|
||||
*/
|
||||
for (i = 1; i < a->length; i++)
|
||||
if (a->data[i]) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret += pad;
|
||||
}
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
p = *pp;
|
||||
if (a == NULL) return(0);
|
||||
neg=a->type & V_ASN1_NEG;
|
||||
if (a->length == 0)
|
||||
ret=1;
|
||||
else
|
||||
{
|
||||
ret=a->length;
|
||||
i=a->data[0];
|
||||
if (ret == 1 && i == 0)
|
||||
neg = 0;
|
||||
if (!neg && (i > 127)) {
|
||||
pad=1;
|
||||
pb=0;
|
||||
} else if(neg) {
|
||||
if(i>128) {
|
||||
pad=1;
|
||||
pb=0xFF;
|
||||
} else if(i == 128) {
|
||||
/*
|
||||
* Special case: if any other bytes non zero we pad:
|
||||
* otherwise we don't.
|
||||
*/
|
||||
for(i = 1; i < a->length; i++) if(a->data[i]) {
|
||||
pad=1;
|
||||
pb=0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret+=pad;
|
||||
}
|
||||
if (pp == NULL) return(ret);
|
||||
p= *pp;
|
||||
|
||||
if (pad)
|
||||
*(p++) = pb;
|
||||
if (a->length == 0)
|
||||
*(p++) = 0;
|
||||
else if (!neg)
|
||||
memcpy(p, a->data, (unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n = a->data + a->length - 1;
|
||||
p += a->length - 1;
|
||||
i = a->length;
|
||||
/* Copy zeros to destination as long as source is zero */
|
||||
while (!*n && i > 1) {
|
||||
*(p--) = 0;
|
||||
n--;
|
||||
i--;
|
||||
}
|
||||
/* Complement and increment next octet */
|
||||
*(p--) = ((*(n--)) ^ 0xff) + 1;
|
||||
i--;
|
||||
/* Complement any octets left */
|
||||
for (; i > 0; i--)
|
||||
*(p--) = *(n--) ^ 0xff;
|
||||
}
|
||||
if (pad) *(p++)=pb;
|
||||
if (a->length == 0) *(p++)=0;
|
||||
else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n=a->data + a->length - 1;
|
||||
p += a->length - 1;
|
||||
i = a->length;
|
||||
/* Copy zeros to destination as long as source is zero */
|
||||
while(!*n && i > 1) {
|
||||
*(p--) = 0;
|
||||
n--;
|
||||
i--;
|
||||
}
|
||||
/* Complement and increment next octet */
|
||||
*(p--) = ((*(n--)) ^ 0xff) + 1;
|
||||
i--;
|
||||
/* Complement any octets left */
|
||||
for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
|
||||
}
|
||||
|
||||
*pp += ret;
|
||||
return (ret);
|
||||
}
|
||||
*pp+=ret;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
|
||||
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char *to, *s;
|
||||
int i;
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret=NULL;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char *to,*s;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_INTEGER_new()) == NULL)
|
||||
return (NULL);
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
|
||||
p = *pp;
|
||||
pend = p + len;
|
||||
p= *pp;
|
||||
pend = p + len;
|
||||
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
to = s;
|
||||
if (!len) {
|
||||
/*
|
||||
* Strictly speaking this is an illegal INTEGER but we tolerate it.
|
||||
*/
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else if (*p & 0x80) { /* a negative number */
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
if ((*p == 0xff) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
i = len;
|
||||
p += i - 1;
|
||||
to += i - 1;
|
||||
while ((!*p) && i) {
|
||||
*(to--) = 0;
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
/*
|
||||
* Special case: if all zeros then the number will be of the form FF
|
||||
* followed by n zero bytes: this corresponds to 1 followed by n zero
|
||||
* bytes. We've already written n zeros so we just append an extra
|
||||
* one and set the first byte to a 1. This is treated separately
|
||||
* because it is the only case where the number of bytes is larger
|
||||
* than len.
|
||||
*/
|
||||
if (!i) {
|
||||
*s = 1;
|
||||
s[len] = 0;
|
||||
len++;
|
||||
} else {
|
||||
*(to--) = (*(p--) ^ 0xff) + 1;
|
||||
i--;
|
||||
for (; i > 0; i--)
|
||||
*(to--) = *(p--) ^ 0xff;
|
||||
}
|
||||
} else {
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
}
|
||||
/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
|
||||
* signifies a missing NULL parameter. */
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len+1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
to=s;
|
||||
if(!len) {
|
||||
/* Strictly speaking this is an illegal INTEGER but we
|
||||
* tolerate it.
|
||||
*/
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
} else if (*p & 0x80) /* a negative number */
|
||||
{
|
||||
ret->type=V_ASN1_NEG_INTEGER;
|
||||
if ((*p == 0xff) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
i = len;
|
||||
p += i - 1;
|
||||
to += i - 1;
|
||||
while((!*p) && i) {
|
||||
*(to--) = 0;
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
/* Special case: if all zeros then the number will be of
|
||||
* the form FF followed by n zero bytes: this corresponds to
|
||||
* 1 followed by n zero bytes. We've already written n zeros
|
||||
* so we just append an extra one and set the first byte to
|
||||
* a 1. This is treated separately because it is the only case
|
||||
* where the number of bytes is larger than len.
|
||||
*/
|
||||
if(!i) {
|
||||
*s = 1;
|
||||
s[len] = 0;
|
||||
len++;
|
||||
} else {
|
||||
*(to--) = (*(p--) ^ 0xff) + 1;
|
||||
i--;
|
||||
for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
|
||||
}
|
||||
} else {
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
if ((*p == 0) && (len != 1))
|
||||
{
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
}
|
||||
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = pend;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->data=s;
|
||||
ret->length=(int)len;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=pend;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
|
||||
* integers: some broken software can encode a positive INTEGER with its MSB
|
||||
* set as negative (it doesn't add a padding zero).
|
||||
|
||||
/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
|
||||
* ASN1 integers: some broken software can encode a positive INTEGER
|
||||
* with its MSB set as negative (it doesn't add a padding zero).
|
||||
*/
|
||||
|
||||
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i;
|
||||
long length)
|
||||
{
|
||||
ASN1_INTEGER *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_INTEGER_new()) == NULL)
|
||||
return (NULL);
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_INTEGER) {
|
||||
i = ASN1_R_EXPECTING_AN_INTEGER;
|
||||
goto err;
|
||||
}
|
||||
if (tag != V_ASN1_INTEGER)
|
||||
{
|
||||
i=ASN1_R_EXPECTING_AN_INTEGER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if (len) {
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
p += len;
|
||||
}
|
||||
/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
|
||||
* signifies a missing NULL parameter. */
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len+1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
if(len) {
|
||||
if ((*p == 0) && (len != 1))
|
||||
{
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
p+=len;
|
||||
}
|
||||
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->data=s;
|
||||
ret->length=(int)len;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
|
||||
{
|
||||
int j, k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long) + 1];
|
||||
long d;
|
||||
{
|
||||
int j,k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long)+1];
|
||||
long d;
|
||||
|
||||
a->type = V_ASN1_INTEGER;
|
||||
if (a->length < (int)(sizeof(long) + 1)) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
d = v;
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
a->type = V_ASN1_NEG_INTEGER;
|
||||
}
|
||||
a->type=V_ASN1_INTEGER;
|
||||
if (a->length < (int)(sizeof(long)+1))
|
||||
{
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
|
||||
memset((char *)a->data,0,sizeof(long)+1);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
d=v;
|
||||
if (d < 0)
|
||||
{
|
||||
d= -d;
|
||||
a->type=V_ASN1_NEG_INTEGER;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(long); i++) {
|
||||
if (d == 0)
|
||||
break;
|
||||
buf[i] = (int)d & 0xff;
|
||||
d >>= 8;
|
||||
}
|
||||
j = 0;
|
||||
for (k = i - 1; k >= 0; k--)
|
||||
a->data[j++] = buf[k];
|
||||
a->length = j;
|
||||
return (1);
|
||||
}
|
||||
for (i=0; i<sizeof(long); i++)
|
||||
{
|
||||
if (d == 0) break;
|
||||
buf[i]=(int)d&0xff;
|
||||
d>>=8;
|
||||
}
|
||||
j=0;
|
||||
for (k=i-1; k >=0; k--)
|
||||
a->data[j++]=buf[k];
|
||||
a->length=j;
|
||||
return(1);
|
||||
}
|
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
|
||||
{
|
||||
int neg = 0, i;
|
||||
long r = 0;
|
||||
{
|
||||
int neg=0,i;
|
||||
long r=0;
|
||||
|
||||
if (a == NULL)
|
||||
return (0L);
|
||||
i = a->type;
|
||||
if (i == V_ASN1_NEG_INTEGER)
|
||||
neg = 1;
|
||||
else if (i != V_ASN1_INTEGER)
|
||||
return -1;
|
||||
if (a == NULL) return(0L);
|
||||
i=a->type;
|
||||
if (i == V_ASN1_NEG_INTEGER)
|
||||
neg=1;
|
||||
else if (i != V_ASN1_INTEGER)
|
||||
return -1;
|
||||
|
||||
if (a->length > (int)sizeof(long))
|
||||
{
|
||||
/* hmm... a bit ugly, return all ones */
|
||||
return -1;
|
||||
}
|
||||
if (a->data == NULL)
|
||||
return 0;
|
||||
|
||||
if (a->length > (int)sizeof(long)) {
|
||||
/* hmm... a bit ugly, return all ones */
|
||||
return -1;
|
||||
}
|
||||
if (a->data == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < a->length; i++) {
|
||||
r <<= 8;
|
||||
r |= (unsigned char)a->data[i];
|
||||
}
|
||||
if (neg)
|
||||
r = -r;
|
||||
return (r);
|
||||
}
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
r<<=8;
|
||||
r|=(unsigned char)a->data[i];
|
||||
}
|
||||
if (neg) r= -r;
|
||||
return(r);
|
||||
}
|
||||
|
||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len, j;
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len,j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_INTEGER_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
else
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
/* Correct zero case */
|
||||
if (!ret->length) {
|
||||
ret->data[0] = 0;
|
||||
ret->length = 1;
|
||||
}
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
if (ai == NULL)
|
||||
ret=M_ASN1_INTEGER_new();
|
||||
else
|
||||
ret=ai;
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
else ret->type=V_ASN1_INTEGER;
|
||||
j=BN_num_bits(bn);
|
||||
len=((j == 0)?0:((j/8)+1));
|
||||
if (ret->length < len+4)
|
||||
{
|
||||
unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
|
||||
if (!new_data)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data=new_data;
|
||||
}
|
||||
ret->length=BN_bn2bin(bn,ret->data);
|
||||
/* Correct zero case */
|
||||
if(!ret->length)
|
||||
{
|
||||
ret->data[0] = 0;
|
||||
ret->length = 1;
|
||||
}
|
||||
return(ret);
|
||||
err:
|
||||
if (ret != ai) M_ASN1_INTEGER_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if(ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+239
-258
@@ -61,9 +61,9 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
int (*rfunc) (unsigned long value, void *in),
|
||||
void *arg);
|
||||
int (*rfunc)(unsigned long value, void *in), void *arg);
|
||||
static int in_utf8(unsigned long value, void *arg);
|
||||
static int out_utf8(unsigned long value, void *arg);
|
||||
static int type_str(unsigned long value, void *arg);
|
||||
@@ -73,219 +73,208 @@ static int cpy_univ(unsigned long value, void *arg);
|
||||
static int cpy_utf8(unsigned long value, void *arg);
|
||||
static int is_printable(unsigned long value);
|
||||
|
||||
/*
|
||||
* These functions take a string in UTF8, ASCII or multibyte form and a mask
|
||||
* of permissible ASN1 string types. It then works out the minimal type
|
||||
* (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
|
||||
* creates a string of the correct type with the supplied data. Yes this is
|
||||
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
|
||||
* size limits too.
|
||||
/* These functions take a string in UTF8, ASCII or multibyte form and
|
||||
* a mask of permissible ASN1 string types. It then works out the minimal
|
||||
* type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
|
||||
* and creates a string of the correct type with the supplied data.
|
||||
* Yes this is horrible: it has to be :-(
|
||||
* The 'ncopy' form checks minimum and maximum size limits too.
|
||||
*/
|
||||
|
||||
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask)
|
||||
int inform, unsigned long mask)
|
||||
{
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
}
|
||||
|
||||
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask,
|
||||
long minsize, long maxsize)
|
||||
int inform, unsigned long mask,
|
||||
long minsize, long maxsize)
|
||||
{
|
||||
int str_type;
|
||||
int ret;
|
||||
char free_out;
|
||||
int outform, outlen = 0;
|
||||
ASN1_STRING *dest;
|
||||
unsigned char *p;
|
||||
int nchar;
|
||||
char strbuf[32];
|
||||
int (*cpyfunc) (unsigned long, void *) = NULL;
|
||||
if (len == -1)
|
||||
len = strlen((const char *)in);
|
||||
if (!mask)
|
||||
mask = DIRSTRING_TYPE;
|
||||
int str_type;
|
||||
int ret;
|
||||
char free_out;
|
||||
int outform, outlen = 0;
|
||||
ASN1_STRING *dest;
|
||||
unsigned char *p;
|
||||
int nchar;
|
||||
char strbuf[32];
|
||||
int (*cpyfunc)(unsigned long,void *) = NULL;
|
||||
if(len == -1) len = strlen((const char *)in);
|
||||
if(!mask) mask = DIRSTRING_TYPE;
|
||||
|
||||
/* First do a string check and work out the number of characters */
|
||||
switch (inform) {
|
||||
/* First do a string check and work out the number of characters */
|
||||
switch(inform) {
|
||||
|
||||
case MBSTRING_BMP:
|
||||
if (len & 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 1;
|
||||
break;
|
||||
case MBSTRING_BMP:
|
||||
if(len & 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 1;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
if (len & 3) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 2;
|
||||
break;
|
||||
case MBSTRING_UNIV:
|
||||
if(len & 3) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 2;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
nchar = 0;
|
||||
/* This counts the characters and does utf8 syntax checking */
|
||||
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MBSTRING_UTF8:
|
||||
nchar = 0;
|
||||
/* This counts the characters and does utf8 syntax checking */
|
||||
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
|
||||
if(ret < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBSTRING_ASC:
|
||||
nchar = len;
|
||||
break;
|
||||
case MBSTRING_ASC:
|
||||
nchar = len;
|
||||
break;
|
||||
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((minsize > 0) && (nchar < minsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
|
||||
ERR_add_error_data(2, "minsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
if((minsize > 0) && (nchar < minsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
|
||||
ERR_add_error_data(2, "minsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((maxsize > 0) && (nchar > maxsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
if((maxsize > 0) && (nchar > maxsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out minimal type (if any) */
|
||||
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
/* Now work out minimal type (if any) */
|
||||
if(traverse_string(in, len, inform, type_str, &mask) < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out output format and string type */
|
||||
outform = MBSTRING_ASC;
|
||||
if (mask & B_ASN1_PRINTABLESTRING)
|
||||
str_type = V_ASN1_PRINTABLESTRING;
|
||||
else if (mask & B_ASN1_IA5STRING)
|
||||
str_type = V_ASN1_IA5STRING;
|
||||
else if (mask & B_ASN1_T61STRING)
|
||||
str_type = V_ASN1_T61STRING;
|
||||
else if (mask & B_ASN1_BMPSTRING) {
|
||||
str_type = V_ASN1_BMPSTRING;
|
||||
outform = MBSTRING_BMP;
|
||||
} else if (mask & B_ASN1_UNIVERSALSTRING) {
|
||||
str_type = V_ASN1_UNIVERSALSTRING;
|
||||
outform = MBSTRING_UNIV;
|
||||
} else {
|
||||
str_type = V_ASN1_UTF8STRING;
|
||||
outform = MBSTRING_UTF8;
|
||||
}
|
||||
if (!out)
|
||||
return str_type;
|
||||
if (*out) {
|
||||
free_out = 0;
|
||||
dest = *out;
|
||||
if (dest->data) {
|
||||
dest->length = 0;
|
||||
OPENSSL_free(dest->data);
|
||||
dest->data = NULL;
|
||||
}
|
||||
dest->type = str_type;
|
||||
} else {
|
||||
free_out = 1;
|
||||
dest = ASN1_STRING_type_new(str_type);
|
||||
if (!dest) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
*out = dest;
|
||||
}
|
||||
/* If both the same type just copy across */
|
||||
if (inform == outform) {
|
||||
if (!ASN1_STRING_set(dest, in, len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return str_type;
|
||||
}
|
||||
|
||||
/* Work out how much space the destination will need */
|
||||
switch (outform) {
|
||||
case MBSTRING_ASC:
|
||||
outlen = nchar;
|
||||
cpyfunc = cpy_asc;
|
||||
break;
|
||||
/* Now work out output format and string type */
|
||||
outform = MBSTRING_ASC;
|
||||
if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
|
||||
else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
|
||||
else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
|
||||
else if(mask & B_ASN1_BMPSTRING) {
|
||||
str_type = V_ASN1_BMPSTRING;
|
||||
outform = MBSTRING_BMP;
|
||||
} else if(mask & B_ASN1_UNIVERSALSTRING) {
|
||||
str_type = V_ASN1_UNIVERSALSTRING;
|
||||
outform = MBSTRING_UNIV;
|
||||
} else {
|
||||
str_type = V_ASN1_UTF8STRING;
|
||||
outform = MBSTRING_UTF8;
|
||||
}
|
||||
if(!out) return str_type;
|
||||
if(*out) {
|
||||
free_out = 0;
|
||||
dest = *out;
|
||||
if(dest->data) {
|
||||
dest->length = 0;
|
||||
OPENSSL_free(dest->data);
|
||||
dest->data = NULL;
|
||||
}
|
||||
dest->type = str_type;
|
||||
} else {
|
||||
free_out = 1;
|
||||
dest = ASN1_STRING_type_new(str_type);
|
||||
if(!dest) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
*out = dest;
|
||||
}
|
||||
/* If both the same type just copy across */
|
||||
if(inform == outform) {
|
||||
if(!ASN1_STRING_set(dest, in, len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return str_type;
|
||||
}
|
||||
|
||||
case MBSTRING_BMP:
|
||||
outlen = nchar << 1;
|
||||
cpyfunc = cpy_bmp;
|
||||
break;
|
||||
/* Work out how much space the destination will need */
|
||||
switch(outform) {
|
||||
case MBSTRING_ASC:
|
||||
outlen = nchar;
|
||||
cpyfunc = cpy_asc;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
outlen = nchar << 2;
|
||||
cpyfunc = cpy_univ;
|
||||
break;
|
||||
case MBSTRING_BMP:
|
||||
outlen = nchar << 1;
|
||||
cpyfunc = cpy_bmp;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
outlen = 0;
|
||||
traverse_string(in, len, inform, out_utf8, &outlen);
|
||||
cpyfunc = cpy_utf8;
|
||||
break;
|
||||
}
|
||||
if (!(p = OPENSSL_malloc(outlen + 1))) {
|
||||
if (free_out)
|
||||
ASN1_STRING_free(dest);
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
dest->length = outlen;
|
||||
dest->data = p;
|
||||
p[outlen] = 0;
|
||||
traverse_string(in, len, inform, cpyfunc, &p);
|
||||
return str_type;
|
||||
case MBSTRING_UNIV:
|
||||
outlen = nchar << 2;
|
||||
cpyfunc = cpy_univ;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
outlen = 0;
|
||||
traverse_string(in, len, inform, out_utf8, &outlen);
|
||||
cpyfunc = cpy_utf8;
|
||||
break;
|
||||
}
|
||||
if(!(p = OPENSSL_malloc(outlen + 1))) {
|
||||
if(free_out) ASN1_STRING_free(dest);
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
dest->length = outlen;
|
||||
dest->data = p;
|
||||
p[outlen] = 0;
|
||||
traverse_string(in, len, inform, cpyfunc, &p);
|
||||
return str_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function traverses a string and passes the value of each character to
|
||||
* an optional function along with a void * argument.
|
||||
/* This function traverses a string and passes the value of each character
|
||||
* to an optional function along with a void * argument.
|
||||
*/
|
||||
|
||||
static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
int (*rfunc) (unsigned long value, void *in),
|
||||
void *arg)
|
||||
int (*rfunc)(unsigned long value, void *in), void *arg)
|
||||
{
|
||||
unsigned long value;
|
||||
int ret;
|
||||
while (len) {
|
||||
if (inform == MBSTRING_ASC) {
|
||||
value = *p++;
|
||||
len--;
|
||||
} else if (inform == MBSTRING_BMP) {
|
||||
value = *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 2;
|
||||
} else if (inform == MBSTRING_UNIV) {
|
||||
value = ((unsigned long)*p++) << 24;
|
||||
value |= ((unsigned long)*p++) << 16;
|
||||
value |= *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 4;
|
||||
} else {
|
||||
ret = UTF8_getc(p, len, &value);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
len -= ret;
|
||||
p += ret;
|
||||
}
|
||||
if (rfunc) {
|
||||
ret = rfunc(value, arg);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
while(len) {
|
||||
if(inform == MBSTRING_ASC) {
|
||||
value = *p++;
|
||||
len--;
|
||||
} else if(inform == MBSTRING_BMP) {
|
||||
value = *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 2;
|
||||
} else if(inform == MBSTRING_UNIV) {
|
||||
value = ((unsigned long)*p++) << 24;
|
||||
value |= ((unsigned long)*p++) << 16;
|
||||
value |= *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 4;
|
||||
} else {
|
||||
ret = UTF8_getc(p, len, &value);
|
||||
if(ret < 0) return -1;
|
||||
len -= ret;
|
||||
p += ret;
|
||||
}
|
||||
if(rfunc) {
|
||||
ret = rfunc(value, arg);
|
||||
if(ret <= 0) return ret;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Various utility functions for traverse_string */
|
||||
@@ -294,116 +283,108 @@ static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
|
||||
static int in_utf8(unsigned long value, void *arg)
|
||||
{
|
||||
int *nchar;
|
||||
nchar = arg;
|
||||
(*nchar)++;
|
||||
return 1;
|
||||
int *nchar;
|
||||
nchar = arg;
|
||||
(*nchar)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine size of output as a UTF8 String */
|
||||
|
||||
static int out_utf8(unsigned long value, void *arg)
|
||||
{
|
||||
int *outlen;
|
||||
outlen = arg;
|
||||
*outlen += UTF8_putc(NULL, -1, value);
|
||||
return 1;
|
||||
int *outlen;
|
||||
outlen = arg;
|
||||
*outlen += UTF8_putc(NULL, -1, value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the "type" of a string: check each character against a supplied
|
||||
* "mask".
|
||||
/* Determine the "type" of a string: check each character against a
|
||||
* supplied "mask".
|
||||
*/
|
||||
|
||||
static int type_str(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned long types;
|
||||
types = *((unsigned long *)arg);
|
||||
if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
|
||||
types &= ~B_ASN1_PRINTABLESTRING;
|
||||
if ((types & B_ASN1_IA5STRING) && (value > 127))
|
||||
types &= ~B_ASN1_IA5STRING;
|
||||
if ((types & B_ASN1_T61STRING) && (value > 0xff))
|
||||
types &= ~B_ASN1_T61STRING;
|
||||
if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
|
||||
types &= ~B_ASN1_BMPSTRING;
|
||||
if (!types)
|
||||
return -1;
|
||||
*((unsigned long *)arg) = types;
|
||||
return 1;
|
||||
unsigned long types;
|
||||
types = *((unsigned long *)arg);
|
||||
if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
|
||||
types &= ~B_ASN1_PRINTABLESTRING;
|
||||
if((types & B_ASN1_IA5STRING) && (value > 127))
|
||||
types &= ~B_ASN1_IA5STRING;
|
||||
if((types & B_ASN1_T61STRING) && (value > 0xff))
|
||||
types &= ~B_ASN1_T61STRING;
|
||||
if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
|
||||
types &= ~B_ASN1_BMPSTRING;
|
||||
if(!types) return -1;
|
||||
*((unsigned long *)arg) = types;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy one byte per character ASCII like strings */
|
||||
|
||||
static int cpy_asc(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q = (unsigned char)value;
|
||||
(*p)++;
|
||||
return 1;
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q = (unsigned char) value;
|
||||
(*p)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy two byte per character BMPStrings */
|
||||
|
||||
static int cpy_bmp(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q++ = (unsigned char)((value >> 8) & 0xff);
|
||||
*q = (unsigned char)(value & 0xff);
|
||||
*p += 2;
|
||||
return 1;
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q++ = (unsigned char) ((value >> 8) & 0xff);
|
||||
*q = (unsigned char) (value & 0xff);
|
||||
*p += 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy four byte per character UniversalStrings */
|
||||
|
||||
static int cpy_univ(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q++ = (unsigned char)((value >> 24) & 0xff);
|
||||
*q++ = (unsigned char)((value >> 16) & 0xff);
|
||||
*q++ = (unsigned char)((value >> 8) & 0xff);
|
||||
*q = (unsigned char)(value & 0xff);
|
||||
*p += 4;
|
||||
return 1;
|
||||
unsigned char **p, *q;
|
||||
p = arg;
|
||||
q = *p;
|
||||
*q++ = (unsigned char) ((value >> 24) & 0xff);
|
||||
*q++ = (unsigned char) ((value >> 16) & 0xff);
|
||||
*q++ = (unsigned char) ((value >> 8) & 0xff);
|
||||
*q = (unsigned char) (value & 0xff);
|
||||
*p += 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy to a UTF8String */
|
||||
|
||||
static int cpy_utf8(unsigned long value, void *arg)
|
||||
{
|
||||
unsigned char **p;
|
||||
int ret;
|
||||
p = arg;
|
||||
/* We already know there is enough room so pass 0xff as the length */
|
||||
ret = UTF8_putc(*p, 0xff, value);
|
||||
*p += ret;
|
||||
return 1;
|
||||
unsigned char **p;
|
||||
int ret;
|
||||
p = arg;
|
||||
/* We already know there is enough room so pass 0xff as the length */
|
||||
ret = UTF8_putc(*p, 0xff, value);
|
||||
*p += ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return 1 if the character is permitted in a PrintableString */
|
||||
static int is_printable(unsigned long value)
|
||||
{
|
||||
int ch;
|
||||
if (value > 0x7f)
|
||||
return 0;
|
||||
ch = (int)value;
|
||||
/*
|
||||
* Note: we can't use 'isalnum' because certain accented characters may
|
||||
* count as alphanumeric in some environments.
|
||||
*/
|
||||
if ((ch >= 'a') && (ch <= 'z'))
|
||||
return 1;
|
||||
if ((ch >= 'A') && (ch <= 'Z'))
|
||||
return 1;
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
return 1;
|
||||
if ((ch == ' ') || strchr("'()+,-./:=?", ch))
|
||||
return 1;
|
||||
return 0;
|
||||
int ch;
|
||||
if(value > 0x7f) return 0;
|
||||
ch = (int) value;
|
||||
/* Note: we can't use 'isalnum' because certain accented
|
||||
* characters may count as alphanumeric in some environments.
|
||||
*/
|
||||
if((ch >= 'a') && (ch <= 'z')) return 1;
|
||||
if((ch >= 'A') && (ch <= 'Z')) return 1;
|
||||
if((ch >= '0') && (ch <= '9')) return 1;
|
||||
if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+309
-293
@@ -63,334 +63,350 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p;
|
||||
int objsize;
|
||||
{
|
||||
unsigned char *p;
|
||||
int objsize;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (0);
|
||||
if ((a == NULL) || (a->data == NULL)) return(0);
|
||||
|
||||
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
|
||||
if (pp == NULL)
|
||||
return objsize;
|
||||
objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT);
|
||||
if (pp == NULL) return objsize;
|
||||
|
||||
p = *pp;
|
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||
memcpy(p, a->data, a->length);
|
||||
p += a->length;
|
||||
p= *pp;
|
||||
ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
|
||||
memcpy(p,a->data,a->length);
|
||||
p+=a->length;
|
||||
|
||||
*pp = p;
|
||||
return (objsize);
|
||||
}
|
||||
*pp=p;
|
||||
return(objsize);
|
||||
}
|
||||
|
||||
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
|
||||
{
|
||||
int i, first, len = 0, c, use_bn;
|
||||
char ftmp[24], *tmp = ftmp;
|
||||
int tmpsize = sizeof ftmp;
|
||||
const char *p;
|
||||
unsigned long l;
|
||||
BIGNUM *bl = NULL;
|
||||
{
|
||||
int i,first,len=0,c, use_bn;
|
||||
char ftmp[24], *tmp = ftmp;
|
||||
int tmpsize = sizeof ftmp;
|
||||
const char *p;
|
||||
unsigned long l;
|
||||
BIGNUM *bl = NULL;
|
||||
|
||||
if (num == 0)
|
||||
return (0);
|
||||
else if (num == -1)
|
||||
num = strlen(buf);
|
||||
if (num == 0)
|
||||
return(0);
|
||||
else if (num == -1)
|
||||
num=strlen(buf);
|
||||
|
||||
p = buf;
|
||||
c = *(p++);
|
||||
num--;
|
||||
if ((c >= '0') && (c <= '2')) {
|
||||
first = c - '0';
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
p=buf;
|
||||
c= *(p++);
|
||||
num--;
|
||||
if ((c >= '0') && (c <= '2'))
|
||||
{
|
||||
first= c-'0';
|
||||
}
|
||||
else
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (num <= 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
|
||||
goto err;
|
||||
}
|
||||
c = *(p++);
|
||||
num--;
|
||||
for (;;) {
|
||||
if (num <= 0)
|
||||
break;
|
||||
if ((c != '.') && (c != ' ')) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
|
||||
goto err;
|
||||
}
|
||||
l = 0;
|
||||
use_bn = 0;
|
||||
for (;;) {
|
||||
if (num <= 0)
|
||||
break;
|
||||
num--;
|
||||
c = *(p++);
|
||||
if ((c == ' ') || (c == '.'))
|
||||
break;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
|
||||
goto err;
|
||||
}
|
||||
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
|
||||
use_bn = 1;
|
||||
if (!bl)
|
||||
bl = BN_new();
|
||||
if (!bl || !BN_set_word(bl, l))
|
||||
goto err;
|
||||
}
|
||||
if (use_bn) {
|
||||
if (!BN_mul_word(bl, 10L)
|
||||
|| !BN_add_word(bl, c - '0'))
|
||||
goto err;
|
||||
} else
|
||||
l = l * 10L + (long)(c - '0');
|
||||
}
|
||||
if (len == 0) {
|
||||
if ((first < 2) && (l >= 40)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (use_bn) {
|
||||
if (!BN_add_word(bl, first * 40))
|
||||
goto err;
|
||||
} else
|
||||
l += (long)first *40;
|
||||
}
|
||||
i = 0;
|
||||
if (use_bn) {
|
||||
int blsize;
|
||||
blsize = BN_num_bits(bl);
|
||||
blsize = (blsize + 6) / 7;
|
||||
if (blsize > tmpsize) {
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
tmpsize = blsize + 32;
|
||||
tmp = OPENSSL_malloc(tmpsize);
|
||||
if (!tmp)
|
||||
goto err;
|
||||
}
|
||||
while (blsize--)
|
||||
tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
|
||||
} else {
|
||||
if (num <= 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
|
||||
goto err;
|
||||
}
|
||||
c= *(p++);
|
||||
num--;
|
||||
for (;;)
|
||||
{
|
||||
if (num <= 0) break;
|
||||
if ((c != '.') && (c != ' '))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
|
||||
goto err;
|
||||
}
|
||||
l=0;
|
||||
use_bn = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (num <= 0) break;
|
||||
num--;
|
||||
c= *(p++);
|
||||
if ((c == ' ') || (c == '.'))
|
||||
break;
|
||||
if ((c < '0') || (c > '9'))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
|
||||
goto err;
|
||||
}
|
||||
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L))
|
||||
{
|
||||
use_bn = 1;
|
||||
if (!bl)
|
||||
bl = BN_new();
|
||||
if (!bl || !BN_set_word(bl, l))
|
||||
goto err;
|
||||
}
|
||||
if (use_bn)
|
||||
{
|
||||
if (!BN_mul_word(bl, 10L)
|
||||
|| !BN_add_word(bl, c-'0'))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
l=l*10L+(long)(c-'0');
|
||||
}
|
||||
if (len == 0)
|
||||
{
|
||||
if ((first < 2) && (l >= 40))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (use_bn)
|
||||
{
|
||||
if (!BN_add_word(bl, first * 40))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
l+=(long)first*40;
|
||||
}
|
||||
i=0;
|
||||
if (use_bn)
|
||||
{
|
||||
int blsize;
|
||||
blsize = BN_num_bits(bl);
|
||||
blsize = (blsize + 6)/7;
|
||||
if (blsize > tmpsize)
|
||||
{
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
tmpsize = blsize + 32;
|
||||
tmp = OPENSSL_malloc(tmpsize);
|
||||
if (!tmp)
|
||||
goto err;
|
||||
}
|
||||
while(blsize--)
|
||||
tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (;;)
|
||||
{
|
||||
tmp[i++]=(unsigned char)l&0x7f;
|
||||
l>>=7L;
|
||||
if (l == 0L) break;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
tmp[i++] = (unsigned char)l & 0x7f;
|
||||
l >>= 7L;
|
||||
if (l == 0L)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (out != NULL) {
|
||||
if (len + i > olen) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
while (--i > 0)
|
||||
out[len++] = tmp[i] | 0x80;
|
||||
out[len++] = tmp[0];
|
||||
} else
|
||||
len += i;
|
||||
}
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
if (bl)
|
||||
BN_free(bl);
|
||||
return (len);
|
||||
err:
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
if (bl)
|
||||
BN_free(bl);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (out != NULL)
|
||||
{
|
||||
if (len+i > olen)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
while (--i > 0)
|
||||
out[len++]=tmp[i]|0x80;
|
||||
out[len++]=tmp[0];
|
||||
}
|
||||
else
|
||||
len+=i;
|
||||
}
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
if (bl)
|
||||
BN_free(bl);
|
||||
return(len);
|
||||
err:
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
if (bl)
|
||||
BN_free(bl);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
||||
{
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
}
|
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (BIO_write(bp, "NULL", 4));
|
||||
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
|
||||
if (i > (int)(sizeof(buf) - 1)) {
|
||||
p = OPENSSL_malloc(i + 1);
|
||||
if (!p)
|
||||
return -1;
|
||||
i2t_ASN1_OBJECT(p, i + 1, a);
|
||||
}
|
||||
if (i <= 0)
|
||||
return BIO_write(bp, "<INVALID>", 9);
|
||||
BIO_write(bp, p, i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return (i);
|
||||
}
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return(BIO_write(bp,"NULL",4));
|
||||
i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
|
||||
if (i > (int)(sizeof(buf) - 1))
|
||||
{
|
||||
p = OPENSSL_malloc(i + 1);
|
||||
if (!p)
|
||||
return -1;
|
||||
i2t_ASN1_OBJECT(p,i + 1,a);
|
||||
}
|
||||
if (i <= 0)
|
||||
return BIO_write(bp, "<INVALID>", 9);
|
||||
BIO_write(bp,p,i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return(i);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long length)
|
||||
long length)
|
||||
{
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag, xclass;
|
||||
int inf, i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag,xclass;
|
||||
int inf,i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_OBJECT) {
|
||||
i = ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if (ret)
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (NULL);
|
||||
if (tag != V_ASN1_OBJECT)
|
||||
{
|
||||
i=ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if(ret) *pp = p;
|
||||
return ret;
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
|
||||
/*
|
||||
* Sanity check OID encoding. Need at least one content octet. MSB must
|
||||
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
|
||||
* see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
for (i = 0; i < length; i++, p++) {
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Sanity check OID encoding.
|
||||
* Need at least one content octet.
|
||||
* MSB must be clear in the last octet.
|
||||
* can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
for (i = 0; i < length; i++, p++)
|
||||
{
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
|
||||
* ->ln
|
||||
*/
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
|
||||
if ((ret = ASN1_OBJECT_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
/* only the ASN1_OBJECTs from the 'table' will have values
|
||||
* for ->sn or ->ln */
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
|
||||
{
|
||||
if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
|
||||
}
|
||||
else ret=(*a);
|
||||
|
||||
p = *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length)) {
|
||||
ret->length = 0;
|
||||
if (data != NULL)
|
||||
OPENSSL_free(data);
|
||||
data = (unsigned char *)OPENSSL_malloc(length);
|
||||
if (data == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
memcpy(data, p, length);
|
||||
/* reattach data to object, after which it remains const */
|
||||
ret->data = data;
|
||||
ret->length = length;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
|
||||
p += length;
|
||||
p= *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length))
|
||||
{
|
||||
ret->length=0;
|
||||
if (data != NULL) OPENSSL_free(data);
|
||||
data=(unsigned char *)OPENSSL_malloc(length);
|
||||
if (data == NULL)
|
||||
{ i=ERR_R_MALLOC_FAILURE; goto err; }
|
||||
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
memcpy(data,p,length);
|
||||
/* reattach data to object, after which it remains const */
|
||||
ret->data =data;
|
||||
ret->length=length;
|
||||
ret->sn=NULL;
|
||||
ret->ln=NULL;
|
||||
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
|
||||
p+=length;
|
||||
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void)
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
|
||||
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->data = NULL;
|
||||
ret->nid = 0;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return (ret);
|
||||
}
|
||||
ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(NULL);
|
||||
}
|
||||
ret->length=0;
|
||||
ret->data=NULL;
|
||||
ret->nid=0;
|
||||
ret->sn=NULL;
|
||||
ret->ln=NULL;
|
||||
ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void ASN1_OBJECT_free(ASN1_OBJECT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict
|
||||
* const checking. Doing this on a "real"
|
||||
* compile will cause memory leaks */
|
||||
if (a->sn != NULL)
|
||||
OPENSSL_free((void *)a->sn);
|
||||
if (a->ln != NULL)
|
||||
OPENSSL_free((void *)a->ln);
|
||||
{
|
||||
if (a == NULL) return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
|
||||
{
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
|
||||
if (a->sn != NULL) OPENSSL_free((void *)a->sn);
|
||||
if (a->ln != NULL) OPENSSL_free((void *)a->ln);
|
||||
#endif
|
||||
a->sn = a->ln = NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free((void *)a->data);
|
||||
a->data = NULL;
|
||||
a->length = 0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
a->sn=a->ln=NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
|
||||
{
|
||||
if (a->data != NULL) OPENSSL_free((void *)a->data);
|
||||
a->data=NULL;
|
||||
a->length=0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
|
||||
o.sn = sn;
|
||||
o.ln = ln;
|
||||
o.data = data;
|
||||
o.nid = nid;
|
||||
o.length = len;
|
||||
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return (OBJ_dup(&o));
|
||||
}
|
||||
o.sn=sn;
|
||||
o.ln=ln;
|
||||
o.data=data;
|
||||
o.nid=nid;
|
||||
o.length=len;
|
||||
o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return(OBJ_dup(&o));
|
||||
}
|
||||
|
||||
+6
-13
@@ -59,19 +59,12 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_dup(x);
|
||||
}
|
||||
{ return M_ASN1_OCTET_STRING_dup(x); }
|
||||
|
||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
|
||||
const ASN1_OCTET_STRING *b)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_cmp(a, b);
|
||||
}
|
||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
|
||||
{ return M_ASN1_OCTET_STRING_cmp(a, b); }
|
||||
|
||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
|
||||
int len)
|
||||
{
|
||||
return M_ASN1_OCTET_STRING_set(x, d, len);
|
||||
}
|
||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
|
||||
{ return M_ASN1_OCTET_STRING_set(x, d, len); }
|
||||
|
||||
+52
-54
@@ -59,63 +59,61 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
|
||||
{
|
||||
int c;
|
||||
int ia5 = 0;
|
||||
int t61 = 0;
|
||||
{
|
||||
int c;
|
||||
int ia5=0;
|
||||
int t61=0;
|
||||
|
||||
if (len <= 0)
|
||||
len = -1;
|
||||
if (s == NULL)
|
||||
return (V_ASN1_PRINTABLESTRING);
|
||||
if (len <= 0) len= -1;
|
||||
if (s == NULL) return(V_ASN1_PRINTABLESTRING);
|
||||
|
||||
while ((*s) && (len-- != 0)) {
|
||||
c = *(s++);
|
||||
if (!(((c >= 'a') && (c <= 'z')) ||
|
||||
((c >= 'A') && (c <= 'Z')) ||
|
||||
(c == ' ') ||
|
||||
((c >= '0') && (c <= '9')) ||
|
||||
(c == ' ') || (c == '\'') ||
|
||||
(c == '(') || (c == ')') ||
|
||||
(c == '+') || (c == ',') ||
|
||||
(c == '-') || (c == '.') ||
|
||||
(c == '/') || (c == ':') || (c == '=') || (c == '?')))
|
||||
ia5 = 1;
|
||||
if (c & 0x80)
|
||||
t61 = 1;
|
||||
}
|
||||
if (t61)
|
||||
return (V_ASN1_T61STRING);
|
||||
if (ia5)
|
||||
return (V_ASN1_IA5STRING);
|
||||
return (V_ASN1_PRINTABLESTRING);
|
||||
}
|
||||
while ((*s) && (len-- != 0))
|
||||
{
|
||||
c= *(s++);
|
||||
if (!( ((c >= 'a') && (c <= 'z')) ||
|
||||
((c >= 'A') && (c <= 'Z')) ||
|
||||
(c == ' ') ||
|
||||
((c >= '0') && (c <= '9')) ||
|
||||
(c == ' ') || (c == '\'') ||
|
||||
(c == '(') || (c == ')') ||
|
||||
(c == '+') || (c == ',') ||
|
||||
(c == '-') || (c == '.') ||
|
||||
(c == '/') || (c == ':') ||
|
||||
(c == '=') || (c == '?')))
|
||||
ia5=1;
|
||||
if (c&0x80)
|
||||
t61=1;
|
||||
}
|
||||
if (t61) return(V_ASN1_T61STRING);
|
||||
if (ia5) return(V_ASN1_IA5STRING);
|
||||
return(V_ASN1_PRINTABLESTRING);
|
||||
}
|
||||
|
||||
int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
|
||||
if (s->type != V_ASN1_UNIVERSALSTRING)
|
||||
return (0);
|
||||
if ((s->length % 4) != 0)
|
||||
return (0);
|
||||
p = s->data;
|
||||
for (i = 0; i < s->length; i += 4) {
|
||||
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
|
||||
break;
|
||||
else
|
||||
p += 4;
|
||||
}
|
||||
if (i < s->length)
|
||||
return (0);
|
||||
p = s->data;
|
||||
for (i = 3; i < s->length; i += 4) {
|
||||
*(p++) = s->data[i];
|
||||
}
|
||||
*(p) = '\0';
|
||||
s->length /= 4;
|
||||
s->type = ASN1_PRINTABLE_type(s->data, s->length);
|
||||
return (1);
|
||||
}
|
||||
if (s->type != V_ASN1_UNIVERSALSTRING) return(0);
|
||||
if ((s->length%4) != 0) return(0);
|
||||
p=s->data;
|
||||
for (i=0; i<s->length; i+=4)
|
||||
{
|
||||
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
|
||||
break;
|
||||
else
|
||||
p+=4;
|
||||
}
|
||||
if (i < s->length) return(0);
|
||||
p=s->data;
|
||||
for (i=3; i<s->length; i+=4)
|
||||
{
|
||||
*(p++)=s->data[i];
|
||||
}
|
||||
*(p)='\0';
|
||||
s->length/=4;
|
||||
s->type=ASN1_PRINTABLE_type(s->data,s->length);
|
||||
return(1);
|
||||
}
|
||||
|
||||
+152
-174
@@ -56,253 +56,231 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
|
||||
static void st_free(ASN1_STRING_TABLE *tbl);
|
||||
|
||||
/*
|
||||
* This is the global mask for the mbstring functions: this is use to mask
|
||||
* out certain types (such as BMPString and UTF8String) because certain
|
||||
* software (e.g. Netscape) has problems with them.
|
||||
/* This is the global mask for the mbstring functions: this is use to
|
||||
* mask out certain types (such as BMPString and UTF8String) because
|
||||
* certain software (e.g. Netscape) has problems with them.
|
||||
*/
|
||||
|
||||
static unsigned long global_mask = B_ASN1_UTF8STRING;
|
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask)
|
||||
{
|
||||
global_mask = mask;
|
||||
global_mask = mask;
|
||||
}
|
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void)
|
||||
{
|
||||
return global_mask;
|
||||
return global_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
|
||||
* value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
|
||||
* recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
|
||||
* recommendation for 2004). default: the default value, Printable, T61, BMP.
|
||||
/* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is:
|
||||
* MASK:XXXX : a numerical mask value.
|
||||
* nobmp : Don't use BMPStrings (just Printable, T61).
|
||||
* pkix : PKIX recommendation in RFC2459.
|
||||
* utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
|
||||
* default: the default value, Printable, T61, BMP.
|
||||
*/
|
||||
|
||||
int ASN1_STRING_set_default_mask_asc(const char *p)
|
||||
{
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
if (!strncmp(p, "MASK:", 5)) {
|
||||
if (!p[5])
|
||||
return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if (*end)
|
||||
return 0;
|
||||
} else if (!strcmp(p, "nombstr"))
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
|
||||
else if (!strcmp(p, "pkix"))
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if (!strcmp(p, "utf8only"))
|
||||
mask = B_ASN1_UTF8STRING;
|
||||
else if (!strcmp(p, "default"))
|
||||
mask = 0xFFFFFFFFL;
|
||||
else
|
||||
return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
if(!strncmp(p, "MASK:", 5)) {
|
||||
if(!p[5]) return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if(*end) return 0;
|
||||
} else if(!strcmp(p, "nombstr"))
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
|
||||
else if(!strcmp(p, "pkix"))
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
|
||||
else if(!strcmp(p, "default"))
|
||||
mask = 0xFFFFFFFFL;
|
||||
else return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function generates an ASN1_STRING based on limits in a
|
||||
* table. Frequently the types and length of an ASN1_STRING are restricted by
|
||||
* a corresponding OID. For example certificates and certificate requests.
|
||||
/* The following function generates an ASN1_STRING based on limits in a table.
|
||||
* Frequently the types and length of an ASN1_STRING are restricted by a
|
||||
* corresponding OID. For example certificates and certificate requests.
|
||||
*/
|
||||
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
|
||||
const unsigned char *in, int inlen,
|
||||
int inform, int nid)
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
|
||||
int inlen, int inform, int nid)
|
||||
{
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
if (!out)
|
||||
out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if (tbl) {
|
||||
mask = tbl->mask;
|
||||
if (!(tbl->flags & STABLE_NO_MASK))
|
||||
mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else
|
||||
ret =
|
||||
ASN1_mbstring_copy(out, in, inlen, inform,
|
||||
DIRSTRING_TYPE & global_mask);
|
||||
if (ret <= 0)
|
||||
return NULL;
|
||||
return *out;
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
if(!out) out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if(tbl) {
|
||||
mask = tbl->mask;
|
||||
if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask);
|
||||
if(ret <= 0) return NULL;
|
||||
return *out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the tables and helper functions for the string table:
|
||||
/* Now the tables and helper functions for the string table:
|
||||
*/
|
||||
|
||||
/* size limits: this stuff is taken straight from RFC3280 */
|
||||
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
|
||||
|
||||
/* This table must be kept in NID order */
|
||||
|
||||
static const ASN1_STRING_TABLE tbl_standard[] = {
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
|
||||
0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
|
||||
};
|
||||
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
|
||||
const ASN1_STRING_TABLE **b)
|
||||
const ASN1_STRING_TABLE **b)
|
||||
{
|
||||
return (*a)->nid - (*b)->nid;
|
||||
return (*a)->nid - (*b)->nid;
|
||||
}
|
||||
|
||||
static int table_cmp(const void *in_a, const void *in_b)
|
||||
{
|
||||
const ASN1_STRING_TABLE *a = in_a;
|
||||
const ASN1_STRING_TABLE *b = in_b;
|
||||
return a->nid - b->nid;
|
||||
const ASN1_STRING_TABLE *a = in_a;
|
||||
const ASN1_STRING_TABLE *b = in_b;
|
||||
return a->nid - b->nid;
|
||||
}
|
||||
|
||||
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
|
||||
{
|
||||
int found;
|
||||
size_t idx;
|
||||
ASN1_STRING_TABLE *ttmp;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
fnd.nid = nid;
|
||||
int found;
|
||||
size_t idx;
|
||||
ASN1_STRING_TABLE *ttmp;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
fnd.nid = nid;
|
||||
|
||||
ttmp =
|
||||
bsearch(&fnd, tbl_standard,
|
||||
sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
|
||||
sizeof(ASN1_STRING_TABLE), table_cmp);
|
||||
if (ttmp)
|
||||
return ttmp;
|
||||
if (!stable)
|
||||
return NULL;
|
||||
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
|
||||
if (!found)
|
||||
return NULL;
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
ttmp = bsearch(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), sizeof(ASN1_STRING_TABLE), table_cmp);
|
||||
if(ttmp) return ttmp;
|
||||
if(!stable) return NULL;
|
||||
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
|
||||
if (!found) return NULL;
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
}
|
||||
|
||||
|
||||
int ASN1_STRING_TABLE_add(int nid,
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
char new_nid = 0;
|
||||
flags &= ~STABLE_FLAGS_MALLOC;
|
||||
if (!stable)
|
||||
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if (!stable) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
|
||||
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
|
||||
if (!tmp) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
tmp->flags = flags | STABLE_FLAGS_MALLOC;
|
||||
tmp->nid = nid;
|
||||
new_nid = 1;
|
||||
} else
|
||||
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
|
||||
if (minsize != -1)
|
||||
tmp->minsize = minsize;
|
||||
if (maxsize != -1)
|
||||
tmp->maxsize = maxsize;
|
||||
tmp->mask = mask;
|
||||
if (new_nid)
|
||||
sk_ASN1_STRING_TABLE_push(stable, tmp);
|
||||
return 1;
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
char new_nid = 0;
|
||||
flags &= ~STABLE_FLAGS_MALLOC;
|
||||
if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if(!stable) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
|
||||
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
|
||||
if(!tmp) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
tmp->flags = flags | STABLE_FLAGS_MALLOC;
|
||||
tmp->nid = nid;
|
||||
new_nid = 1;
|
||||
} else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
|
||||
if(minsize != -1) tmp->minsize = minsize;
|
||||
if(maxsize != -1) tmp->maxsize = maxsize;
|
||||
tmp->mask = mask;
|
||||
if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ASN1_STRING_TABLE_cleanup(void)
|
||||
{
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
tmp = stable;
|
||||
if (!tmp)
|
||||
return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
tmp = stable;
|
||||
if(!tmp) return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
}
|
||||
|
||||
static void st_free(ASN1_STRING_TABLE *tbl)
|
||||
{
|
||||
if (tbl->flags & STABLE_FLAGS_MALLOC)
|
||||
OPENSSL_free(tbl);
|
||||
if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl);
|
||||
}
|
||||
|
||||
|
||||
#ifdef STRING_TABLE_TEST
|
||||
|
||||
int main(void)
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
int i, last_nid = -1;
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
int i, last_nid = -1;
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
|
||||
if (tmp->nid < last_nid) {
|
||||
last_nid = 0;
|
||||
break;
|
||||
}
|
||||
last_nid = tmp->nid;
|
||||
}
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
{
|
||||
if (tmp->nid < last_nid)
|
||||
{
|
||||
last_nid = 0;
|
||||
break;
|
||||
}
|
||||
last_nid = tmp->nid;
|
||||
}
|
||||
|
||||
if (last_nid != 0) {
|
||||
printf("Table order OK\n");
|
||||
exit(0);
|
||||
}
|
||||
if (last_nid != 0)
|
||||
{
|
||||
printf("Table order OK\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
|
||||
OBJ_nid2ln(tmp->nid));
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
|
||||
OBJ_nid2ln(tmp->nid));
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+118
-114
@@ -67,10 +67,12 @@
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
/*
|
||||
* This is an implementation of the ASN1 Time structure which is: Time ::=
|
||||
* CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
|
||||
* Henson.
|
||||
|
||||
/* This is an implementation of the ASN1 Time structure which is:
|
||||
* Time ::= CHOICE {
|
||||
* utcTime UTCTime,
|
||||
* generalTime GeneralizedTime }
|
||||
* written by Steve Henson.
|
||||
*/
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
|
||||
@@ -79,139 +81,141 @@ IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
|
||||
|
||||
#if 0
|
||||
int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
|
||||
{
|
||||
if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
|
||||
return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
|
||||
a->type, V_ASN1_UNIVERSAL));
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
|
||||
return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
|
||||
a->type ,V_ASN1_UNIVERSAL));
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
|
||||
{
|
||||
return ASN1_TIME_adj(s, t, 0, 0);
|
||||
}
|
||||
{
|
||||
return ASN1_TIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if ((ts->tm_year >= 50) && (ts->tm_year < 150))
|
||||
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
ts=OPENSSL_gmtime(&t,&data);
|
||||
if (ts == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec)
|
||||
{
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if((ts->tm_year >= 50) && (ts->tm_year < 150))
|
||||
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
|
||||
int ASN1_TIME_check(ASN1_TIME *t)
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
char *str;
|
||||
int newlen;
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
if (!ASN1_TIME_check(t))
|
||||
return NULL;
|
||||
if (!ASN1_TIME_check(t)) return NULL;
|
||||
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
return NULL;
|
||||
if (out)
|
||||
*out = ret;
|
||||
} else
|
||||
ret = *out;
|
||||
if (!out || !*out)
|
||||
{
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new ()))
|
||||
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))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
{
|
||||
if(!ASN1_STRING_set(ret, t->data, t->length))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
return NULL;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5')
|
||||
BUF_strlcpy(str, "19", newlen);
|
||||
else
|
||||
BUF_strlcpy(str, "20", newlen);
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
return NULL;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
|
||||
else BUF_strlcpy(str, "20", newlen);
|
||||
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
if (!ASN1_TIME_check(&t))
|
||||
{
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
if (!ASN1_TIME_check(&t))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
|
||||
return 0;
|
||||
|
||||
if (!ASN1_TIME_check(&t)) {
|
||||
t.type = V_ASN1_GENERALIZEDTIME;
|
||||
if (!ASN1_TIME_check(&t))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
|
||||
{
|
||||
if (t == NULL) {
|
||||
time_t now_t;
|
||||
time(&now_t);
|
||||
if (OPENSSL_gmtime(&now_t, tm))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
if (t == NULL)
|
||||
{
|
||||
time_t now_t;
|
||||
time(&now_t);
|
||||
if (OPENSSL_gmtime(&now_t, tm))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (t->type == V_ASN1_UTCTIME)
|
||||
return asn1_utctime_to_tm(tm, t);
|
||||
else if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return asn1_generalizedtime_to_tm(tm, t);
|
||||
|
||||
if (t->type == V_ASN1_UTCTIME)
|
||||
return asn1_utctime_to_tm(tm, t);
|
||||
else if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return asn1_generalizedtime_to_tm(tm, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_TIME_diff(int *pday, int *psec,
|
||||
const ASN1_TIME *from, const ASN1_TIME *to)
|
||||
{
|
||||
struct tm tm_from, tm_to;
|
||||
if (!asn1_time_to_tm(&tm_from, from))
|
||||
return 0;
|
||||
if (!asn1_time_to_tm(&tm_to, to))
|
||||
return 0;
|
||||
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
|
||||
}
|
||||
const ASN1_TIME *from, const ASN1_TIME *to)
|
||||
{
|
||||
struct tm tm_from, tm_to;
|
||||
if (!asn1_time_to_tm(&tm_from, from))
|
||||
return 0;
|
||||
if (!asn1_time_to_tm(&tm_to, to))
|
||||
return 0;
|
||||
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
|
||||
}
|
||||
|
||||
+86
-79
@@ -61,93 +61,100 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
int ASN1_TYPE_get(ASN1_TYPE *a)
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return (a->type);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return(a->type);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
|
||||
{
|
||||
if (a->value.ptr != NULL) {
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
|
||||
}
|
||||
a->type = type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr = value;
|
||||
}
|
||||
{
|
||||
if (a->value.ptr != NULL)
|
||||
{
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
|
||||
}
|
||||
a->type=type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr=value;
|
||||
}
|
||||
|
||||
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN)) {
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
} else if (type == V_ASN1_OBJECT) {
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
} else {
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN))
|
||||
{
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
}
|
||||
else if (type == V_ASN1_OBJECT)
|
||||
{
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns 0 if they are equal, != 0 otherwise. */
|
||||
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
|
||||
{
|
||||
int result = -1;
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (!a || !b || a->type != b->type)
|
||||
return -1;
|
||||
if (!a || !b || a->type != b->type) return -1;
|
||||
|
||||
switch (a->type) {
|
||||
case V_ASN1_OBJECT:
|
||||
result = OBJ_cmp(a->value.object, b->value.object);
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
break;
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_NEG_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
case V_ASN1_NEG_ENUMERATED:
|
||||
case V_ASN1_BIT_STRING:
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_OTHER:
|
||||
default:
|
||||
result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
|
||||
(ASN1_STRING *)b->value.ptr);
|
||||
break;
|
||||
}
|
||||
switch (a->type)
|
||||
{
|
||||
case V_ASN1_OBJECT:
|
||||
result = OBJ_cmp(a->value.object, b->value.object);
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
break;
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_NEG_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
case V_ASN1_NEG_ENUMERATED:
|
||||
case V_ASN1_BIT_STRING:
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_OTHER:
|
||||
default:
|
||||
result = ASN1_STRING_cmp((ASN1_STRING *) a->value.ptr,
|
||||
(ASN1_STRING *) b->value.ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+234
-227
@@ -63,273 +63,280 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.h>
|
||||
|
||||
#include "asn1_locl.h"
|
||||
|
||||
#if 0
|
||||
int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
|
||||
{
|
||||
return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
|
||||
V_ASN1_UTCTIME, V_ASN1_UNIVERSAL));
|
||||
}
|
||||
{
|
||||
return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
|
||||
V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
|
||||
}
|
||||
|
||||
|
||||
ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
ASN1_UTCTIME *ret = NULL;
|
||||
long length)
|
||||
{
|
||||
ASN1_UTCTIME *ret=NULL;
|
||||
|
||||
ret = (ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a, pp, length,
|
||||
V_ASN1_UTCTIME, V_ASN1_UNIVERSAL);
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR);
|
||||
return (NULL);
|
||||
}
|
||||
if (!ASN1_UTCTIME_check(ret)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
|
||||
goto err;
|
||||
}
|
||||
ret=(ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a,pp,length,
|
||||
V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR);
|
||||
return(NULL);
|
||||
}
|
||||
if (!ASN1_UTCTIME_check(ret))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_UTCTIME_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
return(ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_UTCTIME_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
|
||||
{
|
||||
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
{
|
||||
static const int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
|
||||
static const int max[8]={99,12,31,23,59,59,12,59};
|
||||
char *a;
|
||||
int n,i,l,o;
|
||||
|
||||
if (d->type != V_ASN1_UTCTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
if (d->type != V_ASN1_UTCTIME) return(0);
|
||||
l=d->length;
|
||||
a=(char *)d->data;
|
||||
o=0;
|
||||
|
||||
if (l < 11)
|
||||
goto err;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
if (l < 11) goto err;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
if ((i == 5) && ((a[o] == 'Z') ||
|
||||
(a[o] == '+') || (a[o] == '-')))
|
||||
{
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n= a[o]-'0';
|
||||
if (++o > l) goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n=(n*10)+ a[o]-'0';
|
||||
if (++o > l) goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n < 50 ? n + 100 : n;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 6; i < 8; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 6)
|
||||
offset = n * 3600;
|
||||
else if (i == 7)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
return o == l;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
if ((n < min[i]) || (n > max[i])) goto err;
|
||||
if (tm)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
tm->tm_year = n < 50 ? n + 100 : n;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-'))
|
||||
{
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
o++;
|
||||
if (o+4 > l) goto err;
|
||||
for (i=6; i<8; i++)
|
||||
{
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n= a[o]-'0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n=(n*10)+ a[o]-'0';
|
||||
if ((n < min[i]) || (n > max[i])) goto err;
|
||||
if (tm)
|
||||
{
|
||||
if (i == 6)
|
||||
offset = n * 3600;
|
||||
else if (i == 7)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
return o == l;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_UTCTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
t.type=V_ASN1_UTCTIME;
|
||||
t.length=strlen(str);
|
||||
t.data=(unsigned char *)str;
|
||||
if (ASN1_UTCTIME_check(&t))
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str,t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
int free_s = 0;
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
int free_s = 0;
|
||||
|
||||
if (s == NULL) {
|
||||
free_s = 1;
|
||||
s = M_ASN1_UTCTIME_new();
|
||||
}
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
if (s == NULL)
|
||||
{
|
||||
free_s = 1;
|
||||
s=M_ASN1_UTCTIME_new();
|
||||
}
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
ts=OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
if ((ts->tm_year < 50) || (ts->tm_year >= 150))
|
||||
goto err;
|
||||
if (offset_day || offset_sec)
|
||||
{
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data = (unsigned char *)p;
|
||||
}
|
||||
if((ts->tm_year < 50) || (ts->tm_year >= 150))
|
||||
goto err;
|
||||
|
||||
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;
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data=(unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
|
||||
ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
|
||||
s->length=strlen(p);
|
||||
s->type=V_ASN1_UTCTIME;
|
||||
return(s);
|
||||
err:
|
||||
if (free_s && s)
|
||||
M_ASN1_UTCTIME_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
s->length = strlen(p);
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
return (s);
|
||||
err:
|
||||
if (free_s && s)
|
||||
M_ASN1_UTCTIME_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
struct tm stm, ttm;
|
||||
int day, sec;
|
||||
{
|
||||
struct tm stm, ttm;
|
||||
int day, sec;
|
||||
|
||||
if (!asn1_utctime_to_tm(&stm, s))
|
||||
return -2;
|
||||
if (!asn1_utctime_to_tm(&stm, s))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime(&t, &ttm))
|
||||
return -2;
|
||||
if (!OPENSSL_gmtime(&t, &ttm))
|
||||
return -2;
|
||||
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
|
||||
if (day > 0)
|
||||
return 1;
|
||||
if (day < 0)
|
||||
return -1;
|
||||
if (sec > 0)
|
||||
return 1;
|
||||
if (sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (day > 0)
|
||||
return 1;
|
||||
if (day < 0)
|
||||
return -1;
|
||||
if (sec > 0)
|
||||
return 1;
|
||||
if (sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
|
||||
{
|
||||
struct tm tm;
|
||||
int offset;
|
||||
{
|
||||
struct tm tm;
|
||||
int offset;
|
||||
|
||||
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);
|
||||
if (tm.tm_year < 50)
|
||||
tm.tm_year += 100;
|
||||
tm.tm_mon = g2(s->data + 2) - 1;
|
||||
tm.tm_mday = g2(s->data + 4);
|
||||
tm.tm_hour = g2(s->data + 6);
|
||||
tm.tm_min = g2(s->data + 8);
|
||||
tm.tm_sec = g2(s->data + 10);
|
||||
if (s->data[12] == 'Z')
|
||||
offset = 0;
|
||||
else {
|
||||
offset = g2(s->data + 13) * 60 + g2(s->data + 15);
|
||||
if (s->data[12] == '-')
|
||||
offset = -offset;
|
||||
}
|
||||
# undef g2
|
||||
#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
|
||||
tm.tm_year=g2(s->data);
|
||||
if(tm.tm_year < 50)
|
||||
tm.tm_year+=100;
|
||||
tm.tm_mon=g2(s->data+2)-1;
|
||||
tm.tm_mday=g2(s->data+4);
|
||||
tm.tm_hour=g2(s->data+6);
|
||||
tm.tm_min=g2(s->data+8);
|
||||
tm.tm_sec=g2(s->data+10);
|
||||
if(s->data[12] == 'Z')
|
||||
offset=0;
|
||||
else
|
||||
{
|
||||
offset=g2(s->data+13)*60+g2(s->data+15);
|
||||
if(s->data[12] == '-')
|
||||
offset= -offset;
|
||||
}
|
||||
#undef g2
|
||||
|
||||
return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
|
||||
* timezone instead of UTC, and unless
|
||||
* we rewrite OpenSSL in Lisp we cannot
|
||||
* locally change the timezone without
|
||||
* possibly interfering with other
|
||||
* parts of the program. timegm, which
|
||||
* uses UTC, is non-standard. Also
|
||||
* time_t is inappropriate for general
|
||||
* UTC times because it may a 32 bit
|
||||
* type. */
|
||||
}
|
||||
return mktime(&tm)-offset*60; /* FIXME: mktime assumes the current timezone
|
||||
* instead of UTC, and unless we rewrite OpenSSL
|
||||
* in Lisp we cannot locally change the timezone
|
||||
* without possibly interfering with other parts
|
||||
* of the program. timegm, which uses UTC, is
|
||||
* non-standard.
|
||||
* Also time_t is inappropriate for general
|
||||
* UTC times because it may a 32 bit type. */
|
||||
}
|
||||
#endif
|
||||
|
||||
+135
-159
@@ -59,176 +59,152 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* UTF8 utilities */
|
||||
|
||||
/*
|
||||
* This parses a UTF8 string one character at a time. It is passed a pointer
|
||||
* to the string and the length of the string. It sets 'value' to the value
|
||||
* of the current character. It returns the number of characters read or a
|
||||
* negative error code: -1 = string too short -2 = illegal character -3 =
|
||||
* subsequent characters not of the form 10xxxxxx -4 = character encoded
|
||||
* incorrectly (not minimal length).
|
||||
/* This parses a UTF8 string one character at a time. It is passed a pointer
|
||||
* to the string and the length of the string. It sets 'value' to the value of
|
||||
* the current character. It returns the number of characters read or a
|
||||
* negative error code:
|
||||
* -1 = string too short
|
||||
* -2 = illegal character
|
||||
* -3 = subsequent characters not of the form 10xxxxxx
|
||||
* -4 = character encoded incorrectly (not minimal length).
|
||||
*/
|
||||
|
||||
int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
|
||||
{
|
||||
const unsigned char *p;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
p = str;
|
||||
const unsigned char *p;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
if(len <= 0) return 0;
|
||||
p = str;
|
||||
|
||||
/* Check syntax and work out the encoded value (if correct) */
|
||||
if ((*p & 0x80) == 0) {
|
||||
value = *p++ & 0x7f;
|
||||
ret = 1;
|
||||
} else if ((*p & 0xe0) == 0xc0) {
|
||||
if (len < 2)
|
||||
return -1;
|
||||
if ((p[1] & 0xc0) != 0x80)
|
||||
return -3;
|
||||
value = (*p++ & 0x1f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x80)
|
||||
return -4;
|
||||
ret = 2;
|
||||
} else if ((*p & 0xf0) == 0xe0) {
|
||||
if (len < 3)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = (*p++ & 0xf) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x800)
|
||||
return -4;
|
||||
ret = 3;
|
||||
} else if ((*p & 0xf8) == 0xf0) {
|
||||
if (len < 4)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = ((unsigned long)(*p++ & 0x7)) << 18;
|
||||
value |= (*p++ & 0x3f) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x10000)
|
||||
return -4;
|
||||
ret = 4;
|
||||
} else if ((*p & 0xfc) == 0xf8) {
|
||||
if (len < 5)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80)
|
||||
|| ((p[4] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = ((unsigned long)(*p++ & 0x3)) << 24;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x200000)
|
||||
return -4;
|
||||
ret = 5;
|
||||
} else if ((*p & 0xfe) == 0xfc) {
|
||||
if (len < 6)
|
||||
return -1;
|
||||
if (((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80)
|
||||
|| ((p[4] & 0xc0) != 0x80)
|
||||
|| ((p[5] & 0xc0) != 0x80))
|
||||
return -3;
|
||||
value = ((unsigned long)(*p++ & 0x1)) << 30;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 24;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if (value < 0x4000000)
|
||||
return -4;
|
||||
ret = 6;
|
||||
} else
|
||||
return -2;
|
||||
*val = value;
|
||||
return ret;
|
||||
/* Check syntax and work out the encoded value (if correct) */
|
||||
if((*p & 0x80) == 0) {
|
||||
value = *p++ & 0x7f;
|
||||
ret = 1;
|
||||
} else if((*p & 0xe0) == 0xc0) {
|
||||
if(len < 2) return -1;
|
||||
if((p[1] & 0xc0) != 0x80) return -3;
|
||||
value = (*p++ & 0x1f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if(value < 0x80) return -4;
|
||||
ret = 2;
|
||||
} else if((*p & 0xf0) == 0xe0) {
|
||||
if(len < 3) return -1;
|
||||
if( ((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80) ) return -3;
|
||||
value = (*p++ & 0xf) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if(value < 0x800) return -4;
|
||||
ret = 3;
|
||||
} else if((*p & 0xf8) == 0xf0) {
|
||||
if(len < 4) return -1;
|
||||
if( ((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80) ) return -3;
|
||||
value = ((unsigned long)(*p++ & 0x7)) << 18;
|
||||
value |= (*p++ & 0x3f) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if(value < 0x10000) return -4;
|
||||
ret = 4;
|
||||
} else if((*p & 0xfc) == 0xf8) {
|
||||
if(len < 5) return -1;
|
||||
if( ((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80)
|
||||
|| ((p[4] & 0xc0) != 0x80) ) return -3;
|
||||
value = ((unsigned long)(*p++ & 0x3)) << 24;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if(value < 0x200000) return -4;
|
||||
ret = 5;
|
||||
} else if((*p & 0xfe) == 0xfc) {
|
||||
if(len < 6) return -1;
|
||||
if( ((p[1] & 0xc0) != 0x80)
|
||||
|| ((p[2] & 0xc0) != 0x80)
|
||||
|| ((p[3] & 0xc0) != 0x80)
|
||||
|| ((p[4] & 0xc0) != 0x80)
|
||||
|| ((p[5] & 0xc0) != 0x80) ) return -3;
|
||||
value = ((unsigned long)(*p++ & 0x1)) << 30;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 24;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
|
||||
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
|
||||
value |= (*p++ & 0x3f) << 6;
|
||||
value |= *p++ & 0x3f;
|
||||
if(value < 0x4000000) return -4;
|
||||
ret = 6;
|
||||
} else return -2;
|
||||
*val = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This takes a character 'value' and writes the UTF8 encoded value in 'str'
|
||||
* where 'str' is a buffer containing 'len' characters. Returns the number of
|
||||
* characters written or -1 if 'len' is too small. 'str' can be set to NULL
|
||||
* in which case it just returns the number of characters. It will need at
|
||||
* most 6 characters.
|
||||
/* This takes a character 'value' and writes the UTF8 encoded value in
|
||||
* 'str' where 'str' is a buffer containing 'len' characters. Returns
|
||||
* the number of characters written or -1 if 'len' is too small. 'str' can
|
||||
* be set to NULL in which case it just returns the number of characters.
|
||||
* It will need at most 6 characters.
|
||||
*/
|
||||
|
||||
int UTF8_putc(unsigned char *str, int len, unsigned long value)
|
||||
{
|
||||
if (!str)
|
||||
len = 6; /* Maximum we will need */
|
||||
else if (len <= 0)
|
||||
return -1;
|
||||
if (value < 0x80) {
|
||||
if (str)
|
||||
*str = (unsigned char)value;
|
||||
return 1;
|
||||
}
|
||||
if (value < 0x800) {
|
||||
if (len < 2)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (value < 0x10000) {
|
||||
if (len < 3)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
if (value < 0x200000) {
|
||||
if (len < 4)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
if (value < 0x4000000) {
|
||||
if (len < 5)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
if (len < 6)
|
||||
return -1;
|
||||
if (str) {
|
||||
*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
|
||||
*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 6;
|
||||
if(!str) len = 6; /* Maximum we will need */
|
||||
else if(len <= 0) return -1;
|
||||
if(value < 0x80) {
|
||||
if(str) *str = (unsigned char)value;
|
||||
return 1;
|
||||
}
|
||||
if(value < 0x800) {
|
||||
if(len < 2) return -1;
|
||||
if(str) {
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if(value < 0x10000) {
|
||||
if(len < 3) return -1;
|
||||
if(str) {
|
||||
*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
if(value < 0x200000) {
|
||||
if(len < 4) return -1;
|
||||
if(str) {
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
if(value < 0x4000000) {
|
||||
if(len < 5) return -1;
|
||||
if(str) {
|
||||
*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
if(len < 6) return -1;
|
||||
if(str) {
|
||||
*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
|
||||
*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
|
||||
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
|
||||
*str = (unsigned char)((value & 0x3f) | 0x80);
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
+359
-353
@@ -63,19 +63,16 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c. */
|
||||
|
||||
/* Used in asn1_mac.h.
|
||||
* TODO(davidben): Remove this once asn1_mac.h is gone or trimmed. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||
|
||||
/* Cross-module errors from crypto/x509/algorithm.c. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE);
|
||||
/*
|
||||
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
|
||||
* these once asn1_gen.c is gone.
|
||||
*/
|
||||
/* Cross-module errors from crypto/x509/asn1_gen.c.
|
||||
* TODO(davidben): Remove these once asn1_gen.c is gone. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
|
||||
@@ -100,410 +97,419 @@ OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
|
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
int max);
|
||||
static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
|
||||
static void asn1_put_length(unsigned char **pp, int length);
|
||||
|
||||
static int _asn1_check_infinite_end(const unsigned char **p, long len)
|
||||
{
|
||||
/*
|
||||
* If there is 0 or 1 byte left, the length check should pick things up
|
||||
*/
|
||||
if (len <= 0)
|
||||
return (1);
|
||||
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
|
||||
(*p) += 2;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
{
|
||||
/* If there is 0 or 1 byte left, the length check should pick
|
||||
* things up */
|
||||
if (len <= 0)
|
||||
return(1);
|
||||
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
|
||||
{
|
||||
(*p)+=2;
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int ASN1_check_infinite_end(unsigned char **p, long len)
|
||||
{
|
||||
return _asn1_check_infinite_end((const unsigned char **)p, len);
|
||||
}
|
||||
{
|
||||
return _asn1_check_infinite_end((const unsigned char **)p, len);
|
||||
}
|
||||
|
||||
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
|
||||
{
|
||||
return _asn1_check_infinite_end(p, len);
|
||||
}
|
||||
{
|
||||
return _asn1_check_infinite_end(p, len);
|
||||
}
|
||||
|
||||
|
||||
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
|
||||
int *pclass, long omax)
|
||||
{
|
||||
int i, ret;
|
||||
long l;
|
||||
const unsigned char *p = *pp;
|
||||
int tag, xclass, inf;
|
||||
long max = omax;
|
||||
int *pclass, long omax)
|
||||
{
|
||||
int i,ret;
|
||||
long l;
|
||||
const unsigned char *p= *pp;
|
||||
int tag,xclass,inf;
|
||||
long max=omax;
|
||||
|
||||
if (!max)
|
||||
goto err;
|
||||
ret = (*p & V_ASN1_CONSTRUCTED);
|
||||
xclass = (*p & V_ASN1_PRIVATE);
|
||||
i = *p & V_ASN1_PRIMITIVE_TAG;
|
||||
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
|
||||
p++;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
l = 0;
|
||||
while (*p & 0x80) {
|
||||
l <<= 7L;
|
||||
l |= *(p++) & 0x7f;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
if (l > (INT_MAX >> 7L))
|
||||
goto err;
|
||||
}
|
||||
l <<= 7L;
|
||||
l |= *(p++) & 0x7f;
|
||||
tag = (int)l;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
} else {
|
||||
tag = i;
|
||||
p++;
|
||||
if (--max == 0)
|
||||
goto err;
|
||||
}
|
||||
if (!max) goto err;
|
||||
ret=(*p&V_ASN1_CONSTRUCTED);
|
||||
xclass=(*p&V_ASN1_PRIVATE);
|
||||
i= *p&V_ASN1_PRIMITIVE_TAG;
|
||||
if (i == V_ASN1_PRIMITIVE_TAG)
|
||||
{ /* high-tag */
|
||||
p++;
|
||||
if (--max == 0) goto err;
|
||||
l=0;
|
||||
while (*p&0x80)
|
||||
{
|
||||
l<<=7L;
|
||||
l|= *(p++)&0x7f;
|
||||
if (--max == 0) goto err;
|
||||
if (l > (INT_MAX >> 7L)) goto err;
|
||||
}
|
||||
l<<=7L;
|
||||
l|= *(p++)&0x7f;
|
||||
tag=(int)l;
|
||||
if (--max == 0) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag=i;
|
||||
p++;
|
||||
if (--max == 0) goto err;
|
||||
}
|
||||
|
||||
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
|
||||
if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
|
||||
goto err;
|
||||
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
|
||||
if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
|
||||
goto err;
|
||||
|
||||
*ptag = tag;
|
||||
*pclass = xclass;
|
||||
if (!asn1_get_length(&p, &inf, plength, (int)max))
|
||||
goto err;
|
||||
*ptag=tag;
|
||||
*pclass=xclass;
|
||||
if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
|
||||
|
||||
if (inf && !(ret & V_ASN1_CONSTRUCTED))
|
||||
goto err;
|
||||
if (inf && !(ret & V_ASN1_CONSTRUCTED))
|
||||
goto err;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
|
||||
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
|
||||
(int)(omax + *pp));
|
||||
fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
|
||||
(int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
|
||||
(int)(omax+ *pp));
|
||||
|
||||
#endif
|
||||
if (*plength > (omax - (p - *pp))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
/*
|
||||
* Set this so that even if things are not long enough the values are
|
||||
* set correctly
|
||||
*/
|
||||
ret |= 0x80;
|
||||
}
|
||||
*pp = p;
|
||||
return (ret | inf);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
return (0x80);
|
||||
}
|
||||
if (*plength > (omax - (p - *pp)))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
/* Set this so that even if things are not long enough
|
||||
* the values are set correctly */
|
||||
ret|=0x80;
|
||||
}
|
||||
*pp=p;
|
||||
return(ret|inf);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
return(0x80);
|
||||
}
|
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
int max)
|
||||
{
|
||||
const unsigned char *p = *pp;
|
||||
unsigned long ret = 0;
|
||||
unsigned int i;
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
|
||||
{
|
||||
const unsigned char *p= *pp;
|
||||
unsigned long ret=0;
|
||||
unsigned int i;
|
||||
|
||||
if (max-- < 1)
|
||||
return (0);
|
||||
if (*p == 0x80) {
|
||||
*inf = 1;
|
||||
ret = 0;
|
||||
p++;
|
||||
} else {
|
||||
*inf = 0;
|
||||
i = *p & 0x7f;
|
||||
if (*(p++) & 0x80) {
|
||||
if (i > sizeof(long))
|
||||
return 0;
|
||||
if (max-- == 0)
|
||||
return (0);
|
||||
while (i-- > 0) {
|
||||
ret <<= 8L;
|
||||
ret |= *(p++);
|
||||
if (max-- == 0)
|
||||
return (0);
|
||||
}
|
||||
} else
|
||||
ret = i;
|
||||
}
|
||||
if (ret > LONG_MAX)
|
||||
return 0;
|
||||
*pp = p;
|
||||
*rl = (long)ret;
|
||||
return (1);
|
||||
}
|
||||
if (max-- < 1) return(0);
|
||||
if (*p == 0x80)
|
||||
{
|
||||
*inf=1;
|
||||
ret=0;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*inf=0;
|
||||
i= *p&0x7f;
|
||||
if (*(p++) & 0x80)
|
||||
{
|
||||
if (i > sizeof(long))
|
||||
return 0;
|
||||
if (max-- == 0) return(0);
|
||||
while (i-- > 0)
|
||||
{
|
||||
ret<<=8L;
|
||||
ret|= *(p++);
|
||||
if (max-- == 0) return(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
ret=i;
|
||||
}
|
||||
if (ret > LONG_MAX)
|
||||
return 0;
|
||||
*pp=p;
|
||||
*rl=(long)ret;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* class 0 is constructed constructed == 2 for indefinite length constructed
|
||||
*/
|
||||
/* class 0 is constructed
|
||||
* constructed == 2 for indefinite length constructed */
|
||||
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, ttag;
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p= *pp;
|
||||
int i, ttag;
|
||||
|
||||
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
|
||||
i |= (xclass & V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
|
||||
else {
|
||||
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
|
||||
for (i = 0, ttag = tag; ttag > 0; i++)
|
||||
ttag >>= 7;
|
||||
ttag = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = tag & 0x7f;
|
||||
if (i != (ttag - 1))
|
||||
p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++) = 0x80;
|
||||
else
|
||||
asn1_put_length(&p, length);
|
||||
*pp = p;
|
||||
}
|
||||
i=(constructed)?V_ASN1_CONSTRUCTED:0;
|
||||
i|=(xclass&V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
|
||||
else
|
||||
{
|
||||
*(p++)=i|V_ASN1_PRIMITIVE_TAG;
|
||||
for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
|
||||
ttag = i;
|
||||
while(i-- > 0)
|
||||
{
|
||||
p[i] = tag & 0x7f;
|
||||
if(i != (ttag - 1)) p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++)=0x80;
|
||||
else
|
||||
asn1_put_length(&p,length);
|
||||
*pp=p;
|
||||
}
|
||||
|
||||
int ASN1_put_eoc(unsigned char **pp)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void asn1_put_length(unsigned char **pp, int length)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, l;
|
||||
if (length <= 127)
|
||||
*(p++) = (unsigned char)length;
|
||||
else {
|
||||
l = length;
|
||||
for (i = 0; l > 0; i++)
|
||||
l >>= 8;
|
||||
*(p++) = i | 0x80;
|
||||
l = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = length & 0xff;
|
||||
length >>= 8;
|
||||
}
|
||||
p += l;
|
||||
}
|
||||
*pp = p;
|
||||
}
|
||||
{
|
||||
unsigned char *p= *pp;
|
||||
int i,l;
|
||||
if (length <= 127)
|
||||
*(p++)=(unsigned char)length;
|
||||
else
|
||||
{
|
||||
l=length;
|
||||
for (i=0; l > 0; i++)
|
||||
l>>=8;
|
||||
*(p++)=i|0x80;
|
||||
l=i;
|
||||
while (i-- > 0)
|
||||
{
|
||||
p[i]=length&0xff;
|
||||
length>>=8;
|
||||
}
|
||||
p+=l;
|
||||
}
|
||||
*pp=p;
|
||||
}
|
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag)
|
||||
{
|
||||
int ret;
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = length;
|
||||
ret++;
|
||||
if (tag >= 31) {
|
||||
while (tag > 0) {
|
||||
tag >>= 7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2)
|
||||
return ret + 3;
|
||||
ret++;
|
||||
if (length > 127) {
|
||||
while (length > 0) {
|
||||
length >>= 8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
ret=length;
|
||||
ret++;
|
||||
if (tag >= 31)
|
||||
{
|
||||
while (tag > 0)
|
||||
{
|
||||
tag>>=7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2)
|
||||
return ret + 3;
|
||||
ret++;
|
||||
if (length > 127)
|
||||
{
|
||||
while (length > 0)
|
||||
{
|
||||
length>>=8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int _asn1_Finish(ASN1_const_CTX *c)
|
||||
{
|
||||
if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
|
||||
if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
|
||||
c->error = ASN1_R_MISSING_ASN1_EOS;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
|
||||
c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
{
|
||||
if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
|
||||
{
|
||||
if (!ASN1_const_check_infinite_end(&c->p,c->slen))
|
||||
{
|
||||
c->error=ASN1_R_MISSING_ASN1_EOS;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
if ( ((c->slen != 0) && !(c->inf & 1)) ||
|
||||
((c->slen < 0) && (c->inf & 1)))
|
||||
{
|
||||
c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
int asn1_Finish(ASN1_CTX *c)
|
||||
{
|
||||
return _asn1_Finish((ASN1_const_CTX *)c);
|
||||
}
|
||||
{
|
||||
return _asn1_Finish((ASN1_const_CTX *)c);
|
||||
}
|
||||
|
||||
int asn1_const_Finish(ASN1_const_CTX *c)
|
||||
{
|
||||
return _asn1_Finish(c);
|
||||
}
|
||||
{
|
||||
return _asn1_Finish(c);
|
||||
}
|
||||
|
||||
int asn1_GetSequence(ASN1_const_CTX *c, long *length)
|
||||
{
|
||||
const unsigned char *q;
|
||||
{
|
||||
const unsigned char *q;
|
||||
|
||||
q = c->p;
|
||||
c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass),
|
||||
*length);
|
||||
if (c->inf & 0x80) {
|
||||
c->error = ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
|
||||
return (0);
|
||||
}
|
||||
if (c->tag != V_ASN1_SEQUENCE) {
|
||||
c->error = ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
|
||||
return (0);
|
||||
}
|
||||
(*length) -= (c->p - q);
|
||||
if (c->max && (*length < 0)) {
|
||||
c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return (0);
|
||||
}
|
||||
if (c->inf == (1 | V_ASN1_CONSTRUCTED))
|
||||
c->slen = *length + *(c->pp) - c->p;
|
||||
c->eos = 0;
|
||||
return (1);
|
||||
}
|
||||
q=c->p;
|
||||
c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
|
||||
*length);
|
||||
if (c->inf & 0x80)
|
||||
{
|
||||
c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
|
||||
return(0);
|
||||
}
|
||||
if (c->tag != V_ASN1_SEQUENCE)
|
||||
{
|
||||
c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
|
||||
return(0);
|
||||
}
|
||||
(*length)-=(c->p-q);
|
||||
if (c->max && (*length < 0))
|
||||
{
|
||||
c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return(0);
|
||||
}
|
||||
if (c->inf == (1|V_ASN1_CONSTRUCTED))
|
||||
c->slen= *length+ *(c->pp)-c->p;
|
||||
c->eos=0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst, str->data, str->length))
|
||||
return 0;
|
||||
dst->flags = str->flags;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst,str->data,str->length))
|
||||
return 0;
|
||||
dst->flags = str->flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret = ASN1_STRING_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret, str)) {
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret=ASN1_STRING_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret,str))
|
||||
{
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data = _data;
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data=_data;
|
||||
|
||||
if (len < 0) {
|
||||
if (data == NULL)
|
||||
return (0);
|
||||
else
|
||||
len = strlen(data);
|
||||
}
|
||||
if ((str->length < len) || (str->data == NULL)) {
|
||||
c = str->data;
|
||||
if (c == NULL)
|
||||
str->data = OPENSSL_malloc(len + 1);
|
||||
else
|
||||
str->data = OPENSSL_realloc(c, len + 1);
|
||||
if (len < 0)
|
||||
{
|
||||
if (data == NULL)
|
||||
return(0);
|
||||
else
|
||||
len=strlen(data);
|
||||
}
|
||||
if ((str->length < len) || (str->data == NULL))
|
||||
{
|
||||
c=str->data;
|
||||
if (c == NULL)
|
||||
str->data=OPENSSL_malloc(len+1);
|
||||
else
|
||||
str->data=OPENSSL_realloc(c,len+1);
|
||||
|
||||
if (str->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
str->data = c;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
str->length = len;
|
||||
if (data != NULL) {
|
||||
memcpy(str->data, data, len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len] = '\0';
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
if (str->data == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
str->data=c;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
str->length=len;
|
||||
if (data != NULL)
|
||||
{
|
||||
memcpy(str->data,data,len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len]='\0';
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
|
||||
{
|
||||
if (str->data)
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
{
|
||||
if (str->data)
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void)
|
||||
{
|
||||
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
|
||||
}
|
||||
{
|
||||
return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
|
||||
}
|
||||
|
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
|
||||
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->type = type;
|
||||
ret->data = NULL;
|
||||
ret->flags = 0;
|
||||
return (ret);
|
||||
}
|
||||
ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(NULL);
|
||||
}
|
||||
ret->length=0;
|
||||
ret->type=type;
|
||||
ret->data=NULL;
|
||||
ret->flags=0;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void ASN1_STRING_free(ASN1_STRING *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
{
|
||||
if (a == NULL) return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
|
||||
{
|
||||
int i;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (a->length - b->length);
|
||||
if (i == 0) {
|
||||
i = memcmp(a->data, b->data, a->length);
|
||||
if (i == 0)
|
||||
return (a->type - b->type);
|
||||
else
|
||||
return (i);
|
||||
} else
|
||||
return (i);
|
||||
}
|
||||
i=(a->length-b->length);
|
||||
if (i == 0)
|
||||
{
|
||||
i=memcmp(a->data,b->data,a->length);
|
||||
if (i == 0)
|
||||
return(a->type-b->type);
|
||||
else
|
||||
return(i);
|
||||
}
|
||||
else
|
||||
return(i);
|
||||
}
|
||||
|
||||
int ASN1_STRING_length(const ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_length(x);
|
||||
}
|
||||
{ return M_ASN1_STRING_length(x); }
|
||||
|
||||
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
|
||||
{
|
||||
M_ASN1_STRING_length_set(x, len);
|
||||
return;
|
||||
}
|
||||
{ M_ASN1_STRING_length_set(x, len); return; }
|
||||
|
||||
int ASN1_STRING_type(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_type(x);
|
||||
}
|
||||
{ return M_ASN1_STRING_type(x); }
|
||||
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_data(x);
|
||||
}
|
||||
unsigned char * ASN1_STRING_data(ASN1_STRING *x)
|
||||
{ return M_ASN1_STRING_data(x); }
|
||||
|
||||
+11
-11
@@ -1,7 +1,6 @@
|
||||
/* asn1t.h */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2006.
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
@@ -11,7 +10,7 @@
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 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
|
||||
@@ -64,10 +63,11 @@ int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
|
||||
|
||||
/* ASN1 print context structure */
|
||||
|
||||
struct asn1_pctx_st {
|
||||
unsigned long flags;
|
||||
unsigned long nm_flags;
|
||||
unsigned long cert_flags;
|
||||
unsigned long oid_flags;
|
||||
unsigned long str_flags;
|
||||
} /* ASN1_PCTX */ ;
|
||||
struct asn1_pctx_st
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long nm_flags;
|
||||
unsigned long cert_flags;
|
||||
unsigned long oid_flags;
|
||||
unsigned long str_flags;
|
||||
} /* ASN1_PCTX */;
|
||||
|
||||
+351
-309
@@ -60,343 +60,385 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
#define ASN1_PARSE_MAXDEPTH 128
|
||||
|
||||
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
|
||||
int indent);
|
||||
static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed,
|
||||
int indent);
|
||||
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
|
||||
int offset, int depth, int indent, int dump);
|
||||
int offset, int depth, int indent, int dump);
|
||||
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
|
||||
int indent)
|
||||
{
|
||||
static const char fmt[] = "%-18s";
|
||||
char str[128];
|
||||
const char *p;
|
||||
int indent)
|
||||
{
|
||||
static const char fmt[]="%-18s";
|
||||
char str[128];
|
||||
const char *p;
|
||||
|
||||
if (constructed & V_ASN1_CONSTRUCTED)
|
||||
p = "cons: ";
|
||||
else
|
||||
p = "prim: ";
|
||||
if (BIO_write(bp, p, 6) < 6)
|
||||
goto err;
|
||||
BIO_indent(bp, indent, 128);
|
||||
if (constructed & V_ASN1_CONSTRUCTED)
|
||||
p="cons: ";
|
||||
else
|
||||
p="prim: ";
|
||||
if (BIO_write(bp,p,6) < 6) goto err;
|
||||
BIO_indent(bp,indent,128);
|
||||
|
||||
p = str;
|
||||
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
|
||||
BIO_snprintf(str, sizeof str, "priv [ %d ] ", tag);
|
||||
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
|
||||
BIO_snprintf(str, sizeof str, "cont [ %d ]", tag);
|
||||
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
|
||||
BIO_snprintf(str, sizeof str, "appl [ %d ]", tag);
|
||||
else if (tag > 30)
|
||||
BIO_snprintf(str, sizeof str, "<ASN1 %d>", tag);
|
||||
else
|
||||
p = ASN1_tag2str(tag);
|
||||
p=str;
|
||||
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
|
||||
BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag);
|
||||
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
|
||||
BIO_snprintf(str,sizeof str,"cont [ %d ]",tag);
|
||||
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
|
||||
BIO_snprintf(str,sizeof str,"appl [ %d ]",tag);
|
||||
else if (tag > 30)
|
||||
BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag);
|
||||
else
|
||||
p = ASN1_tag2str(tag);
|
||||
|
||||
if (BIO_printf(bp, fmt, p) <= 0)
|
||||
goto err;
|
||||
return (1);
|
||||
err:
|
||||
return (0);
|
||||
}
|
||||
if (BIO_printf(bp,fmt,p) <= 0)
|
||||
goto err;
|
||||
return(1);
|
||||
err:
|
||||
return(0);
|
||||
}
|
||||
|
||||
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
|
||||
{
|
||||
return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
|
||||
}
|
||||
{
|
||||
return(asn1_parse2(bp,&pp,len,0,0,indent,0));
|
||||
}
|
||||
|
||||
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
|
||||
int dump)
|
||||
{
|
||||
return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
|
||||
}
|
||||
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
|
||||
{
|
||||
return(asn1_parse2(bp,&pp,len,0,0,indent,dump));
|
||||
}
|
||||
|
||||
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
|
||||
int offset, int depth, int indent, int dump)
|
||||
{
|
||||
const unsigned char *p, *ep, *tot, *op, *opp;
|
||||
long len;
|
||||
int tag, xclass, ret = 0;
|
||||
int nl, hl, j, r;
|
||||
ASN1_OBJECT *o = NULL;
|
||||
ASN1_OCTET_STRING *os = NULL;
|
||||
/* ASN1_BMPSTRING *bmp=NULL; */
|
||||
int dump_indent;
|
||||
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
|
||||
int depth, int indent, int dump)
|
||||
{
|
||||
const unsigned char *p,*ep,*tot,*op,*opp;
|
||||
long len;
|
||||
int tag,xclass,ret=0;
|
||||
int nl,hl,j,r;
|
||||
ASN1_OBJECT *o=NULL;
|
||||
ASN1_OCTET_STRING *os=NULL;
|
||||
/* ASN1_BMPSTRING *bmp=NULL;*/
|
||||
int dump_indent;
|
||||
|
||||
#if 0
|
||||
dump_indent = indent;
|
||||
dump_indent = indent;
|
||||
#else
|
||||
dump_indent = 6; /* Because we know BIO_dump_indent() */
|
||||
dump_indent = 6; /* Because we know BIO_dump_indent() */
|
||||
#endif
|
||||
|
||||
if (depth > ASN1_PARSE_MAXDEPTH) {
|
||||
BIO_puts(bp, "BAD RECURSION DEPTH\n");
|
||||
return 0;
|
||||
}
|
||||
if (depth > ASN1_PARSE_MAXDEPTH)
|
||||
{
|
||||
BIO_puts(bp, "BAD RECURSION DEPTH\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = *pp;
|
||||
tot = p + length;
|
||||
op = p - 1;
|
||||
while ((p < tot) && (op < p)) {
|
||||
op = p;
|
||||
j = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
p= *pp;
|
||||
tot=p+length;
|
||||
op=p-1;
|
||||
while ((p < tot) && (op < p))
|
||||
{
|
||||
op=p;
|
||||
j=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
#ifdef LINT
|
||||
j = j;
|
||||
j=j;
|
||||
#endif
|
||||
if (j & 0x80) {
|
||||
if (BIO_puts(bp, "Error in encoding\n") <= 0)
|
||||
goto end;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
hl = (p - op);
|
||||
length -= hl;
|
||||
/*
|
||||
* if j == 0x21 it is a constructed indefinite length object
|
||||
*/
|
||||
if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
|
||||
<= 0)
|
||||
goto end;
|
||||
if (j & 0x80)
|
||||
{
|
||||
if (BIO_puts(bp, "Error in encoding\n") <= 0)
|
||||
goto end;
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
hl=(p-op);
|
||||
length-=hl;
|
||||
/* if j == 0x21 it is a constructed indefinite length object */
|
||||
if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
|
||||
<= 0) goto end;
|
||||
|
||||
if (j != (V_ASN1_CONSTRUCTED | 1)) {
|
||||
if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
|
||||
depth, (long)hl, len) <= 0)
|
||||
goto end;
|
||||
} else {
|
||||
if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
|
||||
goto end;
|
||||
if (j & V_ASN1_CONSTRUCTED) {
|
||||
ep = p + len;
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
if (len > length) {
|
||||
BIO_printf(bp, "length is greater than %ld\n", length);
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
if ((j == 0x21) && (len == 0)) {
|
||||
for (;;) {
|
||||
r = asn1_parse2(bp, &p, (long)(tot - p),
|
||||
offset + (p - *pp), depth + 1,
|
||||
indent, dump);
|
||||
if (r == 0) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
if ((r == 2) || (p >= tot))
|
||||
break;
|
||||
}
|
||||
} else
|
||||
while (p < ep) {
|
||||
r = asn1_parse2(bp, &p, (long)len,
|
||||
offset + (p - *pp), depth + 1,
|
||||
indent, dump);
|
||||
if (r == 0) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} else if (xclass != 0) {
|
||||
p += len;
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
} else {
|
||||
nl = 0;
|
||||
if ((tag == V_ASN1_PRINTABLESTRING) ||
|
||||
(tag == V_ASN1_T61STRING) ||
|
||||
(tag == V_ASN1_IA5STRING) ||
|
||||
(tag == V_ASN1_VISIBLESTRING) ||
|
||||
(tag == V_ASN1_NUMERICSTRING) ||
|
||||
(tag == V_ASN1_UTF8STRING) ||
|
||||
(tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
|
||||
!= (int)len)
|
||||
goto end;
|
||||
} else if (tag == V_ASN1_OBJECT) {
|
||||
opp = op;
|
||||
if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
i2a_ASN1_OBJECT(bp, o);
|
||||
} else {
|
||||
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else if (tag == V_ASN1_BOOLEAN) {
|
||||
int ii;
|
||||
if (j != (V_ASN1_CONSTRUCTED | 1))
|
||||
{
|
||||
if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
|
||||
depth,(long)hl,len) <= 0)
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_printf(bp,"d=%-2d hl=%ld l=inf ",
|
||||
depth,(long)hl) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
|
||||
goto end;
|
||||
if (j & V_ASN1_CONSTRUCTED)
|
||||
{
|
||||
ep=p+len;
|
||||
if (BIO_puts(bp, "\n") <= 0) goto end;
|
||||
if (len > length)
|
||||
{
|
||||
BIO_printf(bp,
|
||||
"length is greater than %ld\n",length);
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
if ((j == 0x21) && (len == 0))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
r=asn1_parse2(bp,&p,(long)(tot-p),
|
||||
offset+(p - *pp),depth+1,
|
||||
indent,dump);
|
||||
if (r == 0) { ret=0; goto end; }
|
||||
if ((r == 2) || (p >= tot)) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
while (p < ep)
|
||||
{
|
||||
r=asn1_parse2(bp,&p,(long)len,
|
||||
offset+(p - *pp),depth+1,
|
||||
indent,dump);
|
||||
if (r == 0) { ret=0; goto end; }
|
||||
}
|
||||
}
|
||||
else if (xclass != 0)
|
||||
{
|
||||
p+=len;
|
||||
if (BIO_puts(bp, "\n") <= 0) goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
nl=0;
|
||||
if ( (tag == V_ASN1_PRINTABLESTRING) ||
|
||||
(tag == V_ASN1_T61STRING) ||
|
||||
(tag == V_ASN1_IA5STRING) ||
|
||||
(tag == V_ASN1_VISIBLESTRING) ||
|
||||
(tag == V_ASN1_NUMERICSTRING) ||
|
||||
(tag == V_ASN1_UTF8STRING) ||
|
||||
(tag == V_ASN1_UTCTIME) ||
|
||||
(tag == V_ASN1_GENERALIZEDTIME))
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
if ((len > 0) &&
|
||||
BIO_write(bp,(const char *)p,(int)len)
|
||||
!= (int)len)
|
||||
goto end;
|
||||
}
|
||||
else if (tag == V_ASN1_OBJECT)
|
||||
{
|
||||
opp=op;
|
||||
if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
i2a_ASN1_OBJECT(bp,o);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (tag == V_ASN1_BOOLEAN)
|
||||
{
|
||||
int ii;
|
||||
|
||||
opp = op;
|
||||
ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
|
||||
if (ii < 0) {
|
||||
if (BIO_puts(bp, "Bad boolean\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
BIO_printf(bp, ":%d", ii);
|
||||
} else if (tag == V_ASN1_BMPSTRING) {
|
||||
/* do the BMP thang */
|
||||
} else if (tag == V_ASN1_OCTET_STRING) {
|
||||
int i, printable = 1;
|
||||
opp=op;
|
||||
ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
|
||||
if (ii < 0)
|
||||
{
|
||||
if (BIO_puts(bp, "Bad boolean\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
BIO_printf(bp,":%d",ii);
|
||||
}
|
||||
else if (tag == V_ASN1_BMPSTRING)
|
||||
{
|
||||
/* do the BMP thang */
|
||||
}
|
||||
else if (tag == V_ASN1_OCTET_STRING)
|
||||
{
|
||||
int i,printable=1;
|
||||
|
||||
opp = op;
|
||||
os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
|
||||
if (os != NULL && os->length > 0) {
|
||||
opp = os->data;
|
||||
/*
|
||||
* testing whether the octet string is printable
|
||||
*/
|
||||
for (i = 0; i < os->length; i++) {
|
||||
if (((opp[i] < ' ') &&
|
||||
(opp[i] != '\n') &&
|
||||
(opp[i] != '\r') &&
|
||||
(opp[i] != '\t')) || (opp[i] > '~')) {
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (printable)
|
||||
/* printable string */
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (BIO_write(bp, (const char *)opp, os->length) <= 0)
|
||||
goto end;
|
||||
} else if (!dump)
|
||||
/*
|
||||
* not printable => print octet string as hex dump
|
||||
*/
|
||||
{
|
||||
if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < os->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", opp[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else
|
||||
/* print the normal dump */
|
||||
{
|
||||
if (!nl) {
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp, opp,
|
||||
((dump == -1 || dump >
|
||||
os->length) ? os->length : dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl = 1;
|
||||
}
|
||||
}
|
||||
if (os != NULL) {
|
||||
M_ASN1_OCTET_STRING_free(os);
|
||||
os = NULL;
|
||||
}
|
||||
} else if (tag == V_ASN1_INTEGER) {
|
||||
ASN1_INTEGER *bs;
|
||||
int i;
|
||||
opp=op;
|
||||
os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl);
|
||||
if (os != NULL && os->length > 0)
|
||||
{
|
||||
opp = os->data;
|
||||
/* testing whether the octet string is
|
||||
* printable */
|
||||
for (i=0; i<os->length; i++)
|
||||
{
|
||||
if (( (opp[i] < ' ') &&
|
||||
(opp[i] != '\n') &&
|
||||
(opp[i] != '\r') &&
|
||||
(opp[i] != '\t')) ||
|
||||
(opp[i] > '~'))
|
||||
{
|
||||
printable=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (printable)
|
||||
/* printable string */
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (BIO_write(bp,(const char *)opp,
|
||||
os->length) <= 0)
|
||||
goto end;
|
||||
}
|
||||
else if (!dump)
|
||||
/* not printable => print octet string
|
||||
* as hex dump */
|
||||
{
|
||||
if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
|
||||
goto end;
|
||||
for (i=0; i<os->length; i++)
|
||||
{
|
||||
if (BIO_printf(bp,"%02X"
|
||||
, opp[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* print the normal dump */
|
||||
{
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp, opp,
|
||||
((dump == -1 || dump >
|
||||
os->length)?os->length:dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl=1;
|
||||
}
|
||||
}
|
||||
if (os != NULL)
|
||||
{
|
||||
M_ASN1_OCTET_STRING_free(os);
|
||||
os=NULL;
|
||||
}
|
||||
}
|
||||
else if (tag == V_ASN1_INTEGER)
|
||||
{
|
||||
ASN1_INTEGER *bs;
|
||||
int i;
|
||||
|
||||
opp = op;
|
||||
bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
|
||||
if (bs != NULL) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (bs->type == V_ASN1_NEG_INTEGER)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < bs->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0) {
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (BIO_puts(bp, "BAD INTEGER") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_INTEGER_free(bs);
|
||||
} else if (tag == V_ASN1_ENUMERATED) {
|
||||
ASN1_ENUMERATED *bs;
|
||||
int i;
|
||||
opp=op;
|
||||
bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
|
||||
if (bs != NULL)
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
if (bs->type == V_ASN1_NEG_INTEGER)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i=0; i<bs->length; i++)
|
||||
{
|
||||
if (BIO_printf(bp,"%02X",
|
||||
bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0)
|
||||
{
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_puts(bp, "BAD INTEGER") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_INTEGER_free(bs);
|
||||
}
|
||||
else if (tag == V_ASN1_ENUMERATED)
|
||||
{
|
||||
ASN1_ENUMERATED *bs;
|
||||
int i;
|
||||
|
||||
opp = op;
|
||||
bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
|
||||
if (bs != NULL) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (bs->type == V_ASN1_NEG_ENUMERATED)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < bs->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0) {
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_ENUMERATED_free(bs);
|
||||
} else if (len > 0 && dump) {
|
||||
if (!nl) {
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp, p,
|
||||
((dump == -1 || dump > len) ? len : dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl = 1;
|
||||
}
|
||||
opp=op;
|
||||
bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
|
||||
if (bs != NULL)
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
if (bs->type == V_ASN1_NEG_ENUMERATED)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i=0; i<bs->length; i++)
|
||||
{
|
||||
if (BIO_printf(bp,"%02X",
|
||||
bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0)
|
||||
{
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_ENUMERATED_free(bs);
|
||||
}
|
||||
else if (len > 0 && dump)
|
||||
{
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp,p,
|
||||
((dump == -1 || dump > len)?len:dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl=1;
|
||||
}
|
||||
|
||||
if (!nl) {
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
p += len;
|
||||
if ((tag == V_ASN1_EOC) && (xclass == 0)) {
|
||||
ret = 2; /* End of sequence */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
length -= len;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
if (o != NULL)
|
||||
ASN1_OBJECT_free(o);
|
||||
if (os != NULL)
|
||||
M_ASN1_OCTET_STRING_free(os);
|
||||
*pp = p;
|
||||
return (ret);
|
||||
}
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_puts(bp, "\n") <= 0) goto end;
|
||||
}
|
||||
p+=len;
|
||||
if ((tag == V_ASN1_EOC) && (xclass == 0))
|
||||
{
|
||||
ret=2; /* End of sequence */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
length-=len;
|
||||
}
|
||||
ret=1;
|
||||
end:
|
||||
if (o != NULL) ASN1_OBJECT_free(o);
|
||||
if (os != NULL) M_ASN1_OCTET_STRING_free(os);
|
||||
*pp=p;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
const char *ASN1_tag2str(int tag)
|
||||
{
|
||||
static const char *const tag2str[] = {
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
|
||||
*/
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
|
||||
};
|
||||
static const char * const tag2str[] = {
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
|
||||
};
|
||||
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
|
||||
if (tag < 0 || tag > 30)
|
||||
return "(unknown)";
|
||||
return tag2str[tag];
|
||||
if(tag < 0 || tag > 30) return "(unknown)";
|
||||
return tag2str[tag];
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,6 @@
|
||||
#include "../test/scoped_types.h"
|
||||
|
||||
|
||||
// kTag128 is an ASN.1 structure with a universal tag with number 128.
|
||||
static const uint8_t kTag128[] = {
|
||||
0x1f, 0x81, 0x00, 0x01, 0x00,
|
||||
};
|
||||
|
||||
// kTag258 is an ASN.1 structure with a universal tag with number 258.
|
||||
static const uint8_t kTag258[] = {
|
||||
0x1f, 0x82, 0x02, 0x01, 0x00,
|
||||
@@ -34,38 +29,13 @@ static const uint8_t kTag258[] = {
|
||||
static_assert(V_ASN1_NEG_INTEGER == 258,
|
||||
"V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it.");
|
||||
|
||||
// kTagOverflow is an ASN.1 structure with a universal tag with number 2^35-1,
|
||||
// which will not fit in an int.
|
||||
static const uint8_t kTagOverflow[] = {
|
||||
0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static bool TestLargeTags() {
|
||||
bool TestLargeTags() {
|
||||
const uint8_t *p = kTag258;
|
||||
ScopedASN1_TYPE obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
|
||||
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)));
|
||||
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)));
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+29
-30
@@ -59,47 +59,46 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* ASN1_ITEM versions of the above */
|
||||
|
||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
{
|
||||
ASN1_STRING *octmp;
|
||||
ASN1_STRING *octmp;
|
||||
|
||||
if (!oct || !*oct) {
|
||||
if (!(octmp = ASN1_STRING_new())) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (oct)
|
||||
*oct = octmp;
|
||||
} else
|
||||
octmp = *oct;
|
||||
if (!oct || !*oct) {
|
||||
if (!(octmp = ASN1_STRING_new ())) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (oct) *oct = octmp;
|
||||
} else octmp = *oct;
|
||||
|
||||
if (octmp->data) {
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
}
|
||||
|
||||
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return octmp;
|
||||
if(octmp->data) {
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
}
|
||||
|
||||
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return octmp;
|
||||
}
|
||||
|
||||
/* Extract an ASN1 object from an ASN1_STRING */
|
||||
|
||||
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
{
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
|
||||
p = oct->data;
|
||||
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
p = oct->data;
|
||||
if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+348
-329
@@ -62,48 +62,53 @@
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* Must be large enough for biggest tag+length */
|
||||
#define DEFAULT_ASN1_BUF_SIZE 20
|
||||
|
||||
typedef enum {
|
||||
ASN1_STATE_START,
|
||||
ASN1_STATE_PRE_COPY,
|
||||
ASN1_STATE_HEADER,
|
||||
ASN1_STATE_HEADER_COPY,
|
||||
ASN1_STATE_DATA_COPY,
|
||||
ASN1_STATE_POST_COPY,
|
||||
ASN1_STATE_DONE
|
||||
} asn1_bio_state_t;
|
||||
typedef enum
|
||||
{
|
||||
ASN1_STATE_START,
|
||||
ASN1_STATE_PRE_COPY,
|
||||
ASN1_STATE_HEADER,
|
||||
ASN1_STATE_HEADER_COPY,
|
||||
ASN1_STATE_DATA_COPY,
|
||||
ASN1_STATE_POST_COPY,
|
||||
ASN1_STATE_DONE
|
||||
} asn1_bio_state_t;
|
||||
|
||||
typedef struct BIO_ASN1_EX_FUNCS_st {
|
||||
asn1_ps_func *ex_func;
|
||||
asn1_ps_func *ex_free_func;
|
||||
} BIO_ASN1_EX_FUNCS;
|
||||
typedef struct BIO_ASN1_EX_FUNCS_st
|
||||
{
|
||||
asn1_ps_func *ex_func;
|
||||
asn1_ps_func *ex_free_func;
|
||||
} BIO_ASN1_EX_FUNCS;
|
||||
|
||||
typedef struct BIO_ASN1_BUF_CTX_t {
|
||||
/* Internal state */
|
||||
asn1_bio_state_t state;
|
||||
/* Internal buffer */
|
||||
unsigned char *buf;
|
||||
/* Size of buffer */
|
||||
int bufsize;
|
||||
/* Current position in buffer */
|
||||
int bufpos;
|
||||
/* Current buffer length */
|
||||
int buflen;
|
||||
/* Amount of data to copy */
|
||||
int copylen;
|
||||
/* Class and tag to use */
|
||||
int asn1_class, asn1_tag;
|
||||
asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
|
||||
/* Extra buffer for prefix and suffix data */
|
||||
unsigned char *ex_buf;
|
||||
int ex_len;
|
||||
int ex_pos;
|
||||
void *ex_arg;
|
||||
} BIO_ASN1_BUF_CTX;
|
||||
typedef struct BIO_ASN1_BUF_CTX_t
|
||||
{
|
||||
/* Internal state */
|
||||
asn1_bio_state_t state;
|
||||
/* Internal buffer */
|
||||
unsigned char *buf;
|
||||
/* Size of buffer */
|
||||
int bufsize;
|
||||
/* Current position in buffer */
|
||||
int bufpos;
|
||||
/* Current buffer length */
|
||||
int buflen;
|
||||
/* Amount of data to copy */
|
||||
int copylen;
|
||||
/* Class and tag to use */
|
||||
int asn1_class, asn1_tag;
|
||||
asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
|
||||
/* Extra buffer for prefix and suffix data */
|
||||
unsigned char *ex_buf;
|
||||
int ex_len;
|
||||
int ex_pos;
|
||||
void *ex_arg;
|
||||
} BIO_ASN1_BUF_CTX;
|
||||
|
||||
static int asn1_bio_write(BIO *h, const char *buf, int num);
|
||||
|
||||
static int asn1_bio_write(BIO *h, const char *buf,int num);
|
||||
static int asn1_bio_read(BIO *h, char *buf, int size);
|
||||
static int asn1_bio_puts(BIO *h, const char *str);
|
||||
static int asn1_bio_gets(BIO *h, char *str, int size);
|
||||
@@ -114,364 +119,378 @@ static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
|
||||
|
||||
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
|
||||
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next);
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next);
|
||||
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state);
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state);
|
||||
|
||||
static const BIO_METHOD methods_asn1 = {
|
||||
BIO_TYPE_ASN1,
|
||||
"asn1",
|
||||
asn1_bio_write,
|
||||
asn1_bio_read,
|
||||
asn1_bio_puts,
|
||||
asn1_bio_gets,
|
||||
asn1_bio_ctrl,
|
||||
asn1_bio_new,
|
||||
asn1_bio_free,
|
||||
asn1_bio_callback_ctrl,
|
||||
};
|
||||
static const BIO_METHOD methods_asn1=
|
||||
{
|
||||
BIO_TYPE_ASN1,
|
||||
"asn1",
|
||||
asn1_bio_write,
|
||||
asn1_bio_read,
|
||||
asn1_bio_puts,
|
||||
asn1_bio_gets,
|
||||
asn1_bio_ctrl,
|
||||
asn1_bio_new,
|
||||
asn1_bio_free,
|
||||
asn1_bio_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_asn1(void)
|
||||
{
|
||||
return (&methods_asn1);
|
||||
}
|
||||
{
|
||||
return(&methods_asn1);
|
||||
}
|
||||
|
||||
|
||||
static int asn1_bio_new(BIO *b)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
|
||||
if (!ctx)
|
||||
return 0;
|
||||
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
b->init = 1;
|
||||
b->ptr = (char *)ctx;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
|
||||
if (!ctx)
|
||||
return 0;
|
||||
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
b->init = 1;
|
||||
b->ptr = (char *)ctx;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
|
||||
{
|
||||
ctx->buf = OPENSSL_malloc(size);
|
||||
if (!ctx->buf)
|
||||
return 0;
|
||||
ctx->bufsize = size;
|
||||
ctx->bufpos = 0;
|
||||
ctx->buflen = 0;
|
||||
ctx->copylen = 0;
|
||||
ctx->asn1_class = V_ASN1_UNIVERSAL;
|
||||
ctx->asn1_tag = V_ASN1_OCTET_STRING;
|
||||
ctx->ex_buf = 0;
|
||||
ctx->ex_pos = 0;
|
||||
ctx->ex_len = 0;
|
||||
ctx->state = ASN1_STATE_START;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
ctx->buf = OPENSSL_malloc(size);
|
||||
if (!ctx->buf)
|
||||
return 0;
|
||||
ctx->bufsize = size;
|
||||
ctx->bufpos = 0;
|
||||
ctx->buflen = 0;
|
||||
ctx->copylen = 0;
|
||||
ctx->asn1_class = V_ASN1_UNIVERSAL;
|
||||
ctx->asn1_tag = V_ASN1_OCTET_STRING;
|
||||
ctx->ex_buf = 0;
|
||||
ctx->ex_pos = 0;
|
||||
ctx->ex_len = 0;
|
||||
ctx->state = ASN1_STATE_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_free(BIO *b)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
if (ctx->buf)
|
||||
OPENSSL_free(ctx->buf);
|
||||
OPENSSL_free(ctx);
|
||||
b->init = 0;
|
||||
b->ptr = NULL;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
if (ctx->buf)
|
||||
OPENSSL_free(ctx->buf);
|
||||
OPENSSL_free(ctx);
|
||||
b->init = 0;
|
||||
b->ptr = NULL;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
int wrmax, wrlen, ret;
|
||||
unsigned char *p;
|
||||
if (!in || (inl < 0) || (b->next_bio == NULL))
|
||||
return 0;
|
||||
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
static int asn1_bio_write(BIO *b, const char *in , int inl)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
int wrmax, wrlen, ret;
|
||||
unsigned char *p;
|
||||
if (!in || (inl < 0) || (b->next_bio == NULL))
|
||||
return 0;
|
||||
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
|
||||
wrlen = 0;
|
||||
ret = -1;
|
||||
wrlen = 0;
|
||||
ret = -1;
|
||||
|
||||
for (;;) {
|
||||
switch (ctx->state) {
|
||||
for(;;)
|
||||
{
|
||||
switch (ctx->state)
|
||||
{
|
||||
|
||||
/* Setup prefix data, call it */
|
||||
case ASN1_STATE_START:
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
|
||||
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
|
||||
return 0;
|
||||
break;
|
||||
/* Setup prefix data, call it */
|
||||
case ASN1_STATE_START:
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
|
||||
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
/* Copy any pre data first */
|
||||
case ASN1_STATE_PRE_COPY:
|
||||
/* Copy any pre data first */
|
||||
case ASN1_STATE_PRE_COPY:
|
||||
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
|
||||
ASN1_STATE_HEADER);
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
|
||||
ASN1_STATE_HEADER);
|
||||
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ASN1_STATE_HEADER:
|
||||
ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
|
||||
assert(ctx->buflen <= ctx->bufsize);
|
||||
p = ctx->buf;
|
||||
ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
|
||||
ctx->copylen = inl;
|
||||
ctx->state = ASN1_STATE_HEADER_COPY;
|
||||
case ASN1_STATE_HEADER:
|
||||
ctx->buflen =
|
||||
ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
|
||||
assert(ctx->buflen <= ctx->bufsize);
|
||||
p = ctx->buf;
|
||||
ASN1_put_object(&p, 0, inl,
|
||||
ctx->asn1_tag, ctx->asn1_class);
|
||||
ctx->copylen = inl;
|
||||
ctx->state = ASN1_STATE_HEADER_COPY;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ASN1_STATE_HEADER_COPY:
|
||||
ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
case ASN1_STATE_HEADER_COPY:
|
||||
ret = BIO_write(b->next_bio,
|
||||
ctx->buf + ctx->bufpos, ctx->buflen);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
ctx->buflen -= ret;
|
||||
if (ctx->buflen)
|
||||
ctx->bufpos += ret;
|
||||
else {
|
||||
ctx->bufpos = 0;
|
||||
ctx->state = ASN1_STATE_DATA_COPY;
|
||||
}
|
||||
ctx->buflen -= ret;
|
||||
if (ctx->buflen)
|
||||
ctx->bufpos += ret;
|
||||
else
|
||||
{
|
||||
ctx->bufpos = 0;
|
||||
ctx->state = ASN1_STATE_DATA_COPY;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ASN1_STATE_DATA_COPY:
|
||||
case ASN1_STATE_DATA_COPY:
|
||||
|
||||
if (inl > ctx->copylen)
|
||||
wrmax = ctx->copylen;
|
||||
else
|
||||
wrmax = inl;
|
||||
ret = BIO_write(b->next_bio, in, wrmax);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
wrlen += ret;
|
||||
ctx->copylen -= ret;
|
||||
in += ret;
|
||||
inl -= ret;
|
||||
if (inl > ctx->copylen)
|
||||
wrmax = ctx->copylen;
|
||||
else
|
||||
wrmax = inl;
|
||||
ret = BIO_write(b->next_bio, in, wrmax);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
wrlen += ret;
|
||||
ctx->copylen -= ret;
|
||||
in += ret;
|
||||
inl -= ret;
|
||||
|
||||
if (ctx->copylen == 0)
|
||||
ctx->state = ASN1_STATE_HEADER;
|
||||
if (ctx->copylen == 0)
|
||||
ctx->state = ASN1_STATE_HEADER;
|
||||
|
||||
if (inl == 0)
|
||||
goto done;
|
||||
if (inl == 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
default:
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
done:
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
|
||||
return (wrlen > 0) ? wrlen : ret;
|
||||
return (wrlen > 0) ? wrlen : ret;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next)
|
||||
{
|
||||
int ret;
|
||||
if (ctx->ex_len <= 0)
|
||||
return 1;
|
||||
for (;;) {
|
||||
ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ctx->ex_len -= ret;
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->ex_pos += ret;
|
||||
else {
|
||||
if (cleanup)
|
||||
cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
|
||||
ctx->state = next;
|
||||
ctx->ex_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next)
|
||||
{
|
||||
int ret;
|
||||
if (ctx->ex_len <= 0)
|
||||
return 1;
|
||||
for(;;)
|
||||
{
|
||||
ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
|
||||
ctx->ex_len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ctx->ex_len -= ret;
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->ex_pos += ret;
|
||||
else
|
||||
{
|
||||
if(cleanup)
|
||||
cleanup(b, &ctx->ex_buf, &ctx->ex_len,
|
||||
&ctx->ex_arg);
|
||||
ctx->state = next;
|
||||
ctx->ex_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state)
|
||||
{
|
||||
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->state = ex_state;
|
||||
else
|
||||
ctx->state = other_state;
|
||||
return 1;
|
||||
}
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state)
|
||||
{
|
||||
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
|
||||
{
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->state = ex_state;
|
||||
else
|
||||
ctx->state = other_state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_read(BIO *b, char *in, int inl)
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_read(b->next_bio, in, inl);
|
||||
}
|
||||
static int asn1_bio_read(BIO *b, char *in , int inl)
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_read(b->next_bio, in , inl);
|
||||
}
|
||||
|
||||
static int asn1_bio_puts(BIO *b, const char *str)
|
||||
{
|
||||
return asn1_bio_write(b, str, strlen(str));
|
||||
}
|
||||
{
|
||||
return asn1_bio_write(b, str, strlen(str));
|
||||
}
|
||||
|
||||
static int asn1_bio_gets(BIO *b, char *str, int size)
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_gets(b->next_bio, str, size);
|
||||
}
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_gets(b->next_bio, str , size);
|
||||
}
|
||||
|
||||
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
|
||||
{
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
return BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
}
|
||||
{
|
||||
if (b->next_bio == NULL) return(0);
|
||||
return BIO_callback_ctrl(b->next_bio,cmd,fp);
|
||||
}
|
||||
|
||||
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
BIO_ASN1_EX_FUNCS *ex_func;
|
||||
long ret = 1;
|
||||
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
switch (cmd) {
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
BIO_ASN1_EX_FUNCS *ex_func;
|
||||
long ret = 1;
|
||||
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
switch(cmd)
|
||||
{
|
||||
|
||||
case BIO_C_SET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ctx->prefix = ex_func->ex_func;
|
||||
ctx->prefix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
case BIO_C_SET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ctx->prefix = ex_func->ex_func;
|
||||
ctx->prefix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->prefix;
|
||||
ex_func->ex_free_func = ctx->prefix_free;
|
||||
break;
|
||||
case BIO_C_GET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->prefix;
|
||||
ex_func->ex_free_func = ctx->prefix_free;
|
||||
break;
|
||||
|
||||
case BIO_C_SET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ctx->suffix = ex_func->ex_func;
|
||||
ctx->suffix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
case BIO_C_SET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ctx->suffix = ex_func->ex_func;
|
||||
ctx->suffix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->suffix;
|
||||
ex_func->ex_free_func = ctx->suffix_free;
|
||||
break;
|
||||
case BIO_C_GET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->suffix;
|
||||
ex_func->ex_free_func = ctx->suffix_free;
|
||||
break;
|
||||
|
||||
case BIO_C_SET_EX_ARG:
|
||||
ctx->ex_arg = arg2;
|
||||
break;
|
||||
case BIO_C_SET_EX_ARG:
|
||||
ctx->ex_arg = arg2;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_EX_ARG:
|
||||
*(void **)arg2 = ctx->ex_arg;
|
||||
break;
|
||||
case BIO_C_GET_EX_ARG:
|
||||
*(void **)arg2 = ctx->ex_arg;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
|
||||
/* Call post function if possible */
|
||||
if (ctx->state == ASN1_STATE_HEADER) {
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
|
||||
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
|
||||
return 0;
|
||||
}
|
||||
/* Call post function if possible */
|
||||
if (ctx->state == ASN1_STATE_HEADER)
|
||||
{
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
|
||||
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->state == ASN1_STATE_POST_COPY) {
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
|
||||
ASN1_STATE_DONE);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
if (ctx->state == ASN1_STATE_POST_COPY)
|
||||
{
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
|
||||
ASN1_STATE_DONE);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ctx->state == ASN1_STATE_DONE)
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
else {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
if (ctx->state == ASN1_STATE_DONE)
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
else
|
||||
{
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
|
||||
}
|
||||
default:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_bio_set_ex(BIO *b, int cmd,
|
||||
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
extmp.ex_func = ex_func;
|
||||
extmp.ex_free_func = ex_free_func;
|
||||
return BIO_ctrl(b, cmd, 0, &extmp);
|
||||
}
|
||||
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
extmp.ex_func = ex_func;
|
||||
extmp.ex_free_func = ex_free_func;
|
||||
return BIO_ctrl(b, cmd, 0, &extmp);
|
||||
}
|
||||
|
||||
static int asn1_bio_get_ex(BIO *b, int cmd,
|
||||
asn1_ps_func **ex_func,
|
||||
asn1_ps_func **ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
int ret;
|
||||
ret = BIO_ctrl(b, cmd, 0, &extmp);
|
||||
if (ret > 0) {
|
||||
*ex_func = extmp.ex_func;
|
||||
*ex_free_func = extmp.ex_free_func;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
int ret;
|
||||
ret = BIO_ctrl(b, cmd, 0, &extmp);
|
||||
if (ret > 0)
|
||||
{
|
||||
*ex_func = extmp.ex_func;
|
||||
*ex_free_func = extmp.ex_free_func;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
|
||||
asn1_ps_func *prefix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
|
||||
}
|
||||
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
|
||||
asn1_ps_func **pprefix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
|
||||
}
|
||||
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
|
||||
asn1_ps_func *suffix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
|
||||
}
|
||||
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
|
||||
asn1_ps_func **psuffix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
|
||||
}
|
||||
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
|
||||
}
|
||||
|
||||
+141
-138
@@ -63,189 +63,192 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* Experimental NDEF ASN1 BIO support routines */
|
||||
|
||||
/*
|
||||
* The usage is quite simple, initialize an ASN1 structure, get a BIO from it
|
||||
* then any data written through the BIO will end up translated to
|
||||
* approptiate format on the fly. The data is streamed out and does *not*
|
||||
* need to be all held in memory at once. When the BIO is flushed the output
|
||||
* is finalized and any signatures etc written out. The BIO is a 'proper'
|
||||
* BIO and can handle non blocking I/O correctly. The usage is simple. The
|
||||
* implementation is *not*...
|
||||
/* The usage is quite simple, initialize an ASN1 structure,
|
||||
* get a BIO from it then any data written through the BIO
|
||||
* will end up translated to approptiate format on the fly.
|
||||
* The data is streamed out and does *not* need to be
|
||||
* all held in memory at once.
|
||||
*
|
||||
* When the BIO is flushed the output is finalized and any
|
||||
* signatures etc written out.
|
||||
*
|
||||
* The BIO is a 'proper' BIO and can handle non blocking I/O
|
||||
* correctly.
|
||||
*
|
||||
* The usage is simple. The implementation is *not*...
|
||||
*/
|
||||
|
||||
/* BIO support data stored in the ASN1 BIO ex_arg */
|
||||
|
||||
typedef struct ndef_aux_st {
|
||||
/* ASN1 structure this BIO refers to */
|
||||
ASN1_VALUE *val;
|
||||
const ASN1_ITEM *it;
|
||||
/* Top of the BIO chain */
|
||||
BIO *ndef_bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} NDEF_SUPPORT;
|
||||
typedef struct ndef_aux_st
|
||||
{
|
||||
/* ASN1 structure this BIO refers to */
|
||||
ASN1_VALUE *val;
|
||||
const ASN1_ITEM *it;
|
||||
/* Top of the BIO chain */
|
||||
BIO *ndef_bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} NDEF_SUPPORT;
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg);
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg);
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
|
||||
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!aux || !aux->asn1_cb) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
if (!aux || !aux->asn1_cb)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
|
||||
out = BIO_push(asn_bio, out);
|
||||
out = BIO_push(asn_bio, out);
|
||||
|
||||
if (!ndef_aux || !asn_bio || !out)
|
||||
goto err;
|
||||
if (!ndef_aux || !asn_bio || !out)
|
||||
goto err;
|
||||
|
||||
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
|
||||
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
|
||||
|
||||
/*
|
||||
* Now let callback prepend any digest, cipher etc BIOs ASN1 structure
|
||||
* needs.
|
||||
*/
|
||||
/* Now let callback prepend any digest, cipher etc BIOs
|
||||
* ASN1 structure needs.
|
||||
*/
|
||||
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
|
||||
goto err;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
|
||||
goto err;
|
||||
|
||||
ndef_aux->val = val;
|
||||
ndef_aux->it = it;
|
||||
ndef_aux->ndef_bio = sarg.ndef_bio;
|
||||
ndef_aux->boundary = sarg.boundary;
|
||||
ndef_aux->out = out;
|
||||
ndef_aux->val = val;
|
||||
ndef_aux->it = it;
|
||||
ndef_aux->ndef_bio = sarg.ndef_bio;
|
||||
ndef_aux->boundary = sarg.boundary;
|
||||
ndef_aux->out = out;
|
||||
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
|
||||
|
||||
return sarg.ndef_bio;
|
||||
return sarg.ndef_bio;
|
||||
|
||||
err:
|
||||
if (asn_bio)
|
||||
BIO_free(asn_bio);
|
||||
if (ndef_aux)
|
||||
OPENSSL_free(ndef_aux);
|
||||
return NULL;
|
||||
}
|
||||
err:
|
||||
if (asn_bio)
|
||||
BIO_free(asn_bio);
|
||||
if (ndef_aux)
|
||||
OPENSSL_free(ndef_aux);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
|
||||
*plen = *ndef_aux->boundary - *pbuf;
|
||||
*plen = *ndef_aux->boundary - *pbuf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
if (ndef_aux->derbuf)
|
||||
OPENSSL_free(ndef_aux->derbuf);
|
||||
if (ndef_aux->derbuf)
|
||||
OPENSSL_free(ndef_aux->derbuf);
|
||||
|
||||
ndef_aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
ndef_aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg)
|
||||
{
|
||||
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
|
||||
if (!ndef_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pndef_aux);
|
||||
*pndef_aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
|
||||
if (!ndef_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pndef_aux);
|
||||
*pndef_aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
const ASN1_AUX *aux;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
const ASN1_AUX *aux;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
aux = ndef_aux->it->funcs;
|
||||
aux = ndef_aux->it->funcs;
|
||||
|
||||
/* Finalize structures */
|
||||
sarg.ndef_bio = ndef_aux->ndef_bio;
|
||||
sarg.out = ndef_aux->out;
|
||||
sarg.boundary = ndef_aux->boundary;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
|
||||
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
|
||||
return 0;
|
||||
/* Finalize structures */
|
||||
sarg.ndef_bio = ndef_aux->ndef_bio;
|
||||
sarg.out = ndef_aux->out;
|
||||
sarg.boundary = ndef_aux->boundary;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
|
||||
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *ndef_aux->boundary;
|
||||
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *ndef_aux->boundary;
|
||||
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+134
-128
@@ -62,139 +62,145 @@
|
||||
/* Based on a_int.c: equivalent ENUMERATED functions */
|
||||
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
{
|
||||
int i,n=0;
|
||||
static const char *h="0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a == NULL) return(0);
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n = 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
if (a->length == 0)
|
||||
{
|
||||
if (BIO_write(bp,"00",2) != 2) goto err;
|
||||
n=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
if ((i != 0) && (i%35 == 0))
|
||||
{
|
||||
if (BIO_write(bp,"\\\n",2) != 2) goto err;
|
||||
n+=2;
|
||||
}
|
||||
buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
|
||||
buf[1]=h[((unsigned char)a->data[i] )&0x0f];
|
||||
if (BIO_write(bp,buf,2) != 2) goto err;
|
||||
n+=2;
|
||||
}
|
||||
}
|
||||
return(n);
|
||||
err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, j, k, m, n, again, bufsize;
|
||||
unsigned char *s = NULL, *sp;
|
||||
unsigned char *bufp;
|
||||
int num = 0, slen = 0, first = 1;
|
||||
{
|
||||
int ret=0;
|
||||
int i,j,k,m,n,again,bufsize;
|
||||
unsigned char *s=NULL,*sp;
|
||||
unsigned char *bufp;
|
||||
int num=0,slen=0,first=1;
|
||||
|
||||
bs->type = V_ASN1_ENUMERATED;
|
||||
bs->type=V_ASN1_ENUMERATED;
|
||||
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
for (;;) {
|
||||
if (bufsize < 1)
|
||||
goto err_sl;
|
||||
i = bufsize;
|
||||
if (buf[i - 1] == '\n')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err_sl;
|
||||
if (buf[i - 1] == '\r')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err_sl;
|
||||
again = (buf[i - 1] == '\\');
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
for (;;)
|
||||
{
|
||||
if (bufsize < 1) goto err_sl;
|
||||
i=bufsize;
|
||||
if (buf[i-1] == '\n') buf[--i]='\0';
|
||||
if (i == 0) goto err_sl;
|
||||
if (buf[i-1] == '\r') buf[--i]='\0';
|
||||
if (i == 0) goto err_sl;
|
||||
again=(buf[i-1] == '\\');
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F')))) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err_sl;
|
||||
for (j=0; j<i; j++)
|
||||
{
|
||||
if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
|
||||
{
|
||||
i=j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i]='\0';
|
||||
/* We have now cleared all the crap off the end of the
|
||||
* line */
|
||||
if (i < 2) goto err_sl;
|
||||
|
||||
bufp=(unsigned char *)buf;
|
||||
if (first)
|
||||
{
|
||||
first=0;
|
||||
if ((bufp[0] == '0') && (buf[1] == '0'))
|
||||
{
|
||||
bufp+=2;
|
||||
i-=2;
|
||||
}
|
||||
}
|
||||
k=0;
|
||||
i-=again;
|
||||
if (i%2 != 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i/=2;
|
||||
if (num+i > slen)
|
||||
{
|
||||
if (s == NULL)
|
||||
sp=(unsigned char *)OPENSSL_malloc(
|
||||
(unsigned int)num+i*2);
|
||||
else
|
||||
sp=(unsigned char *)OPENSSL_realloc(s,
|
||||
(unsigned int)num+i*2);
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
slen=num+i*2;
|
||||
}
|
||||
for (j=0; j<i; j++,k+=2)
|
||||
{
|
||||
for (n=0; n<2; n++)
|
||||
{
|
||||
m=bufp[k+n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m-='0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m=m-'a'+10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m=m-'A'+10;
|
||||
else
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num+j]<<=4;
|
||||
s[num+j]|=m;
|
||||
}
|
||||
}
|
||||
num+=i;
|
||||
if (again)
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length=num;
|
||||
bs->data=s;
|
||||
ret=1;
|
||||
err:
|
||||
if (0)
|
||||
{
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if ((bufp[0] == '0') && (buf[1] == '0')) {
|
||||
bufp += 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
if (s == NULL)
|
||||
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
|
||||
i * 2);
|
||||
else
|
||||
sp = (unsigned char *)OPENSSL_realloc(s,
|
||||
(unsigned int)num +
|
||||
i * 2);
|
||||
if (sp == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = bufp[k + n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m -= '0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m = m - 'a' + 10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m = m - 'A' + 10;
|
||||
else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
ret = 1;
|
||||
err:
|
||||
if (0) {
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+139
-131
@@ -59,144 +59,152 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
{
|
||||
int i,n=0;
|
||||
static const char *h="0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a == NULL) return(0);
|
||||
|
||||
if (a->type & V_ASN1_NEG) {
|
||||
if (BIO_write(bp, "-", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
}
|
||||
if (a->type & V_ASN1_NEG)
|
||||
{
|
||||
if (BIO_write(bp, "-", 1) != 1) goto err;
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "00", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
if (a->length == 0)
|
||||
{
|
||||
if (BIO_write(bp,"00",2) != 2) goto err;
|
||||
n += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
if ((i != 0) && (i%35 == 0))
|
||||
{
|
||||
if (BIO_write(bp,"\\\n",2) != 2) goto err;
|
||||
n+=2;
|
||||
}
|
||||
buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
|
||||
buf[1]=h[((unsigned char)a->data[i] )&0x0f];
|
||||
if (BIO_write(bp,buf,2) != 2) goto err;
|
||||
n+=2;
|
||||
}
|
||||
}
|
||||
return(n);
|
||||
err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, j, k, m, n, again, bufsize;
|
||||
unsigned char *s = NULL, *sp;
|
||||
unsigned char *bufp;
|
||||
int num = 0, slen = 0, first = 1;
|
||||
{
|
||||
int ret=0;
|
||||
int i,j,k,m,n,again,bufsize;
|
||||
unsigned char *s=NULL,*sp;
|
||||
unsigned char *bufp;
|
||||
int num=0,slen=0,first=1;
|
||||
|
||||
bs->type = V_ASN1_INTEGER;
|
||||
bs->type=V_ASN1_INTEGER;
|
||||
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
for (;;) {
|
||||
if (bufsize < 1)
|
||||
goto err_sl;
|
||||
i = bufsize;
|
||||
if (buf[i - 1] == '\n')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err_sl;
|
||||
if (buf[i - 1] == '\r')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err_sl;
|
||||
again = (buf[i - 1] == '\\');
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
for (;;)
|
||||
{
|
||||
if (bufsize < 1) goto err_sl;
|
||||
i=bufsize;
|
||||
if (buf[i-1] == '\n') buf[--i]='\0';
|
||||
if (i == 0) goto err_sl;
|
||||
if (buf[i-1] == '\r') buf[--i]='\0';
|
||||
if (i == 0) goto err_sl;
|
||||
again=(buf[i-1] == '\\');
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F')))) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err_sl;
|
||||
for (j=0; j<i; j++)
|
||||
{
|
||||
if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
|
||||
{
|
||||
i=j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i]='\0';
|
||||
/* We have now cleared all the crap off the end of the
|
||||
* line */
|
||||
if (i < 2) goto err_sl;
|
||||
|
||||
bufp=(unsigned char *)buf;
|
||||
if (first)
|
||||
{
|
||||
first=0;
|
||||
if ((bufp[0] == '0') && (buf[1] == '0'))
|
||||
{
|
||||
bufp+=2;
|
||||
i-=2;
|
||||
}
|
||||
}
|
||||
k=0;
|
||||
i-=again;
|
||||
if (i%2 != 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i/=2;
|
||||
if (num+i > slen)
|
||||
{
|
||||
if (s == NULL)
|
||||
sp=(unsigned char *)OPENSSL_malloc(
|
||||
(unsigned int)num+i*2);
|
||||
else
|
||||
sp=OPENSSL_realloc_clean(s,slen,num+i*2);
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
slen=num+i*2;
|
||||
}
|
||||
for (j=0; j<i; j++,k+=2)
|
||||
{
|
||||
for (n=0; n<2; n++)
|
||||
{
|
||||
m=bufp[k+n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m-='0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m=m-'a'+10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m=m-'A'+10;
|
||||
else
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num+j]<<=4;
|
||||
s[num+j]|=m;
|
||||
}
|
||||
}
|
||||
num+=i;
|
||||
if (again)
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length=num;
|
||||
bs->data=s;
|
||||
ret=1;
|
||||
err:
|
||||
if (0)
|
||||
{
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if ((bufp[0] == '0') && (buf[1] == '0')) {
|
||||
bufp += 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
if (s == NULL)
|
||||
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
|
||||
i * 2);
|
||||
else
|
||||
sp = OPENSSL_realloc_clean(s, slen, num + i * 2);
|
||||
if (sp == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = bufp[k + n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m -= '0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m = m - 'a' + 10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m = m - 'A' + 10;
|
||||
else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
ret = 1;
|
||||
err:
|
||||
if (0) {
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+133
-125
@@ -59,138 +59,146 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
|
||||
{
|
||||
int i, n = 0;
|
||||
static const char *h = "0123456789ABCDEF";
|
||||
char buf[2];
|
||||
{
|
||||
int i,n=0;
|
||||
static const char *h="0123456789ABCDEF";
|
||||
char buf[2];
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a == NULL) return(0);
|
||||
|
||||
if (a->length == 0) {
|
||||
if (BIO_write(bp, "0", 1) != 1)
|
||||
goto err;
|
||||
n = 1;
|
||||
} else {
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if ((i != 0) && (i % 35 == 0)) {
|
||||
if (BIO_write(bp, "\\\n", 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
|
||||
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
|
||||
if (BIO_write(bp, buf, 2) != 2)
|
||||
goto err;
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
err:
|
||||
return (-1);
|
||||
}
|
||||
if (a->length == 0)
|
||||
{
|
||||
if (BIO_write(bp,"0",1) != 1) goto err;
|
||||
n=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
if ((i != 0) && (i%35 == 0))
|
||||
{
|
||||
if (BIO_write(bp,"\\\n",2) != 2) goto err;
|
||||
n+=2;
|
||||
}
|
||||
buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
|
||||
buf[1]=h[((unsigned char)a->data[i] )&0x0f];
|
||||
if (BIO_write(bp,buf,2) != 2) goto err;
|
||||
n+=2;
|
||||
}
|
||||
}
|
||||
return(n);
|
||||
err:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, j, k, m, n, again, bufsize;
|
||||
unsigned char *s = NULL, *sp;
|
||||
unsigned char *bufp;
|
||||
int num = 0, slen = 0, first = 1;
|
||||
{
|
||||
int ret=0;
|
||||
int i,j,k,m,n,again,bufsize;
|
||||
unsigned char *s=NULL,*sp;
|
||||
unsigned char *bufp;
|
||||
int num=0,slen=0,first=1;
|
||||
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
for (;;) {
|
||||
if (bufsize < 1) {
|
||||
if (first)
|
||||
break;
|
||||
else
|
||||
goto err_sl;
|
||||
}
|
||||
first = 0;
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
for (;;)
|
||||
{
|
||||
if (bufsize < 1)
|
||||
{
|
||||
if (first)
|
||||
break;
|
||||
else
|
||||
goto err_sl;
|
||||
}
|
||||
first=0;
|
||||
|
||||
i = bufsize;
|
||||
if (buf[i - 1] == '\n')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err_sl;
|
||||
if (buf[i - 1] == '\r')
|
||||
buf[--i] = '\0';
|
||||
if (i == 0)
|
||||
goto err_sl;
|
||||
again = (buf[i - 1] == '\\');
|
||||
i=bufsize;
|
||||
if (buf[i-1] == '\n') buf[--i]='\0';
|
||||
if (i == 0) goto err_sl;
|
||||
if (buf[i-1] == '\r') buf[--i]='\0';
|
||||
if (i == 0) goto err_sl;
|
||||
again=(buf[i-1] == '\\');
|
||||
|
||||
for (j = i - 1; j > 0; j--) {
|
||||
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F')))) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err_sl;
|
||||
for (j=i-1; j>0; j--)
|
||||
{
|
||||
if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
|
||||
{
|
||||
i=j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i]='\0';
|
||||
/* We have now cleared all the crap off the end of the
|
||||
* line */
|
||||
if (i < 2) goto err_sl;
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
bufp=(unsigned char *)buf;
|
||||
|
||||
k=0;
|
||||
i-=again;
|
||||
if (i%2 != 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i/=2;
|
||||
if (num+i > slen)
|
||||
{
|
||||
if (s == NULL)
|
||||
sp=(unsigned char *)OPENSSL_malloc(
|
||||
(unsigned int)num+i*2);
|
||||
else
|
||||
sp=(unsigned char *)OPENSSL_realloc(s,
|
||||
(unsigned int)num+i*2);
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
slen=num+i*2;
|
||||
}
|
||||
for (j=0; j<i; j++,k+=2)
|
||||
{
|
||||
for (n=0; n<2; n++)
|
||||
{
|
||||
m=bufp[k+n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m-='0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m=m-'a'+10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m=m-'A'+10;
|
||||
else
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num+j]<<=4;
|
||||
s[num+j]|=m;
|
||||
}
|
||||
}
|
||||
num+=i;
|
||||
if (again)
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length=num;
|
||||
bs->data=s;
|
||||
ret=1;
|
||||
err:
|
||||
if (0)
|
||||
{
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
if (s == NULL)
|
||||
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
|
||||
i * 2);
|
||||
else
|
||||
sp = (unsigned char *)OPENSSL_realloc(s,
|
||||
(unsigned int)num +
|
||||
i * 2);
|
||||
if (sp == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = bufp[k + n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m -= '0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m = m - 'a' + 10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m = m - 'A' + 10;
|
||||
else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
ret = 1;
|
||||
err:
|
||||
if (0) {
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+29
-30
@@ -60,44 +60,43 @@
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
|
||||
BIT_STRING_BITNAME *tbl, int indent)
|
||||
BIT_STRING_BITNAME *tbl, int indent)
|
||||
{
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
char first = 1;
|
||||
BIO_printf(out, "%*s", indent, "");
|
||||
for (bnam = tbl; bnam->lname; bnam++) {
|
||||
if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
|
||||
if (!first)
|
||||
BIO_puts(out, ", ");
|
||||
BIO_puts(out, bnam->lname);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
BIO_puts(out, "\n");
|
||||
return 1;
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
char first = 1;
|
||||
BIO_printf(out, "%*s", indent, "");
|
||||
for(bnam = tbl; bnam->lname; bnam++) {
|
||||
if(ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
|
||||
if(!first) BIO_puts(out, ", ");
|
||||
BIO_puts(out, bnam->lname);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
BIO_puts(out, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
|
||||
BIT_STRING_BITNAME *tbl)
|
||||
BIT_STRING_BITNAME *tbl)
|
||||
{
|
||||
int bitnum;
|
||||
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
|
||||
if (bitnum < 0)
|
||||
return 0;
|
||||
if (bs) {
|
||||
if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
int bitnum;
|
||||
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
|
||||
if(bitnum < 0) return 0;
|
||||
if(bs) {
|
||||
if(!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl)
|
||||
{
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
for (bnam = tbl; bnam->lname; bnam++) {
|
||||
if (!strcmp(bnam->sname, name) || !strcmp(bnam->lname, name))
|
||||
return bnam->bitnum;
|
||||
}
|
||||
return -1;
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
for(bnam = tbl; bnam->lname; bnam++) {
|
||||
if(!strcmp(bnam->sname, name) ||
|
||||
!strcmp(bnam->lname, name) ) return bnam->bitnum;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -54,54 +54,59 @@
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#ifndef OPENSSL_HEADER_RIPEMD_H
|
||||
#define OPENSSL_HEADER_RIPEMD_H
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
# define RIPEMD160_CBLOCK 64
|
||||
# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4)
|
||||
# define RIPEMD160_DIGEST_LENGTH 20
|
||||
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
|
||||
unsigned char *buf, int off)
|
||||
{
|
||||
int n,i;
|
||||
const char *neg;
|
||||
|
||||
struct RIPEMD160state_st {
|
||||
uint32_t h[5];
|
||||
uint32_t Nl, Nh;
|
||||
uint8_t data[RIPEMD160_CBLOCK];
|
||||
unsigned num;
|
||||
};
|
||||
if (num == NULL) return(1);
|
||||
neg = (BN_is_negative(num))?"-":"";
|
||||
if(!BIO_indent(bp,off,128))
|
||||
return 0;
|
||||
if (BN_is_zero(num))
|
||||
{
|
||||
if (BIO_printf(bp, "%s 0\n", number) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* RIPEMD160_Init initialises |ctx| and returns one. */
|
||||
OPENSSL_EXPORT int RIPEMD160_Init(RIPEMD160_CTX *ctx);
|
||||
if (BN_num_bytes(num) <= sizeof(long))
|
||||
{
|
||||
if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
|
||||
(unsigned long)num->d[0],neg,(unsigned long)num->d[0])
|
||||
<= 0) return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0]=0;
|
||||
if (BIO_printf(bp,"%s%s",number,
|
||||
(neg[0] == '-')?" (Negative)":"") <= 0)
|
||||
return(0);
|
||||
n=BN_bn2bin(num,&buf[1]);
|
||||
|
||||
if (buf[1] & 0x80)
|
||||
n++;
|
||||
else buf++;
|
||||
|
||||
/* RIPEMD160_Update adds |len| bytes from |data| to |ctx| and returns one. */
|
||||
OPENSSL_EXPORT int RIPEMD160_Update(RIPEMD160_CTX *ctx, const void *data,
|
||||
size_t len);
|
||||
|
||||
/* RIPEMD160_Final adds the final padding to |ctx| and writes the resulting
|
||||
* digest to |md|, which must have at least |RIPEMD160_DIGEST_LENGTH| bytes of
|
||||
* space. It returns one. */
|
||||
OPENSSL_EXPORT int RIPEMD160_Final(uint8_t *md, RIPEMD160_CTX *ctx);
|
||||
|
||||
/* RIPEMD160 writes the digest of |len| bytes from |data| to |out| and returns
|
||||
* |out|. There must be at least |RIPEMD160_DIGEST_LENGTH| bytes of space in
|
||||
* |out|. */
|
||||
OPENSSL_EXPORT uint8_t *RIPEMD160(const uint8_t *data, size_t len,
|
||||
uint8_t *out);
|
||||
|
||||
/* RIPEMD160_Transform is a low-level function that performs a single,
|
||||
* RIPEMD160 block transformation using the state from |ctx| and 64 bytes from
|
||||
* |block|. */
|
||||
OPENSSL_EXPORT void RIPEMD160_Transform(RIPEMD160_CTX *ctx,
|
||||
const uint8_t *block);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_RIPEMD_H */
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
if ((i%15) == 0)
|
||||
{
|
||||
if(BIO_puts(bp,"\n") <= 0
|
||||
|| !BIO_indent(bp,off+4,128))
|
||||
return 0;
|
||||
}
|
||||
if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
|
||||
<= 0) return(0);
|
||||
}
|
||||
if (BIO_write(bp,"\n",1) <= 0) return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
+1150
-1029
File diff suppressed because it is too large
Load Diff
+548
-512
File diff suppressed because it is too large
Load Diff
+180
-162
@@ -59,188 +59,206 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
|
||||
|
||||
/* Free up an ASN1 structure */
|
||||
|
||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(&val, it, 0);
|
||||
}
|
||||
{
|
||||
asn1_item_combine_free(&val, it, 0);
|
||||
}
|
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(pval, it, 0);
|
||||
}
|
||||
{
|
||||
asn1_item_combine_free(pval, it, 0);
|
||||
}
|
||||
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
switch (it->itype) {
|
||||
switch(it->itype)
|
||||
{
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
ASN1_template_free(pval, it->templates);
|
||||
else
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
ASN1_template_free(pval, it->templates);
|
||||
else
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
ASN1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount))
|
||||
{
|
||||
ASN1_VALUE **pchval;
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
ASN1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine)
|
||||
{
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_free)
|
||||
cf->asn1_free(*pval);
|
||||
break;
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_free)
|
||||
cf->asn1_free(*pval);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (!asn1_refcount_dec_and_test_zero(pval, it))
|
||||
return;
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/*
|
||||
* If we free up as normal we will invalidate any ANY DEFINED BY
|
||||
* field and we wont be able to determine the type of the field it
|
||||
* defines. So free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount - 1;
|
||||
for (i = 0; i < it->tcount; tt--, i++) {
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
ASN1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (!asn1_refcount_dec_and_test_zero(pval, it))
|
||||
return;
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/* If we free up as normal we will invalidate any
|
||||
* ANY DEFINED BY field and we wont be able to
|
||||
* determine the type of the field it defines. So
|
||||
* free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount - 1;
|
||||
for (i = 0; i < it->tcount; tt--, i++)
|
||||
{
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
ASN1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine)
|
||||
{
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
size_t i;
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
ASN1_VALUE *vtmp;
|
||||
vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
} else
|
||||
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
|
||||
tt->flags & ASN1_TFLG_COMBINE);
|
||||
}
|
||||
{
|
||||
size_t i;
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK)
|
||||
{
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
|
||||
{
|
||||
ASN1_VALUE *vtmp;
|
||||
vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item),
|
||||
0);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
}
|
||||
else
|
||||
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
|
||||
tt->flags & ASN1_TFLG_COMBINE);
|
||||
}
|
||||
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_free) {
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
|
||||
if (!it) {
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else {
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
{
|
||||
int utype;
|
||||
if (it)
|
||||
{
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_free)
|
||||
{
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
|
||||
if (!it)
|
||||
{
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
}
|
||||
else if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
{
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
switch(utype)
|
||||
{
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
ASN1_primitive_free(pval, NULL);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
case V_ASN1_ANY:
|
||||
ASN1_primitive_free(pval, NULL);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASN1_STRING_free((ASN1_STRING *)*pval);
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
default:
|
||||
ASN1_STRING_free((ASN1_STRING *)*pval);
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
+268
-251
@@ -63,319 +63,336 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
int combine);
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate an ASN1 structure */
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_ex_combine_new(pval, it, 0);
|
||||
}
|
||||
{
|
||||
return asn1_item_ex_combine_new(pval, it, 0);
|
||||
}
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_push_info(it->sname);
|
||||
if (it->sname)
|
||||
CRYPTO_push_info(it->sname);
|
||||
#endif
|
||||
|
||||
switch (it->itype) {
|
||||
switch(it->itype)
|
||||
{
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new) {
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new)
|
||||
{
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_new) {
|
||||
*pval = cf->asn1_new();
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_new) {
|
||||
*pval = cf->asn1_new();
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates) {
|
||||
if (!ASN1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
} else if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
{
|
||||
if (!ASN1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
}
|
||||
else if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i==2)
|
||||
{
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
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 auxerr;
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine)
|
||||
{
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
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 auxerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i==2)
|
||||
{
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
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 memerr;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine)
|
||||
{
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
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 memerr;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr;
|
||||
break;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname) CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
memerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
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();
|
||||
if (it->sname) CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
auxerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
|
||||
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();
|
||||
if (it->sname) CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
|
||||
switch (it->itype) {
|
||||
switch(it->itype)
|
||||
{
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
break;
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else *pval = NULL;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_clear(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_clear(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int ret;
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL) {
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int ret;
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL)
|
||||
{
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) {
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK)
|
||||
{
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (tt->field_name)
|
||||
CRYPTO_push_info(tt->field_name);
|
||||
if (tt->field_name)
|
||||
CRYPTO_push_info(tt->field_name);
|
||||
#endif
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
|
||||
done:
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK)
|
||||
{
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
|
||||
done:
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
|
||||
/* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
* all the old functions.
|
||||
*/
|
||||
|
||||
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
|
||||
if (!it)
|
||||
return 0;
|
||||
if (!it)
|
||||
return 0;
|
||||
|
||||
if (it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_new)
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
if (it->funcs)
|
||||
{
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_new)
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch(utype)
|
||||
{
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
|
||||
if (!typ)
|
||||
return 0;
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
case V_ASN1_ANY:
|
||||
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
|
||||
if (!typ)
|
||||
return 0;
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
|
||||
default:
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*pval = NULL;
|
||||
}
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs)
|
||||
{
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else *pval = NULL;
|
||||
}
|
||||
|
||||
+483
-437
File diff suppressed because it is too large
Load Diff
+21
-28
@@ -58,19 +58,20 @@
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
|
||||
/* Declarations for string types */
|
||||
|
||||
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
|
||||
@@ -94,16 +95,12 @@ IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY);
|
||||
|
||||
/*
|
||||
* Just swallow an ASN1_SEQUENCE in an ASN1_STRING
|
||||
*/ ;
|
||||
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE);
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE);
|
||||
|
||||
/*
|
||||
* Multistring types
|
||||
*/ ;
|
||||
/* Multistring types */;
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE);
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE);
|
||||
@@ -114,23 +111,18 @@ IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT);
|
||||
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING);
|
||||
|
||||
/*
|
||||
* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE
|
||||
*/ ;
|
||||
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */;
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1);
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1);
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0);
|
||||
|
||||
/*
|
||||
* Special, OCTET STRING with indefinite length constructed support
|
||||
*/ ;
|
||||
/* Special, OCTET STRING with indefinite length constructed support */;
|
||||
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING,
|
||||
ASN1_TFLG_NDEF);
|
||||
ASN1_TFLG_NDEF);
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
|
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY,
|
||||
ASN1_ANY);
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = ASN1_EX_TEMPLATE_TYPE(
|
||||
ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY);
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY);
|
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
|
||||
@@ -139,6 +131,7 @@ ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
|
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY);
|
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY,
|
||||
ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY);
|
||||
ASN1_SEQUENCE_ANY,
|
||||
ASN1_SEQUENCE_ANY);
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY,
|
||||
ASN1_SET_ANY);
|
||||
ASN1_SET_ANY);
|
||||
|
||||
+52
-62
@@ -59,95 +59,85 @@
|
||||
#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.
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#define BN_SENSITIVE 1
|
||||
#define BN_SENSITIVE 1
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
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 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 */ ,
|
||||
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_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_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;
|
||||
*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;
|
||||
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)
|
||||
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);
|
||||
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)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
+82
-97
@@ -63,135 +63,120 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
|
||||
/* 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 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
|
||||
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_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_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;
|
||||
*(long *)pval = it->size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
*(long *)pval = it->size;
|
||||
}
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
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;
|
||||
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));
|
||||
/* 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;
|
||||
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;
|
||||
/* 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;
|
||||
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 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;
|
||||
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);
|
||||
}
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
return BIO_printf(out, "%ld\n", *(long *)pval);
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ static bool TestDecode() {
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
if (!TestEncode() ||
|
||||
!TestDecode()) {
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
BIO *BIO_new_mem_buf(const void *buf, int len) {
|
||||
BIO *BIO_new_mem_buf(void *buf, int len) {
|
||||
BIO *ret;
|
||||
BUF_MEM *b;
|
||||
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
|
||||
@@ -80,8 +80,7 @@ BIO *BIO_new_mem_buf(const void *buf, int len) {
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)ret->ptr;
|
||||
/* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */
|
||||
b->data = (void *)buf;
|
||||
b->data = buf;
|
||||
b->length = size;
|
||||
b->max = size;
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@ static bool TestPrintf() {
|
||||
|
||||
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
|
||||
size_t expected_len, size_t max_len) {
|
||||
ScopedBIO bio(BIO_new_mem_buf(data, data_len));
|
||||
ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(data), data_len));
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_len;
|
||||
@@ -412,6 +412,7 @@ static bool TestASN1() {
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
|
||||
+3
-3
@@ -100,7 +100,7 @@ static int buffer_new(BIO *bio) {
|
||||
if (ctx->ibuf == NULL) {
|
||||
goto err1;
|
||||
}
|
||||
ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->obuf == NULL) {
|
||||
goto err2;
|
||||
}
|
||||
@@ -340,13 +340,13 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
p1 = ctx->ibuf;
|
||||
p2 = ctx->obuf;
|
||||
if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
|
||||
p1 = OPENSSL_malloc(ibs);
|
||||
p1 = (char *)OPENSSL_malloc(ibs);
|
||||
if (p1 == NULL) {
|
||||
goto malloc_error;
|
||||
}
|
||||
}
|
||||
if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
|
||||
p2 = OPENSSL_malloc(obs);
|
||||
p2 = (char *)OPENSSL_malloc(obs);
|
||||
if (p2 == NULL) {
|
||||
if (p1 != ctx->ibuf) {
|
||||
OPENSSL_free(p1);
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
@@ -541,7 +542,3 @@ int BIO_set_conn_port(BIO *bio, const char *port_str) {
|
||||
int BIO_set_nbio(BIO *bio, int on) {
|
||||
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
|
||||
}
|
||||
|
||||
int BIO_do_connect(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -72,8 +72,6 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static int bio_fd_non_fatal_error(int err) {
|
||||
if (
|
||||
|
||||
+38
-2
@@ -87,11 +87,47 @@
|
||||
#define BIO_FP_WRITE 0x04
|
||||
#define BIO_FP_APPEND 0x08
|
||||
|
||||
static FILE *open_file(const char *filename, const char *mode) {
|
||||
#if defined(OPENSSL_WINDOWS) && defined(CP_UTF8)
|
||||
int sz, len_0 = (int)strlen(filename) + 1;
|
||||
DWORD flags;
|
||||
|
||||
/* Basically there are three cases to cover: a) filename is pure ASCII
|
||||
* string; b) actual UTF-8 encoded string and c) locale-ized string, i.e. one
|
||||
* containing 8-bit characters that are meaningful in current system locale.
|
||||
* If filename is pure ASCII or real UTF-8 encoded string,
|
||||
* MultiByteToWideChar succeeds and _wfopen works. If filename is locale-ized
|
||||
* string, chances are that MultiByteToWideChar fails reporting
|
||||
* ERROR_NO_UNICODE_TRANSLATION, in which case we fall back to fopen... */
|
||||
if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
|
||||
filename, len_0, NULL, 0)) > 0 ||
|
||||
(GetLastError() == ERROR_INVALID_FLAGS &&
|
||||
(sz = MultiByteToWideChar(CP_UTF8, (flags = 0), filename, len_0, NULL,
|
||||
0)) > 0)) {
|
||||
WCHAR wmode[8];
|
||||
WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
|
||||
|
||||
if (MultiByteToWideChar(CP_UTF8, flags, filename, len_0, wfilename, sz) &&
|
||||
MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, wmode,
|
||||
sizeof(wmode) / sizeof(wmode[0])) &&
|
||||
(file = _wfopen(wfilename, wmode)) == NULL &&
|
||||
(errno == ENOENT ||
|
||||
errno == EBADF)) /* UTF-8 decode succeeded, but no file, filename
|
||||
* could still have been locale-ized... */
|
||||
return fopen(filename, mode);
|
||||
} else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
|
||||
return fopen(filename, mode);
|
||||
}
|
||||
#else
|
||||
return fopen(filename, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
BIO *BIO_new_file(const char *filename, const char *mode) {
|
||||
BIO *ret;
|
||||
FILE *file;
|
||||
|
||||
file = fopen(filename, mode);
|
||||
file = open_file(filename, mode);
|
||||
if (file == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
|
||||
@@ -220,7 +256,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
fp = fopen(ptr, p);
|
||||
fp = open_file(ptr, p);
|
||||
if (fp == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
|
||||
|
||||
@@ -67,9 +67,6 @@ typedef unsigned short u_short;
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#pragma warning(push, 3)
|
||||
#include <winsock2.h>
|
||||
#pragma warning(pop)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
|
||||
+1
-1
@@ -742,7 +742,7 @@ static const BIO_METHOD methods_biop = {
|
||||
bio_free, NULL /* no bio_callback_ctrl */
|
||||
};
|
||||
|
||||
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
|
||||
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
|
||||
BIO** bio2_p, size_t writebuf2) {
|
||||
|
||||
@@ -91,6 +91,7 @@ $code=<<___;
|
||||
#endif
|
||||
|
||||
.global bn_mul_mont
|
||||
.hidden bn_mul_mont
|
||||
.type bn_mul_mont,%function
|
||||
|
||||
.align 5
|
||||
@@ -107,7 +108,7 @@ bn_mul_mont:
|
||||
#ifdef __APPLE__
|
||||
ldr r0,[r0]
|
||||
#endif
|
||||
tst r0,#ARMV7_NEON @ NEON available?
|
||||
tst r0,#1 @ NEON available?
|
||||
ldmia sp, {r0,r2}
|
||||
beq .Lialu
|
||||
add sp,sp,#8
|
||||
|
||||
Executable → Regular
+76
-139
@@ -427,7 +427,7 @@ $TEMP2 = $B2;
|
||||
$TEMP3 = $Y1;
|
||||
$TEMP4 = $Y2;
|
||||
$code.=<<___;
|
||||
# we need to fix indices 32-39 to avoid overflow
|
||||
#we need to fix indexes 32-39 to avoid overflow
|
||||
vmovdqu 32*8(%rsp), $ACC8 # 32*8-192($tp0),
|
||||
vmovdqu 32*9(%rsp), $ACC1 # 32*9-192($tp0)
|
||||
vmovdqu 32*10(%rsp), $ACC2 # 32*10-192($tp0)
|
||||
@@ -1576,128 +1576,68 @@ rsaz_1024_scatter5_avx2:
|
||||
.type rsaz_1024_gather5_avx2,\@abi-omnipotent
|
||||
.align 32
|
||||
rsaz_1024_gather5_avx2:
|
||||
vzeroupper
|
||||
mov %rsp,%r11
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
lea -0x88(%rsp),%rax
|
||||
vzeroupper
|
||||
.LSEH_begin_rsaz_1024_gather5:
|
||||
# I can't trust assembler to use specific encoding:-(
|
||||
.byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax),%rsp
|
||||
.byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6,-0x20(%rax)
|
||||
.byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7,-0x10(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8,0(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9,0x10(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10,0x20(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11,0x30(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12,0x40(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13,0x50(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14,0x60(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15,0x70(%rax)
|
||||
.byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
|
||||
.byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6,-0x20(%rax)
|
||||
.byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7,-0x10(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8,0(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9,0x10(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10,0x20(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11,0x30(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12,0x40(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13,0x50(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14,0x60(%rax)
|
||||
.byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15,0x70(%rax)
|
||||
___
|
||||
$code.=<<___;
|
||||
lea -0x100(%rsp),%rsp
|
||||
and \$-32, %rsp
|
||||
lea .Linc(%rip), %r10
|
||||
lea -128(%rsp),%rax # control u-op density
|
||||
lea .Lgather_table(%rip),%r11
|
||||
mov $power,%eax
|
||||
and \$3,$power
|
||||
shr \$2,%eax # cache line number
|
||||
shl \$4,$power # offset within cache line
|
||||
|
||||
vmovd $power, %xmm4
|
||||
vmovdqa (%r10),%ymm0
|
||||
vmovdqa 32(%r10),%ymm1
|
||||
vmovdqa 64(%r10),%ymm5
|
||||
vpbroadcastd %xmm4,%ymm4
|
||||
vmovdqu -32(%r11),%ymm7 # .Lgather_permd
|
||||
vpbroadcastb 8(%r11,%rax), %xmm8
|
||||
vpbroadcastb 7(%r11,%rax), %xmm9
|
||||
vpbroadcastb 6(%r11,%rax), %xmm10
|
||||
vpbroadcastb 5(%r11,%rax), %xmm11
|
||||
vpbroadcastb 4(%r11,%rax), %xmm12
|
||||
vpbroadcastb 3(%r11,%rax), %xmm13
|
||||
vpbroadcastb 2(%r11,%rax), %xmm14
|
||||
vpbroadcastb 1(%r11,%rax), %xmm15
|
||||
|
||||
vpaddd %ymm5, %ymm0, %ymm2
|
||||
vpcmpeqd %ymm4, %ymm0, %ymm0
|
||||
vpaddd %ymm5, %ymm1, %ymm3
|
||||
vpcmpeqd %ymm4, %ymm1, %ymm1
|
||||
vmovdqa %ymm0, 32*0+128(%rax)
|
||||
vpaddd %ymm5, %ymm2, %ymm0
|
||||
vpcmpeqd %ymm4, %ymm2, %ymm2
|
||||
vmovdqa %ymm1, 32*1+128(%rax)
|
||||
vpaddd %ymm5, %ymm3, %ymm1
|
||||
vpcmpeqd %ymm4, %ymm3, %ymm3
|
||||
vmovdqa %ymm2, 32*2+128(%rax)
|
||||
vpaddd %ymm5, %ymm0, %ymm2
|
||||
vpcmpeqd %ymm4, %ymm0, %ymm0
|
||||
vmovdqa %ymm3, 32*3+128(%rax)
|
||||
vpaddd %ymm5, %ymm1, %ymm3
|
||||
vpcmpeqd %ymm4, %ymm1, %ymm1
|
||||
vmovdqa %ymm0, 32*4+128(%rax)
|
||||
vpaddd %ymm5, %ymm2, %ymm8
|
||||
vpcmpeqd %ymm4, %ymm2, %ymm2
|
||||
vmovdqa %ymm1, 32*5+128(%rax)
|
||||
vpaddd %ymm5, %ymm3, %ymm9
|
||||
vpcmpeqd %ymm4, %ymm3, %ymm3
|
||||
vmovdqa %ymm2, 32*6+128(%rax)
|
||||
vpaddd %ymm5, %ymm8, %ymm10
|
||||
vpcmpeqd %ymm4, %ymm8, %ymm8
|
||||
vmovdqa %ymm3, 32*7+128(%rax)
|
||||
vpaddd %ymm5, %ymm9, %ymm11
|
||||
vpcmpeqd %ymm4, %ymm9, %ymm9
|
||||
vpaddd %ymm5, %ymm10, %ymm12
|
||||
vpcmpeqd %ymm4, %ymm10, %ymm10
|
||||
vpaddd %ymm5, %ymm11, %ymm13
|
||||
vpcmpeqd %ymm4, %ymm11, %ymm11
|
||||
vpaddd %ymm5, %ymm12, %ymm14
|
||||
vpcmpeqd %ymm4, %ymm12, %ymm12
|
||||
vpaddd %ymm5, %ymm13, %ymm15
|
||||
vpcmpeqd %ymm4, %ymm13, %ymm13
|
||||
vpcmpeqd %ymm4, %ymm14, %ymm14
|
||||
vpcmpeqd %ymm4, %ymm15, %ymm15
|
||||
|
||||
vmovdqa -32(%r10),%ymm7 # .Lgather_permd
|
||||
lea 128($inp), $inp
|
||||
mov \$9,$power
|
||||
lea 64($inp,$power),$inp
|
||||
mov \$64,%r11 # size optimization
|
||||
mov \$9,%eax
|
||||
jmp .Loop_gather_1024
|
||||
|
||||
.align 32
|
||||
.Loop_gather_1024:
|
||||
vmovdqa 32*0-128($inp), %ymm0
|
||||
vmovdqa 32*1-128($inp), %ymm1
|
||||
vmovdqa 32*2-128($inp), %ymm2
|
||||
vmovdqa 32*3-128($inp), %ymm3
|
||||
vpand 32*0+128(%rax), %ymm0, %ymm0
|
||||
vpand 32*1+128(%rax), %ymm1, %ymm1
|
||||
vpand 32*2+128(%rax), %ymm2, %ymm2
|
||||
vpor %ymm0, %ymm1, %ymm4
|
||||
vpand 32*3+128(%rax), %ymm3, %ymm3
|
||||
vmovdqa 32*4-128($inp), %ymm0
|
||||
vmovdqa 32*5-128($inp), %ymm1
|
||||
vpor %ymm2, %ymm3, %ymm5
|
||||
vmovdqa 32*6-128($inp), %ymm2
|
||||
vmovdqa 32*7-128($inp), %ymm3
|
||||
vpand 32*4+128(%rax), %ymm0, %ymm0
|
||||
vpand 32*5+128(%rax), %ymm1, %ymm1
|
||||
vpand 32*6+128(%rax), %ymm2, %ymm2
|
||||
vpor %ymm0, %ymm4, %ymm4
|
||||
vpand 32*7+128(%rax), %ymm3, %ymm3
|
||||
vpand 32*8-128($inp), %ymm8, %ymm0
|
||||
vpor %ymm1, %ymm5, %ymm5
|
||||
vpand 32*9-128($inp), %ymm9, %ymm1
|
||||
vpor %ymm2, %ymm4, %ymm4
|
||||
vpand 32*10-128($inp),%ymm10, %ymm2
|
||||
vpor %ymm3, %ymm5, %ymm5
|
||||
vpand 32*11-128($inp),%ymm11, %ymm3
|
||||
vpor %ymm0, %ymm4, %ymm4
|
||||
vpand 32*12-128($inp),%ymm12, %ymm0
|
||||
vpor %ymm1, %ymm5, %ymm5
|
||||
vpand 32*13-128($inp),%ymm13, %ymm1
|
||||
vpor %ymm2, %ymm4, %ymm4
|
||||
vpand 32*14-128($inp),%ymm14, %ymm2
|
||||
vpor %ymm3, %ymm5, %ymm5
|
||||
vpand 32*15-128($inp),%ymm15, %ymm3
|
||||
lea 32*16($inp), $inp
|
||||
vpor %ymm0, %ymm4, %ymm4
|
||||
vpor %ymm1, %ymm5, %ymm5
|
||||
vpor %ymm2, %ymm4, %ymm4
|
||||
vpor %ymm3, %ymm5, %ymm5
|
||||
|
||||
vpor %ymm5, %ymm4, %ymm4
|
||||
vextracti128 \$1, %ymm4, %xmm5 # upper half is cleared
|
||||
vpor %xmm4, %xmm5, %xmm5
|
||||
vpermd %ymm5,%ymm7,%ymm5
|
||||
vmovdqu %ymm5,($out)
|
||||
vpand -64($inp), %xmm8,%xmm0
|
||||
vpand ($inp), %xmm9,%xmm1
|
||||
vpand 64($inp), %xmm10,%xmm2
|
||||
vpand ($inp,%r11,2), %xmm11,%xmm3
|
||||
vpor %xmm0,%xmm1,%xmm1
|
||||
vpand 64($inp,%r11,2), %xmm12,%xmm4
|
||||
vpor %xmm2,%xmm3,%xmm3
|
||||
vpand ($inp,%r11,4), %xmm13,%xmm5
|
||||
vpor %xmm1,%xmm3,%xmm3
|
||||
vpand 64($inp,%r11,4), %xmm14,%xmm6
|
||||
vpor %xmm4,%xmm5,%xmm5
|
||||
vpand -128($inp,%r11,8), %xmm15,%xmm2
|
||||
lea ($inp,%r11,8),$inp
|
||||
vpor %xmm3,%xmm5,%xmm5
|
||||
vpor %xmm2,%xmm6,%xmm6
|
||||
vpor %xmm5,%xmm6,%xmm6
|
||||
vpermd %ymm6,%ymm7,%ymm6
|
||||
vmovdqu %ymm6,($out)
|
||||
lea 32($out),$out
|
||||
dec $power
|
||||
dec %eax
|
||||
jnz .Loop_gather_1024
|
||||
|
||||
vpxor %ymm0,%ymm0,%ymm0
|
||||
@@ -1705,20 +1645,20 @@ $code.=<<___;
|
||||
vzeroupper
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps -0xa8(%r11),%xmm6
|
||||
movaps -0x98(%r11),%xmm7
|
||||
movaps -0x88(%r11),%xmm8
|
||||
movaps -0x78(%r11),%xmm9
|
||||
movaps -0x68(%r11),%xmm10
|
||||
movaps -0x58(%r11),%xmm11
|
||||
movaps -0x48(%r11),%xmm12
|
||||
movaps -0x38(%r11),%xmm13
|
||||
movaps -0x28(%r11),%xmm14
|
||||
movaps -0x18(%r11),%xmm15
|
||||
movaps (%rsp),%xmm6
|
||||
movaps 0x10(%rsp),%xmm7
|
||||
movaps 0x20(%rsp),%xmm8
|
||||
movaps 0x30(%rsp),%xmm9
|
||||
movaps 0x40(%rsp),%xmm10
|
||||
movaps 0x50(%rsp),%xmm11
|
||||
movaps 0x60(%rsp),%xmm12
|
||||
movaps 0x70(%rsp),%xmm13
|
||||
movaps 0x80(%rsp),%xmm14
|
||||
movaps 0x90(%rsp),%xmm15
|
||||
lea 0xa8(%rsp),%rsp
|
||||
.LSEH_end_rsaz_1024_gather5:
|
||||
___
|
||||
$code.=<<___;
|
||||
lea (%r11),%rsp
|
||||
ret
|
||||
.size rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
|
||||
___
|
||||
@@ -1752,10 +1692,8 @@ $code.=<<___;
|
||||
.long 0,2,4,6,7,7,7,7
|
||||
.Lgather_permd:
|
||||
.long 0,7,1,7,2,7,3,7
|
||||
.Linc:
|
||||
.long 0,0,0,0, 1,1,1,1
|
||||
.long 2,2,2,2, 3,3,3,3
|
||||
.long 4,4,4,4, 4,4,4,4
|
||||
.Lgather_table:
|
||||
.byte 0,0,0,0,0,0,0,0, 0xff,0,0,0,0,0,0,0
|
||||
.align 64
|
||||
___
|
||||
|
||||
@@ -1883,19 +1821,18 @@ rsaz_se_handler:
|
||||
.rva rsaz_se_handler
|
||||
.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
|
||||
.byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
|
||||
.byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
|
||||
.byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
|
||||
.byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
|
||||
.byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
|
||||
.byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
|
||||
.byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
|
||||
.byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
|
||||
.byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
|
||||
.byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8
|
||||
.byte 0x00,0xb3,0x00,0x00 # set_frame r11
|
||||
.byte 0x01,0x33,0x16,0x00
|
||||
.byte 0x36,0xf8,0x09,0x00 #vmovaps 0x90(rsp),xmm15
|
||||
.byte 0x31,0xe8,0x08,0x00 #vmovaps 0x80(rsp),xmm14
|
||||
.byte 0x2c,0xd8,0x07,0x00 #vmovaps 0x70(rsp),xmm13
|
||||
.byte 0x27,0xc8,0x06,0x00 #vmovaps 0x60(rsp),xmm12
|
||||
.byte 0x22,0xb8,0x05,0x00 #vmovaps 0x50(rsp),xmm11
|
||||
.byte 0x1d,0xa8,0x04,0x00 #vmovaps 0x40(rsp),xmm10
|
||||
.byte 0x18,0x98,0x03,0x00 #vmovaps 0x30(rsp),xmm9
|
||||
.byte 0x13,0x88,0x02,0x00 #vmovaps 0x20(rsp),xmm8
|
||||
.byte 0x0e,0x78,0x01,0x00 #vmovaps 0x10(rsp),xmm7
|
||||
.byte 0x09,0x68,0x00,0x00 #vmovaps 0x00(rsp),xmm6
|
||||
.byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
|
||||
___
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
+84
-291
@@ -902,76 +902,9 @@ rsaz_512_mul_gather4:
|
||||
push %r14
|
||||
push %r15
|
||||
|
||||
subq \$`128+24+($win64?0xb0:0)`, %rsp
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps %xmm6,0xa0(%rsp)
|
||||
movaps %xmm7,0xb0(%rsp)
|
||||
movaps %xmm8,0xc0(%rsp)
|
||||
movaps %xmm9,0xd0(%rsp)
|
||||
movaps %xmm10,0xe0(%rsp)
|
||||
movaps %xmm11,0xf0(%rsp)
|
||||
movaps %xmm12,0x100(%rsp)
|
||||
movaps %xmm13,0x110(%rsp)
|
||||
movaps %xmm14,0x120(%rsp)
|
||||
movaps %xmm15,0x130(%rsp)
|
||||
___
|
||||
$code.=<<___;
|
||||
mov $pwr, $pwr
|
||||
subq \$128+24, %rsp
|
||||
.Lmul_gather4_body:
|
||||
movd $pwr,%xmm8
|
||||
movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002
|
||||
movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000
|
||||
|
||||
pshufd \$0,%xmm8,%xmm8 # broadcast $power
|
||||
movdqa %xmm1,%xmm7
|
||||
movdqa %xmm1,%xmm2
|
||||
___
|
||||
########################################################################
|
||||
# calculate mask by comparing 0..15 to $power
|
||||
#
|
||||
for($i=0;$i<4;$i++) {
|
||||
$code.=<<___;
|
||||
paddd %xmm`$i`,%xmm`$i+1`
|
||||
pcmpeqd %xmm8,%xmm`$i`
|
||||
movdqa %xmm7,%xmm`$i+3`
|
||||
___
|
||||
}
|
||||
for(;$i<7;$i++) {
|
||||
$code.=<<___;
|
||||
paddd %xmm`$i`,%xmm`$i+1`
|
||||
pcmpeqd %xmm8,%xmm`$i`
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
pcmpeqd %xmm8,%xmm7
|
||||
|
||||
movdqa 16*0($bp),%xmm8
|
||||
movdqa 16*1($bp),%xmm9
|
||||
movdqa 16*2($bp),%xmm10
|
||||
movdqa 16*3($bp),%xmm11
|
||||
pand %xmm0,%xmm8
|
||||
movdqa 16*4($bp),%xmm12
|
||||
pand %xmm1,%xmm9
|
||||
movdqa 16*5($bp),%xmm13
|
||||
pand %xmm2,%xmm10
|
||||
movdqa 16*6($bp),%xmm14
|
||||
pand %xmm3,%xmm11
|
||||
movdqa 16*7($bp),%xmm15
|
||||
leaq 128($bp), %rbp
|
||||
pand %xmm4,%xmm12
|
||||
pand %xmm5,%xmm13
|
||||
pand %xmm6,%xmm14
|
||||
pand %xmm7,%xmm15
|
||||
por %xmm10,%xmm8
|
||||
por %xmm11,%xmm9
|
||||
por %xmm12,%xmm8
|
||||
por %xmm13,%xmm9
|
||||
por %xmm14,%xmm8
|
||||
por %xmm15,%xmm9
|
||||
|
||||
por %xmm9,%xmm8
|
||||
pshufd \$0x4e,%xmm8,%xmm9
|
||||
por %xmm9,%xmm8
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
movl \$0x80100,%r11d
|
||||
@@ -980,38 +913,45 @@ $code.=<<___ if ($addx);
|
||||
je .Lmulx_gather
|
||||
___
|
||||
$code.=<<___;
|
||||
movq %xmm8,%rbx
|
||||
|
||||
movq $n0, 128(%rsp) # off-load arguments
|
||||
movq $out, 128+8(%rsp)
|
||||
movq $mod, 128+16(%rsp)
|
||||
movl 64($bp,$pwr,4), %eax
|
||||
movq $out, %xmm0 # off-load arguments
|
||||
movl ($bp,$pwr,4), %ebx
|
||||
movq $mod, %xmm1
|
||||
movq $n0, 128(%rsp)
|
||||
|
||||
shlq \$32, %rax
|
||||
or %rax, %rbx
|
||||
movq ($ap), %rax
|
||||
movq 8($ap), %rcx
|
||||
leaq 128($bp,$pwr,4), %rbp
|
||||
mulq %rbx # 0 iteration
|
||||
movq %rax, (%rsp)
|
||||
movq %rcx, %rax
|
||||
movq %rdx, %r8
|
||||
|
||||
mulq %rbx
|
||||
movd (%rbp), %xmm4
|
||||
addq %rax, %r8
|
||||
movq 16($ap), %rax
|
||||
movq %rdx, %r9
|
||||
adcq \$0, %r9
|
||||
|
||||
mulq %rbx
|
||||
movd 64(%rbp), %xmm5
|
||||
addq %rax, %r9
|
||||
movq 24($ap), %rax
|
||||
movq %rdx, %r10
|
||||
adcq \$0, %r10
|
||||
|
||||
mulq %rbx
|
||||
pslldq \$4, %xmm5
|
||||
addq %rax, %r10
|
||||
movq 32($ap), %rax
|
||||
movq %rdx, %r11
|
||||
adcq \$0, %r11
|
||||
|
||||
mulq %rbx
|
||||
por %xmm5, %xmm4
|
||||
addq %rax, %r11
|
||||
movq 40($ap), %rax
|
||||
movq %rdx, %r12
|
||||
@@ -1024,12 +964,14 @@ $code.=<<___;
|
||||
adcq \$0, %r13
|
||||
|
||||
mulq %rbx
|
||||
leaq 128(%rbp), %rbp
|
||||
addq %rax, %r13
|
||||
movq 56($ap), %rax
|
||||
movq %rdx, %r14
|
||||
adcq \$0, %r14
|
||||
|
||||
mulq %rbx
|
||||
movq %xmm4, %rbx
|
||||
addq %rax, %r14
|
||||
movq ($ap), %rax
|
||||
movq %rdx, %r15
|
||||
@@ -1041,35 +983,6 @@ $code.=<<___;
|
||||
|
||||
.align 32
|
||||
.Loop_mul_gather:
|
||||
movdqa 16*0(%rbp),%xmm8
|
||||
movdqa 16*1(%rbp),%xmm9
|
||||
movdqa 16*2(%rbp),%xmm10
|
||||
movdqa 16*3(%rbp),%xmm11
|
||||
pand %xmm0,%xmm8
|
||||
movdqa 16*4(%rbp),%xmm12
|
||||
pand %xmm1,%xmm9
|
||||
movdqa 16*5(%rbp),%xmm13
|
||||
pand %xmm2,%xmm10
|
||||
movdqa 16*6(%rbp),%xmm14
|
||||
pand %xmm3,%xmm11
|
||||
movdqa 16*7(%rbp),%xmm15
|
||||
leaq 128(%rbp), %rbp
|
||||
pand %xmm4,%xmm12
|
||||
pand %xmm5,%xmm13
|
||||
pand %xmm6,%xmm14
|
||||
pand %xmm7,%xmm15
|
||||
por %xmm10,%xmm8
|
||||
por %xmm11,%xmm9
|
||||
por %xmm12,%xmm8
|
||||
por %xmm13,%xmm9
|
||||
por %xmm14,%xmm8
|
||||
por %xmm15,%xmm9
|
||||
|
||||
por %xmm9,%xmm8
|
||||
pshufd \$0x4e,%xmm8,%xmm9
|
||||
por %xmm9,%xmm8
|
||||
movq %xmm8,%rbx
|
||||
|
||||
mulq %rbx
|
||||
addq %rax, %r8
|
||||
movq 8($ap), %rax
|
||||
@@ -1078,6 +991,7 @@ $code.=<<___;
|
||||
adcq \$0, %r8
|
||||
|
||||
mulq %rbx
|
||||
movd (%rbp), %xmm4
|
||||
addq %rax, %r9
|
||||
movq 16($ap), %rax
|
||||
adcq \$0, %rdx
|
||||
@@ -1086,6 +1000,7 @@ $code.=<<___;
|
||||
adcq \$0, %r9
|
||||
|
||||
mulq %rbx
|
||||
movd 64(%rbp), %xmm5
|
||||
addq %rax, %r10
|
||||
movq 24($ap), %rax
|
||||
adcq \$0, %rdx
|
||||
@@ -1094,6 +1009,7 @@ $code.=<<___;
|
||||
adcq \$0, %r10
|
||||
|
||||
mulq %rbx
|
||||
pslldq \$4, %xmm5
|
||||
addq %rax, %r11
|
||||
movq 32($ap), %rax
|
||||
adcq \$0, %rdx
|
||||
@@ -1102,6 +1018,7 @@ $code.=<<___;
|
||||
adcq \$0, %r11
|
||||
|
||||
mulq %rbx
|
||||
por %xmm5, %xmm4
|
||||
addq %rax, %r12
|
||||
movq 40($ap), %rax
|
||||
adcq \$0, %rdx
|
||||
@@ -1126,6 +1043,7 @@ $code.=<<___;
|
||||
adcq \$0, %r14
|
||||
|
||||
mulq %rbx
|
||||
movq %xmm4, %rbx
|
||||
addq %rax, %r15
|
||||
movq ($ap), %rax
|
||||
adcq \$0, %rdx
|
||||
@@ -1133,6 +1051,7 @@ $code.=<<___;
|
||||
movq %rdx, %r15
|
||||
adcq \$0, %r15
|
||||
|
||||
leaq 128(%rbp), %rbp
|
||||
leaq 8(%rdi), %rdi
|
||||
|
||||
decl %ecx
|
||||
@@ -1147,8 +1066,8 @@ $code.=<<___;
|
||||
movq %r14, 48(%rdi)
|
||||
movq %r15, 56(%rdi)
|
||||
|
||||
movq 128+8(%rsp), $out
|
||||
movq 128+16(%rsp), %rbp
|
||||
movq %xmm0, $out
|
||||
movq %xmm1, %rbp
|
||||
|
||||
movq (%rsp), %r8
|
||||
movq 8(%rsp), %r9
|
||||
@@ -1166,37 +1085,45 @@ $code.=<<___ if ($addx);
|
||||
|
||||
.align 32
|
||||
.Lmulx_gather:
|
||||
movq %xmm8,%rdx
|
||||
|
||||
mov $n0, 128(%rsp) # off-load arguments
|
||||
mov $out, 128+8(%rsp)
|
||||
mov $mod, 128+16(%rsp)
|
||||
mov 64($bp,$pwr,4), %eax
|
||||
movq $out, %xmm0 # off-load arguments
|
||||
lea 128($bp,$pwr,4), %rbp
|
||||
mov ($bp,$pwr,4), %edx
|
||||
movq $mod, %xmm1
|
||||
mov $n0, 128(%rsp)
|
||||
|
||||
shl \$32, %rax
|
||||
or %rax, %rdx
|
||||
mulx ($ap), %rbx, %r8 # 0 iteration
|
||||
mov %rbx, (%rsp)
|
||||
xor %edi, %edi # cf=0, of=0
|
||||
|
||||
mulx 8($ap), %rax, %r9
|
||||
movd (%rbp), %xmm4
|
||||
|
||||
mulx 16($ap), %rbx, %r10
|
||||
movd 64(%rbp), %xmm5
|
||||
adcx %rax, %r8
|
||||
|
||||
mulx 24($ap), %rax, %r11
|
||||
pslldq \$4, %xmm5
|
||||
adcx %rbx, %r9
|
||||
|
||||
mulx 32($ap), %rbx, %r12
|
||||
por %xmm5, %xmm4
|
||||
adcx %rax, %r10
|
||||
|
||||
mulx 40($ap), %rax, %r13
|
||||
adcx %rbx, %r11
|
||||
|
||||
mulx 48($ap), %rbx, %r14
|
||||
lea 128(%rbp), %rbp
|
||||
adcx %rax, %r12
|
||||
|
||||
mulx 56($ap), %rax, %r15
|
||||
movq %xmm4, %rdx
|
||||
adcx %rbx, %r13
|
||||
adcx %rax, %r14
|
||||
.byte 0x67
|
||||
mov %r8, %rbx
|
||||
adcx %rdi, %r15 # %rdi is 0
|
||||
|
||||
@@ -1205,48 +1132,24 @@ $code.=<<___ if ($addx);
|
||||
|
||||
.align 32
|
||||
.Loop_mulx_gather:
|
||||
movdqa 16*0(%rbp),%xmm8
|
||||
movdqa 16*1(%rbp),%xmm9
|
||||
movdqa 16*2(%rbp),%xmm10
|
||||
movdqa 16*3(%rbp),%xmm11
|
||||
pand %xmm0,%xmm8
|
||||
movdqa 16*4(%rbp),%xmm12
|
||||
pand %xmm1,%xmm9
|
||||
movdqa 16*5(%rbp),%xmm13
|
||||
pand %xmm2,%xmm10
|
||||
movdqa 16*6(%rbp),%xmm14
|
||||
pand %xmm3,%xmm11
|
||||
movdqa 16*7(%rbp),%xmm15
|
||||
leaq 128(%rbp), %rbp
|
||||
pand %xmm4,%xmm12
|
||||
pand %xmm5,%xmm13
|
||||
pand %xmm6,%xmm14
|
||||
pand %xmm7,%xmm15
|
||||
por %xmm10,%xmm8
|
||||
por %xmm11,%xmm9
|
||||
por %xmm12,%xmm8
|
||||
por %xmm13,%xmm9
|
||||
por %xmm14,%xmm8
|
||||
por %xmm15,%xmm9
|
||||
|
||||
por %xmm9,%xmm8
|
||||
pshufd \$0x4e,%xmm8,%xmm9
|
||||
por %xmm9,%xmm8
|
||||
movq %xmm8,%rdx
|
||||
|
||||
.byte 0xc4,0x62,0xfb,0xf6,0x86,0x00,0x00,0x00,0x00 # mulx ($ap), %rax, %r8
|
||||
mulx ($ap), %rax, %r8
|
||||
adcx %rax, %rbx
|
||||
adox %r9, %r8
|
||||
|
||||
mulx 8($ap), %rax, %r9
|
||||
.byte 0x66,0x0f,0x6e,0xa5,0x00,0x00,0x00,0x00 # movd (%rbp), %xmm4
|
||||
adcx %rax, %r8
|
||||
adox %r10, %r9
|
||||
|
||||
mulx 16($ap), %rax, %r10
|
||||
movd 64(%rbp), %xmm5
|
||||
lea 128(%rbp), %rbp
|
||||
adcx %rax, %r9
|
||||
adox %r11, %r10
|
||||
|
||||
.byte 0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00 # mulx 24($ap), %rax, %r11
|
||||
pslldq \$4, %xmm5
|
||||
por %xmm5, %xmm4
|
||||
adcx %rax, %r10
|
||||
adox %r12, %r11
|
||||
|
||||
@@ -1260,10 +1163,10 @@ $code.=<<___ if ($addx);
|
||||
|
||||
.byte 0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00 # mulx 48($ap), %rax, %r14
|
||||
adcx %rax, %r13
|
||||
.byte 0x67
|
||||
adox %r15, %r14
|
||||
|
||||
mulx 56($ap), %rax, %r15
|
||||
movq %xmm4, %rdx
|
||||
mov %rbx, 64(%rsp,%rcx,8)
|
||||
adcx %rax, %r14
|
||||
adox %rdi, %r15
|
||||
@@ -1282,10 +1185,10 @@ $code.=<<___ if ($addx);
|
||||
mov %r14, 64+48(%rsp)
|
||||
mov %r15, 64+56(%rsp)
|
||||
|
||||
mov 128(%rsp), %rdx # pull arguments
|
||||
mov 128+8(%rsp), $out
|
||||
mov 128+16(%rsp), %rbp
|
||||
movq %xmm0, $out
|
||||
movq %xmm1, %rbp
|
||||
|
||||
mov 128(%rsp), %rdx # pull $n0
|
||||
mov (%rsp), %r8
|
||||
mov 8(%rsp), %r9
|
||||
mov 16(%rsp), %r10
|
||||
@@ -1313,21 +1216,6 @@ $code.=<<___;
|
||||
call __rsaz_512_subtract
|
||||
|
||||
leaq 128+24+48(%rsp), %rax
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0xa0-0xc8(%rax),%xmm6
|
||||
movaps 0xb0-0xc8(%rax),%xmm7
|
||||
movaps 0xc0-0xc8(%rax),%xmm8
|
||||
movaps 0xd0-0xc8(%rax),%xmm9
|
||||
movaps 0xe0-0xc8(%rax),%xmm10
|
||||
movaps 0xf0-0xc8(%rax),%xmm11
|
||||
movaps 0x100-0xc8(%rax),%xmm12
|
||||
movaps 0x110-0xc8(%rax),%xmm13
|
||||
movaps 0x120-0xc8(%rax),%xmm14
|
||||
movaps 0x130-0xc8(%rax),%xmm15
|
||||
lea 0xb0(%rax),%rax
|
||||
___
|
||||
$code.=<<___;
|
||||
movq -48(%rax), %r15
|
||||
movq -40(%rax), %r14
|
||||
movq -32(%rax), %r13
|
||||
@@ -1357,7 +1245,7 @@ rsaz_512_mul_scatter4:
|
||||
mov $pwr, $pwr
|
||||
subq \$128+24, %rsp
|
||||
.Lmul_scatter4_body:
|
||||
leaq ($tbl,$pwr,8), $tbl
|
||||
leaq ($tbl,$pwr,4), $tbl
|
||||
movq $out, %xmm0 # off-load arguments
|
||||
movq $mod, %xmm1
|
||||
movq $tbl, %xmm2
|
||||
@@ -1428,14 +1316,30 @@ $code.=<<___;
|
||||
|
||||
call __rsaz_512_subtract
|
||||
|
||||
movq %r8, 128*0($inp) # scatter
|
||||
movq %r9, 128*1($inp)
|
||||
movq %r10, 128*2($inp)
|
||||
movq %r11, 128*3($inp)
|
||||
movq %r12, 128*4($inp)
|
||||
movq %r13, 128*5($inp)
|
||||
movq %r14, 128*6($inp)
|
||||
movq %r15, 128*7($inp)
|
||||
movl %r8d, 64*0($inp) # scatter
|
||||
shrq \$32, %r8
|
||||
movl %r9d, 64*2($inp)
|
||||
shrq \$32, %r9
|
||||
movl %r10d, 64*4($inp)
|
||||
shrq \$32, %r10
|
||||
movl %r11d, 64*6($inp)
|
||||
shrq \$32, %r11
|
||||
movl %r12d, 64*8($inp)
|
||||
shrq \$32, %r12
|
||||
movl %r13d, 64*10($inp)
|
||||
shrq \$32, %r13
|
||||
movl %r14d, 64*12($inp)
|
||||
shrq \$32, %r14
|
||||
movl %r15d, 64*14($inp)
|
||||
shrq \$32, %r15
|
||||
movl %r8d, 64*1($inp)
|
||||
movl %r9d, 64*3($inp)
|
||||
movl %r10d, 64*5($inp)
|
||||
movl %r11d, 64*7($inp)
|
||||
movl %r12d, 64*9($inp)
|
||||
movl %r13d, 64*11($inp)
|
||||
movl %r14d, 64*13($inp)
|
||||
movl %r15d, 64*15($inp)
|
||||
|
||||
leaq 128+24+48(%rsp), %rax
|
||||
movq -48(%rax), %r15
|
||||
@@ -2039,14 +1943,16 @@ $code.=<<___;
|
||||
.type rsaz_512_scatter4,\@abi-omnipotent
|
||||
.align 16
|
||||
rsaz_512_scatter4:
|
||||
leaq ($out,$power,8), $out
|
||||
leaq ($out,$power,4), $out
|
||||
movl \$8, %r9d
|
||||
jmp .Loop_scatter
|
||||
.align 16
|
||||
.Loop_scatter:
|
||||
movq ($inp), %rax
|
||||
leaq 8($inp), $inp
|
||||
movq %rax, ($out)
|
||||
movl %eax, ($out)
|
||||
shrq \$32, %rax
|
||||
movl %eax, 64($out)
|
||||
leaq 128($out), $out
|
||||
decl %r9d
|
||||
jnz .Loop_scatter
|
||||
@@ -2057,106 +1963,22 @@ rsaz_512_scatter4:
|
||||
.type rsaz_512_gather4,\@abi-omnipotent
|
||||
.align 16
|
||||
rsaz_512_gather4:
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
.LSEH_begin_rsaz_512_gather4:
|
||||
.byte 0x48,0x81,0xec,0xa8,0x00,0x00,0x00 # sub $0xa8,%rsp
|
||||
.byte 0x0f,0x29,0x34,0x24 # movaps %xmm6,(%rsp)
|
||||
.byte 0x0f,0x29,0x7c,0x24,0x10 # movaps %xmm7,0x10(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0x44,0x24,0x20 # movaps %xmm8,0x20(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0x4c,0x24,0x30 # movaps %xmm9,0x30(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0x54,0x24,0x40 # movaps %xmm10,0x40(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0x5c,0x24,0x50 # movaps %xmm11,0x50(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0x64,0x24,0x60 # movaps %xmm12,0x60(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0x6c,0x24,0x70 # movaps %xmm13,0x70(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0xb4,0x24,0x80,0,0,0 # movaps %xmm14,0x80(%rsp)
|
||||
.byte 0x44,0x0f,0x29,0xbc,0x24,0x90,0,0,0 # movaps %xmm15,0x90(%rsp)
|
||||
___
|
||||
$code.=<<___;
|
||||
movd $power,%xmm8
|
||||
movdqa .Linc+16(%rip),%xmm1 # 00000002000000020000000200000002
|
||||
movdqa .Linc(%rip),%xmm0 # 00000001000000010000000000000000
|
||||
|
||||
pshufd \$0,%xmm8,%xmm8 # broadcast $power
|
||||
movdqa %xmm1,%xmm7
|
||||
movdqa %xmm1,%xmm2
|
||||
___
|
||||
########################################################################
|
||||
# calculate mask by comparing 0..15 to $power
|
||||
#
|
||||
for($i=0;$i<4;$i++) {
|
||||
$code.=<<___;
|
||||
paddd %xmm`$i`,%xmm`$i+1`
|
||||
pcmpeqd %xmm8,%xmm`$i`
|
||||
movdqa %xmm7,%xmm`$i+3`
|
||||
___
|
||||
}
|
||||
for(;$i<7;$i++) {
|
||||
$code.=<<___;
|
||||
paddd %xmm`$i`,%xmm`$i+1`
|
||||
pcmpeqd %xmm8,%xmm`$i`
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
pcmpeqd %xmm8,%xmm7
|
||||
leaq ($inp,$power,4), $inp
|
||||
movl \$8, %r9d
|
||||
jmp .Loop_gather
|
||||
.align 16
|
||||
.Loop_gather:
|
||||
movdqa 16*0($inp),%xmm8
|
||||
movdqa 16*1($inp),%xmm9
|
||||
movdqa 16*2($inp),%xmm10
|
||||
movdqa 16*3($inp),%xmm11
|
||||
pand %xmm0,%xmm8
|
||||
movdqa 16*4($inp),%xmm12
|
||||
pand %xmm1,%xmm9
|
||||
movdqa 16*5($inp),%xmm13
|
||||
pand %xmm2,%xmm10
|
||||
movdqa 16*6($inp),%xmm14
|
||||
pand %xmm3,%xmm11
|
||||
movdqa 16*7($inp),%xmm15
|
||||
movl ($inp), %eax
|
||||
movl 64($inp), %r8d
|
||||
leaq 128($inp), $inp
|
||||
pand %xmm4,%xmm12
|
||||
pand %xmm5,%xmm13
|
||||
pand %xmm6,%xmm14
|
||||
pand %xmm7,%xmm15
|
||||
por %xmm10,%xmm8
|
||||
por %xmm11,%xmm9
|
||||
por %xmm12,%xmm8
|
||||
por %xmm13,%xmm9
|
||||
por %xmm14,%xmm8
|
||||
por %xmm15,%xmm9
|
||||
|
||||
por %xmm9,%xmm8
|
||||
pshufd \$0x4e,%xmm8,%xmm9
|
||||
por %xmm9,%xmm8
|
||||
movq %xmm8,($out)
|
||||
shlq \$32, %r8
|
||||
or %r8, %rax
|
||||
movq %rax, ($out)
|
||||
leaq 8($out), $out
|
||||
decl %r9d
|
||||
jnz .Loop_gather
|
||||
___
|
||||
$code.=<<___ if ($win64);
|
||||
movaps 0x00(%rsp),%xmm6
|
||||
movaps 0x10(%rsp),%xmm7
|
||||
movaps 0x20(%rsp),%xmm8
|
||||
movaps 0x30(%rsp),%xmm9
|
||||
movaps 0x40(%rsp),%xmm10
|
||||
movaps 0x50(%rsp),%xmm11
|
||||
movaps 0x60(%rsp),%xmm12
|
||||
movaps 0x70(%rsp),%xmm13
|
||||
movaps 0x80(%rsp),%xmm14
|
||||
movaps 0x90(%rsp),%xmm15
|
||||
add \$0xa8,%rsp
|
||||
___
|
||||
$code.=<<___;
|
||||
ret
|
||||
.LSEH_end_rsaz_512_gather4:
|
||||
.size rsaz_512_gather4,.-rsaz_512_gather4
|
||||
|
||||
.align 64
|
||||
.Linc:
|
||||
.long 0,0, 1,1
|
||||
.long 2,2, 2,2
|
||||
___
|
||||
}
|
||||
|
||||
@@ -2204,18 +2026,6 @@ se_handler:
|
||||
|
||||
lea 128+24+48(%rax),%rax
|
||||
|
||||
lea .Lmul_gather4_epilogue(%rip),%rbx
|
||||
cmp %r10,%rbx
|
||||
jne .Lse_not_in_mul_gather4
|
||||
|
||||
lea 0xb0(%rax),%rax
|
||||
|
||||
lea -48-0xa8(%rax),%rsi
|
||||
lea 512($context),%rdi
|
||||
mov \$20,%ecx
|
||||
.long 0xa548f3fc # cld; rep movsq
|
||||
|
||||
.Lse_not_in_mul_gather4:
|
||||
mov -8(%rax),%rbx
|
||||
mov -16(%rax),%rbp
|
||||
mov -24(%rax),%r12
|
||||
@@ -2267,7 +2077,7 @@ se_handler:
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
ret
|
||||
.size se_handler,.-se_handler
|
||||
.size sqr_handler,.-sqr_handler
|
||||
|
||||
.section .pdata
|
||||
.align 4
|
||||
@@ -2291,10 +2101,6 @@ se_handler:
|
||||
.rva .LSEH_end_rsaz_512_mul_by_one
|
||||
.rva .LSEH_info_rsaz_512_mul_by_one
|
||||
|
||||
.rva .LSEH_begin_rsaz_512_gather4
|
||||
.rva .LSEH_end_rsaz_512_gather4
|
||||
.rva .LSEH_info_rsaz_512_gather4
|
||||
|
||||
.section .xdata
|
||||
.align 8
|
||||
.LSEH_info_rsaz_512_sqr:
|
||||
@@ -2317,19 +2123,6 @@ se_handler:
|
||||
.byte 9,0,0,0
|
||||
.rva se_handler
|
||||
.rva .Lmul_by_one_body,.Lmul_by_one_epilogue # HandlerData[]
|
||||
.LSEH_info_rsaz_512_gather4:
|
||||
.byte 0x01,0x46,0x16,0x00
|
||||
.byte 0x46,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
|
||||
.byte 0x3d,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
|
||||
.byte 0x34,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
|
||||
.byte 0x2e,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
|
||||
.byte 0x28,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
|
||||
.byte 0x22,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
|
||||
.byte 0x1c,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
|
||||
.byte 0x16,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
|
||||
.byte 0x10,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
|
||||
.byte 0x0b,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
|
||||
.byte 0x07,0x01,0x15,0x00 # sub rsp,0xa8
|
||||
___
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
/* x86_64 BIGNUM accelerator version 0.1, December 2002.
|
||||
*
|
||||
* Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
|
||||
@@ -50,13 +56,7 @@
|
||||
* machine.
|
||||
*/
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/* TODO(davidben): Get this file working on Windows x64. */
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
/* TODO(davidben): Get this file working on Windows x64. */
|
||||
|
||||
#undef mul
|
||||
#undef mul_add
|
||||
@@ -186,6 +186,14 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
}
|
||||
}
|
||||
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
BN_ULONG ret, waste;
|
||||
|
||||
asm("divq %4" : "=a"(ret), "=d"(waste) : "a"(l), "d"(h), "g"(d) : "cc");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int n) {
|
||||
BN_ULONG ret;
|
||||
@@ -212,6 +220,7 @@ BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
return ret & 1;
|
||||
}
|
||||
|
||||
#ifndef SIMICS
|
||||
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int n) {
|
||||
BN_ULONG ret;
|
||||
@@ -237,6 +246,65 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
|
||||
return ret & 1;
|
||||
}
|
||||
#else
|
||||
/* Simics 1.4<7 has buggy sbbq:-( */
|
||||
#define BN_MASK2 0xffffffffffffffffL
|
||||
BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
|
||||
BN_ULONG t1, t2;
|
||||
int c = 0;
|
||||
|
||||
if (n <= 0) {
|
||||
return (BN_ULONG)0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
t1 = a[0];
|
||||
t2 = b[0];
|
||||
r[0] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2) {
|
||||
c = (t1 < t2);
|
||||
}
|
||||
if (--n <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t1 = a[1];
|
||||
t2 = b[1];
|
||||
r[1] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2) {
|
||||
c = (t1 < t2);
|
||||
}
|
||||
if (--n <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t1 = a[2];
|
||||
t2 = b[2];
|
||||
r[2] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2) {
|
||||
c = (t1 < t2);
|
||||
}
|
||||
if (--n <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
t1 = a[3];
|
||||
t2 = b[3];
|
||||
r[3] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2) {
|
||||
c = (t1 < t2);
|
||||
}
|
||||
if (--n <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
a += 4;
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
|
||||
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
|
||||
@@ -528,4 +596,4 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
#endif /* !NO_ASM && X86_64 && __GNUC__ */
|
||||
#endif /* !NO_ASM && X86_64 && !WINDOWS */
|
||||
|
||||
Executable → Regular
+96
-133
@@ -761,126 +761,100 @@ bn_sqr8x_mont:
|
||||
# 4096. this is done to allow memory disambiguation logic
|
||||
# do its job.
|
||||
#
|
||||
lea -64(%rsp,$num,2),%r11
|
||||
lea -64(%rsp,$num,4),%r11
|
||||
mov ($n0),$n0 # *n0
|
||||
sub $aptr,%r11
|
||||
and \$4095,%r11
|
||||
cmp %r11,%r10
|
||||
jb .Lsqr8x_sp_alt
|
||||
sub %r11,%rsp # align with $aptr
|
||||
lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
|
||||
lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
|
||||
jmp .Lsqr8x_sp_done
|
||||
|
||||
.align 32
|
||||
.Lsqr8x_sp_alt:
|
||||
lea 4096-64(,$num,2),%r10 # 4096-frame-2*$num
|
||||
lea -64(%rsp,$num,2),%rsp # alloca(frame+2*$num)
|
||||
lea 4096-64(,$num,4),%r10 # 4096-frame-4*$num
|
||||
lea -64(%rsp,$num,4),%rsp # alloca(frame+4*$num)
|
||||
sub %r10,%r11
|
||||
mov \$0,%r10
|
||||
cmovc %r10,%r11
|
||||
sub %r11,%rsp
|
||||
.Lsqr8x_sp_done:
|
||||
and \$-64,%rsp
|
||||
mov $num,%r10
|
||||
mov $num,%r10
|
||||
neg $num
|
||||
|
||||
lea 64(%rsp,$num,2),%r11 # copy of modulus
|
||||
mov $n0, 32(%rsp)
|
||||
mov %rax, 40(%rsp) # save original %rsp
|
||||
.Lsqr8x_body:
|
||||
|
||||
movq $nptr, %xmm2 # save pointer to modulus
|
||||
mov $num,$i
|
||||
movq %r11, %xmm2 # save pointer to modulus copy
|
||||
shr \$3+2,$i
|
||||
mov OPENSSL_ia32cap_P+8(%rip),%eax
|
||||
jmp .Lsqr8x_copy_n
|
||||
|
||||
.align 32
|
||||
.Lsqr8x_copy_n:
|
||||
movq 8*0($nptr),%xmm0
|
||||
movq 8*1($nptr),%xmm1
|
||||
movq 8*2($nptr),%xmm3
|
||||
movq 8*3($nptr),%xmm4
|
||||
lea 8*4($nptr),$nptr
|
||||
movdqa %xmm0,16*0(%r11)
|
||||
movdqa %xmm1,16*1(%r11)
|
||||
movdqa %xmm3,16*2(%r11)
|
||||
movdqa %xmm4,16*3(%r11)
|
||||
lea 16*4(%r11),%r11
|
||||
dec $i
|
||||
jnz .Lsqr8x_copy_n
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
movq $rptr,%xmm1 # save $rptr
|
||||
movq %r10, %xmm3 # -$num
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
mov OPENSSL_ia32cap_P+8(%rip),%eax
|
||||
and \$0x80100,%eax
|
||||
cmp \$0x80100,%eax
|
||||
jne .Lsqr8x_nox
|
||||
|
||||
call bn_sqrx8x_internal # see x86_64-mont5 module
|
||||
# %rax top-most carry
|
||||
# %rbp nptr
|
||||
# %rcx -8*num
|
||||
# %r8 end of tp[2*num]
|
||||
lea (%r8,%rcx),%rbx
|
||||
mov %rcx,$num
|
||||
mov %rcx,%rdx
|
||||
movq %xmm1,$rptr
|
||||
sar \$3+2,%rcx # %cf=0
|
||||
jmp .Lsqr8x_sub
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
lea 48(%rsp),%rax
|
||||
lea 64(%rsp,$num,2),%rdx
|
||||
shr \$3+2,$num
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
jmp .Lsqr8x_zero
|
||||
|
||||
.align 32
|
||||
.Lsqr8x_nox:
|
||||
___
|
||||
$code.=<<___;
|
||||
call bn_sqr8x_internal # see x86_64-mont5 module
|
||||
# %rax top-most carry
|
||||
# %rbp nptr
|
||||
# %r8 -8*num
|
||||
# %rdi end of tp[2*num]
|
||||
lea (%rdi,$num),%rbx
|
||||
mov $num,%rcx
|
||||
mov $num,%rdx
|
||||
movq %xmm1,$rptr
|
||||
sar \$3+2,%rcx # %cf=0
|
||||
jmp .Lsqr8x_sub
|
||||
|
||||
.align 32
|
||||
.Lsqr8x_sub:
|
||||
mov 8*0(%rbx),%r12
|
||||
mov 8*1(%rbx),%r13
|
||||
mov 8*2(%rbx),%r14
|
||||
mov 8*3(%rbx),%r15
|
||||
lea 8*4(%rbx),%rbx
|
||||
sbb 8*0(%rbp),%r12
|
||||
sbb 8*1(%rbp),%r13
|
||||
sbb 8*2(%rbp),%r14
|
||||
sbb 8*3(%rbp),%r15
|
||||
lea 8*4(%rbp),%rbp
|
||||
mov %r12,8*0($rptr)
|
||||
mov %r13,8*1($rptr)
|
||||
mov %r14,8*2($rptr)
|
||||
mov %r15,8*3($rptr)
|
||||
lea 8*4($rptr),$rptr
|
||||
inc %rcx # preserves %cf
|
||||
jnz .Lsqr8x_sub
|
||||
|
||||
sbb \$0,%rax # top-most carry
|
||||
lea (%rbx,$num),%rbx # rewind
|
||||
lea ($rptr,$num),$rptr # rewind
|
||||
|
||||
movq %rax,%xmm1
|
||||
pxor %xmm0,%xmm0
|
||||
pshufd \$0,%xmm1,%xmm1
|
||||
lea 48(%rsp),%rax
|
||||
lea 64(%rsp,$num,2),%rdx
|
||||
shr \$3+2,$num
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
jmp .Lsqr8x_cond_copy
|
||||
jmp .Lsqr8x_zero
|
||||
|
||||
.align 32
|
||||
.Lsqr8x_cond_copy:
|
||||
movdqa 16*0(%rbx),%xmm2
|
||||
movdqa 16*1(%rbx),%xmm3
|
||||
lea 16*2(%rbx),%rbx
|
||||
movdqu 16*0($rptr),%xmm4
|
||||
movdqu 16*1($rptr),%xmm5
|
||||
lea 16*2($rptr),$rptr
|
||||
movdqa %xmm0,-16*2(%rbx) # zero tp
|
||||
movdqa %xmm0,-16*1(%rbx)
|
||||
movdqa %xmm0,-16*2(%rbx,%rdx)
|
||||
movdqa %xmm0,-16*1(%rbx,%rdx)
|
||||
pcmpeqd %xmm1,%xmm0
|
||||
pand %xmm1,%xmm2
|
||||
pand %xmm1,%xmm3
|
||||
pand %xmm0,%xmm4
|
||||
pand %xmm0,%xmm5
|
||||
pxor %xmm0,%xmm0
|
||||
por %xmm2,%xmm4
|
||||
por %xmm3,%xmm5
|
||||
movdqu %xmm4,-16*2($rptr)
|
||||
movdqu %xmm5,-16*1($rptr)
|
||||
add \$32,$num
|
||||
jnz .Lsqr8x_cond_copy
|
||||
.Lsqr8x_zero:
|
||||
movdqa %xmm0,16*0(%rax) # wipe t
|
||||
movdqa %xmm0,16*1(%rax)
|
||||
movdqa %xmm0,16*2(%rax)
|
||||
movdqa %xmm0,16*3(%rax)
|
||||
lea 16*4(%rax),%rax
|
||||
movdqa %xmm0,16*0(%rdx) # wipe n
|
||||
movdqa %xmm0,16*1(%rdx)
|
||||
movdqa %xmm0,16*2(%rdx)
|
||||
movdqa %xmm0,16*3(%rdx)
|
||||
lea 16*4(%rdx),%rdx
|
||||
dec $num
|
||||
jnz .Lsqr8x_zero
|
||||
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
@@ -1147,75 +1121,64 @@ $code.=<<___;
|
||||
adc $zero,%r15 # modulo-scheduled
|
||||
sub 0*8($tptr),$zero # pull top-most carry
|
||||
adc %r15,%r14
|
||||
mov -8($nptr),$mi
|
||||
sbb %r15,%r15 # top-most carry
|
||||
mov %r14,-1*8($tptr)
|
||||
|
||||
cmp 16(%rsp),$bptr
|
||||
jne .Lmulx4x_outer
|
||||
|
||||
lea 64(%rsp),$tptr
|
||||
sub $num,$nptr # rewind $nptr
|
||||
neg %r15
|
||||
mov $num,%rdx
|
||||
shr \$3+2,$num # %cf=0
|
||||
sub %r14,$mi # compare top-most words
|
||||
sbb $mi,$mi
|
||||
or $mi,%r15
|
||||
|
||||
neg $num
|
||||
xor %rdx,%rdx
|
||||
mov 32(%rsp),$rptr # restore rp
|
||||
jmp .Lmulx4x_sub
|
||||
lea 64(%rsp),$tptr
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
mov 0*8($nptr,$num),%r8
|
||||
mov 1*8($nptr,$num),%r9
|
||||
neg %r8
|
||||
jmp .Lmulx4x_sub_entry
|
||||
|
||||
.align 32
|
||||
.Lmulx4x_sub:
|
||||
mov 8*0($tptr),%r11
|
||||
mov 8*1($tptr),%r12
|
||||
mov 8*2($tptr),%r13
|
||||
mov 8*3($tptr),%r14
|
||||
lea 8*4($tptr),$tptr
|
||||
sbb 8*0($nptr),%r11
|
||||
sbb 8*1($nptr),%r12
|
||||
sbb 8*2($nptr),%r13
|
||||
sbb 8*3($nptr),%r14
|
||||
lea 8*4($nptr),$nptr
|
||||
mov %r11,8*0($rptr)
|
||||
mov %r12,8*1($rptr)
|
||||
mov %r13,8*2($rptr)
|
||||
mov %r14,8*3($rptr)
|
||||
lea 8*4($rptr),$rptr
|
||||
dec $num # preserves %cf
|
||||
mov 0*8($nptr,$num),%r8
|
||||
mov 1*8($nptr,$num),%r9
|
||||
not %r8
|
||||
.Lmulx4x_sub_entry:
|
||||
mov 2*8($nptr,$num),%r10
|
||||
not %r9
|
||||
and %r15,%r8
|
||||
mov 3*8($nptr,$num),%r11
|
||||
not %r10
|
||||
and %r15,%r9
|
||||
not %r11
|
||||
and %r15,%r10
|
||||
and %r15,%r11
|
||||
|
||||
neg %rdx # mov %rdx,%cf
|
||||
adc 0*8($tptr),%r8
|
||||
adc 1*8($tptr),%r9
|
||||
movdqa %xmm0,($tptr)
|
||||
adc 2*8($tptr),%r10
|
||||
adc 3*8($tptr),%r11
|
||||
movdqa %xmm0,16($tptr)
|
||||
lea 4*8($tptr),$tptr
|
||||
sbb %rdx,%rdx # mov %cf,%rdx
|
||||
|
||||
mov %r8,0*8($rptr)
|
||||
mov %r9,1*8($rptr)
|
||||
mov %r10,2*8($rptr)
|
||||
mov %r11,3*8($rptr)
|
||||
lea 4*8($rptr),$rptr
|
||||
|
||||
add \$32,$num
|
||||
jnz .Lmulx4x_sub
|
||||
|
||||
sbb \$0,%r15 # top-most carry
|
||||
lea 64(%rsp),$tptr
|
||||
sub %rdx,$rptr # rewind
|
||||
|
||||
movq %r15,%xmm1
|
||||
pxor %xmm0,%xmm0
|
||||
pshufd \$0,%xmm1,%xmm1
|
||||
mov 40(%rsp),%rsi # restore %rsp
|
||||
jmp .Lmulx4x_cond_copy
|
||||
|
||||
.align 32
|
||||
.Lmulx4x_cond_copy:
|
||||
movdqa 16*0($tptr),%xmm2
|
||||
movdqa 16*1($tptr),%xmm3
|
||||
lea 16*2($tptr),$tptr
|
||||
movdqu 16*0($rptr),%xmm4
|
||||
movdqu 16*1($rptr),%xmm5
|
||||
lea 16*2($rptr),$rptr
|
||||
movdqa %xmm0,-16*2($tptr) # zero tp
|
||||
movdqa %xmm0,-16*1($tptr)
|
||||
pcmpeqd %xmm1,%xmm0
|
||||
pand %xmm1,%xmm2
|
||||
pand %xmm1,%xmm3
|
||||
pand %xmm0,%xmm4
|
||||
pand %xmm0,%xmm5
|
||||
pxor %xmm0,%xmm0
|
||||
por %xmm2,%xmm4
|
||||
por %xmm3,%xmm5
|
||||
movdqu %xmm4,-16*2($rptr)
|
||||
movdqu %xmm5,-16*1($rptr)
|
||||
sub \$32,%rdx
|
||||
jnz .Lmulx4x_cond_copy
|
||||
|
||||
mov %rdx,($tptr)
|
||||
|
||||
mov \$1,%rax
|
||||
mov -48(%rsi),%r15
|
||||
mov -40(%rsi),%r14
|
||||
|
||||
Executable → Regular
+554
-716
File diff suppressed because it is too large
Load Diff
+1
-13
@@ -266,18 +266,6 @@ int BN_set_word(BIGNUM *bn, BN_ULONG value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
|
||||
if (bn_wexpand(bn, num) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
bn->neg = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_is_negative(const BIGNUM *bn) {
|
||||
return bn->neg != 0;
|
||||
}
|
||||
@@ -307,7 +295,7 @@ BIGNUM *bn_wexpand(BIGNUM *bn, size_t words) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a = OPENSSL_malloc(sizeof(BN_ULONG) * words);
|
||||
a = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * words);
|
||||
if (a == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
|
||||
+22
-9
@@ -18,7 +18,7 @@
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
@@ -42,7 +42,7 @@ int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
@@ -58,7 +58,7 @@ int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) {
|
||||
/* Negative numbers are unsupported. */
|
||||
if (BN_is_negative(bn)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
@@ -66,15 +66,28 @@ int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
}
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
|
||||
/* The number must be padded with a leading zero if the high bit would
|
||||
* otherwise be set or if |bn| is zero. */
|
||||
(BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
|
||||
!BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
|
||||
!CBB_flush(cbb)) {
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The number must be padded with a leading zero if the high bit would
|
||||
* otherwise be set (or |bn| is zero). */
|
||||
if (BN_num_bits(bn) % 8 == 0 &&
|
||||
!CBB_add_u8(&child, 0x00)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *out;
|
||||
if (!CBB_add_space(&child, &out, BN_num_bytes(bn))) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
BN_bn2bin(bn, out);
|
||||
if (!CBB_flush(cbb)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+27
-27
@@ -1316,23 +1316,23 @@ static bool test_exp(FILE *fp, BN_CTX *ctx) {
|
||||
|
||||
// test_exp_mod_zero tests that 1**0 mod 1 == 0.
|
||||
static bool test_exp_mod_zero(void) {
|
||||
ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new());
|
||||
if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) {
|
||||
ScopedBIGNUM zero(BN_new());
|
||||
if (!zero) {
|
||||
return false;
|
||||
}
|
||||
BN_zero(zero.get());
|
||||
|
||||
if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) ||
|
||||
!BN_is_zero(r.get()) ||
|
||||
!BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr,
|
||||
nullptr) ||
|
||||
!BN_is_zero(r.get()) ||
|
||||
!BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(),
|
||||
nullptr, nullptr) ||
|
||||
!BN_is_zero(r.get()) ||
|
||||
!BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr,
|
||||
nullptr) ||
|
||||
!BN_is_zero(r.get())) {
|
||||
ScopedBN_CTX ctx(BN_CTX_new());
|
||||
ScopedBIGNUM r(BN_new());
|
||||
if (!ctx || !r ||
|
||||
!BN_mod_exp(r.get(), BN_value_one(), zero.get(), BN_value_one(), ctx.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BN_is_zero(r.get())) {
|
||||
fprintf(stderr, "1**0 mod 1 = ");
|
||||
BN_print_fp(stderr, r.get());
|
||||
fprintf(stderr, ", should be 0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1799,8 +1799,8 @@ static const ASN1InvalidTest kASN1InvalidTests[] = {
|
||||
{"\x02\x00", 2},
|
||||
};
|
||||
|
||||
// kASN1BuggyTests contains incorrect encodings and the corresponding, expected
|
||||
// results of |BN_parse_asn1_unsigned_buggy| given that input.
|
||||
// kASN1BuggyTests are incorrect encodings and how |BN_cbs2unsigned_buggy|
|
||||
// should interpret them.
|
||||
static const ASN1Test kASN1BuggyTests[] = {
|
||||
// Negative numbers.
|
||||
{"128", "\x02\x01\x80", 3},
|
||||
@@ -1823,7 +1823,7 @@ static bool test_asn1() {
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (!BN_parse_asn1_unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
if (!BN_cbs2unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1838,7 +1838,7 @@ static bool test_asn1() {
|
||||
size_t der_len;
|
||||
CBB_zero(&cbb);
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
!BN_marshal_asn1(&cbb, bn.get()) ||
|
||||
!BN_bn2cbb(&cbb, bn.get()) ||
|
||||
!CBB_finish(&cbb, &der, &der_len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return false;
|
||||
@@ -1850,9 +1850,9 @@ static bool test_asn1() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// |BN_parse_asn1_unsigned_buggy| parses all valid input.
|
||||
// |BN_cbs2unsigned_buggy| parses all valid input.
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (!BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
if (!BN_cbs2unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1869,16 +1869,16 @@ static bool test_asn1() {
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
|
||||
if (BN_cbs2unsigned(&cbs, bn.get())) {
|
||||
fprintf(stderr, "Parsed invalid input.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// All tests in kASN1InvalidTests are also rejected by
|
||||
// |BN_parse_asn1_unsigned_buggy|.
|
||||
// |BN_cbs2unsigned_buggy|.
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (BN_parse_asn1_unsigned_buggy(&cbs, bn.get())) {
|
||||
if (BN_cbs2unsigned_buggy(&cbs, bn.get())) {
|
||||
fprintf(stderr, "Parsed invalid input.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1886,7 +1886,7 @@ static bool test_asn1() {
|
||||
}
|
||||
|
||||
for (const ASN1Test &test : kASN1BuggyTests) {
|
||||
// These broken encodings are rejected by |BN_parse_asn1_unsigned|.
|
||||
// These broken encodings are rejected by |BN_cbs2unsigned|.
|
||||
ScopedBIGNUM bn(BN_new());
|
||||
if (!bn) {
|
||||
return false;
|
||||
@@ -1894,20 +1894,20 @@ static bool test_asn1() {
|
||||
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
|
||||
if (BN_cbs2unsigned(&cbs, bn.get())) {
|
||||
fprintf(stderr, "Parsed invalid input.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// However |BN_parse_asn1_unsigned_buggy| accepts them.
|
||||
// However |BN_cbs2unsigned_buggy| accepts them.
|
||||
ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii);
|
||||
if (!bn2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (!BN_parse_asn1_unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
|
||||
if (!BN_cbs2unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
|
||||
fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1926,7 +1926,7 @@ static bool test_asn1() {
|
||||
CBB cbb;
|
||||
CBB_zero(&cbb);
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
BN_marshal_asn1(&cbb, bn.get())) {
|
||||
BN_bn2cbb(&cbb, bn.get())) {
|
||||
fprintf(stderr, "Serialized negative number.\n");
|
||||
CBB_cleanup(&cbb);
|
||||
return false;
|
||||
|
||||
+4
-9
@@ -63,7 +63,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -196,11 +195,6 @@ int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
|
||||
uint8_t *ptr;
|
||||
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
|
||||
}
|
||||
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
|
||||
char *BN_bn2hex(const BIGNUM *bn) {
|
||||
@@ -208,7 +202,7 @@ char *BN_bn2hex(const BIGNUM *bn) {
|
||||
char *buf;
|
||||
char *p;
|
||||
|
||||
buf = OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
|
||||
buf = (char *)OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
@@ -385,8 +379,9 @@ char *BN_bn2dec(const BIGNUM *a) {
|
||||
*/
|
||||
i = BN_num_bits(a) * 3;
|
||||
num = i / 10 + i / 1000 + 1 + 1;
|
||||
bn_data = OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
|
||||
buf = OPENSSL_malloc(num + 3);
|
||||
bn_data =
|
||||
(BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
|
||||
buf = (char *)OPENSSL_malloc(num + 3);
|
||||
if ((buf == NULL) || (bn_data == NULL)) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
|
||||
+89
-121
@@ -56,126 +56,55 @@
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#if !defined(BN_ULLONG)
|
||||
/* bn_div_words divides a double-width |h|,|l| by |d| and returns the result,
|
||||
* which must fit in a |BN_ULONG|. */
|
||||
static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
BN_ULONG dh, dl, q, ret = 0, th, tl, t;
|
||||
int i, count = 2;
|
||||
#define asm __asm__
|
||||
|
||||
if (d == 0) {
|
||||
return BN_MASK2;
|
||||
}
|
||||
|
||||
i = BN_num_bits_word(d);
|
||||
assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
|
||||
|
||||
i = BN_BITS2 - i;
|
||||
if (h >= d) {
|
||||
h -= d;
|
||||
}
|
||||
|
||||
if (i) {
|
||||
d <<= i;
|
||||
h = (h << i) | (l >> (BN_BITS2 - i));
|
||||
l <<= i;
|
||||
}
|
||||
dh = (d & BN_MASK2h) >> BN_BITS4;
|
||||
dl = (d & BN_MASK2l);
|
||||
for (;;) {
|
||||
if ((h >> BN_BITS4) == dh) {
|
||||
q = BN_MASK2l;
|
||||
} else {
|
||||
q = h / dh;
|
||||
}
|
||||
|
||||
th = q * dh;
|
||||
tl = dl * q;
|
||||
for (;;) {
|
||||
t = h - th;
|
||||
if ((t & BN_MASK2h) ||
|
||||
((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
|
||||
break;
|
||||
}
|
||||
q--;
|
||||
th -= dh;
|
||||
tl -= dl;
|
||||
}
|
||||
t = (tl >> BN_BITS4);
|
||||
tl = (tl << BN_BITS4) & BN_MASK2h;
|
||||
th += t;
|
||||
|
||||
if (l < tl) {
|
||||
th++;
|
||||
}
|
||||
l -= tl;
|
||||
if (h < th) {
|
||||
h += d;
|
||||
q--;
|
||||
}
|
||||
h -= th;
|
||||
|
||||
if (--count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = q << BN_BITS4;
|
||||
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
|
||||
l = (l & BN_MASK2l) << BN_BITS4;
|
||||
}
|
||||
|
||||
ret |= q;
|
||||
return ret;
|
||||
}
|
||||
#endif /* !defined(BN_ULLONG) */
|
||||
|
||||
static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
|
||||
BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) {
|
||||
/* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when
|
||||
* the |BN_ULLONG|-based C code is used.
|
||||
*
|
||||
* GCC bugs:
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668
|
||||
*
|
||||
* Clang bugs:
|
||||
* * https://llvm.org/bugs/show_bug.cgi?id=6397
|
||||
* * https://llvm.org/bugs/show_bug.cgi?id=12418
|
||||
*
|
||||
* These issues aren't specific to x86 and x86_64, so it might be worthwhile
|
||||
* to add more assembly language implementations. */
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__)
|
||||
__asm__ volatile (
|
||||
"divl %4"
|
||||
: "=a"(*quotient_out), "=d"(*rem_out)
|
||||
: "a"(n1), "d"(n0), "g"(d0)
|
||||
: "cc" );
|
||||
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
|
||||
__asm__ volatile (
|
||||
"divq %4"
|
||||
: "=a"(*quotient_out), "=d"(*rem_out)
|
||||
: "a"(n1), "d"(n0), "g"(d0)
|
||||
: "cc" );
|
||||
#else
|
||||
#if defined(BN_ULLONG)
|
||||
BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
|
||||
*quotient_out = (BN_ULONG)(n / d0);
|
||||
#else
|
||||
*quotient_out = bn_div_words(n0, n1, d0);
|
||||
#endif
|
||||
*rem_out = n1 - (*quotient_out * d0);
|
||||
#endif
|
||||
}
|
||||
#if !defined(OPENSSL_NO_ASM)
|
||||
# if defined(__GNUC__) && __GNUC__>=2
|
||||
# if defined(OPENSSL_X86)
|
||||
/*
|
||||
* There were two reasons for implementing this template:
|
||||
* - GNU C generates a call to a function (__udivdi3 to be exact)
|
||||
* in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
|
||||
* understand why...);
|
||||
* - divl doesn't only calculate quotient, but also leaves
|
||||
* remainder in %edx which we can definitely use here:-)
|
||||
*
|
||||
* <appro@fy.chalmers.se>
|
||||
*/
|
||||
#undef div_asm
|
||||
# define div_asm(n0,n1,d0) \
|
||||
({ asm volatile ( \
|
||||
"divl %4" \
|
||||
: "=a"(q), "=d"(rem) \
|
||||
: "a"(n1), "d"(n0), "g"(d0) \
|
||||
: "cc"); \
|
||||
q; \
|
||||
})
|
||||
# define REMAINDER_IS_ALREADY_CALCULATED
|
||||
# elif defined(OPENSSL_X86_64)
|
||||
/*
|
||||
* Same story here, but it's 128-bit by 64-bit division. Wow!
|
||||
* <appro@fy.chalmers.se>
|
||||
*/
|
||||
# undef div_asm
|
||||
# define div_asm(n0,n1,d0) \
|
||||
({ asm volatile ( \
|
||||
"divq %4" \
|
||||
: "=a"(q), "=d"(rem) \
|
||||
: "a"(n1), "d"(n0), "g"(d0) \
|
||||
: "cc"); \
|
||||
q; \
|
||||
})
|
||||
# define REMAINDER_IS_ALREADY_CALCULATED
|
||||
# endif /* __<cpu> */
|
||||
# endif /* __GNUC__ */
|
||||
#endif /* OPENSSL_NO_ASM */
|
||||
|
||||
/* BN_div computes dv := num / divisor, rounding towards
|
||||
* zero, and sets up rm such that dv*divisor + rm = num holds.
|
||||
@@ -331,10 +260,23 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
q = BN_MASK2;
|
||||
} else {
|
||||
/* n0 < d0 */
|
||||
bn_div_rem_words(&q, &rem, n0, n1, d0);
|
||||
|
||||
#ifdef BN_ULLONG
|
||||
BN_ULLONG t2 = (BN_ULLONG)d1 * q;
|
||||
BN_ULLONG t2;
|
||||
|
||||
#if defined(BN_ULLONG) && !defined(div_asm)
|
||||
q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
|
||||
#else
|
||||
q = div_asm(n0, n1, d0);
|
||||
#endif
|
||||
|
||||
#ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
/* rem doesn't have to be BN_ULLONG. The least we know it's less that d0,
|
||||
* isn't it? */
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
#endif
|
||||
|
||||
t2 = (BN_ULLONG)d1 * q;
|
||||
|
||||
for (;;) {
|
||||
if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
|
||||
break;
|
||||
@@ -348,7 +290,33 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
}
|
||||
#else /* !BN_ULLONG */
|
||||
BN_ULONG t2l, t2h;
|
||||
|
||||
#if defined(div_asm)
|
||||
q = div_asm(n0, n1, d0);
|
||||
#else
|
||||
q = bn_div_words(n0, n1, d0);
|
||||
#endif
|
||||
|
||||
#ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
#endif
|
||||
|
||||
#if defined(BN_UMULT_LOHI)
|
||||
BN_UMULT_LOHI(t2l, t2h, d1, q);
|
||||
#elif defined(BN_UMULT_HIGH)
|
||||
t2l = d1 * q;
|
||||
t2h = BN_UMULT_HIGH(d1, q);
|
||||
#else
|
||||
{
|
||||
BN_ULONG ql, qh;
|
||||
t2l = LBITS(d1);
|
||||
t2h = HBITS(d1);
|
||||
ql = LBITS(q);
|
||||
qh = HBITS(q);
|
||||
mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
|
||||
break;
|
||||
@@ -608,7 +576,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* normalize input for |bn_div_rem_words|. */
|
||||
/* normalize input (so bn_div_words doesn't complain) */
|
||||
j = BN_BITS2 - BN_num_bits_word(w);
|
||||
w <<= j;
|
||||
if (!BN_lshift(a, a, j)) {
|
||||
@@ -616,10 +584,10 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
|
||||
}
|
||||
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
BN_ULONG l = a->d[i];
|
||||
BN_ULONG d;
|
||||
BN_ULONG unused_rem;
|
||||
bn_div_rem_words(&d, &unused_rem, ret, l, w);
|
||||
BN_ULONG l, d;
|
||||
|
||||
l = a->d[i];
|
||||
d = bn_div_words(ret, l, w);
|
||||
ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
|
||||
a->d[i] = d;
|
||||
}
|
||||
|
||||
+48
-86
@@ -209,7 +209,6 @@ static void BN_RECP_CTX_init(BN_RECP_CTX *recp) {
|
||||
BN_init(&recp->N);
|
||||
BN_init(&recp->Nr);
|
||||
recp->num_bits = 0;
|
||||
recp->shift = 0;
|
||||
recp->flags = 0;
|
||||
}
|
||||
|
||||
@@ -446,12 +445,8 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
bits = BN_num_bits(p);
|
||||
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(r);
|
||||
ret = BN_one(r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
@@ -637,12 +632,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
bits = BN_num_bits(p);
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(rr);
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
@@ -788,65 +779,29 @@ err:
|
||||
* pattern as far as cache lines are concerned. The following functions are
|
||||
* used to transfer a BIGNUM from/to that table. */
|
||||
static int copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx,
|
||||
int window) {
|
||||
int i, j;
|
||||
const int width = 1 << window;
|
||||
BN_ULONG *table = (BN_ULONG *) buf;
|
||||
int width) {
|
||||
size_t i, j;
|
||||
|
||||
if (top > b->top) {
|
||||
top = b->top; /* this works because 'buf' is explicitly zeroed */
|
||||
}
|
||||
|
||||
for (i = 0, j = idx; i < top; i++, j += width) {
|
||||
table[j] = b->d[i];
|
||||
for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
|
||||
buf[j] = ((unsigned char *)b->d)[i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
|
||||
int window) {
|
||||
int i, j;
|
||||
const int width = 1 << window;
|
||||
volatile BN_ULONG *table = (volatile BN_ULONG *)buf;
|
||||
int width) {
|
||||
size_t i, j;
|
||||
|
||||
if (bn_wexpand(b, top) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (window <= 3) {
|
||||
for (i = 0; i < top; i++, table += width) {
|
||||
BN_ULONG acc = 0;
|
||||
|
||||
for (j = 0; j < width; j++) {
|
||||
acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
|
||||
}
|
||||
|
||||
b->d[i] = acc;
|
||||
}
|
||||
} else {
|
||||
int xstride = 1 << (window - 2);
|
||||
BN_ULONG y0, y1, y2, y3;
|
||||
|
||||
i = idx >> (window - 2); /* equivalent of idx / xstride */
|
||||
idx &= xstride - 1; /* equivalent of idx % xstride */
|
||||
|
||||
y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1);
|
||||
y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1);
|
||||
y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1);
|
||||
y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1);
|
||||
|
||||
for (i = 0; i < top; i++, table += width) {
|
||||
BN_ULONG acc = 0;
|
||||
|
||||
for (j = 0; j < xstride; j++) {
|
||||
acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) |
|
||||
(table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) &
|
||||
((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
|
||||
}
|
||||
|
||||
b->d[i] = acc;
|
||||
}
|
||||
for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
|
||||
((unsigned char *)b->d)[i] = buf[j];
|
||||
}
|
||||
|
||||
b->top = top;
|
||||
@@ -920,14 +875,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
|
||||
bits = BN_num_bits(p);
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(rr);
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
/* Allocate a montgomery context if it was not supplied by the caller. */
|
||||
if (mont == NULL) {
|
||||
new_mont = BN_MONT_CTX_new();
|
||||
@@ -970,8 +923,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
#if defined(OPENSSL_BN_ASM_MONT5)
|
||||
if (window >= 5) {
|
||||
window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */
|
||||
/* reserve space for mont->N.d[] copy */
|
||||
powerbufLen += top * sizeof(mont->N.d[0]);
|
||||
if ((top & 7) == 0) {
|
||||
powerbufLen += 2 * top * sizeof(m->d[0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -988,7 +942,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if ((powerbufFree = OPENSSL_malloc(
|
||||
if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
|
||||
powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
@@ -1042,8 +996,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
/* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
|
||||
* 512-bit RSA is hardly relevant, we omit it to spare size... */
|
||||
if (window == 5 && top > 1) {
|
||||
const BN_ULONG *n0 = mont->n0;
|
||||
BN_ULONG *np;
|
||||
const BN_ULONG *np = mont->N.d, *n0 = mont->n0, *np2;
|
||||
|
||||
/* BN_to_montgomery can contaminate words above .top
|
||||
* [in BN_DEBUG[_DEBUG] build]... */
|
||||
@@ -1054,9 +1007,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
tmp.d[i] = 0;
|
||||
}
|
||||
|
||||
/* copy mont->N.d[] to improve cache locality */
|
||||
for (np = am.d + top, i = 0; i < top; i++) {
|
||||
np[i] = mont->N.d[i];
|
||||
if (top & 7) {
|
||||
np2 = np;
|
||||
} else {
|
||||
BN_ULONG *np_double = am.d + top;
|
||||
for (i = 0; i < top; i++) {
|
||||
np_double[2 * i] = np[i];
|
||||
}
|
||||
np2 = np_double;
|
||||
}
|
||||
|
||||
bn_scatter5(tmp.d, top, powerbuf, 0);
|
||||
@@ -1071,7 +1029,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
for (i = 3; i < 8; i += 2) {
|
||||
int j;
|
||||
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
|
||||
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
|
||||
bn_scatter5(tmp.d, top, powerbuf, i);
|
||||
for (j = 2 * i; j < 32; j *= 2) {
|
||||
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
|
||||
@@ -1079,13 +1037,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
}
|
||||
for (; i < 16; i += 2) {
|
||||
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
|
||||
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
|
||||
bn_scatter5(tmp.d, top, powerbuf, i);
|
||||
bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
|
||||
bn_scatter5(tmp.d, top, powerbuf, 2 * i);
|
||||
}
|
||||
for (; i < 32; i += 2) {
|
||||
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
|
||||
bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
|
||||
bn_scatter5(tmp.d, top, powerbuf, i);
|
||||
}
|
||||
|
||||
@@ -1133,7 +1091,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
wvalue >>= (bits - 4) & 7;
|
||||
wvalue &= 0x1f;
|
||||
bits -= 5;
|
||||
bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
|
||||
bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
|
||||
}
|
||||
while (bits >= 0) {
|
||||
/* Read five bits from |bits-4| through |bits|, inclusive. */
|
||||
@@ -1142,11 +1100,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
wvalue >>= first_bit & 7;
|
||||
wvalue &= 0x1f;
|
||||
bits -= 5;
|
||||
bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
|
||||
bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
|
||||
}
|
||||
}
|
||||
|
||||
ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
|
||||
ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np2, n0, top);
|
||||
tmp.top = top;
|
||||
bn_correct_top(&tmp);
|
||||
if (ret) {
|
||||
@@ -1158,8 +1116,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!copy_to_prebuf(&tmp, top, powerbuf, 0, window) ||
|
||||
!copy_to_prebuf(&am, top, powerbuf, 1, window)) {
|
||||
if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers) ||
|
||||
!copy_to_prebuf(&am, top, powerbuf, 1, numPowers)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1170,13 +1128,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
*/
|
||||
if (window > 1) {
|
||||
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) ||
|
||||
!copy_to_prebuf(&tmp, top, powerbuf, 2, window)) {
|
||||
!copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers)) {
|
||||
goto err;
|
||||
}
|
||||
for (i = 3; i < numPowers; i++) {
|
||||
/* Calculate a^i = a^(i-1) * a */
|
||||
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) ||
|
||||
!copy_to_prebuf(&tmp, top, powerbuf, i, window)) {
|
||||
!copy_to_prebuf(&tmp, top, powerbuf, i, numPowers)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -1186,7 +1144,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) {
|
||||
wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
|
||||
}
|
||||
if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, window)) {
|
||||
if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1205,7 +1163,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
|
||||
/* Fetch the appropriate pre-computed value from the pre-buf */
|
||||
if (!copy_from_prebuf(&am, top, powerbuf, wvalue, window)) {
|
||||
if (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1228,6 +1186,7 @@ err:
|
||||
OPENSSL_cleanse(powerbuf, powerbufLen);
|
||||
OPENSSL_free(powerbufFree);
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -1271,14 +1230,17 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
ret = 1;
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
} else {
|
||||
ret = BN_one(rr);
|
||||
}
|
||||
return BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
if (a == 0) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
+322
-6
@@ -61,10 +61,13 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
/* This file has two other implementations: x86 assembly language in
|
||||
* asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */
|
||||
/* Generic implementations of most operations are needed for:
|
||||
* - Configurations without inline assembly.
|
||||
* - Architectures other than x86 or x86_64.
|
||||
* - Windows x84_64; x86_64-gcc.c does not build on MSVC. */
|
||||
#if defined(OPENSSL_NO_ASM) || \
|
||||
!(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
|
||||
(!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || \
|
||||
(defined(OPENSSL_X86_64) && defined(OPENSSL_WINDOWS))
|
||||
|
||||
#ifdef BN_ULLONG
|
||||
#define mul_add(r, a, w, c) \
|
||||
@@ -91,8 +94,7 @@
|
||||
(r1) = Hw(t); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#elif defined(BN_UMULT_LOHI)
|
||||
#define mul_add(r, a, w, c) \
|
||||
{ \
|
||||
BN_ULONG high, low, ret, tmp = (a); \
|
||||
@@ -122,8 +124,102 @@
|
||||
BN_UMULT_LOHI(r0, r1, tmp, tmp); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*************************************************************
|
||||
* No long long type
|
||||
*/
|
||||
|
||||
#define LBITS(a) ((a) & BN_MASK2l)
|
||||
#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
|
||||
#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
|
||||
|
||||
#define LLBITS(a) ((a) & BN_MASKl)
|
||||
#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
|
||||
#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
|
||||
|
||||
#define mul64(l, h, bl, bh) \
|
||||
{ \
|
||||
BN_ULONG m, m1, lt, ht; \
|
||||
\
|
||||
lt = l; \
|
||||
ht = h; \
|
||||
m = (bh) * (lt); \
|
||||
lt = (bl) * (lt); \
|
||||
m1 = (bl) * (ht); \
|
||||
ht = (bh) * (ht); \
|
||||
m = (m + m1) & BN_MASK2; \
|
||||
if (m < m1) \
|
||||
ht += L2HBITS((BN_ULONG)1); \
|
||||
ht += HBITS(m); \
|
||||
m1 = L2HBITS(m); \
|
||||
lt = (lt + m1) & BN_MASK2; \
|
||||
if (lt < m1) \
|
||||
ht++; \
|
||||
(l) = lt; \
|
||||
(h) = ht; \
|
||||
}
|
||||
|
||||
#define sqr64(lo, ho, in) \
|
||||
{ \
|
||||
BN_ULONG l, h, m; \
|
||||
\
|
||||
h = (in); \
|
||||
l = LBITS(h); \
|
||||
h = HBITS(h); \
|
||||
m = (l) * (h); \
|
||||
l *= l; \
|
||||
h *= h; \
|
||||
h += (m & BN_MASK2h1) >> (BN_BITS4 - 1); \
|
||||
m = (m & BN_MASK2l) << (BN_BITS4 + 1); \
|
||||
l = (l + m) & BN_MASK2; \
|
||||
if (l < m) \
|
||||
h++; \
|
||||
(lo) = l; \
|
||||
(ho) = h; \
|
||||
}
|
||||
|
||||
#define mul_add(r, a, bl, bh, c) \
|
||||
{ \
|
||||
BN_ULONG l, h; \
|
||||
\
|
||||
h = (a); \
|
||||
l = LBITS(h); \
|
||||
h = HBITS(h); \
|
||||
mul64(l, h, (bl), (bh)); \
|
||||
\
|
||||
/* non-multiply part */ \
|
||||
l = (l + (c)) & BN_MASK2; \
|
||||
if (l < (c)) \
|
||||
h++; \
|
||||
(c) = (r); \
|
||||
l = (l + (c)) & BN_MASK2; \
|
||||
if (l < (c)) \
|
||||
h++; \
|
||||
(c) = h & BN_MASK2; \
|
||||
(r) = l; \
|
||||
}
|
||||
|
||||
#define mul(r, a, bl, bh, c) \
|
||||
{ \
|
||||
BN_ULONG l, h; \
|
||||
\
|
||||
h = (a); \
|
||||
l = LBITS(h); \
|
||||
h = HBITS(h); \
|
||||
mul64(l, h, (bl), (bh)); \
|
||||
\
|
||||
/* non-multiply part */ \
|
||||
l += (c); \
|
||||
if ((l & BN_MASK2) < (c)) \
|
||||
h++; \
|
||||
(c) = h & BN_MASK2; \
|
||||
(r) = l & BN_MASK2; \
|
||||
}
|
||||
#endif /* !BN_ULLONG */
|
||||
|
||||
#if defined(BN_ULLONG) || defined(BN_UMULT_HIGH)
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w) {
|
||||
BN_ULONG c1 = 0;
|
||||
@@ -202,6 +298,174 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !(defined(BN_ULLONG) || defined(BN_UMULT_HIGH)) */
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w) {
|
||||
BN_ULONG c = 0;
|
||||
BN_ULONG bl, bh;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0) {
|
||||
return (BN_ULONG)0;
|
||||
}
|
||||
|
||||
bl = LBITS(w);
|
||||
bh = HBITS(w);
|
||||
|
||||
while (num & ~3) {
|
||||
mul_add(rp[0], ap[0], bl, bh, c);
|
||||
mul_add(rp[1], ap[1], bl, bh, c);
|
||||
mul_add(rp[2], ap[2], bl, bh, c);
|
||||
mul_add(rp[3], ap[3], bl, bh, c);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
while (num) {
|
||||
mul_add(rp[0], ap[0], bl, bh, c);
|
||||
ap++;
|
||||
rp++;
|
||||
num--;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
|
||||
BN_ULONG carry = 0;
|
||||
BN_ULONG bl, bh;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0) {
|
||||
return (BN_ULONG)0;
|
||||
}
|
||||
|
||||
bl = LBITS(w);
|
||||
bh = HBITS(w);
|
||||
|
||||
while (num & ~3) {
|
||||
mul(rp[0], ap[0], bl, bh, carry);
|
||||
mul(rp[1], ap[1], bl, bh, carry);
|
||||
mul(rp[2], ap[2], bl, bh, carry);
|
||||
mul(rp[3], ap[3], bl, bh, carry);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
while (num) {
|
||||
mul(rp[0], ap[0], bl, bh, carry);
|
||||
ap++;
|
||||
rp++;
|
||||
num--;
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
assert(n >= 0);
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (n & ~3) {
|
||||
sqr64(r[0], r[1], a[0]);
|
||||
sqr64(r[2], r[3], a[1]);
|
||||
sqr64(r[4], r[5], a[2]);
|
||||
sqr64(r[6], r[7], a[3]);
|
||||
a += 4;
|
||||
r += 8;
|
||||
n -= 4;
|
||||
}
|
||||
while (n) {
|
||||
sqr64(r[0], r[1], a[0]);
|
||||
a++;
|
||||
r += 2;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(defined(BN_ULLONG) || defined(BN_UMULT_HIGH)) */
|
||||
|
||||
#if defined(BN_ULLONG)
|
||||
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
return (BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2) | l) / (BN_ULLONG)d);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Divide h,l by d and return the result. */
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
BN_ULONG dh, dl, q, ret = 0, th, tl, t;
|
||||
int i, count = 2;
|
||||
|
||||
if (d == 0) {
|
||||
return BN_MASK2;
|
||||
}
|
||||
|
||||
i = BN_num_bits_word(d);
|
||||
assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
|
||||
|
||||
i = BN_BITS2 - i;
|
||||
if (h >= d) {
|
||||
h -= d;
|
||||
}
|
||||
|
||||
if (i) {
|
||||
d <<= i;
|
||||
h = (h << i) | (l >> (BN_BITS2 - i));
|
||||
l <<= i;
|
||||
}
|
||||
dh = (d & BN_MASK2h) >> BN_BITS4;
|
||||
dl = (d & BN_MASK2l);
|
||||
for (;;) {
|
||||
if ((h >> BN_BITS4) == dh) {
|
||||
q = BN_MASK2l;
|
||||
} else {
|
||||
q = h / dh;
|
||||
}
|
||||
|
||||
th = q * dh;
|
||||
tl = dl * q;
|
||||
for (;;) {
|
||||
t = h - th;
|
||||
if ((t & BN_MASK2h) ||
|
||||
((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
|
||||
break;
|
||||
}
|
||||
q--;
|
||||
th -= dh;
|
||||
tl -= dl;
|
||||
}
|
||||
t = (tl >> BN_BITS4);
|
||||
tl = (tl << BN_BITS4) & BN_MASK2h;
|
||||
th += t;
|
||||
|
||||
if (l < tl) {
|
||||
th++;
|
||||
}
|
||||
l -= tl;
|
||||
if (h < th) {
|
||||
h += d;
|
||||
q--;
|
||||
}
|
||||
h -= th;
|
||||
|
||||
if (--count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = q << BN_BITS4;
|
||||
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
|
||||
l = (l & BN_MASK2l) << BN_BITS4;
|
||||
}
|
||||
|
||||
ret |= q;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !defined(BN_ULLONG) */
|
||||
|
||||
#ifdef BN_ULLONG
|
||||
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n) {
|
||||
@@ -409,7 +673,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#else
|
||||
#elif defined(BN_UMULT_LOHI)
|
||||
|
||||
/* Keep in mind that additions to hi can not overflow, because the high word of
|
||||
* a multiplication result cannot be all-ones. */
|
||||
@@ -452,6 +716,58 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#else /* !BN_ULLONG */
|
||||
|
||||
/* Keep in mind that additions to hi can not overflow, because
|
||||
* the high word of a multiplication result cannot be all-ones. */
|
||||
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
|
||||
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
|
||||
mul64(lo, hi, bl, bh); \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG tt; \
|
||||
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
|
||||
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
|
||||
mul64(lo, hi, bl, bh); \
|
||||
tt = hi; \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
tt++; \
|
||||
c1 = (c1 + tt) & BN_MASK2; \
|
||||
if (c1 < tt) \
|
||||
c2++; \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG lo, hi; \
|
||||
sqr64(lo, hi, (a)[i]); \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
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)
|
||||
#endif /* !BN_ULLONG */
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
|
||||
+71
-14
@@ -125,15 +125,13 @@
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
#pragma warning(push, 3)
|
||||
#include <intrin.h>
|
||||
#pragma warning(pop)
|
||||
#pragma intrinsic(__umulh, _umul128)
|
||||
#endif
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -146,7 +144,7 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
/* MSVC doesn't support two-word integers on 64-bit. */
|
||||
#define BN_ULLONG uint128_t
|
||||
#define BN_ULLONG __uint128_t
|
||||
#endif
|
||||
|
||||
#define BN_BITS2 64
|
||||
@@ -181,6 +179,14 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
#endif
|
||||
|
||||
|
||||
/* Pentium pro 16,16,16,32,64 */
|
||||
/* Alpha 16,16,16,16.64 */
|
||||
#define BN_MULL_SIZE_NORMAL (16) /* 32 */
|
||||
#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */
|
||||
#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */
|
||||
#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
|
||||
#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */
|
||||
|
||||
#define STATIC_BIGNUM(x) \
|
||||
{ \
|
||||
(BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \
|
||||
@@ -192,14 +198,10 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
|
||||
#endif
|
||||
|
||||
|
||||
/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
|
||||
* least significant word first. */
|
||||
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
|
||||
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
|
||||
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
|
||||
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
|
||||
|
||||
@@ -221,12 +223,67 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
|
||||
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
const BN_ULONG *np, const BN_ULONG *n0, int num);
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
#endif
|
||||
#if !defined(BN_ULLONG)
|
||||
|
||||
#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
|
||||
#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
|
||||
#define LBITS(a) ((a) & BN_MASK2l)
|
||||
#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
|
||||
#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
|
||||
|
||||
#define LLBITS(a) ((a) & BN_MASKl)
|
||||
#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
|
||||
#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
|
||||
|
||||
#define mul64(l, h, bl, bh) \
|
||||
{ \
|
||||
BN_ULONG m, m1, lt, ht; \
|
||||
\
|
||||
lt = l; \
|
||||
ht = h; \
|
||||
m = (bh) * (lt); \
|
||||
lt = (bl) * (lt); \
|
||||
m1 = (bl) * (ht); \
|
||||
ht = (bh) * (ht); \
|
||||
m = (m + m1) & BN_MASK2; \
|
||||
if (m < m1) \
|
||||
ht += L2HBITS((BN_ULONG)1); \
|
||||
ht += HBITS(m); \
|
||||
m1 = L2HBITS(m); \
|
||||
lt = (lt + m1) & BN_MASK2; \
|
||||
if (lt < m1) \
|
||||
ht++; \
|
||||
(l) = lt; \
|
||||
(h) = ht; \
|
||||
}
|
||||
|
||||
#endif /* !defined(BN_ULLONG) */
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
|
||||
# if defined(__GNUC__) && __GNUC__ >= 2
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret,discard; \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(discard),"=d"(ret) \
|
||||
: "a"(a), "g"(b) \
|
||||
: "cc"); \
|
||||
ret; })
|
||||
# define BN_UMULT_LOHI(low,high,a,b) \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(low),"=d"(high) \
|
||||
: "a"(a),"g"(b) \
|
||||
: "cc");
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
# define BN_UMULT_HIGH(a, b) __umulh((a), (b))
|
||||
# define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
# endif
|
||||
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64)
|
||||
# if defined(__GNUC__) && __GNUC__>=2
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret; \
|
||||
__asm__ ("umulh %0,%1,%2" \
|
||||
: "=r"(ret) \
|
||||
: "r"(a), "r"(b)); \
|
||||
ret; })
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+94
-13
@@ -326,12 +326,14 @@ int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
|
||||
return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
|
||||
const BN_MONT_CTX *mont) {
|
||||
const BIGNUM *n;
|
||||
BN_ULONG *ap, *np, *rp, n0, v, carry;
|
||||
int nl, max, i;
|
||||
|
||||
const BIGNUM *n = &mont->N;
|
||||
n = &mont->N;
|
||||
nl = n->top;
|
||||
if (nl == 0) {
|
||||
ret->top = 0;
|
||||
@@ -374,13 +376,13 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
|
||||
|
||||
{
|
||||
BN_ULONG *nrp;
|
||||
uintptr_t m;
|
||||
size_t m;
|
||||
|
||||
v = bn_sub_words(rp, ap, np, nl) - carry;
|
||||
/* if subtraction result is real, then trick unconditional memcpy below to
|
||||
* perform in-place "refresh" instead of actual copy. */
|
||||
m = (0u - (uintptr_t)v);
|
||||
nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m));
|
||||
m = (0 - (size_t)v);
|
||||
nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
|
||||
|
||||
for (i = 0, nl -= 4; i < nl; i += 4) {
|
||||
BN_ULONG t1, t2, t3, t4;
|
||||
@@ -409,25 +411,104 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont,
|
||||
#define PTR_SIZE_INT size_t
|
||||
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
|
||||
{
|
||||
BIGNUM *n;
|
||||
BN_ULONG *ap,*np,*rp,n0,v,carry;
|
||||
int nl,max,i;
|
||||
|
||||
n= (BIGNUM*) &(mont->N);
|
||||
nl=n->top;
|
||||
if (nl == 0) { ret->top=0; return(1); }
|
||||
|
||||
max=(2*nl); /* carry is stored separately */
|
||||
if (bn_wexpand(r,max) == NULL) return(0);
|
||||
|
||||
r->neg^=n->neg;
|
||||
np=n->d;
|
||||
rp=r->d;
|
||||
|
||||
/* clear the top words of T */
|
||||
#if 1
|
||||
for (i=r->top; i<max; i++) /* memset? XXX */
|
||||
rp[i]=0;
|
||||
#else
|
||||
memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
|
||||
#endif
|
||||
|
||||
r->top=max;
|
||||
n0=mont->n0[0];
|
||||
|
||||
for (carry=0, i=0; i<nl; i++, rp++)
|
||||
{
|
||||
v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
|
||||
v = (v+carry+rp[nl])&BN_MASK2;
|
||||
carry |= (v != rp[nl]);
|
||||
carry &= (v <= rp[nl]);
|
||||
rp[nl]=v;
|
||||
}
|
||||
|
||||
if (bn_wexpand(ret,nl) == NULL) return(0);
|
||||
ret->top=nl;
|
||||
ret->neg=r->neg;
|
||||
|
||||
rp=ret->d;
|
||||
ap=&(r->d[nl]);
|
||||
|
||||
{
|
||||
BN_ULONG *nrp;
|
||||
size_t m;
|
||||
|
||||
v=bn_sub_words(rp,ap,np,nl)-carry;
|
||||
/* if subtraction result is real, then
|
||||
* trick unconditional memcpy below to perform in-place
|
||||
* "refresh" instead of actual copy. */
|
||||
m=(0-(size_t)v);
|
||||
nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
|
||||
|
||||
for (i=0,nl-=4; i<nl; i+=4)
|
||||
{
|
||||
BN_ULONG t1,t2,t3,t4;
|
||||
|
||||
t1=nrp[i+0];
|
||||
t2=nrp[i+1];
|
||||
t3=nrp[i+2]; ap[i+0]=0;
|
||||
t4=nrp[i+3]; ap[i+1]=0;
|
||||
rp[i+0]=t1; ap[i+2]=0;
|
||||
rp[i+1]=t2; ap[i+3]=0;
|
||||
rp[i+2]=t3;
|
||||
rp[i+3]=t4;
|
||||
}
|
||||
for (nl+=4; i<nl; i++)
|
||||
rp[i]=nrp[i], ap[i]=0;
|
||||
}
|
||||
bn_correct_top(r);
|
||||
bn_correct_top(ret);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
int ret = 0;
|
||||
int retn = 0;
|
||||
BIGNUM *t;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
if (t == NULL ||
|
||||
!BN_copy(t, a)) {
|
||||
goto err;
|
||||
if (t == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = BN_from_montgomery_word(r, t, mont);
|
||||
|
||||
err:
|
||||
if (BN_copy(t, a)) {
|
||||
retn = BN_from_montgomery_word(ret, t, mont);
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
|
||||
return ret;
|
||||
return retn;
|
||||
}
|
||||
|
||||
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
|
||||
+27
-8
@@ -62,12 +62,7 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#define BN_MUL_RECURSIVE_SIZE_NORMAL 16
|
||||
#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL
|
||||
|
||||
|
||||
static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
|
||||
int nb) {
|
||||
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
|
||||
BN_ULONG *rr;
|
||||
|
||||
if (na < nb) {
|
||||
@@ -112,6 +107,31 @@ static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
|
||||
bn_mul_words(r, a, n, b[0]);
|
||||
|
||||
for (;;) {
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[1]), a, n, b[1]);
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[2]), a, n, b[2]);
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[3]), a, n, b[3]);
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[4]), a, n, b[4]);
|
||||
r += 4;
|
||||
b += 4;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
|
||||
/* Here follows specialised variants of bn_add_words() and bn_sub_words(). They
|
||||
* have the property performing operations on arrays of different sizes. The
|
||||
@@ -598,8 +618,7 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
static const int kMulNormalSize = 16;
|
||||
if (al >= kMulNormalSize && bl >= kMulNormalSize) {
|
||||
if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
|
||||
if (i >= -1 && i <= 1) {
|
||||
/* Find out the power of two lower or equal
|
||||
to the longest of the two numbers */
|
||||
|
||||
+28
-21
@@ -48,9 +48,6 @@
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* See crypto/bn/asm/rsaz-avx2.pl for further details.
|
||||
*/
|
||||
@@ -61,30 +58,42 @@ void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i);
|
||||
void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i);
|
||||
void rsaz_1024_red2norm_avx2(void *norm,const void *red);
|
||||
|
||||
alignas(64) static const BN_ULONG one[40] =
|
||||
#if defined(__GNUC__)
|
||||
# define ALIGN64 __attribute__((aligned(64)))
|
||||
#elif defined(_MSC_VER)
|
||||
# define ALIGN64 __declspec(align(64))
|
||||
#elif defined(__SUNPRO_C)
|
||||
# define ALIGN64
|
||||
# pragma align 64(one,two80)
|
||||
#else
|
||||
# define ALIGN64 /* not fatal, might hurt performance a little */
|
||||
#endif
|
||||
|
||||
ALIGN64 static const BN_ULONG one[40] =
|
||||
{1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
alignas(64) static const BN_ULONG two80[40] =
|
||||
ALIGN64 static const BN_ULONG two80[40] =
|
||||
{0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
|
||||
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0)
|
||||
{
|
||||
alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */
|
||||
unsigned char storage[320*3+32*9*16+64]; /* 5.5KB */
|
||||
unsigned char *p_str = storage + (64-((size_t)storage%64));
|
||||
unsigned char *a_inv, *m, *result,
|
||||
*table_s = storage + (320 * 3),
|
||||
*table_s = p_str+320*3,
|
||||
*R2 = table_s; /* borrow */
|
||||
int index;
|
||||
int wvalue;
|
||||
|
||||
if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) {
|
||||
result = storage;
|
||||
a_inv = storage + 320;
|
||||
m = storage + (320 * 2); /* should not cross page */
|
||||
if ((((size_t)p_str&4095)+320)>>12) {
|
||||
result = p_str;
|
||||
a_inv = p_str + 320;
|
||||
m = p_str + 320*2; /* should not cross page */
|
||||
} else {
|
||||
m = storage; /* should not cross page */
|
||||
result = storage + 320;
|
||||
a_inv = storage + (320 * 2);
|
||||
m = p_str; /* should not cross page */
|
||||
result = p_str + 320;
|
||||
a_inv = p_str + 320*2;
|
||||
}
|
||||
|
||||
rsaz_1024_norm2red_avx2(m, m_norm);
|
||||
@@ -215,9 +224,8 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
rsaz_1024_scatter5_avx2(table_s,result,31);
|
||||
#endif
|
||||
|
||||
const uint8_t *p_str = (const uint8_t *)exponent;
|
||||
|
||||
/* load first window */
|
||||
p_str = (unsigned char*)exponent;
|
||||
wvalue = p_str[127] >> 3;
|
||||
rsaz_1024_gather5_avx2(result,table_s,wvalue);
|
||||
|
||||
@@ -227,7 +235,7 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
|
||||
rsaz_1024_sqr_avx2(result, result, m, k0, 5);
|
||||
|
||||
wvalue = *((const unsigned short*)&p_str[index / 8]);
|
||||
wvalue = *((unsigned short*)&p_str[index/8]);
|
||||
wvalue = (wvalue>> (index%8)) & 31;
|
||||
index-=5;
|
||||
|
||||
@@ -266,10 +274,11 @@ 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;
|
||||
unsigned char storage[16*8*8+64*2+64]; /* 1.2KB */
|
||||
unsigned char *table = storage + (64-((size_t)storage%64));
|
||||
BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8),
|
||||
*temp = (BN_ULONG *)(table+16*8*8+8*8);
|
||||
unsigned char *p_str = (unsigned char*)exponent;
|
||||
int index;
|
||||
unsigned int wvalue;
|
||||
|
||||
@@ -291,8 +300,6 @@ void RSAZ_512_mod_exp(BN_ULONG result[8],
|
||||
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];
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ add_library(
|
||||
|
||||
OBJECT
|
||||
|
||||
asn1_compat.c
|
||||
ber.c
|
||||
cbs.c
|
||||
cbb.c
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/* Copyright (c) 2016, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
assert(cbb->base->can_resize);
|
||||
|
||||
uint8_t *der;
|
||||
size_t der_len;
|
||||
if (!CBB_finish(cbb, &der, &der_len)) {
|
||||
CBB_cleanup(cbb);
|
||||
return -1;
|
||||
}
|
||||
if (der_len > INT_MAX) {
|
||||
OPENSSL_free(der);
|
||||
return -1;
|
||||
}
|
||||
if (outp != NULL) {
|
||||
if (*outp == NULL) {
|
||||
*outp = der;
|
||||
der = NULL;
|
||||
} else {
|
||||
memcpy(*outp, der, der_len);
|
||||
*outp += der_len;
|
||||
}
|
||||
}
|
||||
OPENSSL_free(der);
|
||||
return (int)der_len;
|
||||
}
|
||||
+88
-130
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
@@ -25,37 +24,11 @@
|
||||
* input could otherwise cause the stack to overflow. */
|
||||
static const unsigned kMaxDepth = 2048;
|
||||
|
||||
/* is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
* ignores the constructed bit. */
|
||||
static int is_string_type(unsigned tag) {
|
||||
if ((tag & 0xc0) != 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (tag & 0x1f) {
|
||||
case CBS_ASN1_BITSTRING:
|
||||
case CBS_ASN1_OCTETSTRING:
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T16STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
case CBS_ASN1_VISIBLESTRING:
|
||||
case CBS_ASN1_GENERALSTRING:
|
||||
case CBS_ASN1_UNIVERSALSTRING:
|
||||
case CBS_ASN1_BMPSTRING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
* depending on whether an indefinite length element or constructed string was
|
||||
* found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
* |*ber_found| was set) and zero on error. */
|
||||
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
* depending on whether an indefinite length element was found. The value of
|
||||
* |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
|
||||
* and zero on error. */
|
||||
static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
CBS in;
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
@@ -76,16 +49,10 @@ static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
if (CBS_len(&contents) == header_len &&
|
||||
header_len > 0 &&
|
||||
CBS_data(&contents)[header_len-1] == 0x80) {
|
||||
/* Found an indefinite-length element. */
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (is_string_type(tag)) {
|
||||
/* Constructed strings are only legal in BER and require conversion. */
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (!CBS_skip(&contents, header_len) ||
|
||||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
|
||||
return 0;
|
||||
@@ -96,6 +63,16 @@ static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is_primitive_type returns true if |tag| likely a primitive type. Normally
|
||||
* one can just test the "constructed" bit in the tag but, in BER, even
|
||||
* primitive tags can have the constructed bit if they have indefinite
|
||||
* length. */
|
||||
static char is_primitive_type(unsigned tag) {
|
||||
return (tag & 0xc0) == 0 &&
|
||||
(tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
|
||||
(tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
|
||||
}
|
||||
|
||||
/* is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
* |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
@@ -104,86 +81,111 @@ static char is_eoc(size_t header_len, CBS *contents) {
|
||||
}
|
||||
|
||||
/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
* |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
* constructed bit and primitive element bodies are written to |out| without
|
||||
* element headers. This is used when concatenating the fragments of a
|
||||
* constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
* will cause the function to return after consuming it. It returns one on
|
||||
* success and zero on error. */
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
* |squash_header| is set then the top-level of elements from |in| will not
|
||||
* have their headers written. This is used when concatenating the fragments of
|
||||
* an indefinite length, primitive value. If |looking_for_eoc| is set then any
|
||||
* EOC elements found will cause the function to return after consuming it.
|
||||
* It returns one on success and zero on error. */
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
|
||||
char looking_for_eoc, unsigned depth) {
|
||||
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (CBS_len(in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag, child_string_tag = string_tag;
|
||||
unsigned tag;
|
||||
size_t header_len;
|
||||
CBB *out_contents, out_contents_storage;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
if (CBS_len(&contents) == header_len) {
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
}
|
||||
|
||||
if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
/* This is an indefinite length element. If it's a SEQUENCE or SET then
|
||||
* we just need to write the out the contents as normal, but with a
|
||||
* concrete length prefix.
|
||||
*
|
||||
* If it's a something else then the contents will be a series of BER
|
||||
* elements of the same type which need to be concatenated. */
|
||||
const char context_specific = (tag & 0xc0) == 0x80;
|
||||
char squash_child_headers = is_primitive_type(tag);
|
||||
|
||||
/* This is a hack, but it sufficies to handle NSS's output. If we find
|
||||
* an indefinite length, context-specific tag with a definite, primitive
|
||||
* tag inside it, then we assume that the context-specific tag is
|
||||
* implicit and the tags within are fragments of a primitive type that
|
||||
* need to be concatenated. */
|
||||
if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
|
||||
CBS in_copy, inner_contents;
|
||||
unsigned inner_tag;
|
||||
size_t inner_header_len;
|
||||
|
||||
CBS_init(&in_copy, CBS_data(in), CBS_len(in));
|
||||
if (!CBS_get_any_ber_asn1_element(&in_copy, &inner_contents,
|
||||
&inner_tag, &inner_header_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CBS_len(&inner_contents) > inner_header_len &&
|
||||
is_primitive_type(inner_tag)) {
|
||||
squash_child_headers = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!squash_header) {
|
||||
unsigned out_tag = tag;
|
||||
if (squash_child_headers) {
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (!cbs_convert_ber(in, out_contents,
|
||||
squash_child_headers,
|
||||
1 /* looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
if (out_contents != out && !CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (string_tag != 0) {
|
||||
/* This is part of a constructed string. All elements must match
|
||||
* |string_tag| up to the constructed bit and get appended to |out|
|
||||
* without a child element. */
|
||||
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
} else {
|
||||
unsigned out_tag = tag;
|
||||
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
|
||||
/* If a constructed string, clear the constructed bit and inform
|
||||
* children to concatenate bodies. */
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
child_string_tag = out_tag;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
if (!squash_header) {
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (CBS_len(&contents) == header_len && header_len > 0 &&
|
||||
CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
/* This is an indefinite length element. */
|
||||
if (!cbs_convert_ber(in, out_contents, child_string_tag,
|
||||
1 /* looking for eoc */, depth + 1) ||
|
||||
!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CBS_skip(&contents, header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
/* Recurse into children. */
|
||||
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
|
||||
if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
|
||||
0 /* not looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Copy primitive contents as-is. */
|
||||
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
|
||||
CBS_len(&contents))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CBB_flush(out)) {
|
||||
if (out_contents != out && !CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -207,57 +209,13 @@ int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!CBB_init(&cbb, CBS_len(in)) ||
|
||||
!cbs_convert_ber(in, &cbb, 0, 0, 0) ||
|
||||
!CBB_finish(&cbb, out, out_len)) {
|
||||
if (!CBB_init(&cbb, CBS_len(in))) {
|
||||
return 0;
|
||||
}
|
||||
if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
|
||||
unsigned outer_tag, unsigned inner_tag) {
|
||||
assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(is_string_type(inner_tag));
|
||||
|
||||
if (CBS_peek_asn1_tag(in, outer_tag)) {
|
||||
/* Normal implicitly-tagged string. */
|
||||
*out_storage = NULL;
|
||||
return CBS_get_asn1(in, out, outer_tag);
|
||||
}
|
||||
|
||||
/* Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
* |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
* of nesting. */
|
||||
CBB result;
|
||||
CBS child;
|
||||
if (!CBB_init(&result, CBS_len(in)) ||
|
||||
!CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (CBS_len(&child) > 0) {
|
||||
CBS chunk;
|
||||
if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
|
||||
!CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&result, &data, &len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS_init(out, data, len);
|
||||
*out_storage = data;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
CBB_cleanup(&result);
|
||||
return 0;
|
||||
return CBB_finish(&cbb, out, out_len);
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ static bool TestBerConvert() {
|
||||
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
|
||||
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
|
||||
|
||||
// kOctetStringBER contains an indefinite length OCTET STRING with two parts.
|
||||
// kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
|
||||
// These parts need to be concatenated in DER form.
|
||||
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
|
||||
0x04, 0x02, 2, 3, 0x00, 0x00};
|
||||
@@ -609,16 +609,6 @@ static bool TestBerConvert() {
|
||||
0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
|
||||
};
|
||||
|
||||
// kConstructedStringBER contains a deeply-nested constructed OCTET STRING.
|
||||
// The BER conversion collapses this to one level deep, but not completely.
|
||||
static const uint8_t kConstructedStringBER[] = {
|
||||
0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01,
|
||||
0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03,
|
||||
};
|
||||
static const uint8_t kConstructedStringDER[] = {
|
||||
0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03,
|
||||
};
|
||||
|
||||
return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
|
||||
kSimpleBER, sizeof(kSimpleBER)) &&
|
||||
DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
|
||||
@@ -627,59 +617,7 @@ static bool TestBerConvert() {
|
||||
sizeof(kOctetStringDER), kOctetStringBER,
|
||||
sizeof(kOctetStringBER)) &&
|
||||
DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
|
||||
sizeof(kNSSBER)) &&
|
||||
DoBerConvert("kConstructedStringBER", kConstructedStringDER,
|
||||
sizeof(kConstructedStringDER), kConstructedStringBER,
|
||||
sizeof(kConstructedStringBER));
|
||||
}
|
||||
|
||||
struct ImplicitStringTest {
|
||||
const char *in;
|
||||
size_t in_len;
|
||||
bool ok;
|
||||
const char *out;
|
||||
size_t out_len;
|
||||
};
|
||||
|
||||
static const ImplicitStringTest kImplicitStringTests[] = {
|
||||
// A properly-encoded string.
|
||||
{"\x80\x03\x61\x61\x61", 5, true, "aaa", 3},
|
||||
// An implicit-tagged string.
|
||||
{"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3},
|
||||
// |CBS_get_asn1_implicit_string| only accepts one level deep of nesting.
|
||||
{"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr,
|
||||
0},
|
||||
// The outer tag must match.
|
||||
{"\x81\x03\x61\x61\x61", 5, false, nullptr, 0},
|
||||
{"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0},
|
||||
// The inner tag must match.
|
||||
{"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0},
|
||||
};
|
||||
|
||||
static bool TestImplicitString() {
|
||||
for (const auto &test : kImplicitStringTests) {
|
||||
uint8_t *storage = nullptr;
|
||||
CBS in, out;
|
||||
CBS_init(&in, reinterpret_cast<const uint8_t *>(test.in), test.in_len);
|
||||
int ok = CBS_get_asn1_implicit_string(&in, &out, &storage,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
CBS_ASN1_OCTETSTRING);
|
||||
ScopedOpenSSLBytes scoper(storage);
|
||||
|
||||
if (static_cast<bool>(ok) != test.ok) {
|
||||
fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n",
|
||||
ok ? "succeeded" : "failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ok && (CBS_len(&out) != test.out_len ||
|
||||
memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
|
||||
fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
sizeof(kNSSBER));
|
||||
}
|
||||
|
||||
struct ASN1Uint64Test {
|
||||
@@ -765,32 +703,12 @@ static bool TestASN1Uint64() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestZero() {
|
||||
static int TestZero() {
|
||||
CBB cbb;
|
||||
CBB_zero(&cbb);
|
||||
// Calling |CBB_cleanup| on a zero-state |CBB| must not crash.
|
||||
CBB_cleanup(&cbb);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCBBReserve() {
|
||||
uint8_t buf[10];
|
||||
uint8_t *ptr;
|
||||
size_t len;
|
||||
ScopedCBB cbb;
|
||||
if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
|
||||
// Too large.
|
||||
CBB_reserve(cbb.get(), &ptr, 11) ||
|
||||
// Successfully reserve the entire space.
|
||||
!CBB_reserve(cbb.get(), &ptr, 10) ||
|
||||
ptr != buf ||
|
||||
// Advancing under the maximum bytes is legal.
|
||||
!CBB_did_write(cbb.get(), 5) ||
|
||||
!CBB_finish(cbb.get(), NULL, &len) ||
|
||||
len != 5) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -809,11 +727,9 @@ int main(void) {
|
||||
!TestCBBDiscardChild() ||
|
||||
!TestCBBASN1() ||
|
||||
!TestBerConvert() ||
|
||||
!TestImplicitString() ||
|
||||
!TestASN1Uint64() ||
|
||||
!TestGetOptionalASN1Bool() ||
|
||||
!TestZero() ||
|
||||
!TestCBBReserve()) {
|
||||
!TestZero()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+3
-37
@@ -84,8 +84,8 @@ void CBB_cleanup(CBB *cbb) {
|
||||
cbb->base = NULL;
|
||||
}
|
||||
|
||||
static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
size_t newlen;
|
||||
|
||||
if (base == NULL) {
|
||||
@@ -121,17 +121,7 @@ static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
|
||||
if (out) {
|
||||
*out = base->buf + base->len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
if (!cbb_buffer_reserve(base, out, len)) {
|
||||
return 0;
|
||||
}
|
||||
/* This will not overflow or |cbb_buffer_reserve| would have failed. */
|
||||
base->len += len;
|
||||
base->len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -261,11 +251,6 @@ int CBB_flush(CBB *cbb) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t *CBB_data(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
return cbb->base->buf + cbb->offset + cbb->pending_len_len;
|
||||
}
|
||||
|
||||
size_t CBB_len(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
|
||||
@@ -354,25 +339,6 @@ int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_reserve(cbb->base, out_data, len)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_did_write(CBB *cbb, size_t len) {
|
||||
size_t newlen = cbb->base->len + len;
|
||||
if (cbb->child != NULL ||
|
||||
newlen < cbb->base->len ||
|
||||
newlen > cbb->base->cap) {
|
||||
return 0;
|
||||
}
|
||||
cbb->base->len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_u8(CBB *cbb, uint8_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
|
||||
@@ -22,51 +22,22 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
|
||||
* indefinite-length elements or constructed strings then it converts the BER
|
||||
* data to DER and sets |*out| and |*out_length| to describe a malloced buffer
|
||||
* containing the DER data. Additionally, |*in| will be advanced over the BER
|
||||
* element.
|
||||
/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
|
||||
* indefinite-length elements then it attempts to convert the BER data to DER
|
||||
* and sets |*out| and |*out_length| to describe a malloced buffer containing
|
||||
* the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
|
||||
*
|
||||
* If it doesn't find any indefinite-length elements or constructed strings then
|
||||
* it sets |*out| to NULL and |*in| is unmodified.
|
||||
* If it doesn't find any indefinite-length elements then it sets |*out| to
|
||||
* NULL and |*in| is unmodified.
|
||||
*
|
||||
* This function should successfully process any valid BER input, however it
|
||||
* will not convert all of BER's deviations from DER. BER is ambiguous between
|
||||
* implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
|
||||
* strings. Implicitly-tagged strings must be parsed with
|
||||
* |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
|
||||
* must also account for BER variations in the contents of a primitive.
|
||||
* A sufficiently complex ASN.1 structure will break this function because it's
|
||||
* not possible to generically convert BER to DER without knowledge of the
|
||||
* structure itself. However, this sufficies to handle the PKCS#7 and #12 output
|
||||
* from NSS.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
|
||||
|
||||
/* CBS_get_asn1_implicit_string parses a BER string of primitive type
|
||||
* |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
|
||||
* contents. If concatenation was needed, it sets |*out_storage| to a buffer
|
||||
* which the caller must release with |OPENSSL_free|. Otherwise, it sets
|
||||
* |*out_storage| to NULL.
|
||||
*
|
||||
* This function does not parse all of BER. It requires the string be
|
||||
* definite-length. Constructed strings are allowed, but all children of the
|
||||
* outermost element must be primitive. The caller should use
|
||||
* |CBS_asn1_ber_to_der| before running this function.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
|
||||
uint8_t **out_storage,
|
||||
unsigned outer_tag,
|
||||
unsigned inner_tag);
|
||||
|
||||
/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
|
||||
* with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
|
||||
* and |*outp| is advanced just past the output. It returns the number of bytes
|
||||
* in the result, whether written or not, or a negative value on error. On
|
||||
* error, it calls |CBB_cleanup| on |cbb|.
|
||||
*
|
||||
* This function may be used to help implement legacy i2d ASN.1 functions. */
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
|
||||
@@ -4,31 +4,7 @@ if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
CHACHA_ARCH_SOURCES
|
||||
|
||||
chacha-armv4.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
CHACHA_ARCH_SOURCES
|
||||
|
||||
chacha-armv8.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
CHACHA_ARCH_SOURCES
|
||||
|
||||
chacha-x86.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CHACHA_ARCH_SOURCES
|
||||
|
||||
chacha-x86_64.${ASM_EXT}
|
||||
chacha_vec_arm.S
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -37,22 +13,8 @@ add_library(
|
||||
|
||||
OBJECT
|
||||
|
||||
chacha.c
|
||||
chacha_generic.c
|
||||
chacha_vec.c
|
||||
|
||||
${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)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,769 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||
# project. The module is, however, dual licensed under OpenSSL and
|
||||
# CRYPTOGAMS licenses depending on where you obtain it. For further
|
||||
# details see http://www.openssl.org/~appro/cryptogams/.
|
||||
# ====================================================================
|
||||
#
|
||||
# January 2015
|
||||
#
|
||||
# ChaCha20 for x86.
|
||||
#
|
||||
# Performance in cycles per byte out of large buffer.
|
||||
#
|
||||
# 1xIALU/gcc 4xSSSE3
|
||||
# Pentium 17.5/+80%
|
||||
# PIII 14.2/+60%
|
||||
# P4 18.6/+84%
|
||||
# Core2 9.56/+89% 4.83
|
||||
# Westmere 9.50/+45% 3.35
|
||||
# Sandy Bridge 10.7/+47% 3.24
|
||||
# Haswell 8.22/+50% 2.89
|
||||
# Silvermont 17.8/+36% 8.53
|
||||
# Sledgehammer 10.2/+54%
|
||||
# Bulldozer 13.5/+50% 4.39(*)
|
||||
#
|
||||
# (*) Bulldozer actually executes 4xXOP code path that delivers 3.50;
|
||||
#
|
||||
# Modified from upstream OpenSSL to remove the XOP code.
|
||||
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
push(@INC,"${dir}","${dir}../../perlasm");
|
||||
require "x86asm.pl";
|
||||
|
||||
&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
|
||||
|
||||
$xmm=$ymm=0;
|
||||
for (@ARGV) { $xmm=1 if (/-DOPENSSL_IA32_SSE2/); }
|
||||
|
||||
$ymm=$xmm;
|
||||
|
||||
$a="eax";
|
||||
($b,$b_)=("ebx","ebp");
|
||||
($c,$c_)=("ecx","esi");
|
||||
($d,$d_)=("edx","edi");
|
||||
|
||||
sub QUARTERROUND {
|
||||
my ($ai,$bi,$ci,$di,$i)=@_;
|
||||
my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next
|
||||
my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
|
||||
|
||||
# a b c d
|
||||
#
|
||||
# 0 4 8 12 < even round
|
||||
# 1 5 9 13
|
||||
# 2 6 10 14
|
||||
# 3 7 11 15
|
||||
# 0 5 10 15 < odd round
|
||||
# 1 6 11 12
|
||||
# 2 7 8 13
|
||||
# 3 4 9 14
|
||||
|
||||
if ($i==0) {
|
||||
my $j=4;
|
||||
($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
|
||||
} elsif ($i==3) {
|
||||
my $j=0;
|
||||
($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
|
||||
} elsif ($i==4) {
|
||||
my $j=4;
|
||||
($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
|
||||
} elsif ($i==7) {
|
||||
my $j=0;
|
||||
($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
|
||||
}
|
||||
|
||||
#&add ($a,$b); # see elsewhere
|
||||
&xor ($d,$a);
|
||||
&mov (&DWP(4*$cp,"esp"),$c_) if ($ai>0 && $ai<3);
|
||||
&rol ($d,16);
|
||||
&mov (&DWP(4*$bp,"esp"),$b_) if ($i!=0);
|
||||
&add ($c,$d);
|
||||
&mov ($c_,&DWP(4*$cn,"esp")) if ($ai>0 && $ai<3);
|
||||
&xor ($b,$c);
|
||||
&mov ($d_,&DWP(4*$dn,"esp")) if ($di!=$dn);
|
||||
&rol ($b,12);
|
||||
&mov ($b_,&DWP(4*$bn,"esp")) if ($i<7);
|
||||
&mov ($b_,&DWP(128,"esp")) if ($i==7); # loop counter
|
||||
&add ($a,$b);
|
||||
&xor ($d,$a);
|
||||
&mov (&DWP(4*$ai,"esp"),$a);
|
||||
&rol ($d,8);
|
||||
&mov ($a,&DWP(4*$an,"esp"));
|
||||
&add ($c,$d);
|
||||
&mov (&DWP(4*$di,"esp"),$d) if ($di!=$dn);
|
||||
&mov ($d_,$d) if ($di==$dn);
|
||||
&xor ($b,$c);
|
||||
&add ($a,$b_) if ($i<7); # elsewhere
|
||||
&rol ($b,7);
|
||||
|
||||
($b,$b_)=($b_,$b);
|
||||
($c,$c_)=($c_,$c);
|
||||
($d,$d_)=($d_,$d);
|
||||
}
|
||||
|
||||
&static_label("ssse3_shortcut");
|
||||
&static_label("ssse3_data");
|
||||
&static_label("pic_point");
|
||||
|
||||
&function_begin("ChaCha20_ctr32");
|
||||
&xor ("eax","eax");
|
||||
&cmp ("eax",&wparam(2)); # len==0?
|
||||
&je (&label("no_data"));
|
||||
if ($xmm) {
|
||||
&call (&label("pic_point"));
|
||||
&set_label("pic_point");
|
||||
&blindpop("eax");
|
||||
&picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point"));
|
||||
&test (&DWP(0,"ebp"),1<<24); # test FXSR bit
|
||||
&jz (&label("x86"));
|
||||
&test (&DWP(4,"ebp"),1<<9); # test SSSE3 bit
|
||||
&jz (&label("x86"));
|
||||
&jmp (&label("ssse3_shortcut"));
|
||||
&set_label("x86");
|
||||
}
|
||||
&mov ("esi",&wparam(3)); # key
|
||||
&mov ("edi",&wparam(4)); # counter and nonce
|
||||
|
||||
&stack_push(33);
|
||||
|
||||
&mov ("eax",&DWP(4*0,"esi")); # copy key
|
||||
&mov ("ebx",&DWP(4*1,"esi"));
|
||||
&mov ("ecx",&DWP(4*2,"esi"));
|
||||
&mov ("edx",&DWP(4*3,"esi"));
|
||||
&mov (&DWP(64+4*4,"esp"),"eax");
|
||||
&mov (&DWP(64+4*5,"esp"),"ebx");
|
||||
&mov (&DWP(64+4*6,"esp"),"ecx");
|
||||
&mov (&DWP(64+4*7,"esp"),"edx");
|
||||
&mov ("eax",&DWP(4*4,"esi"));
|
||||
&mov ("ebx",&DWP(4*5,"esi"));
|
||||
&mov ("ecx",&DWP(4*6,"esi"));
|
||||
&mov ("edx",&DWP(4*7,"esi"));
|
||||
&mov (&DWP(64+4*8,"esp"),"eax");
|
||||
&mov (&DWP(64+4*9,"esp"),"ebx");
|
||||
&mov (&DWP(64+4*10,"esp"),"ecx");
|
||||
&mov (&DWP(64+4*11,"esp"),"edx");
|
||||
&mov ("eax",&DWP(4*0,"edi")); # copy counter and nonce
|
||||
&mov ("ebx",&DWP(4*1,"edi"));
|
||||
&mov ("ecx",&DWP(4*2,"edi"));
|
||||
&mov ("edx",&DWP(4*3,"edi"));
|
||||
&sub ("eax",1);
|
||||
&mov (&DWP(64+4*12,"esp"),"eax");
|
||||
&mov (&DWP(64+4*13,"esp"),"ebx");
|
||||
&mov (&DWP(64+4*14,"esp"),"ecx");
|
||||
&mov (&DWP(64+4*15,"esp"),"edx");
|
||||
&jmp (&label("entry"));
|
||||
|
||||
&set_label("outer_loop",16);
|
||||
&mov (&wparam(1),$b); # save input
|
||||
&mov (&wparam(0),$a); # save output
|
||||
&mov (&wparam(2),$c); # save len
|
||||
&set_label("entry");
|
||||
&mov ($a,0x61707865);
|
||||
&mov (&DWP(4*1,"esp"),0x3320646e);
|
||||
&mov (&DWP(4*2,"esp"),0x79622d32);
|
||||
&mov (&DWP(4*3,"esp"),0x6b206574);
|
||||
|
||||
&mov ($b, &DWP(64+4*5,"esp")); # copy key material
|
||||
&mov ($b_,&DWP(64+4*6,"esp"));
|
||||
&mov ($c, &DWP(64+4*10,"esp"));
|
||||
&mov ($c_,&DWP(64+4*11,"esp"));
|
||||
&mov ($d, &DWP(64+4*13,"esp"));
|
||||
&mov ($d_,&DWP(64+4*14,"esp"));
|
||||
&mov (&DWP(4*5,"esp"),$b);
|
||||
&mov (&DWP(4*6,"esp"),$b_);
|
||||
&mov (&DWP(4*10,"esp"),$c);
|
||||
&mov (&DWP(4*11,"esp"),$c_);
|
||||
&mov (&DWP(4*13,"esp"),$d);
|
||||
&mov (&DWP(4*14,"esp"),$d_);
|
||||
|
||||
&mov ($b, &DWP(64+4*7,"esp"));
|
||||
&mov ($d_,&DWP(64+4*15,"esp"));
|
||||
&mov ($d, &DWP(64+4*12,"esp"));
|
||||
&mov ($b_,&DWP(64+4*4,"esp"));
|
||||
&mov ($c, &DWP(64+4*8,"esp"));
|
||||
&mov ($c_,&DWP(64+4*9,"esp"));
|
||||
&add ($d,1); # counter value
|
||||
&mov (&DWP(4*7,"esp"),$b);
|
||||
&mov (&DWP(4*15,"esp"),$d_);
|
||||
&mov (&DWP(64+4*12,"esp"),$d); # save counter value
|
||||
|
||||
&mov ($b,10); # loop counter
|
||||
&jmp (&label("loop"));
|
||||
|
||||
&set_label("loop",16);
|
||||
&add ($a,$b_); # elsewhere
|
||||
&mov (&DWP(128,"esp"),$b); # save loop counter
|
||||
&mov ($b,$b_);
|
||||
&QUARTERROUND(0, 4, 8, 12, 0);
|
||||
&QUARTERROUND(1, 5, 9, 13, 1);
|
||||
&QUARTERROUND(2, 6,10, 14, 2);
|
||||
&QUARTERROUND(3, 7,11, 15, 3);
|
||||
&QUARTERROUND(0, 5,10, 15, 4);
|
||||
&QUARTERROUND(1, 6,11, 12, 5);
|
||||
&QUARTERROUND(2, 7, 8, 13, 6);
|
||||
&QUARTERROUND(3, 4, 9, 14, 7);
|
||||
&dec ($b);
|
||||
&jnz (&label("loop"));
|
||||
|
||||
&mov ($b,&wparam(2)); # load len
|
||||
|
||||
&add ($a,0x61707865); # accumulate key material
|
||||
&add ($b_,&DWP(64+4*4,"esp"));
|
||||
&add ($c, &DWP(64+4*8,"esp"));
|
||||
&add ($c_,&DWP(64+4*9,"esp"));
|
||||
|
||||
&cmp ($b,64);
|
||||
&jb (&label("tail"));
|
||||
|
||||
&mov ($b,&wparam(1)); # load input pointer
|
||||
&add ($d, &DWP(64+4*12,"esp"));
|
||||
&add ($d_,&DWP(64+4*14,"esp"));
|
||||
|
||||
&xor ($a, &DWP(4*0,$b)); # xor with input
|
||||
&xor ($b_,&DWP(4*4,$b));
|
||||
&mov (&DWP(4*0,"esp"),$a); # off-load for later write
|
||||
&mov ($a,&wparam(0)); # load output pointer
|
||||
&xor ($c, &DWP(4*8,$b));
|
||||
&xor ($c_,&DWP(4*9,$b));
|
||||
&xor ($d, &DWP(4*12,$b));
|
||||
&xor ($d_,&DWP(4*14,$b));
|
||||
&mov (&DWP(4*4,"esp"),$b_);
|
||||
&mov ($b_,&DWP(4*0,"esp"));
|
||||
&mov (&DWP(4*8,"esp"),$c);
|
||||
&mov (&DWP(4*9,"esp"),$c_);
|
||||
&mov (&DWP(4*12,"esp"),$d);
|
||||
&mov (&DWP(4*14,"esp"),$d_);
|
||||
|
||||
&mov (&DWP(4*0,$a),$b_); # write output in order
|
||||
&mov ($b_,&DWP(4*1,"esp"));
|
||||
&mov ($c, &DWP(4*2,"esp"));
|
||||
&mov ($c_,&DWP(4*3,"esp"));
|
||||
&mov ($d, &DWP(4*5,"esp"));
|
||||
&mov ($d_,&DWP(4*6,"esp"));
|
||||
&add ($b_,0x3320646e); # accumulate key material
|
||||
&add ($c, 0x79622d32);
|
||||
&add ($c_,0x6b206574);
|
||||
&add ($d, &DWP(64+4*5,"esp"));
|
||||
&add ($d_,&DWP(64+4*6,"esp"));
|
||||
&xor ($b_,&DWP(4*1,$b));
|
||||
&xor ($c, &DWP(4*2,$b));
|
||||
&xor ($c_,&DWP(4*3,$b));
|
||||
&xor ($d, &DWP(4*5,$b));
|
||||
&xor ($d_,&DWP(4*6,$b));
|
||||
&mov (&DWP(4*1,$a),$b_);
|
||||
&mov ($b_,&DWP(4*4,"esp"));
|
||||
&mov (&DWP(4*2,$a),$c);
|
||||
&mov (&DWP(4*3,$a),$c_);
|
||||
&mov (&DWP(4*4,$a),$b_);
|
||||
&mov (&DWP(4*5,$a),$d);
|
||||
&mov (&DWP(4*6,$a),$d_);
|
||||
|
||||
&mov ($c,&DWP(4*7,"esp"));
|
||||
&mov ($d,&DWP(4*8,"esp"));
|
||||
&mov ($d_,&DWP(4*9,"esp"));
|
||||
&add ($c,&DWP(64+4*7,"esp"));
|
||||
&mov ($b_, &DWP(4*10,"esp"));
|
||||
&xor ($c,&DWP(4*7,$b));
|
||||
&mov ($c_,&DWP(4*11,"esp"));
|
||||
&mov (&DWP(4*7,$a),$c);
|
||||
&mov (&DWP(4*8,$a),$d);
|
||||
&mov (&DWP(4*9,$a),$d_);
|
||||
|
||||
&add ($b_, &DWP(64+4*10,"esp"));
|
||||
&add ($c_,&DWP(64+4*11,"esp"));
|
||||
&xor ($b_, &DWP(4*10,$b));
|
||||
&xor ($c_,&DWP(4*11,$b));
|
||||
&mov (&DWP(4*10,$a),$b_);
|
||||
&mov (&DWP(4*11,$a),$c_);
|
||||
|
||||
&mov ($c,&DWP(4*12,"esp"));
|
||||
&mov ($c_,&DWP(4*14,"esp"));
|
||||
&mov ($d, &DWP(4*13,"esp"));
|
||||
&mov ($d_,&DWP(4*15,"esp"));
|
||||
&add ($d, &DWP(64+4*13,"esp"));
|
||||
&add ($d_,&DWP(64+4*15,"esp"));
|
||||
&xor ($d, &DWP(4*13,$b));
|
||||
&xor ($d_,&DWP(4*15,$b));
|
||||
&lea ($b,&DWP(4*16,$b));
|
||||
&mov (&DWP(4*12,$a),$c);
|
||||
&mov ($c,&wparam(2)); # len
|
||||
&mov (&DWP(4*13,$a),$d);
|
||||
&mov (&DWP(4*14,$a),$c_);
|
||||
&mov (&DWP(4*15,$a),$d_);
|
||||
&lea ($a,&DWP(4*16,$a));
|
||||
&sub ($c,64);
|
||||
&jnz (&label("outer_loop"));
|
||||
|
||||
&jmp (&label("done"));
|
||||
|
||||
&set_label("tail");
|
||||
&add ($d, &DWP(64+4*12,"esp"));
|
||||
&add ($d_,&DWP(64+4*14,"esp"));
|
||||
&mov (&DWP(4*0,"esp"),$a);
|
||||
&mov (&DWP(4*4,"esp"),$b_);
|
||||
&mov (&DWP(4*8,"esp"),$c);
|
||||
&mov (&DWP(4*9,"esp"),$c_);
|
||||
&mov (&DWP(4*12,"esp"),$d);
|
||||
&mov (&DWP(4*14,"esp"),$d_);
|
||||
|
||||
&mov ($b_,&DWP(4*1,"esp"));
|
||||
&mov ($c, &DWP(4*2,"esp"));
|
||||
&mov ($c_,&DWP(4*3,"esp"));
|
||||
&mov ($d, &DWP(4*5,"esp"));
|
||||
&mov ($d_,&DWP(4*6,"esp"));
|
||||
&add ($b_,0x3320646e); # accumulate key material
|
||||
&add ($c, 0x79622d32);
|
||||
&add ($c_,0x6b206574);
|
||||
&add ($d, &DWP(64+4*5,"esp"));
|
||||
&add ($d_,&DWP(64+4*6,"esp"));
|
||||
&mov (&DWP(4*1,"esp"),$b_);
|
||||
&mov (&DWP(4*2,"esp"),$c);
|
||||
&mov (&DWP(4*3,"esp"),$c_);
|
||||
&mov (&DWP(4*5,"esp"),$d);
|
||||
&mov (&DWP(4*6,"esp"),$d_);
|
||||
|
||||
&mov ($b_,&DWP(4*7,"esp"));
|
||||
&mov ($c, &DWP(4*10,"esp"));
|
||||
&mov ($c_,&DWP(4*11,"esp"));
|
||||
&mov ($d, &DWP(4*13,"esp"));
|
||||
&mov ($d_,&DWP(4*15,"esp"));
|
||||
&add ($b_,&DWP(64+4*7,"esp"));
|
||||
&add ($c, &DWP(64+4*10,"esp"));
|
||||
&add ($c_,&DWP(64+4*11,"esp"));
|
||||
&add ($d, &DWP(64+4*13,"esp"));
|
||||
&add ($d_,&DWP(64+4*15,"esp"));
|
||||
&mov (&DWP(4*7,"esp"),$b_);
|
||||
&mov ($b_,&wparam(1)); # load input
|
||||
&mov (&DWP(4*10,"esp"),$c);
|
||||
&mov ($c,&wparam(0)); # load output
|
||||
&mov (&DWP(4*11,"esp"),$c_);
|
||||
&xor ($c_,$c_);
|
||||
&mov (&DWP(4*13,"esp"),$d);
|
||||
&mov (&DWP(4*15,"esp"),$d_);
|
||||
|
||||
&xor ("eax","eax");
|
||||
&xor ("edx","edx");
|
||||
&set_label("tail_loop");
|
||||
&movb ("al",&BP(0,$c_,$b_));
|
||||
&movb ("dl",&BP(0,"esp",$c_));
|
||||
&lea ($c_,&DWP(1,$c_));
|
||||
&xor ("al","dl");
|
||||
&mov (&BP(-1,$c,$c_),"al");
|
||||
&dec ($b);
|
||||
&jnz (&label("tail_loop"));
|
||||
|
||||
&set_label("done");
|
||||
&stack_pop(33);
|
||||
&set_label("no_data");
|
||||
&function_end("ChaCha20_ctr32");
|
||||
|
||||
if ($xmm) {
|
||||
my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7));
|
||||
my ($out,$inp,$len)=("edi","esi","ecx");
|
||||
|
||||
sub QUARTERROUND_SSSE3 {
|
||||
my ($ai,$bi,$ci,$di,$i)=@_;
|
||||
my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di)); # next
|
||||
my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di)); # previous
|
||||
|
||||
# a b c d
|
||||
#
|
||||
# 0 4 8 12 < even round
|
||||
# 1 5 9 13
|
||||
# 2 6 10 14
|
||||
# 3 7 11 15
|
||||
# 0 5 10 15 < odd round
|
||||
# 1 6 11 12
|
||||
# 2 7 8 13
|
||||
# 3 4 9 14
|
||||
|
||||
if ($i==0) {
|
||||
my $j=4;
|
||||
($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
|
||||
} elsif ($i==3) {
|
||||
my $j=0;
|
||||
($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
|
||||
} elsif ($i==4) {
|
||||
my $j=4;
|
||||
($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
|
||||
} elsif ($i==7) {
|
||||
my $j=0;
|
||||
($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
|
||||
}
|
||||
|
||||
#&paddd ($xa,$xb); # see elsewhere
|
||||
#&pxor ($xd,$xa); # see elsewhere
|
||||
&movdqa(&QWP(16*$cp-128,"ebx"),$xc_) if ($ai>0 && $ai<3);
|
||||
&pshufb ($xd,&QWP(0,"eax")); # rot16
|
||||
&movdqa(&QWP(16*$bp-128,"ebx"),$xb_) if ($i!=0);
|
||||
&paddd ($xc,$xd);
|
||||
&movdqa($xc_,&QWP(16*$cn-128,"ebx")) if ($ai>0 && $ai<3);
|
||||
&pxor ($xb,$xc);
|
||||
&movdqa($xb_,&QWP(16*$bn-128,"ebx")) if ($i<7);
|
||||
&movdqa ($xa_,$xb); # borrow as temporary
|
||||
&pslld ($xb,12);
|
||||
&psrld ($xa_,20);
|
||||
&por ($xb,$xa_);
|
||||
&movdqa($xa_,&QWP(16*$an-128,"ebx"));
|
||||
&paddd ($xa,$xb);
|
||||
&movdqa($xd_,&QWP(16*$dn-128,"ebx")) if ($di!=$dn);
|
||||
&pxor ($xd,$xa);
|
||||
&movdqa (&QWP(16*$ai-128,"ebx"),$xa);
|
||||
&pshufb ($xd,&QWP(16,"eax")); # rot8
|
||||
&paddd ($xc,$xd);
|
||||
&movdqa (&QWP(16*$di-128,"ebx"),$xd) if ($di!=$dn);
|
||||
&movdqa ($xd_,$xd) if ($di==$dn);
|
||||
&pxor ($xb,$xc);
|
||||
&paddd ($xa_,$xb_) if ($i<7); # elsewhere
|
||||
&movdqa ($xa,$xb); # borrow as temporary
|
||||
&pslld ($xb,7);
|
||||
&psrld ($xa,25);
|
||||
&pxor ($xd_,$xa_) if ($i<7); # elsewhere
|
||||
&por ($xb,$xa);
|
||||
|
||||
($xa,$xa_)=($xa_,$xa);
|
||||
($xb,$xb_)=($xb_,$xb);
|
||||
($xc,$xc_)=($xc_,$xc);
|
||||
($xd,$xd_)=($xd_,$xd);
|
||||
}
|
||||
|
||||
&function_begin("ChaCha20_ssse3");
|
||||
&set_label("ssse3_shortcut");
|
||||
&mov ($out,&wparam(0));
|
||||
&mov ($inp,&wparam(1));
|
||||
&mov ($len,&wparam(2));
|
||||
&mov ("edx",&wparam(3)); # key
|
||||
&mov ("ebx",&wparam(4)); # counter and nonce
|
||||
|
||||
&mov ("ebp","esp");
|
||||
&stack_push (131);
|
||||
&and ("esp",-64);
|
||||
&mov (&DWP(512,"esp"),"ebp");
|
||||
|
||||
&lea ("eax",&DWP(&label("ssse3_data")."-".
|
||||
&label("pic_point"),"eax"));
|
||||
&movdqu ("xmm3",&QWP(0,"ebx")); # counter and nonce
|
||||
|
||||
&cmp ($len,64*4);
|
||||
&jb (&label("1x"));
|
||||
|
||||
&mov (&DWP(512+4,"esp"),"edx"); # offload pointers
|
||||
&mov (&DWP(512+8,"esp"),"ebx");
|
||||
&sub ($len,64*4); # bias len
|
||||
&lea ("ebp",&DWP(256+128,"esp")); # size optimization
|
||||
|
||||
&movdqu ("xmm7",&QWP(0,"edx")); # key
|
||||
&pshufd ("xmm0","xmm3",0x00);
|
||||
&pshufd ("xmm1","xmm3",0x55);
|
||||
&pshufd ("xmm2","xmm3",0xaa);
|
||||
&pshufd ("xmm3","xmm3",0xff);
|
||||
&paddd ("xmm0",&QWP(16*3,"eax")); # fix counters
|
||||
&pshufd ("xmm4","xmm7",0x00);
|
||||
&pshufd ("xmm5","xmm7",0x55);
|
||||
&psubd ("xmm0",&QWP(16*4,"eax"));
|
||||
&pshufd ("xmm6","xmm7",0xaa);
|
||||
&pshufd ("xmm7","xmm7",0xff);
|
||||
&movdqa (&QWP(16*12-128,"ebp"),"xmm0");
|
||||
&movdqa (&QWP(16*13-128,"ebp"),"xmm1");
|
||||
&movdqa (&QWP(16*14-128,"ebp"),"xmm2");
|
||||
&movdqa (&QWP(16*15-128,"ebp"),"xmm3");
|
||||
&movdqu ("xmm3",&QWP(16,"edx")); # key
|
||||
&movdqa (&QWP(16*4-128,"ebp"),"xmm4");
|
||||
&movdqa (&QWP(16*5-128,"ebp"),"xmm5");
|
||||
&movdqa (&QWP(16*6-128,"ebp"),"xmm6");
|
||||
&movdqa (&QWP(16*7-128,"ebp"),"xmm7");
|
||||
&movdqa ("xmm7",&QWP(16*2,"eax")); # sigma
|
||||
&lea ("ebx",&DWP(128,"esp")); # size optimization
|
||||
|
||||
&pshufd ("xmm0","xmm3",0x00);
|
||||
&pshufd ("xmm1","xmm3",0x55);
|
||||
&pshufd ("xmm2","xmm3",0xaa);
|
||||
&pshufd ("xmm3","xmm3",0xff);
|
||||
&pshufd ("xmm4","xmm7",0x00);
|
||||
&pshufd ("xmm5","xmm7",0x55);
|
||||
&pshufd ("xmm6","xmm7",0xaa);
|
||||
&pshufd ("xmm7","xmm7",0xff);
|
||||
&movdqa (&QWP(16*8-128,"ebp"),"xmm0");
|
||||
&movdqa (&QWP(16*9-128,"ebp"),"xmm1");
|
||||
&movdqa (&QWP(16*10-128,"ebp"),"xmm2");
|
||||
&movdqa (&QWP(16*11-128,"ebp"),"xmm3");
|
||||
&movdqa (&QWP(16*0-128,"ebp"),"xmm4");
|
||||
&movdqa (&QWP(16*1-128,"ebp"),"xmm5");
|
||||
&movdqa (&QWP(16*2-128,"ebp"),"xmm6");
|
||||
&movdqa (&QWP(16*3-128,"ebp"),"xmm7");
|
||||
|
||||
&lea ($inp,&DWP(128,$inp)); # size optimization
|
||||
&lea ($out,&DWP(128,$out)); # size optimization
|
||||
&jmp (&label("outer_loop"));
|
||||
|
||||
&set_label("outer_loop",16);
|
||||
#&movdqa ("xmm0",&QWP(16*0-128,"ebp")); # copy key material
|
||||
&movdqa ("xmm1",&QWP(16*1-128,"ebp"));
|
||||
&movdqa ("xmm2",&QWP(16*2-128,"ebp"));
|
||||
&movdqa ("xmm3",&QWP(16*3-128,"ebp"));
|
||||
#&movdqa ("xmm4",&QWP(16*4-128,"ebp"));
|
||||
&movdqa ("xmm5",&QWP(16*5-128,"ebp"));
|
||||
&movdqa ("xmm6",&QWP(16*6-128,"ebp"));
|
||||
&movdqa ("xmm7",&QWP(16*7-128,"ebp"));
|
||||
#&movdqa (&QWP(16*0-128,"ebx"),"xmm0");
|
||||
&movdqa (&QWP(16*1-128,"ebx"),"xmm1");
|
||||
&movdqa (&QWP(16*2-128,"ebx"),"xmm2");
|
||||
&movdqa (&QWP(16*3-128,"ebx"),"xmm3");
|
||||
#&movdqa (&QWP(16*4-128,"ebx"),"xmm4");
|
||||
&movdqa (&QWP(16*5-128,"ebx"),"xmm5");
|
||||
&movdqa (&QWP(16*6-128,"ebx"),"xmm6");
|
||||
&movdqa (&QWP(16*7-128,"ebx"),"xmm7");
|
||||
#&movdqa ("xmm0",&QWP(16*8-128,"ebp"));
|
||||
#&movdqa ("xmm1",&QWP(16*9-128,"ebp"));
|
||||
&movdqa ("xmm2",&QWP(16*10-128,"ebp"));
|
||||
&movdqa ("xmm3",&QWP(16*11-128,"ebp"));
|
||||
&movdqa ("xmm4",&QWP(16*12-128,"ebp"));
|
||||
&movdqa ("xmm5",&QWP(16*13-128,"ebp"));
|
||||
&movdqa ("xmm6",&QWP(16*14-128,"ebp"));
|
||||
&movdqa ("xmm7",&QWP(16*15-128,"ebp"));
|
||||
&paddd ("xmm4",&QWP(16*4,"eax")); # counter value
|
||||
#&movdqa (&QWP(16*8-128,"ebx"),"xmm0");
|
||||
#&movdqa (&QWP(16*9-128,"ebx"),"xmm1");
|
||||
&movdqa (&QWP(16*10-128,"ebx"),"xmm2");
|
||||
&movdqa (&QWP(16*11-128,"ebx"),"xmm3");
|
||||
&movdqa (&QWP(16*12-128,"ebx"),"xmm4");
|
||||
&movdqa (&QWP(16*13-128,"ebx"),"xmm5");
|
||||
&movdqa (&QWP(16*14-128,"ebx"),"xmm6");
|
||||
&movdqa (&QWP(16*15-128,"ebx"),"xmm7");
|
||||
&movdqa (&QWP(16*12-128,"ebp"),"xmm4"); # save counter value
|
||||
|
||||
&movdqa ($xa, &QWP(16*0-128,"ebp"));
|
||||
&movdqa ($xd, "xmm4");
|
||||
&movdqa ($xb_,&QWP(16*4-128,"ebp"));
|
||||
&movdqa ($xc, &QWP(16*8-128,"ebp"));
|
||||
&movdqa ($xc_,&QWP(16*9-128,"ebp"));
|
||||
|
||||
&mov ("edx",10); # loop counter
|
||||
&nop ();
|
||||
|
||||
&set_label("loop",16);
|
||||
&paddd ($xa,$xb_); # elsewhere
|
||||
&movdqa ($xb,$xb_);
|
||||
&pxor ($xd,$xa); # elsewhere
|
||||
&QUARTERROUND_SSSE3(0, 4, 8, 12, 0);
|
||||
&QUARTERROUND_SSSE3(1, 5, 9, 13, 1);
|
||||
&QUARTERROUND_SSSE3(2, 6,10, 14, 2);
|
||||
&QUARTERROUND_SSSE3(3, 7,11, 15, 3);
|
||||
&QUARTERROUND_SSSE3(0, 5,10, 15, 4);
|
||||
&QUARTERROUND_SSSE3(1, 6,11, 12, 5);
|
||||
&QUARTERROUND_SSSE3(2, 7, 8, 13, 6);
|
||||
&QUARTERROUND_SSSE3(3, 4, 9, 14, 7);
|
||||
&dec ("edx");
|
||||
&jnz (&label("loop"));
|
||||
|
||||
&movdqa (&QWP(16*4-128,"ebx"),$xb_);
|
||||
&movdqa (&QWP(16*8-128,"ebx"),$xc);
|
||||
&movdqa (&QWP(16*9-128,"ebx"),$xc_);
|
||||
&movdqa (&QWP(16*12-128,"ebx"),$xd);
|
||||
&movdqa (&QWP(16*14-128,"ebx"),$xd_);
|
||||
|
||||
my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7));
|
||||
|
||||
for($i=0;$i<256;$i+=64) {
|
||||
#&movdqa ($xa0,&QWP($i+16*0-128,"ebx")); # it's there
|
||||
&movdqa ($xa1,&QWP($i+16*1-128,"ebx"));
|
||||
&movdqa ($xa2,&QWP($i+16*2-128,"ebx"));
|
||||
&movdqa ($xa3,&QWP($i+16*3-128,"ebx"));
|
||||
|
||||
&paddd ($xa0,&QWP($i+16*0-128,"ebp")); # accumulate key material
|
||||
&paddd ($xa1,&QWP($i+16*1-128,"ebp"));
|
||||
&paddd ($xa2,&QWP($i+16*2-128,"ebp"));
|
||||
&paddd ($xa3,&QWP($i+16*3-128,"ebp"));
|
||||
|
||||
&movdqa ($xt2,$xa0); # "de-interlace" data
|
||||
&punpckldq ($xa0,$xa1);
|
||||
&movdqa ($xt3,$xa2);
|
||||
&punpckldq ($xa2,$xa3);
|
||||
&punpckhdq ($xt2,$xa1);
|
||||
&punpckhdq ($xt3,$xa3);
|
||||
&movdqa ($xa1,$xa0);
|
||||
&punpcklqdq ($xa0,$xa2); # "a0"
|
||||
&movdqa ($xa3,$xt2);
|
||||
&punpcklqdq ($xt2,$xt3); # "a2"
|
||||
&punpckhqdq ($xa1,$xa2); # "a1"
|
||||
&punpckhqdq ($xa3,$xt3); # "a3"
|
||||
|
||||
#($xa2,$xt2)=($xt2,$xa2);
|
||||
|
||||
&movdqa (&QWP($i+16*0-128,"ebx"),$xa0);
|
||||
&movdqa ($xa0,&QWP($i+16*4-128,"ebx")) if ($i<192);
|
||||
&movdqa (&QWP($i+16*1-128,"ebx"),$xa1);
|
||||
&movdqa (&QWP($i+16*2-128,"ebx"),$xt2);
|
||||
&movdqa (&QWP($i+16*3-128,"ebx"),$xa3);
|
||||
}
|
||||
for($i=0;$i<256;$i+=64) {
|
||||
my $j = 16*($i/64);
|
||||
&movdqu ($xa0,&QWP($i+16*0-128,$inp)); # load input
|
||||
&movdqu ($xa1,&QWP($i+16*1-128,$inp));
|
||||
&movdqu ($xa2,&QWP($i+16*2-128,$inp));
|
||||
&movdqu ($xa3,&QWP($i+16*3-128,$inp));
|
||||
&pxor ($xa0,&QWP($j+64*0-128,"ebx"));
|
||||
&pxor ($xa1,&QWP($j+64*1-128,"ebx"));
|
||||
&pxor ($xa2,&QWP($j+64*2-128,"ebx"));
|
||||
&pxor ($xa3,&QWP($j+64*3-128,"ebx"));
|
||||
&movdqu (&QWP($i+16*0-128,$out),$xa0); # write output
|
||||
&movdqu (&QWP($i+16*1-128,$out),$xa1);
|
||||
&movdqu (&QWP($i+16*2-128,$out),$xa2);
|
||||
&movdqu (&QWP($i+16*3-128,$out),$xa3);
|
||||
}
|
||||
&lea ($inp,&DWP(256,$inp));
|
||||
&lea ($out,&DWP(256,$out));
|
||||
&sub ($len,64*4);
|
||||
&jnc (&label("outer_loop"));
|
||||
|
||||
&add ($len,64*4);
|
||||
&jz (&label("done"));
|
||||
|
||||
&mov ("ebx",&DWP(512+8,"esp")); # restore pointers
|
||||
&lea ($inp,&DWP(-128,$inp));
|
||||
&mov ("edx",&DWP(512+4,"esp"));
|
||||
&lea ($out,&DWP(-128,$out));
|
||||
|
||||
&movd ("xmm2",&DWP(16*12-128,"ebp")); # counter value
|
||||
&movdqu ("xmm3",&QWP(0,"ebx"));
|
||||
&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));
|
||||
|
||||
sub SSSE3ROUND { # critical path is 20 "SIMD ticks" per round
|
||||
&paddd ($a,$b);
|
||||
&pxor ($d,$a);
|
||||
&pshufb ($d,$rot16);
|
||||
|
||||
&paddd ($c,$d);
|
||||
&pxor ($b,$c);
|
||||
&movdqa ($t,$b);
|
||||
&psrld ($b,20);
|
||||
&pslld ($t,12);
|
||||
&por ($b,$t);
|
||||
|
||||
&paddd ($a,$b);
|
||||
&pxor ($d,$a);
|
||||
&pshufb ($d,$rot24);
|
||||
|
||||
&paddd ($c,$d);
|
||||
&pxor ($b,$c);
|
||||
&movdqa ($t,$b);
|
||||
&psrld ($b,25);
|
||||
&pslld ($t,7);
|
||||
&por ($b,$t);
|
||||
}
|
||||
|
||||
&set_label("1x");
|
||||
&movdqa ($a,&QWP(16*2,"eax")); # sigma
|
||||
&movdqu ($b,&QWP(0,"edx"));
|
||||
&movdqu ($c,&QWP(16,"edx"));
|
||||
#&movdqu ($d,&QWP(0,"ebx")); # already loaded
|
||||
&movdqa ($rot16,&QWP(0,"eax"));
|
||||
&movdqa ($rot24,&QWP(16,"eax"));
|
||||
&mov (&DWP(16*3,"esp"),"ebp");
|
||||
|
||||
&movdqa (&QWP(16*0,"esp"),$a);
|
||||
&movdqa (&QWP(16*1,"esp"),$b);
|
||||
&movdqa (&QWP(16*2,"esp"),$c);
|
||||
&movdqa (&QWP(16*3,"esp"),$d);
|
||||
&mov ("edx",10);
|
||||
&jmp (&label("loop1x"));
|
||||
|
||||
&set_label("outer1x",16);
|
||||
&movdqa ($d,&QWP(16*5,"eax")); # one
|
||||
&movdqa ($a,&QWP(16*0,"esp"));
|
||||
&movdqa ($b,&QWP(16*1,"esp"));
|
||||
&movdqa ($c,&QWP(16*2,"esp"));
|
||||
&paddd ($d,&QWP(16*3,"esp"));
|
||||
&mov ("edx",10);
|
||||
&movdqa (&QWP(16*3,"esp"),$d);
|
||||
&jmp (&label("loop1x"));
|
||||
|
||||
&set_label("loop1x",16);
|
||||
&SSSE3ROUND();
|
||||
&pshufd ($c,$c,0b01001110);
|
||||
&pshufd ($b,$b,0b00111001);
|
||||
&pshufd ($d,$d,0b10010011);
|
||||
&nop ();
|
||||
|
||||
&SSSE3ROUND();
|
||||
&pshufd ($c,$c,0b01001110);
|
||||
&pshufd ($b,$b,0b10010011);
|
||||
&pshufd ($d,$d,0b00111001);
|
||||
|
||||
&dec ("edx");
|
||||
&jnz (&label("loop1x"));
|
||||
|
||||
&paddd ($a,&QWP(16*0,"esp"));
|
||||
&paddd ($b,&QWP(16*1,"esp"));
|
||||
&paddd ($c,&QWP(16*2,"esp"));
|
||||
&paddd ($d,&QWP(16*3,"esp"));
|
||||
|
||||
&cmp ($len,64);
|
||||
&jb (&label("tail"));
|
||||
|
||||
&movdqu ($t,&QWP(16*0,$inp));
|
||||
&movdqu ($t1,&QWP(16*1,$inp));
|
||||
&pxor ($a,$t); # xor with input
|
||||
&movdqu ($t,&QWP(16*2,$inp));
|
||||
&pxor ($b,$t1);
|
||||
&movdqu ($t1,&QWP(16*3,$inp));
|
||||
&pxor ($c,$t);
|
||||
&pxor ($d,$t1);
|
||||
&lea ($inp,&DWP(16*4,$inp)); # inp+=64
|
||||
|
||||
&movdqu (&QWP(16*0,$out),$a); # write output
|
||||
&movdqu (&QWP(16*1,$out),$b);
|
||||
&movdqu (&QWP(16*2,$out),$c);
|
||||
&movdqu (&QWP(16*3,$out),$d);
|
||||
&lea ($out,&DWP(16*4,$out)); # inp+=64
|
||||
|
||||
&sub ($len,64);
|
||||
&jnz (&label("outer1x"));
|
||||
|
||||
&jmp (&label("done"));
|
||||
|
||||
&set_label("tail");
|
||||
&movdqa (&QWP(16*0,"esp"),$a);
|
||||
&movdqa (&QWP(16*1,"esp"),$b);
|
||||
&movdqa (&QWP(16*2,"esp"),$c);
|
||||
&movdqa (&QWP(16*3,"esp"),$d);
|
||||
|
||||
&xor ("eax","eax");
|
||||
&xor ("edx","edx");
|
||||
&xor ("ebp","ebp");
|
||||
|
||||
&set_label("tail_loop");
|
||||
&movb ("al",&BP(0,"esp","ebp"));
|
||||
&movb ("dl",&BP(0,$inp,"ebp"));
|
||||
&lea ("ebp",&DWP(1,"ebp"));
|
||||
&xor ("al","dl");
|
||||
&movb (&BP(-1,$out,"ebp"),"al");
|
||||
&dec ($len);
|
||||
&jnz (&label("tail_loop"));
|
||||
}
|
||||
&set_label("done");
|
||||
&mov ("esp",&DWP(512,"esp"));
|
||||
&function_end("ChaCha20_ssse3");
|
||||
|
||||
&align (64);
|
||||
&set_label("ssse3_data");
|
||||
&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd);
|
||||
&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe);
|
||||
&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574);
|
||||
&data_word(0,1,2,3);
|
||||
&data_word(4,4,4,4);
|
||||
&data_word(1,0,0,0);
|
||||
&data_word(4,0,0,0);
|
||||
&data_word(0,-1,-1,-1);
|
||||
&align (64);
|
||||
}
|
||||
&asciz ("ChaCha20 for x86, CRYPTOGAMS by <appro\@openssl.org>");
|
||||
|
||||
&asm_finish();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,49 +21,7 @@
|
||||
#include <openssl/cpu.h>
|
||||
|
||||
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
|
||||
((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && \
|
||||
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
|
||||
defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
|
||||
|
||||
/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */
|
||||
void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
const uint32_t key[8], const uint32_t counter[4]);
|
||||
|
||||
void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
const uint8_t key[32], const uint8_t nonce[12],
|
||||
uint32_t counter) {
|
||||
uint32_t counter_nonce[4];
|
||||
counter_nonce[0] = counter;
|
||||
counter_nonce[1] = U8TO32_LITTLE(nonce + 0);
|
||||
counter_nonce[2] = U8TO32_LITTLE(nonce + 4);
|
||||
counter_nonce[3] = U8TO32_LITTLE(nonce + 8);
|
||||
|
||||
const uint32_t *key_ptr = (const uint32_t *)key;
|
||||
#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
|
||||
/* The assembly expects the key to be four-byte aligned. */
|
||||
uint32_t key_u32[8];
|
||||
if ((((uintptr_t)key) & 3) != 0) {
|
||||
key_u32[0] = U8TO32_LITTLE(key + 0);
|
||||
key_u32[1] = U8TO32_LITTLE(key + 4);
|
||||
key_u32[2] = U8TO32_LITTLE(key + 8);
|
||||
key_u32[3] = U8TO32_LITTLE(key + 12);
|
||||
key_u32[4] = U8TO32_LITTLE(key + 16);
|
||||
key_u32[5] = U8TO32_LITTLE(key + 20);
|
||||
key_u32[6] = U8TO32_LITTLE(key + 24);
|
||||
key_u32[7] = U8TO32_LITTLE(key + 28);
|
||||
|
||||
key_ptr = key_u32;
|
||||
}
|
||||
#endif
|
||||
|
||||
ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
|
||||
}
|
||||
|
||||
#else
|
||||
#if defined(OPENSSL_WINDOWS) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || !defined(__SSE2__)
|
||||
|
||||
/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
|
||||
static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
|
||||
@@ -82,6 +40,10 @@ static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
|
||||
(p)[3] = (v >> 24) & 0xff; \
|
||||
}
|
||||
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
|
||||
((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
|
||||
|
||||
/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
|
||||
#define QUARTERROUND(a,b,c,d) \
|
||||
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
|
||||
@@ -89,6 +51,13 @@ static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
|
||||
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
|
||||
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
|
||||
|
||||
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
|
||||
/* Defined in chacha_vec.c */
|
||||
void CRYPTO_chacha_20_neon(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
const uint8_t key[32], const uint8_t nonce[12],
|
||||
uint32_t counter);
|
||||
#endif
|
||||
|
||||
/* chacha_core performs 20 rounds of ChaCha on the input words in
|
||||
* |input| and writes the 64 output bytes to |output|. */
|
||||
static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
|
||||
@@ -122,6 +91,13 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
uint8_t buf[64];
|
||||
size_t todo, i;
|
||||
|
||||
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
|
||||
if (CRYPTO_is_NEON_capable()) {
|
||||
CRYPTO_chacha_20_neon(out, in, in_len, key, nonce, counter);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
input[0] = U8TO32_LITTLE(sigma + 0);
|
||||
input[1] = U8TO32_LITTLE(sigma + 4);
|
||||
input[2] = U8TO32_LITTLE(sigma + 8);
|
||||
@@ -161,4 +137,4 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 && !OPENSSL_X86 || !__SSE2__ */
|
||||
@@ -1,257 +0,0 @@
|
||||
/* Copyright (c) 2016, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/chacha.h>
|
||||
|
||||
|
||||
static const uint8_t kKey[32] = {
|
||||
0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b,
|
||||
0xfb, 0xc9, 0x2a, 0x5a, 0x6a, 0xc7, 0x62, 0x50, 0x7c, 0xf9, 0x64,
|
||||
0x43, 0xbf, 0x33, 0xb9, 0x6b, 0x1b, 0xd4, 0xc6, 0xf8, 0xf6,
|
||||
};
|
||||
|
||||
static const uint8_t kNonce[12] = {
|
||||
0x44, 0xe7, 0x92, 0xd6, 0x33, 0x35, 0xab, 0xb1, 0x58, 0x2e, 0x92, 0x53,
|
||||
};
|
||||
|
||||
static uint32_t kCounter = 42;
|
||||
|
||||
static const uint8_t kInput[] = {
|
||||
0x58, 0x28, 0xd5, 0x30, 0x36, 0x2c, 0x60, 0x55, 0x29, 0xf8, 0xe1, 0x8c,
|
||||
0xae, 0x15, 0x15, 0x26, 0xf2, 0x3a, 0x73, 0xa0, 0xf3, 0x12, 0xa3, 0x88,
|
||||
0x5f, 0x2b, 0x74, 0x23, 0x3d, 0xc9, 0x05, 0x23, 0xc6, 0x54, 0x49, 0x1e,
|
||||
0x44, 0x88, 0x14, 0xd9, 0xda, 0x37, 0x15, 0xdc, 0xb7, 0xe4, 0x23, 0xb3,
|
||||
0x9d, 0x7e, 0x16, 0x68, 0x35, 0xfc, 0x02, 0x6d, 0xcc, 0x8a, 0xe5, 0xdd,
|
||||
0x5f, 0xe4, 0xd2, 0x56, 0x6f, 0x12, 0x9c, 0x9c, 0x7d, 0x6a, 0x38, 0x48,
|
||||
0xbd, 0xdf, 0xd9, 0xac, 0x1b, 0xa2, 0x4d, 0xc5, 0x43, 0x04, 0x3c, 0xd7,
|
||||
0x99, 0xe1, 0xa7, 0x13, 0x9c, 0x51, 0xc2, 0x6d, 0xf9, 0xcf, 0x07, 0x3b,
|
||||
0xe4, 0xbf, 0x93, 0xa3, 0xa9, 0xb4, 0xc5, 0xf0, 0x1a, 0xe4, 0x8d, 0x5f,
|
||||
0xc6, 0xc4, 0x7c, 0x69, 0x7a, 0xde, 0x1a, 0xc1, 0xc9, 0xcf, 0xc2, 0x4e,
|
||||
0x7a, 0x25, 0x2c, 0x32, 0xe9, 0x17, 0xba, 0x68, 0xf1, 0x37, 0x5d, 0x62,
|
||||
0x84, 0x46, 0xf5, 0x80, 0x7f, 0x1a, 0x71, 0xf7, 0xbe, 0x72, 0x4b, 0xb8,
|
||||
0x1c, 0xfe, 0x3e, 0xbd, 0xae, 0x0d, 0x73, 0x0d, 0x87, 0x4a, 0x31, 0xc3,
|
||||
0x3d, 0x46, 0x6f, 0xb3, 0xd7, 0x6b, 0xe3, 0xb8, 0x70, 0x17, 0x8e, 0x7a,
|
||||
0x6a, 0x0e, 0xbf, 0xa8, 0xbc, 0x2b, 0xdb, 0xfa, 0x4f, 0xb6, 0x26, 0x20,
|
||||
0xee, 0x63, 0xf0, 0x6d, 0x26, 0xac, 0x6a, 0x18, 0x37, 0x6e, 0x59, 0x81,
|
||||
0xd1, 0x60, 0xe6, 0x40, 0xd5, 0x6d, 0x68, 0xba, 0x8b, 0x65, 0x4a, 0xf9,
|
||||
0xf1, 0xae, 0x56, 0x24, 0x8f, 0xe3, 0x8e, 0xe7, 0x7e, 0x6f, 0xcf, 0x92,
|
||||
0xdf, 0xa9, 0x75, 0x3a, 0xd6, 0x2e, 0x1c, 0xaf, 0xf2, 0xd6, 0x8b, 0x39,
|
||||
0xad, 0xd2, 0x5d, 0xfb, 0xd7, 0xdf, 0x05, 0x57, 0x0d, 0xf7, 0xf6, 0x8f,
|
||||
0x2d, 0x14, 0xb0, 0x4e, 0x1a, 0x3c, 0x77, 0x04, 0xcd, 0x3c, 0x5c, 0x58,
|
||||
0x52, 0x10, 0x6f, 0xcf, 0x5c, 0x03, 0xc8, 0x5f, 0x85, 0x2b, 0x05, 0x82,
|
||||
0x60, 0xda, 0xcc, 0xcd, 0xd6, 0x88, 0xbf, 0xc0, 0x10, 0xb3, 0x6f, 0x54,
|
||||
0x54, 0x42, 0xbc, 0x4b, 0x77, 0x21, 0x4d, 0xee, 0x87, 0x45, 0x06, 0x4c,
|
||||
0x60, 0x38, 0xd2, 0x7e, 0x1d, 0x30, 0x6c, 0x55, 0xf0, 0x38, 0x80, 0x1c,
|
||||
0xde, 0x3d, 0xea, 0x68, 0x3e, 0xf6, 0x3e, 0x59, 0xcf, 0x0d, 0x08, 0xae,
|
||||
0x8c, 0x02, 0x0b, 0xc1, 0x72, 0x6a, 0xb4, 0x6d, 0xf3, 0xf7, 0xb3, 0xef,
|
||||
0x3a, 0xb1, 0x06, 0xf2, 0xf4, 0xd6, 0x69, 0x7b, 0x3e, 0xa2, 0x16, 0x31,
|
||||
0x31, 0x79, 0xb6, 0x33, 0xa9, 0xca, 0x8a, 0xa8, 0xbe, 0xf3, 0xe9, 0x38,
|
||||
0x28, 0xd1, 0xe1, 0x3b, 0x4e, 0x2e, 0x47, 0x35, 0xa4, 0x61, 0x14, 0x1e,
|
||||
0x42, 0x2c, 0x49, 0x55, 0xea, 0xe3, 0xb3, 0xce, 0x39, 0xd3, 0xb3, 0xef,
|
||||
0x4a, 0x4d, 0x78, 0x49, 0xbd, 0xf6, 0x7c, 0x0a, 0x2c, 0xd3, 0x26, 0xcb,
|
||||
0xd9, 0x6a, 0xad, 0x63, 0x93, 0xa7, 0x29, 0x92, 0xdc, 0x1f, 0xaf, 0x61,
|
||||
0x82, 0x80, 0x74, 0xb2, 0x9c, 0x4a, 0x86, 0x73, 0x50, 0xd8, 0xd1, 0xff,
|
||||
0xee, 0x1a, 0xe2, 0xdd, 0xa2, 0x61, 0xbd, 0x10, 0xc3, 0x5f, 0x67, 0x9f,
|
||||
0x29, 0xe4, 0xd3, 0x70, 0xe5, 0x67, 0x3a, 0xd2, 0x20, 0x00, 0xcc, 0x25,
|
||||
0x15, 0x96, 0x54, 0x45, 0x85, 0xed, 0x82, 0x88, 0x3b, 0x9f, 0x3b, 0xc3,
|
||||
0x04, 0xd4, 0x23, 0xb1, 0x0d, 0xdc, 0xc8, 0x26, 0x9d, 0x28, 0xb3, 0x25,
|
||||
0x4d, 0x52, 0xe5, 0x33, 0xf3, 0xed, 0x2c, 0xb8, 0x1a, 0xcf, 0xc3, 0x52,
|
||||
0xb4, 0x2f, 0xc7, 0x79, 0x96, 0x14, 0x7d, 0x72, 0x27, 0x72, 0x85, 0xea,
|
||||
0x6d, 0x41, 0xa0, 0x22, 0x13, 0x6d, 0x06, 0x83, 0xa4, 0xdd, 0x0f, 0x69,
|
||||
0xd2, 0x01, 0xcd, 0xc6, 0xb8, 0x64, 0x5c, 0x2c, 0x79, 0xd1, 0xc7, 0xd3,
|
||||
0x31, 0xdb, 0x2c, 0xff, 0xda, 0xd0, 0x69, 0x31, 0xad, 0x83, 0x5f, 0xed,
|
||||
0x6a, 0x97, 0xe4, 0x00, 0x43, 0xb0, 0x2e, 0x97, 0xae, 0x00, 0x5f, 0x5c,
|
||||
0xb9, 0xe8, 0x39, 0x80, 0x10, 0xca, 0x0c, 0xfa, 0xf0, 0xb5, 0xcd, 0xaa,
|
||||
0x27, 0x11, 0x60, 0xd9, 0x21, 0x86, 0x93, 0x91, 0x9f, 0x2d, 0x1a, 0x8e,
|
||||
0xde, 0x0b, 0xb5, 0xcb, 0x05, 0x24, 0x30, 0x45, 0x4d, 0x11, 0x75, 0xfd,
|
||||
0xe5, 0xa0, 0xa9, 0x4e, 0x3a, 0x8c, 0x3b, 0x52, 0x5a, 0x37, 0x18, 0x05,
|
||||
0x4a, 0x7a, 0x09, 0x6a, 0xe6, 0xd5, 0xa9, 0xa6, 0x71, 0x47, 0x4c, 0x50,
|
||||
0xe1, 0x3e, 0x8a, 0x21, 0x2b, 0x4f, 0x0e, 0xe3, 0xcb, 0x72, 0xc5, 0x28,
|
||||
0x3e, 0x5a, 0x33, 0xec, 0x48, 0x92, 0x2e, 0xa1, 0x24, 0x57, 0x09, 0x0f,
|
||||
0x01, 0x85, 0x3b, 0x34, 0x39, 0x7e, 0xc7, 0x90, 0x62, 0xe2, 0xdc, 0x5d,
|
||||
0x0a, 0x2c, 0x51, 0x26, 0x95, 0x3a, 0x95, 0x92, 0xa5, 0x39, 0x8f, 0x0c,
|
||||
0x83, 0x0b, 0x9d, 0x38, 0xab, 0x98, 0x2a, 0xc4, 0x01, 0xc4, 0x0d, 0x77,
|
||||
0x13, 0xcb, 0xca, 0xf1, 0x28, 0x31, 0x52, 0x75, 0x27, 0x2c, 0xf0, 0x04,
|
||||
0x86, 0xc8, 0xf3, 0x3d, 0xf2, 0x9d, 0x8f, 0x55, 0x52, 0x40, 0x3f, 0xaa,
|
||||
0x22, 0x7f, 0xe7, 0x69, 0x3b, 0xee, 0x44, 0x09, 0xde, 0xff, 0xb0, 0x69,
|
||||
0x3a, 0xae, 0x74, 0xe9, 0x9d, 0x33, 0xae, 0x8b, 0x6d, 0x60, 0x04, 0xff,
|
||||
0x53, 0x3f, 0x88, 0xe9, 0x63, 0x9b, 0xb1, 0x6d, 0x2c, 0x22, 0x15, 0x5a,
|
||||
0x15, 0xd9, 0xe5, 0xcb, 0x03, 0x78, 0x3c, 0xca, 0x59, 0x8c, 0xc8, 0xc2,
|
||||
0x86, 0xff, 0xd2, 0x79, 0xd6, 0xc6, 0xec, 0x5b, 0xbb, 0xa0, 0xae, 0x01,
|
||||
0x20, 0x09, 0x2e, 0x38, 0x5d, 0xda, 0x5d, 0xe0, 0x59, 0x4e, 0xe5, 0x8b,
|
||||
0x84, 0x8f, 0xb6, 0xe0, 0x56, 0x9f, 0x21, 0xa1, 0xcf, 0xb2, 0x0f, 0x2c,
|
||||
0x93, 0xf8, 0xcf, 0x37, 0xc1, 0x9f, 0x32, 0x98, 0x21, 0x65, 0x52, 0x66,
|
||||
0x6e, 0xd3, 0x71, 0x98, 0x55, 0xb9, 0x46, 0x9f, 0x1a, 0x35, 0xc4, 0x47,
|
||||
0x69, 0x62, 0x70, 0x4b, 0x77, 0x9e, 0xe4, 0x21, 0xe6, 0x32, 0x5a, 0x26,
|
||||
0x05, 0xba, 0x57, 0x53, 0xd7, 0x9b, 0x55, 0x3c, 0xbb, 0x53, 0x79, 0x60,
|
||||
0x9c, 0xc8, 0x4d, 0xf7, 0xf5, 0x1d, 0x54, 0x02, 0x91, 0x68, 0x0e, 0xaa,
|
||||
0xca, 0x5a, 0x78, 0x0c, 0x28, 0x9a, 0xc3, 0xac, 0x49, 0xc0, 0xf4, 0x85,
|
||||
0xee, 0x59, 0x76, 0x7e, 0x28, 0x4e, 0xf1, 0x5c, 0x63, 0xf7, 0xce, 0x0e,
|
||||
0x2c, 0x21, 0xa0, 0x58, 0xe9, 0x01, 0xfd, 0xeb, 0xd1, 0xaf, 0xe6, 0xef,
|
||||
0x93, 0xb3, 0x95, 0x51, 0x60, 0xa2, 0x74, 0x40, 0x15, 0xe5, 0xf4, 0x0a,
|
||||
0xca, 0x6d, 0x9a, 0x37, 0x42, 0x4d, 0x5a, 0x58, 0x49, 0x0f, 0xe9, 0x02,
|
||||
0xfc, 0x77, 0xd8, 0x59, 0xde, 0xdd, 0xad, 0x4b, 0x99, 0x2e, 0x64, 0x73,
|
||||
0xad, 0x42, 0x2f, 0xf3, 0x2c, 0x0d, 0x49, 0xe4, 0x2e, 0x6c, 0xa4, 0x73,
|
||||
0x75, 0x18, 0x14, 0x85, 0xbb, 0x64, 0xb4, 0xa1, 0xb0, 0x6e, 0x01, 0xc0,
|
||||
0xcf, 0x17, 0x9c, 0xc5, 0x28, 0xc3, 0x2d, 0x6c, 0x17, 0x2a, 0x3d, 0x06,
|
||||
0x5c, 0xf3, 0xb4, 0x49, 0x75, 0xad, 0x17, 0x69, 0xd4, 0xca, 0x65, 0xae,
|
||||
0x44, 0x71, 0xa5, 0xf6, 0x0d, 0x0f, 0x8e, 0x37, 0xc7, 0x43, 0xce, 0x6b,
|
||||
0x08, 0xe9, 0xd1, 0x34, 0x48, 0x8f, 0xc9, 0xfc, 0xf3, 0x5d, 0x2d, 0xec,
|
||||
0x62, 0xd3, 0xf0, 0xb3, 0xfe, 0x2e, 0x40, 0x55, 0x76, 0x54, 0xc7, 0xb4,
|
||||
0x61, 0x16, 0xcc, 0x7c, 0x1c, 0x19, 0x24, 0xe6, 0x4d, 0xd4, 0xc3, 0x77,
|
||||
0x67, 0x1f, 0x3c, 0x74, 0x79, 0xa1, 0xf8, 0x85, 0x88, 0x1d, 0x6f, 0xa4,
|
||||
0x7e, 0x2c, 0x21, 0x9f, 0x49, 0xf5, 0xaa, 0x4e, 0xf3, 0x4a, 0xfa, 0x9d,
|
||||
0xbe, 0xf6, 0xce, 0xda, 0xb5, 0xab, 0x39, 0xbd, 0x16, 0x41, 0xa9, 0x4a,
|
||||
0xac, 0x09, 0x01, 0xca,
|
||||
};
|
||||
static const uint8_t kOutput[] = {
|
||||
0x54, 0x30, 0x6a, 0x13, 0xda, 0x59, 0x6b, 0x6d, 0x59, 0x49, 0xc8, 0xc5,
|
||||
0xab, 0x26, 0xd4, 0x8a, 0xad, 0xc0, 0x3d, 0xaf, 0x14, 0xb9, 0x15, 0xb8,
|
||||
0xca, 0xdf, 0x17, 0xa7, 0x03, 0xd3, 0xc5, 0x06, 0x01, 0xef, 0x21, 0xdd,
|
||||
0xa3, 0x0b, 0x9e, 0x48, 0xb8, 0x5e, 0x0b, 0x87, 0x9f, 0x95, 0x23, 0x68,
|
||||
0x85, 0x69, 0xd2, 0x5d, 0xaf, 0x57, 0xe9, 0x27, 0x11, 0x3d, 0x49, 0xfa,
|
||||
0xf1, 0x08, 0xcc, 0x15, 0xec, 0x1d, 0x19, 0x16, 0x12, 0x9b, 0xc8, 0x66,
|
||||
0x1f, 0xfa, 0x2c, 0x93, 0xf4, 0x99, 0x11, 0x27, 0x31, 0x0e, 0xd8, 0x46,
|
||||
0x47, 0x40, 0x11, 0x70, 0x01, 0xca, 0xe8, 0x5b, 0xc5, 0x91, 0xc8, 0x3a,
|
||||
0xdc, 0xaa, 0xf3, 0x4b, 0x80, 0xe5, 0xbc, 0x03, 0xd0, 0x89, 0x72, 0xbc,
|
||||
0xce, 0x2a, 0x76, 0x0c, 0xf5, 0xda, 0x4c, 0x10, 0x06, 0x35, 0x41, 0xb1,
|
||||
0xe6, 0xb4, 0xaa, 0x7a, 0xef, 0xf0, 0x62, 0x4a, 0xc5, 0x9f, 0x2c, 0xaf,
|
||||
0xb8, 0x2f, 0xd9, 0xd1, 0x01, 0x7a, 0x36, 0x2f, 0x3e, 0x83, 0xa5, 0xeb,
|
||||
0x81, 0x70, 0xa0, 0x57, 0x17, 0x46, 0xea, 0x9e, 0xcb, 0x0e, 0x74, 0xd3,
|
||||
0x44, 0x57, 0x1d, 0x40, 0x06, 0xf8, 0xb7, 0xcb, 0x5f, 0xf4, 0x79, 0xbd,
|
||||
0x11, 0x19, 0xd6, 0xee, 0xf8, 0xb0, 0xaa, 0xdd, 0x00, 0x62, 0xad, 0x3b,
|
||||
0x88, 0x9a, 0x88, 0x5b, 0x1b, 0x07, 0xc9, 0xae, 0x9e, 0xa6, 0x94, 0xe5,
|
||||
0x55, 0xdb, 0x45, 0x23, 0xb9, 0x2c, 0xcd, 0x29, 0xd3, 0x54, 0xc3, 0x88,
|
||||
0x1e, 0x5f, 0x52, 0xf2, 0x09, 0x00, 0x26, 0x26, 0x1a, 0xed, 0xf5, 0xc2,
|
||||
0xa9, 0x7d, 0xf9, 0x21, 0x5a, 0xaf, 0x6d, 0xab, 0x8e, 0x16, 0x84, 0x96,
|
||||
0xb5, 0x4f, 0xcf, 0x1e, 0xa3, 0xaf, 0x08, 0x9f, 0x79, 0x86, 0xc3, 0xbe,
|
||||
0x0c, 0x70, 0xcb, 0x8f, 0xf3, 0xc5, 0xf8, 0xe8, 0x4b, 0x21, 0x7d, 0x18,
|
||||
0xa9, 0xed, 0x8b, 0xfb, 0x6b, 0x5a, 0x6f, 0x26, 0x0b, 0x56, 0x04, 0x7c,
|
||||
0xfe, 0x0e, 0x1e, 0xc1, 0x3f, 0x82, 0xc5, 0x73, 0xbd, 0x53, 0x0c, 0xf0,
|
||||
0xe2, 0xc9, 0xf3, 0x3d, 0x1b, 0x6d, 0xba, 0x70, 0xc1, 0x6d, 0xb6, 0x00,
|
||||
0x28, 0xe1, 0xc4, 0x78, 0x62, 0x04, 0xda, 0x23, 0x86, 0xc3, 0xda, 0x74,
|
||||
0x3d, 0x7c, 0xd6, 0x76, 0x29, 0xb2, 0x27, 0x2e, 0xb2, 0x35, 0x42, 0x60,
|
||||
0x82, 0xcf, 0x30, 0x2c, 0x59, 0xe4, 0xe3, 0xd0, 0x74, 0x1f, 0x58, 0xe8,
|
||||
0xda, 0x47, 0x45, 0x73, 0x1c, 0x05, 0x93, 0xae, 0x75, 0xbe, 0x1f, 0x81,
|
||||
0xd8, 0xb7, 0xb3, 0xff, 0xfc, 0x8b, 0x52, 0x9e, 0xed, 0x8b, 0x37, 0x9f,
|
||||
0xe0, 0xb8, 0xa2, 0x66, 0xe1, 0x6a, 0xc5, 0x1f, 0x1d, 0xf0, 0xde, 0x3f,
|
||||
0x3d, 0xb0, 0x28, 0xf3, 0xaa, 0x4e, 0x4d, 0x31, 0xb0, 0x26, 0x79, 0x2b,
|
||||
0x08, 0x0f, 0xe9, 0x2f, 0x79, 0xb3, 0xc8, 0xdd, 0xa7, 0x89, 0xa8, 0xa8,
|
||||
0x1d, 0x59, 0x0e, 0x4f, 0x1e, 0x93, 0x1f, 0x70, 0x7f, 0x4e, 0x7e, 0xfe,
|
||||
0xb8, 0xca, 0x63, 0xe0, 0xa6, 0x05, 0xcc, 0xd7, 0xde, 0x2a, 0x49, 0x31,
|
||||
0x78, 0x5c, 0x5f, 0x44, 0xb2, 0x9b, 0x91, 0x99, 0x14, 0x29, 0x63, 0x09,
|
||||
0x12, 0xdd, 0x02, 0xd9, 0x7b, 0xe9, 0xf5, 0x12, 0x07, 0xd0, 0xe7, 0xe6,
|
||||
0xe8, 0xdd, 0xda, 0xa4, 0x73, 0xc4, 0x8e, 0xbd, 0x7b, 0xb7, 0xbb, 0xcb,
|
||||
0x83, 0x2f, 0x43, 0xf6, 0x1c, 0x50, 0xae, 0x9b, 0x2e, 0x52, 0x80, 0x18,
|
||||
0x85, 0xa8, 0x23, 0x52, 0x7a, 0x6a, 0xf7, 0x42, 0x36, 0xca, 0x91, 0x5a,
|
||||
0x3d, 0x2a, 0xa0, 0x35, 0x7d, 0x70, 0xfc, 0x4c, 0x18, 0x7c, 0x57, 0x72,
|
||||
0xcf, 0x9b, 0x29, 0xd6, 0xd0, 0xb4, 0xd7, 0xe6, 0x89, 0x70, 0x69, 0x22,
|
||||
0x5e, 0x45, 0x09, 0x4d, 0x49, 0x87, 0x84, 0x5f, 0x8a, 0x5f, 0xe4, 0x15,
|
||||
0xd3, 0xe3, 0x72, 0xaf, 0xb2, 0x30, 0x9c, 0xc1, 0xff, 0x8e, 0x6d, 0x2a,
|
||||
0x76, 0x9e, 0x08, 0x03, 0x7e, 0xe0, 0xc3, 0xc2, 0x97, 0x06, 0x6b, 0x33,
|
||||
0x2b, 0x08, 0xe3, 0xd5, 0x0b, 0xd8, 0x32, 0x67, 0x61, 0x10, 0xed, 0x6b,
|
||||
0xed, 0x50, 0xef, 0xd7, 0x1c, 0x1b, 0xe0, 0x6d, 0xa1, 0x64, 0x19, 0x34,
|
||||
0x2f, 0xe4, 0xe8, 0x54, 0xbf, 0x84, 0x0e, 0xdf, 0x0e, 0x8b, 0xd8, 0xdd,
|
||||
0x77, 0x96, 0xb8, 0x54, 0xab, 0xf2, 0x95, 0x59, 0x0d, 0x0d, 0x0a, 0x15,
|
||||
0x6e, 0x01, 0xf2, 0x24, 0xab, 0xa0, 0xd8, 0xdf, 0x38, 0xea, 0x97, 0x58,
|
||||
0x76, 0x88, 0xbe, 0xaf, 0x45, 0xe3, 0x56, 0x4f, 0x68, 0xe8, 0x4b, 0xe7,
|
||||
0x2b, 0x22, 0x18, 0x96, 0x82, 0x89, 0x25, 0x34, 0xd1, 0xdd, 0x08, 0xea,
|
||||
0x7e, 0x21, 0xef, 0x57, 0x55, 0x43, 0xf7, 0xfa, 0xca, 0x1c, 0xde, 0x99,
|
||||
0x2e, 0x8b, 0xd8, 0xc3, 0xcf, 0x89, 0x4d, 0xfc, 0x3b, 0x7d, 0x4a, 0xc9,
|
||||
0x99, 0xc4, 0x31, 0xb6, 0x7a, 0xae, 0xf8, 0x49, 0xb2, 0x46, 0xc1, 0x60,
|
||||
0x05, 0x75, 0xf3, 0x3d, 0xf2, 0xc9, 0x84, 0xa4, 0xb9, 0x8a, 0x87, 0x2a,
|
||||
0x87, 0x5c, 0x0a, 0xbc, 0x51, 0x7d, 0x9a, 0xf5, 0xc9, 0x24, 0x2d, 0x5e,
|
||||
0xe6, 0xc6, 0xe3, 0xcd, 0x7e, 0xe4, 0xaf, 0x8a, 0x6c, 0x00, 0x04, 0xc8,
|
||||
0xd7, 0xa5, 0xad, 0xfa, 0xb2, 0x08, 0x4a, 0x26, 0x9b, 0x7c, 0xd0, 0xc6,
|
||||
0x13, 0xb1, 0xb9, 0x65, 0x3f, 0x70, 0x30, 0xf9, 0x98, 0x9d, 0x87, 0x99,
|
||||
0x57, 0x71, 0x3e, 0xb1, 0xc3, 0x24, 0xf0, 0xa6, 0xa2, 0x60, 0x9d, 0x66,
|
||||
0xd2, 0x5f, 0xae, 0xe3, 0x94, 0x87, 0xea, 0xd1, 0xea, 0x0d, 0x2a, 0x77,
|
||||
0xef, 0x31, 0xcc, 0xeb, 0xf9, 0x0c, 0xdc, 0x9c, 0x12, 0x80, 0xbb, 0xb0,
|
||||
0x8e, 0xab, 0x9a, 0x04, 0xcd, 0x4b, 0x95, 0x4f, 0x7a, 0x0b, 0x53, 0x7c,
|
||||
0x16, 0xcc, 0x0e, 0xb1, 0x73, 0x10, 0xdd, 0xaa, 0x76, 0x94, 0x90, 0xd9,
|
||||
0x8b, 0x66, 0x41, 0x31, 0xed, 0x8c, 0x7d, 0x74, 0xc4, 0x33, 0xfa, 0xc3,
|
||||
0x43, 0x8d, 0x10, 0xbc, 0x84, 0x4d, 0x0e, 0x95, 0x32, 0xdf, 0x17, 0x43,
|
||||
0x6d, 0xd2, 0x5e, 0x12, 0xb9, 0xed, 0x33, 0xd9, 0x97, 0x6f, 0x4a, 0xcd,
|
||||
0xc3, 0xcd, 0x81, 0x34, 0xbe, 0x7e, 0xa2, 0xd0, 0xa7, 0x91, 0x5d, 0x90,
|
||||
0xf6, 0x5e, 0x4a, 0x25, 0x0f, 0xcc, 0x24, 0xeb, 0xe1, 0xe4, 0x62, 0x6c,
|
||||
0x8f, 0x45, 0x36, 0x97, 0x5d, 0xda, 0x20, 0x2b, 0x86, 0x00, 0x8c, 0x94,
|
||||
0xa9, 0x6a, 0x69, 0xb2, 0xe9, 0xbb, 0x82, 0x8e, 0x41, 0x95, 0xb4, 0xb7,
|
||||
0xf1, 0x55, 0x52, 0x30, 0x39, 0x48, 0xb3, 0x25, 0x82, 0xa9, 0x10, 0x27,
|
||||
0x89, 0xb5, 0xe5, 0x1f, 0xab, 0x72, 0x3c, 0x70, 0x08, 0xce, 0xe6, 0x61,
|
||||
0xbf, 0x19, 0xc8, 0x90, 0x2b, 0x29, 0x30, 0x3e, 0xb8, 0x4c, 0x33, 0xf0,
|
||||
0xf0, 0x15, 0x2e, 0xb7, 0x25, 0xca, 0x99, 0x4b, 0x6f, 0x4b, 0x41, 0x50,
|
||||
0xee, 0x56, 0x99, 0xcf, 0x2b, 0xa4, 0xc4, 0x7c, 0x5c, 0xa6, 0xd4, 0x67,
|
||||
0x04, 0x5c, 0x5d, 0x5f, 0x26, 0x9e, 0x0f, 0xe2, 0x58, 0x68, 0x4c, 0x30,
|
||||
0xcd, 0xef, 0x46, 0xdb, 0x37, 0x6f, 0xbb, 0xc4, 0x80, 0xca, 0x8a, 0x54,
|
||||
0x5d, 0x71, 0x9d, 0x0c, 0xe8, 0xb8, 0x2c, 0x10, 0x90, 0x44, 0xa4, 0x88,
|
||||
0x3f, 0xbc, 0x15, 0x3c, 0xd2, 0xca, 0x0e, 0xc3, 0xe4, 0x6e, 0xef, 0xb0,
|
||||
0xcb, 0xfd, 0x61, 0x7c, 0x27, 0xf2, 0x25, 0xea, 0x71, 0x6d, 0xf7, 0x49,
|
||||
0x9c, 0x81, 0x27, 0xf0, 0x61, 0x33, 0xcf, 0x55, 0x68, 0xd3, 0x73, 0xa4,
|
||||
0xed, 0x35, 0x65, 0x2a, 0xf2, 0x3e, 0xcf, 0x90, 0x98, 0x54, 0x6d, 0x95,
|
||||
0x6a, 0x0c, 0x9c, 0x24, 0x0e, 0xb4, 0xb7, 0x9b, 0x8d, 0x6e, 0x1c, 0xbc,
|
||||
0xeb, 0x17, 0x10, 0x86, 0xda, 0x91, 0x6d, 0x89, 0x4c, 0xeb, 0xf5, 0x50,
|
||||
0x8f, 0x40, 0xcf, 0x4a,
|
||||
};
|
||||
|
||||
static_assert(sizeof(kInput) == sizeof(kOutput),
|
||||
"Input and output lengths don't match.");
|
||||
|
||||
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 %u.\n", static_cast<unsigned>(len));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place at various offsets.
|
||||
static const size_t kOffsets[] = {
|
||||
0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
|
||||
64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
|
||||
};
|
||||
for (size_t offset : kOffsets) {
|
||||
buf.reset(new uint8_t[len + offset]);
|
||||
memcpy(buf.get() + offset, kInput, len);
|
||||
CRYPTO_chacha_20(buf.get(), buf.get() + offset, len, kKey, kNonce,
|
||||
kCounter);
|
||||
if (memcmp(buf.get(), kOutput, len) != 0) {
|
||||
fprintf(stderr, "Mismatch at length %u with in-place offset %u.\n",
|
||||
static_cast<unsigned>(len), static_cast<unsigned>(offset));
|
||||
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++) {
|
||||
if (!TestChaCha20(len)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
/* ====================================================================
|
||||
*
|
||||
* When updating this file, also update chacha_vec_arm.S
|
||||
*
|
||||
* ==================================================================== */
|
||||
|
||||
|
||||
/* This implementation is by Ted Krovetz and was submitted to SUPERCOP and
|
||||
* marked as public domain. It was been altered to allow for non-aligned inputs
|
||||
* and to allow the block counter to be passed in specifically. */
|
||||
|
||||
#include <openssl/chacha.h>
|
||||
|
||||
#if defined(ASM_GEN) || \
|
||||
!defined(OPENSSL_WINDOWS) && \
|
||||
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
|
||||
|
||||
#define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */
|
||||
|
||||
/* Architecture-neutral way to specify 16-byte vector of ints */
|
||||
typedef unsigned vec __attribute__((vector_size(16)));
|
||||
|
||||
/* This implementation is designed for Neon, SSE and AltiVec machines. The
|
||||
* following specify how to do certain vector operations efficiently on
|
||||
* each architecture, using intrinsics.
|
||||
* This implementation supports parallel processing of multiple blocks,
|
||||
* including potentially using general-purpose registers. */
|
||||
#if __ARM_NEON__
|
||||
#include <string.h>
|
||||
#include <arm_neon.h>
|
||||
#define GPR_TOO 1
|
||||
#define VBPI 2
|
||||
#define ONE (vec) vsetq_lane_u32(1, vdupq_n_u32(0), 0)
|
||||
#define LOAD_ALIGNED(m) (vec)(*((vec *)(m)))
|
||||
#define LOAD(m) ({ \
|
||||
memcpy(alignment_buffer, m, 16); \
|
||||
LOAD_ALIGNED(alignment_buffer); \
|
||||
})
|
||||
#define STORE(m, r) ({ \
|
||||
(*((vec *)(alignment_buffer))) = (r); \
|
||||
memcpy(m, alignment_buffer, 16); \
|
||||
})
|
||||
#define ROTV1(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 1)
|
||||
#define ROTV2(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 2)
|
||||
#define ROTV3(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 3)
|
||||
#define ROTW16(x) (vec) vrev32q_u16((uint16x8_t)x)
|
||||
#if __clang__
|
||||
#define ROTW7(x) (x << ((vec) {7, 7, 7, 7})) ^ (x >> ((vec) {25, 25, 25, 25}))
|
||||
#define ROTW8(x) (x << ((vec) {8, 8, 8, 8})) ^ (x >> ((vec) {24, 24, 24, 24}))
|
||||
#define ROTW12(x) \
|
||||
(x << ((vec) {12, 12, 12, 12})) ^ (x >> ((vec) {20, 20, 20, 20}))
|
||||
#else
|
||||
#define ROTW7(x) \
|
||||
(vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 7), (uint32x4_t)x, 25)
|
||||
#define ROTW8(x) \
|
||||
(vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 8), (uint32x4_t)x, 24)
|
||||
#define ROTW12(x) \
|
||||
(vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 12), (uint32x4_t)x, 20)
|
||||
#endif
|
||||
#elif __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#define GPR_TOO 0
|
||||
#if __clang__
|
||||
#define VBPI 4
|
||||
#else
|
||||
#define VBPI 3
|
||||
#endif
|
||||
#define ONE (vec) _mm_set_epi32(0, 0, 0, 1)
|
||||
#define LOAD(m) (vec) _mm_loadu_si128((__m128i *)(m))
|
||||
#define LOAD_ALIGNED(m) (vec) _mm_load_si128((__m128i *)(m))
|
||||
#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r))
|
||||
#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1))
|
||||
#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2))
|
||||
#define ROTV3(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(2, 1, 0, 3))
|
||||
#define ROTW7(x) \
|
||||
(vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x, 25))
|
||||
#define ROTW12(x) \
|
||||
(vec)(_mm_slli_epi32((__m128i)x, 12) ^ _mm_srli_epi32((__m128i)x, 20))
|
||||
#if __SSSE3__
|
||||
#include <tmmintrin.h>
|
||||
#define ROTW8(x) \
|
||||
(vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, \
|
||||
11, 6, 5, 4, 7, 2, 1, 0, 3))
|
||||
#define ROTW16(x) \
|
||||
(vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, \
|
||||
10, 5, 4, 7, 6, 1, 0, 3, 2))
|
||||
#else
|
||||
#define ROTW8(x) \
|
||||
(vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x, 24))
|
||||
#define ROTW16(x) \
|
||||
(vec)(_mm_slli_epi32((__m128i)x, 16) ^ _mm_srli_epi32((__m128i)x, 16))
|
||||
#endif
|
||||
#else
|
||||
#error-- Implementation supports only machines with neon or SSE2
|
||||
#endif
|
||||
|
||||
#ifndef REVV_BE
|
||||
#define REVV_BE(x) (x)
|
||||
#endif
|
||||
|
||||
#ifndef REVW_BE
|
||||
#define REVW_BE(x) (x)
|
||||
#endif
|
||||
|
||||
#define BPI (VBPI + GPR_TOO) /* Blocks computed per loop iteration */
|
||||
|
||||
#define DQROUND_VECTORS(a,b,c,d) \
|
||||
a += b; d ^= a; d = ROTW16(d); \
|
||||
c += d; b ^= c; b = ROTW12(b); \
|
||||
a += b; d ^= a; d = ROTW8(d); \
|
||||
c += d; b ^= c; b = ROTW7(b); \
|
||||
b = ROTV1(b); c = ROTV2(c); d = ROTV3(d); \
|
||||
a += b; d ^= a; d = ROTW16(d); \
|
||||
c += d; b ^= c; b = ROTW12(b); \
|
||||
a += b; d ^= a; d = ROTW8(d); \
|
||||
c += d; b ^= c; b = ROTW7(b); \
|
||||
b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
|
||||
|
||||
#define QROUND_WORDS(a,b,c,d) \
|
||||
a = a+b; d ^= a; d = d<<16 | d>>16; \
|
||||
c = c+d; b ^= c; b = b<<12 | b>>20; \
|
||||
a = a+b; d ^= a; d = d<< 8 | d>>24; \
|
||||
c = c+d; b ^= c; b = b<< 7 | b>>25;
|
||||
|
||||
#define WRITE_XOR(in, op, d, v0, v1, v2, v3) \
|
||||
STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0)); \
|
||||
STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1)); \
|
||||
STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2)); \
|
||||
STORE(op + d +12, LOAD(in + d +12) ^ REVV_BE(v3));
|
||||
|
||||
#if __ARM_NEON__
|
||||
/* For ARM, we can't depend on NEON support, so this function is compiled with
|
||||
* a different name, along with the generic code, and can be enabled at
|
||||
* run-time. */
|
||||
void CRYPTO_chacha_20_neon(
|
||||
#else
|
||||
void CRYPTO_chacha_20(
|
||||
#endif
|
||||
uint8_t *out,
|
||||
const uint8_t *in,
|
||||
size_t inlen,
|
||||
const uint8_t key[32],
|
||||
const uint8_t nonce[12],
|
||||
uint32_t counter)
|
||||
{
|
||||
unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
|
||||
#if defined(__ARM_NEON__)
|
||||
uint32_t np[3];
|
||||
uint8_t alignment_buffer[16] __attribute__((aligned(16)));
|
||||
#endif
|
||||
vec s0, s1, s2, s3;
|
||||
__attribute__ ((aligned (16))) unsigned chacha_const[] =
|
||||
{0x61707865,0x3320646E,0x79622D32,0x6B206574};
|
||||
kp = (unsigned *)key;
|
||||
#if defined(__ARM_NEON__)
|
||||
memcpy(np, nonce, 12);
|
||||
#endif
|
||||
s0 = LOAD_ALIGNED(chacha_const);
|
||||
s1 = LOAD(&((vec*)kp)[0]);
|
||||
s2 = LOAD(&((vec*)kp)[1]);
|
||||
s3 = (vec){
|
||||
counter,
|
||||
((uint32_t*)nonce)[0],
|
||||
((uint32_t*)nonce)[1],
|
||||
((uint32_t*)nonce)[2]
|
||||
};
|
||||
|
||||
for (iters = 0; iters < inlen/(BPI*64); iters++)
|
||||
{
|
||||
#if GPR_TOO
|
||||
register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8,
|
||||
x9, x10, x11, x12, x13, x14, x15;
|
||||
#endif
|
||||
#if VBPI > 2
|
||||
vec v8,v9,v10,v11;
|
||||
#endif
|
||||
#if VBPI > 3
|
||||
vec v12,v13,v14,v15;
|
||||
#endif
|
||||
|
||||
vec v0,v1,v2,v3,v4,v5,v6,v7;
|
||||
v4 = v0 = s0; v5 = v1 = s1; v6 = v2 = s2; v3 = s3;
|
||||
v7 = v3 + ONE;
|
||||
#if VBPI > 2
|
||||
v8 = v4; v9 = v5; v10 = v6;
|
||||
v11 = v7 + ONE;
|
||||
#endif
|
||||
#if VBPI > 3
|
||||
v12 = v8; v13 = v9; v14 = v10;
|
||||
v15 = v11 + ONE;
|
||||
#endif
|
||||
#if GPR_TOO
|
||||
x0 = chacha_const[0]; x1 = chacha_const[1];
|
||||
x2 = chacha_const[2]; x3 = chacha_const[3];
|
||||
x4 = kp[0]; x5 = kp[1]; x6 = kp[2]; x7 = kp[3];
|
||||
x8 = kp[4]; x9 = kp[5]; x10 = kp[6]; x11 = kp[7];
|
||||
x12 = counter+BPI*iters+(BPI-1); x13 = np[0];
|
||||
x14 = np[1]; x15 = np[2];
|
||||
#endif
|
||||
for (i = CHACHA_RNDS/2; i; i--)
|
||||
{
|
||||
DQROUND_VECTORS(v0,v1,v2,v3)
|
||||
DQROUND_VECTORS(v4,v5,v6,v7)
|
||||
#if VBPI > 2
|
||||
DQROUND_VECTORS(v8,v9,v10,v11)
|
||||
#endif
|
||||
#if VBPI > 3
|
||||
DQROUND_VECTORS(v12,v13,v14,v15)
|
||||
#endif
|
||||
#if GPR_TOO
|
||||
QROUND_WORDS( x0, x4, x8,x12)
|
||||
QROUND_WORDS( x1, x5, x9,x13)
|
||||
QROUND_WORDS( x2, x6,x10,x14)
|
||||
QROUND_WORDS( x3, x7,x11,x15)
|
||||
QROUND_WORDS( x0, x5,x10,x15)
|
||||
QROUND_WORDS( x1, x6,x11,x12)
|
||||
QROUND_WORDS( x2, x7, x8,x13)
|
||||
QROUND_WORDS( x3, x4, x9,x14)
|
||||
#endif
|
||||
}
|
||||
|
||||
WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
|
||||
s3 += ONE;
|
||||
WRITE_XOR(ip, op, 16, v4+s0, v5+s1, v6+s2, v7+s3)
|
||||
s3 += ONE;
|
||||
#if VBPI > 2
|
||||
WRITE_XOR(ip, op, 32, v8+s0, v9+s1, v10+s2, v11+s3)
|
||||
s3 += ONE;
|
||||
#endif
|
||||
#if VBPI > 3
|
||||
WRITE_XOR(ip, op, 48, v12+s0, v13+s1, v14+s2, v15+s3)
|
||||
s3 += ONE;
|
||||
#endif
|
||||
ip += VBPI*16;
|
||||
op += VBPI*16;
|
||||
#if GPR_TOO
|
||||
op[0] = REVW_BE(REVW_BE(ip[0]) ^ (x0 + chacha_const[0]));
|
||||
op[1] = REVW_BE(REVW_BE(ip[1]) ^ (x1 + chacha_const[1]));
|
||||
op[2] = REVW_BE(REVW_BE(ip[2]) ^ (x2 + chacha_const[2]));
|
||||
op[3] = REVW_BE(REVW_BE(ip[3]) ^ (x3 + chacha_const[3]));
|
||||
op[4] = REVW_BE(REVW_BE(ip[4]) ^ (x4 + kp[0]));
|
||||
op[5] = REVW_BE(REVW_BE(ip[5]) ^ (x5 + kp[1]));
|
||||
op[6] = REVW_BE(REVW_BE(ip[6]) ^ (x6 + kp[2]));
|
||||
op[7] = REVW_BE(REVW_BE(ip[7]) ^ (x7 + kp[3]));
|
||||
op[8] = REVW_BE(REVW_BE(ip[8]) ^ (x8 + kp[4]));
|
||||
op[9] = REVW_BE(REVW_BE(ip[9]) ^ (x9 + kp[5]));
|
||||
op[10] = REVW_BE(REVW_BE(ip[10]) ^ (x10 + kp[6]));
|
||||
op[11] = REVW_BE(REVW_BE(ip[11]) ^ (x11 + kp[7]));
|
||||
op[12] = REVW_BE(REVW_BE(ip[12]) ^ (x12 + counter+BPI*iters+(BPI-1)));
|
||||
op[13] = REVW_BE(REVW_BE(ip[13]) ^ (x13 + np[0]));
|
||||
op[14] = REVW_BE(REVW_BE(ip[14]) ^ (x14 + np[1]));
|
||||
op[15] = REVW_BE(REVW_BE(ip[15]) ^ (x15 + np[2]));
|
||||
s3 += ONE;
|
||||
ip += 16;
|
||||
op += 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (iters = inlen%(BPI*64)/64; iters != 0; iters--)
|
||||
{
|
||||
vec v0 = s0, v1 = s1, v2 = s2, v3 = s3;
|
||||
for (i = CHACHA_RNDS/2; i; i--)
|
||||
{
|
||||
DQROUND_VECTORS(v0,v1,v2,v3);
|
||||
}
|
||||
WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
|
||||
s3 += ONE;
|
||||
ip += 16;
|
||||
op += 16;
|
||||
}
|
||||
|
||||
inlen = inlen % 64;
|
||||
if (inlen)
|
||||
{
|
||||
__attribute__ ((aligned (16))) vec buf[4];
|
||||
vec v0,v1,v2,v3;
|
||||
v0 = s0; v1 = s1; v2 = s2; v3 = s3;
|
||||
for (i = CHACHA_RNDS/2; i; i--)
|
||||
{
|
||||
DQROUND_VECTORS(v0,v1,v2,v3);
|
||||
}
|
||||
|
||||
if (inlen >= 16)
|
||||
{
|
||||
STORE(op + 0, LOAD(ip + 0) ^ REVV_BE(v0 + s0));
|
||||
if (inlen >= 32)
|
||||
{
|
||||
STORE(op + 4, LOAD(ip + 4) ^ REVV_BE(v1 + s1));
|
||||
if (inlen >= 48)
|
||||
{
|
||||
STORE(op + 8, LOAD(ip + 8) ^
|
||||
REVV_BE(v2 + s2));
|
||||
buf[3] = REVV_BE(v3 + s3);
|
||||
}
|
||||
else
|
||||
buf[2] = REVV_BE(v2 + s2);
|
||||
}
|
||||
else
|
||||
buf[1] = REVV_BE(v1 + s1);
|
||||
}
|
||||
else
|
||||
buf[0] = REVV_BE(v0 + s0);
|
||||
|
||||
for (i=inlen & ~15; i<inlen; i++)
|
||||
((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ASM_GEN || !OPENSSL_WINDOWS && (OPENSSL_X86_64 || OPENSSL_X86) && SSE2 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2014, Google Inc.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
// This package generates chacha_vec_arm.S from chacha_vec.c. Install the
|
||||
// arm-linux-gnueabihf-gcc compiler as described in BUILDING.md. Then:
|
||||
// `(cd crypto/chacha && go run chacha_vec_arm_generate.go)`.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const defaultCompiler = "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
|
||||
|
||||
func main() {
|
||||
compiler := defaultCompiler
|
||||
if len(os.Args) > 1 {
|
||||
compiler = os.Args[1]
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-O3",
|
||||
"-mcpu=cortex-a8",
|
||||
"-mfpu=neon",
|
||||
"-fpic",
|
||||
"-DASM_GEN",
|
||||
"-I", "../../include",
|
||||
"-S", "chacha_vec.c",
|
||||
"-o", "-",
|
||||
}
|
||||
|
||||
output, err := os.OpenFile("chacha_vec_arm.S", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer output.Close()
|
||||
|
||||
output.WriteString(preamble)
|
||||
output.WriteString(compiler)
|
||||
output.WriteString(" ")
|
||||
output.WriteString(strings.Join(args, " "))
|
||||
output.WriteString("\n\n#if !defined(OPENSSL_NO_ASM)\n")
|
||||
output.WriteString("#if defined(__arm__)\n\n")
|
||||
|
||||
cmd := exec.Command(compiler, args...)
|
||||
cmd.Stderr = os.Stderr
|
||||
asm, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
attr28 := []byte(".eabi_attribute 28,")
|
||||
globalDirective := []byte(".global\t")
|
||||
newLine := []byte("\n")
|
||||
attr28Handled := false
|
||||
|
||||
scanner := bufio.NewScanner(asm)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Bytes()
|
||||
|
||||
if bytes.Contains(line, attr28) {
|
||||
output.WriteString(attr28Block)
|
||||
attr28Handled = true
|
||||
continue
|
||||
}
|
||||
|
||||
output.Write(line)
|
||||
output.Write(newLine)
|
||||
|
||||
if i := bytes.Index(line, globalDirective); i >= 0 {
|
||||
output.Write(line[:i])
|
||||
output.WriteString(".hidden\t")
|
||||
output.Write(line[i+len(globalDirective):])
|
||||
output.Write(newLine)
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if !attr28Handled {
|
||||
panic("EABI attribute 28 not seen in processing")
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
output.WriteString(trailer)
|
||||
}
|
||||
|
||||
const preamble = `# Copyright (c) 2014, Google Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
|
||||
# needed to support switching on NEON code at runtime. If the whole of OpenSSL
|
||||
# were to be compiled with the needed flags to build chacha_vec.c, then it
|
||||
# wouldn't be possible to run on non-NEON systems.
|
||||
#
|
||||
# This file was generated by chacha_vec_arm_generate.go using the following
|
||||
# compiler command:
|
||||
#
|
||||
# `
|
||||
|
||||
const attr28Block = `
|
||||
# EABI attribute 28 sets whether VFP register arguments were used to build this
|
||||
# file. If object files are inconsistent on this point, the linker will refuse
|
||||
# to link them. Thus we report whatever the compiler expects since we don't use
|
||||
# VFP arguments.
|
||||
|
||||
#if defined(__ARM_PCS_VFP)
|
||||
.eabi_attribute 28, 1
|
||||
#else
|
||||
.eabi_attribute 28, 0
|
||||
#endif
|
||||
|
||||
`
|
||||
|
||||
const trailer = `
|
||||
#endif /* __arm__ */
|
||||
#endif /* !OPENSSL_NO_ASM */
|
||||
`
|
||||
+32
-159
@@ -192,158 +192,37 @@ static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
|
||||
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');
|
||||
ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint8_t kPlaintext[260] =
|
||||
"testing123456testing123456testing123456testing123456testing123456testing"
|
||||
"123456testing123456testing123456testing123456testing123456testing123456t"
|
||||
"esting123456testing123456testing123456testing123456testing123456testing1"
|
||||
"23456testing123456testing123456testing12345";
|
||||
const std::vector<size_t> offsets = {
|
||||
0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
|
||||
64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> nonce(nonce_len, 'b');
|
||||
std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
|
||||
size_t valid_encryption_len;
|
||||
if (!EVP_AEAD_CTX_seal(
|
||||
ctx.get(), valid_encryption.data(), &valid_encryption_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
|
||||
kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// First test with out > in, which we expect to fail.
|
||||
for (auto offset : offsets) {
|
||||
if (offset == 0) {
|
||||
// Will be tested in the next loop.
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buffer(offset + valid_encryption_len);
|
||||
memcpy(buffer.data(), kPlaintext, sizeof(kPlaintext));
|
||||
uint8_t *out = buffer.data() + offset;
|
||||
|
||||
size_t out_len;
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), out, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, buffer.data(), sizeof(kPlaintext),
|
||||
nullptr, 0)) {
|
||||
// We expect offsets where the output is greater than the input to fail.
|
||||
ERR_clear_error();
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"EVP_AEAD_CTX_seal unexpectedly succeeded for offset %u.\n",
|
||||
static_cast<unsigned>(offset));
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(buffer.data(), valid_encryption.data(), valid_encryption_len);
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), out, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, buffer.data(),
|
||||
valid_encryption_len, nullptr, 0)) {
|
||||
// We expect offsets where the output is greater than the input to fail.
|
||||
ERR_clear_error();
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"EVP_AEAD_CTX_open unexpectedly succeeded for offset %u.\n",
|
||||
static_cast<unsigned>(offset));
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test with out <= in, which we expect to work.
|
||||
for (auto offset : offsets) {
|
||||
std::vector<uint8_t> buffer(offset + valid_encryption_len);
|
||||
uint8_t *const out = buffer.data();
|
||||
uint8_t *const in = buffer.data() + offset;
|
||||
memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
|
||||
size_t out_len;
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), out, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal failed for offset -%u.\n",
|
||||
static_cast<unsigned>(offset));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != valid_encryption_len ||
|
||||
memcmp(out, valid_encryption.data(), out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output for offset -%u.\n",
|
||||
static_cast<unsigned>(offset));
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), out, &out_len,
|
||||
offset + valid_encryption_len, nonce.data(),
|
||||
nonce_len, in, valid_encryption_len, nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open failed for offset -%u.\n",
|
||||
static_cast<unsigned>(offset));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != sizeof(kPlaintext) ||
|
||||
memcmp(out, kPlaintext, out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open produced bad output for offset -%u.\n",
|
||||
static_cast<unsigned>(offset));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct KnownAEAD {
|
||||
struct AEADName {
|
||||
const char name[40];
|
||||
const EVP_AEAD *(*func)(void);
|
||||
// limited_implementation indicates that tests that assume a generic AEAD
|
||||
// interface should not be performed. For example, the key-wrap AEADs only
|
||||
// handle inputs that are a multiple of eight bytes in length and the
|
||||
// SSLv3/TLS AEADs have the concept of “direction”.
|
||||
bool limited_implementation;
|
||||
};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{ "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 },
|
||||
{ "rc4-md5-tls", EVP_aead_rc4_md5_tls, true },
|
||||
{ "rc4-sha1-tls", EVP_aead_rc4_sha1_tls, true },
|
||||
{ "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 },
|
||||
{ "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3, true },
|
||||
{ "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3, 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 },
|
||||
static const struct AEADName kAEADs[] = {
|
||||
{ "aes-128-gcm", EVP_aead_aes_128_gcm },
|
||||
{ "aes-256-gcm", EVP_aead_aes_256_gcm },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305 },
|
||||
{ "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old },
|
||||
{ "rc4-md5-tls", EVP_aead_rc4_md5_tls },
|
||||
{ "rc4-sha1-tls", EVP_aead_rc4_sha1_tls },
|
||||
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls },
|
||||
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv },
|
||||
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls },
|
||||
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls },
|
||||
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv },
|
||||
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls },
|
||||
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls },
|
||||
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls },
|
||||
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv },
|
||||
{ "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3 },
|
||||
{ "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3 },
|
||||
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3 },
|
||||
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3 },
|
||||
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3 },
|
||||
{ "aes-128-key-wrap", EVP_aead_aes_128_key_wrap },
|
||||
{ "aes-256-key-wrap", EVP_aead_aes_256_key_wrap },
|
||||
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256 },
|
||||
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256 },
|
||||
{ "", NULL },
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@@ -354,28 +233,22 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct KnownAEAD *known_aead;
|
||||
const EVP_AEAD *aead;
|
||||
for (unsigned i = 0;; i++) {
|
||||
known_aead = &kAEADs[i];
|
||||
if (known_aead->func == NULL) {
|
||||
const struct AEADName &aead_name = kAEADs[i];
|
||||
if (aead_name.func == NULL) {
|
||||
fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(known_aead->name, argv[1]) == 0) {
|
||||
if (strcmp(aead_name.name, argv[1]) == 0) {
|
||||
aead = aead_name.func();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_AEAD *const aead = known_aead->func();
|
||||
|
||||
if (!TestCleanupAfterInitFailure(aead)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
|
||||
fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
static bool TestOperation(FileTest *t,
|
||||
const EVP_CIPHER *cipher,
|
||||
bool encrypt,
|
||||
size_t chunk_size,
|
||||
bool streaming,
|
||||
const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &iv,
|
||||
const std::vector<uint8_t> &plaintext,
|
||||
@@ -138,7 +138,7 @@ static bool TestOperation(FileTest *t,
|
||||
iv.size(), 0)) {
|
||||
return false;
|
||||
}
|
||||
} else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
} else if (iv.size() != (size_t)EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
t->PrintLine("Bad IV length.");
|
||||
return false;
|
||||
}
|
||||
@@ -170,21 +170,16 @@ static bool TestOperation(FileTest *t,
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
if (chunk_size != 0) {
|
||||
for (size_t i = 0; i < in->size();) {
|
||||
size_t todo = chunk_size;
|
||||
if (i + todo > in->size()) {
|
||||
todo = in->size() - i;
|
||||
}
|
||||
|
||||
if (streaming) {
|
||||
for (size_t i = 0; i < in->size(); i++) {
|
||||
uint8_t c = (*in)[i];
|
||||
int len;
|
||||
if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
|
||||
in->data() + i, todo)) {
|
||||
if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len, &c,
|
||||
1)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
result_len1 += len;
|
||||
i += todo;
|
||||
}
|
||||
} else if (!in->empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
|
||||
@@ -263,20 +258,20 @@ static bool TestCipher(FileTest *t, void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
|
||||
17, 31, 32, 33, 63, 64, 65, 512};
|
||||
|
||||
for (size_t chunk_size : chunk_sizes) {
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt &&
|
||||
!TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag)) {
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt) {
|
||||
if (!TestOperation(t, cipher, true /* encrypt */, false /* single-shot */,
|
||||
key, iv, plaintext, ciphertext, aad, tag) ||
|
||||
!TestOperation(t, cipher, true /* encrypt */, true /* streaming */, key,
|
||||
iv, plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (operation != kEncrypt &&
|
||||
!TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag)) {
|
||||
}
|
||||
if (operation != kEncrypt) {
|
||||
if (!TestOperation(t, cipher, false /* decrypt */, false /* single-shot */,
|
||||
key, iv, plaintext, ciphertext, aad, tag) ||
|
||||
!TestOperation(t, cipher, false /* decrypt */, true /* streaming */,
|
||||
key, iv, plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+63
-15
@@ -54,7 +54,7 @@
|
||||
#include <openssl/cpu.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
@@ -67,10 +67,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4702) /* Unreachable code. */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
double align;
|
||||
@@ -256,6 +252,22 @@ void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t *ivec, int enc);
|
||||
|
||||
void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
|
||||
const void *key, const uint8_t *ivec);
|
||||
|
||||
#if defined(OPENSSL_X86_64)
|
||||
size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const void *key, uint8_t ivec[16], uint64_t *Xi);
|
||||
#define AES_gcm_encrypt aesni_gcm_encrypt
|
||||
size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const void *key, uint8_t ivec[16], uint64_t *Xi);
|
||||
#define AES_gcm_decrypt aesni_gcm_decrypt
|
||||
void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
|
||||
size_t len);
|
||||
#define AES_GCM_ASM(gctx) \
|
||||
(gctx->ctr == aesni_ctr32_encrypt_blocks && gctx->gcm.ghash == gcm_ghash_avx)
|
||||
#endif /* OPENSSL_X86_64 */
|
||||
|
||||
#else
|
||||
|
||||
/* On other platforms, aesni_capable() will always return false and so the
|
||||
@@ -276,7 +288,8 @@ static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
#endif
|
||||
|
||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
const uint8_t *iv, int enc) {
|
||||
const uint8_t *iv, int enc)
|
||||
OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
|
||||
int ret, mode;
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
@@ -371,7 +384,7 @@ static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
|
||||
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
size_t len) {
|
||||
unsigned num = (unsigned)ctx->num;
|
||||
unsigned int num = ctx->num;
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
if (dat->stream.ctr) {
|
||||
@@ -381,7 +394,7 @@ static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
|
||||
dat->block);
|
||||
}
|
||||
ctx->num = (int)num;
|
||||
ctx->num = (size_t)num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -397,7 +410,8 @@ static char aesni_capable(void);
|
||||
|
||||
static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
|
||||
block128_f *out_block, const uint8_t *key,
|
||||
size_t key_len) {
|
||||
size_t key_len)
|
||||
OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
|
||||
if (aesni_capable()) {
|
||||
aesni_set_encrypt_key(key, key_len * 8, aes_key);
|
||||
if (gcm_ctx != NULL) {
|
||||
@@ -637,23 +651,57 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
}
|
||||
} else if (ctx->encrypt) {
|
||||
if (gctx->ctr) {
|
||||
if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
|
||||
gctx->ctr)) {
|
||||
size_t bulk = 0;
|
||||
#if defined(AES_GCM_ASM)
|
||||
if (len >= 32 && AES_GCM_ASM(gctx)) {
|
||||
size_t res = (16 - gctx->gcm.mres) % 16;
|
||||
|
||||
if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bulk = AES_gcm_encrypt(in + res, out + res, len - res, &gctx->ks.ks,
|
||||
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
|
||||
gctx->gcm.len.u[1] += bulk;
|
||||
bulk += res;
|
||||
}
|
||||
#endif
|
||||
if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
|
||||
out + bulk, len - bulk, gctx->ctr)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
|
||||
size_t bulk = 0;
|
||||
if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
|
||||
out + bulk, len - bulk)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (gctx->ctr) {
|
||||
if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
|
||||
gctx->ctr)) {
|
||||
size_t bulk = 0;
|
||||
#if defined(AES_GCM_ASM)
|
||||
if (len >= 16 && AES_GCM_ASM(gctx)) {
|
||||
size_t res = (16 - gctx->gcm.mres) % 16;
|
||||
|
||||
if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bulk = AES_gcm_decrypt(in + res, out + res, len - res, &gctx->ks.ks,
|
||||
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
|
||||
gctx->gcm.len.u[1] += bulk;
|
||||
bulk += res;
|
||||
}
|
||||
#endif
|
||||
if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
|
||||
out + bulk, len - bulk, gctx->ctr)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
|
||||
size_t bulk = 0;
|
||||
if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
|
||||
out + bulk, len - bulk)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <openssl/poly1305.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define POLY1305_TAG_LEN 16
|
||||
@@ -80,6 +79,12 @@ static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
|
||||
CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
|
||||
}
|
||||
|
||||
#if defined(__arm__)
|
||||
#define ALIGNED __attribute__((aligned(16)))
|
||||
#else
|
||||
#define ALIGNED
|
||||
#endif
|
||||
|
||||
typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad,
|
||||
size_t ad_len, const uint8_t *ciphertext,
|
||||
size_t ciphertext_len);
|
||||
@@ -93,7 +98,7 @@ static void aead_poly1305(aead_poly1305_update update,
|
||||
const uint8_t nonce[12], const uint8_t *ad,
|
||||
size_t ad_len, const uint8_t *ciphertext,
|
||||
size_t ciphertext_len) {
|
||||
alignas(16) uint8_t poly1305_key[32];
|
||||
uint8_t poly1305_key[32] ALIGNED;
|
||||
memset(poly1305_key, 0, sizeof(poly1305_key));
|
||||
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
|
||||
c20_ctx->key, nonce, 0);
|
||||
@@ -117,7 +122,7 @@ static int seal_impl(aead_poly1305_update poly1305_update,
|
||||
* 32-bits and this produces a warning because it's always false.
|
||||
* Casting to uint64_t inside the conditional is not sufficient to stop
|
||||
* the warning. */
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
|
||||
if (in_len_64 >= (1ull << 32) * 64 - 64) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
@@ -134,7 +139,7 @@ static int seal_impl(aead_poly1305_update poly1305_update,
|
||||
|
||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||
|
||||
alignas(16) uint8_t tag[POLY1305_TAG_LEN];
|
||||
uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
|
||||
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len);
|
||||
|
||||
memcpy(out + in_len, tag, c20_ctx->tag_len);
|
||||
@@ -162,13 +167,13 @@ static int open_impl(aead_poly1305_update poly1305_update,
|
||||
* 32-bits and this produces a warning because it's always false.
|
||||
* Casting to uint64_t inside the conditional is not sufficient to stop
|
||||
* the warning. */
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
|
||||
if (in_len_64 >= (1ull << 32) * 64 - 64) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
plaintext_len = in_len - c20_ctx->tag_len;
|
||||
alignas(16) uint8_t tag[POLY1305_TAG_LEN];
|
||||
uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
|
||||
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in,
|
||||
plaintext_len);
|
||||
if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user