Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 345b735e31 | |||
| 3fbc298104 | |||
| 54e455157a |
@@ -2,5 +2,3 @@ build/
|
||||
ssl/test/runner/runner
|
||||
*.swp
|
||||
*.swo
|
||||
doc/*.html
|
||||
doc/doc.css
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
Note that the default build flags in the top-leve CMakeLists.txt are for
|
||||
debugging - optimisation isn't enabled.
|
||||
|
||||
If you'll be building a lot, then installing Ninja[1] is highly recommended.
|
||||
Wipe out the build directory and recreate it, but using:
|
||||
|
||||
cmake -GNinja ..
|
||||
ninja
|
||||
|
||||
If you want to cross-compile then there are example toolchain files for 32-bit
|
||||
Intel and ARM in util/. Wipe out the build directory, recreate it and run cmake
|
||||
like this:
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../util/arm-toolchain.cmake -GNinja ..
|
||||
|
||||
If you want to build as a shared library you need to tweak the STATIC tags in
|
||||
the CMakeLists.txts and also define BORINGSSL_SHARED_LIBRARY and
|
||||
BORINGSSL_IMPLEMENTATION. On Windows, where functions need to be tagged with
|
||||
"dllimport" when coming from a shared library, you need just
|
||||
BORINGSSL_SHARED_LIBRARY defined in the code which #includes the BoringSSL
|
||||
headers.
|
||||
|
||||
To build on Windows, Yasm[2] is required for assembly. Either ensure yasm.exe
|
||||
is in %PATH% or configure CMAKE_ASM_NASM_COMPILER appropriately. Note that
|
||||
full Windows support is still in progress.
|
||||
|
||||
[1] http://martine.github.io/ninja/
|
||||
[2] http://yasm.tortall.net/
|
||||
-151
@@ -1,151 +0,0 @@
|
||||
# Building BoringSSL
|
||||
|
||||
## Build Prerequisites
|
||||
|
||||
* [CMake](https://cmake.org/download/) 2.8.8 or later is required.
|
||||
|
||||
* Perl 5.6.1 or later is required. On Windows,
|
||||
[Active State Perl](http://www.activestate.com/activeperl/) has been
|
||||
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`.
|
||||
|
||||
* On Windows you currently must use [Ninja](https://ninja-build.org/)
|
||||
to build; on other platforms, it is not required, but recommended, because
|
||||
it makes builds faster.
|
||||
|
||||
* If you need to build Ninja from source, then a recent version of
|
||||
[Python](https://www.python.org/downloads/) is required (Python 2.7.5 works).
|
||||
|
||||
* On Windows only, [Yasm](http://yasm.tortall.net/) is required. If not found
|
||||
by CMake, it may be configured explicitly by setting
|
||||
`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.
|
||||
|
||||
* [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):
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -GNinja ..
|
||||
ninja
|
||||
|
||||
Using Make (does not work on Windows):
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
You usually don't need to run `cmake` again after changing `CMakeLists.txt`
|
||||
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.
|
||||
|
||||
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
|
||||
this:
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../util/32-bit-toolchain.cmake -GNinja ..
|
||||
|
||||
If you want to build as a shared library, pass `-DBUILD_SHARED_LIBS=1`. On
|
||||
Windows, where functions need to be tagged with `dllimport` when coming from a
|
||||
shared library, define `BORINGSSL_SHARED_LIBRARY` in any code which `#include`s
|
||||
the BoringSSL headers.
|
||||
|
||||
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
|
||||
been tested with version 10d of the NDK.
|
||||
|
||||
Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the
|
||||
directory. Clone https://github.com/taka-no-me/android-cmake into `util/`. Then
|
||||
make a build directory as above and run CMake *twice* like this:
|
||||
|
||||
cmake -DANDROID_NATIVE_API_LEVEL=android-9 \
|
||||
-DANDROID_ABI=armeabi-v7a \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../util/android-cmake/android.toolchain.cmake \
|
||||
-DANDROID_NATIVE_API_LEVEL=16 \
|
||||
-GNinja ..
|
||||
|
||||
Once you've run that twice, Ninja should produce Android-compatible binaries.
|
||||
You can replace `armeabi-v7a` in the above with `arm64-v8a` to build aarch64
|
||||
binaries.
|
||||
|
||||
## Known Limitations on Windows
|
||||
|
||||
* Versions of CMake since 3.0.2 have a bug in its Ninja generator that causes
|
||||
yasm to output warnings
|
||||
|
||||
yasm: warning: can open only one input file, only the last file will be processed
|
||||
|
||||
These warnings can be safely ignored. The cmake bug is
|
||||
http://www.cmake.org/Bug/view.php?id=15253.
|
||||
|
||||
* CMake can generate Visual Studio projects, but the generated project files
|
||||
don't have steps for assembling the assembly language source files, so they
|
||||
currently cannot be used to build BoringSSL.
|
||||
|
||||
## Embedded ARM
|
||||
|
||||
ARM, unlike Intel, does not have an instruction that allows applications to
|
||||
discover the capabilities of the processor. Instead, the capability information
|
||||
has to be provided by the operating system somehow.
|
||||
|
||||
BoringSSL will try to use `getauxval` to discover the capabilities and, failing
|
||||
that, will probe for NEON support by executing a NEON instruction and handling
|
||||
any illegal-instruction signal. But some environments don't support that sort
|
||||
of thing and, for them, it's possible to configure the CPU capabilities
|
||||
at compile time.
|
||||
|
||||
If you define `OPENSSL_STATIC_ARMCAP` then you can define any of the following
|
||||
to enabling the corresponding ARM feature.
|
||||
|
||||
* `OPENSSL_STATIC_ARMCAP_NEON` or `__ARM_NEON__` (note that the latter is set by compilers when NEON support is enabled).
|
||||
* `OPENSSL_STATIC_ARMCAP_AES`
|
||||
* `OPENSSL_STATIC_ARMCAP_SHA1`
|
||||
* `OPENSSL_STATIC_ARMCAP_SHA256`
|
||||
* `OPENSSL_STATIC_ARMCAP_PMULL`
|
||||
|
||||
Note that if a feature is enabled in this way, but not actually supported at
|
||||
run-time, BoringSSL will likely crash.
|
||||
|
||||
# Running tests
|
||||
|
||||
There are two sets of tests: the C/C++ tests and the blackbox tests. For former
|
||||
are built by Ninja and can be run from the top-level directory with `go run
|
||||
util/all_tests.go`. The latter have to be run separately by running `go test`
|
||||
from within `ssl/test/runner`.
|
||||
|
||||
Both sets of tests may also be run with `ninja -C build run_tests`, but CMake
|
||||
3.2 or later is required to avoid Ninja's output buffering.
|
||||
+21
-169
@@ -1,190 +1,42 @@
|
||||
cmake_minimum_required (VERSION 2.8.10)
|
||||
cmake_minimum_required (VERSION 2.8.8)
|
||||
|
||||
# Defer enabling C and CXX languages.
|
||||
project (BoringSSL NONE)
|
||||
project (BoringSSL)
|
||||
|
||||
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)
|
||||
|
||||
if(ANDROID)
|
||||
# Android-NDK CMake files reconfigure the path and so Go and Perl won't be
|
||||
# found. However, ninja will still find them in $PATH if we just name them.
|
||||
set(PERL_EXECUTABLE "perl")
|
||||
set(GO_EXECUTABLE "go")
|
||||
else()
|
||||
find_package(Perl REQUIRED)
|
||||
find_program(GO_EXECUTABLE go)
|
||||
endif()
|
||||
|
||||
if (NOT GO_EXECUTABLE)
|
||||
message(FATAL_ERROR "Could not find Go")
|
||||
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}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${C_CXX_FLAGS}")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -ggdb -std=c89")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -ggdb -std=c++0x")
|
||||
elseif(MSVC)
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
"C4100" # 'exarg' : unreferenced formal parameter
|
||||
"C4127" # conditional expression is constant
|
||||
"C4200" # nonstandard extension used : zero-sized array in
|
||||
# struct/union.
|
||||
"C4242" # 'function' : conversion from 'int' to 'uint8_t',
|
||||
# possible loss of data
|
||||
"C4244" # 'function' : conversion from 'int' to 'uint8_t',
|
||||
# possible loss of data
|
||||
"C4245" # 'initializing' : conversion from 'long' to
|
||||
# 'unsigned long', signed/unsigned mismatch
|
||||
"C4267" # conversion from 'size_t' to 'int', possible loss of data
|
||||
"C4371" # layout of class may have changed from a previous version of the
|
||||
# compiler due to better packing of member '...'
|
||||
"C4388" # signed/unsigned mismatch
|
||||
"C4296" # '>=' : expression is always true
|
||||
"C4350" # behavior change: 'std::_Wrap_alloc...'
|
||||
"C4365" # '=' : conversion from 'size_t' to 'int',
|
||||
# signed/unsigned mismatch
|
||||
"C4389" # '!=' : signed/unsigned mismatch
|
||||
"C4510" # 'argument' : default constructor could not be generated
|
||||
"C4512" # 'argument' : assignment operator could not be generated
|
||||
"C4514" # 'function': unreferenced inline function has been removed
|
||||
"C4548" # expression before comma has no effect; expected expression with
|
||||
# side-effect" caused by FD_* macros.
|
||||
"C4610" # struct 'argument' can never be instantiated - user defined
|
||||
# constructor required.
|
||||
"C4625" # copy constructor could not be generated because a base class
|
||||
# copy constructor is inaccessible or deleted
|
||||
"C4626" # assignment operator could not be generated because a base class
|
||||
# assignment operator is inaccessible or deleted
|
||||
"C4701" # potentially uninitialized local variable 'p' used
|
||||
"C4706" # assignment within conditional expression
|
||||
"C4710" # 'function': function not inlined
|
||||
"C4711" # function 'function' selected for inline expansion
|
||||
"C4800" # 'int' : forcing value to bool 'true' or 'false'
|
||||
# (performance warning)
|
||||
"C4820" # 'bytes' bytes padding added after construct 'member_name'
|
||||
"C4996" # 'read': The POSIX name for this item is deprecated. Instead,
|
||||
# use the ISO C++ conformant name: _read.
|
||||
)
|
||||
string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
|
||||
${MSVC_DISABLED_WARNINGS_LIST})
|
||||
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)
|
||||
endif()
|
||||
|
||||
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR
|
||||
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
|
||||
endif()
|
||||
|
||||
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR
|
||||
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_XOPEN_SOURCE=700")
|
||||
endif()
|
||||
|
||||
if(FUZZ)
|
||||
if(!CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message("You need to build with Clang for fuzzing to work")
|
||||
endif()
|
||||
|
||||
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(.)
|
||||
# Disable warnings for implicit integer narrowing.
|
||||
set(CMAKE_C_FLAGS "/wd4267")
|
||||
set(CMAKE_CXX_FLAGS "/wd4267")
|
||||
endif()
|
||||
|
||||
add_definitions(-DBORINGSSL_IMPLEMENTATION)
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
add_definitions(-DBORINGSSL_SHARED_LIBRARY)
|
||||
# Enable position-independent code globally. This is needed because
|
||||
# some library targets are OBJECT libraries.
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(ARCH "x86_64")
|
||||
set(ARCH "x86_64")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
|
||||
set(ARCH "x86_64")
|
||||
set(ARCH "x86_64")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
|
||||
# cmake reports AMD64 on Windows, but we might be building for 32-bit.
|
||||
if (CMAKE_CL_64)
|
||||
set(ARCH "x86_64")
|
||||
else()
|
||||
set(ARCH "x86")
|
||||
endif()
|
||||
# cmake reports AMD64 on Windows, but we might be building for 32-bit.
|
||||
if (CMAKE_CL_64)
|
||||
set(ARCH "x86_64")
|
||||
else()
|
||||
set(ARCH "x86")
|
||||
endif()
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86")
|
||||
set(ARCH "x86")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386")
|
||||
set(ARCH "x86")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
|
||||
set(ARCH "x86")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv6")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7-a")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
set(ARCH "aarch64")
|
||||
set(ARCH "arm")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
|
||||
message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
if (ANDROID AND ${ARCH} STREQUAL "arm")
|
||||
# The Android-NDK CMake files somehow fail to set the -march flag for
|
||||
# assembly files. Without this flag, the compiler believes that it's
|
||||
# building for ARMv5.
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -march=${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86" AND APPLE)
|
||||
# With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X,
|
||||
# but clang defaults to 64-bit builds on OS X unless otherwise told.
|
||||
# Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3.
|
||||
set(ARCH "x86_64")
|
||||
endif()
|
||||
|
||||
if (OPENSSL_NO_ASM)
|
||||
add_definitions(-DOPENSSL_NO_ASM)
|
||||
set(ARCH "generic")
|
||||
endif()
|
||||
|
||||
# Declare a dummy target to build all unit tests. Test targets should inject
|
||||
# themselves as dependencies next to the target definition.
|
||||
add_custom_target(all_tests)
|
||||
|
||||
add_subdirectory(crypto)
|
||||
add_subdirectory(ssl)
|
||||
add_subdirectory(ssl/test)
|
||||
add_subdirectory(tool)
|
||||
add_subdirectory(decrepit)
|
||||
|
||||
if(FUZZ)
|
||||
add_subdirectory(fuzz)
|
||||
endif()
|
||||
|
||||
if (NOT ${CMAKE_VERSION} VERSION_LESS "3.2")
|
||||
# USES_TERMINAL is only available in CMake 3.2 or later.
|
||||
set(MAYBE_USES_TERMINAL USES_TERMINAL)
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
run_tests
|
||||
COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir
|
||||
${CMAKE_BINARY_DIR}
|
||||
COMMAND cd ssl/test/runner
|
||||
COMMAND ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
|
||||
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).
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
# Fuzz testing
|
||||
|
||||
Modern fuzz testers are very effective and we wish to use them to ensure that no silly bugs creep into BoringSSL.
|
||||
|
||||
We primarily use Clang's [libFuzzer](http://llvm.org/docs/LibFuzzer.html) for fuzz testing and there are a number of fuzz testing functions in `fuzz/`. They are not built by default because they require libFuzzer at build time.
|
||||
|
||||
In order to build the fuzz tests you will need at least Clang 3.7. Pass `-DFUZZ=1` on the CMake command line to enable building BoringSSL with coverage and AddressSanitizer, and to build the fuzz test binaries. You'll probably need to set the `CC` and `CXX` environment variables too, like this:
|
||||
|
||||
```
|
||||
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:
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
From the `build/` directory, you can then run the fuzzers. For example:
|
||||
|
||||
```
|
||||
./fuzz/cert -max_len=4000 -jobs=32 -workers=32 ../fuzz/cert_corpus/
|
||||
```
|
||||
|
||||
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.)
|
||||
|
||||
Here are the recommended values of `max_len` for each test.
|
||||
|
||||
| Test | `max_len` value |
|
||||
|-----------|-----------------|
|
||||
| `privkey` | 2048 |
|
||||
| `cert` | 3072 |
|
||||
| `server` | 1024 |
|
||||
| `client` | 4096 |
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
# Porting from OpenSSL to BoringSSL
|
||||
|
||||
BoringSSL is an OpenSSL derivative and is mostly source-compatible, for the
|
||||
subset of OpenSSL retained. Libraries ideally need little to no changes for
|
||||
BoringSSL support, provided they do not use removed APIs. In general, see if the
|
||||
library compiles and, on failure, consult the documentation in the header files
|
||||
and see if problematic features can be removed.
|
||||
|
||||
In some cases, BoringSSL-specific code may be necessary. In that case, the
|
||||
`OPENSSL_IS_BORINGSSL` preprocessor macro may be used in `#ifdef`s. This macro
|
||||
should also be used in lieu of the presence of any particular function to detect
|
||||
OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary.
|
||||
|
||||
For convenience, BoringSSL defines upstream's `OPENSSL_NO_*` feature macros
|
||||
corresponding to removed features. These may also be used to disable code which
|
||||
uses a removed feature.
|
||||
|
||||
Note: BoringSSL does *not* have a stable API or ABI. It must be updated with its
|
||||
consumers. It is not suitable for, say, a system library in a traditional Linux
|
||||
distribution. For instance, Chromium statically links the specific revision of
|
||||
BoringSSL it was built against. Likewise, Android's system-internal copy of
|
||||
BoringSSL is not exposed by the NDK and must not be used by third-party
|
||||
applications.
|
||||
|
||||
|
||||
## Major API changes
|
||||
|
||||
### Integer types
|
||||
|
||||
Some APIs have been converted to use `size_t` for consistency and to avoid
|
||||
integer overflows at the API boundary. (Existing logic uses a mismash of `int`,
|
||||
`long`, and `unsigned`.) For the most part, implicit casts mean that existing
|
||||
code continues to compile. In some cases, this may require BoringSSL-specific
|
||||
code, particularly to avoid compiler warnings.
|
||||
|
||||
Most notably, the `STACK_OF(T)` types have all been converted to use `size_t`
|
||||
instead of `int` for indices and lengths.
|
||||
|
||||
### Reference counts
|
||||
|
||||
Some external consumers increment reference counts directly by calling
|
||||
`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value.
|
||||
|
||||
These APIs no longer exist in BoringSSL. Instead, code which increments
|
||||
reference counts should call the corresponding `FOO_up_ref` function, such as
|
||||
`EVP_PKEY_up_ref`. Note that not all of these APIs are present in OpenSSL and
|
||||
may require `#ifdef`s.
|
||||
|
||||
### Error codes
|
||||
|
||||
OpenSSL's errors are extremely specific, leaking internals of the library,
|
||||
including even a function code for the function which emitted the error! As some
|
||||
logic in BoringSSL has been rewritten, code which conditions on the error may
|
||||
break (grep for `ERR_GET_REASON` and `ERR_GET_FUNC`). This danger also exists
|
||||
when upgrading OpenSSL versions.
|
||||
|
||||
Where possible, avoid conditioning on the exact error reason. Otherwise, a
|
||||
BoringSSL `#ifdef` may be necessary. Exactly how best to resolve this issue is
|
||||
still being determined. It's possible some new APIs will be added in the future.
|
||||
|
||||
Function codes have been completely removed. Remove code which conditions on
|
||||
these as it will break with the slightest change in the library, OpenSSL or
|
||||
BoringSSL.
|
||||
|
||||
### `*_ctrl` functions
|
||||
|
||||
Some OpenSSL APIs are implemented with `ioctl`-style functions such as
|
||||
`SSL_ctrl` and `EVP_PKEY_CTX_ctrl`, combined with convenience macros, such as
|
||||
|
||||
# define SSL_CTX_set_mode(ctx,op) \
|
||||
SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
|
||||
|
||||
In BoringSSL, these macros have been replaced with proper functions. The
|
||||
underlying `_ctrl` functions have been removed.
|
||||
|
||||
For convenience, `SSL_CTRL_*` values are retained as macros to `doesnt_exist` so
|
||||
existing code which uses them (or the wrapper macros) in `#ifdef` expressions
|
||||
will continue to function. However, the macros themselves will not work.
|
||||
|
||||
Switch any `*_ctrl` callers to the macro/function versions. This works in both
|
||||
OpenSSL and BoringSSL. Note that BoringSSL's function versions will be
|
||||
type-checked and may require more care with types.
|
||||
|
||||
### HMAC `EVP_PKEY`s
|
||||
|
||||
`EVP_PKEY_HMAC` is removed. Use the `HMAC_*` functions in `hmac.h` instead. This
|
||||
is compatible with OpenSSL.
|
||||
|
||||
### DSA `EVP_PKEY`s
|
||||
|
||||
`EVP_PKEY_DSA` is deprecated. It is currently still possible to parse DER into a
|
||||
DSA `EVP_PKEY`, but signing or verifying with those objects will not work.
|
||||
|
||||
### DES
|
||||
|
||||
The `DES_cblock` type has been switched from an array to a struct to avoid the
|
||||
pitfalls around array types in C. Where features which require DES cannot be
|
||||
disabled, BoringSSL-specific codepaths may be necessary.
|
||||
|
||||
### TLS renegotiation
|
||||
|
||||
OpenSSL enables TLS renegotiation by default and accepts renegotiation requests
|
||||
from the peer transparently. Renegotiation is an extremely problematic protocol
|
||||
feature, so BoringSSL rejects peer renegotiations by default.
|
||||
|
||||
To enable renegotiation, call `SSL_set_renegotiate_mode` and set it to
|
||||
`ssl_renegotiate_once` or `ssl_renegotiate_freely`. Renegotiation is only
|
||||
supported as a client in SSL3/TLS and the HelloRequest must be received at a
|
||||
quiet point in the application protocol. This is sufficient to support the
|
||||
common use of requesting a new client certificate between an HTTP request and
|
||||
response in (unpipelined) HTTP/1.1.
|
||||
|
||||
Things which do not work:
|
||||
|
||||
* There is no support for renegotiation as a server.
|
||||
|
||||
* There is no support for renegotiation in DTLS.
|
||||
|
||||
* There is no support for initiating renegotiation; `SSL_renegotiate` always
|
||||
fails and `SSL_set_state` does nothing.
|
||||
|
||||
* Interleaving application data with the new handshake is forbidden.
|
||||
|
||||
* If a HelloRequest is received while `SSL_write` has unsent application data,
|
||||
the renegotiation is rejected.
|
||||
|
||||
### Lowercase hexadecimal
|
||||
|
||||
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
|
||||
|
||||
BoringSSL makes some changes to OpenSSL which simplify the API but remain
|
||||
compatible with OpenSSL consumers. In general, consult the BoringSSL
|
||||
documentation for any functions in new BoringSSL-only code.
|
||||
|
||||
### Return values
|
||||
|
||||
Most OpenSSL APIs return 1 on success and either 0 or -1 on failure. BoringSSL
|
||||
has narrowed most of these to 1 on success and 0 on failure. BoringSSL-specific
|
||||
code may take advantage of the less error-prone APIs and use `!` to check for
|
||||
errors.
|
||||
|
||||
### Initialization
|
||||
|
||||
OpenSSL has a number of different initialization functions for setting up error
|
||||
strings and loading algorithms, etc. All of these functions still exist in
|
||||
BoringSSL for convenience, but they do nothing and are not necessary.
|
||||
|
||||
The one exception is `CRYPTO_library_init`. In `BORINGSSL_NO_STATIC_INITIALIZER`
|
||||
builds, it must be called to query CPU capabitilies before the rest of the
|
||||
library. In the default configuration, this is done with a static initializer
|
||||
and is also unnecessary.
|
||||
|
||||
### Threading
|
||||
|
||||
OpenSSL provides a number of APIs to configure threading callbacks and set up
|
||||
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.
|
||||
@@ -1,31 +0,0 @@
|
||||
# BoringSSL
|
||||
|
||||
BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
|
||||
|
||||
Although BoringSSL is an open source project, it is not intended for general
|
||||
use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing
|
||||
so is likely to be frustrating because there are no guarantees of API or ABI
|
||||
stability.
|
||||
|
||||
Programs ship their own copies of BoringSSL when they use it and we update
|
||||
everything as needed when deciding to make API changes. This allows us to
|
||||
mostly avoid compromises in the name of compatibility. It works for us, but it
|
||||
may not work for you.
|
||||
|
||||
BoringSSL arose because Google used OpenSSL for many years in various ways and,
|
||||
over time, built up a large number of patches that were maintained while
|
||||
tracking upstream OpenSSL. As Google's product portfolio became more complex,
|
||||
more copies of OpenSSL sprung up and the effort involved in maintaining all
|
||||
these patches in multiple places was growing steadily.
|
||||
|
||||
Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's
|
||||
not part of the NDK) and a number of other apps/programs.
|
||||
|
||||
There are other files in this directory which might be helpful:
|
||||
|
||||
* [PORTING.md](/PORTING.md): how to port OpenSSL-using code to BoringSSL.
|
||||
* [BUILDING.md](/BUILDING.md): how to build BoringSSL
|
||||
* [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.
|
||||
@@ -1,197 +0,0 @@
|
||||
# BoringSSL Style Guide
|
||||
|
||||
BoringSSL usually follows the
|
||||
[Google C++ style guide](https://google.github.io/styleguide/cppguide.html),
|
||||
The rest of this document describes differences and clarifications on
|
||||
top of the base guide.
|
||||
|
||||
|
||||
## Legacy code
|
||||
|
||||
As a derivative of OpenSSL, BoringSSL contains a lot of legacy code that
|
||||
does not follow this style guide. Particularly where public API is
|
||||
concerned, balance consistency within a module with the benefits of a
|
||||
given rule. Module-wide deviations on naming should be respected while
|
||||
integer and return value conventions take precedence over consistency.
|
||||
|
||||
Some modules have seen few changes, so they still retain the original
|
||||
indentation style for now. When editing these, try to retain the
|
||||
original style. For Emacs, `doc/c-indentation.el` from OpenSSL may be
|
||||
helpful in this.
|
||||
|
||||
|
||||
## Language
|
||||
|
||||
The majority of the project is in C, so C++-specific rules in the
|
||||
Google style guide do not apply. Support for C99 features depends on
|
||||
our target platforms. Typically, Chromium's target MSVC is the most
|
||||
restrictive.
|
||||
|
||||
Variable declarations in the middle of a function are allowed.
|
||||
|
||||
Comments should be `/* C-style */` for consistency.
|
||||
|
||||
When declaration pointer types, `*` should be placed next to the variable
|
||||
name, not the type. So
|
||||
|
||||
uint8_t *ptr;
|
||||
|
||||
not
|
||||
|
||||
uint8_t* ptr;
|
||||
|
||||
Rather than `malloc()` and `free()`, use the wrappers `OPENSSL_malloc()`
|
||||
and `OPENSSL_free()`. Use the standard C `assert()` function freely.
|
||||
|
||||
For new constants, prefer enums when the values are sequential and typed
|
||||
constants for flags. If adding values to an existing set of `#define`s,
|
||||
continue with `#define`.
|
||||
|
||||
|
||||
## Formatting
|
||||
|
||||
Single-statement blocks are not allowed. All conditions and loops must
|
||||
use braces:
|
||||
|
||||
if (foo) {
|
||||
do_something();
|
||||
}
|
||||
|
||||
not
|
||||
|
||||
if (foo)
|
||||
do_something();
|
||||
|
||||
|
||||
## Integers
|
||||
|
||||
Prefer using explicitly-sized integers where appropriate rather than
|
||||
generic C ones. For instance, to represent a byte, use `uint8_t`, not
|
||||
`unsigned char`. Likewise, represent a two-byte field as `uint16_t`, not
|
||||
`unsigned short`.
|
||||
|
||||
Sizes are represented as `size_t`.
|
||||
|
||||
Within a struct that is retained across the lifetime of an SSL
|
||||
connection, if bounds of a size are known and it's easy, use a smaller
|
||||
integer type like `uint8_t`. This is a "free" connection footprint
|
||||
optimization for servers. Don't make code significantly more complex for
|
||||
it, and do still check the bounds when passing in and out of the
|
||||
struct. This narrowing should not propagate to local variables and
|
||||
function parameters.
|
||||
|
||||
When doing arithmetic, account for overflow conditions.
|
||||
|
||||
Except with platform APIs, do not use `ssize_t`. MSVC lacks it, and
|
||||
prefer out-of-band error signaling for `size_t` (see Return values).
|
||||
|
||||
|
||||
## Naming
|
||||
|
||||
Follow Google naming conventions in C++ files. In C files, use the
|
||||
following naming conventions for consistency with existing OpenSSL and C
|
||||
styles:
|
||||
|
||||
Define structs with typedef named `TYPE_NAME`. The corresponding struct
|
||||
should be named `struct type_name_st`.
|
||||
|
||||
Name public functions as `MODULE_function_name`, unless the module
|
||||
already uses a different naming scheme for legacy reasons. The module
|
||||
name should be a type name if the function is a method of a particular
|
||||
type.
|
||||
|
||||
Some types are allocated within the library while others are initialized
|
||||
into a struct allocated by the caller, often on the stack. Name these
|
||||
functions `TYPE_NAME_new`/`TYPE_NAME_free` and
|
||||
`TYPE_NAME_init`/`TYPE_NAME_cleanup`, respectively. All `TYPE_NAME_free`
|
||||
functions must do nothing on `NULL` input.
|
||||
|
||||
If a variable is the length of a pointer value, it has the suffix
|
||||
`_len`. An output parameter is named `out` or has an `out_` prefix. For
|
||||
instance, For instance:
|
||||
|
||||
uint8_t *out,
|
||||
size_t *out_len,
|
||||
const uint8_t *in,
|
||||
size_t in_len,
|
||||
|
||||
Name public headers like `include/openssl/evp.h` with header guards like
|
||||
`OPENSSL_HEADER_EVP_H`. Name internal headers like
|
||||
`crypto/ec/internal.h` with header guards like
|
||||
`OPENSSL_HEADER_EC_INTERNAL_H`.
|
||||
|
||||
Name enums like `enum unix_hacker_t`. For instance:
|
||||
|
||||
enum should_free_handshake_buffer_t {
|
||||
free_handshake_buffer,
|
||||
dont_free_handshake_buffer,
|
||||
};
|
||||
|
||||
|
||||
## Return values
|
||||
|
||||
As even `malloc` may fail in BoringSSL, the vast majority of functions
|
||||
will have a failure case. Functions should return `int` with one on
|
||||
success and zero on error. Do not overload the return value to both
|
||||
signal success/failure and output an integer. For example:
|
||||
|
||||
OPENSSL_EXPORT int CBS_get_u16(CBS *cbs, uint16_t *out);
|
||||
|
||||
If a function needs more than a true/false result code, define an enum
|
||||
rather than arbitrarily assigning meaning to int values.
|
||||
|
||||
If a function outputs a pointer to an object on success and there are no
|
||||
other outputs, return the pointer directly and `NULL` on error.
|
||||
|
||||
|
||||
## Parameters
|
||||
|
||||
Where not constrained by legacy code, parameter order should be:
|
||||
|
||||
1. context parameters
|
||||
2. output parameters
|
||||
3. input parameters
|
||||
|
||||
For example,
|
||||
|
||||
/* CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an
|
||||
* ASN.1 object can be written. The |tag| argument will be used as the tag for
|
||||
* the object. It returns one on success or zero on error. */
|
||||
OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag);
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
All public symbols must have a documentation comment in their header
|
||||
file. The style is based on that of Go. The first sentence begins with
|
||||
the symbol name, optionally prefixed with "A" or "An". Apart from the
|
||||
initial mention of symbol, references to other symbols or parameter
|
||||
names should be surrounded by |pipes|.
|
||||
|
||||
Documentation should be concise but completely describe the exposed
|
||||
behavior of the function. Pay special note to success/failure behaviors
|
||||
and caller obligations on object lifetimes. If this sacrifices
|
||||
conciseness, consider simplifying the function's behavior.
|
||||
|
||||
/* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which
|
||||
* will be verified by |EVP_DigestVerifyFinal|. It returns one on success and
|
||||
* zero otherwise. */
|
||||
OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t len);
|
||||
|
||||
Explicitly mention any surprising edge cases or deviations from common
|
||||
return value patterns in legacy functions.
|
||||
|
||||
/* RSA_private_encrypt encrypts |flen| bytes from |from| with the private key in
|
||||
* |rsa| and writes the encrypted data to |to|. The |to| buffer must have at
|
||||
* least |RSA_size| bytes of space. It returns the number of bytes written, or
|
||||
* -1 on error. The |padding| argument must be one of the |RSA_*_PADDING|
|
||||
* values. If in doubt, |RSA_PKCS1_PADDING| is the most common.
|
||||
*
|
||||
* WARNING: this function is dangerous because it breaks the usual return value
|
||||
* convention. Use |RSA_sign_raw| instead. */
|
||||
OPENSSL_EXPORT int RSA_private_encrypt(int flen, const uint8_t *from,
|
||||
uint8_t *to, RSA *rsa, int padding);
|
||||
|
||||
Document private functions in their `internal.h` header or, if static,
|
||||
where defined.
|
||||
@@ -1,4 +0,0 @@
|
||||
# This file is used by gcl to get repository specific information.
|
||||
GERRIT_HOST: True
|
||||
GERRIT_PORT: True
|
||||
CODE_REVIEW_SERVER: https://boringssl-review.googlesource.com
|
||||
+94
-159
@@ -1,89 +1,67 @@
|
||||
include_directories(../include)
|
||||
include_directories(. ../include)
|
||||
|
||||
if(APPLE)
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
|
||||
endif()
|
||||
set(PERLASM_STYLE macosx)
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
set(PERLASM_STYLE macosx)
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
elseif(UNIX)
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
# The "armx" Perl scripts look for "64" in the style argument
|
||||
# in order to decide whether to generate 32- or 64-bit asm.
|
||||
set(PERLASM_STYLE linux64)
|
||||
elseif (${ARCH} STREQUAL "arm")
|
||||
set(PERLASM_STYLE linux32)
|
||||
elseif (${ARCH} STREQUAL "x86")
|
||||
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
|
||||
set(PERLASM_STYLE elf)
|
||||
else()
|
||||
set(PERLASM_STYLE elf)
|
||||
endif()
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
set(PERLASM_STYLE elf)
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
else()
|
||||
if (CMAKE_CL_64)
|
||||
message("Using nasm")
|
||||
set(PERLASM_STYLE nasm)
|
||||
else()
|
||||
message("Using win32n")
|
||||
set(PERLASM_STYLE win32n)
|
||||
set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
|
||||
endif()
|
||||
if (CMAKE_CL_64)
|
||||
message("Using nasm")
|
||||
set(PERLASM_STYLE nasm)
|
||||
else()
|
||||
message("Using win32n")
|
||||
set(PERLASM_STYLE win32n)
|
||||
endif()
|
||||
|
||||
# On Windows, we use the NASM output, specifically built with Yasm.
|
||||
set(ASM_EXT asm)
|
||||
enable_language(ASM_NASM)
|
||||
# On Windows, we use the NASM output, specifically built with Yasm.
|
||||
set(ASM_EXT asm)
|
||||
enable_language(ASM_NASM)
|
||||
endif()
|
||||
|
||||
function(perlasm dest src)
|
||||
add_custom_command(
|
||||
OUTPUT ${dest}
|
||||
COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest}
|
||||
DEPENDS
|
||||
${src}
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl
|
||||
WORKING_DIRECTORY .
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${dest}
|
||||
COMMAND perl ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${ARGN} > ${dest}
|
||||
DEPENDS
|
||||
${src}
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl
|
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl
|
||||
WORKING_DIRECTORY .
|
||||
)
|
||||
endfunction()
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-intel.c
|
||||
)
|
||||
cpu-x86_64-asm.${ASM_EXT}
|
||||
cpu-intel.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-intel.c
|
||||
)
|
||||
cpu-x86-asm.${ASM_EXT}
|
||||
cpu-intel.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-arm.c
|
||||
cpu-arm-asm.S
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
CRYPTO_ARCH_SOURCES
|
||||
|
||||
cpu-arm.c
|
||||
)
|
||||
cpu-x86-asm.${ASM_EXT}
|
||||
cpu-arm.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# Level 0.1 - depends on nothing outside this set.
|
||||
@@ -105,7 +83,6 @@ add_subdirectory(rc4)
|
||||
add_subdirectory(conf)
|
||||
add_subdirectory(chacha)
|
||||
add_subdirectory(poly1305)
|
||||
add_subdirectory(curve25519)
|
||||
|
||||
# Level 1, depends only on 0.*
|
||||
add_subdirectory(digest)
|
||||
@@ -127,9 +104,7 @@ add_subdirectory(ecdsa)
|
||||
add_subdirectory(hmac)
|
||||
|
||||
# Level 3
|
||||
add_subdirectory(cmac)
|
||||
add_subdirectory(evp)
|
||||
add_subdirectory(hkdf)
|
||||
add_subdirectory(pem)
|
||||
add_subdirectory(x509)
|
||||
add_subdirectory(x509v3)
|
||||
@@ -137,99 +112,59 @@ add_subdirectory(x509v3)
|
||||
# Level 4
|
||||
add_subdirectory(pkcs8)
|
||||
|
||||
# Test support code
|
||||
add_subdirectory(test)
|
||||
|
||||
add_library(
|
||||
crypto
|
||||
crypto
|
||||
STATIC
|
||||
|
||||
crypto.c
|
||||
directory_posix.c
|
||||
directory_win.c
|
||||
ex_data.c
|
||||
mem.c
|
||||
refcount_c11.c
|
||||
refcount_lock.c
|
||||
thread.c
|
||||
thread_none.c
|
||||
thread_pthread.c
|
||||
thread_win.c
|
||||
time_support.c
|
||||
crypto.c
|
||||
crypto_error.c
|
||||
mem.c
|
||||
thread.c
|
||||
ex_data.c
|
||||
ex_data_impl.c
|
||||
time_support.c
|
||||
directory_posix.c
|
||||
directory_win.c
|
||||
|
||||
${CRYPTO_ARCH_SOURCES}
|
||||
${CRYPTO_ARCH_SOURCES}
|
||||
|
||||
$<TARGET_OBJECTS:stack>
|
||||
$<TARGET_OBJECTS:lhash>
|
||||
$<TARGET_OBJECTS:err>
|
||||
$<TARGET_OBJECTS:base64>
|
||||
$<TARGET_OBJECTS:bytestring>
|
||||
$<TARGET_OBJECTS:sha>
|
||||
$<TARGET_OBJECTS:md4>
|
||||
$<TARGET_OBJECTS:md5>
|
||||
$<TARGET_OBJECTS:digest>
|
||||
$<TARGET_OBJECTS:cipher>
|
||||
$<TARGET_OBJECTS:modes>
|
||||
$<TARGET_OBJECTS:aes>
|
||||
$<TARGET_OBJECTS:des>
|
||||
$<TARGET_OBJECTS:rc4>
|
||||
$<TARGET_OBJECTS:conf>
|
||||
$<TARGET_OBJECTS:chacha>
|
||||
$<TARGET_OBJECTS:poly1305>
|
||||
$<TARGET_OBJECTS:curve25519>
|
||||
$<TARGET_OBJECTS:buf>
|
||||
$<TARGET_OBJECTS:bn>
|
||||
$<TARGET_OBJECTS:bio>
|
||||
$<TARGET_OBJECTS:rand>
|
||||
$<TARGET_OBJECTS:obj>
|
||||
$<TARGET_OBJECTS:asn1>
|
||||
$<TARGET_OBJECTS:engine>
|
||||
$<TARGET_OBJECTS:dh>
|
||||
$<TARGET_OBJECTS:dsa>
|
||||
$<TARGET_OBJECTS:rsa>
|
||||
$<TARGET_OBJECTS:ec>
|
||||
$<TARGET_OBJECTS:ecdh>
|
||||
$<TARGET_OBJECTS:ecdsa>
|
||||
$<TARGET_OBJECTS:hmac>
|
||||
$<TARGET_OBJECTS:cmac>
|
||||
$<TARGET_OBJECTS:evp>
|
||||
$<TARGET_OBJECTS:hkdf>
|
||||
$<TARGET_OBJECTS:pem>
|
||||
$<TARGET_OBJECTS:x509>
|
||||
$<TARGET_OBJECTS:x509v3>
|
||||
$<TARGET_OBJECTS:pkcs8>
|
||||
$<TARGET_OBJECTS:stack>
|
||||
$<TARGET_OBJECTS:lhash>
|
||||
$<TARGET_OBJECTS:err>
|
||||
$<TARGET_OBJECTS:base64>
|
||||
$<TARGET_OBJECTS:bytestring>
|
||||
$<TARGET_OBJECTS:sha>
|
||||
$<TARGET_OBJECTS:md4>
|
||||
$<TARGET_OBJECTS:md5>
|
||||
$<TARGET_OBJECTS:digest>
|
||||
$<TARGET_OBJECTS:cipher>
|
||||
$<TARGET_OBJECTS:modes>
|
||||
$<TARGET_OBJECTS:aes>
|
||||
$<TARGET_OBJECTS:des>
|
||||
$<TARGET_OBJECTS:rc4>
|
||||
$<TARGET_OBJECTS:conf>
|
||||
$<TARGET_OBJECTS:chacha>
|
||||
$<TARGET_OBJECTS:poly1305>
|
||||
$<TARGET_OBJECTS:buf>
|
||||
$<TARGET_OBJECTS:bn>
|
||||
$<TARGET_OBJECTS:bio>
|
||||
$<TARGET_OBJECTS:rand>
|
||||
$<TARGET_OBJECTS:obj>
|
||||
$<TARGET_OBJECTS:asn1>
|
||||
$<TARGET_OBJECTS:engine>
|
||||
$<TARGET_OBJECTS:dh>
|
||||
$<TARGET_OBJECTS:dsa>
|
||||
$<TARGET_OBJECTS:rsa>
|
||||
$<TARGET_OBJECTS:ec>
|
||||
$<TARGET_OBJECTS:ecdh>
|
||||
$<TARGET_OBJECTS:ecdsa>
|
||||
$<TARGET_OBJECTS:hmac>
|
||||
$<TARGET_OBJECTS:evp>
|
||||
$<TARGET_OBJECTS:pem>
|
||||
$<TARGET_OBJECTS:x509>
|
||||
$<TARGET_OBJECTS:x509v3>
|
||||
$<TARGET_OBJECTS:pkcs8>
|
||||
)
|
||||
|
||||
if(NOT MSVC AND NOT ANDROID)
|
||||
target_link_libraries(crypto pthread)
|
||||
endif()
|
||||
|
||||
add_executable(
|
||||
constant_time_test
|
||||
|
||||
constant_time_test.c
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(constant_time_test crypto)
|
||||
add_dependencies(all_tests constant_time_test)
|
||||
|
||||
add_executable(
|
||||
thread_test
|
||||
|
||||
thread_test.c
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(thread_test crypto)
|
||||
add_dependencies(all_tests thread_test)
|
||||
|
||||
add_executable(
|
||||
refcount_test
|
||||
|
||||
refcount_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(refcount_test crypto)
|
||||
add_dependencies(all_tests refcount_test)
|
||||
perlasm(cpu-x86_64-asm.${ASM_EXT} cpu-x86_64-asm.pl)
|
||||
perlasm(cpu-x86-asm.${ASM_EXT} cpu-x86-asm.pl)
|
||||
|
||||
+24
-44
@@ -1,53 +1,44 @@
|
||||
include_directories(../../include)
|
||||
include_directories(. .. ../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aes-x86_64.${ASM_EXT}
|
||||
aesni-x86_64.${ASM_EXT}
|
||||
bsaes-x86_64.${ASM_EXT}
|
||||
vpaes-x86_64.${ASM_EXT}
|
||||
)
|
||||
aes-x86_64.${ASM_EXT}
|
||||
aesni-x86_64.${ASM_EXT}
|
||||
bsaes-x86_64.${ASM_EXT}
|
||||
vpaes-x86_64.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aes-586.${ASM_EXT}
|
||||
vpaes-x86.${ASM_EXT}
|
||||
aesni-x86.${ASM_EXT}
|
||||
)
|
||||
aes-586.${ASM_EXT}
|
||||
vpaes-x86.${ASM_EXT}
|
||||
aesni-x86.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aes-armv4.${ASM_EXT}
|
||||
bsaes-armv7.${ASM_EXT}
|
||||
aesv8-armx.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aesv8-armx.${ASM_EXT}
|
||||
)
|
||||
aes-armv4.${ASM_EXT}
|
||||
bsaes-armv7.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
aes
|
||||
aes
|
||||
|
||||
OBJECT
|
||||
OBJECT
|
||||
|
||||
aes.c
|
||||
mode_wrappers.c
|
||||
aes.c
|
||||
mode_wrappers.c
|
||||
|
||||
${AES_ARCH_SOURCES}
|
||||
${AES_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
perlasm(aes-x86_64.${ASM_EXT} asm/aes-x86_64.pl)
|
||||
@@ -59,14 +50,3 @@ perlasm(vpaes-x86.${ASM_EXT} asm/vpaes-x86.pl)
|
||||
perlasm(aesni-x86.${ASM_EXT} asm/aesni-x86.pl)
|
||||
perlasm(aes-armv4.${ASM_EXT} asm/aes-armv4.pl)
|
||||
perlasm(bsaes-armv7.${ASM_EXT} asm/bsaes-armv7.pl)
|
||||
perlasm(aesv8-armx.${ASM_EXT} asm/aesv8-armx.pl)
|
||||
|
||||
add_executable(
|
||||
aes_test
|
||||
|
||||
aes_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(aes_test crypto)
|
||||
add_dependencies(all_tests aes_test)
|
||||
|
||||
+38
-77
@@ -49,9 +49,6 @@
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openssl/cpu.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -528,6 +525,32 @@ static const uint8_t Td4[256] = {
|
||||
0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U,
|
||||
0x21U, 0x0cU, 0x7dU, };
|
||||
|
||||
static const uint8_t Te4[256] = {
|
||||
0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, 0x30U, 0x01U, 0x67U,
|
||||
0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U,
|
||||
0x47U, 0xf0U, 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, 0xb7U,
|
||||
0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, 0x34U, 0xa5U, 0xe5U, 0xf1U,
|
||||
0x71U, 0xd8U, 0x31U, 0x15U, 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U,
|
||||
0x9aU, 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, 0x09U, 0x83U,
|
||||
0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U,
|
||||
0xe3U, 0x2fU, 0x84U, 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU,
|
||||
0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, 0xd0U, 0xefU, 0xaaU,
|
||||
0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU,
|
||||
0x9fU, 0xa8U, 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, 0xbcU,
|
||||
0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, 0xcdU, 0x0cU, 0x13U, 0xecU,
|
||||
0x5fU, 0x97U, 0x44U, 0x17U, 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U,
|
||||
0x73U, 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, 0x46U, 0xeeU,
|
||||
0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U,
|
||||
0x06U, 0x24U, 0x5cU, 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U,
|
||||
0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, 0x6cU, 0x56U, 0xf4U,
|
||||
0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U,
|
||||
0xb4U, 0xc6U, 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, 0x70U,
|
||||
0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, 0x61U, 0x35U, 0x57U, 0xb9U,
|
||||
0x86U, 0xc1U, 0x1dU, 0x9eU, 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU,
|
||||
0x94U, 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, 0x8cU, 0xa1U,
|
||||
0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U,
|
||||
0x54U, 0xbbU, 0x16U};
|
||||
|
||||
static const uint32_t rcon[] = {
|
||||
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
||||
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
|
||||
@@ -1036,68 +1059,22 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
#endif /* ?FULL_UNROLL */
|
||||
/* apply last round and
|
||||
* map cipher state to byte array block: */
|
||||
s0 = ((uint32_t)Td4[(t0 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t3 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t2 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t1) & 0xff]) ^ rk[0];
|
||||
s0 = (Td4[(t0 >> 24)] << 24) ^ (Td4[(t3 >> 16) & 0xff] << 16) ^
|
||||
(Td4[(t2 >> 8) & 0xff] << 8) ^ (Td4[(t1) & 0xff]) ^ rk[0];
|
||||
PUTU32(out, s0);
|
||||
s1 = ((uint32_t)Td4[(t1 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t0 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t3 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t2) & 0xff]) ^ rk[1];
|
||||
s1 = (Td4[(t1 >> 24)] << 24) ^ (Td4[(t0 >> 16) & 0xff] << 16) ^
|
||||
(Td4[(t3 >> 8) & 0xff] << 8) ^ (Td4[(t2) & 0xff]) ^ rk[1];
|
||||
PUTU32(out + 4, s1);
|
||||
s2 = ((uint32_t)Td4[(t2 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t1 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t0 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t3) & 0xff]) ^ rk[2];
|
||||
s2 = (Td4[(t2 >> 24)] << 24) ^ (Td4[(t1 >> 16) & 0xff] << 16) ^
|
||||
(Td4[(t0 >> 8) & 0xff] << 8) ^ (Td4[(t3) & 0xff]) ^ rk[2];
|
||||
PUTU32(out + 8, s2);
|
||||
s3 = ((uint32_t)Td4[(t3 >> 24)] << 24) ^
|
||||
((uint32_t)Td4[(t2 >> 16) & 0xff] << 16) ^
|
||||
((uint32_t)Td4[(t1 >> 8) & 0xff] << 8) ^
|
||||
((uint32_t)Td4[(t0) & 0xff]) ^ rk[3];
|
||||
s3 = (Td4[(t3 >> 24)] << 24) ^ (Td4[(t2 >> 16) & 0xff] << 16) ^
|
||||
(Td4[(t1 >> 8) & 0xff] << 8) ^ (Td4[(t0) & 0xff]) ^ rk[3];
|
||||
PUTU32(out + 12, s3);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
|
||||
|
||||
static int hwaes_capable(void) {
|
||||
return CRYPTO_is_ARMv8_AES_capable();
|
||||
}
|
||||
|
||||
int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits,
|
||||
AES_KEY *key);
|
||||
int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits,
|
||||
AES_KEY *key);
|
||||
void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
|
||||
#else
|
||||
|
||||
static int hwaes_capable(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* In this case several functions are provided by asm code. However, one cannot
|
||||
* control asm symbol visibility with command line flags and such so they are
|
||||
* always hidden and wrapped by these C functions, which can be so
|
||||
@@ -1105,38 +1082,22 @@ static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key)
|
||||
|
||||
void asm_AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
if (hwaes_capable()) {
|
||||
aes_v8_encrypt(in, out, key);
|
||||
} else {
|
||||
asm_AES_encrypt(in, out, key);
|
||||
}
|
||||
asm_AES_encrypt(in, out, key);
|
||||
}
|
||||
|
||||
void asm_AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
if (hwaes_capable()) {
|
||||
aes_v8_decrypt(in, out, key);
|
||||
} else {
|
||||
asm_AES_decrypt(in, out, key);
|
||||
}
|
||||
asm_AES_decrypt(in, out, key);
|
||||
}
|
||||
|
||||
int asm_AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
|
||||
int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
|
||||
if (hwaes_capable()) {
|
||||
return aes_v8_set_encrypt_key(key, bits, aeskey);
|
||||
} else {
|
||||
return asm_AES_set_encrypt_key(key, bits, aeskey);
|
||||
}
|
||||
return asm_AES_set_encrypt_key(key, bits, aeskey);
|
||||
}
|
||||
|
||||
int asm_AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
|
||||
int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
|
||||
if (hwaes_capable()) {
|
||||
return aes_v8_set_decrypt_key(key, bits, aeskey);
|
||||
} else {
|
||||
return asm_AES_set_decrypt_key(key, bits, aeskey);
|
||||
}
|
||||
return asm_AES_set_decrypt_key(key, bits, aeskey);
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86 && !OPENSSL_X86_64 && !OPENSSL_ARM) */
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
|
||||
static bool TestAES(const uint8_t *key, size_t key_len,
|
||||
const uint8_t plaintext[AES_BLOCK_SIZE],
|
||||
const uint8_t ciphertext[AES_BLOCK_SIZE]) {
|
||||
AES_KEY aes_key;
|
||||
if (AES_set_encrypt_key(key, key_len * 8, &aes_key) != 0) {
|
||||
fprintf(stderr, "AES_set_encrypt_key failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test encryption.
|
||||
uint8_t block[AES_BLOCK_SIZE];
|
||||
AES_encrypt(plaintext, block, &aes_key);
|
||||
if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_encrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place encryption.
|
||||
memcpy(block, plaintext, AES_BLOCK_SIZE);
|
||||
AES_encrypt(block, block, &aes_key);
|
||||
if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_encrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AES_set_decrypt_key(key, key_len * 8, &aes_key) != 0) {
|
||||
fprintf(stderr, "AES_set_decrypt_key failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test decryption.
|
||||
AES_decrypt(ciphertext, block, &aes_key);
|
||||
if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_decrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place decryption.
|
||||
memcpy(block, ciphertext, AES_BLOCK_SIZE);
|
||||
AES_decrypt(block, block, &aes_key);
|
||||
if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
|
||||
fprintf(stderr, "AES_decrypt gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
// Test vectors from FIPS-197, Appendix C.
|
||||
if (!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
|
||||
128 / 8,
|
||||
(const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
|
||||
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
|
||||
(const uint8_t *)"\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
|
||||
"\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a") ||
|
||||
!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17",
|
||||
192 / 8,
|
||||
(const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
|
||||
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
|
||||
(const uint8_t *)"\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
|
||||
"\x6e\xaf\x70\xa0\xec\x0d\x71\x91") ||
|
||||
!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
|
||||
"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17"
|
||||
"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
|
||||
256 / 8,
|
||||
(const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
|
||||
"\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
|
||||
(const uint8_t *)"\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
|
||||
"\xea\xfc\x49\x90\x4b\x49\x60\x89")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -45,7 +45,7 @@
|
||||
# the undertaken effort was that it appeared that in tight IA-32
|
||||
# register window little-endian flavor could achieve slightly higher
|
||||
# Instruction Level Parallelism, and it indeed resulted in up to 15%
|
||||
# better performance on most recent µ-archs...
|
||||
# better performance on most recent µ-archs...
|
||||
#
|
||||
# Third version adds AES_cbc_encrypt implementation, which resulted in
|
||||
# up to 40% performance imrovement of CBC benchmark results. 40% was
|
||||
@@ -224,7 +224,7 @@ sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } }
|
||||
$speed_limit=512; # chunks smaller than $speed_limit are
|
||||
# processed with compact routine in CBC mode
|
||||
$small_footprint=1; # $small_footprint=1 code is ~5% slower [on
|
||||
# recent µ-archs], but ~5 times smaller!
|
||||
# recent µ-archs], but ~5 times smaller!
|
||||
# I favor compact code to minimize cache
|
||||
# contention and in hope to "collect" 5% back
|
||||
# in real-life applications...
|
||||
@@ -565,7 +565,7 @@ sub enctransform()
|
||||
# Performance is not actually extraordinary in comparison to pure
|
||||
# x86 code. In particular encrypt performance is virtually the same.
|
||||
# Decrypt performance on the other hand is 15-20% better on newer
|
||||
# µ-archs [but we're thankful for *any* improvement here], and ~50%
|
||||
# µ-archs [but we're thankful for *any* improvement here], and ~50%
|
||||
# better on PIII:-) And additionally on the pros side this code
|
||||
# eliminates redundant references to stack and thus relieves/
|
||||
# minimizes the pressure on the memory bus.
|
||||
|
||||
+15
-35
@@ -32,20 +32,8 @@
|
||||
# Profiler-assisted and platform-specific optimization resulted in 16%
|
||||
# improvement on Cortex A8 core and ~21.5 cycles per byte.
|
||||
|
||||
$flavour = shift;
|
||||
if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
|
||||
else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
|
||||
|
||||
if ($flavour && $flavour ne "void") {
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
|
||||
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
|
||||
die "can't locate arm-xlate.pl";
|
||||
|
||||
open STDOUT,"| \"$^X\" $xlate $flavour $output";
|
||||
} else {
|
||||
open STDOUT,">$output";
|
||||
}
|
||||
while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
|
||||
open STDOUT,">$output";
|
||||
|
||||
$s0="r0";
|
||||
$s1="r1";
|
||||
@@ -65,7 +53,7 @@ $rounds="r12";
|
||||
$code=<<___;
|
||||
#if defined(__arm__)
|
||||
#ifndef __KERNEL__
|
||||
# include <openssl/arm_arch.h>
|
||||
# include "arm_arch.h"
|
||||
#else
|
||||
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
|
||||
#endif
|
||||
@@ -75,7 +63,7 @@ $code=<<___;
|
||||
.code 32
|
||||
#else
|
||||
.syntax unified
|
||||
# if defined(__thumb2__) && !defined(__APPLE__)
|
||||
# ifdef __thumb2__
|
||||
.thumb
|
||||
# else
|
||||
.code 32
|
||||
@@ -191,6 +179,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:
|
||||
@@ -200,13 +189,9 @@ asm_AES_encrypt:
|
||||
adr r3,asm_AES_encrypt
|
||||
#endif
|
||||
stmdb sp!,{r1,r4-r12,lr}
|
||||
#ifdef __APPLE__
|
||||
adr $tbl,AES_Te
|
||||
#else
|
||||
sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te
|
||||
#endif
|
||||
mov $rounds,r0 @ inp
|
||||
mov $key,r2
|
||||
sub $tbl,r3,#asm_AES_encrypt-AES_Te @ Te
|
||||
#if __ARM_ARCH__<7
|
||||
ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
|
||||
ldrb $t1,[$rounds,#2] @ manner...
|
||||
@@ -440,6 +425,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:
|
||||
@@ -474,16 +460,12 @@ _armv4_AES_set_encrypt_key:
|
||||
bne .Labrt
|
||||
|
||||
.Lok: stmdb sp!,{r4-r12,lr}
|
||||
sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
|
||||
|
||||
mov $rounds,r0 @ inp
|
||||
mov lr,r1 @ bits
|
||||
mov $key,r2 @ key
|
||||
|
||||
#ifdef __APPLE__
|
||||
adr $tbl,AES_Te+1024 @ Te4
|
||||
#else
|
||||
sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH__<7
|
||||
ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
|
||||
ldrb $t1,[$rounds,#2] @ manner...
|
||||
@@ -736,8 +718,8 @@ _armv4_AES_set_encrypt_key:
|
||||
.Ldone: mov r0,#0
|
||||
ldmia sp!,{r4-r12,lr}
|
||||
.Labrt:
|
||||
#if __ARM_ARCH__>=5
|
||||
ret @ bx lr
|
||||
#if defined(__thumb2__) && __ARM_ARCH__>=7
|
||||
.short 0x4770 @ bx lr in Thumb2 encoding
|
||||
#else
|
||||
tst lr,#1
|
||||
moveq pc,lr @ be binary compatible with V4, yet
|
||||
@@ -746,6 +728,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 +745,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 +951,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:
|
||||
@@ -976,13 +961,9 @@ asm_AES_decrypt:
|
||||
adr r3,asm_AES_decrypt
|
||||
#endif
|
||||
stmdb sp!,{r1,r4-r12,lr}
|
||||
#ifdef __APPLE__
|
||||
adr $tbl,AES_Td
|
||||
#else
|
||||
sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td
|
||||
#endif
|
||||
mov $rounds,r0 @ inp
|
||||
mov $key,r2
|
||||
sub $tbl,r3,#asm_AES_decrypt-AES_Td @ Td
|
||||
#if __ARM_ARCH__<7
|
||||
ldrb $s0,[$rounds,#3] @ load input data in endian-neutral
|
||||
ldrb $t1,[$rounds,#2] @ manner...
|
||||
@@ -1230,7 +1211,6 @@ _armv4_AES_decrypt:
|
||||
___
|
||||
|
||||
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
|
||||
$code =~ s/\bret\b/bx\tlr/gm;
|
||||
|
||||
open SELF,$0;
|
||||
while(<SELF>) {
|
||||
|
||||
+14
-307
@@ -51,7 +51,7 @@
|
||||
# Westmere 3.77/1.37 1.37 1.52 1.27
|
||||
# * Bridge 5.07/0.98 0.99 1.09 0.91
|
||||
# Haswell 4.44/0.80 0.97 1.03 0.72
|
||||
# Silvermont 5.77/3.56 3.67 4.03 3.46
|
||||
# Atom 5.77/3.56 3.67 4.03 3.46
|
||||
# Bulldozer 5.80/0.98 1.05 1.24 0.93
|
||||
|
||||
$PREFIX="aesni"; # if $PREFIX is set to "AES", the script
|
||||
@@ -65,9 +65,6 @@ require "x86asm.pl";
|
||||
|
||||
&asm_init($ARGV[0],$0);
|
||||
|
||||
&external_label("OPENSSL_ia32cap_P");
|
||||
&static_label("key_const");
|
||||
|
||||
if ($PREFIX eq "aesni") { $movekey=\&movups; }
|
||||
else { $movekey=\&movups; }
|
||||
|
||||
@@ -88,7 +85,7 @@ $inout3="xmm5"; $in1="xmm5";
|
||||
$inout4="xmm6"; $in0="xmm6";
|
||||
$inout5="xmm7"; $ivec="xmm7";
|
||||
|
||||
# AESNI extension
|
||||
# AESNI extenstion
|
||||
sub aeskeygenassist
|
||||
{ my($dst,$src,$imm)=@_;
|
||||
if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
|
||||
@@ -184,10 +181,7 @@ sub aesni_generate1 # fully unrolled loop
|
||||
{ &aesni_inline_generate1("enc"); }
|
||||
else
|
||||
{ &call ("_aesni_encrypt1"); }
|
||||
&pxor ($rndkey0,$rndkey0); # clear register bank
|
||||
&pxor ($rndkey1,$rndkey1);
|
||||
&movups (&QWP(0,"eax"),$inout0);
|
||||
&pxor ($inout0,$inout0);
|
||||
&ret ();
|
||||
&function_end_B("${PREFIX}_encrypt");
|
||||
|
||||
@@ -203,10 +197,7 @@ sub aesni_generate1 # fully unrolled loop
|
||||
{ &aesni_inline_generate1("dec"); }
|
||||
else
|
||||
{ &call ("_aesni_decrypt1"); }
|
||||
&pxor ($rndkey0,$rndkey0); # clear register bank
|
||||
&pxor ($rndkey1,$rndkey1);
|
||||
&movups (&QWP(0,"eax"),$inout0);
|
||||
&pxor ($inout0,$inout0);
|
||||
&ret ();
|
||||
&function_end_B("${PREFIX}_decrypt");
|
||||
|
||||
@@ -358,15 +349,17 @@ sub aesni_generate6
|
||||
&neg ($rounds);
|
||||
eval"&aes${p} ($inout2,$rndkey1)";
|
||||
&pxor ($inout5,$rndkey0);
|
||||
&$movekey ($rndkey0,&QWP(0,$key,$rounds));
|
||||
&add ($rounds,16);
|
||||
&jmp (&label("_aesni_${p}rypt6_inner"));
|
||||
eval"&aes${p} ($inout3,$rndkey1)";
|
||||
eval"&aes${p} ($inout4,$rndkey1)";
|
||||
eval"&aes${p} ($inout5,$rndkey1)";
|
||||
&$movekey ($rndkey0,&QWP(-16,$key,$rounds));
|
||||
&jmp (&label("_aesni_${p}rypt6_enter"));
|
||||
|
||||
&set_label("${p}6_loop",16);
|
||||
eval"&aes${p} ($inout0,$rndkey1)";
|
||||
eval"&aes${p} ($inout1,$rndkey1)";
|
||||
eval"&aes${p} ($inout2,$rndkey1)";
|
||||
&set_label("_aesni_${p}rypt6_inner");
|
||||
eval"&aes${p} ($inout3,$rndkey1)";
|
||||
eval"&aes${p} ($inout4,$rndkey1)";
|
||||
eval"&aes${p} ($inout5,$rndkey1)";
|
||||
@@ -622,14 +615,6 @@ if ($PREFIX eq "aesni") {
|
||||
&movups (&QWP(0x30,$out),$inout3);
|
||||
|
||||
&set_label("ecb_ret");
|
||||
&pxor ("xmm0","xmm0"); # clear register bank
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&pxor ("xmm3","xmm3");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&pxor ("xmm5","xmm5");
|
||||
&pxor ("xmm6","xmm6");
|
||||
&pxor ("xmm7","xmm7");
|
||||
&function_end("aesni_ecb_encrypt");
|
||||
|
||||
######################################################################
|
||||
@@ -719,15 +704,6 @@ if ($PREFIX eq "aesni") {
|
||||
&mov ("esp",&DWP(48,"esp"));
|
||||
&mov ($out,&wparam(5));
|
||||
&movups (&QWP(0,$out),$cmac);
|
||||
|
||||
&pxor ("xmm0","xmm0"); # clear register bank
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&pxor ("xmm3","xmm3");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&pxor ("xmm5","xmm5");
|
||||
&pxor ("xmm6","xmm6");
|
||||
&pxor ("xmm7","xmm7");
|
||||
&function_end("aesni_ccm64_encrypt_blocks");
|
||||
|
||||
&function_begin("aesni_ccm64_decrypt_blocks");
|
||||
@@ -828,15 +804,6 @@ if ($PREFIX eq "aesni") {
|
||||
&mov ("esp",&DWP(48,"esp"));
|
||||
&mov ($out,&wparam(5));
|
||||
&movups (&QWP(0,$out),$cmac);
|
||||
|
||||
&pxor ("xmm0","xmm0"); # clear register bank
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&pxor ("xmm3","xmm3");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&pxor ("xmm5","xmm5");
|
||||
&pxor ("xmm6","xmm6");
|
||||
&pxor ("xmm7","xmm7");
|
||||
&function_end("aesni_ccm64_decrypt_blocks");
|
||||
}
|
||||
|
||||
@@ -1086,17 +1053,6 @@ if ($PREFIX eq "aesni") {
|
||||
&movups (&QWP(0x30,$out),$inout3);
|
||||
|
||||
&set_label("ctr32_ret");
|
||||
&pxor ("xmm0","xmm0"); # clear register bank
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&pxor ("xmm3","xmm3");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&movdqa (&QWP(32,"esp"),"xmm0"); # clear stack
|
||||
&pxor ("xmm5","xmm5");
|
||||
&movdqa (&QWP(48,"esp"),"xmm0");
|
||||
&pxor ("xmm6","xmm6");
|
||||
&movdqa (&QWP(64,"esp"),"xmm0");
|
||||
&pxor ("xmm7","xmm7");
|
||||
&mov ("esp",&DWP(80,"esp"));
|
||||
&function_end("aesni_ctr32_encrypt_blocks");
|
||||
|
||||
@@ -1438,20 +1394,6 @@ if ($PREFIX eq "aesni") {
|
||||
&movups (&QWP(-16,$out),$inout0); # write output
|
||||
|
||||
&set_label("xts_enc_ret");
|
||||
&pxor ("xmm0","xmm0"); # clear register bank
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack
|
||||
&pxor ("xmm3","xmm3");
|
||||
&movdqa (&QWP(16*1,"esp"),"xmm0");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&movdqa (&QWP(16*2,"esp"),"xmm0");
|
||||
&pxor ("xmm5","xmm5");
|
||||
&movdqa (&QWP(16*3,"esp"),"xmm0");
|
||||
&pxor ("xmm6","xmm6");
|
||||
&movdqa (&QWP(16*4,"esp"),"xmm0");
|
||||
&pxor ("xmm7","xmm7");
|
||||
&movdqa (&QWP(16*5,"esp"),"xmm0");
|
||||
&mov ("esp",&DWP(16*7+4,"esp")); # restore %esp
|
||||
&function_end("aesni_xts_encrypt");
|
||||
|
||||
@@ -1814,20 +1756,6 @@ if ($PREFIX eq "aesni") {
|
||||
&movups (&QWP(0,$out),$inout0); # write output
|
||||
|
||||
&set_label("xts_dec_ret");
|
||||
&pxor ("xmm0","xmm0"); # clear register bank
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&movdqa (&QWP(16*0,"esp"),"xmm0"); # clear stack
|
||||
&pxor ("xmm3","xmm3");
|
||||
&movdqa (&QWP(16*1,"esp"),"xmm0");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&movdqa (&QWP(16*2,"esp"),"xmm0");
|
||||
&pxor ("xmm5","xmm5");
|
||||
&movdqa (&QWP(16*3,"esp"),"xmm0");
|
||||
&pxor ("xmm6","xmm6");
|
||||
&movdqa (&QWP(16*4,"esp"),"xmm0");
|
||||
&pxor ("xmm7","xmm7");
|
||||
&movdqa (&QWP(16*5,"esp"),"xmm0");
|
||||
&mov ("esp",&DWP(16*7+4,"esp")); # restore %esp
|
||||
&function_end("aesni_xts_decrypt");
|
||||
}
|
||||
@@ -1880,7 +1808,6 @@ if ($PREFIX eq "aesni") {
|
||||
&add ($len,16);
|
||||
&jnz (&label("cbc_enc_tail"));
|
||||
&movaps ($ivec,$inout0);
|
||||
&pxor ($inout0,$inout0);
|
||||
&jmp (&label("cbc_ret"));
|
||||
|
||||
&set_label("cbc_enc_tail");
|
||||
@@ -1944,7 +1871,7 @@ if ($PREFIX eq "aesni") {
|
||||
&movaps ($inout0,$inout5);
|
||||
&movaps ($ivec,$rndkey0);
|
||||
&add ($len,0x50);
|
||||
&jle (&label("cbc_dec_clear_tail_collected"));
|
||||
&jle (&label("cbc_dec_tail_collected"));
|
||||
&movups (&QWP(0,$out),$inout0);
|
||||
&lea ($out,&DWP(0x10,$out));
|
||||
&set_label("cbc_dec_tail");
|
||||
@@ -1983,14 +1910,10 @@ if ($PREFIX eq "aesni") {
|
||||
&xorps ($inout4,$rndkey0);
|
||||
&movups (&QWP(0,$out),$inout0);
|
||||
&movups (&QWP(0x10,$out),$inout1);
|
||||
&pxor ($inout1,$inout1);
|
||||
&movups (&QWP(0x20,$out),$inout2);
|
||||
&pxor ($inout2,$inout2);
|
||||
&movups (&QWP(0x30,$out),$inout3);
|
||||
&pxor ($inout3,$inout3);
|
||||
&lea ($out,&DWP(0x40,$out));
|
||||
&movaps ($inout0,$inout4);
|
||||
&pxor ($inout4,$inout4);
|
||||
&sub ($len,0x50);
|
||||
&jmp (&label("cbc_dec_tail_collected"));
|
||||
|
||||
@@ -2010,7 +1933,6 @@ if ($PREFIX eq "aesni") {
|
||||
&xorps ($inout1,$in0);
|
||||
&movups (&QWP(0,$out),$inout0);
|
||||
&movaps ($inout0,$inout1);
|
||||
&pxor ($inout1,$inout1);
|
||||
&lea ($out,&DWP(0x10,$out));
|
||||
&movaps ($ivec,$in1);
|
||||
&sub ($len,0x20);
|
||||
@@ -2023,9 +1945,7 @@ if ($PREFIX eq "aesni") {
|
||||
&xorps ($inout2,$in1);
|
||||
&movups (&QWP(0,$out),$inout0);
|
||||
&movaps ($inout0,$inout2);
|
||||
&pxor ($inout2,$inout2);
|
||||
&movups (&QWP(0x10,$out),$inout1);
|
||||
&pxor ($inout1,$inout1);
|
||||
&lea ($out,&DWP(0x20,$out));
|
||||
&movups ($ivec,&QWP(0x20,$inp));
|
||||
&sub ($len,0x30);
|
||||
@@ -2041,44 +1961,29 @@ if ($PREFIX eq "aesni") {
|
||||
&movups (&QWP(0,$out),$inout0);
|
||||
&xorps ($inout2,$rndkey1);
|
||||
&movups (&QWP(0x10,$out),$inout1);
|
||||
&pxor ($inout1,$inout1);
|
||||
&xorps ($inout3,$rndkey0);
|
||||
&movups (&QWP(0x20,$out),$inout2);
|
||||
&pxor ($inout2,$inout2);
|
||||
&lea ($out,&DWP(0x30,$out));
|
||||
&movaps ($inout0,$inout3);
|
||||
&pxor ($inout3,$inout3);
|
||||
&sub ($len,0x40);
|
||||
&jmp (&label("cbc_dec_tail_collected"));
|
||||
|
||||
&set_label("cbc_dec_clear_tail_collected",16);
|
||||
&pxor ($inout1,$inout1);
|
||||
&pxor ($inout2,$inout2);
|
||||
&pxor ($inout3,$inout3);
|
||||
&pxor ($inout4,$inout4);
|
||||
&set_label("cbc_dec_tail_collected");
|
||||
&and ($len,15);
|
||||
&jnz (&label("cbc_dec_tail_partial"));
|
||||
&movups (&QWP(0,$out),$inout0);
|
||||
&pxor ($rndkey0,$rndkey0);
|
||||
&jmp (&label("cbc_ret"));
|
||||
|
||||
&set_label("cbc_dec_tail_partial",16);
|
||||
&movaps (&QWP(0,"esp"),$inout0);
|
||||
&pxor ($rndkey0,$rndkey0);
|
||||
&mov ("ecx",16);
|
||||
&mov ($inp,"esp");
|
||||
&sub ("ecx",$len);
|
||||
&data_word(0xA4F3F689); # rep movsb
|
||||
&movdqa (&QWP(0,"esp"),$inout0);
|
||||
|
||||
&set_label("cbc_ret");
|
||||
&mov ("esp",&DWP(16,"esp")); # pull original %esp
|
||||
&mov ($key_,&wparam(4));
|
||||
&pxor ($inout0,$inout0);
|
||||
&pxor ($rndkey1,$rndkey1);
|
||||
&movups (&QWP(0,$key_),$ivec); # output IV
|
||||
&pxor ($ivec,$ivec);
|
||||
&set_label("cbc_abort");
|
||||
&function_end("${PREFIX}_cbc_encrypt");
|
||||
|
||||
@@ -2095,24 +2000,14 @@ if ($PREFIX eq "aesni") {
|
||||
# $round rounds
|
||||
|
||||
&function_begin_B("_aesni_set_encrypt_key");
|
||||
&push ("ebp");
|
||||
&push ("ebx");
|
||||
&test ("eax","eax");
|
||||
&jz (&label("bad_pointer"));
|
||||
&test ($key,$key);
|
||||
&jz (&label("bad_pointer"));
|
||||
|
||||
&call (&label("pic"));
|
||||
&set_label("pic");
|
||||
&blindpop("ebx");
|
||||
&lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx"));
|
||||
|
||||
&picmeup("ebp","OPENSSL_ia32cap_P","ebx",&label("key_const"));
|
||||
&movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey
|
||||
&xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0
|
||||
&mov ("ebp",&DWP(4,"ebp"));
|
||||
&lea ($key,&DWP(16,$key));
|
||||
&and ("ebp",1<<28|1<<11); # AVX and XOP bits
|
||||
&cmp ($rounds,256);
|
||||
&je (&label("14rounds"));
|
||||
&cmp ($rounds,192);
|
||||
@@ -2121,9 +2016,6 @@ if ($PREFIX eq "aesni") {
|
||||
&jne (&label("bad_keybits"));
|
||||
|
||||
&set_label("10rounds",16);
|
||||
&cmp ("ebp",1<<28);
|
||||
&je (&label("10rounds_alt"));
|
||||
|
||||
&mov ($rounds,9);
|
||||
&$movekey (&QWP(-16,$key),"xmm0"); # round 0
|
||||
&aeskeygenassist("xmm1","xmm0",0x01); # round 1
|
||||
@@ -2148,8 +2040,8 @@ if ($PREFIX eq "aesni") {
|
||||
&call (&label("key_128"));
|
||||
&$movekey (&QWP(0,$key),"xmm0");
|
||||
&mov (&DWP(80,$key),$rounds);
|
||||
|
||||
&jmp (&label("good_key"));
|
||||
&xor ("eax","eax");
|
||||
&ret();
|
||||
|
||||
&set_label("key_128",16);
|
||||
&$movekey (&QWP(0,$key),"xmm0");
|
||||
@@ -2163,76 +2055,8 @@ if ($PREFIX eq "aesni") {
|
||||
&xorps ("xmm0","xmm1");
|
||||
&ret();
|
||||
|
||||
&set_label("10rounds_alt",16);
|
||||
&movdqa ("xmm5",&QWP(0x00,"ebx"));
|
||||
&mov ($rounds,8);
|
||||
&movdqa ("xmm4",&QWP(0x20,"ebx"));
|
||||
&movdqa ("xmm2","xmm0");
|
||||
&movdqu (&QWP(-16,$key),"xmm0");
|
||||
|
||||
&set_label("loop_key128");
|
||||
&pshufb ("xmm0","xmm5");
|
||||
&aesenclast ("xmm0","xmm4");
|
||||
&pslld ("xmm4",1);
|
||||
&lea ($key,&DWP(16,$key));
|
||||
|
||||
&movdqa ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm2","xmm3");
|
||||
|
||||
&pxor ("xmm0","xmm2");
|
||||
&movdqu (&QWP(-16,$key),"xmm0");
|
||||
&movdqa ("xmm2","xmm0");
|
||||
|
||||
&dec ($rounds);
|
||||
&jnz (&label("loop_key128"));
|
||||
|
||||
&movdqa ("xmm4",&QWP(0x30,"ebx"));
|
||||
|
||||
&pshufb ("xmm0","xmm5");
|
||||
&aesenclast ("xmm0","xmm4");
|
||||
&pslld ("xmm4",1);
|
||||
|
||||
&movdqa ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm2","xmm3");
|
||||
|
||||
&pxor ("xmm0","xmm2");
|
||||
&movdqu (&QWP(0,$key),"xmm0");
|
||||
|
||||
&movdqa ("xmm2","xmm0");
|
||||
&pshufb ("xmm0","xmm5");
|
||||
&aesenclast ("xmm0","xmm4");
|
||||
|
||||
&movdqa ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm3","xmm2");
|
||||
&pslldq ("xmm2",4);
|
||||
&pxor ("xmm2","xmm3");
|
||||
|
||||
&pxor ("xmm0","xmm2");
|
||||
&movdqu (&QWP(16,$key),"xmm0");
|
||||
|
||||
&mov ($rounds,9);
|
||||
&mov (&DWP(96,$key),$rounds);
|
||||
|
||||
&jmp (&label("good_key"));
|
||||
|
||||
&set_label("12rounds",16);
|
||||
&movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey
|
||||
&cmp ("ebp",1<<28);
|
||||
&je (&label("12rounds_alt"));
|
||||
|
||||
&mov ($rounds,11);
|
||||
&$movekey (&QWP(-16,$key),"xmm0"); # round 0
|
||||
&aeskeygenassist("xmm1","xmm2",0x01); # round 1,2
|
||||
@@ -2253,8 +2077,8 @@ if ($PREFIX eq "aesni") {
|
||||
&call (&label("key_192b"));
|
||||
&$movekey (&QWP(0,$key),"xmm0");
|
||||
&mov (&DWP(48,$key),$rounds);
|
||||
|
||||
&jmp (&label("good_key"));
|
||||
&xor ("eax","eax");
|
||||
&ret();
|
||||
|
||||
&set_label("key_192a",16);
|
||||
&$movekey (&QWP(0,$key),"xmm0");
|
||||
@@ -2284,52 +2108,10 @@ if ($PREFIX eq "aesni") {
|
||||
&lea ($key,&DWP(32,$key));
|
||||
&jmp (&label("key_192b_warm"));
|
||||
|
||||
&set_label("12rounds_alt",16);
|
||||
&movdqa ("xmm5",&QWP(0x10,"ebx"));
|
||||
&movdqa ("xmm4",&QWP(0x20,"ebx"));
|
||||
&mov ($rounds,8);
|
||||
&movdqu (&QWP(-16,$key),"xmm0");
|
||||
|
||||
&set_label("loop_key192");
|
||||
&movq (&QWP(0,$key),"xmm2");
|
||||
&movdqa ("xmm1","xmm2");
|
||||
&pshufb ("xmm2","xmm5");
|
||||
&aesenclast ("xmm2","xmm4");
|
||||
&pslld ("xmm4",1);
|
||||
&lea ($key,&DWP(24,$key));
|
||||
|
||||
&movdqa ("xmm3","xmm0");
|
||||
&pslldq ("xmm0",4);
|
||||
&pxor ("xmm3","xmm0");
|
||||
&pslldq ("xmm0",4);
|
||||
&pxor ("xmm3","xmm0");
|
||||
&pslldq ("xmm0",4);
|
||||
&pxor ("xmm0","xmm3");
|
||||
|
||||
&pshufd ("xmm3","xmm0",0xff);
|
||||
&pxor ("xmm3","xmm1");
|
||||
&pslldq ("xmm1",4);
|
||||
&pxor ("xmm3","xmm1");
|
||||
|
||||
&pxor ("xmm0","xmm2");
|
||||
&pxor ("xmm2","xmm3");
|
||||
&movdqu (&QWP(-16,$key),"xmm0");
|
||||
|
||||
&dec ($rounds);
|
||||
&jnz (&label("loop_key192"));
|
||||
|
||||
&mov ($rounds,11);
|
||||
&mov (&DWP(32,$key),$rounds);
|
||||
|
||||
&jmp (&label("good_key"));
|
||||
|
||||
&set_label("14rounds",16);
|
||||
&movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey
|
||||
&lea ($key,&DWP(16,$key));
|
||||
&cmp ("ebp",1<<28);
|
||||
&je (&label("14rounds_alt"));
|
||||
|
||||
&mov ($rounds,13);
|
||||
&lea ($key,&DWP(16,$key));
|
||||
&$movekey (&QWP(-32,$key),"xmm0"); # round 0
|
||||
&$movekey (&QWP(-16,$key),"xmm2"); # round 1
|
||||
&aeskeygenassist("xmm1","xmm2",0x01); # round 2
|
||||
@@ -2361,8 +2143,7 @@ if ($PREFIX eq "aesni") {
|
||||
&$movekey (&QWP(0,$key),"xmm0");
|
||||
&mov (&DWP(16,$key),$rounds);
|
||||
&xor ("eax","eax");
|
||||
|
||||
&jmp (&label("good_key"));
|
||||
&ret();
|
||||
|
||||
&set_label("key_256a",16);
|
||||
&$movekey (&QWP(0,$key),"xmm2");
|
||||
@@ -2388,77 +2169,11 @@ if ($PREFIX eq "aesni") {
|
||||
&xorps ("xmm2","xmm1");
|
||||
&ret();
|
||||
|
||||
&set_label("14rounds_alt",16);
|
||||
&movdqa ("xmm5",&QWP(0x00,"ebx"));
|
||||
&movdqa ("xmm4",&QWP(0x20,"ebx"));
|
||||
&mov ($rounds,7);
|
||||
&movdqu (&QWP(-32,$key),"xmm0");
|
||||
&movdqa ("xmm1","xmm2");
|
||||
&movdqu (&QWP(-16,$key),"xmm2");
|
||||
|
||||
&set_label("loop_key256");
|
||||
&pshufb ("xmm2","xmm5");
|
||||
&aesenclast ("xmm2","xmm4");
|
||||
|
||||
&movdqa ("xmm3","xmm0");
|
||||
&pslldq ("xmm0",4);
|
||||
&pxor ("xmm3","xmm0");
|
||||
&pslldq ("xmm0",4);
|
||||
&pxor ("xmm3","xmm0");
|
||||
&pslldq ("xmm0",4);
|
||||
&pxor ("xmm0","xmm3");
|
||||
&pslld ("xmm4",1);
|
||||
|
||||
&pxor ("xmm0","xmm2");
|
||||
&movdqu (&QWP(0,$key),"xmm0");
|
||||
|
||||
&dec ($rounds);
|
||||
&jz (&label("done_key256"));
|
||||
|
||||
&pshufd ("xmm2","xmm0",0xff);
|
||||
&pxor ("xmm3","xmm3");
|
||||
&aesenclast ("xmm2","xmm3");
|
||||
|
||||
&movdqa ("xmm3","xmm1")
|
||||
&pslldq ("xmm1",4);
|
||||
&pxor ("xmm3","xmm1");
|
||||
&pslldq ("xmm1",4);
|
||||
&pxor ("xmm3","xmm1");
|
||||
&pslldq ("xmm1",4);
|
||||
&pxor ("xmm1","xmm3");
|
||||
|
||||
&pxor ("xmm2","xmm1");
|
||||
&movdqu (&QWP(16,$key),"xmm2");
|
||||
&lea ($key,&DWP(32,$key));
|
||||
&movdqa ("xmm1","xmm2");
|
||||
&jmp (&label("loop_key256"));
|
||||
|
||||
&set_label("done_key256");
|
||||
&mov ($rounds,13);
|
||||
&mov (&DWP(16,$key),$rounds);
|
||||
|
||||
&set_label("good_key");
|
||||
&pxor ("xmm0","xmm0");
|
||||
&pxor ("xmm1","xmm1");
|
||||
&pxor ("xmm2","xmm2");
|
||||
&pxor ("xmm3","xmm3");
|
||||
&pxor ("xmm4","xmm4");
|
||||
&pxor ("xmm5","xmm5");
|
||||
&xor ("eax","eax");
|
||||
&pop ("ebx");
|
||||
&pop ("ebp");
|
||||
&ret ();
|
||||
|
||||
&set_label("bad_pointer",4);
|
||||
&mov ("eax",-1);
|
||||
&pop ("ebx");
|
||||
&pop ("ebp");
|
||||
&ret ();
|
||||
&set_label("bad_keybits",4);
|
||||
&pxor ("xmm0","xmm0");
|
||||
&mov ("eax",-2);
|
||||
&pop ("ebx");
|
||||
&pop ("ebp");
|
||||
&ret ();
|
||||
&function_end_B("_aesni_set_encrypt_key");
|
||||
|
||||
@@ -2508,18 +2223,10 @@ if ($PREFIX eq "aesni") {
|
||||
&aesimc ("xmm0","xmm0");
|
||||
&$movekey (&QWP(0,$key),"xmm0");
|
||||
|
||||
&pxor ("xmm0","xmm0");
|
||||
&pxor ("xmm1","xmm1");
|
||||
&xor ("eax","eax"); # return success
|
||||
&set_label("dec_key_ret");
|
||||
&ret ();
|
||||
&function_end_B("${PREFIX}_set_decrypt_key");
|
||||
|
||||
&set_label("key_const",64);
|
||||
&data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d);
|
||||
&data_word(0x04070605,0x04070605,0x04070605,0x04070605);
|
||||
&data_word(1,1,1,1);
|
||||
&data_word(0x1b,0x1b,0x1b,0x1b);
|
||||
&asciz("AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>");
|
||||
|
||||
&asm_finish();
|
||||
|
||||
+252
-747
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -47,20 +47,8 @@
|
||||
#
|
||||
# <ard.biesheuvel@linaro.org>
|
||||
|
||||
$flavour = shift;
|
||||
if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
|
||||
else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
|
||||
|
||||
if ($flavour && $flavour ne "void") {
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
|
||||
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
|
||||
die "can't locate arm-xlate.pl";
|
||||
|
||||
open STDOUT,"| \"$^X\" $xlate $flavour $output";
|
||||
} else {
|
||||
open STDOUT,">$output";
|
||||
}
|
||||
while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
|
||||
open STDOUT,">$output";
|
||||
|
||||
my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
|
||||
my @XMM=map("q$_",(0..15));
|
||||
@@ -701,8 +689,9 @@ ___
|
||||
}
|
||||
|
||||
$code.=<<___;
|
||||
#if defined(__arm__)
|
||||
#ifndef __KERNEL__
|
||||
# include <openssl/arm_arch.h>
|
||||
# include "arm_arch.h"
|
||||
|
||||
# define VFP_ABI_PUSH vstmdb sp!,{d8-d15}
|
||||
# define VFP_ABI_POP vldmia sp!,{d8-d15}
|
||||
@@ -714,35 +703,29 @@ $code.=<<___;
|
||||
# define BSAES_ASM_EXTENDED_KEY
|
||||
# define XTS_CHAIN_TWEAK
|
||||
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
|
||||
# define __ARM_MAX_ARCH__ 7
|
||||
#endif
|
||||
|
||||
#ifdef __thumb__
|
||||
# define adrl adr
|
||||
#endif
|
||||
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
#if __ARM_ARCH__>=7
|
||||
.text
|
||||
.syntax unified @ ARMv7-capable assembler is expected to handle this
|
||||
#if defined(__thumb2__) && !defined(__APPLE__)
|
||||
#ifdef __thumb2__
|
||||
.thumb
|
||||
#else
|
||||
.code 32
|
||||
#endif
|
||||
|
||||
.fpu neon
|
||||
|
||||
.type _bsaes_decrypt8,%function
|
||||
.align 4
|
||||
_bsaes_decrypt8:
|
||||
adr $const,_bsaes_decrypt8
|
||||
vldmia $key!, {@XMM[9]} @ round 0 key
|
||||
#ifdef __APPLE__
|
||||
adr $const,.LM0ISR
|
||||
#else
|
||||
add $const,$const,#.LM0ISR-_bsaes_decrypt8
|
||||
#endif
|
||||
|
||||
vldmia $const!, {@XMM[8]} @ .LM0ISR
|
||||
veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
|
||||
@@ -837,11 +820,7 @@ _bsaes_const:
|
||||
_bsaes_encrypt8:
|
||||
adr $const,_bsaes_encrypt8
|
||||
vldmia $key!, {@XMM[9]} @ round 0 key
|
||||
#ifdef __APPLE__
|
||||
adr $const,.LM0SR
|
||||
#else
|
||||
sub $const,$const,#_bsaes_encrypt8-.LM0SR
|
||||
#endif
|
||||
|
||||
vldmia $const!, {@XMM[8]} @ .LM0SR
|
||||
_bsaes_encrypt8_alt:
|
||||
@@ -945,11 +924,7 @@ $code.=<<___;
|
||||
_bsaes_key_convert:
|
||||
adr $const,_bsaes_key_convert
|
||||
vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key
|
||||
#ifdef __APPLE__
|
||||
adr $const,.LM0
|
||||
#else
|
||||
sub $const,$const,#_bsaes_key_convert-.LM0
|
||||
#endif
|
||||
vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key
|
||||
|
||||
vmov.i8 @XMM[8], #0x01 @ bit masks
|
||||
@@ -1006,6 +981,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 +1000,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 +1031,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 +1052,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 +1092,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 +1368,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:
|
||||
@@ -1416,12 +1397,7 @@ bsaes_ctr32_encrypt_blocks:
|
||||
vstmia r12, {@XMM[7]} @ save last round key
|
||||
|
||||
vld1.8 {@XMM[0]}, [$ctr] @ load counter
|
||||
#ifdef __APPLE__
|
||||
mov $ctr, #:lower16:(.LREVM0SR-.LM0)
|
||||
add $ctr, $const, $ctr
|
||||
#else
|
||||
add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
|
||||
#endif
|
||||
vldmia $keysched, {@XMM[4]} @ load round0 key
|
||||
#else
|
||||
ldr r12, [$key, #244]
|
||||
@@ -1478,12 +1454,7 @@ bsaes_ctr32_encrypt_blocks:
|
||||
vldmia $ctr, {@XMM[8]} @ .LREVM0SR
|
||||
mov r5, $rounds @ pass rounds
|
||||
vstmia $fp, {@XMM[10]} @ save next counter
|
||||
#ifdef __APPLE__
|
||||
mov $const, #:lower16:(.LREVM0SR-.LSR)
|
||||
sub $const, $ctr, $const
|
||||
#else
|
||||
sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants
|
||||
#endif
|
||||
|
||||
bl _bsaes_encrypt8_alt
|
||||
|
||||
@@ -1584,7 +1555,7 @@ bsaes_ctr32_encrypt_blocks:
|
||||
rev r8, r8
|
||||
#endif
|
||||
sub sp, sp, #0x10
|
||||
vst1.8 {@XMM[1]}, [sp] @ copy counter value
|
||||
vst1.8 {@XMM[1]}, [sp,:64] @ copy counter value
|
||||
sub sp, sp, #0x10
|
||||
|
||||
.Lctr_enc_short_loop:
|
||||
@@ -1595,7 +1566,7 @@ bsaes_ctr32_encrypt_blocks:
|
||||
bl AES_encrypt
|
||||
|
||||
vld1.8 {@XMM[0]}, [r4]! @ load input
|
||||
vld1.8 {@XMM[1]}, [sp] @ load encrypted counter
|
||||
vld1.8 {@XMM[1]}, [sp,:64] @ load encrypted counter
|
||||
add r8, r8, #1
|
||||
#ifdef __ARMEL__
|
||||
rev r0, r8
|
||||
@@ -1629,6 +1600,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 +2015,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:
|
||||
@@ -2112,11 +2085,9 @@ bsaes_xts_decrypt:
|
||||
vld1.8 {@XMM[8]}, [r0] @ initial tweak
|
||||
adr $magic, .Lxts_magic
|
||||
|
||||
#ifndef XTS_CHAIN_TWEAK
|
||||
tst $len, #0xf @ if not multiple of 16
|
||||
it ne @ Thumb2 thing, sanity check in ARM
|
||||
subne $len, #0x10 @ subtract another 16 bytes
|
||||
#endif
|
||||
subs $len, #0x80
|
||||
|
||||
blo .Lxts_dec_short
|
||||
@@ -2488,6 +2459,7 @@ ___
|
||||
}
|
||||
$code.=<<___;
|
||||
#endif
|
||||
#endif
|
||||
___
|
||||
|
||||
$code =~ s/\`([^\`]*)\`/eval($1)/gem;
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
# Core 2 9.30 8.69 +7%
|
||||
# Nehalem(**) 7.63 6.88 +11%
|
||||
# Atom 17.1 16.4 +4%
|
||||
# Silvermont - 12.9
|
||||
#
|
||||
# (*) Comparison is not completely fair, because "this" is ECB,
|
||||
# i.e. no extra processing such as counter values calculation
|
||||
@@ -79,7 +78,6 @@
|
||||
# Core 2 9.98
|
||||
# Nehalem 7.80
|
||||
# Atom 17.9
|
||||
# Silvermont 14.0
|
||||
#
|
||||
# November 2011.
|
||||
#
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***)
|
||||
# Nehalem 27.9/40.4/18.1 10.2/11.9
|
||||
# Atom 70.7/92.1/60.1 61.1/75.4(***)
|
||||
# Silvermont 45.4/62.9/24.1 49.2/61.1(***)
|
||||
#
|
||||
# (*) "Hyper-threading" in the context refers rather to cache shared
|
||||
# among multiple cores, than to specifically Intel HTT. As vast
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
# Core 2(**) 29.6/41.1/14.3 21.9/25.2(***)
|
||||
# Nehalem 29.6/40.3/14.6 10.0/11.8
|
||||
# Atom 57.3/74.2/32.1 60.9/77.2(***)
|
||||
# Silvermont 52.7/64.0/19.5 48.8/60.8(***)
|
||||
#
|
||||
# (*) "Hyper-threading" in the context refers rather to cache shared
|
||||
# among multiple cores, than to specifically Intel HTT. As vast
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include "assert.h"
|
||||
|
||||
#include "../modes/internal.h"
|
||||
#include <openssl/modes.h>
|
||||
|
||||
|
||||
void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
|
||||
|
||||
@@ -62,22 +62,11 @@
|
||||
# define __ARMEL__
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# if defined(__aarch64__)
|
||||
# define __ARM_ARCH__ 8
|
||||
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define __ARMEB__
|
||||
# else
|
||||
# define __ARMEL__
|
||||
# endif
|
||||
/* Why doesn't gcc define __ARM_ARCH__? Instead it defines
|
||||
* bunch of below macros. See all_architectires[] table in
|
||||
* gcc/config/arm/arm.c. On a side note it defines
|
||||
* __ARMEL__/__ARMEB__ for little-/big-endian. */
|
||||
# elif defined(__ARM_ARCH)
|
||||
# define __ARM_ARCH__ __ARM_ARCH
|
||||
# elif defined(__ARM_ARCH_8A__)
|
||||
# define __ARM_ARCH__ 8
|
||||
# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
|
||||
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
|
||||
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
|
||||
defined(__ARM_ARCH_7EM__)
|
||||
# define __ARM_ARCH__ 7
|
||||
@@ -98,9 +87,12 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Even when building for 32-bit ARM, support for aarch64 crypto instructions
|
||||
* will be included. */
|
||||
#define __ARM_MAX_ARCH__ 8
|
||||
#if !__ASSEMBLER__
|
||||
|
||||
/* OPENSSL_armcap_P contains flags describing the capabilities of the CPU and
|
||||
* is easy for assembly code to acesss. For C code, see the functions in
|
||||
* |cpu.h|. */
|
||||
extern uint32_t OPENSSL_armcap_P;
|
||||
|
||||
/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
|
||||
#define ARMV7_NEON (1 << 0)
|
||||
@@ -109,19 +101,9 @@
|
||||
* The Poly1305 NEON code is known to trigger bugs in the NEON units of some
|
||||
* phones. If this bit isn't set then the Poly1305 NEON code won't be used.
|
||||
* See https://code.google.com/p/chromium/issues/detail?id=341598. */
|
||||
#define ARMV7_NEON_FUNCTIONAL (1 << 10)
|
||||
#define ARMV7_NEON_FUNCTIONAL (1 << 1)
|
||||
|
||||
/* ARMV8_AES indicates support for hardware AES instructions. */
|
||||
#define ARMV8_AES (1 << 2)
|
||||
|
||||
/* ARMV8_SHA1 indicates support for hardware SHA-1 instructions. */
|
||||
#define ARMV8_SHA1 (1 << 3)
|
||||
|
||||
/* ARMV8_SHA256 indicates support for hardware SHA-256 instructions. */
|
||||
#define ARMV8_SHA256 (1 << 4)
|
||||
|
||||
/* ARMV8_PMULL indicates support for carryless multiplication. */
|
||||
#define ARMV8_PMULL (1 << 5)
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
|
||||
#endif /* OPENSSL_HEADER_ARM_ARCH_H */
|
||||
#endif /* OPENSSL_HEADER_THREAD_H */
|
||||
+41
-51
@@ -1,56 +1,46 @@
|
||||
include_directories(../../include)
|
||||
include_directories(. .. ../../include)
|
||||
|
||||
add_library(
|
||||
asn1
|
||||
asn1
|
||||
|
||||
OBJECT
|
||||
OBJECT
|
||||
|
||||
a_bitstr.c
|
||||
a_bool.c
|
||||
a_bytes.c
|
||||
a_d2i_fp.c
|
||||
a_dup.c
|
||||
a_enum.c
|
||||
a_gentm.c
|
||||
a_i2d_fp.c
|
||||
a_int.c
|
||||
a_mbstr.c
|
||||
a_object.c
|
||||
a_octet.c
|
||||
a_print.c
|
||||
a_strnid.c
|
||||
a_time.c
|
||||
a_type.c
|
||||
a_utctm.c
|
||||
a_utf8.c
|
||||
asn1_lib.c
|
||||
asn1_par.c
|
||||
asn_pack.c
|
||||
bio_asn1.c
|
||||
bio_ndef.c
|
||||
f_enum.c
|
||||
f_int.c
|
||||
f_string.c
|
||||
t_bitst.c
|
||||
t_pkey.c
|
||||
tasn_dec.c
|
||||
tasn_enc.c
|
||||
tasn_fre.c
|
||||
tasn_new.c
|
||||
tasn_prn.c
|
||||
tasn_typ.c
|
||||
tasn_utl.c
|
||||
x_bignum.c
|
||||
x_long.c
|
||||
a_bitstr.c
|
||||
a_bool.c
|
||||
a_bytes.c
|
||||
a_d2i_fp.c
|
||||
a_dup.c
|
||||
a_enum.c
|
||||
a_gentm.c
|
||||
a_i2d_fp.c
|
||||
a_int.c
|
||||
a_mbstr.c
|
||||
a_object.c
|
||||
a_octet.c
|
||||
a_print.c
|
||||
a_strnid.c
|
||||
a_time.c
|
||||
a_type.c
|
||||
a_utctm.c
|
||||
a_utf8.c
|
||||
asn1_error.c
|
||||
asn1_lib.c
|
||||
asn1_par.c
|
||||
asn_pack.c
|
||||
bio_asn1.c
|
||||
bio_ndef.c
|
||||
f_enum.c
|
||||
f_int.c
|
||||
f_string.c
|
||||
t_bitst.c
|
||||
t_pkey.c
|
||||
tasn_dec.c
|
||||
tasn_enc.c
|
||||
tasn_fre.c
|
||||
tasn_new.c
|
||||
tasn_prn.c
|
||||
tasn_typ.c
|
||||
tasn_utl.c
|
||||
x_bignum.c
|
||||
x_long.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
asn1_test
|
||||
|
||||
asn1_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(asn1_test crypto)
|
||||
add_dependencies(all_tests asn1_test)
|
||||
|
||||
+153
-169
@@ -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)"
|
||||
*
|
||||
@@ -56,208 +56,192 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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 i;
|
||||
|
||||
if (len < 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
if (len < 1)
|
||||
{
|
||||
i=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;
|
||||
i= *(p++);
|
||||
/* 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|(i&0x07)); /* 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)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
s[len-1]&=(0xff<<i);
|
||||
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:
|
||||
OPENSSL_PUT_ERROR(ASN1, c2i_ASN1_BIT_STRING, i);
|
||||
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, ASN1_BIT_STRING_set_bit, 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, d2i_ASN1_BOOLEAN, i);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+221
-214
@@ -56,253 +56,260 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#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, d2i_ASN1_type_bytes, 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, d2i_ASN1_bytes, 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, asn1_collate_primitive, 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, ASN1_d2i_fp, 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, ASN1_item_d2i_fp, 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, asn1_d2i_read_bio, 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, asn1_d2i_read_bio, 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_d2i_read_bio, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
if (len+i < len)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, 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)
|
||||
{
|
||||
unsigned long 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_d2i_read_bio, 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_d2i_read_bio, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(b,len+want))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, asn1_d2i_read_bio, 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_d2i_read_bio, 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_d2i_read_bio, 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_d2i_read_bio, 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, ASN1_dup, 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, ASN1_item_dup, ERR_R_MALLOC_FAILURE); return(NULL); }
|
||||
p= b;
|
||||
ret=ASN1_item_d2i(NULL,&p,i, it);
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+102
-102
@@ -56,126 +56,126 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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, ASN1_ENUMERATED_set, 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, BN_to_ASN1_ENUMERATED, 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, BN_to_ASN1_ENUMERATED, 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_ENUMERATED_to_BN, ASN1_R_BN_LIB);
|
||||
else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+171
-173
@@ -56,199 +56,197 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.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, ASN1_GENERALIZEDTIME_adj, 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);
|
||||
}
|
||||
|
||||
+83
-76
@@ -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;
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_i2d_fp, 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);
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
|
||||
{
|
||||
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, ASN1_i2d_bio, 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);
|
||||
}
|
||||
|
||||
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, ASN1_item_i2d_fp, 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, ASN1_item_i2d_bio, 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);
|
||||
}
|
||||
|
||||
+331
-337
@@ -56,51 +56,50 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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 +111,344 @@ 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 (!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) {
|
||||
*(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, c2i_ASN1_INTEGER, 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, d2i_ASN1_UINTEGER, 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, ASN1_INTEGER_set, 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, BN_to_ASN1_INTEGER, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(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, BN_to_ASN1_INTEGER, 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_INTEGER_to_BN, ASN1_R_BN_LIB);
|
||||
else if(ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
+239
-260
@@ -56,14 +56,12 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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 +71,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_mbstring_ncopy, 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_mbstring_ncopy, 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_mbstring_ncopy, 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_mbstring_ncopy, 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_mbstring_ncopy, 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_mbstring_ncopy, 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_mbstring_ncopy, 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, ASN1_mbstring_ncopy, 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, ASN1_mbstring_ncopy, 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, ASN1_mbstring_ncopy, 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 +281,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
-294
@@ -57,340 +57,355 @@
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#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, a2d_ASN1_OBJECT, 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, a2d_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
|
||||
goto err;
|
||||
}
|
||||
c= *(p++);
|
||||
num--;
|
||||
for (;;)
|
||||
{
|
||||
if (num <= 0) break;
|
||||
if ((c != '.') && (c != ' '))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, a2d_ASN1_OBJECT, 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, a2d_ASN1_OBJECT, 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, a2d_ASN1_OBJECT, 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, a2d_ASN1_OBJECT, 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, d2i_ASN1_OBJECT, 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, c2i_ASN1_OBJECT, 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, c2i_ASN1_OBJECT, 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, c2i_ASN1_OBJECT, 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, ASN1_OBJECT_new, 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
-175
@@ -56,253 +56,230 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
|
||||
#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, ASN1_STRING_TABLE_add, 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, ASN1_STRING_TABLE_add, 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
-117
@@ -56,9 +56,6 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -67,10 +64,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 +78,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, XXX, 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_TIME_adj, 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);
|
||||
}
|
||||
|
||||
+84
-80
@@ -61,93 +61,97 @@
|
||||
#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 ASN1_TYPE_cmp(ASN1_TYPE *a, ASN1_TYPE *b)
|
||||
{
|
||||
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_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;
|
||||
}
|
||||
|
||||
+235
-229
@@ -56,278 +56,284 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/time_support.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, XXX, ERR_R_NESTED_ASN1_ERROR);
|
||||
return(NULL);
|
||||
}
|
||||
if (!ASN1_UTCTIME_check(ret))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, XXX, 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, ASN1_UTCTIME_adj, 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, &stm, &ttm))
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/* 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. */
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
const ERR_STRING_DATA ASN1_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_set_bit, 0), "ASN1_BIT_STRING_set_bit"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENUMERATED_set, 0), "ASN1_ENUMERATED_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENUMERATED_to_BN, 0), "ASN1_ENUMERATED_to_BN"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_adj, 0), "ASN1_GENERALIZEDTIME_adj"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_INTEGER_set, 0), "ASN1_INTEGER_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_INTEGER_to_BN, 0), "ASN1_INTEGER_to_BN"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_new, 0), "ASN1_OBJECT_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_new, 0), "ASN1_PCTX_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_add, 0), "ASN1_STRING_TABLE_add"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_set, 0), "ASN1_STRING_set"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_type_new, 0), "ASN1_STRING_type_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_adj, 0), "ASN1_TIME_adj"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_adj, 0), "ASN1_UTCTIME_adj"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_d2i_fp, 0), "ASN1_d2i_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_dup, 0), "ASN1_dup"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_get_object, 0), "ASN1_get_object"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_i2d_bio, 0), "ASN1_i2d_bio"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_i2d_fp, 0), "ASN1_i2d_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_d2i_fp, 0), "ASN1_item_d2i_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_dup, 0), "ASN1_item_dup"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_ex_d2i, 0), "ASN1_item_ex_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_i2d_bio, 0), "ASN1_item_i2d_bio"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_i2d_fp, 0), "ASN1_item_i2d_fp"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_pack, 0), "ASN1_item_pack"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_item_unpack, 0), "ASN1_item_unpack"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_mbstring_ncopy, 0), "ASN1_mbstring_ncopy"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_pack_string, 0), "ASN1_pack_string"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_seq_pack, 0), "ASN1_seq_pack"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_seq_unpack, 0), "ASN1_seq_unpack"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_template_new, 0), "ASN1_template_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_unpack_string, 0), "ASN1_unpack_string"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_new_NDEF, 0), "BIO_new_NDEF"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_to_ASN1_ENUMERATED, 0), "BN_to_ASN1_ENUMERATED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_to_ASN1_INTEGER, 0), "BN_to_ASN1_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2d_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_ENUMERATED, 0), "a2i_ASN1_ENUMERATED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_a2i_ASN1_STRING, 0), "a2i_ASN1_STRING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_check_tlen, 0), "asn1_check_tlen"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_collate_primitive, 0), "asn1_collate_primitive"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_collect, 0), "asn1_collect"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_d2i_ex_primitive, 0), "asn1_d2i_ex_primitive"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_d2i_read_bio, 0), "asn1_d2i_read_bio"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_do_adb, 0), "asn1_do_adb"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_ex_c2i, 0), "asn1_ex_c2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_find_end, 0), "asn1_find_end"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_item_ex_combine_new, 0), "asn1_item_ex_combine_new"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_template_ex_d2i, 0), "asn1_template_ex_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_asn1_template_noexp_d2i, 0), "asn1_template_noexp_d2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_BIT_STRING, 0), "c2i_ASN1_BIT_STRING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_c2i_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_collect_data, 0), "collect_data"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_BOOLEAN, 0), "d2i_ASN1_BOOLEAN"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_UTCTIME, 0), "d2i_ASN1_UTCTIME"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_bytes, 0), "d2i_ASN1_bytes"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_d2i_ASN1_type_bytes, 0), "d2i_ASN1_type_bytes"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_i2d_ASN1_TIME, 0), "i2d_ASN1_TIME"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, ASN1_F_long_c2i, 0), "long_c2i"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "ADDING_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "ASN1_PARSE_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_SIG_PARSE_ERROR), "ASN1_SIG_PARSE_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "AUX_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_CLASS), "BAD_CLASS"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_GET_ASN1_OBJECT_CALL), "BAD_GET_ASN1_OBJECT_CALL"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "BAD_OBJECT_HEADER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_PASSWORD_READ), "BAD_PASSWORD_READ"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_TAG), "BAD_TAG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH), "BMPSTRING_IS_WRONG_LENGTH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "BN_LIB"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "BOOLEAN_IS_WRONG_LENGTH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DATA_IS_WRONG), "DATA_IS_WRONG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODE_ERROR), "DECODE_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DECODING_ERROR), "DECODING_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_DEPTH_EXCEEDED), "DEPTH_EXCEEDED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ENCODE_ERROR), "ENCODE_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_GETTING_TIME), "ERROR_GETTING_TIME"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_LOADING_SECTION), "ERROR_LOADING_SECTION"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_PARSING_SET_ELEMENT), "ERROR_PARSING_SET_ELEMENT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_ASN1_SEQUENCE), "EXPECTING_AN_ASN1_SEQUENCE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_INTEGER), "EXPECTING_AN_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_AN_OBJECT), "EXPECTING_AN_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_A_BOOLEAN), "EXPECTING_A_BOOLEAN"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPECTING_A_TIME), "EXPECTING_A_TIME"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_LENGTH_MISMATCH), "EXPLICIT_LENGTH_MISMATCH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), "EXPLICIT_TAG_NOT_CONSTRUCTED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "FIELD_MISSING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE), "FIRST_NUM_TOO_LARGE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "HEADER_TOO_LONG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT), "ILLEGAL_BITSTRING_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BOOLEAN), "ILLEGAL_BOOLEAN"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_CHARACTERS), "ILLEGAL_CHARACTERS"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_FORMAT), "ILLEGAL_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_HEX), "ILLEGAL_HEX"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_IMPLICIT_TAG), "ILLEGAL_IMPLICIT_TAG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_INTEGER), "ILLEGAL_INTEGER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NESTED_TAGGING), "ILLEGAL_NESTED_TAGGING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL), "ILLEGAL_NULL"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_NULL_VALUE), "ILLEGAL_NULL_VALUE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OBJECT), "ILLEGAL_OBJECT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONAL_ANY), "ILLEGAL_OPTIONAL_ANY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TAGGED_ANY), "ILLEGAL_TAGGED_ANY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_TIME_VALUE), "ILLEGAL_TIME_VALUE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_NOT_ASCII_FORMAT), "INTEGER_NOT_ASCII_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), "INTEGER_TOO_LARGE_FOR_LONG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_BMPSTRING_LENGTH), "INVALID_BMPSTRING_LENGTH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_DIGIT), "INVALID_DIGIT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MIME_TYPE), "INVALID_MIME_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_MODIFIER), "INVALID_MODIFIER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_NUMBER), "INVALID_NUMBER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_OBJECT_ENCODING), "INVALID_OBJECT_ENCODING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_SEPARATOR), "INVALID_SEPARATOR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_TIME_FORMAT), "INVALID_TIME_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), "INVALID_UNIVERSALSTRING_LENGTH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING), "INVALID_UTF8STRING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_IV_TOO_LARGE), "IV_TOO_LARGE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LENGTH_ERROR), "LENGTH_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "LIST_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MALLOC_FAILURE), "MALLOC_FAILURE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE), "MIME_NO_CONTENT_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_PARSE_ERROR), "MIME_PARSE_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_SIG_PARSE_ERROR), "MIME_SIG_PARSE_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_ASN1_EOS), "MISSING_ASN1_EOS"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_EOC), "MISSING_EOC"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_SECOND_NUMBER), "MISSING_SECOND_NUMBER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MISSING_VALUE), "MISSING_VALUE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_NOT_UNIVERSAL), "MSTRING_NOT_UNIVERSAL"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MSTRING_WRONG_TAG), "MSTRING_WRONG_TAG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_ERROR), "NESTED_ASN1_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NESTED_ASN1_STRING), "NESTED_ASN1_STRING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NON_HEX_CHARACTERS), "NON_HEX_CHARACTERS"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ASCII_FORMAT), "NOT_ASCII_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NOT_ENOUGH_DATA), "NOT_ENOUGH_DATA"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_CONTENT_TYPE), "NO_CONTENT_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_DEFAULT_DIGEST), "NO_DEFAULT_DIGEST"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MATCHING_CHOICE_TYPE), "NO_MATCHING_CHOICE_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BODY_FAILURE), "NO_MULTIPART_BODY_FAILURE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_MULTIPART_BOUNDARY), "NO_MULTIPART_BOUNDARY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NO_SIG_CONTENT_TYPE), "NO_SIG_CONTENT_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_NULL_IS_WRONG_LENGTH), "NULL_IS_WRONG_LENGTH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_OBJECT_NOT_ASCII_FORMAT), "OBJECT_NOT_ASCII_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ODD_NUMBER_OF_CHARS), "ODD_NUMBER_OF_CHARS"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_PRIVATE_KEY_HEADER_MISSING), "PRIVATE_KEY_HEADER_MISSING"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SECOND_NUMBER_TOO_LARGE), "SECOND_NUMBER_TOO_LARGE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_LENGTH_MISMATCH), "SEQUENCE_LENGTH_MISMATCH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "SEQUENCE_NOT_CONSTRUCTED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), "SEQUENCE_OR_SET_NEEDS_CONFIG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SHORT_LINE), "SHORT_LINE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_SIG_INVALID_MIME_TYPE), "SIG_INVALID_MIME_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STREAMING_NOT_SUPPORTED), "STREAMING_NOT_SUPPORTED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_LONG), "STRING_TOO_LONG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_STRING_TOO_SHORT), "STRING_TOO_SHORT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TAG_VALUE_TOO_HIGH), "TAG_VALUE_TOO_HIGH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TIME_NOT_ASCII_FORMAT), "TIME_NOT_ASCII_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TOO_LONG), "TOO_LONG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_TYPE_NOT_CONSTRUCTED), "TYPE_NOT_CONSTRUCTED"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "UNABLE_TO_DECODE_RSA_KEY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "UNABLE_TO_DECODE_RSA_PRIVATE_KEY"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "UNEXPECTED_EOC"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), "UNIVERSALSTRING_IS_WRONG_LENGTH"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "UNKNOWN_FORMAT"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_OBJECT_TYPE), "UNKNOWN_OBJECT_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "UNKNOWN_PUBLIC_KEY_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "UNKNOWN_TAG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), "UNSUPPORTED_ANY_DEFINED_BY_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "UNSUPPORTED_ENCRYPTION_ALGORITHM"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "UNSUPPORTED_PUBLIC_KEY_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "UNSUPPORTED_TYPE"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TAG), "WRONG_TAG"},
|
||||
{ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_TYPE), "WRONG_TYPE"},
|
||||
{0, NULL},
|
||||
};
|
||||
+358
-374
@@ -57,447 +57,431 @@
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1_mac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT);
|
||||
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;
|
||||
}
|
||||
*ptag=tag;
|
||||
*pclass=xclass;
|
||||
if (!asn1_get_length(&p,&inf,plength,(int)max)) 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;
|
||||
|
||||
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_get_object, 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_get_object, 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, ASN1_STRING_set, 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, ASN1_STRING_type_new, 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);
|
||||
}
|
||||
|
||||
void asn1_add_error(const unsigned char *address, int offset)
|
||||
{
|
||||
char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1];
|
||||
|
||||
BIO_snprintf(buf1,sizeof buf1,"%lu",(unsigned long)address);
|
||||
BIO_snprintf(buf2,sizeof buf2,"%d",offset);
|
||||
ERR_add_error_data(4,"address=",buf1," offset=",buf2);
|
||||
}
|
||||
|
||||
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 */;
|
||||
|
||||
+345
-312
@@ -60,343 +60,376 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
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_write(bp,"Error in encoding\n",18) <= 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_write(bp,"\n",1) <= 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_write(bp,"\n",1) <= 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_write(bp,":",1) <= 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_write(bp,":",1) <= 0) goto end;
|
||||
i2a_ASN1_OBJECT(bp,o);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_write(bp,":BAD OBJECT",11) <= 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_write(bp,"Bad boolean\n",12) <= 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_write(bp,":",1) <= 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_write(bp,"[HEX DUMP]:",11) <= 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_write(bp,"\n",1) <= 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_write(bp,":",1) <= 0) goto end;
|
||||
if (bs->type == V_ASN1_NEG_INTEGER)
|
||||
if (BIO_write(bp,"-",1) <= 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_write(bp,"00",2) <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_write(bp,"BAD INTEGER",11) <= 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_write(bp,":",1) <= 0) goto end;
|
||||
if (bs->type == V_ASN1_NEG_ENUMERATED)
|
||||
if (BIO_write(bp,"-",1) <= 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_write(bp,"00",2) <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_write(bp,"BAD ENUMERATED",11) <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_ENUMERATED_free(bs);
|
||||
}
|
||||
else if (len > 0 && dump)
|
||||
{
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_write(bp,"\n",1) <= 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_write(bp,"\n",1) <= 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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <stdio.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/scoped_types.h"
|
||||
|
||||
|
||||
// kTag258 is an ASN.1 structure with a universal tag with number 258.
|
||||
static const uint8_t kTag258[] = {
|
||||
0x1f, 0x82, 0x02, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static_assert(V_ASN1_NEG_INTEGER == 258,
|
||||
"V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it.");
|
||||
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestLargeTags()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
+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, ASN1_item_pack, 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_item_pack, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_item_pack, 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_item_unpack, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+349
-331
@@ -57,53 +57,57 @@
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 +118,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 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,
|
||||
};
|
||||
|
||||
BIO_METHOD *BIO_f_asn1(void)
|
||||
{
|
||||
return(&methods_asn1);
|
||||
}
|
||||
|
||||
const BIO_METHOD *BIO_f_asn1(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
+137
-140
@@ -63,189 +63,186 @@
|
||||
#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, BIO_new_NDEF, 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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ print <<EOF;
|
||||
* Mask of various character properties
|
||||
*/
|
||||
|
||||
static const unsigned char char_type[] = {
|
||||
static unsigned char char_type[] = {
|
||||
EOF
|
||||
|
||||
for($i = 0; $i < 128; $i++) {
|
||||
|
||||
+133
-128
@@ -62,139 +62,144 @@
|
||||
/* 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, a2i_ASN1_ENUMERATED, 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, a2i_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
|
||||
if (s != NULL) OPENSSL_free(s);
|
||||
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, a2i_ASN1_ENUMERATED, 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, a2i_ASN1_ENUMERATED, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
+138
-131
@@ -59,144 +59,151 @@
|
||||
#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, a2i_ASN1_INTEGER, 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, a2i_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
|
||||
if (s != NULL) OPENSSL_free(s);
|
||||
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, a2i_ASN1_INTEGER, 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, a2i_ASN1_INTEGER, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
+132
-125
@@ -59,138 +59,145 @@
|
||||
#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, a2i_ASN1_STRING, 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, a2i_ASN1_STRING, ERR_R_MALLOC_FAILURE);
|
||||
if (s != NULL) OPENSSL_free(s);
|
||||
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, a2i_ASN1_STRING, 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, a2i_ASN1_STRING, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
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
-32
@@ -56,48 +56,45 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
+47
-45
@@ -59,52 +59,54 @@
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
|
||||
unsigned char *buf, int off)
|
||||
{
|
||||
int n, i;
|
||||
const char *neg;
|
||||
unsigned char *buf, int off)
|
||||
{
|
||||
int n,i;
|
||||
const char *neg;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 (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++;
|
||||
|
||||
if (buf[1] & 0x80)
|
||||
n++;
|
||||
else
|
||||
buf++;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
+1115
-1037
File diff suppressed because it is too large
Load Diff
+548
-514
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_do_lock(pval, -1, it) > 0)
|
||||
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;
|
||||
}
|
||||
|
||||
+267
-254
@@ -56,326 +56,339 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/err.h>
|
||||
#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;
|
||||
|
||||
if (!combine) *pval = NULL;
|
||||
|
||||
#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_do_lock(pval, 0, 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, asn1_item_ex_combine_new, ERR_R_MALLOC_FAILURE);
|
||||
#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_item_ex_combine_new, 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, ASN1_template_new, 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 && 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 || (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;
|
||||
}
|
||||
|
||||
+480
-437
File diff suppressed because it is too large
Load Diff
+51
-43
@@ -58,52 +58,64 @@
|
||||
|
||||
#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(ASN1_INTEGER);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER);
|
||||
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_BIT_STRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_OCTET_STRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_NULL);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTF8STRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_T61STRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_VISIBLESTRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_BMPSTRING);
|
||||
|
||||
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 +126,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 +146,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);
|
||||
|
||||
+18
-26
@@ -56,15 +56,10 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/thread.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Utility functions for manipulating fields and offsets */
|
||||
@@ -88,32 +83,28 @@ int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
|
||||
const ASN1_ITEM *it) {
|
||||
/* Do reference counting. The value 'op' decides what to do. if it is +1 then
|
||||
* the count is incremented. If op is 0 count is set to 1. If op is -1 count is
|
||||
* decremented and the return value is the current refrence count or 0 if no
|
||||
* reference count exists. */
|
||||
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) {
|
||||
const ASN1_AUX *aux;
|
||||
int *lck, ret;
|
||||
if (it->itype != ASN1_ITYPE_SEQUENCE &&
|
||||
it->itype != ASN1_ITYPE_NDEF_SEQUENCE) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
aux = it->funcs;
|
||||
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
return offset2ptr(*pval, aux->ref_offset);
|
||||
}
|
||||
|
||||
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
|
||||
if (references != NULL) {
|
||||
*references = 1;
|
||||
lck = offset2ptr(*pval, aux->ref_offset);
|
||||
if (op == 0) {
|
||||
*lck = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
|
||||
if (references != NULL) {
|
||||
return CRYPTO_refcount_dec_and_test_zero(references);
|
||||
}
|
||||
return 1;
|
||||
ret = CRYPTO_add(lck, op, aux->ref_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
|
||||
@@ -260,7 +251,8 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
|
||||
err:
|
||||
/* FIXME: should log the value or OID of unsupported type */
|
||||
if (nullerr) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
|
||||
OPENSSL_PUT_ERROR(ASN1, asn1_do_adb,
|
||||
ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+46
-63
@@ -59,95 +59,78 @@
|
||||
#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 */ ,
|
||||
static ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c
|
||||
};
|
||||
|
||||
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) bn_new(pval, it);
|
||||
bn = (BIGNUM *)*pval;
|
||||
if(!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+83
-100
@@ -56,142 +56,125 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
|
||||
/* 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
|
||||
static ASN1_PRIMITIVE_FUNCS long_pf = {
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(LONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_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, long_c2i, 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, long_c2i, 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);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
include_directories(../../include)
|
||||
include_directories(. .. ../../include)
|
||||
|
||||
add_library(
|
||||
base64
|
||||
base64
|
||||
|
||||
OBJECT
|
||||
OBJECT
|
||||
|
||||
base64.c
|
||||
base64.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
base64_test
|
||||
base64_test
|
||||
|
||||
base64_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
base64_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(base64_test crypto)
|
||||
add_dependencies(all_tests base64_test)
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static const unsigned char data_bin2ascii[65] =
|
||||
@@ -373,10 +372,6 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
rv = 0;
|
||||
goto end;
|
||||
}
|
||||
if (eof > v) {
|
||||
rv = -1;
|
||||
goto end;
|
||||
}
|
||||
ret += (v - eof);
|
||||
} else {
|
||||
eof = 1;
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
struct TestVector {
|
||||
typedef struct {
|
||||
const char *decoded;
|
||||
const char *encoded;
|
||||
};
|
||||
} TEST_VECTOR;
|
||||
|
||||
// Test vectors from RFC 4648.
|
||||
static const TestVector kTestVectors[] = {
|
||||
/* Test vectors from RFC 4648. */
|
||||
static const TEST_VECTOR test_vectors[] = {
|
||||
{ "", "" },
|
||||
{ "f" , "Zg==" },
|
||||
{ "fo", "Zm8=" },
|
||||
@@ -36,89 +36,95 @@ static const TestVector kTestVectors[] = {
|
||||
{ "foobar", "Zm9vYmFy" },
|
||||
};
|
||||
|
||||
static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]);
|
||||
static const size_t kNumTests = sizeof(test_vectors) / sizeof(test_vectors[0]);
|
||||
|
||||
static bool TestEncode() {
|
||||
for (size_t i = 0; i < kNumTests; i++) {
|
||||
const TestVector *t = &kTestVectors[i];
|
||||
uint8_t out[9];
|
||||
size_t len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded,
|
||||
strlen(t->decoded));
|
||||
static int test_encode(void) {
|
||||
uint8_t out[9];
|
||||
size_t i, len;
|
||||
|
||||
for (i = 0; i < kNumTests; i++) {
|
||||
const TEST_VECTOR *t = &test_vectors[i];
|
||||
len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded, strlen(t->decoded));
|
||||
if (len != strlen(t->encoded) ||
|
||||
memcmp(out, t->encoded, len) != 0) {
|
||||
fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->decoded, (int)len, (const char*)out, t->encoded);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool TestDecode() {
|
||||
static int test_decode(void) {
|
||||
uint8_t out[6];
|
||||
size_t len;
|
||||
size_t i, len;
|
||||
int ret;
|
||||
|
||||
for (size_t i = 0; i < kNumTests; i++) {
|
||||
// Test the normal API.
|
||||
const TestVector *t = &kTestVectors[i];
|
||||
for (i = 0; i < kNumTests; i++) {
|
||||
/* Test the normal API. */
|
||||
const TEST_VECTOR *t = &test_vectors[i];
|
||||
size_t expected_len = strlen(t->decoded);
|
||||
if (!EVP_DecodeBase64(out, &len, sizeof(out),
|
||||
(const uint8_t*)t->encoded, strlen(t->encoded))) {
|
||||
fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (len != strlen(t->decoded) ||
|
||||
memcmp(out, t->decoded, len) != 0) {
|
||||
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->encoded, (int)len, (const char*)out, t->decoded);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test that the padding behavior of the deprecated API is preserved.
|
||||
int ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded,
|
||||
strlen(t->encoded));
|
||||
/* Test that the padding behavior of the deprecated API is
|
||||
* preserved. */
|
||||
ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded, strlen(t->encoded));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (ret % 3 != 0) {
|
||||
fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (expected_len % 3 != 0) {
|
||||
ret -= 3 - (expected_len % 3);
|
||||
}
|
||||
if (static_cast<size_t>(ret) != strlen(t->decoded) ||
|
||||
if (ret != strlen(t->decoded) ||
|
||||
memcmp(out, t->decoded, ret) != 0) {
|
||||
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->encoded, ret, (const char*)out, t->decoded);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) {
|
||||
fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) {
|
||||
fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) {
|
||||
fprintf(stderr, "Failed to reject invalid input length.\n");
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
if (!TestEncode() ||
|
||||
!TestDecode()) {
|
||||
if (!test_encode()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!test_decode()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+18
-20
@@ -1,33 +1,31 @@
|
||||
include_directories(../../include)
|
||||
include_directories(. .. ../../include)
|
||||
|
||||
add_library(
|
||||
bio
|
||||
bio
|
||||
|
||||
OBJECT
|
||||
OBJECT
|
||||
|
||||
bio.c
|
||||
bio_mem.c
|
||||
buffer.c
|
||||
connect.c
|
||||
fd.c
|
||||
file.c
|
||||
hexdump.c
|
||||
pair.c
|
||||
printf.c
|
||||
socket.c
|
||||
socket_helper.c
|
||||
bio.c
|
||||
bio_error.c
|
||||
bio_mem.c
|
||||
buffer.c
|
||||
connect.c
|
||||
fd.c
|
||||
file.c
|
||||
hexdump.c
|
||||
pair.c
|
||||
printf.c
|
||||
socket.c
|
||||
socket_helper.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
bio_test
|
||||
bio_test
|
||||
|
||||
bio_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
bio_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(bio_test crypto)
|
||||
if (WIN32)
|
||||
target_link_libraries(bio_test ws2_32)
|
||||
target_link_libraries(bio_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests bio_test)
|
||||
|
||||
+29
-161
@@ -56,17 +56,14 @@
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/thread.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* BIO_set initialises a BIO structure to have the given type and sets the
|
||||
* reference count to one. It returns one on success or zero on error. */
|
||||
@@ -80,17 +77,24 @@ static int bio_set(BIO *bio, const BIO_METHOD *method) {
|
||||
bio->shutdown = 1;
|
||||
bio->references = 1;
|
||||
|
||||
if (method->create != NULL && !method->create(bio)) {
|
||||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (method->create != NULL) {
|
||||
if (!method->create(bio)) {
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BIO *BIO_new(const BIO_METHOD *method) {
|
||||
BIO *ret = OPENSSL_malloc(sizeof(BIO));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_new, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -106,7 +110,8 @@ int BIO_free(BIO *bio) {
|
||||
BIO *next_bio;
|
||||
|
||||
for (; bio != NULL; bio = next_bio) {
|
||||
if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) {
|
||||
int refs = CRYPTO_add(&bio->references, -1, CRYPTO_LOCK_BIO);
|
||||
if (refs > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -119,6 +124,8 @@ int BIO_free(BIO *bio) {
|
||||
|
||||
next_bio = BIO_pop(bio);
|
||||
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
|
||||
|
||||
if (bio->method != NULL && bio->method->destroy != NULL) {
|
||||
bio->method->destroy(bio);
|
||||
}
|
||||
@@ -128,11 +135,6 @@ int BIO_free(BIO *bio) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
BIO *BIO_up_ref(BIO *bio) {
|
||||
CRYPTO_refcount_inc(&bio->references);
|
||||
return bio;
|
||||
}
|
||||
|
||||
void BIO_vfree(BIO *bio) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
@@ -153,7 +155,7 @@ static int bio_io(BIO *bio, void *buf, int len, size_t method_offset,
|
||||
}
|
||||
|
||||
if (io_func == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
OPENSSL_PUT_ERROR(BIO, bio_io, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -165,7 +167,7 @@ static int bio_io(BIO *bio, void *buf, int len, size_t method_offset,
|
||||
}
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
OPENSSL_PUT_ERROR(BIO, bio_io, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -217,7 +219,7 @@ long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
|
||||
}
|
||||
|
||||
if (bio->method == NULL || bio->method->ctrl == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_ctrl, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -323,7 +325,7 @@ long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
}
|
||||
|
||||
if (bio->method == NULL || bio->method->callback_ctrl == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_callback_ctrl, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -394,6 +396,10 @@ BIO *BIO_push(BIO *bio, BIO *appended_bio) {
|
||||
}
|
||||
|
||||
last_bio->next_bio = appended_bio;
|
||||
/* TODO(fork): this seems very suspect. If we got rid of BIO SSL, we could
|
||||
* get rid of this. */
|
||||
BIO_ctrl(bio, BIO_CTRL_PUSH, 0, bio);
|
||||
|
||||
return bio;
|
||||
}
|
||||
|
||||
@@ -404,6 +410,7 @@ BIO *BIO_pop(BIO *bio) {
|
||||
return NULL;
|
||||
}
|
||||
ret = bio->next_bio;
|
||||
BIO_ctrl(bio, BIO_CTRL_POP, 0, bio);
|
||||
bio->next_bio = NULL;
|
||||
return ret;
|
||||
}
|
||||
@@ -454,6 +461,12 @@ int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_print_errors_fp(FILE *out) {
|
||||
BIO *bio = BIO_new_fp(out, BIO_NOCLOSE);
|
||||
BIO_print_errors(bio);
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
static int print_bio(const char *str, size_t len, void *bio) {
|
||||
return BIO_write((BIO *)bio, str, len);
|
||||
}
|
||||
@@ -461,148 +474,3 @@ static int print_bio(const char *str, size_t len, void *bio) {
|
||||
void BIO_print_errors(BIO *bio) {
|
||||
ERR_print_errors_cb(print_bio, bio);
|
||||
}
|
||||
|
||||
void ERR_print_errors(BIO *bio) {
|
||||
BIO_print_errors(bio);
|
||||
}
|
||||
|
||||
/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On
|
||||
* success, |*out| is set to an allocated buffer (which should be freed with
|
||||
* |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
|
||||
* buffer will contain |prefix| followed by the contents of |bio|. On failure,
|
||||
* zero is returned.
|
||||
*
|
||||
* The function will fail if the size of the output would equal or exceed
|
||||
* |max_len|. */
|
||||
static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
|
||||
const uint8_t *prefix, size_t prefix_len,
|
||||
size_t max_len) {
|
||||
static const size_t kChunkSize = 4096;
|
||||
|
||||
size_t len = prefix_len + kChunkSize;
|
||||
if (len > max_len) {
|
||||
len = max_len;
|
||||
}
|
||||
if (len < prefix_len) {
|
||||
return 0;
|
||||
}
|
||||
*out = OPENSSL_malloc(len);
|
||||
if (*out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(*out, prefix, prefix_len);
|
||||
size_t done = prefix_len;
|
||||
|
||||
for (;;) {
|
||||
if (done == len) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
const size_t todo = len - done;
|
||||
assert(todo < INT_MAX);
|
||||
const int n = BIO_read(bio, *out + done, todo);
|
||||
if (n == 0) {
|
||||
*out_len = done;
|
||||
return 1;
|
||||
} else if (n == -1) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
done += n;
|
||||
if (len < max_len && len - done < kChunkSize / 2) {
|
||||
len += kChunkSize;
|
||||
if (len < kChunkSize || len > max_len) {
|
||||
len = max_len;
|
||||
}
|
||||
uint8_t *new_buf = OPENSSL_realloc(*out, len);
|
||||
if (new_buf == NULL) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
*out = new_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
uint8_t header[6];
|
||||
|
||||
static const size_t kInitialHeaderLen = 2;
|
||||
if (BIO_read(bio, header, kInitialHeaderLen) != (int) kInitialHeaderLen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t tag = header[0];
|
||||
const uint8_t length_byte = header[1];
|
||||
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
/* Long form tags are not supported. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len, header_len;
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
/* Short form length. */
|
||||
len = length_byte;
|
||||
header_len = kInitialHeaderLen;
|
||||
} else {
|
||||
const size_t num_bytes = length_byte & 0x7f;
|
||||
|
||||
if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
|
||||
/* indefinite length. */
|
||||
return bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
|
||||
max_len);
|
||||
}
|
||||
|
||||
if (num_bytes == 0 || num_bytes > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) !=
|
||||
(int)num_bytes) {
|
||||
return 0;
|
||||
}
|
||||
header_len = kInitialHeaderLen + num_bytes;
|
||||
|
||||
uint32_t len32 = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < num_bytes; i++) {
|
||||
len32 <<= 8;
|
||||
len32 |= header[kInitialHeaderLen + i];
|
||||
}
|
||||
|
||||
if (len32 < 128) {
|
||||
/* Length should have used short-form encoding. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
||||
/* Length should have been at least one byte shorter. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = len32;
|
||||
}
|
||||
|
||||
if (len + header_len < len ||
|
||||
len + header_len > max_len ||
|
||||
len > INT_MAX) {
|
||||
return 0;
|
||||
}
|
||||
len += header_len;
|
||||
*out_len = len;
|
||||
|
||||
*out = OPENSSL_malloc(len);
|
||||
if (*out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(*out, header, header_len);
|
||||
if (BIO_read(bio, (*out) + header_len, len - header_len) !=
|
||||
(int) (len - header_len)) {
|
||||
OPENSSL_free(*out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* 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. */
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
const ERR_STRING_DATA BIO_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_callback_ctrl, 0), "BIO_callback_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ctrl, 0), "BIO_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new, 0), "BIO_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new_file, 0), "BIO_new_file"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_new_mem_buf, 0), "BIO_new_mem_buf"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_ctrl, 0), "bio_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_io, 0), "bio_io"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_ip_and_port_to_socket_and_addr, 0), "bio_ip_and_port_to_socket_and_addr"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_make_pair, 0), "bio_make_pair"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_bio_write, 0), "bio_write"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_buffer_ctrl, 0), "buffer_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_conn_ctrl, 0), "conn_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_conn_state, 0), "conn_state"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_file_ctrl, 0), "file_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_file_read, 0), "file_read"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_mem_write, 0), "mem_write"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ASN1_OBJECT_TOO_LONG), "ASN1_OBJECT_TOO_LONG"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "BAD_FOPEN_MODE"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "BROKEN_PIPE"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "CONNECT_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ERROR_SETTING_NBIO), "ERROR_SETTING_NBIO"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_ARGUMENT), "INVALID_ARGUMENT"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_IN_USE), "IN_USE"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_KEEPALIVE), "KEEPALIVE"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NBIO_CONNECT_ERROR), "NBIO_CONNECT_ERROR"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_HOSTNAME_SPECIFIED), "NO_HOSTNAME_SPECIFIED"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_SPECIFIED), "NO_PORT_SPECIFIED"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "NO_SUCH_FILE"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "NULL_PARAMETER"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_SYS_LIB), "SYS_LIB"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET), "UNABLE_TO_CREATE_SOCKET"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNINITIALIZED), "UNINITIALIZED"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_METHOD), "UNSUPPORTED_METHOD"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO), "WRITE_TO_READ_ONLY_BIO"},
|
||||
{0, NULL},
|
||||
};
|
||||
@@ -57,7 +57,6 @@
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -70,7 +69,7 @@ BIO *BIO_new_mem_buf(void *buf, int len) {
|
||||
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
|
||||
|
||||
if (!buf && len != 0) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_new_mem_buf, BIO_R_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -167,7 +166,7 @@ static int mem_write(BIO *bio, const char *in, int inl) {
|
||||
b = (BUF_MEM *)bio->ptr;
|
||||
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
OPENSSL_PUT_ERROR(BIO, mem_write, BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -176,7 +175,7 @@ static int mem_write(BIO *bio, const char *in, int inl) {
|
||||
if (INT_MAX - blen < inl) {
|
||||
goto err;
|
||||
}
|
||||
if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
|
||||
if (BUF_MEM_grow_clean(b, blen + inl) != (blen + inl)) {
|
||||
goto err;
|
||||
}
|
||||
memcpy(&b->data[blen], in, inl);
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/* 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. */
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 201410L
|
||||
#endif
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
|
||||
static void print_socket_error(const char *func) {
|
||||
perror(func);
|
||||
}
|
||||
#else
|
||||
static void print_socket_error(const char *func) {
|
||||
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
|
||||
}
|
||||
#endif
|
||||
|
||||
static int test_socket_connect(void) {
|
||||
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int sock;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sockaddr_len = sizeof(sin);
|
||||
static const char kTestMessage[] = "test";
|
||||
char hostname[80], buf[5];
|
||||
BIO *bio;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
|
||||
print_socket_error("inet_pton");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
|
||||
print_socket_error("bind");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (listen(listening_sock, 1)) {
|
||||
print_socket_error("listen");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
|
||||
sockaddr_len != sizeof(sin)) {
|
||||
print_socket_error("getsockname");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
|
||||
ntohs(sin.sin_port));
|
||||
bio = BIO_new_connect(hostname);
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new_connect failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BIO_write(bio, kTestMessage, sizeof(kTestMessage)) !=
|
||||
sizeof(kTestMessage)) {
|
||||
fprintf(stderr, "BIO_write failed.\n");
|
||||
BIO_print_errors_fp(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
|
||||
if (sock < 0) {
|
||||
print_socket_error("accept");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
|
||||
print_socket_error("read");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
closesocket(sock);
|
||||
closesocket(listening_sock);
|
||||
BIO_free(bio);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_printf(void) {
|
||||
/* Test a short output, a very long one, and various sizes around
|
||||
* 256 (the size of the buffer) to ensure edge cases are correct. */
|
||||
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
|
||||
BIO *bio;
|
||||
char string[1024];
|
||||
int ret;
|
||||
const uint8_t *contents;
|
||||
size_t i, len;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
|
||||
if (kLengths[i] >= sizeof(string)) {
|
||||
fprintf(stderr, "Bad test string length\n");
|
||||
return 0;
|
||||
}
|
||||
memset(string, 'a', sizeof(string));
|
||||
string[kLengths[i]] = '\0';
|
||||
|
||||
ret = BIO_printf(bio, "test %s", string);
|
||||
if (ret != 5 + kLengths[i]) {
|
||||
fprintf(stderr, "BIO_printf failed: %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
if (!BIO_mem_contents(bio, &contents, &len)) {
|
||||
fprintf(stderr, "BIO_mem_contents failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (len != 5 + kLengths[i] ||
|
||||
strncmp((const char *)contents, "test ", 5) != 0 ||
|
||||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
|
||||
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BIO_reset(bio)) {
|
||||
fprintf(stderr, "BIO_reset failed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
WSADATA wsa_data;
|
||||
WORD wsa_version;
|
||||
int wsa_err;
|
||||
#endif
|
||||
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
/* Initialize Winsock. */
|
||||
wsa_version = MAKEWORD(2, 2);
|
||||
wsa_err = WSAStartup(wsa_version, &wsa_data);
|
||||
if (wsa_err != 0) {
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
||||
return 1;
|
||||
}
|
||||
if (wsa_data.wVersion != wsa_version) {
|
||||
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!test_socket_connect()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!test_printf()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,440 +0,0 @@
|
||||
/* 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. */
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 201410L
|
||||
#endif
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#pragma warning(push, 3)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../test/scoped_types.h"
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
|
||||
static void PrintSocketError(const char *func) {
|
||||
perror(func);
|
||||
}
|
||||
#else
|
||||
static void PrintSocketError(const char *func) {
|
||||
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
|
||||
}
|
||||
#endif
|
||||
|
||||
class ScopedSocket {
|
||||
public:
|
||||
ScopedSocket(int sock) : sock_(sock) {}
|
||||
~ScopedSocket() {
|
||||
closesocket(sock_);
|
||||
}
|
||||
|
||||
private:
|
||||
const int sock_;
|
||||
};
|
||||
|
||||
static bool TestSocketConnect() {
|
||||
static const char kTestMessage[] = "test";
|
||||
|
||||
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listening_sock == -1) {
|
||||
PrintSocketError("socket");
|
||||
return false;
|
||||
}
|
||||
ScopedSocket listening_sock_closer(listening_sock);
|
||||
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
|
||||
PrintSocketError("inet_pton");
|
||||
return false;
|
||||
}
|
||||
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
|
||||
PrintSocketError("bind");
|
||||
return false;
|
||||
}
|
||||
if (listen(listening_sock, 1)) {
|
||||
PrintSocketError("listen");
|
||||
return false;
|
||||
}
|
||||
socklen_t sockaddr_len = sizeof(sin);
|
||||
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
|
||||
sockaddr_len != sizeof(sin)) {
|
||||
PrintSocketError("getsockname");
|
||||
return false;
|
||||
}
|
||||
|
||||
char hostname[80];
|
||||
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
|
||||
ntohs(sin.sin_port));
|
||||
ScopedBIO bio(BIO_new_connect(hostname));
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new_connect failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
|
||||
sizeof(kTestMessage)) {
|
||||
fprintf(stderr, "BIO_write failed.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
|
||||
if (sock == -1) {
|
||||
PrintSocketError("accept");
|
||||
return false;
|
||||
}
|
||||
ScopedSocket sock_closer(sock);
|
||||
|
||||
char buf[5];
|
||||
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
|
||||
PrintSocketError("read");
|
||||
return false;
|
||||
}
|
||||
if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make
|
||||
// testing easier.
|
||||
static size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) {
|
||||
uint8_t *read_buf;
|
||||
size_t read_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t len_read = 0;
|
||||
|
||||
do {
|
||||
if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
available_bytes = std::min(available_bytes, len - len_read);
|
||||
memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
|
||||
|
||||
BIO_zero_copy_get_read_buf_done(bio, available_bytes);
|
||||
|
||||
len_read += available_bytes;
|
||||
} while (len - len_read > 0 && available_bytes > 0);
|
||||
|
||||
return len_read;
|
||||
}
|
||||
|
||||
// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make
|
||||
// testing easier.
|
||||
static size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data,
|
||||
size_t len) {
|
||||
uint8_t *write_buf;
|
||||
size_t write_buf_offset;
|
||||
size_t available_bytes;
|
||||
size_t len_written = 0;
|
||||
|
||||
do {
|
||||
if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
|
||||
&available_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
available_bytes = std::min(available_bytes, len - len_written);
|
||||
memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
|
||||
|
||||
BIO_zero_copy_get_write_buf_done(bio, available_bytes);
|
||||
|
||||
len_written += available_bytes;
|
||||
} while (len - len_written > 0 && available_bytes > 0);
|
||||
|
||||
return len_written;
|
||||
}
|
||||
|
||||
static bool TestZeroCopyBioPairs() {
|
||||
// Test read and write, especially triggering the ring buffer wrap-around.
|
||||
uint8_t bio1_application_send_buffer[1024];
|
||||
uint8_t bio2_application_recv_buffer[1024];
|
||||
|
||||
const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
|
||||
|
||||
// These trigger ring buffer wrap around.
|
||||
const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
|
||||
|
||||
static const size_t kBufferSize = 512;
|
||||
|
||||
srand(1);
|
||||
for (size_t i = 0; i < sizeof(bio1_application_send_buffer); i++) {
|
||||
bio1_application_send_buffer[i] = rand() & 255;
|
||||
}
|
||||
|
||||
// Transfer bytes from bio1_application_send_buffer to
|
||||
// bio2_application_recv_buffer in various ways.
|
||||
for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
|
||||
for (size_t j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]);
|
||||
j++) {
|
||||
size_t total_write = 0;
|
||||
size_t total_read = 0;
|
||||
|
||||
BIO *bio1, *bio2;
|
||||
if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) {
|
||||
return false;
|
||||
}
|
||||
ScopedBIO bio1_scoper(bio1);
|
||||
ScopedBIO bio2_scoper(bio2);
|
||||
|
||||
total_write += BioWriteZeroCopyWrapper(
|
||||
bio1, bio1_application_send_buffer, kLengths[i]);
|
||||
|
||||
// This tests interleaved read/write calls. Do a read between zero copy
|
||||
// write calls.
|
||||
uint8_t *write_buf;
|
||||
size_t write_buf_offset;
|
||||
size_t available_bytes;
|
||||
if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
|
||||
&available_bytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
|
||||
// This enables ring buffer wrap around for the next write.
|
||||
total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
|
||||
kPartialLengths[j]);
|
||||
|
||||
size_t interleaved_write_len = std::min(kPartialLengths[j],
|
||||
available_bytes);
|
||||
|
||||
// Write the data for the interleaved write call. If the buffer becomes
|
||||
// empty after a read, the write offset is normally set to 0. Check that
|
||||
// this does not happen for interleaved read/write and that
|
||||
// |write_buf_offset| is still valid.
|
||||
memcpy(write_buf + write_buf_offset,
|
||||
bio1_application_send_buffer + total_write, interleaved_write_len);
|
||||
if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
|
||||
total_write += interleaved_write_len;
|
||||
}
|
||||
|
||||
// Do another write in case |write_buf_offset| was wrapped.
|
||||
total_write += BioWriteZeroCopyWrapper(
|
||||
bio1, bio1_application_send_buffer + total_write,
|
||||
kPartialLengths[j] - interleaved_write_len);
|
||||
|
||||
// Drain the rest.
|
||||
size_t bytes_left = BIO_pending(bio2);
|
||||
total_read += BioReadZeroCopyWrapper(
|
||||
bio2, bio2_application_recv_buffer + total_read, bytes_left);
|
||||
|
||||
if (total_read != total_write) {
|
||||
fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return false;
|
||||
}
|
||||
if (total_read > kLengths[i] + kPartialLengths[j]) {
|
||||
fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return false;
|
||||
}
|
||||
if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
|
||||
total_read) != 0) {
|
||||
fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
|
||||
(unsigned)j);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestPrintf() {
|
||||
// Test a short output, a very long one, and various sizes around
|
||||
// 256 (the size of the buffer) to ensure edge cases are correct.
|
||||
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
|
||||
|
||||
ScopedBIO bio(BIO_new(BIO_s_mem()));
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
|
||||
char string[1024];
|
||||
if (kLengths[i] >= sizeof(string)) {
|
||||
fprintf(stderr, "Bad test string length\n");
|
||||
return false;
|
||||
}
|
||||
memset(string, 'a', sizeof(string));
|
||||
string[kLengths[i]] = '\0';
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", string);
|
||||
if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
|
||||
fprintf(stderr, "BIO_printf failed: %d\n", ret);
|
||||
return false;
|
||||
}
|
||||
const uint8_t *contents;
|
||||
size_t len;
|
||||
if (!BIO_mem_contents(bio.get(), &contents, &len)) {
|
||||
fprintf(stderr, "BIO_mem_contents failed\n");
|
||||
return false;
|
||||
}
|
||||
if (len != 5 + kLengths[i] ||
|
||||
strncmp((const char *)contents, "test ", 5) != 0 ||
|
||||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
|
||||
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BIO_reset(bio.get())) {
|
||||
fprintf(stderr, "BIO_reset failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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(const_cast<uint8_t*>(data), data_len));
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_len;
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
|
||||
if (!ok) {
|
||||
out = nullptr;
|
||||
}
|
||||
ScopedOpenSSLBytes out_storage(out);
|
||||
|
||||
if (should_succeed != (ok == 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (should_succeed &&
|
||||
(out_len != expected_len || memcmp(data, out, expected_len) != 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestASN1() {
|
||||
static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
|
||||
static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
|
||||
static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
|
||||
static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
|
||||
|
||||
if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
|
||||
!ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
|
||||
!ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
|
||||
!ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const size_t kLargePayloadLen = 8000;
|
||||
static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
|
||||
kLargePayloadLen & 0xff};
|
||||
ScopedOpenSSLBytes large(reinterpret_cast<uint8_t *>(
|
||||
OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
|
||||
if (!large) {
|
||||
return false;
|
||||
}
|
||||
memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
|
||||
memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
|
||||
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen * 2)) {
|
||||
fprintf(stderr, "Large payload test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen - 1)) {
|
||||
fprintf(stderr, "max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint8_t kIndefPrefix[] = {0x30, 0x80};
|
||||
memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen*2)) {
|
||||
fprintf(stderr, "indefinite length test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen-1)) {
|
||||
fprintf(stderr, "indefinite length, max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
WORD wsa_version = MAKEWORD(2, 2);
|
||||
WSADATA wsa_data;
|
||||
int wsa_err = WSAStartup(wsa_version, &wsa_data);
|
||||
if (wsa_err != 0) {
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
||||
return 1;
|
||||
}
|
||||
if (wsa_data.wVersion != wsa_version) {
|
||||
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!TestSocketConnect() ||
|
||||
!TestPrintf() ||
|
||||
!TestZeroCopyBioPairs() ||
|
||||
!TestASN1()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
+13
-12
@@ -56,8 +56,6 @@
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
@@ -100,7 +98,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;
|
||||
}
|
||||
@@ -122,13 +120,17 @@ err1:
|
||||
static int buffer_free(BIO *bio) {
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
if (bio == NULL || bio->ptr == NULL) {
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
OPENSSL_free(ctx->obuf);
|
||||
if (ctx->ibuf != NULL) {
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
}
|
||||
if (ctx->obuf != NULL) {
|
||||
OPENSSL_free(ctx->obuf);
|
||||
}
|
||||
OPENSSL_free(bio->ptr);
|
||||
|
||||
bio->ptr = NULL;
|
||||
@@ -311,9 +313,8 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = (long)ctx->obuf_len;
|
||||
if (ret == 0) {
|
||||
if (b->next_bio == NULL) {
|
||||
if (b->next_bio == NULL)
|
||||
return 0;
|
||||
}
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
}
|
||||
break;
|
||||
@@ -340,13 +341,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);
|
||||
@@ -406,7 +407,7 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
return ret;
|
||||
|
||||
malloc_error:
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_PUT_ERROR(BIO, buffer_ctrl, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -479,7 +480,7 @@ static int buffer_puts(BIO *b, const char *str) {
|
||||
return buffer_write(b, str, strlen(str));
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_buffer = {
|
||||
static BIO_METHOD methods_buffer = {
|
||||
BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read,
|
||||
buffer_puts, buffer_gets, buffer_ctrl, buffer_new,
|
||||
buffer_free, buffer_callback_ctrl,
|
||||
|
||||
+86
-95
@@ -59,18 +59,12 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#pragma warning(push, 3)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <openssl/buf.h>
|
||||
@@ -93,6 +87,7 @@ typedef struct bio_connect_st {
|
||||
char *param_port;
|
||||
int nbio;
|
||||
|
||||
uint8_t ip[4];
|
||||
unsigned short port;
|
||||
|
||||
struct sockaddr_storage them;
|
||||
@@ -113,59 +108,23 @@ static int closesocket(int sock) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* split_host_and_port sets |*out_host| and |*out_port| to the host and port
|
||||
* parsed from |name|. It returns one on success or zero on error. Even when
|
||||
* successful, |*out_port| may be NULL on return if no port was specified. */
|
||||
static int split_host_and_port(char **out_host, char **out_port, const char *name) {
|
||||
const char *host, *port = NULL;
|
||||
size_t host_len = 0;
|
||||
/* maybe_copy_ipv4_address sets |*ipv4| to the IPv4 address from |ss| (in
|
||||
* big-endian order), if |ss| contains an IPv4 socket address. */
|
||||
static void maybe_copy_ipv4_address(uint8_t *ipv4,
|
||||
const struct sockaddr_storage *ss) {
|
||||
const struct sockaddr_in *sin;
|
||||
|
||||
*out_host = NULL;
|
||||
*out_port = NULL;
|
||||
|
||||
if (name[0] == '[') { /* bracketed IPv6 address */
|
||||
const char *close = strchr(name, ']');
|
||||
if (close == NULL) {
|
||||
return 0;
|
||||
}
|
||||
host = name + 1;
|
||||
host_len = close - host;
|
||||
if (close[1] == ':') { /* [IP]:port */
|
||||
port = close + 2;
|
||||
} else if (close[1] != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
const char *colon = strchr(name, ':');
|
||||
if (colon == NULL || strchr(colon + 1, ':') != NULL) { /* IPv6 address */
|
||||
host = name;
|
||||
host_len = strlen(name);
|
||||
} else { /* host:port */
|
||||
host = name;
|
||||
host_len = colon - name;
|
||||
port = colon + 1;
|
||||
}
|
||||
if (ss->ss_family != AF_INET) {
|
||||
return;
|
||||
}
|
||||
|
||||
*out_host = BUF_strndup(host, host_len);
|
||||
if (*out_host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (port == NULL) {
|
||||
*out_port = NULL;
|
||||
return 1;
|
||||
}
|
||||
*out_port = OPENSSL_strdup(port);
|
||||
if (*out_port == NULL) {
|
||||
OPENSSL_free(*out_host);
|
||||
*out_host = NULL;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
sin = (const struct sockaddr_in*) ss;
|
||||
memcpy(ipv4, &sin->sin_addr, 4);
|
||||
}
|
||||
|
||||
static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
int ret = -1, i;
|
||||
char *p, *q;
|
||||
int (*cb)(const BIO *, int, int) = NULL;
|
||||
|
||||
if (c->info_callback != NULL) {
|
||||
@@ -175,43 +134,54 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case BIO_CONN_S_BEFORE:
|
||||
/* If there's a hostname and a port, assume that both are
|
||||
* exactly what they say. If there is only a hostname, try
|
||||
* (just once) to split it into a hostname and port. */
|
||||
|
||||
if (c->param_hostname == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED);
|
||||
p = c->param_hostname;
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_HOSTNAME_SPECIFIED);
|
||||
goto exit_loop;
|
||||
}
|
||||
for (; *p != 0; p++) {
|
||||
if (*p == ':' || *p == '/') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i = *p;
|
||||
if (i == ':' || i == '/') {
|
||||
*(p++) = 0;
|
||||
if (i == ':') {
|
||||
for (q = p; *q; q++) {
|
||||
if (*q == '/') {
|
||||
*q = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c->param_port != NULL) {
|
||||
OPENSSL_free(c->param_port);
|
||||
}
|
||||
c->param_port = BUF_strdup(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->param_port == NULL) {
|
||||
char *host, *port;
|
||||
if (!split_host_and_port(&host, &port, c->param_hostname) ||
|
||||
port == NULL) {
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(port);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED);
|
||||
ERR_add_error_data(2, "host=", c->param_hostname);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
OPENSSL_free(c->param_port);
|
||||
c->param_port = port;
|
||||
OPENSSL_free(c->param_hostname);
|
||||
c->param_hostname = host;
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_PORT_SPECIFIED);
|
||||
ERR_add_error_data(2, "host=", c->param_hostname);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (!bio_ip_and_port_to_socket_and_addr(
|
||||
&bio->num, &c->them, &c->them_length, c->param_hostname,
|
||||
c->param_port)) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
memset(c->ip, 0, 4);
|
||||
maybe_copy_ipv4_address(c->ip, &c->them);
|
||||
|
||||
if (c->nbio) {
|
||||
if (!bio_socket_nbio(bio->num, 1)) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO);
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_ERROR_SETTING_NBIO);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":",
|
||||
c->param_port);
|
||||
goto exit_loop;
|
||||
@@ -222,8 +192,8 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
|
||||
sizeof(i));
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_KEEPALIVE);
|
||||
OPENSSL_PUT_SYSTEM_ERROR(setsockopt);
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_KEEPALIVE);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
@@ -236,8 +206,8 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
c->state = BIO_CONN_S_BLOCKED_CONNECT;
|
||||
bio->retry_reason = BIO_RR_CONNECT;
|
||||
} else {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_CONNECT_ERROR);
|
||||
OPENSSL_PUT_SYSTEM_ERROR(connect);
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_CONNECT_ERROR);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":",
|
||||
c->param_port);
|
||||
}
|
||||
@@ -257,8 +227,8 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
ret = -1;
|
||||
} else {
|
||||
BIO_clear_retry_flags(bio);
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NBIO_CONNECT_ERROR);
|
||||
OPENSSL_PUT_SYSTEM_ERROR(connect);
|
||||
OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NBIO_CONNECT_ERROR);
|
||||
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
|
||||
ret = 0;
|
||||
}
|
||||
@@ -310,8 +280,12 @@ static void BIO_CONNECT_free(BIO_CONNECT *c) {
|
||||
return;
|
||||
}
|
||||
|
||||
OPENSSL_free(c->param_hostname);
|
||||
OPENSSL_free(c->param_port);
|
||||
if (c->param_hostname != NULL) {
|
||||
OPENSSL_free(c->param_hostname);
|
||||
}
|
||||
if (c->param_port != NULL) {
|
||||
OPENSSL_free(c->param_port);
|
||||
}
|
||||
OPENSSL_free(c);
|
||||
}
|
||||
|
||||
@@ -402,6 +376,7 @@ static int conn_write(BIO *bio, const char *in, int in_len) {
|
||||
|
||||
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
int *ip;
|
||||
const char **pptr;
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
@@ -416,9 +391,27 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
/* use this one to start the connection */
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
if (data->state != BIO_CONN_S_OK)
|
||||
ret = (long)conn_state(bio, data);
|
||||
} else {
|
||||
else
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_C_GET_CONNECT:
|
||||
/* TODO(fork): can this be removed? (Or maybe this whole file). */
|
||||
if (ptr != NULL) {
|
||||
pptr = (const char **)ptr;
|
||||
if (num == 0) {
|
||||
*pptr = data->param_hostname;
|
||||
} else if (num == 1) {
|
||||
*pptr = data->param_port;
|
||||
} else if (num == 2) {
|
||||
*pptr = (char *) &data->ip[0];
|
||||
} else if (num == 3) {
|
||||
*((int *)ptr) = data->port;
|
||||
}
|
||||
if (!bio->init) {
|
||||
*pptr = "not initialized";
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
@@ -426,17 +419,15 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
if (ptr != NULL) {
|
||||
bio->init = 1;
|
||||
if (num == 0) {
|
||||
OPENSSL_free(data->param_hostname);
|
||||
if (data->param_hostname != NULL) {
|
||||
OPENSSL_free(data->param_hostname);
|
||||
}
|
||||
data->param_hostname = BUF_strdup(ptr);
|
||||
if (data->param_hostname == NULL) {
|
||||
ret = 0;
|
||||
}
|
||||
} else if (num == 1) {
|
||||
OPENSSL_free(data->param_port);
|
||||
data->param_port = BUF_strdup(ptr);
|
||||
if (data->param_port == NULL) {
|
||||
ret = 0;
|
||||
if (data->param_port != NULL) {
|
||||
OPENSSL_free(data->param_port);
|
||||
}
|
||||
data->param_port = BUF_strdup(ptr);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
@@ -451,9 +442,9 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
if (ip != NULL) {
|
||||
*ip = bio->num;
|
||||
}
|
||||
ret = bio->num;
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = -1;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
@@ -470,7 +461,7 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
break;
|
||||
case BIO_CTRL_SET_CALLBACK: {
|
||||
#if 0 /* FIXME: Should this be used? -- Richard Levitte */
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
OPENSSL_PUT_ERROR(BIO, XXX, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
ret = -1;
|
||||
#else
|
||||
ret = 0;
|
||||
|
||||
+3
-6
@@ -57,15 +57,12 @@
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#pragma warning(push, 3)
|
||||
#include <windows.h>
|
||||
#pragma warning(pop)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/buf.h>
|
||||
@@ -208,9 +205,9 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
if (ip != NULL) {
|
||||
*ip = b->num;
|
||||
}
|
||||
return b->num;
|
||||
return 1;
|
||||
} else {
|
||||
ret = -1;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
|
||||
+14
-14
@@ -76,7 +76,6 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -88,7 +87,7 @@
|
||||
#define BIO_FP_APPEND 0x08
|
||||
|
||||
static FILE *open_file(const char *filename, const char *mode) {
|
||||
#if defined(OPENSSL_WINDOWS) && defined(CP_UTF8)
|
||||
#if defined(_WIN32) && defined(CP_UTF8)
|
||||
int sz, len_0 = (int)strlen(filename) + 1;
|
||||
DWORD flags;
|
||||
|
||||
@@ -129,13 +128,13 @@ BIO *BIO_new_file(const char *filename, const char *mode) {
|
||||
|
||||
file = open_file(filename, mode);
|
||||
if (file == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_SYSTEM_ERROR(fopen);
|
||||
|
||||
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
|
||||
if (errno == ENOENT) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_new_file, BIO_R_NO_SUCH_FILE);
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_SYS_LIB);
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_new_file, BIO_R_SYS_LIB);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -182,19 +181,20 @@ static int file_free(BIO *bio) {
|
||||
}
|
||||
|
||||
static int file_read(BIO *b, char *out, int outl) {
|
||||
int ret = 0;
|
||||
|
||||
if (!b->init) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ret = fread(out, 1, outl, (FILE *)b->ptr);
|
||||
ret = fread(out, 1, outl, (FILE *)b->ptr);
|
||||
if (ret == 0 && ferror((FILE *)b->ptr)) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
|
||||
return -1;
|
||||
OPENSSL_PUT_SYSTEM_ERROR(fread);
|
||||
OPENSSL_PUT_ERROR(BIO, file_read, ERR_R_SYS_LIB);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* fread reads at most |outl| bytes, so |ret| fits in an int. */
|
||||
return (int)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_write(BIO *b, const char *in, int inl) {
|
||||
@@ -252,15 +252,15 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
} else if (num & BIO_FP_READ) {
|
||||
BUF_strlcpy(p, "r", sizeof(p));
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
|
||||
OPENSSL_PUT_ERROR(BIO, file_ctrl, BIO_R_BAD_FOPEN_MODE);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
fp = open_file(ptr, p);
|
||||
if (fp == NULL) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_SYSTEM_ERROR(fopen);
|
||||
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
|
||||
OPENSSL_PUT_ERROR(BIO, file_ctrl, ERR_R_SYS_LIB);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* hexdump_ctx contains the state of a hexdump. */
|
||||
@@ -82,10 +81,9 @@ static char to_char(uint8_t b) {
|
||||
return b;
|
||||
}
|
||||
|
||||
/* hexdump_write adds |len| bytes of |data| to the current hex dump described by
|
||||
/* hexdump adds |len| bytes of |data| to the current hex dump described by
|
||||
* |ctx|. */
|
||||
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
size_t len) {
|
||||
static int hexdump(struct hexdump_ctx *ctx, const uint8_t *data, size_t len) {
|
||||
size_t i;
|
||||
char buf[10];
|
||||
unsigned l;
|
||||
@@ -184,7 +182,7 @@ int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
|
||||
ctx.bio = bio;
|
||||
ctx.indent = indent;
|
||||
|
||||
if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
|
||||
if (!hexdump(&ctx, data, len) || !finish(&ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,8 @@ typedef unsigned short u_short;
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
typedef int socklen_t;
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
+82
-336
@@ -53,7 +53,6 @@
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -71,13 +70,7 @@ struct bio_bio_st {
|
||||
size_t len; /* valid iff buf != NULL; 0 if peer == NULL */
|
||||
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
|
||||
size_t size;
|
||||
uint8_t *buf; /* "size" elements (if != NULL) */
|
||||
char buf_externally_allocated; /* true iff buf was externally allocated. */
|
||||
|
||||
char zero_copy_read_lock; /* true iff a zero copy read operation
|
||||
* is in progress. */
|
||||
char zero_copy_write_lock; /* true iff a zero copy write operation
|
||||
* is in progress. */
|
||||
char *buf; /* "size" elements (if != NULL) */
|
||||
|
||||
size_t request; /* valid iff peer != NULL; 0 if len != 0,
|
||||
* otherwise set by peer to number of bytes
|
||||
@@ -92,9 +85,11 @@ static int bio_new(BIO *bio) {
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memset(b, 0, sizeof(struct bio_bio_st));
|
||||
|
||||
b->peer = NULL;
|
||||
b->size = 17 * 1024; /* enough for one TLS record (just a default) */
|
||||
b->buf = NULL;
|
||||
|
||||
bio->ptr = b;
|
||||
return 1;
|
||||
}
|
||||
@@ -145,7 +140,7 @@ static int bio_free(BIO *bio) {
|
||||
bio_destroy_pair(bio);
|
||||
}
|
||||
|
||||
if (!b->buf_externally_allocated) {
|
||||
if (b->buf != NULL) {
|
||||
OPENSSL_free(b->buf);
|
||||
}
|
||||
|
||||
@@ -154,254 +149,6 @@ static int bio_free(BIO *bio) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
|
||||
uint8_t** out_read_buf,
|
||||
size_t* out_buf_offset) {
|
||||
size_t max_available;
|
||||
if (peer_b->len > peer_b->size - peer_b->offset) {
|
||||
/* Only the first half of the ring buffer can be read. */
|
||||
max_available = peer_b->size - peer_b->offset;
|
||||
} else {
|
||||
max_available = peer_b->len;
|
||||
}
|
||||
|
||||
*out_read_buf = peer_b->buf;
|
||||
*out_buf_offset = peer_b->offset;
|
||||
return max_available;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
|
||||
size_t* out_buf_offset,
|
||||
size_t* out_available_bytes) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
*out_available_bytes = 0;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (peer_b->zero_copy_read_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b->request = 0; /* Is not used by zero-copy API. */
|
||||
|
||||
max_available =
|
||||
bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
|
||||
|
||||
assert(peer_b->buf != NULL);
|
||||
if (max_available > 0) {
|
||||
peer_b->zero_copy_read_lock = 1;
|
||||
}
|
||||
|
||||
*out_available_bytes = max_available;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
size_t dummy_read_offset;
|
||||
uint8_t* dummy_read_buf;
|
||||
|
||||
assert(BIO_get_retry_flags(bio) == 0);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!peer_b->zero_copy_read_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_available =
|
||||
bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
|
||||
if (bytes_read > max_available) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(peer_b->len >= bytes_read);
|
||||
peer_b->len -= bytes_read;
|
||||
assert(peer_b->offset + bytes_read <= peer_b->size);
|
||||
|
||||
/* Move read offset. If zero_copy_write_lock == 1 we must advance the
|
||||
* offset even if buffer becomes empty, to make sure
|
||||
* write_offset = (offset + len) mod size does not change. */
|
||||
if (peer_b->offset + bytes_read == peer_b->size ||
|
||||
(!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
|
||||
peer_b->offset = 0;
|
||||
} else {
|
||||
peer_b->offset += bytes_read;
|
||||
}
|
||||
|
||||
bio->num_read += bytes_read;
|
||||
peer_b->zero_copy_read_lock = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
|
||||
uint8_t** out_write_buf,
|
||||
size_t* out_buf_offset) {
|
||||
size_t write_offset;
|
||||
size_t max_available;
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
write_offset = b->offset + b->len;
|
||||
|
||||
if (write_offset >= b->size) {
|
||||
/* Only the first half of the ring buffer can be written to. */
|
||||
write_offset -= b->size;
|
||||
/* write up to the start of the ring buffer. */
|
||||
max_available = b->offset - write_offset;
|
||||
} else {
|
||||
/* write up to the end the buffer. */
|
||||
max_available = b->size - write_offset;
|
||||
}
|
||||
|
||||
*out_write_buf = b->buf;
|
||||
*out_buf_offset = write_offset;
|
||||
return max_available;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
|
||||
size_t* out_buf_offset,
|
||||
size_t* out_available_bytes) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
size_t max_available;
|
||||
|
||||
*out_available_bytes = 0;
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->buf || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(b->buf != NULL);
|
||||
|
||||
if (b->zero_copy_write_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* Bio is already closed. */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
|
||||
|
||||
if (max_available > 0) {
|
||||
b->zero_copy_write_lock = 1;
|
||||
}
|
||||
|
||||
*out_available_bytes = max_available;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
|
||||
struct bio_bio_st* b;
|
||||
struct bio_bio_st* peer_b;
|
||||
|
||||
size_t rest;
|
||||
size_t dummy_write_offset;
|
||||
uint8_t* dummy_write_buf;
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
if (!b || !b->buf || !b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
peer_b = b->peer->ptr;
|
||||
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* BIO is already closed. */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!b->zero_copy_write_lock) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
|
||||
|
||||
if (bytes_written > rest) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio->num_write += bytes_written;
|
||||
/* Move write offset. */
|
||||
b->len += bytes_written;
|
||||
b->zero_copy_write_lock = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
size_t size = size_;
|
||||
size_t rest;
|
||||
@@ -422,7 +169,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
|
||||
peer_b->request = 0; /* will be set in "retry_read" situation */
|
||||
|
||||
if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
|
||||
if (buf == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -467,10 +214,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
|
||||
peer_b->len -= chunk;
|
||||
/* If zero_copy_write_lock == 1 we must advance the offset even if buffer
|
||||
* becomes empty, to make sure write_offset = (offset + len) % size
|
||||
* does not change. */
|
||||
if (peer_b->len || peer_b->zero_copy_write_lock) {
|
||||
if (peer_b->len) {
|
||||
peer_b->offset += chunk;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size) {
|
||||
@@ -504,14 +248,10 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
if (b->zero_copy_write_lock) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* we already closed */
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
OPENSSL_PUT_ERROR(BIO, bio_write, BIO_R_BROKEN_PIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -564,9 +304,7 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
return num;
|
||||
}
|
||||
|
||||
static int bio_make_pair(BIO* bio1, BIO* bio2,
|
||||
size_t writebuf1_len, uint8_t* ext_writebuf1,
|
||||
size_t writebuf2_len, uint8_t* ext_writebuf2) {
|
||||
static int bio_make_pair(BIO *bio1, BIO *bio2) {
|
||||
struct bio_bio_st *b1, *b2;
|
||||
|
||||
assert(bio1 != NULL);
|
||||
@@ -576,46 +314,25 @@ static int bio_make_pair(BIO* bio1, BIO* bio2,
|
||||
b2 = bio2->ptr;
|
||||
|
||||
if (b1->peer != NULL || b2->peer != NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, BIO_R_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(b1->buf_externally_allocated == 0);
|
||||
assert(b2->buf_externally_allocated == 0);
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
if (writebuf1_len) {
|
||||
b1->size = writebuf1_len;
|
||||
}
|
||||
if (!ext_writebuf1) {
|
||||
b1->buf_externally_allocated = 0;
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
b1->buf = ext_writebuf1;
|
||||
b1->buf_externally_allocated = 1;
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
}
|
||||
|
||||
if (b2->buf == NULL) {
|
||||
if (writebuf2_len) {
|
||||
b2->size = writebuf2_len;
|
||||
}
|
||||
if (!ext_writebuf2) {
|
||||
b2->buf_externally_allocated = 0;
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
b2->buf = ext_writebuf2;
|
||||
b2->buf_externally_allocated = 1;
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b2->len = 0;
|
||||
b2->offset = 0;
|
||||
@@ -624,13 +341,9 @@ static int bio_make_pair(BIO* bio1, BIO* bio2,
|
||||
b1->peer = bio2;
|
||||
b1->closed = 0;
|
||||
b1->request = 0;
|
||||
b1->zero_copy_read_lock = 0;
|
||||
b1->zero_copy_write_lock = 0;
|
||||
b2->peer = bio1;
|
||||
b2->closed = 0;
|
||||
b2->request = 0;
|
||||
b2->zero_copy_read_lock = 0;
|
||||
b2->zero_copy_write_lock = 0;
|
||||
|
||||
bio1->init = 1;
|
||||
bio2->init = 1;
|
||||
@@ -647,6 +360,27 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
switch (cmd) {
|
||||
/* specific CTRL codes */
|
||||
|
||||
case BIO_C_SET_BUFF_SIZE:
|
||||
if (b->peer) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_ctrl, BIO_R_IN_USE);
|
||||
ret = 0;
|
||||
} else if (num == 0) {
|
||||
OPENSSL_PUT_ERROR(BIO, bio_ctrl, BIO_R_INVALID_ARGUMENT);
|
||||
ret = 0;
|
||||
} else {
|
||||
size_t new_size = num;
|
||||
|
||||
if (b->size != new_size) {
|
||||
if (b->buf) {
|
||||
OPENSSL_free(b->buf);
|
||||
b->buf = NULL;
|
||||
}
|
||||
b->size = new_size;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_BUF_SIZE:
|
||||
ret = (long)b->size;
|
||||
break;
|
||||
@@ -685,6 +419,14 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
|
||||
/* standard CTRL codes follow */
|
||||
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->buf != NULL) {
|
||||
b->len = 0;
|
||||
b->offset = 0;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
@@ -736,53 +478,49 @@ static int bio_puts(BIO *bio, const char *str) {
|
||||
return bio_write(bio, str, strlen(str));
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read,
|
||||
bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new,
|
||||
bio_free, NULL /* no bio_callback_ctrl */
|
||||
};
|
||||
|
||||
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) {
|
||||
return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
|
||||
writebuf2, NULL);
|
||||
}
|
||||
|
||||
int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
|
||||
uint8_t* ext_writebuf1,
|
||||
BIO** bio2_p, size_t writebuf2_len,
|
||||
uint8_t* ext_writebuf2) {
|
||||
int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p,
|
||||
size_t writebuf2) {
|
||||
BIO *bio1 = NULL, *bio2 = NULL;
|
||||
long r;
|
||||
int ret = 0;
|
||||
|
||||
/* External buffers must have sizes greater than 0. */
|
||||
if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bio1 = BIO_new(bio_s_bio());
|
||||
bio1 = BIO_new(BIO_s_bio());
|
||||
if (bio1 == NULL) {
|
||||
goto err;
|
||||
}
|
||||
bio2 = BIO_new(bio_s_bio());
|
||||
bio2 = BIO_new(BIO_s_bio());
|
||||
if (bio2 == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
|
||||
ext_writebuf2)) {
|
||||
if (writebuf1) {
|
||||
r = BIO_set_write_buffer_size(bio1, writebuf1);
|
||||
if (!r) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (writebuf2) {
|
||||
r = BIO_set_write_buffer_size(bio2, writebuf2);
|
||||
if (!r) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bio_make_pair(bio1, bio2)) {
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ret == 0) {
|
||||
BIO_free(bio1);
|
||||
bio1 = NULL;
|
||||
BIO_free(bio2);
|
||||
bio2 = NULL;
|
||||
if (bio1) {
|
||||
BIO_free(bio1);
|
||||
bio1 = NULL;
|
||||
}
|
||||
if (bio2) {
|
||||
BIO_free(bio2);
|
||||
bio2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*bio1_p = bio1;
|
||||
@@ -790,6 +528,14 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read,
|
||||
bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new,
|
||||
bio_free, NULL /* no bio_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_bio(void) { return &methods_biop; }
|
||||
|
||||
size_t BIO_ctrl_get_read_request(BIO *bio) {
|
||||
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
|
||||
}
|
||||
|
||||
+4
-8
@@ -64,7 +64,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
@@ -87,11 +86,7 @@ int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (out_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size_t) out_len >= sizeof(buf)) {
|
||||
if (out_len >= sizeof(buf)) {
|
||||
const int requested_len = out_len;
|
||||
/* The output was truncated. Note that vsnprintf's return value
|
||||
* does not include a trailing NUL, but the buffer must be sized
|
||||
@@ -99,8 +94,9 @@ int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
out = OPENSSL_malloc(requested_len + 1);
|
||||
out_malloced = 1;
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
/* Unclear what can be done in this situation. OpenSSL has historically
|
||||
* crashed and that seems better than producing the wrong output. */
|
||||
abort();
|
||||
}
|
||||
va_start(args, format);
|
||||
out_len = vsnprintf(out, requested_len + 1, format, args);
|
||||
|
||||
+2
-11
@@ -58,16 +58,9 @@
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#pragma warning(push, 3)
|
||||
#include <winsock2.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
@@ -152,13 +145,11 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL) {
|
||||
if (ip != NULL)
|
||||
*ip = b->num;
|
||||
}
|
||||
ret = b->num;
|
||||
} else {
|
||||
} else
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
|
||||
@@ -12,24 +12,21 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#define _POSIX_SOURCE
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#pragma warning(push, 3)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma warning(pop)
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
@@ -51,15 +48,15 @@ int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
|
||||
ret = getaddrinfo(hostname, port_str, &hint, &result);
|
||||
if (ret != 0) {
|
||||
OPENSSL_PUT_ERROR(SYS, 0);
|
||||
ERR_add_error_data(1, gai_strerror(ret));
|
||||
OPENSSL_PUT_ERROR(SYS, getaddrinfo, 0);
|
||||
ERR_add_error_data(2, gai_strerror(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
for (cur = result; cur; cur = cur->ai_next) {
|
||||
if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
|
||||
if (cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
|
||||
continue;
|
||||
}
|
||||
memset(out_addr, 0, sizeof(struct sockaddr_storage));
|
||||
@@ -68,7 +65,7 @@ int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
|
||||
*out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
||||
if (*out_sock < 0) {
|
||||
OPENSSL_PUT_SYSTEM_ERROR();
|
||||
OPENSSL_PUT_SYSTEM_ERROR(socket);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
+44
-54
@@ -1,88 +1,78 @@
|
||||
include_directories(../../include)
|
||||
include_directories(. .. ../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
x86_64-mont.${ASM_EXT}
|
||||
x86_64-mont5.${ASM_EXT}
|
||||
rsaz-x86_64.${ASM_EXT}
|
||||
rsaz-avx2.${ASM_EXT}
|
||||
asm/x86_64-gcc.c
|
||||
x86_64-mont.${ASM_EXT}
|
||||
x86_64-mont5.${ASM_EXT}
|
||||
modexp512-x86_64.${ASM_EXT}
|
||||
rsaz-x86_64.${ASM_EXT}
|
||||
rsaz-avx2.${ASM_EXT}
|
||||
|
||||
rsaz_exp.c
|
||||
)
|
||||
rsaz_exp.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
bn-586.${ASM_EXT}
|
||||
co-586.${ASM_EXT}
|
||||
x86-mont.${ASM_EXT}
|
||||
)
|
||||
bn-586.${ASM_EXT}
|
||||
co-586.${ASM_EXT}
|
||||
x86-mont.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
armv4-mont.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
armv8-mont.${ASM_EXT}
|
||||
)
|
||||
armv4-mont.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
bn
|
||||
bn
|
||||
|
||||
OBJECT
|
||||
OBJECT
|
||||
|
||||
add.c
|
||||
asm/x86_64-gcc.c
|
||||
bn.c
|
||||
bn_asn1.c
|
||||
cmp.c
|
||||
convert.c
|
||||
ctx.c
|
||||
div.c
|
||||
exponentiation.c
|
||||
generic.c
|
||||
gcd.c
|
||||
kronecker.c
|
||||
montgomery.c
|
||||
mul.c
|
||||
prime.c
|
||||
random.c
|
||||
shift.c
|
||||
sqrt.c
|
||||
bn_error.c
|
||||
add.c
|
||||
bn.c
|
||||
cmp.c
|
||||
convert.c
|
||||
ctx.c
|
||||
div.c
|
||||
exponentiation.c
|
||||
generic.c
|
||||
gcd.c
|
||||
kronecker.c
|
||||
montgomery.c
|
||||
mul.c
|
||||
prime.c
|
||||
random.c
|
||||
shift.c
|
||||
sqrt.c
|
||||
|
||||
${BN_ARCH_SOURCES}
|
||||
${BN_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
|
||||
perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
|
||||
perlasm(modexp512-x86_64.${ASM_EXT} asm/modexp512-x86_64.pl)
|
||||
perlasm(rsaz-x86_64.${ASM_EXT} asm/rsaz-x86_64.pl)
|
||||
perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
|
||||
perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
|
||||
perlasm(co-586.${ASM_EXT} asm/co-586.pl)
|
||||
perlasm(x86-mont.${ASM_EXT} asm/x86-mont.pl)
|
||||
perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl)
|
||||
perlasm(armv8-mont.${ASM_EXT} asm/armv8-mont.pl)
|
||||
|
||||
add_executable(
|
||||
bn_test
|
||||
bn_test
|
||||
|
||||
bn_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
bn_test.c
|
||||
)
|
||||
|
||||
target_link_libraries(bn_test crypto)
|
||||
add_dependencies(all_tests bn_test)
|
||||
|
||||
+22
-5
@@ -56,8 +56,6 @@
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -269,7 +267,7 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
|
||||
|
||||
if (dif < 0) /* hmm... should not be happening */
|
||||
{
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3);
|
||||
OPENSSL_PUT_ERROR(BN, BN_usub, BN_R_ARG2_LT_ARG3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -313,8 +311,27 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
|
||||
}
|
||||
}
|
||||
|
||||
if (dif > 0 && rp != ap) {
|
||||
memcpy(rp, ap, sizeof(*rp) * dif);
|
||||
if (rp != ap) {
|
||||
for (;;) {
|
||||
if (!dif--) {
|
||||
break;
|
||||
}
|
||||
rp[0] = ap[0];
|
||||
if (!dif--) {
|
||||
break;
|
||||
}
|
||||
rp[1] = ap[1];
|
||||
if (!dif--) {
|
||||
break;
|
||||
}
|
||||
rp[2] = ap[2];
|
||||
if (!dif--) {
|
||||
break;
|
||||
}
|
||||
rp[3] = ap[3];
|
||||
rp += 4;
|
||||
ap += 4;
|
||||
}
|
||||
}
|
||||
|
||||
r->top = max;
|
||||
|
||||
+11
-34
@@ -38,20 +38,8 @@
|
||||
# for execution on all NEON-capable processors, because gain on
|
||||
# others outweighs the marginal loss on Cortex-A9.
|
||||
|
||||
$flavour = shift;
|
||||
if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
|
||||
else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
|
||||
|
||||
if ($flavour && $flavour ne "void") {
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
|
||||
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
|
||||
die "can't locate arm-xlate.pl";
|
||||
|
||||
open STDOUT,"| \"$^X\" $xlate $flavour $output";
|
||||
} else {
|
||||
open STDOUT,">$output";
|
||||
}
|
||||
while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
|
||||
open STDOUT,">$output";
|
||||
|
||||
$num="r0"; # starts as num argument, but holds &tp[num-1]
|
||||
$ap="r1";
|
||||
@@ -79,34 +67,31 @@ $_n0="$num,#14*4";
|
||||
$_num="$num,#15*4"; $_bpend=$_num;
|
||||
|
||||
$code=<<___;
|
||||
#include <openssl/arm_arch.h>
|
||||
#include "arm_arch.h"
|
||||
|
||||
.text
|
||||
.code 32
|
||||
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
#if __ARM_ARCH__>=7
|
||||
.align 5
|
||||
.LOPENSSL_armcap:
|
||||
.word OPENSSL_armcap_P-.Lbn_mul_mont
|
||||
.word OPENSSL_armcap_P-bn_mul_mont
|
||||
#endif
|
||||
|
||||
.global bn_mul_mont
|
||||
.hidden bn_mul_mont
|
||||
.type bn_mul_mont,%function
|
||||
|
||||
.align 5
|
||||
bn_mul_mont:
|
||||
.Lbn_mul_mont:
|
||||
ldr ip,[sp,#4] @ load num
|
||||
stmdb sp!,{r0,r2} @ sp points at argument block
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
#if __ARM_ARCH__>=7
|
||||
tst ip,#7
|
||||
bne .Lialu
|
||||
adr r0,bn_mul_mont
|
||||
ldr r2,.LOPENSSL_armcap
|
||||
ldr r0,[r0,r2]
|
||||
#ifdef __APPLE__
|
||||
ldr r0,[r0]
|
||||
#endif
|
||||
tst r0,#1 @ NEON available?
|
||||
ldmia sp, {r0,r2}
|
||||
beq .Lialu
|
||||
@@ -246,14 +231,9 @@ bn_mul_mont:
|
||||
ldmia sp!,{r4-r12,lr} @ restore registers
|
||||
add sp,sp,#2*4 @ skip over {r0,r2}
|
||||
mov r0,#1
|
||||
.Labrt:
|
||||
#if __ARM_ARCH__>=5
|
||||
ret @ bx lr
|
||||
#else
|
||||
tst lr,#1
|
||||
.Labrt: tst lr,#1
|
||||
moveq pc,lr @ be binary compatible with V4, yet
|
||||
bx lr @ interoperable with Thumb ISA:-)
|
||||
#endif
|
||||
.size bn_mul_mont,.-bn_mul_mont
|
||||
___
|
||||
{
|
||||
@@ -272,8 +252,7 @@ my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5));
|
||||
my ($tinptr,$toutptr,$inner,$outer)=map("r$_",(6..9));
|
||||
|
||||
$code.=<<___;
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
.arch armv7-a
|
||||
#if __ARM_ARCH__>=7
|
||||
.fpu neon
|
||||
|
||||
.type bn_mul8x_mont_neon,%function
|
||||
@@ -672,7 +651,7 @@ bn_mul8x_mont_neon:
|
||||
sub sp,ip,#96
|
||||
vldmia sp!,{d8-d15}
|
||||
ldmia sp!,{r4-r11}
|
||||
ret @ bx lr
|
||||
bx lr
|
||||
.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
|
||||
#endif
|
||||
___
|
||||
@@ -680,14 +659,12 @@ ___
|
||||
$code.=<<___;
|
||||
.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
.align 2
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
#if __ARM_ARCH__>=7
|
||||
.comm OPENSSL_armcap_P,4,4
|
||||
.hidden OPENSSL_armcap_P
|
||||
#endif
|
||||
___
|
||||
|
||||
$code =~ s/\`([^\`]*)\`/eval $1/gem;
|
||||
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
|
||||
$code =~ s/\bret\b/bx lr/gm;
|
||||
print $code;
|
||||
close STDOUT;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+24
-12
@@ -61,12 +61,8 @@
|
||||
#
|
||||
# rsa2048 sign/sec OpenSSL 1.0.1 scalar(*) this
|
||||
# 2.3GHz Haswell 621 765/+23% 1113/+79%
|
||||
# 2.3GHz Broadwell(**) 688 1200(***)/+74% 1120/+63%
|
||||
#
|
||||
# (*) if system doesn't support AVX2, for reference purposes;
|
||||
# (**) scaled to 2.3GHz to simplify comparison;
|
||||
# (***) scalar AD*X code is faster than AVX2 and is preferred code
|
||||
# path for Broadwell;
|
||||
|
||||
$flavour = shift;
|
||||
$output = shift;
|
||||
@@ -79,15 +75,31 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
|
||||
die "can't locate x86_64-xlate.pl";
|
||||
|
||||
# In upstream, this is controlled by shelling out to the compiler to check
|
||||
# versions, but BoringSSL is intended to be used with pre-generated perlasm
|
||||
# output, so this isn't useful anyway.
|
||||
#
|
||||
# TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1.
|
||||
$avx = 0;
|
||||
$addx = 0;
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
|
||||
$avx = ($1>=2.19) + ($1>=2.22);
|
||||
$addx = ($1>=2.23);
|
||||
}
|
||||
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
|
||||
`nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
|
||||
$avx = ($1>=2.09) + ($1>=2.10);
|
||||
$addx = ($1>=2.10);
|
||||
}
|
||||
|
||||
if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
|
||||
`ml64 2>&1` =~ /Version ([0-9]+)\./) {
|
||||
$avx = ($1>=10) + ($1>=11);
|
||||
$addx = ($1>=11);
|
||||
}
|
||||
|
||||
if (!$avx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
|
||||
my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
|
||||
$avx = ($ver>=3.0) + ($ver>=3.01);
|
||||
$addx = ($ver>=3.03);
|
||||
}
|
||||
|
||||
open OUT,"| $^X $xlate $flavour $output";
|
||||
*STDOUT = *OUT;
|
||||
|
||||
if ($avx>1) {{{
|
||||
|
||||
@@ -95,15 +95,28 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
|
||||
die "can't locate x86_64-xlate.pl";
|
||||
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
open OUT,"| $^X $xlate $flavour $output";
|
||||
*STDOUT=*OUT;
|
||||
|
||||
# In upstream, this is controlled by shelling out to the compiler to check
|
||||
# versions, but BoringSSL is intended to be used with pre-generated perlasm
|
||||
# output, so this isn't useful anyway.
|
||||
#
|
||||
# TODO(davidben): Enable this after testing. $addx goes up to 1.
|
||||
$addx = 0;
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
|
||||
$addx = ($1>=2.23);
|
||||
}
|
||||
|
||||
if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
|
||||
`nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
|
||||
$addx = ($1>=2.10);
|
||||
}
|
||||
|
||||
if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
|
||||
`ml64 2>&1` =~ /Version ([0-9]+)\./) {
|
||||
$addx = ($1>=12);
|
||||
}
|
||||
|
||||
if (!$addx && `$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
|
||||
my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
|
||||
$addx = ($ver>=3.03);
|
||||
}
|
||||
|
||||
($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp"); # common internal API
|
||||
{
|
||||
|
||||
+139
-61
@@ -1,3 +1,9 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#if 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
|
||||
@@ -64,7 +64,7 @@
|
||||
#define asm __asm__
|
||||
|
||||
/*
|
||||
* "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
|
||||
* "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
|
||||
* "g"(0) let the compiler to decide where does it
|
||||
* want to keep the value of zero;
|
||||
*/
|
||||
@@ -100,9 +100,8 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w) {
|
||||
BN_ULONG c1 = 0;
|
||||
|
||||
if (num <= 0) {
|
||||
if (num <= 0)
|
||||
return (c1);
|
||||
}
|
||||
|
||||
while (num & ~3) {
|
||||
mul_add(rp[0], ap[0], w, c1);
|
||||
@@ -115,26 +114,23 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
}
|
||||
if (num) {
|
||||
mul_add(rp[0], ap[0], w, c1);
|
||||
if (--num == 0) {
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
}
|
||||
mul_add(rp[1], ap[1], w, c1);
|
||||
if (--num == 0) {
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
}
|
||||
mul_add(rp[2], ap[2], w, c1);
|
||||
return c1;
|
||||
}
|
||||
|
||||
return c1;
|
||||
return (c1);
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
|
||||
BN_ULONG c1 = 0;
|
||||
|
||||
if (num <= 0) {
|
||||
return c1;
|
||||
}
|
||||
if (num <= 0)
|
||||
return (c1);
|
||||
|
||||
while (num & ~3) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
@@ -147,22 +143,19 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
|
||||
}
|
||||
if (num) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
if (--num == 0) {
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
}
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
if (--num == 0) {
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
}
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
}
|
||||
return c1;
|
||||
return (c1);
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
if (n <= 0) {
|
||||
if (n <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
while (n & ~3) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
@@ -175,13 +168,11 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
}
|
||||
if (n) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
if (--n == 0) {
|
||||
if (--n == 0)
|
||||
return;
|
||||
}
|
||||
sqr(r[2], r[3], a[1]);
|
||||
if (--n == 0) {
|
||||
if (--n == 0)
|
||||
return;
|
||||
}
|
||||
sqr(r[4], r[5], a[2]);
|
||||
}
|
||||
}
|
||||
@@ -199,9 +190,8 @@ BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
BN_ULONG ret;
|
||||
size_t i = 0;
|
||||
|
||||
if (n <= 0) {
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
asm volatile (
|
||||
" subq %0,%0 \n" /* clear carry */
|
||||
@@ -220,14 +210,14 @@ 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;
|
||||
size_t i = 0;
|
||||
|
||||
if (n <= 0) {
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
asm volatile (
|
||||
" subq %0,%0 \n" /* clear borrow */
|
||||
@@ -245,6 +235,56 @@ 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) */
|
||||
@@ -252,45 +292,80 @@ BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0)
|
||||
*/
|
||||
|
||||
/* Keep in mind that carrying into high part of multiplication result can not
|
||||
* overflow, because it cannot be all-ones. */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
#if 0
|
||||
/* original macros are kept for reference purposes */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b); \
|
||||
t1 = ta * tb; \
|
||||
t2 = BN_UMULT_HIGH(ta, tb); \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
{ \
|
||||
BN_ULONG ta = (a), tb = (b), t0; \
|
||||
t1 = BN_UMULT_HIGH(ta, tb); \
|
||||
t0 = ta * tb; \
|
||||
t2 = t1 + t1; \
|
||||
c2 += (t2 < t1) ? 1 : 0; \
|
||||
t1 = t0 + t0; \
|
||||
t2 += (t1 < t0) ? 1 : 0; \
|
||||
c0 += t1; \
|
||||
t2 += (c0 < t1) ? 1 : 0; \
|
||||
c1 += t2; \
|
||||
c2 += (c1 < t2) ? 1 : 0; \
|
||||
}
|
||||
#else
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0), "+d"(t2) \
|
||||
: "a"(t1), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1), "+r"(c2) \
|
||||
: "d"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0), "+d"(t2) \
|
||||
: "a"(t1), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1), "+r"(c2) \
|
||||
: "d"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %0,%0; adcq %2,%1" : "+d"(t2), "+r"(c2) : "g"(0) : "cc"); \
|
||||
asm("addq %0,%0; adcq %2,%1" : "+a"(t1), "+d"(t2) : "g"(0) : "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0), "+d"(t2) \
|
||||
: "a"(t1), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1), "+r"(c2) \
|
||||
: "d"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -393,6 +468,7 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -431,6 +507,7 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
}
|
||||
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -505,6 +582,7 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
}
|
||||
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
@@ -536,4 +614,4 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
#endif /* !NO_ASM && X86_64 && __GNUC__ */
|
||||
#endif /* defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS) */
|
||||
|
||||
@@ -53,12 +53,20 @@ die "can't locate x86_64-xlate.pl";
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
*STDOUT=*OUT;
|
||||
|
||||
# In upstream, this is controlled by shelling out to the compiler to check
|
||||
# versions, but BoringSSL is intended to be used with pre-generated perlasm
|
||||
# output, so this isn't useful anyway.
|
||||
#
|
||||
# TODO(davidben): Enable this option after testing. $addx goes up to 1.
|
||||
$addx = 0;
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
|
||||
$addx = ($1>=2.23);
|
||||
}
|
||||
|
||||
if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
|
||||
`nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
|
||||
$addx = ($1>=2.10);
|
||||
}
|
||||
|
||||
if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
|
||||
`ml64 2>&1` =~ /Version ([0-9]+)\./) {
|
||||
$addx = ($1>=12);
|
||||
}
|
||||
|
||||
# int bn_mul_mont(
|
||||
$rp="%rdi"; # BN_ULONG *rp,
|
||||
|
||||
@@ -38,12 +38,20 @@ die "can't locate x86_64-xlate.pl";
|
||||
open OUT,"| \"$^X\" $xlate $flavour $output";
|
||||
*STDOUT=*OUT;
|
||||
|
||||
# In upstream, this is controlled by shelling out to the compiler to check
|
||||
# versions, but BoringSSL is intended to be used with pre-generated perlasm
|
||||
# output, so this isn't useful anyway.
|
||||
#
|
||||
# TODO(davidben): Enable this after testing. $addx goes up to 1.
|
||||
$addx = 0;
|
||||
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
|
||||
=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
|
||||
$addx = ($1>=2.23);
|
||||
}
|
||||
|
||||
if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
|
||||
`nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
|
||||
$addx = ($1>=2.10);
|
||||
}
|
||||
|
||||
if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
|
||||
`ml64 2>&1` =~ /Version ([0-9]+)\./) {
|
||||
$addx = ($1>=12);
|
||||
}
|
||||
|
||||
# int bn_mul_mont_gather5(
|
||||
$rp="%rdi"; # BN_ULONG *rp,
|
||||
@@ -1770,15 +1778,6 @@ sqr8x_reduction:
|
||||
.align 32
|
||||
.L8x_tail_done:
|
||||
add (%rdx),%r8 # can this overflow?
|
||||
adc \$0,%r9
|
||||
adc \$0,%r10
|
||||
adc \$0,%r11
|
||||
adc \$0,%r12
|
||||
adc \$0,%r13
|
||||
adc \$0,%r14
|
||||
adc \$0,%r15 # can't overflow, because we
|
||||
# started with "overhung" part
|
||||
# of multiplication
|
||||
xor %rax,%rax
|
||||
|
||||
neg $carry
|
||||
@@ -3125,15 +3124,6 @@ sqrx8x_reduction:
|
||||
.align 32
|
||||
.Lsqrx8x_tail_done:
|
||||
add 24+8(%rsp),%r8 # can this overflow?
|
||||
adc \$0,%r9
|
||||
adc \$0,%r10
|
||||
adc \$0,%r11
|
||||
adc \$0,%r12
|
||||
adc \$0,%r13
|
||||
adc \$0,%r14
|
||||
adc \$0,%r15 # can't overflow, because we
|
||||
# started with "overhung" part
|
||||
# of multiplication
|
||||
mov $carry,%rax # xor %rax,%rax
|
||||
|
||||
sub 16+8(%rsp),$carry # mov 16(%rsp),%cf
|
||||
@@ -3177,11 +3167,13 @@ my ($rptr,$nptr)=("%rdx","%rbp");
|
||||
my @ri=map("%r$_",(10..13));
|
||||
my @ni=map("%r$_",(14..15));
|
||||
$code.=<<___;
|
||||
xor %ebx,%ebx
|
||||
xor %rbx,%rbx
|
||||
sub %r15,%rsi # compare top-most words
|
||||
adc %rbx,%rbx
|
||||
mov %rcx,%r10 # -$num
|
||||
.byte 0x67
|
||||
or %rbx,%rax
|
||||
.byte 0x67
|
||||
mov %rcx,%r9 # -$num
|
||||
xor \$1,%rax
|
||||
sar \$3+2,%rcx # cf=0
|
||||
|
||||
+19
-24
@@ -57,8 +57,6 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -69,7 +67,7 @@ BIGNUM *BN_new(void) {
|
||||
BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM));
|
||||
|
||||
if (bn == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_PUT_ERROR(BN, BN_new, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -88,7 +86,7 @@ void BN_free(BIGNUM *bn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((bn->flags & BN_FLG_STATIC_DATA) == 0) {
|
||||
if (bn->d != NULL && (bn->flags & BN_FLG_STATIC_DATA) == 0) {
|
||||
OPENSSL_free(bn->d);
|
||||
}
|
||||
|
||||
@@ -166,10 +164,11 @@ void BN_clear(BIGNUM *bn) {
|
||||
}
|
||||
|
||||
const BIGNUM *BN_value_one(void) {
|
||||
static const BN_ULONG kOneLimbs[1] = { 1 };
|
||||
static const BIGNUM kOne = STATIC_BIGNUM(kOneLimbs);
|
||||
static const BN_ULONG data_one = 1;
|
||||
static const BIGNUM const_one = {(BN_ULONG *)&data_one, 1, 1, 0,
|
||||
BN_FLG_STATIC_DATA};
|
||||
|
||||
return &kOne;
|
||||
return &const_one;
|
||||
}
|
||||
|
||||
void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
|
||||
@@ -199,15 +198,13 @@ unsigned BN_num_bits_word(BN_ULONG l) {
|
||||
if (l & 0xffff000000000000L) {
|
||||
if (l & 0xff00000000000000L) {
|
||||
return (bits[(int)(l >> 56)] + 56);
|
||||
} else {
|
||||
} else
|
||||
return (bits[(int)(l >> 48)] + 48);
|
||||
}
|
||||
} else {
|
||||
if (l & 0x0000ff0000000000L) {
|
||||
return (bits[(int)(l >> 40)] + 40);
|
||||
} else {
|
||||
} else
|
||||
return (bits[(int)(l >> 32)] + 32);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
@@ -278,43 +275,41 @@ void BN_set_negative(BIGNUM *bn, int sign) {
|
||||
}
|
||||
}
|
||||
|
||||
BIGNUM *bn_wexpand(BIGNUM *bn, size_t words) {
|
||||
BIGNUM *bn_wexpand(BIGNUM *bn, unsigned words) {
|
||||
BN_ULONG *a;
|
||||
|
||||
if (words <= (size_t)bn->dmax) {
|
||||
if (words <= (unsigned) bn->dmax) {
|
||||
return bn;
|
||||
}
|
||||
|
||||
if (words > (INT_MAX / (4 * BN_BITS2))) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
OPENSSL_PUT_ERROR(BN, bn_wexpand, BN_R_BIGNUM_TOO_LONG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bn->flags & BN_FLG_STATIC_DATA) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
||||
OPENSSL_PUT_ERROR(BN, bn_wexpand, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
||||
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);
|
||||
OPENSSL_PUT_ERROR(BN, bn_wexpand, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
|
||||
|
||||
OPENSSL_free(bn->d);
|
||||
if (bn->d) {
|
||||
OPENSSL_free(bn->d);
|
||||
}
|
||||
bn->d = a;
|
||||
bn->dmax = (int)words;
|
||||
bn->dmax = words;
|
||||
|
||||
return bn;
|
||||
}
|
||||
|
||||
BIGNUM *bn_expand(BIGNUM *bn, size_t bits) {
|
||||
if (bits + BN_BITS2 - 1 < bits) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return NULL;
|
||||
}
|
||||
BIGNUM *bn_expand(BIGNUM *bn, unsigned bits) {
|
||||
return bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CBS_data(&child)[0] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* INTEGERs must be minimal. */
|
||||
if (CBS_data(&child)[0] == 0x00 &&
|
||||
CBS_len(&child) > 1 &&
|
||||
!(CBS_data(&child)[1] & 0x80)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function intentionally does not reject negative numbers or non-minimal
|
||||
* encodings. Estonian IDs issued between September 2014 to September 2015 are
|
||||
* broken. See https://crbug.com/532048 and https://crbug.com/534766.
|
||||
*
|
||||
* TODO(davidben): Remove this code and callers in March 2016. */
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
/* Negative numbers are unsupported. */
|
||||
if (BN_is_negative(bn)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* 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. */
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
const ERR_STRING_DATA BN_error_string_data[] = {
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_get, 0), "BN_CTX_get"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_new, 0), "BN_CTX_new"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_CTX_start, 0), "BN_CTX_start"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_bn2dec, 0), "BN_bn2dec"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_bn2hex, 0), "BN_bn2hex"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_div, 0), "BN_div"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_div_recp, 0), "BN_div_recp"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_exp, 0), "BN_exp"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_dsa_nonce, 0), "BN_generate_dsa_nonce"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_generate_prime_ex, 0), "BN_generate_prime_ex"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp2_mont, 0), "BN_mod_exp2_mont"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont, 0), "BN_mod_exp_mont"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_consttime, 0), "BN_mod_exp_mont_consttime"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_exp_mont_word, 0), "BN_mod_exp_mont_word"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_inverse, 0), "BN_mod_inverse"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_inverse_no_branch, 0), "BN_mod_inverse_no_branch"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_lshift_quick, 0), "BN_mod_lshift_quick"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_mod_sqrt, 0), "BN_mod_sqrt"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_new, 0), "BN_new"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_rand, 0), "BN_rand"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_rand_range, 0), "BN_rand_range"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_sqrt, 0), "BN_sqrt"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_BN_usub, 0), "BN_usub"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_bn_wexpand, 0), "bn_wexpand"},
|
||||
{ERR_PACK(ERR_LIB_BN, BN_F_mod_exp_recp, 0), "mod_exp_recp"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_ARG2_LT_ARG3), "ARG2_LT_ARG3"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_BAD_RECIPROCAL), "BAD_RECIPROCAL"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_BIGNUM_TOO_LONG), "BIGNUM_TOO_LONG"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_BITS_TOO_SMALL), "BITS_TOO_SMALL"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_CALLED_WITH_EVEN_MODULUS), "CALLED_WITH_EVEN_MODULUS"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_DIV_BY_ZERO), "DIV_BY_ZERO"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA), "EXPAND_ON_STATIC_BIGNUM_DATA"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_INPUT_NOT_REDUCED), "INPUT_NOT_REDUCED"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_INVALID_RANGE), "INVALID_RANGE"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NEGATIVE_NUMBER), "NEGATIVE_NUMBER"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_A_SQUARE), "NOT_A_SQUARE"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NOT_INITIALIZED), "NOT_INITIALIZED"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_NO_INVERSE), "NO_INVERSE"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_PRIVATE_KEY_TOO_LARGE), "PRIVATE_KEY_TOO_LARGE"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_P_IS_NOT_PRIME), "P_IS_NOT_PRIME"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_ITERATIONS), "TOO_MANY_ITERATIONS"},
|
||||
{ERR_PACK(ERR_LIB_BN, 0, BN_R_TOO_MANY_TEMPORARY_VARIABLES), "TOO_MANY_TEMPORARY_VARIABLES"},
|
||||
{0, NULL},
|
||||
};
|
||||
+1411
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user