Compare commits
282 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f04ac1c4d | |||
| c880e42ba1 | |||
| c02d05fe19 | |||
| 6d49157929 | |||
| e976e4349d | |||
| f48fcaf901 | |||
| de94238217 | |||
| d3a49953d8 | |||
| f4ef9b517e | |||
| 9cd7fbdac6 | |||
| e30a09e604 | |||
| 440f103771 | |||
| 239a0abfd5 | |||
| 32fdc512ca | |||
| 68772b31b0 | |||
| 2dc469e066 | |||
| df98a7ad3a | |||
| fda22a7573 | |||
| 3cadf63c68 | |||
| 985da09340 | |||
| 2f6410ba4e | |||
| 666973b8e9 | |||
| 815b12ece6 | |||
| bd42603943 | |||
| 375124b162 | |||
| fb974e6cb3 | |||
| 894a47df24 | |||
| 11676a7399 | |||
| 5ba06897be | |||
| 46a4d6d705 | |||
| 3ab3e3db6e | |||
| 5acc423517 | |||
| 042e8f721a | |||
| 642b0b825e | |||
| a051bdd6cd | |||
| 767e1210e0 | |||
| b121a26736 | |||
| 4862b3b93c | |||
| fce7604350 | |||
| aadf1ee77f | |||
| 8c5ea1338a | |||
| 2c71ce135c | |||
| 6b34d54945 | |||
| 089cba090c | |||
| f98be21fad | |||
| a37fc70175 | |||
| fcde5aa74d | |||
| 926f2194df | |||
| 11aac10987 | |||
| 168297e870 | |||
| d057454f90 | |||
| e66148a18f | |||
| 6014ea6248 | |||
| dd31c4eba2 | |||
| 47ebec1210 | |||
| 43946d44ae | |||
| 4e3d17a7e7 | |||
| 4aafe6a3af | |||
| bf3335c621 | |||
| 72f7e21087 | |||
| 5fa8f5bc9a | |||
| 2cdf398773 | |||
| 415564fe2c | |||
| 4f6acaf0da | |||
| c3774c1187 | |||
| 0a2c9938a5 | |||
| f6094e05ef | |||
| c612e61e1d | |||
| 719594e512 | |||
| b6155e60f3 | |||
| 4e98e5c903 | |||
| 692878a5f4 | |||
| 8ac35f0274 | |||
| 9bf1b1b440 | |||
| acb2451807 | |||
| 647cd02e59 | |||
| b04c905da9 | |||
| 8f2d4e344c | |||
| 87c7640773 | |||
| 24e428899b | |||
| f547007332 | |||
| 9333d6df11 | |||
| f5f4be8fac | |||
| 54a8d7c14f | |||
| 91b2501f02 | |||
| cdd0b7e775 | |||
| 4b9205b583 | |||
| b83003ebc6 | |||
| a565d29ce6 | |||
| a1e9cabd8b | |||
| ef7dba6ac7 | |||
| ce9d85eedd | |||
| eac0ce09d8 | |||
| 241ae837f0 | |||
| f6494f4928 | |||
| 7027d25c6b | |||
| e5aa791a1c | |||
| 5aae776ede | |||
| 75a64c08fc | |||
| 7cae9f5b6c | |||
| 34749f47da | |||
| 232127d245 | |||
| 95219feafd | |||
| d3a4e280db | |||
| a646258c14 | |||
| d92f1d39a8 | |||
| 8d3c43e4b1 | |||
| 061332f216 | |||
| 0687bdfc12 | |||
| 6c22f542f4 | |||
| fc6e5a7372 | |||
| d2f0ce80a2 | |||
| 3a39b06011 | |||
| 57707c70dc | |||
| 62882187c9 | |||
| b8ba65a73a | |||
| 0b553eb531 | |||
| b9e4fa5e02 | |||
| 23b0a65df1 | |||
| 928f32a492 | |||
| baa1216ac0 | |||
| f8d807176a | |||
| b35d68483c | |||
| 79978df4ec | |||
| 57997da8ee | |||
| 0623bceb25 | |||
| 4119d42e7c | |||
| 1db2156ce8 | |||
| 96ba15fc69 | |||
| ef1b009344 | |||
| dd1f6f4fba | |||
| e021a245bf | |||
| 625475f3e3 | |||
| 7b8b9c17db | |||
| 3202750a98 | |||
| 6544426d82 | |||
| fe5f7c7b56 | |||
| 0d56f888c3 | |||
| 974c7ba4ef | |||
| 4cc36adf5a | |||
| 4298d77379 | |||
| c18ef750ee | |||
| 3a2a48086b | |||
| cba2b62a85 | |||
| ab14563022 | |||
| a029ebc4c6 | |||
| 64d9250e2f | |||
| 8c2b3bf965 | |||
| fc8251258d | |||
| 5fb18c6b42 | |||
| 2a0b391ac9 | |||
| d16bf3421c | |||
| af21bcf91f | |||
| ae0eaaa397 | |||
| 3ac4b3a391 | |||
| e6c540290d | |||
| 77a173efed | |||
| c75c0ae088 | |||
| 48cce66aac | |||
| c1cc858af2 | |||
| 4cc671cbf4 | |||
| e13263d5e4 | |||
| 841934f079 | |||
| 70ab223490 | |||
| b965c63acb | |||
| 3f5b43df07 | |||
| 3ef608594d | |||
| afe57cb14d | |||
| 77c3c0b025 | |||
| 9f897b2580 | |||
| 1741a9d143 | |||
| df571631cc | |||
| 13414b3a04 | |||
| 37489902ba | |||
| 2089fdd10e | |||
| 86e412dc18 | |||
| 23a681b9f9 | |||
| e3203923b5 | |||
| 8ffab72683 | |||
| fef6fb592b | |||
| 60a08ac211 | |||
| 4ec0cce743 | |||
| 2936170d68 | |||
| a01deee96b | |||
| 77385bb43d | |||
| 6969971fef | |||
| 1b36716ce2 | |||
| 017231a544 | |||
| 793c21e266 | |||
| 0aff3ffb88 | |||
| 5a19d7dfa8 | |||
| 78fefbf3bb | |||
| fea1137e55 | |||
| 871fff076b | |||
| d9f0671bbe | |||
| cd480380fa | |||
| 7fc010014c | |||
| ece5ba2797 | |||
| a41280d8cb | |||
| 8fd5c23218 | |||
| ef5dfd2980 | |||
| 8411b248c3 | |||
| 502a843dee | |||
| c3ae38b4f8 | |||
| 7100ee9832 | |||
| f28dd64d43 | |||
| 423488557c | |||
| 45dab251f3 | |||
| 8a58933db0 | |||
| 0abd6f2eb6 | |||
| 1246670caa | |||
| 5ddffbb8bc | |||
| 53e5c2c225 | |||
| 756ad17337 | |||
| 1634a33495 | |||
| b36a395a9a | |||
| 0bd71eb85d | |||
| e9cddb8879 | |||
| 3e052de5a0 | |||
| 03f000577f | |||
| ef5e515819 | |||
| c100ef4379 | |||
| 2205093e7e | |||
| 6ae67dfee8 | |||
| a0ef7b0a56 | |||
| 533a273871 | |||
| a3d9de05fb | |||
| 88478562a4 | |||
| dca63cfa75 | |||
| afd565ff9c | |||
| 902870e3b5 | |||
| 34aa55c05e | |||
| 6d9e5a7448 | |||
| 28243c08db | |||
| e701f16bd6 | |||
| cb852981cd | |||
| c4f25ce0c6 | |||
| c5eb4676b6 | |||
| 758d12732a | |||
| fde89b43c3 | |||
| 60a45aa7cc | |||
| 81edc9beb6 | |||
| e8fe07fcc4 | |||
| 93a5b44296 | |||
| bf762186c6 | |||
| 596ab10b0f | |||
| 7af36e1e38 | |||
| ff2df337a0 | |||
| 9f2e2770e1 | |||
| d6e9eec3f8 | |||
| dcb6ef0f0b | |||
| d28f59c27b | |||
| fba735cfd8 | |||
| f3376ace43 | |||
| 301efc8cea | |||
| e2136d9c28 | |||
| 9b26297608 | |||
| 5058d79948 | |||
| b1b6229fc8 | |||
| 9e65d487b8 | |||
| 3ac32b1eda | |||
| 4fb0dc4b03 | |||
| c324f1783e | |||
| 9361243065 | |||
| b00061cea7 | |||
| 3a59611726 | |||
| b324159be9 | |||
| f584a5aaa2 | |||
| 2077cf9152 | |||
| af07365b49 | |||
| 780cd92b98 | |||
| f9c77dedfa | |||
| a33915d690 | |||
| c5c85defb2 | |||
| d9e27021e1 | |||
| e7806fd477 | |||
| 20c373118c | |||
| 7308aaa9b4 | |||
| f872951880 | |||
| 8bde5d2e51 | |||
| ce7ae6fa27 | |||
| 9f1f04f313 |
+16
-8
@@ -2,14 +2,18 @@
|
||||
|
||||
## Build Prerequisites
|
||||
|
||||
* [CMake](http://www.cmake.org/download/) 2.8.8 or later is required.
|
||||
* [CMake](https://cmake.org/download/) 2.8.8 or later is required.
|
||||
|
||||
* Perl 5.6.1 or later is required. On Windows,
|
||||
[Strawberry Perl](http://strawberryperl.com/) and MSYS Perl have both been
|
||||
reported to work. If not found by CMake, it may be configured explicitly by
|
||||
setting `PERL_EXECUTABLE`.
|
||||
[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://martine.github.io/ninja/)
|
||||
* 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.
|
||||
|
||||
@@ -21,8 +25,8 @@
|
||||
`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 and
|
||||
Clang should work on non-Windows platforms, and maybe on Windows too.
|
||||
with Platform SDK 8.1 or later are supported. Recent versions of GCC (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`.
|
||||
@@ -58,7 +62,8 @@ 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.
|
||||
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
|
||||
@@ -75,6 +80,9 @@ 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
|
||||
|
||||
+15
-3
@@ -1,6 +1,16 @@
|
||||
cmake_minimum_required (VERSION 2.8.10)
|
||||
|
||||
project (BoringSSL)
|
||||
# Defer enabling C and CXX languages.
|
||||
project (BoringSSL NONE)
|
||||
|
||||
if(WIN32)
|
||||
# On Windows, prefer cl over gcc if both are available. By default most of
|
||||
# the CMake generators prefer gcc, even on Windows.
|
||||
set(CMAKE_GENERATOR_CC cl)
|
||||
endif()
|
||||
|
||||
enable_language(C)
|
||||
enable_language(CXX)
|
||||
|
||||
if(ANDROID)
|
||||
# Android-NDK CMake files reconfigure the path and so Go and Perl won't be
|
||||
@@ -17,8 +27,9 @@ if (NOT GO_EXECUTABLE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -std=c++0x -fvisibility=hidden")
|
||||
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}")
|
||||
elseif(MSVC)
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
"C4100" # 'exarg' : unreferenced formal parameter
|
||||
@@ -51,6 +62,7 @@ elseif(MSVC)
|
||||
# copy constructor is inaccessible or deleted
|
||||
"C4626" # assignment operator could not be generated because a base class
|
||||
# assignment operator is inaccessible or deleted
|
||||
"C4701" # potentially uninitialized local variable 'p' used
|
||||
"C4706" # assignment within conditional expression
|
||||
"C4710" # 'function': function not inlined
|
||||
"C4711" # function 'function' selected for inline expansion
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
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).
|
||||
+23
@@ -130,6 +130,23 @@ 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
|
||||
|
||||
@@ -162,3 +179,9 @@ locks. Without initializing these, the library is not thread-safe. Configuring
|
||||
these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the
|
||||
corresponding Windows APIs internally and is always thread-safe where the API
|
||||
guarantees it.
|
||||
|
||||
### ASN.1
|
||||
|
||||
BoringSSL is in the process of deprecating OpenSSL's `d2i` and `i2d` in favor of
|
||||
new functions using the much less error-prone `CBS` and `CBB` types.
|
||||
BoringSSL-only code should use those functions where available.
|
||||
|
||||
@@ -28,3 +28,4 @@ There are other files in this directory which might be helpful:
|
||||
* [STYLE.md](/STYLE.md): rules and guidelines for coding style.
|
||||
* include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
|
||||
* [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
|
||||
* [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.
|
||||
|
||||
@@ -105,6 +105,7 @@ add_subdirectory(rc4)
|
||||
add_subdirectory(conf)
|
||||
add_subdirectory(chacha)
|
||||
add_subdirectory(poly1305)
|
||||
add_subdirectory(curve25519)
|
||||
|
||||
# Level 1, depends only on 0.*
|
||||
add_subdirectory(digest)
|
||||
@@ -174,6 +175,7 @@ add_library(
|
||||
$<TARGET_OBJECTS:conf>
|
||||
$<TARGET_OBJECTS:chacha>
|
||||
$<TARGET_OBJECTS:poly1305>
|
||||
$<TARGET_OBJECTS:curve25519>
|
||||
$<TARGET_OBJECTS:buf>
|
||||
$<TARGET_OBJECTS:bn>
|
||||
$<TARGET_OBJECTS:bio>
|
||||
|
||||
@@ -191,7 +191,6 @@ 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:
|
||||
@@ -441,7 +440,6 @@ _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:
|
||||
@@ -748,7 +746,6 @@ _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:
|
||||
@@ -765,7 +762,6 @@ 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:
|
||||
@@ -971,7 +967,6 @@ AES_Td:
|
||||
@ void asm_AES_decrypt(const unsigned char *in, unsigned char *out,
|
||||
@ const AES_KEY *key) {
|
||||
.global asm_AES_decrypt
|
||||
.hidden asm_AES_decrypt
|
||||
.type asm_AES_decrypt,%function
|
||||
.align 5
|
||||
asm_AES_decrypt:
|
||||
|
||||
@@ -1006,7 +1006,6 @@ 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:
|
||||
@@ -1025,7 +1024,6 @@ 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:
|
||||
@@ -1056,7 +1054,6 @@ 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:
|
||||
@@ -1077,7 +1074,6 @@ 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:
|
||||
@@ -1117,7 +1113,6 @@ $code.=<<___;
|
||||
.extern AES_decrypt
|
||||
|
||||
.global bsaes_cbc_encrypt
|
||||
.hidden bsaes_cbc_encrypt
|
||||
.type bsaes_cbc_encrypt,%function
|
||||
.align 5
|
||||
bsaes_cbc_encrypt:
|
||||
@@ -1393,7 +1388,6 @@ 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:
|
||||
@@ -1635,7 +1629,6 @@ my @T=@XMM[6..7];
|
||||
|
||||
$code.=<<___;
|
||||
.globl bsaes_xts_encrypt
|
||||
.hidden bsaes_xts_encrypt
|
||||
.type bsaes_xts_encrypt,%function
|
||||
.align 4
|
||||
bsaes_xts_encrypt:
|
||||
@@ -2050,7 +2043,6 @@ $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:
|
||||
|
||||
@@ -43,3 +43,14 @@ add_library(
|
||||
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)
|
||||
|
||||
+176
-168
@@ -33,7 +33,7 @@
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
@@ -61,195 +61,203 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
|
||||
{ return M_ASN1_BIT_STRING_set(x, d, len); }
|
||||
{
|
||||
return M_ASN1_BIT_STRING_set(x, d, len);
|
||||
}
|
||||
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
|
||||
{
|
||||
int ret,j,bits,len;
|
||||
unsigned char *p,*d;
|
||||
{
|
||||
int ret, j, bits, len;
|
||||
unsigned char *p, *d;
|
||||
|
||||
if (a == NULL) return(0);
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
len=a->length;
|
||||
len = a->length;
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
|
||||
{
|
||||
bits=(int)a->flags&0x07;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ; len > 0; len--)
|
||||
{
|
||||
if (a->data[len-1]) break;
|
||||
}
|
||||
j=a->data[len-1];
|
||||
if (j & 0x01) bits=0;
|
||||
else if (j & 0x02) bits=1;
|
||||
else if (j & 0x04) bits=2;
|
||||
else if (j & 0x08) bits=3;
|
||||
else if (j & 0x10) bits=4;
|
||||
else if (j & 0x20) bits=5;
|
||||
else if (j & 0x40) bits=6;
|
||||
else if (j & 0x80) bits=7;
|
||||
else bits=0; /* should not happen */
|
||||
}
|
||||
}
|
||||
else
|
||||
bits=0;
|
||||
if (len > 0) {
|
||||
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
|
||||
bits = (int)a->flags & 0x07;
|
||||
} else {
|
||||
for (; len > 0; len--) {
|
||||
if (a->data[len - 1])
|
||||
break;
|
||||
}
|
||||
j = a->data[len - 1];
|
||||
if (j & 0x01)
|
||||
bits = 0;
|
||||
else if (j & 0x02)
|
||||
bits = 1;
|
||||
else if (j & 0x04)
|
||||
bits = 2;
|
||||
else if (j & 0x08)
|
||||
bits = 3;
|
||||
else if (j & 0x10)
|
||||
bits = 4;
|
||||
else if (j & 0x20)
|
||||
bits = 5;
|
||||
else if (j & 0x40)
|
||||
bits = 6;
|
||||
else if (j & 0x80)
|
||||
bits = 7;
|
||||
else
|
||||
bits = 0; /* should not happen */
|
||||
}
|
||||
} else
|
||||
bits = 0;
|
||||
|
||||
ret=1+len;
|
||||
if (pp == NULL) return(ret);
|
||||
ret = 1 + len;
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
|
||||
p= *pp;
|
||||
p = *pp;
|
||||
|
||||
*(p++)=(unsigned char)bits;
|
||||
d=a->data;
|
||||
memcpy(p,d,len);
|
||||
p+=len;
|
||||
if (len > 0) p[-1]&=(0xff<<bits);
|
||||
*pp=p;
|
||||
return(ret);
|
||||
}
|
||||
*(p++) = (unsigned char)bits;
|
||||
d = a->data;
|
||||
memcpy(p, d, len);
|
||||
p += len;
|
||||
if (len > 0)
|
||||
p[-1] &= (0xff << bits);
|
||||
*pp = p;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
|
||||
const unsigned char **pp, long len)
|
||||
{
|
||||
ASN1_BIT_STRING *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
int padding;
|
||||
const unsigned char **pp, long len)
|
||||
{
|
||||
ASN1_BIT_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
int padding;
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
if (len < 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL);
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p= *pp;
|
||||
padding = *(p++);
|
||||
if (padding > 7)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
goto err;
|
||||
}
|
||||
p = *pp;
|
||||
padding = *(p++);
|
||||
if (padding > 7) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We do this to preserve the settings. If we modify
|
||||
* the settings, via the _set_bit function, we will recalculate
|
||||
* on output */
|
||||
ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
|
||||
ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|padding); /* set */
|
||||
/*
|
||||
* We do this to preserve the settings. If we modify the settings, via
|
||||
* the _set_bit function, we will recalculate on output
|
||||
*/
|
||||
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
|
||||
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */
|
||||
|
||||
if (len-- > 1) /* using one because of the bits left byte */
|
||||
{
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len);
|
||||
if (s == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
s[len-1]&=(0xff<<padding);
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
s=NULL;
|
||||
if (len-- > 1) { /* using one because of the bits left byte */
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len);
|
||||
if (s == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
s[len - 1] &= (0xff << padding);
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
|
||||
ret->length=(int)len;
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->data=s;
|
||||
ret->type=V_ASN1_BIT_STRING;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_BIT_STRING_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
w=n/8;
|
||||
v=1<<(7-(n&0x07));
|
||||
iv= ~v;
|
||||
if (!value) v=0;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the given bit string contains only bits specified by
|
||||
* 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;
|
||||
|
||||
w = n / 8;
|
||||
v = 1 << (7 - (n & 0x07));
|
||||
iv = ~v;
|
||||
if (!value)
|
||||
v = 0;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
+42
-44
@@ -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,54 +59,52 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
|
||||
{
|
||||
int r;
|
||||
unsigned char *p;
|
||||
{
|
||||
int r;
|
||||
unsigned char *p;
|
||||
|
||||
r=ASN1_object_size(0,1,V_ASN1_BOOLEAN);
|
||||
if (pp == NULL) return(r);
|
||||
p= *pp;
|
||||
r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
|
||||
if (pp == NULL)
|
||||
return (r);
|
||||
p = *pp;
|
||||
|
||||
ASN1_put_object(&p,0,1,V_ASN1_BOOLEAN,V_ASN1_UNIVERSAL);
|
||||
*(p++)= (unsigned char)a;
|
||||
*pp=p;
|
||||
return(r);
|
||||
}
|
||||
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
|
||||
*(p++) = (unsigned char)a;
|
||||
*pp = p;
|
||||
return (r);
|
||||
}
|
||||
|
||||
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
|
||||
{
|
||||
int ret= -1;
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i=0;
|
||||
{
|
||||
int ret = -1;
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_BOOLEAN)
|
||||
{
|
||||
i=ASN1_R_EXPECTING_A_BOOLEAN;
|
||||
goto err;
|
||||
}
|
||||
if (tag != V_ASN1_BOOLEAN) {
|
||||
i = ASN1_R_EXPECTING_A_BOOLEAN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (len != 1)
|
||||
{
|
||||
i=ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
ret= (int)*(p++);
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return(ret);
|
||||
}
|
||||
if (len != 1) {
|
||||
i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
ret = (int)*(p++);
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+212
-221
@@ -62,256 +62,247 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
|
||||
/* type is a 'bitmap' of acceptable string types.
|
||||
/*
|
||||
* type is a 'bitmap' of acceptable string types.
|
||||
*/
|
||||
ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||
long length, int type)
|
||||
{
|
||||
ASN1_STRING *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i=0;
|
||||
long length, int type)
|
||||
{
|
||||
ASN1_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80) goto err;
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80)
|
||||
goto err;
|
||||
|
||||
if (tag >= 32)
|
||||
{
|
||||
i=ASN1_R_TAG_VALUE_TOO_HIGH;
|
||||
goto err;
|
||||
}
|
||||
if (!(ASN1_tag2bit(tag) & type))
|
||||
{
|
||||
i=ASN1_R_WRONG_TYPE;
|
||||
goto err;
|
||||
}
|
||||
if (tag >= 32) {
|
||||
i = ASN1_R_TAG_VALUE_TOO_HIGH;
|
||||
goto err;
|
||||
}
|
||||
if (!(ASN1_tag2bit(tag) & type)) {
|
||||
i = ASN1_R_WRONG_TYPE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If a bit-string, exit early */
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return(d2i_ASN1_BIT_STRING(a,pp,length));
|
||||
/* If a bit-string, exit early */
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return (d2i_ASN1_BIT_STRING(a, pp, length));
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = ASN1_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len+1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
s[len]='\0';
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
s=NULL;
|
||||
if (len != 0) {
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
s[len] = '\0';
|
||||
p += len;
|
||||
} else
|
||||
s = NULL;
|
||||
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->length=(int)len;
|
||||
ret->data=s;
|
||||
ret->type=tag;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->length = (int)len;
|
||||
ret->data = s;
|
||||
ret->type = tag;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
|
||||
{
|
||||
int ret,r,constructed;
|
||||
unsigned char *p;
|
||||
{
|
||||
int ret, r, constructed;
|
||||
unsigned char *p;
|
||||
|
||||
if (a == NULL) return(0);
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return(i2d_ASN1_BIT_STRING(a,pp));
|
||||
|
||||
ret=a->length;
|
||||
r=ASN1_object_size(0,ret,tag);
|
||||
if (pp == NULL) return(r);
|
||||
p= *pp;
|
||||
if (tag == V_ASN1_BIT_STRING)
|
||||
return (i2d_ASN1_BIT_STRING(a, 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||
long length, int Ptag, int Pclass)
|
||||
{
|
||||
ASN1_STRING *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i=0;
|
||||
long length, int Ptag, int Pclass)
|
||||
{
|
||||
ASN1_STRING *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i = 0;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = ASN1_STRING_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != Ptag)
|
||||
{
|
||||
i=ASN1_R_WRONG_TAG;
|
||||
goto err;
|
||||
}
|
||||
if (tag != Ptag) {
|
||||
i = ASN1_R_WRONG_TAG;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (inf & V_ASN1_CONSTRUCTED)
|
||||
{
|
||||
ASN1_const_CTX c;
|
||||
if (inf & V_ASN1_CONSTRUCTED) {
|
||||
ASN1_const_CTX c;
|
||||
|
||||
c.pp=pp;
|
||||
c.p=p;
|
||||
c.inf=inf;
|
||||
c.slen=len;
|
||||
c.tag=Ptag;
|
||||
c.xclass=Pclass;
|
||||
c.max=(length == 0)?0:(p+length);
|
||||
if (!asn1_collate_primitive(ret,&c))
|
||||
goto err;
|
||||
else
|
||||
{
|
||||
p=c.p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len != 0)
|
||||
{
|
||||
if ((ret->length < len) || (ret->data == NULL))
|
||||
{
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
s=ret->data;
|
||||
memcpy(s,p,(int)len);
|
||||
s[len] = '\0';
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
{
|
||||
s=NULL;
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
}
|
||||
c.pp = pp;
|
||||
c.p = p;
|
||||
c.inf = inf;
|
||||
c.slen = len;
|
||||
c.tag = Ptag;
|
||||
c.xclass = Pclass;
|
||||
c.max = (length == 0) ? 0 : (p + length);
|
||||
if (!asn1_collate_primitive(ret, &c))
|
||||
goto err;
|
||||
else {
|
||||
p = c.p;
|
||||
}
|
||||
} else {
|
||||
if (len != 0) {
|
||||
if ((ret->length < len) || (ret->data == NULL)) {
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
s = ret->data;
|
||||
memcpy(s, p, (int)len);
|
||||
s[len] = '\0';
|
||||
p += len;
|
||||
} else {
|
||||
s = NULL;
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
}
|
||||
|
||||
ret->length=(int)len;
|
||||
ret->data=s;
|
||||
ret->type=Ptag;
|
||||
}
|
||||
ret->length = (int)len;
|
||||
ret->data = s;
|
||||
ret->type = Ptag;
|
||||
}
|
||||
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return(NULL);
|
||||
}
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_STRING_free(ret);
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
|
||||
* them into the one structure that is then returned */
|
||||
/* There have been a few bug fixes for this function from
|
||||
* Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
|
||||
/*
|
||||
* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse them
|
||||
* into the one structure that is then returned
|
||||
*/
|
||||
/*
|
||||
* There have been a few bug fixes for this function from Paul Keogh
|
||||
* <paul.keogh@sse.ie>, many thanks to him
|
||||
*/
|
||||
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
|
||||
{
|
||||
ASN1_STRING *os=NULL;
|
||||
BUF_MEM b;
|
||||
int num;
|
||||
{
|
||||
ASN1_STRING *os = NULL;
|
||||
BUF_MEM b;
|
||||
int num;
|
||||
|
||||
b.length=0;
|
||||
b.max=0;
|
||||
b.data=NULL;
|
||||
b.length = 0;
|
||||
b.max = 0;
|
||||
b.data = NULL;
|
||||
|
||||
if (a == NULL)
|
||||
{
|
||||
c->error=ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
if (a == NULL) {
|
||||
c->error = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
num=0;
|
||||
for (;;)
|
||||
{
|
||||
if (c->inf & 1)
|
||||
{
|
||||
c->eos=ASN1_const_check_infinite_end(&c->p,
|
||||
(long)(c->max-c->p));
|
||||
if (c->eos) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c->slen <= 0) break;
|
||||
}
|
||||
num = 0;
|
||||
for (;;) {
|
||||
if (c->inf & 1) {
|
||||
c->eos = ASN1_const_check_infinite_end(&c->p,
|
||||
(long)(c->max - c->p));
|
||||
if (c->eos)
|
||||
break;
|
||||
} else {
|
||||
if (c->slen <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
c->q=c->p;
|
||||
if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
|
||||
== NULL)
|
||||
{
|
||||
c->error=ERR_R_ASN1_LIB;
|
||||
goto err;
|
||||
}
|
||||
c->q = c->p;
|
||||
if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass)
|
||||
== NULL) {
|
||||
c->error = ERR_R_ASN1_LIB;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BUF_MEM_grow_clean(&b,num+os->length))
|
||||
{
|
||||
c->error=ERR_R_BUF_LIB;
|
||||
goto err;
|
||||
}
|
||||
memcpy(&(b.data[num]),os->data,os->length);
|
||||
if (!(c->inf & 1))
|
||||
c->slen-=(c->p-c->q);
|
||||
num+=os->length;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(&b, num + os->length)) {
|
||||
c->error = ERR_R_BUF_LIB;
|
||||
goto err;
|
||||
}
|
||||
memcpy(&(b.data[num]), os->data, os->length);
|
||||
if (!(c->inf & 1))
|
||||
c->slen -= (c->p - c->q);
|
||||
num += os->length;
|
||||
}
|
||||
|
||||
if (!asn1_const_Finish(c)) goto err;
|
||||
|
||||
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);
|
||||
}
|
||||
if (!asn1_const_Finish(c))
|
||||
goto err;
|
||||
|
||||
a->length = num;
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
a->data = (unsigned char *)b.data;
|
||||
if (os != NULL)
|
||||
ASN1_STRING_free(os);
|
||||
return (1);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, c->error);
|
||||
if (os != NULL)
|
||||
ASN1_STRING_free(os);
|
||||
if (b.data != NULL)
|
||||
OPENSSL_free(b.data);
|
||||
return (0);
|
||||
}
|
||||
|
||||
+173
-192
@@ -62,225 +62,206 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
|
||||
|
||||
#ifndef NO_OLD_ASN1
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
# ifndef OPENSSL_NO_FP_API
|
||||
|
||||
void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
|
||||
{
|
||||
BIO *b;
|
||||
void *ret;
|
||||
void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
|
||||
{
|
||||
BIO *b;
|
||||
void *ret;
|
||||
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(NULL);
|
||||
}
|
||||
BIO_set_fp(b,in,BIO_NOCLOSE);
|
||||
ret=ASN1_d2i_bio(xnew,d2i,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (NULL);
|
||||
}
|
||||
BIO_set_fp(b, in, BIO_NOCLOSE);
|
||||
ret = ASN1_d2i_bio(xnew, d2i, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
# endif
|
||||
|
||||
void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret=NULL;
|
||||
int len;
|
||||
void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret = NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if(len < 0) goto err;
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if (len < 0)
|
||||
goto err;
|
||||
|
||||
p=(unsigned char *)b->data;
|
||||
ret=d2i(x,&p,len);
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
}
|
||||
p = (unsigned char *)b->data;
|
||||
ret = d2i(x, &p, len);
|
||||
err:
|
||||
if (b != NULL)
|
||||
BUF_MEM_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret=NULL;
|
||||
int len;
|
||||
{
|
||||
BUF_MEM *b = NULL;
|
||||
const unsigned char *p;
|
||||
void *ret = NULL;
|
||||
int len;
|
||||
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if(len < 0) goto err;
|
||||
len = asn1_d2i_read_bio(in, &b);
|
||||
if (len < 0)
|
||||
goto err;
|
||||
|
||||
p=(const unsigned char *)b->data;
|
||||
ret=ASN1_item_d2i(x,&p,len, it);
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return(ret);
|
||||
}
|
||||
p = (const unsigned char *)b->data;
|
||||
ret = ASN1_item_d2i(x, &p, len, it);
|
||||
err:
|
||||
if (b != NULL)
|
||||
BUF_MEM_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
char *ret;
|
||||
{
|
||||
BIO *b;
|
||||
char *ret;
|
||||
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(NULL);
|
||||
}
|
||||
BIO_set_fp(b,in,BIO_NOCLOSE);
|
||||
ret=ASN1_item_d2i_bio(it,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (NULL);
|
||||
}
|
||||
BIO_set_fp(b, in, BIO_NOCLOSE);
|
||||
ret = ASN1_item_d2i_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
||||
{
|
||||
BUF_MEM *b;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
ASN1_const_CTX c;
|
||||
size_t want=HEADER_SIZE;
|
||||
int eos=0;
|
||||
size_t off=0;
|
||||
size_t len=0;
|
||||
{
|
||||
BUF_MEM *b;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
ASN1_const_CTX c;
|
||||
size_t want = HEADER_SIZE;
|
||||
int eos = 0;
|
||||
size_t off = 0;
|
||||
size_t len = 0;
|
||||
|
||||
b=BUF_MEM_new();
|
||||
if (b == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
b = BUF_MEM_new();
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
for (;;)
|
||||
{
|
||||
if (want >= (len-off))
|
||||
{
|
||||
want-=(len-off);
|
||||
ERR_clear_error();
|
||||
for (;;) {
|
||||
if (want >= (len - off)) {
|
||||
want -= (len - off);
|
||||
|
||||
if (len + want < len || !BUF_MEM_grow_clean(b,len+want))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i=BIO_read(in,&(b->data[len]),want);
|
||||
if ((i < 0) && ((len-off) == 0))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
if (len+i < len)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
len+=i;
|
||||
}
|
||||
}
|
||||
/* else data already loaded */
|
||||
if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i = BIO_read(in, &(b->data[len]), want);
|
||||
if ((i < 0) && ((len - off) == 0)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
if (i > 0) {
|
||||
if (len + i < len) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
len += i;
|
||||
}
|
||||
}
|
||||
/* else data already loaded */
|
||||
|
||||
p=(unsigned char *)&(b->data[off]);
|
||||
c.p=p;
|
||||
c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
|
||||
len-off);
|
||||
if (c.inf & 0x80)
|
||||
{
|
||||
uint32_t e;
|
||||
p = (unsigned char *)&(b->data[off]);
|
||||
c.p = p;
|
||||
c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
|
||||
len - off);
|
||||
if (c.inf & 0x80) {
|
||||
uint32_t e;
|
||||
|
||||
e=ERR_GET_REASON(ERR_peek_error());
|
||||
if (e != ASN1_R_TOO_LONG)
|
||||
goto err;
|
||||
else
|
||||
ERR_clear_error(); /* clear error */
|
||||
}
|
||||
i=c.p-p;/* header length */
|
||||
off+=i; /* end of data */
|
||||
e = ERR_GET_REASON(ERR_peek_error());
|
||||
if (e != ASN1_R_TOO_LONG)
|
||||
goto err;
|
||||
else
|
||||
ERR_clear_error(); /* clear error */
|
||||
}
|
||||
i = c.p - p; /* header length */
|
||||
off += i; /* end of data */
|
||||
|
||||
if (c.inf & 1)
|
||||
{
|
||||
/* no data body so go round again */
|
||||
eos++;
|
||||
if (eos < 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
want=HEADER_SIZE;
|
||||
}
|
||||
else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
|
||||
{
|
||||
/* eos value, so go back and read another header */
|
||||
eos--;
|
||||
if (eos <= 0)
|
||||
break;
|
||||
else
|
||||
want=HEADER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* suck in c.slen bytes of data */
|
||||
want=c.slen;
|
||||
if (want > (len-off))
|
||||
{
|
||||
want-=(len-off);
|
||||
if (want > INT_MAX /* BIO_read takes an int length */ ||
|
||||
len+want < len)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(b,len+want))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
while (want > 0)
|
||||
{
|
||||
i=BIO_read(in,&(b->data[len]),want);
|
||||
if (i <= 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
/* This can't overflow because
|
||||
* |len+want| didn't overflow. */
|
||||
len+=i;
|
||||
want-=i;
|
||||
}
|
||||
}
|
||||
if (off + c.slen < off)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
off+=c.slen;
|
||||
if (eos <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
want=HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
if (c.inf & 1) {
|
||||
/* no data body so go round again */
|
||||
eos++;
|
||||
if (eos < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
want = HEADER_SIZE;
|
||||
} else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) {
|
||||
/* eos value, so go back and read another header */
|
||||
eos--;
|
||||
if (eos <= 0)
|
||||
break;
|
||||
else
|
||||
want = HEADER_SIZE;
|
||||
} else {
|
||||
/* suck in c.slen bytes of data */
|
||||
want = c.slen;
|
||||
if (want > (len - off)) {
|
||||
want -= (len - off);
|
||||
if (want > INT_MAX /* BIO_read takes an int length */ ||
|
||||
len + want < len) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (!BUF_MEM_grow_clean(b, len + want)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
while (want > 0) {
|
||||
i = BIO_read(in, &(b->data[len]), want);
|
||||
if (i <= 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* This can't overflow because |len+want| didn't
|
||||
* overflow.
|
||||
*/
|
||||
len += i;
|
||||
want -= i;
|
||||
}
|
||||
}
|
||||
if (off + c.slen < off) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
off += c.slen;
|
||||
if (eos <= 0) {
|
||||
break;
|
||||
} else
|
||||
want = HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (off > INT_MAX)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (off > INT_MAX) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*pb = b;
|
||||
return off;
|
||||
err:
|
||||
if (b != NULL) BUF_MEM_free(b);
|
||||
return -1;
|
||||
}
|
||||
*pb = b;
|
||||
return off;
|
||||
err:
|
||||
if (b != NULL)
|
||||
BUF_MEM_free(b);
|
||||
return -1;
|
||||
}
|
||||
|
||||
+43
-35
@@ -59,45 +59,53 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
|
||||
{
|
||||
unsigned char *b,*p;
|
||||
const unsigned char *p2;
|
||||
int i;
|
||||
char *ret;
|
||||
{
|
||||
unsigned char *b, *p;
|
||||
const unsigned char *p2;
|
||||
int i;
|
||||
char *ret;
|
||||
|
||||
if (x == NULL) return(NULL);
|
||||
if (x == NULL)
|
||||
return (NULL);
|
||||
|
||||
i=i2d(x,NULL);
|
||||
b=OPENSSL_malloc(i+10);
|
||||
if (b == NULL)
|
||||
{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
|
||||
p= b;
|
||||
i=i2d(x,&p);
|
||||
p2= b;
|
||||
ret=d2i(NULL,&p2,i);
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
i = i2d(x, NULL);
|
||||
b = OPENSSL_malloc(i + 10);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
p = b;
|
||||
i = i2d(x, &p);
|
||||
p2 = b;
|
||||
ret = d2i(NULL, &p2, i);
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* ASN1_ITEM version of dup: this follows the model above except we don't need
|
||||
* to allocate the buffer. At some point this could be rewritten to directly dup
|
||||
* the underlying structure instead of doing and encode and decode. */
|
||||
/*
|
||||
* ASN1_ITEM version of dup: this follows the model above except we don't
|
||||
* need to allocate the buffer. At some point this could be rewritten to
|
||||
* directly dup the underlying structure instead of doing and encode and
|
||||
* decode.
|
||||
*/
|
||||
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
const unsigned char *p;
|
||||
long i;
|
||||
void *ret;
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
const unsigned char *p;
|
||||
long i;
|
||||
void *ret;
|
||||
|
||||
if (x == NULL) return(NULL);
|
||||
if (x == NULL)
|
||||
return (NULL);
|
||||
|
||||
i=ASN1_item_i2d(x,&b,it);
|
||||
if (b == NULL)
|
||||
{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
|
||||
p= b;
|
||||
ret=ASN1_item_d2i(NULL,&p,i, it);
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
i = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
p = b;
|
||||
ret = ASN1_item_d2i(NULL, &p, i, it);
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+100
-102
@@ -61,123 +61,121 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
|
||||
* for comments on encoding see a_int.c
|
||||
*/
|
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
|
||||
{
|
||||
int j,k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long)+1];
|
||||
long d;
|
||||
{
|
||||
int j, k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long) + 1];
|
||||
long d;
|
||||
|
||||
a->type=V_ASN1_ENUMERATED;
|
||||
if (a->length < (int)(sizeof(long)+1))
|
||||
{
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
|
||||
memset((char *)a->data,0,sizeof(long)+1);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
d=v;
|
||||
if (d < 0)
|
||||
{
|
||||
d= -d;
|
||||
a->type=V_ASN1_NEG_ENUMERATED;
|
||||
}
|
||||
a->type = V_ASN1_ENUMERATED;
|
||||
if (a->length < (int)(sizeof(long) + 1)) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
d = v;
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
a->type = V_ASN1_NEG_ENUMERATED;
|
||||
}
|
||||
|
||||
for (i=0; i<sizeof(long); i++)
|
||||
{
|
||||
if (d == 0) break;
|
||||
buf[i]=(int)d&0xff;
|
||||
d>>=8;
|
||||
}
|
||||
j=0;
|
||||
for (k=i-1; k >=0; k--)
|
||||
a->data[j++]=buf[k];
|
||||
a->length=j;
|
||||
return(1);
|
||||
}
|
||||
for (i = 0; i < sizeof(long); i++) {
|
||||
if (d == 0)
|
||||
break;
|
||||
buf[i] = (int)d & 0xff;
|
||||
d >>= 8;
|
||||
}
|
||||
j = 0;
|
||||
for (k = i - 1; k >= 0; k--)
|
||||
a->data[j++] = buf[k];
|
||||
a->length = j;
|
||||
return (1);
|
||||
}
|
||||
|
||||
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
|
||||
{
|
||||
int neg=0,i;
|
||||
long r=0;
|
||||
{
|
||||
int neg = 0, i;
|
||||
long r = 0;
|
||||
|
||||
if (a == NULL) return(0L);
|
||||
i=a->type;
|
||||
if (i == V_ASN1_NEG_ENUMERATED)
|
||||
neg=1;
|
||||
else if (i != V_ASN1_ENUMERATED)
|
||||
return -1;
|
||||
|
||||
if (a->length > (int)sizeof(long))
|
||||
{
|
||||
/* hmm... a bit ugly */
|
||||
return(0xffffffffL);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
return 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;
|
||||
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
r<<=8;
|
||||
r|=(unsigned char)a->data[i];
|
||||
}
|
||||
if (neg) r= -r;
|
||||
return(r);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len,j;
|
||||
{
|
||||
ASN1_ENUMERATED *ret;
|
||||
int len, j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret=M_ASN1_ENUMERATED_new();
|
||||
else
|
||||
ret=ai;
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if(BN_is_negative(bn)) ret->type = V_ASN1_NEG_ENUMERATED;
|
||||
else ret->type=V_ASN1_ENUMERATED;
|
||||
j=BN_num_bits(bn);
|
||||
len=((j == 0)?0:((j/8)+1));
|
||||
if (ret->length < len+4)
|
||||
{
|
||||
unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
|
||||
if (!new_data)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data=new_data;
|
||||
}
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_ENUMERATED_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn))
|
||||
ret->type = V_ASN1_NEG_ENUMERATED;
|
||||
else
|
||||
ret->type = V_ASN1_ENUMERATED;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
|
||||
ret->length=BN_bn2bin(bn,ret->data);
|
||||
return(ret);
|
||||
err:
|
||||
if (ret != ai) M_ASN1_ENUMERATED_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_ENUMERATED_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
|
||||
return(ret);
|
||||
}
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_ENUMERATED)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+170
-171
@@ -63,193 +63,192 @@
|
||||
#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, 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);
|
||||
}
|
||||
|
||||
+73
-80
@@ -59,96 +59,89 @@
|
||||
#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);
|
||||
}
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, out, BIO_NOCLOSE);
|
||||
ret = ASN1_i2d_bio(i2d, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x)
|
||||
{
|
||||
char *b;
|
||||
unsigned char *p;
|
||||
int i,j=0,n,ret=1;
|
||||
{
|
||||
char *b;
|
||||
unsigned char *p;
|
||||
int i, j = 0, n, ret = 1;
|
||||
|
||||
n=i2d(x,NULL);
|
||||
b=(char *)OPENSSL_malloc(n);
|
||||
if (b == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
n = i2d(x, NULL);
|
||||
b = (char *)OPENSSL_malloc(n);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
p=(unsigned char *)b;
|
||||
i2d(x,&p);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
i=BIO_write(out,&(b[j]),n);
|
||||
if (i == n) break;
|
||||
if (i <= 0)
|
||||
{
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
j+=i;
|
||||
n-=i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
p = (unsigned char *)b;
|
||||
i2d(x, &p);
|
||||
|
||||
for (;;) {
|
||||
i = BIO_write(out, &(b[j]), n);
|
||||
if (i == n)
|
||||
break;
|
||||
if (i <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b=BIO_new(BIO_s_file())) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return(0);
|
||||
}
|
||||
BIO_set_fp(b,out,BIO_NOCLOSE);
|
||||
ret=ASN1_item_i2d_bio(it,b,x);
|
||||
BIO_free(b);
|
||||
return(ret);
|
||||
}
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, out, BIO_NOCLOSE);
|
||||
ret = ASN1_item_i2d_bio(it, b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int i,j=0,n,ret=1;
|
||||
{
|
||||
unsigned char *b = NULL;
|
||||
int i, j = 0, n, ret = 1;
|
||||
|
||||
n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
n = ASN1_item_i2d(x, &b, it);
|
||||
if (b == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
i=BIO_write(out,&(b[j]),n);
|
||||
if (i == n) break;
|
||||
if (i <= 0)
|
||||
{
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
j+=i;
|
||||
n-=i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return(ret);
|
||||
}
|
||||
for (;;) {
|
||||
i = BIO_write(out, &(b[j]), n);
|
||||
if (i == n)
|
||||
break;
|
||||
if (i <= 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
j += i;
|
||||
n -= i;
|
||||
}
|
||||
OPENSSL_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+335
-331
@@ -61,47 +61,46 @@
|
||||
#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.
|
||||
@@ -113,344 +112,349 @@ 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 (!neg && (i > 127)) {
|
||||
pad=1;
|
||||
pb=0;
|
||||
} else if(neg) {
|
||||
if(i>128) {
|
||||
pad=1;
|
||||
pb=0xFF;
|
||||
} else if(i == 128) {
|
||||
/*
|
||||
* Special case: if any other bytes non zero we pad:
|
||||
* otherwise we don't.
|
||||
*/
|
||||
for(i = 1; i < a->length; i++) if(a->data[i]) {
|
||||
pad=1;
|
||||
pb=0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret+=pad;
|
||||
}
|
||||
if (pp == NULL) return(ret);
|
||||
p= *pp;
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
neg = a->type & V_ASN1_NEG;
|
||||
if (a->length == 0)
|
||||
ret = 1;
|
||||
else {
|
||||
ret = a->length;
|
||||
i = a->data[0];
|
||||
if (ret == 1 && i == 0)
|
||||
neg = 0;
|
||||
if (!neg && (i > 127)) {
|
||||
pad = 1;
|
||||
pb = 0;
|
||||
} else if (neg) {
|
||||
if (i > 128) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
} else if (i == 128) {
|
||||
/*
|
||||
* Special case: if any other bytes non zero we pad:
|
||||
* otherwise we don't.
|
||||
*/
|
||||
for (i = 1; i < a->length; i++)
|
||||
if (a->data[i]) {
|
||||
pad = 1;
|
||||
pb = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret += pad;
|
||||
}
|
||||
if (pp == NULL)
|
||||
return (ret);
|
||||
p = *pp;
|
||||
|
||||
if (pad) *(p++)=pb;
|
||||
if (a->length == 0) *(p++)=0;
|
||||
else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n=a->data + a->length - 1;
|
||||
p += a->length - 1;
|
||||
i = a->length;
|
||||
/* Copy zeros to destination as long as source is zero */
|
||||
while(!*n) {
|
||||
*(p--) = 0;
|
||||
n--;
|
||||
i--;
|
||||
}
|
||||
/* Complement and increment next octet */
|
||||
*(p--) = ((*(n--)) ^ 0xff) + 1;
|
||||
i--;
|
||||
/* Complement any octets left */
|
||||
for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
|
||||
}
|
||||
if (pad)
|
||||
*(p++) = pb;
|
||||
if (a->length == 0)
|
||||
*(p++) = 0;
|
||||
else if (!neg)
|
||||
memcpy(p, a->data, (unsigned int)a->length);
|
||||
else {
|
||||
/* Begin at the end of the encoding */
|
||||
n = a->data + a->length - 1;
|
||||
p += a->length - 1;
|
||||
i = a->length;
|
||||
/* Copy zeros to destination as long as source is zero */
|
||||
while (!*n && i > 1) {
|
||||
*(p--) = 0;
|
||||
n--;
|
||||
i--;
|
||||
}
|
||||
/* Complement and increment next octet */
|
||||
*(p--) = ((*(n--)) ^ 0xff) + 1;
|
||||
i--;
|
||||
/* Complement any octets left */
|
||||
for (; i > 0; i--)
|
||||
*(p--) = *(n--) ^ 0xff;
|
||||
}
|
||||
|
||||
*pp+=ret;
|
||||
return(ret);
|
||||
}
|
||||
*pp += ret;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
|
||||
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret=NULL;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char *to,*s;
|
||||
int i;
|
||||
long len)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char *to, *s;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_INTEGER_new()) == NULL)
|
||||
return (NULL);
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p= *pp;
|
||||
pend = p + len;
|
||||
p = *pp;
|
||||
pend = p + len;
|
||||
|
||||
/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
|
||||
* signifies a missing NULL parameter. */
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len+1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
to=s;
|
||||
if(!len) {
|
||||
/* Strictly speaking this is an illegal INTEGER but we
|
||||
* tolerate it.
|
||||
*/
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
} else if (*p & 0x80) /* a negative number */
|
||||
{
|
||||
ret->type=V_ASN1_NEG_INTEGER;
|
||||
if ((*p == 0xff) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
i = len;
|
||||
p += i - 1;
|
||||
to += i - 1;
|
||||
while((!*p) && i) {
|
||||
*(to--) = 0;
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
/* Special case: if all zeros then the number will be of
|
||||
* the form FF followed by n zero bytes: this corresponds to
|
||||
* 1 followed by n zero bytes. We've already written n zeros
|
||||
* so we just append an extra one and set the first byte to
|
||||
* a 1. This is treated separately because it is the only case
|
||||
* where the number of bytes is larger than len.
|
||||
*/
|
||||
if(!i) {
|
||||
*s = 1;
|
||||
s[len] = 0;
|
||||
len++;
|
||||
} else {
|
||||
*(to--) = (*(p--) ^ 0xff) + 1;
|
||||
i--;
|
||||
for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
|
||||
}
|
||||
} else {
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
if ((*p == 0) && (len != 1))
|
||||
{
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
}
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
to = s;
|
||||
if (!len) {
|
||||
/*
|
||||
* Strictly speaking this is an illegal INTEGER but we tolerate it.
|
||||
*/
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else if (*p & 0x80) { /* a negative number */
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
if ((*p == 0xff) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
i = len;
|
||||
p += i - 1;
|
||||
to += i - 1;
|
||||
while ((!*p) && i) {
|
||||
*(to--) = 0;
|
||||
i--;
|
||||
p--;
|
||||
}
|
||||
/*
|
||||
* Special case: if all zeros then the number will be of the form FF
|
||||
* followed by n zero bytes: this corresponds to 1 followed by n zero
|
||||
* bytes. We've already written n zeros so we just append an extra
|
||||
* one and set the first byte to a 1. This is treated separately
|
||||
* because it is the only case where the number of bytes is larger
|
||||
* than len.
|
||||
*/
|
||||
if (!i) {
|
||||
*s = 1;
|
||||
s[len] = 0;
|
||||
len++;
|
||||
} else {
|
||||
*(to--) = (*(p--) ^ 0xff) + 1;
|
||||
i--;
|
||||
for (; i > 0; i--)
|
||||
*(to--) = *(p--) ^ 0xff;
|
||||
}
|
||||
} else {
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
}
|
||||
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->data=s;
|
||||
ret->length=(int)len;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=pend;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = pend;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
|
||||
* ASN1 integers: some broken software can encode a positive INTEGER
|
||||
* with its MSB set as negative (it doesn't add a padding zero).
|
||||
/*
|
||||
* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
|
||||
* integers: some broken software can encode a positive INTEGER with its MSB
|
||||
* set as negative (it doesn't add a padding zero).
|
||||
*/
|
||||
|
||||
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||
long length)
|
||||
{
|
||||
ASN1_INTEGER *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf,tag,xclass;
|
||||
int i;
|
||||
long length)
|
||||
{
|
||||
ASN1_INTEGER *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *s;
|
||||
long len;
|
||||
int inf, tag, xclass;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || ((*a) == NULL))
|
||||
{
|
||||
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
}
|
||||
else
|
||||
ret=(*a);
|
||||
if ((a == NULL) || ((*a) == NULL)) {
|
||||
if ((ret = M_ASN1_INTEGER_new()) == NULL)
|
||||
return (NULL);
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_INTEGER)
|
||||
{
|
||||
i=ASN1_R_EXPECTING_AN_INTEGER;
|
||||
goto err;
|
||||
}
|
||||
if (tag != V_ASN1_INTEGER) {
|
||||
i = ASN1_R_EXPECTING_AN_INTEGER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
|
||||
* signifies a missing NULL parameter. */
|
||||
s=(unsigned char *)OPENSSL_malloc((int)len+1);
|
||||
if (s == NULL)
|
||||
{
|
||||
i=ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->type=V_ASN1_INTEGER;
|
||||
if(len) {
|
||||
if ((*p == 0) && (len != 1))
|
||||
{
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s,p,(int)len);
|
||||
p+=len;
|
||||
}
|
||||
/*
|
||||
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
|
||||
* a missing NULL parameter.
|
||||
*/
|
||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
||||
if (s == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
if (len) {
|
||||
if ((*p == 0) && (len != 1)) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
memcpy(s, p, (int)len);
|
||||
p += len;
|
||||
}
|
||||
|
||||
if (ret->data != NULL) OPENSSL_free(ret->data);
|
||||
ret->data=s;
|
||||
ret->length=(int)len;
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (ret->data != NULL)
|
||||
OPENSSL_free(ret->data);
|
||||
ret->data = s;
|
||||
ret->length = (int)len;
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
|
||||
{
|
||||
int j,k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long)+1];
|
||||
long d;
|
||||
{
|
||||
int j, k;
|
||||
unsigned int i;
|
||||
unsigned char buf[sizeof(long) + 1];
|
||||
long d;
|
||||
|
||||
a->type=V_ASN1_INTEGER;
|
||||
if (a->length < (int)(sizeof(long)+1))
|
||||
{
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
|
||||
memset((char *)a->data,0,sizeof(long)+1);
|
||||
}
|
||||
if (a->data == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(0);
|
||||
}
|
||||
d=v;
|
||||
if (d < 0)
|
||||
{
|
||||
d= -d;
|
||||
a->type=V_ASN1_NEG_INTEGER;
|
||||
}
|
||||
a->type = V_ASN1_INTEGER;
|
||||
if (a->length < (int)(sizeof(long) + 1)) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free(a->data);
|
||||
if ((a->data =
|
||||
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
|
||||
memset((char *)a->data, 0, sizeof(long) + 1);
|
||||
}
|
||||
if (a->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
d = v;
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
a->type = V_ASN1_NEG_INTEGER;
|
||||
}
|
||||
|
||||
for (i=0; i<sizeof(long); i++)
|
||||
{
|
||||
if (d == 0) break;
|
||||
buf[i]=(int)d&0xff;
|
||||
d>>=8;
|
||||
}
|
||||
j=0;
|
||||
for (k=i-1; k >=0; k--)
|
||||
a->data[j++]=buf[k];
|
||||
a->length=j;
|
||||
return(1);
|
||||
}
|
||||
for (i = 0; i < sizeof(long); i++) {
|
||||
if (d == 0)
|
||||
break;
|
||||
buf[i] = (int)d & 0xff;
|
||||
d >>= 8;
|
||||
}
|
||||
j = 0;
|
||||
for (k = i - 1; k >= 0; k--)
|
||||
a->data[j++] = buf[k];
|
||||
a->length = j;
|
||||
return (1);
|
||||
}
|
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
|
||||
{
|
||||
int neg=0,i;
|
||||
long r=0;
|
||||
{
|
||||
int neg = 0, i;
|
||||
long r = 0;
|
||||
|
||||
if (a == NULL) return(0L);
|
||||
i=a->type;
|
||||
if (i == V_ASN1_NEG_INTEGER)
|
||||
neg=1;
|
||||
else if (i != V_ASN1_INTEGER)
|
||||
return -1;
|
||||
|
||||
if (a->length > (int)sizeof(long))
|
||||
{
|
||||
/* hmm... a bit ugly, return all ones */
|
||||
return -1;
|
||||
}
|
||||
if (a->data == NULL)
|
||||
return 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;
|
||||
|
||||
for (i=0; i<a->length; i++)
|
||||
{
|
||||
r<<=8;
|
||||
r|=(unsigned char)a->data[i];
|
||||
}
|
||||
if (neg) r= -r;
|
||||
return(r);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len,j;
|
||||
{
|
||||
ASN1_INTEGER *ret;
|
||||
int len, j;
|
||||
|
||||
if (ai == NULL)
|
||||
ret=M_ASN1_INTEGER_new();
|
||||
else
|
||||
ret=ai;
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
else ret->type=V_ASN1_INTEGER;
|
||||
j=BN_num_bits(bn);
|
||||
len=((j == 0)?0:((j/8)+1));
|
||||
if (ret->length < len+4)
|
||||
{
|
||||
unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
|
||||
if (!new_data)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data=new_data;
|
||||
}
|
||||
ret->length=BN_bn2bin(bn,ret->data);
|
||||
/* Correct zero case */
|
||||
if(!ret->length)
|
||||
{
|
||||
ret->data[0] = 0;
|
||||
ret->length = 1;
|
||||
}
|
||||
return(ret);
|
||||
err:
|
||||
if (ret != ai) M_ASN1_INTEGER_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (ai == NULL)
|
||||
ret = M_ASN1_INTEGER_new();
|
||||
else
|
||||
ret = ai;
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (BN_is_negative(bn) && !BN_is_zero(bn))
|
||||
ret->type = V_ASN1_NEG_INTEGER;
|
||||
else
|
||||
ret->type = V_ASN1_INTEGER;
|
||||
j = BN_num_bits(bn);
|
||||
len = ((j == 0) ? 0 : ((j / 8) + 1));
|
||||
if (ret->length < len + 4) {
|
||||
unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
|
||||
if (!new_data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ret->data = new_data;
|
||||
}
|
||||
ret->length = BN_bn2bin(bn, ret->data);
|
||||
/* Correct zero case */
|
||||
if (!ret->length) {
|
||||
ret->data[0] = 0;
|
||||
ret->length = 1;
|
||||
}
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != ai)
|
||||
M_ASN1_INTEGER_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if(ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return(ret);
|
||||
}
|
||||
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
|
||||
else if (ai->type == V_ASN1_NEG_INTEGER)
|
||||
BN_set_negative(ret, 1);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+258
-239
@@ -61,9 +61,9 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
int (*rfunc)(unsigned long value, void *in), void *arg);
|
||||
int (*rfunc) (unsigned long value, void *in),
|
||||
void *arg);
|
||||
static int in_utf8(unsigned long value, void *arg);
|
||||
static int out_utf8(unsigned long value, void *arg);
|
||||
static int type_str(unsigned long value, void *arg);
|
||||
@@ -73,208 +73,219 @@ static int cpy_univ(unsigned long value, void *arg);
|
||||
static int cpy_utf8(unsigned long value, void *arg);
|
||||
static int is_printable(unsigned long value);
|
||||
|
||||
/* These functions take a string in UTF8, ASCII or multibyte form and
|
||||
* a mask of permissible ASN1 string types. It then works out the minimal
|
||||
* type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
|
||||
* and creates a string of the correct type with the supplied data.
|
||||
* Yes this is horrible: it has to be :-(
|
||||
* The 'ncopy' form checks minimum and maximum size limits too.
|
||||
/*
|
||||
* These functions take a string in UTF8, ASCII or multibyte form and a mask
|
||||
* of permissible ASN1 string types. It then works out the minimal type
|
||||
* (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
|
||||
* creates a string of the correct type with the supplied data. Yes this is
|
||||
* horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
|
||||
* size limits too.
|
||||
*/
|
||||
|
||||
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask)
|
||||
int inform, unsigned long mask)
|
||||
{
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
|
||||
}
|
||||
|
||||
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
|
||||
int inform, unsigned long mask,
|
||||
long minsize, long maxsize)
|
||||
int inform, unsigned long mask,
|
||||
long minsize, long maxsize)
|
||||
{
|
||||
int str_type;
|
||||
int ret;
|
||||
char free_out;
|
||||
int outform, outlen = 0;
|
||||
ASN1_STRING *dest;
|
||||
unsigned char *p;
|
||||
int nchar;
|
||||
char strbuf[32];
|
||||
int (*cpyfunc)(unsigned long,void *) = NULL;
|
||||
if(len == -1) len = strlen((const char *)in);
|
||||
if(!mask) mask = DIRSTRING_TYPE;
|
||||
int str_type;
|
||||
int ret;
|
||||
char free_out;
|
||||
int outform, outlen = 0;
|
||||
ASN1_STRING *dest;
|
||||
unsigned char *p;
|
||||
int nchar;
|
||||
char strbuf[32];
|
||||
int (*cpyfunc) (unsigned long, void *) = NULL;
|
||||
if (len == -1)
|
||||
len = strlen((const char *)in);
|
||||
if (!mask)
|
||||
mask = DIRSTRING_TYPE;
|
||||
|
||||
/* First do a string check and work out the number of characters */
|
||||
switch(inform) {
|
||||
/* First do a string check and work out the number of characters */
|
||||
switch (inform) {
|
||||
|
||||
case MBSTRING_BMP:
|
||||
if(len & 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 1;
|
||||
break;
|
||||
case MBSTRING_BMP:
|
||||
if (len & 1) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 1;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
if(len & 3) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 2;
|
||||
break;
|
||||
case MBSTRING_UNIV:
|
||||
if (len & 3) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
nchar = len >> 2;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
nchar = 0;
|
||||
/* This counts the characters and does utf8 syntax checking */
|
||||
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
|
||||
if(ret < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MBSTRING_UTF8:
|
||||
nchar = 0;
|
||||
/* This counts the characters and does utf8 syntax checking */
|
||||
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBSTRING_ASC:
|
||||
nchar = len;
|
||||
break;
|
||||
case MBSTRING_ASC:
|
||||
nchar = len;
|
||||
break;
|
||||
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((minsize > 0) && (nchar < minsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
|
||||
ERR_add_error_data(2, "minsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
if ((minsize > 0) && (nchar < minsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
|
||||
ERR_add_error_data(2, "minsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((maxsize > 0) && (nchar > maxsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
if ((maxsize > 0) && (nchar > maxsize)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
|
||||
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
|
||||
ERR_add_error_data(2, "maxsize=", strbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out minimal type (if any) */
|
||||
if(traverse_string(in, len, inform, type_str, &mask) < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
/* Now work out minimal type (if any) */
|
||||
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now work out output format and string type */
|
||||
outform = MBSTRING_ASC;
|
||||
if (mask & B_ASN1_PRINTABLESTRING)
|
||||
str_type = V_ASN1_PRINTABLESTRING;
|
||||
else if (mask & B_ASN1_IA5STRING)
|
||||
str_type = V_ASN1_IA5STRING;
|
||||
else if (mask & B_ASN1_T61STRING)
|
||||
str_type = V_ASN1_T61STRING;
|
||||
else if (mask & B_ASN1_BMPSTRING) {
|
||||
str_type = V_ASN1_BMPSTRING;
|
||||
outform = MBSTRING_BMP;
|
||||
} else if (mask & B_ASN1_UNIVERSALSTRING) {
|
||||
str_type = V_ASN1_UNIVERSALSTRING;
|
||||
outform = MBSTRING_UNIV;
|
||||
} else {
|
||||
str_type = V_ASN1_UTF8STRING;
|
||||
outform = MBSTRING_UTF8;
|
||||
}
|
||||
if (!out)
|
||||
return str_type;
|
||||
if (*out) {
|
||||
free_out = 0;
|
||||
dest = *out;
|
||||
if (dest->data) {
|
||||
dest->length = 0;
|
||||
OPENSSL_free(dest->data);
|
||||
dest->data = NULL;
|
||||
}
|
||||
dest->type = str_type;
|
||||
} else {
|
||||
free_out = 1;
|
||||
dest = ASN1_STRING_type_new(str_type);
|
||||
if (!dest) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
*out = dest;
|
||||
}
|
||||
/* If both the same type just copy across */
|
||||
if (inform == outform) {
|
||||
if (!ASN1_STRING_set(dest, in, len)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
return str_type;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Work out how much space the destination will need */
|
||||
switch(outform) {
|
||||
case MBSTRING_ASC:
|
||||
outlen = nchar;
|
||||
cpyfunc = cpy_asc;
|
||||
break;
|
||||
case MBSTRING_BMP:
|
||||
outlen = nchar << 1;
|
||||
cpyfunc = cpy_bmp;
|
||||
break;
|
||||
|
||||
case MBSTRING_BMP:
|
||||
outlen = nchar << 1;
|
||||
cpyfunc = cpy_bmp;
|
||||
break;
|
||||
case MBSTRING_UNIV:
|
||||
outlen = nchar << 2;
|
||||
cpyfunc = cpy_univ;
|
||||
break;
|
||||
|
||||
case MBSTRING_UNIV:
|
||||
outlen = nchar << 2;
|
||||
cpyfunc = cpy_univ;
|
||||
break;
|
||||
|
||||
case MBSTRING_UTF8:
|
||||
outlen = 0;
|
||||
traverse_string(in, len, inform, out_utf8, &outlen);
|
||||
cpyfunc = cpy_utf8;
|
||||
break;
|
||||
}
|
||||
if(!(p = OPENSSL_malloc(outlen + 1))) {
|
||||
if(free_out) ASN1_STRING_free(dest);
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
dest->length = outlen;
|
||||
dest->data = p;
|
||||
p[outlen] = 0;
|
||||
traverse_string(in, len, inform, cpyfunc, &p);
|
||||
return str_type;
|
||||
case MBSTRING_UTF8:
|
||||
outlen = 0;
|
||||
traverse_string(in, len, inform, out_utf8, &outlen);
|
||||
cpyfunc = cpy_utf8;
|
||||
break;
|
||||
}
|
||||
if (!(p = OPENSSL_malloc(outlen + 1))) {
|
||||
if (free_out)
|
||||
ASN1_STRING_free(dest);
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
dest->length = outlen;
|
||||
dest->data = p;
|
||||
p[outlen] = 0;
|
||||
traverse_string(in, len, inform, cpyfunc, &p);
|
||||
return str_type;
|
||||
}
|
||||
|
||||
/* This function traverses a string and passes the value of each character
|
||||
* to an optional function along with a void * argument.
|
||||
/*
|
||||
* This function traverses a string and passes the value of each character to
|
||||
* an optional function along with a void * argument.
|
||||
*/
|
||||
|
||||
static int traverse_string(const unsigned char *p, int len, int inform,
|
||||
int (*rfunc)(unsigned long value, void *in), void *arg)
|
||||
int (*rfunc) (unsigned long value, void *in),
|
||||
void *arg)
|
||||
{
|
||||
unsigned long value;
|
||||
int ret;
|
||||
while(len) {
|
||||
if(inform == MBSTRING_ASC) {
|
||||
value = *p++;
|
||||
len--;
|
||||
} else if(inform == MBSTRING_BMP) {
|
||||
value = *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 2;
|
||||
} else if(inform == MBSTRING_UNIV) {
|
||||
value = ((unsigned long)*p++) << 24;
|
||||
value |= ((unsigned long)*p++) << 16;
|
||||
value |= *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 4;
|
||||
} else {
|
||||
ret = UTF8_getc(p, len, &value);
|
||||
if(ret < 0) return -1;
|
||||
len -= ret;
|
||||
p += ret;
|
||||
}
|
||||
if(rfunc) {
|
||||
ret = rfunc(value, arg);
|
||||
if(ret <= 0) return ret;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
while (len) {
|
||||
if (inform == MBSTRING_ASC) {
|
||||
value = *p++;
|
||||
len--;
|
||||
} else if (inform == MBSTRING_BMP) {
|
||||
value = *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 2;
|
||||
} else if (inform == MBSTRING_UNIV) {
|
||||
value = ((unsigned long)*p++) << 24;
|
||||
value |= ((unsigned long)*p++) << 16;
|
||||
value |= *p++ << 8;
|
||||
value |= *p++;
|
||||
len -= 4;
|
||||
} else {
|
||||
ret = UTF8_getc(p, len, &value);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
len -= ret;
|
||||
p += ret;
|
||||
}
|
||||
if (rfunc) {
|
||||
ret = rfunc(value, arg);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Various utility functions for traverse_string */
|
||||
@@ -283,108 +294,116 @@ 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;
|
||||
}
|
||||
|
||||
+293
-309
@@ -63,350 +63,334 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
|
||||
{
|
||||
unsigned char *p;
|
||||
int objsize;
|
||||
{
|
||||
unsigned char *p;
|
||||
int objsize;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL)) return(0);
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (0);
|
||||
|
||||
objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT);
|
||||
if (pp == NULL) return objsize;
|
||||
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
|
||||
if (pp == NULL)
|
||||
return objsize;
|
||||
|
||||
p= *pp;
|
||||
ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
|
||||
memcpy(p,a->data,a->length);
|
||||
p+=a->length;
|
||||
p = *pp;
|
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
|
||||
memcpy(p, a->data, a->length);
|
||||
p += a->length;
|
||||
|
||||
*pp=p;
|
||||
return(objsize);
|
||||
}
|
||||
*pp = p;
|
||||
return (objsize);
|
||||
}
|
||||
|
||||
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
|
||||
{
|
||||
int i,first,len=0,c, use_bn;
|
||||
char ftmp[24], *tmp = ftmp;
|
||||
int tmpsize = sizeof ftmp;
|
||||
const char *p;
|
||||
unsigned long l;
|
||||
BIGNUM *bl = NULL;
|
||||
{
|
||||
int i, first, len = 0, c, use_bn;
|
||||
char ftmp[24], *tmp = ftmp;
|
||||
int tmpsize = sizeof ftmp;
|
||||
const char *p;
|
||||
unsigned long l;
|
||||
BIGNUM *bl = NULL;
|
||||
|
||||
if (num == 0)
|
||||
return(0);
|
||||
else if (num == -1)
|
||||
num=strlen(buf);
|
||||
if (num == 0)
|
||||
return (0);
|
||||
else if (num == -1)
|
||||
num = strlen(buf);
|
||||
|
||||
p=buf;
|
||||
c= *(p++);
|
||||
num--;
|
||||
if ((c >= '0') && (c <= '2'))
|
||||
{
|
||||
first= c-'0';
|
||||
}
|
||||
else
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
p = buf;
|
||||
c = *(p++);
|
||||
num--;
|
||||
if ((c >= '0') && (c <= '2')) {
|
||||
first = c - '0';
|
||||
} else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (num <= 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
|
||||
goto err;
|
||||
}
|
||||
c= *(p++);
|
||||
num--;
|
||||
for (;;)
|
||||
{
|
||||
if (num <= 0) break;
|
||||
if ((c != '.') && (c != ' '))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
|
||||
goto err;
|
||||
}
|
||||
l=0;
|
||||
use_bn = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (num <= 0) break;
|
||||
num--;
|
||||
c= *(p++);
|
||||
if ((c == ' ') || (c == '.'))
|
||||
break;
|
||||
if ((c < '0') || (c > '9'))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
|
||||
goto err;
|
||||
}
|
||||
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L))
|
||||
{
|
||||
use_bn = 1;
|
||||
if (!bl)
|
||||
bl = BN_new();
|
||||
if (!bl || !BN_set_word(bl, l))
|
||||
goto err;
|
||||
}
|
||||
if (use_bn)
|
||||
{
|
||||
if (!BN_mul_word(bl, 10L)
|
||||
|| !BN_add_word(bl, c-'0'))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
l=l*10L+(long)(c-'0');
|
||||
}
|
||||
if (len == 0)
|
||||
{
|
||||
if ((first < 2) && (l >= 40))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (use_bn)
|
||||
{
|
||||
if (!BN_add_word(bl, first * 40))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
l+=(long)first*40;
|
||||
}
|
||||
i=0;
|
||||
if (use_bn)
|
||||
{
|
||||
int blsize;
|
||||
blsize = BN_num_bits(bl);
|
||||
blsize = (blsize + 6)/7;
|
||||
if (blsize > tmpsize)
|
||||
{
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
tmpsize = blsize + 32;
|
||||
tmp = OPENSSL_malloc(tmpsize);
|
||||
if (!tmp)
|
||||
goto err;
|
||||
}
|
||||
while(blsize--)
|
||||
tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (;;)
|
||||
{
|
||||
tmp[i++]=(unsigned char)l&0x7f;
|
||||
l>>=7L;
|
||||
if (l == 0L) break;
|
||||
}
|
||||
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 (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);
|
||||
}
|
||||
for (;;) {
|
||||
tmp[i++] = (unsigned char)l & 0x7f;
|
||||
l >>= 7L;
|
||||
if (l == 0L)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (out != NULL) {
|
||||
if (len + i > olen) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
while (--i > 0)
|
||||
out[len++] = tmp[i] | 0x80;
|
||||
out[len++] = tmp[0];
|
||||
} else
|
||||
len += i;
|
||||
}
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
if (bl)
|
||||
BN_free(bl);
|
||||
return (len);
|
||||
err:
|
||||
if (tmp != ftmp)
|
||||
OPENSSL_free(tmp);
|
||||
if (bl)
|
||||
BN_free(bl);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
|
||||
{
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
return OBJ_obj2txt(buf, buf_len, a, 0);
|
||||
}
|
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
{
|
||||
char buf[80], *p = buf;
|
||||
int i;
|
||||
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return(BIO_write(bp,"NULL",4));
|
||||
i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
|
||||
if (i > (int)(sizeof(buf) - 1))
|
||||
{
|
||||
p = OPENSSL_malloc(i + 1);
|
||||
if (!p)
|
||||
return -1;
|
||||
i2t_ASN1_OBJECT(p,i + 1,a);
|
||||
}
|
||||
if (i <= 0)
|
||||
return BIO_write(bp, "<INVALID>", 9);
|
||||
BIO_write(bp,p,i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return(i);
|
||||
}
|
||||
if ((a == NULL) || (a->data == NULL))
|
||||
return (BIO_write(bp, "NULL", 4));
|
||||
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
|
||||
if (i > (int)(sizeof(buf) - 1)) {
|
||||
p = OPENSSL_malloc(i + 1);
|
||||
if (!p)
|
||||
return -1;
|
||||
i2t_ASN1_OBJECT(p, i + 1, a);
|
||||
}
|
||||
if (i <= 0)
|
||||
return BIO_write(bp, "<INVALID>", 9);
|
||||
BIO_write(bp, p, i);
|
||||
if (p != buf)
|
||||
OPENSSL_free(p);
|
||||
return (i);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long length)
|
||||
long length)
|
||||
{
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag,xclass;
|
||||
int inf,i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p= *pp;
|
||||
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
if (inf & 0x80)
|
||||
{
|
||||
i=ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
const unsigned char *p;
|
||||
long len;
|
||||
int tag, xclass;
|
||||
int inf, i;
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
p = *pp;
|
||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||
if (inf & 0x80) {
|
||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tag != V_ASN1_OBJECT)
|
||||
{
|
||||
i=ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if(ret) *pp = p;
|
||||
return ret;
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return(NULL);
|
||||
if (tag != V_ASN1_OBJECT) {
|
||||
i = ASN1_R_EXPECTING_AN_OBJECT;
|
||||
goto err;
|
||||
}
|
||||
ret = c2i_ASN1_OBJECT(a, &p, len);
|
||||
if (ret)
|
||||
*pp = p;
|
||||
return ret;
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret=NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
long len)
|
||||
{
|
||||
ASN1_OBJECT *ret = NULL;
|
||||
const unsigned char *p;
|
||||
unsigned char *data;
|
||||
int i, length;
|
||||
|
||||
/* Sanity check OID encoding.
|
||||
* Need at least one content octet.
|
||||
* MSB must be clear in the last octet.
|
||||
* can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
for (i = 0; i < length; i++, p++)
|
||||
{
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Sanity check OID encoding. Need at least one content octet. MSB must
|
||||
* be clear in the last octet. can't have leading 0x80 in subidentifiers,
|
||||
* see: X.690 8.19.2
|
||||
*/
|
||||
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
|
||||
p[len - 1] & 0x80) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
/* Now 0 < len <= INT_MAX, so the cast is safe. */
|
||||
length = (int)len;
|
||||
for (i = 0; i < length; i++, p++) {
|
||||
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* only the ASN1_OBJECTs from the 'table' will have values
|
||||
* for ->sn or ->ln */
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
|
||||
{
|
||||
if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
|
||||
}
|
||||
else ret=(*a);
|
||||
/*
|
||||
* only the ASN1_OBJECTs from the 'table' will have values for ->sn or
|
||||
* ->ln
|
||||
*/
|
||||
if ((a == NULL) || ((*a) == NULL) ||
|
||||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
|
||||
if ((ret = ASN1_OBJECT_new()) == NULL)
|
||||
return (NULL);
|
||||
} else
|
||||
ret = (*a);
|
||||
|
||||
p= *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length))
|
||||
{
|
||||
ret->length=0;
|
||||
if (data != NULL) OPENSSL_free(data);
|
||||
data=(unsigned char *)OPENSSL_malloc(length);
|
||||
if (data == NULL)
|
||||
{ i=ERR_R_MALLOC_FAILURE; goto err; }
|
||||
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
memcpy(data,p,length);
|
||||
/* reattach data to object, after which it remains const */
|
||||
ret->data =data;
|
||||
ret->length=length;
|
||||
ret->sn=NULL;
|
||||
ret->ln=NULL;
|
||||
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
|
||||
p+=length;
|
||||
p = *pp;
|
||||
/* detach data from object */
|
||||
data = (unsigned char *)ret->data;
|
||||
ret->data = NULL;
|
||||
/* once detached we can change it */
|
||||
if ((data == NULL) || (ret->length < length)) {
|
||||
ret->length = 0;
|
||||
if (data != NULL)
|
||||
OPENSSL_free(data);
|
||||
data = (unsigned char *)OPENSSL_malloc(length);
|
||||
if (data == NULL) {
|
||||
i = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
}
|
||||
memcpy(data, p, length);
|
||||
/* reattach data to object, after which it remains const */
|
||||
ret->data = data;
|
||||
ret->length = length;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
|
||||
p += length;
|
||||
|
||||
if (a != NULL) (*a)=ret;
|
||||
*pp=p;
|
||||
return(ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (a != NULL)
|
||||
(*a) = ret;
|
||||
*pp = p;
|
||||
return (ret);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, i);
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
ASN1_OBJECT_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void)
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
{
|
||||
ASN1_OBJECT *ret;
|
||||
|
||||
ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(NULL);
|
||||
}
|
||||
ret->length=0;
|
||||
ret->data=NULL;
|
||||
ret->nid=0;
|
||||
ret->sn=NULL;
|
||||
ret->ln=NULL;
|
||||
ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return(ret);
|
||||
}
|
||||
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->data = NULL;
|
||||
ret->nid = 0;
|
||||
ret->sn = NULL;
|
||||
ret->ln = NULL;
|
||||
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void ASN1_OBJECT_free(ASN1_OBJECT *a)
|
||||
{
|
||||
if (a == NULL) return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
|
||||
{
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
|
||||
if (a->sn != NULL) OPENSSL_free((void *)a->sn);
|
||||
if (a->ln != NULL) OPENSSL_free((void *)a->ln);
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
|
||||
#ifndef CONST_STRICT /* disable purely for compile-time strict
|
||||
* const checking. Doing this on a "real"
|
||||
* compile will cause memory leaks */
|
||||
if (a->sn != NULL)
|
||||
OPENSSL_free((void *)a->sn);
|
||||
if (a->ln != NULL)
|
||||
OPENSSL_free((void *)a->ln);
|
||||
#endif
|
||||
a->sn=a->ln=NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
|
||||
{
|
||||
if (a->data != NULL) OPENSSL_free((void *)a->data);
|
||||
a->data=NULL;
|
||||
a->length=0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
a->sn = a->ln = NULL;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
|
||||
if (a->data != NULL)
|
||||
OPENSSL_free((void *)a->data);
|
||||
a->data = NULL;
|
||||
a->length = 0;
|
||||
}
|
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
const char *sn, const char *ln)
|
||||
{
|
||||
ASN1_OBJECT o;
|
||||
|
||||
o.sn=sn;
|
||||
o.ln=ln;
|
||||
o.data=data;
|
||||
o.nid=nid;
|
||||
o.length=len;
|
||||
o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return(OBJ_dup(&o));
|
||||
}
|
||||
o.sn = sn;
|
||||
o.ln = ln;
|
||||
o.data = data;
|
||||
o.nid = nid;
|
||||
o.length = len;
|
||||
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
|
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
|
||||
return (OBJ_dup(&o));
|
||||
}
|
||||
|
||||
+13
-6
@@ -59,12 +59,19 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
+54
-52
@@ -59,61 +59,63 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
+174
-152
@@ -56,231 +56,253 @@
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <stdlib.h> /* For bsearch */
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
|
||||
static void st_free(ASN1_STRING_TABLE *tbl);
|
||||
|
||||
/* This is the global mask for the mbstring functions: this is use to
|
||||
* mask out certain types (such as BMPString and UTF8String) because
|
||||
* certain software (e.g. Netscape) has problems with them.
|
||||
/*
|
||||
* This is the global mask for the mbstring functions: this is use to mask
|
||||
* out certain types (such as BMPString and UTF8String) because certain
|
||||
* software (e.g. Netscape) has problems with them.
|
||||
*/
|
||||
|
||||
static unsigned long global_mask = B_ASN1_UTF8STRING;
|
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask)
|
||||
{
|
||||
global_mask = mask;
|
||||
global_mask = mask;
|
||||
}
|
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void)
|
||||
{
|
||||
return global_mask;
|
||||
return global_mask;
|
||||
}
|
||||
|
||||
/* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is:
|
||||
* MASK:XXXX : a numerical mask value.
|
||||
* nobmp : Don't use BMPStrings (just Printable, T61).
|
||||
* pkix : PKIX recommendation in RFC2459.
|
||||
* utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
|
||||
* default: the default value, Printable, T61, BMP.
|
||||
/*
|
||||
* This function sets the default to various "flavours" of configuration.
|
||||
* based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
|
||||
* value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
|
||||
* recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
|
||||
* recommendation for 2004). default: the default value, Printable, T61, BMP.
|
||||
*/
|
||||
|
||||
int ASN1_STRING_set_default_mask_asc(const char *p)
|
||||
{
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
if(!strncmp(p, "MASK:", 5)) {
|
||||
if(!p[5]) return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if(*end) return 0;
|
||||
} else if(!strcmp(p, "nombstr"))
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
|
||||
else if(!strcmp(p, "pkix"))
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
|
||||
else if(!strcmp(p, "default"))
|
||||
mask = 0xFFFFFFFFL;
|
||||
else return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
unsigned long mask;
|
||||
char *end;
|
||||
if (!strncmp(p, "MASK:", 5)) {
|
||||
if (!p[5])
|
||||
return 0;
|
||||
mask = strtoul(p + 5, &end, 0);
|
||||
if (*end)
|
||||
return 0;
|
||||
} else if (!strcmp(p, "nombstr"))
|
||||
mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
|
||||
else if (!strcmp(p, "pkix"))
|
||||
mask = ~((unsigned long)B_ASN1_T61STRING);
|
||||
else if (!strcmp(p, "utf8only"))
|
||||
mask = B_ASN1_UTF8STRING;
|
||||
else if (!strcmp(p, "default"))
|
||||
mask = 0xFFFFFFFFL;
|
||||
else
|
||||
return 0;
|
||||
ASN1_STRING_set_default_mask(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The following function generates an ASN1_STRING based on limits in a table.
|
||||
* Frequently the types and length of an ASN1_STRING are restricted by a
|
||||
* corresponding OID. For example certificates and certificate requests.
|
||||
/*
|
||||
* The following function generates an ASN1_STRING based on limits in a
|
||||
* table. Frequently the types and length of an ASN1_STRING are restricted by
|
||||
* a corresponding OID. For example certificates and certificate requests.
|
||||
*/
|
||||
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
|
||||
int inlen, int inform, int nid)
|
||||
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
|
||||
const unsigned char *in, int inlen,
|
||||
int inform, int nid)
|
||||
{
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
if(!out) out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if(tbl) {
|
||||
mask = tbl->mask;
|
||||
if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask);
|
||||
if(ret <= 0) return NULL;
|
||||
return *out;
|
||||
ASN1_STRING_TABLE *tbl;
|
||||
ASN1_STRING *str = NULL;
|
||||
unsigned long mask;
|
||||
int ret;
|
||||
if (!out)
|
||||
out = &str;
|
||||
tbl = ASN1_STRING_TABLE_get(nid);
|
||||
if (tbl) {
|
||||
mask = tbl->mask;
|
||||
if (!(tbl->flags & STABLE_NO_MASK))
|
||||
mask &= global_mask;
|
||||
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
|
||||
tbl->minsize, tbl->maxsize);
|
||||
} else
|
||||
ret =
|
||||
ASN1_mbstring_copy(out, in, inlen, inform,
|
||||
DIRSTRING_TYPE & global_mask);
|
||||
if (ret <= 0)
|
||||
return NULL;
|
||||
return *out;
|
||||
}
|
||||
|
||||
/* Now the tables and helper functions for the string table:
|
||||
/*
|
||||
* Now the tables and helper functions for the string table:
|
||||
*/
|
||||
|
||||
/* size limits: this stuff is taken straight from RFC3280 */
|
||||
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
|
||||
#define ub_name 32768
|
||||
#define ub_common_name 64
|
||||
#define ub_locality_name 128
|
||||
#define ub_state_name 128
|
||||
#define ub_organization_name 64
|
||||
#define ub_organization_unit_name 64
|
||||
#define ub_title 64
|
||||
#define ub_email_address 128
|
||||
#define ub_serial_number 64
|
||||
|
||||
/* This table must be kept in NID order */
|
||||
|
||||
static const ASN1_STRING_TABLE tbl_standard[] = {
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
|
||||
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
|
||||
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
|
||||
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
|
||||
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
|
||||
0},
|
||||
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
|
||||
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
|
||||
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
|
||||
STABLE_NO_MASK},
|
||||
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
|
||||
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
|
||||
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
|
||||
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
|
||||
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
|
||||
};
|
||||
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
|
||||
const ASN1_STRING_TABLE **b)
|
||||
const ASN1_STRING_TABLE **b)
|
||||
{
|
||||
return (*a)->nid - (*b)->nid;
|
||||
return (*a)->nid - (*b)->nid;
|
||||
}
|
||||
|
||||
static int table_cmp(const void *in_a, const void *in_b)
|
||||
{
|
||||
const ASN1_STRING_TABLE *a = in_a;
|
||||
const ASN1_STRING_TABLE *b = in_b;
|
||||
return a->nid - b->nid;
|
||||
const ASN1_STRING_TABLE *a = in_a;
|
||||
const ASN1_STRING_TABLE *b = in_b;
|
||||
return a->nid - b->nid;
|
||||
}
|
||||
|
||||
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
|
||||
{
|
||||
int found;
|
||||
size_t idx;
|
||||
ASN1_STRING_TABLE *ttmp;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
fnd.nid = nid;
|
||||
int found;
|
||||
size_t idx;
|
||||
ASN1_STRING_TABLE *ttmp;
|
||||
ASN1_STRING_TABLE fnd;
|
||||
fnd.nid = nid;
|
||||
|
||||
ttmp = bsearch(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), sizeof(ASN1_STRING_TABLE), table_cmp);
|
||||
if(ttmp) return ttmp;
|
||||
if(!stable) return NULL;
|
||||
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
|
||||
if (!found) return NULL;
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
ttmp =
|
||||
bsearch(&fnd, tbl_standard,
|
||||
sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
|
||||
sizeof(ASN1_STRING_TABLE), table_cmp);
|
||||
if (ttmp)
|
||||
return ttmp;
|
||||
if (!stable)
|
||||
return NULL;
|
||||
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
|
||||
if (!found)
|
||||
return NULL;
|
||||
return sk_ASN1_STRING_TABLE_value(stable, idx);
|
||||
}
|
||||
|
||||
|
||||
int ASN1_STRING_TABLE_add(int nid,
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
long minsize, long maxsize, unsigned long mask,
|
||||
unsigned long flags)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
char new_nid = 0;
|
||||
flags &= ~STABLE_FLAGS_MALLOC;
|
||||
if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if(!stable) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
|
||||
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
|
||||
if(!tmp) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
tmp->flags = flags | STABLE_FLAGS_MALLOC;
|
||||
tmp->nid = nid;
|
||||
new_nid = 1;
|
||||
} else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
|
||||
if(minsize != -1) tmp->minsize = minsize;
|
||||
if(maxsize != -1) tmp->maxsize = maxsize;
|
||||
tmp->mask = mask;
|
||||
if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
|
||||
return 1;
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
char new_nid = 0;
|
||||
flags &= ~STABLE_FLAGS_MALLOC;
|
||||
if (!stable)
|
||||
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
|
||||
if (!stable) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
|
||||
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
|
||||
if (!tmp) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
tmp->flags = flags | STABLE_FLAGS_MALLOC;
|
||||
tmp->nid = nid;
|
||||
new_nid = 1;
|
||||
} else
|
||||
tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
|
||||
if (minsize != -1)
|
||||
tmp->minsize = minsize;
|
||||
if (maxsize != -1)
|
||||
tmp->maxsize = maxsize;
|
||||
tmp->mask = mask;
|
||||
if (new_nid)
|
||||
sk_ASN1_STRING_TABLE_push(stable, tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ASN1_STRING_TABLE_cleanup(void)
|
||||
{
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
tmp = stable;
|
||||
if(!tmp) return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
STACK_OF(ASN1_STRING_TABLE) *tmp;
|
||||
tmp = stable;
|
||||
if (!tmp)
|
||||
return;
|
||||
stable = NULL;
|
||||
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
|
||||
}
|
||||
|
||||
static void st_free(ASN1_STRING_TABLE *tbl)
|
||||
{
|
||||
if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl);
|
||||
if (tbl->flags & STABLE_FLAGS_MALLOC)
|
||||
OPENSSL_free(tbl);
|
||||
}
|
||||
|
||||
|
||||
#ifdef STRING_TABLE_TEST
|
||||
|
||||
int
|
||||
main(void)
|
||||
int main(void)
|
||||
{
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
int i, last_nid = -1;
|
||||
ASN1_STRING_TABLE *tmp;
|
||||
int i, last_nid = -1;
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
{
|
||||
if (tmp->nid < last_nid)
|
||||
{
|
||||
last_nid = 0;
|
||||
break;
|
||||
}
|
||||
last_nid = tmp->nid;
|
||||
}
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
|
||||
if (tmp->nid < last_nid) {
|
||||
last_nid = 0;
|
||||
break;
|
||||
}
|
||||
last_nid = tmp->nid;
|
||||
}
|
||||
|
||||
if (last_nid != 0)
|
||||
{
|
||||
printf("Table order OK\n");
|
||||
exit(0);
|
||||
}
|
||||
if (last_nid != 0) {
|
||||
printf("Table order OK\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
|
||||
OBJ_nid2ln(tmp->nid));
|
||||
for (tmp = tbl_standard, i = 0;
|
||||
i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
|
||||
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
|
||||
OBJ_nid2ln(tmp->nid));
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+114
-118
@@ -67,12 +67,10 @@
|
||||
|
||||
#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)
|
||||
@@ -81,141 +79,139 @@ IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
|
||||
|
||||
#if 0
|
||||
int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
|
||||
{
|
||||
if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
|
||||
return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
|
||||
a->type ,V_ASN1_UNIVERSAL));
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
if (a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
|
||||
return (i2d_ASN1_bytes((ASN1_STRING *)a, pp,
|
||||
a->type, V_ASN1_UNIVERSAL));
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
|
||||
{
|
||||
return ASN1_TIME_adj(s, t, 0, 0);
|
||||
}
|
||||
{
|
||||
return ASN1_TIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
|
||||
ts=OPENSSL_gmtime(&t,&data);
|
||||
if (ts == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec)
|
||||
{
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if((ts->tm_year >= 50) && (ts->tm_year < 150))
|
||||
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
|
||||
return NULL;
|
||||
}
|
||||
if (offset_day || offset_sec) {
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
return NULL;
|
||||
}
|
||||
if ((ts->tm_year >= 50) && (ts->tm_year < 150))
|
||||
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
|
||||
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
|
||||
}
|
||||
|
||||
int ASN1_TIME_check(ASN1_TIME *t)
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
return ASN1_GENERALIZEDTIME_check(t);
|
||||
else if (t->type == V_ASN1_UTCTIME)
|
||||
return ASN1_UTCTIME_check(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
char *str;
|
||||
int newlen;
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
if (!ASN1_TIME_check(t)) return NULL;
|
||||
if (!ASN1_TIME_check(t))
|
||||
return NULL;
|
||||
|
||||
if (!out || !*out)
|
||||
{
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new ()))
|
||||
return NULL;
|
||||
if (out) *out = ret;
|
||||
}
|
||||
else ret = *out;
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
return NULL;
|
||||
if (out)
|
||||
*out = ret;
|
||||
} else
|
||||
ret = *out;
|
||||
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME)
|
||||
{
|
||||
if(!ASN1_STRING_set(ret, t->data, t->length))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!ASN1_STRING_set(ret, t->data, t->length))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
return NULL;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
|
||||
else BUF_strlcpy(str, "20", newlen);
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
return NULL;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
/* Work out the century and prepend */
|
||||
if (t->data[0] >= '5')
|
||||
BUF_strlcpy(str, "19", newlen);
|
||||
else
|
||||
BUF_strlcpy(str, "20", newlen);
|
||||
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 0;
|
||||
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
t.flags = 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;
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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->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 == NULL) {
|
||||
time_t now_t;
|
||||
time(&now_t);
|
||||
if (OPENSSL_gmtime(&now_t, tm))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+79
-86
@@ -61,100 +61,93 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
int ASN1_TYPE_get(ASN1_TYPE *a)
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return(a->type);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
{
|
||||
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
|
||||
return (a->type);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
|
||||
{
|
||||
if (a->value.ptr != NULL)
|
||||
{
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
|
||||
}
|
||||
a->type=type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr=value;
|
||||
}
|
||||
{
|
||||
if (a->value.ptr != NULL) {
|
||||
ASN1_TYPE **tmp_a = &a;
|
||||
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
|
||||
}
|
||||
a->type = type;
|
||||
if (type == V_ASN1_BOOLEAN)
|
||||
a->value.boolean = value ? 0xff : 0;
|
||||
else
|
||||
a->value.ptr = value;
|
||||
}
|
||||
|
||||
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN))
|
||||
{
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
}
|
||||
else if (type == V_ASN1_OBJECT)
|
||||
{
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (!value || (type == V_ASN1_BOOLEAN)) {
|
||||
void *p = (void *)value;
|
||||
ASN1_TYPE_set(a, type, p);
|
||||
} else if (type == V_ASN1_OBJECT) {
|
||||
ASN1_OBJECT *odup;
|
||||
odup = OBJ_dup(value);
|
||||
if (!odup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, odup);
|
||||
} else {
|
||||
ASN1_STRING *sdup;
|
||||
sdup = ASN1_STRING_dup(value);
|
||||
if (!sdup)
|
||||
return 0;
|
||||
ASN1_TYPE_set(a, type, sdup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns 0 if they are equal, != 0 otherwise. */
|
||||
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
|
||||
{
|
||||
int result = -1;
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (!a || !b || a->type != b->type) return -1;
|
||||
if (!a || !b || a->type != b->type)
|
||||
return -1;
|
||||
|
||||
switch (a->type)
|
||||
{
|
||||
case V_ASN1_OBJECT:
|
||||
result = OBJ_cmp(a->value.object, b->value.object);
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
break;
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_NEG_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
case V_ASN1_NEG_ENUMERATED:
|
||||
case V_ASN1_BIT_STRING:
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_OTHER:
|
||||
default:
|
||||
result = ASN1_STRING_cmp((ASN1_STRING *) a->value.ptr,
|
||||
(ASN1_STRING *) b->value.ptr);
|
||||
break;
|
||||
}
|
||||
switch (a->type) {
|
||||
case V_ASN1_OBJECT:
|
||||
result = OBJ_cmp(a->value.object, b->value.object);
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
result = 0; /* They do not have content. */
|
||||
break;
|
||||
case V_ASN1_BOOLEAN:
|
||||
result = a->value.boolean - b->value.boolean;
|
||||
break;
|
||||
case V_ASN1_INTEGER:
|
||||
case V_ASN1_NEG_INTEGER:
|
||||
case V_ASN1_ENUMERATED:
|
||||
case V_ASN1_NEG_ENUMERATED:
|
||||
case V_ASN1_BIT_STRING:
|
||||
case V_ASN1_OCTET_STRING:
|
||||
case V_ASN1_SEQUENCE:
|
||||
case V_ASN1_SET:
|
||||
case V_ASN1_NUMERICSTRING:
|
||||
case V_ASN1_PRINTABLESTRING:
|
||||
case V_ASN1_T61STRING:
|
||||
case V_ASN1_VIDEOTEXSTRING:
|
||||
case V_ASN1_IA5STRING:
|
||||
case V_ASN1_UTCTIME:
|
||||
case V_ASN1_GENERALIZEDTIME:
|
||||
case V_ASN1_GRAPHICSTRING:
|
||||
case V_ASN1_VISIBLESTRING:
|
||||
case V_ASN1_GENERALSTRING:
|
||||
case V_ASN1_UNIVERSALSTRING:
|
||||
case V_ASN1_BMPSTRING:
|
||||
case V_ASN1_UTF8STRING:
|
||||
case V_ASN1_OTHER:
|
||||
default:
|
||||
result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
|
||||
(ASN1_STRING *)b->value.ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+226
-235
@@ -63,280 +63,271 @@
|
||||
#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, ERR_R_NESTED_ASN1_ERROR);
|
||||
return (NULL);
|
||||
}
|
||||
if (!ASN1_UTCTIME_check(ret)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_UTCTIME_free(ret);
|
||||
return(NULL);
|
||||
}
|
||||
return (ret);
|
||||
err:
|
||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||
M_ASN1_UTCTIME_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
|
||||
{
|
||||
static const int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
|
||||
static const int max[8]={99,12,31,23,59,59,12,59};
|
||||
char *a;
|
||||
int n,i,l,o;
|
||||
{
|
||||
static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
|
||||
static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
|
||||
char *a;
|
||||
int n, i, l, o;
|
||||
|
||||
if (d->type != V_ASN1_UTCTIME) return(0);
|
||||
l=d->length;
|
||||
a=(char *)d->data;
|
||||
o=0;
|
||||
if (d->type != V_ASN1_UTCTIME)
|
||||
return (0);
|
||||
l = d->length;
|
||||
a = (char *)d->data;
|
||||
o = 0;
|
||||
|
||||
if (l < 11) goto err;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
if ((i == 5) && ((a[o] == 'Z') ||
|
||||
(a[o] == '+') || (a[o] == '-')))
|
||||
{
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n= a[o]-'0';
|
||||
if (++o > l) goto err;
|
||||
if (l < 11)
|
||||
goto err;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
|
||||
i++;
|
||||
if (tm)
|
||||
tm->tm_sec = 0;
|
||||
break;
|
||||
}
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n=(n*10)+ a[o]-'0';
|
||||
if (++o > l) goto err;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if (++o > l)
|
||||
goto err;
|
||||
|
||||
if ((n < min[i]) || (n > max[i])) goto err;
|
||||
if (tm)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
tm->tm_year = n < 50 ? n + 100 : n;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-'))
|
||||
{
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
o++;
|
||||
if (o+4 > l) goto err;
|
||||
for (i=6; i<8; i++)
|
||||
{
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n= a[o]-'0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9')) goto err;
|
||||
n=(n*10)+ a[o]-'0';
|
||||
if ((n < min[i]) || (n > max[i])) goto err;
|
||||
if (tm)
|
||||
{
|
||||
if (i == 6)
|
||||
offset = n * 3600;
|
||||
else if (i == 7)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
return o == l;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tm->tm_year = n < 50 ? n + 100 : n;
|
||||
break;
|
||||
case 1:
|
||||
tm->tm_mon = n - 1;
|
||||
break;
|
||||
case 2:
|
||||
tm->tm_mday = n;
|
||||
break;
|
||||
case 3:
|
||||
tm->tm_hour = n;
|
||||
break;
|
||||
case 4:
|
||||
tm->tm_min = n;
|
||||
break;
|
||||
case 5:
|
||||
tm->tm_sec = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
for (i = 6; i < 8; i++) {
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = a[o] - '0';
|
||||
o++;
|
||||
if ((a[o] < '0') || (a[o] > '9'))
|
||||
goto err;
|
||||
n = (n * 10) + a[o] - '0';
|
||||
if ((n < min[i]) || (n > max[i]))
|
||||
goto err;
|
||||
if (tm) {
|
||||
if (i == 6)
|
||||
offset = n * 3600;
|
||||
else if (i == 7)
|
||||
offset += n * 60;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
|
||||
return 0;
|
||||
}
|
||||
return o == l;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
{
|
||||
return asn1_utctime_to_tm(NULL, d);
|
||||
}
|
||||
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
{
|
||||
ASN1_UTCTIME t;
|
||||
|
||||
t.type=V_ASN1_UTCTIME;
|
||||
t.length=strlen(str);
|
||||
t.data=(unsigned char *)str;
|
||||
if (ASN1_UTCTIME_check(&t))
|
||||
{
|
||||
if (s != NULL)
|
||||
{
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str,t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
t.type = V_ASN1_UTCTIME;
|
||||
t.length = strlen(str);
|
||||
t.data = (unsigned char *)str;
|
||||
if (ASN1_UTCTIME_check(&t)) {
|
||||
if (s != NULL) {
|
||||
if (!ASN1_STRING_set((ASN1_STRING *)s,
|
||||
(unsigned char *)str, t.length))
|
||||
return 0;
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
}
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
{
|
||||
return ASN1_UTCTIME_adj(s, t, 0, 0);
|
||||
}
|
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
int free_s = 0;
|
||||
int offset_day, long offset_sec)
|
||||
{
|
||||
char *p;
|
||||
struct tm *ts;
|
||||
struct tm data;
|
||||
size_t len = 20;
|
||||
int free_s = 0;
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
free_s = 1;
|
||||
s=M_ASN1_UTCTIME_new();
|
||||
}
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
if (s == NULL) {
|
||||
free_s = 1;
|
||||
s = M_ASN1_UTCTIME_new();
|
||||
}
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
ts = OPENSSL_gmtime(&t, &data);
|
||||
if (ts == NULL)
|
||||
goto err;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (offset_day || offset_sec)
|
||||
{
|
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
|
||||
goto err;
|
||||
}
|
||||
if ((ts->tm_year < 50) || (ts->tm_year >= 150))
|
||||
goto err;
|
||||
|
||||
if((ts->tm_year < 50) || (ts->tm_year >= 150))
|
||||
goto err;
|
||||
|
||||
p=(char *)s->data;
|
||||
if ((p == NULL) || ((size_t)s->length < len))
|
||||
{
|
||||
p=OPENSSL_malloc(len);
|
||||
if (p == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data=(unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
|
||||
ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
|
||||
s->length=strlen(p);
|
||||
s->type=V_ASN1_UTCTIME;
|
||||
return(s);
|
||||
err:
|
||||
if (free_s && s)
|
||||
M_ASN1_UTCTIME_free(s);
|
||||
return NULL;
|
||||
}
|
||||
p = (char *)s->data;
|
||||
if ((p == NULL) || ((size_t)s->length < len)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (s->data != NULL)
|
||||
OPENSSL_free(s->data);
|
||||
s->data = (unsigned char *)p;
|
||||
}
|
||||
|
||||
BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
|
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
|
||||
ts->tm_sec);
|
||||
s->length = strlen(p);
|
||||
s->type = V_ASN1_UTCTIME;
|
||||
return (s);
|
||||
err:
|
||||
if (free_s && s)
|
||||
M_ASN1_UTCTIME_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 (day > 0)
|
||||
return 1;
|
||||
if (day < 0)
|
||||
return -1;
|
||||
if (sec > 0)
|
||||
return 1;
|
||||
if (sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
|
||||
return -2;
|
||||
|
||||
if (day > 0)
|
||||
return 1;
|
||||
if (day < 0)
|
||||
return -1;
|
||||
if (sec > 0)
|
||||
return 1;
|
||||
if (sec < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 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
|
||||
|
||||
+159
-135
@@ -59,152 +59,176 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
+348
-355
@@ -63,16 +63,13 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* Used in asn1_mac.h.
|
||||
* TODO(davidben): Remove this once asn1_mac.h is gone or trimmed. */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c */
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
|
||||
|
||||
/* Cross-module errors from crypto/x509/asn1_gen.c.
|
||||
* TODO(davidben): Remove these once asn1_gen.c is gone. */
|
||||
/*
|
||||
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
|
||||
* these once asn1_gen.c is gone.
|
||||
*/
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
|
||||
@@ -97,414 +94,410 @@ 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;
|
||||
}
|
||||
*ptag=tag;
|
||||
*pclass=xclass;
|
||||
if (!asn1_get_length(&p,&inf,plength,(int)max)) 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;
|
||||
}
|
||||
|
||||
if (inf && !(ret & V_ASN1_CONSTRUCTED))
|
||||
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 0
|
||||
fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
|
||||
(int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
|
||||
(int)(omax+ *pp));
|
||||
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
|
||||
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
|
||||
(int)(omax + *pp));
|
||||
|
||||
#endif
|
||||
if (*plength > (omax - (p - *pp)))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
/* Set this so that even if things are not long enough
|
||||
* the values are set correctly */
|
||||
ret|=0x80;
|
||||
}
|
||||
*pp=p;
|
||||
return(ret|inf);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
return(0x80);
|
||||
}
|
||||
if (*plength > (omax - (p - *pp))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
|
||||
/*
|
||||
* Set this so that even if things are not long enough the values are
|
||||
* set correctly
|
||||
*/
|
||||
ret |= 0x80;
|
||||
}
|
||||
*pp = p;
|
||||
return (ret | inf);
|
||||
err:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
|
||||
return (0x80);
|
||||
}
|
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
|
||||
{
|
||||
const unsigned char *p= *pp;
|
||||
unsigned long ret=0;
|
||||
unsigned int i;
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
int max)
|
||||
{
|
||||
const unsigned char *p = *pp;
|
||||
unsigned long ret = 0;
|
||||
unsigned int i;
|
||||
|
||||
if (max-- < 1) return(0);
|
||||
if (*p == 0x80)
|
||||
{
|
||||
*inf=1;
|
||||
ret=0;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*inf=0;
|
||||
i= *p&0x7f;
|
||||
if (*(p++) & 0x80)
|
||||
{
|
||||
if (i > sizeof(long))
|
||||
return 0;
|
||||
if (max-- == 0) return(0);
|
||||
while (i-- > 0)
|
||||
{
|
||||
ret<<=8L;
|
||||
ret|= *(p++);
|
||||
if (max-- == 0) return(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
ret=i;
|
||||
}
|
||||
if (ret > LONG_MAX)
|
||||
return 0;
|
||||
*pp=p;
|
||||
*rl=(long)ret;
|
||||
return(1);
|
||||
}
|
||||
if (max-- < 1)
|
||||
return (0);
|
||||
if (*p == 0x80) {
|
||||
*inf = 1;
|
||||
ret = 0;
|
||||
p++;
|
||||
} else {
|
||||
*inf = 0;
|
||||
i = *p & 0x7f;
|
||||
if (*(p++) & 0x80) {
|
||||
if (i > sizeof(long))
|
||||
return 0;
|
||||
if (max-- == 0)
|
||||
return (0);
|
||||
while (i-- > 0) {
|
||||
ret <<= 8L;
|
||||
ret |= *(p++);
|
||||
if (max-- == 0)
|
||||
return (0);
|
||||
}
|
||||
} else
|
||||
ret = i;
|
||||
}
|
||||
if (ret > LONG_MAX)
|
||||
return 0;
|
||||
*pp = p;
|
||||
*rl = (long)ret;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* class 0 is constructed
|
||||
* constructed == 2 for indefinite length constructed */
|
||||
/*
|
||||
* class 0 is constructed constructed == 2 for indefinite length constructed
|
||||
*/
|
||||
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p= *pp;
|
||||
int i, ttag;
|
||||
int xclass)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, ttag;
|
||||
|
||||
i=(constructed)?V_ASN1_CONSTRUCTED:0;
|
||||
i|=(xclass&V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
|
||||
else
|
||||
{
|
||||
*(p++)=i|V_ASN1_PRIMITIVE_TAG;
|
||||
for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
|
||||
ttag = i;
|
||||
while(i-- > 0)
|
||||
{
|
||||
p[i] = tag & 0x7f;
|
||||
if(i != (ttag - 1)) p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++)=0x80;
|
||||
else
|
||||
asn1_put_length(&p,length);
|
||||
*pp=p;
|
||||
}
|
||||
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
|
||||
i |= (xclass & V_ASN1_PRIVATE);
|
||||
if (tag < 31)
|
||||
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
|
||||
else {
|
||||
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
|
||||
for (i = 0, ttag = tag; ttag > 0; i++)
|
||||
ttag >>= 7;
|
||||
ttag = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = tag & 0x7f;
|
||||
if (i != (ttag - 1))
|
||||
p[i] |= 0x80;
|
||||
tag >>= 7;
|
||||
}
|
||||
p += ttag;
|
||||
}
|
||||
if (constructed == 2)
|
||||
*(p++) = 0x80;
|
||||
else
|
||||
asn1_put_length(&p, length);
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_put_eoc(unsigned char **pp)
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
*pp = p;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void asn1_put_length(unsigned char **pp, int length)
|
||||
{
|
||||
unsigned char *p= *pp;
|
||||
int i,l;
|
||||
if (length <= 127)
|
||||
*(p++)=(unsigned char)length;
|
||||
else
|
||||
{
|
||||
l=length;
|
||||
for (i=0; l > 0; i++)
|
||||
l>>=8;
|
||||
*(p++)=i|0x80;
|
||||
l=i;
|
||||
while (i-- > 0)
|
||||
{
|
||||
p[i]=length&0xff;
|
||||
length>>=8;
|
||||
}
|
||||
p+=l;
|
||||
}
|
||||
*pp=p;
|
||||
}
|
||||
{
|
||||
unsigned char *p = *pp;
|
||||
int i, l;
|
||||
if (length <= 127)
|
||||
*(p++) = (unsigned char)length;
|
||||
else {
|
||||
l = length;
|
||||
for (i = 0; l > 0; i++)
|
||||
l >>= 8;
|
||||
*(p++) = i | 0x80;
|
||||
l = i;
|
||||
while (i-- > 0) {
|
||||
p[i] = length & 0xff;
|
||||
length >>= 8;
|
||||
}
|
||||
p += l;
|
||||
}
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag)
|
||||
{
|
||||
int ret;
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret=length;
|
||||
ret++;
|
||||
if (tag >= 31)
|
||||
{
|
||||
while (tag > 0)
|
||||
{
|
||||
tag>>=7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2)
|
||||
return ret + 3;
|
||||
ret++;
|
||||
if (length > 127)
|
||||
{
|
||||
while (length > 0)
|
||||
{
|
||||
length>>=8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
ret = length;
|
||||
ret++;
|
||||
if (tag >= 31) {
|
||||
while (tag > 0) {
|
||||
tag >>= 7;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
if (constructed == 2)
|
||||
return ret + 3;
|
||||
ret++;
|
||||
if (length > 127) {
|
||||
while (length > 0) {
|
||||
length >>= 8;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int _asn1_Finish(ASN1_const_CTX *c)
|
||||
{
|
||||
if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
|
||||
{
|
||||
if (!ASN1_const_check_infinite_end(&c->p,c->slen))
|
||||
{
|
||||
c->error=ASN1_R_MISSING_ASN1_EOS;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
if ( ((c->slen != 0) && !(c->inf & 1)) ||
|
||||
((c->slen < 0) && (c->inf & 1)))
|
||||
{
|
||||
c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
{
|
||||
if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
|
||||
if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
|
||||
c->error = ASN1_R_MISSING_ASN1_EOS;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
|
||||
c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
int asn1_Finish(ASN1_CTX *c)
|
||||
{
|
||||
return _asn1_Finish((ASN1_const_CTX *)c);
|
||||
}
|
||||
{
|
||||
return _asn1_Finish((ASN1_const_CTX *)c);
|
||||
}
|
||||
|
||||
int asn1_const_Finish(ASN1_const_CTX *c)
|
||||
{
|
||||
return _asn1_Finish(c);
|
||||
}
|
||||
{
|
||||
return _asn1_Finish(c);
|
||||
}
|
||||
|
||||
int asn1_GetSequence(ASN1_const_CTX *c, long *length)
|
||||
{
|
||||
const unsigned char *q;
|
||||
{
|
||||
const unsigned char *q;
|
||||
|
||||
q=c->p;
|
||||
c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
|
||||
*length);
|
||||
if (c->inf & 0x80)
|
||||
{
|
||||
c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
|
||||
return(0);
|
||||
}
|
||||
if (c->tag != V_ASN1_SEQUENCE)
|
||||
{
|
||||
c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
|
||||
return(0);
|
||||
}
|
||||
(*length)-=(c->p-q);
|
||||
if (c->max && (*length < 0))
|
||||
{
|
||||
c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return(0);
|
||||
}
|
||||
if (c->inf == (1|V_ASN1_CONSTRUCTED))
|
||||
c->slen= *length+ *(c->pp)-c->p;
|
||||
c->eos=0;
|
||||
return(1);
|
||||
}
|
||||
q = c->p;
|
||||
c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass),
|
||||
*length);
|
||||
if (c->inf & 0x80) {
|
||||
c->error = ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
|
||||
return (0);
|
||||
}
|
||||
if (c->tag != V_ASN1_SEQUENCE) {
|
||||
c->error = ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
|
||||
return (0);
|
||||
}
|
||||
(*length) -= (c->p - q);
|
||||
if (c->max && (*length < 0)) {
|
||||
c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return (0);
|
||||
}
|
||||
if (c->inf == (1 | V_ASN1_CONSTRUCTED))
|
||||
c->slen = *length + *(c->pp) - c->p;
|
||||
c->eos = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst,str->data,str->length))
|
||||
return 0;
|
||||
dst->flags = str->flags;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
dst->type = str->type;
|
||||
if (!ASN1_STRING_set(dst, str->data, str->length))
|
||||
return 0;
|
||||
dst->flags = str->flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret=ASN1_STRING_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret,str))
|
||||
{
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
if (!str)
|
||||
return NULL;
|
||||
ret = ASN1_STRING_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ASN1_STRING_copy(ret, str)) {
|
||||
ASN1_STRING_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data=_data;
|
||||
{
|
||||
unsigned char *c;
|
||||
const char *data = _data;
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
if (data == NULL)
|
||||
return(0);
|
||||
else
|
||||
len=strlen(data);
|
||||
}
|
||||
if ((str->length < len) || (str->data == NULL))
|
||||
{
|
||||
c=str->data;
|
||||
if (c == NULL)
|
||||
str->data=OPENSSL_malloc(len+1);
|
||||
else
|
||||
str->data=OPENSSL_realloc(c,len+1);
|
||||
if (len < 0) {
|
||||
if (data == NULL)
|
||||
return (0);
|
||||
else
|
||||
len = strlen(data);
|
||||
}
|
||||
if ((str->length < len) || (str->data == NULL)) {
|
||||
c = str->data;
|
||||
if (c == NULL)
|
||||
str->data = OPENSSL_malloc(len + 1);
|
||||
else
|
||||
str->data = OPENSSL_realloc(c, len + 1);
|
||||
|
||||
if (str->data == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
str->data=c;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
str->length=len;
|
||||
if (data != NULL)
|
||||
{
|
||||
memcpy(str->data,data,len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len]='\0';
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
if (str->data == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
str->data = c;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
str->length = len;
|
||||
if (data != NULL) {
|
||||
memcpy(str->data, data, len);
|
||||
/* an allowance for strings :-) */
|
||||
str->data[len] = '\0';
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
|
||||
{
|
||||
if (str->data)
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
{
|
||||
if (str->data)
|
||||
OPENSSL_free(str->data);
|
||||
str->data = data;
|
||||
str->length = len;
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void)
|
||||
{
|
||||
return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
|
||||
}
|
||||
|
||||
{
|
||||
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
|
||||
}
|
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type)
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
{
|
||||
ASN1_STRING *ret;
|
||||
|
||||
ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
|
||||
if (ret == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return(NULL);
|
||||
}
|
||||
ret->length=0;
|
||||
ret->type=type;
|
||||
ret->data=NULL;
|
||||
ret->flags=0;
|
||||
return(ret);
|
||||
}
|
||||
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->length = 0;
|
||||
ret->type = type;
|
||||
ret->data = NULL;
|
||||
ret->flags = 0;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void ASN1_STRING_free(ASN1_STRING *a)
|
||||
{
|
||||
if (a == NULL) return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
|
||||
OPENSSL_free(a->data);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
|
||||
{
|
||||
int i;
|
||||
{
|
||||
int i;
|
||||
|
||||
i=(a->length-b->length);
|
||||
if (i == 0)
|
||||
{
|
||||
i=memcmp(a->data,b->data,a->length);
|
||||
if (i == 0)
|
||||
return(a->type-b->type);
|
||||
else
|
||||
return(i);
|
||||
}
|
||||
else
|
||||
return(i);
|
||||
}
|
||||
i = (a->length - b->length);
|
||||
if (i == 0) {
|
||||
i = memcmp(a->data, b->data, a->length);
|
||||
if (i == 0)
|
||||
return (a->type - b->type);
|
||||
else
|
||||
return (i);
|
||||
} else
|
||||
return (i);
|
||||
}
|
||||
|
||||
int ASN1_STRING_length(const ASN1_STRING *x)
|
||||
{ return M_ASN1_STRING_length(x); }
|
||||
{
|
||||
return M_ASN1_STRING_length(x);
|
||||
}
|
||||
|
||||
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
|
||||
{ M_ASN1_STRING_length_set(x, len); return; }
|
||||
{
|
||||
M_ASN1_STRING_length_set(x, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int ASN1_STRING_type(ASN1_STRING *x)
|
||||
{ return M_ASN1_STRING_type(x); }
|
||||
{
|
||||
return M_ASN1_STRING_type(x);
|
||||
}
|
||||
|
||||
unsigned char * ASN1_STRING_data(ASN1_STRING *x)
|
||||
{ return M_ASN1_STRING_data(x); }
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
|
||||
{
|
||||
return M_ASN1_STRING_data(x);
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,6 +1,7 @@
|
||||
/* 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.
|
||||
@@ -10,7 +11,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
|
||||
@@ -63,11 +64,10 @@ 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 */ ;
|
||||
|
||||
+313
-346
@@ -60,376 +60,343 @@
|
||||
#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_parse2(BIO *bp, const unsigned char **pp, long length,
|
||||
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 int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
|
||||
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;
|
||||
|
||||
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
|
||||
p= *pp;
|
||||
tot=p+length;
|
||||
op=p-1;
|
||||
while ((p < tot) && (op < p))
|
||||
{
|
||||
op=p;
|
||||
j=ASN1_get_object(&p,&len,&tag,&xclass,length);
|
||||
|
||||
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);
|
||||
#ifdef LINT
|
||||
j=j;
|
||||
j = j;
|
||||
#endif
|
||||
if (j & 0x80)
|
||||
{
|
||||
if (BIO_puts(bp, "Error in encoding\n") <= 0)
|
||||
goto end;
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
hl=(p-op);
|
||||
length-=hl;
|
||||
/* if j == 0x21 it is a constructed indefinite length object */
|
||||
if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
|
||||
<= 0) goto end;
|
||||
if (j & 0x80) {
|
||||
if (BIO_puts(bp, "Error in encoding\n") <= 0)
|
||||
goto end;
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
hl = (p - op);
|
||||
length -= hl;
|
||||
/*
|
||||
* if j == 0x21 it is a constructed indefinite length object
|
||||
*/
|
||||
if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
|
||||
<= 0)
|
||||
goto end;
|
||||
|
||||
if (j != (V_ASN1_CONSTRUCTED | 1))
|
||||
{
|
||||
if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
|
||||
depth,(long)hl,len) <= 0)
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_printf(bp,"d=%-2d hl=%ld l=inf ",
|
||||
depth,(long)hl) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
|
||||
goto end;
|
||||
if (j & V_ASN1_CONSTRUCTED)
|
||||
{
|
||||
ep=p+len;
|
||||
if (BIO_puts(bp, "\n") <= 0) goto end;
|
||||
if (len > length)
|
||||
{
|
||||
BIO_printf(bp,
|
||||
"length is greater than %ld\n",length);
|
||||
ret=0;
|
||||
goto end;
|
||||
}
|
||||
if ((j == 0x21) && (len == 0))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
r=asn1_parse2(bp,&p,(long)(tot-p),
|
||||
offset+(p - *pp),depth+1,
|
||||
indent,dump);
|
||||
if (r == 0) { ret=0; goto end; }
|
||||
if ((r == 2) || (p >= tot)) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
while (p < ep)
|
||||
{
|
||||
r=asn1_parse2(bp,&p,(long)len,
|
||||
offset+(p - *pp),depth+1,
|
||||
indent,dump);
|
||||
if (r == 0) { ret=0; goto end; }
|
||||
}
|
||||
}
|
||||
else if (xclass != 0)
|
||||
{
|
||||
p+=len;
|
||||
if (BIO_puts(bp, "\n") <= 0) goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
nl=0;
|
||||
if ( (tag == V_ASN1_PRINTABLESTRING) ||
|
||||
(tag == V_ASN1_T61STRING) ||
|
||||
(tag == V_ASN1_IA5STRING) ||
|
||||
(tag == V_ASN1_VISIBLESTRING) ||
|
||||
(tag == V_ASN1_NUMERICSTRING) ||
|
||||
(tag == V_ASN1_UTF8STRING) ||
|
||||
(tag == V_ASN1_UTCTIME) ||
|
||||
(tag == V_ASN1_GENERALIZEDTIME))
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
if ((len > 0) &&
|
||||
BIO_write(bp,(const char *)p,(int)len)
|
||||
!= (int)len)
|
||||
goto end;
|
||||
}
|
||||
else if (tag == V_ASN1_OBJECT)
|
||||
{
|
||||
opp=op;
|
||||
if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
i2a_ASN1_OBJECT(bp,o);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (tag == V_ASN1_BOOLEAN)
|
||||
{
|
||||
int ii;
|
||||
if (j != (V_ASN1_CONSTRUCTED | 1)) {
|
||||
if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
|
||||
depth, (long)hl, len) <= 0)
|
||||
goto end;
|
||||
} else {
|
||||
if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ", depth, (long)hl) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
|
||||
goto end;
|
||||
if (j & V_ASN1_CONSTRUCTED) {
|
||||
ep = p + len;
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
if (len > length) {
|
||||
BIO_printf(bp, "length is greater than %ld\n", length);
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
if ((j == 0x21) && (len == 0)) {
|
||||
for (;;) {
|
||||
r = asn1_parse2(bp, &p, (long)(tot - p),
|
||||
offset + (p - *pp), depth + 1,
|
||||
indent, dump);
|
||||
if (r == 0) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
if ((r == 2) || (p >= tot))
|
||||
break;
|
||||
}
|
||||
} else
|
||||
while (p < ep) {
|
||||
r = asn1_parse2(bp, &p, (long)len,
|
||||
offset + (p - *pp), depth + 1,
|
||||
indent, dump);
|
||||
if (r == 0) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} else if (xclass != 0) {
|
||||
p += len;
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
} else {
|
||||
nl = 0;
|
||||
if ((tag == V_ASN1_PRINTABLESTRING) ||
|
||||
(tag == V_ASN1_T61STRING) ||
|
||||
(tag == V_ASN1_IA5STRING) ||
|
||||
(tag == V_ASN1_VISIBLESTRING) ||
|
||||
(tag == V_ASN1_NUMERICSTRING) ||
|
||||
(tag == V_ASN1_UTF8STRING) ||
|
||||
(tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
|
||||
!= (int)len)
|
||||
goto end;
|
||||
} else if (tag == V_ASN1_OBJECT) {
|
||||
opp = op;
|
||||
if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
i2a_ASN1_OBJECT(bp, o);
|
||||
} else {
|
||||
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else if (tag == V_ASN1_BOOLEAN) {
|
||||
int ii;
|
||||
|
||||
opp=op;
|
||||
ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
|
||||
if (ii < 0)
|
||||
{
|
||||
if (BIO_puts(bp, "Bad boolean\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
BIO_printf(bp,":%d",ii);
|
||||
}
|
||||
else if (tag == V_ASN1_BMPSTRING)
|
||||
{
|
||||
/* do the BMP thang */
|
||||
}
|
||||
else if (tag == V_ASN1_OCTET_STRING)
|
||||
{
|
||||
int i,printable=1;
|
||||
opp = op;
|
||||
ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
|
||||
if (ii < 0) {
|
||||
if (BIO_puts(bp, "Bad boolean\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
BIO_printf(bp, ":%d", ii);
|
||||
} else if (tag == V_ASN1_BMPSTRING) {
|
||||
/* do the BMP thang */
|
||||
} else if (tag == V_ASN1_OCTET_STRING) {
|
||||
int i, printable = 1;
|
||||
|
||||
opp=op;
|
||||
os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl);
|
||||
if (os != NULL && os->length > 0)
|
||||
{
|
||||
opp = os->data;
|
||||
/* testing whether the octet string is
|
||||
* printable */
|
||||
for (i=0; i<os->length; i++)
|
||||
{
|
||||
if (( (opp[i] < ' ') &&
|
||||
(opp[i] != '\n') &&
|
||||
(opp[i] != '\r') &&
|
||||
(opp[i] != '\t')) ||
|
||||
(opp[i] > '~'))
|
||||
{
|
||||
printable=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (printable)
|
||||
/* printable string */
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (BIO_write(bp,(const char *)opp,
|
||||
os->length) <= 0)
|
||||
goto end;
|
||||
}
|
||||
else if (!dump)
|
||||
/* not printable => print octet string
|
||||
* as hex dump */
|
||||
{
|
||||
if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
|
||||
goto end;
|
||||
for (i=0; i<os->length; i++)
|
||||
{
|
||||
if (BIO_printf(bp,"%02X"
|
||||
, opp[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* print the normal dump */
|
||||
{
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp, opp,
|
||||
((dump == -1 || dump >
|
||||
os->length)?os->length:dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl=1;
|
||||
}
|
||||
}
|
||||
if (os != NULL)
|
||||
{
|
||||
M_ASN1_OCTET_STRING_free(os);
|
||||
os=NULL;
|
||||
}
|
||||
}
|
||||
else if (tag == V_ASN1_INTEGER)
|
||||
{
|
||||
ASN1_INTEGER *bs;
|
||||
int i;
|
||||
opp = op;
|
||||
os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
|
||||
if (os != NULL && os->length > 0) {
|
||||
opp = os->data;
|
||||
/*
|
||||
* testing whether the octet string is printable
|
||||
*/
|
||||
for (i = 0; i < os->length; i++) {
|
||||
if (((opp[i] < ' ') &&
|
||||
(opp[i] != '\n') &&
|
||||
(opp[i] != '\r') &&
|
||||
(opp[i] != '\t')) || (opp[i] > '~')) {
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (printable)
|
||||
/* printable string */
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (BIO_write(bp, (const char *)opp, os->length) <= 0)
|
||||
goto end;
|
||||
} else if (!dump)
|
||||
/*
|
||||
* not printable => print octet string as hex dump
|
||||
*/
|
||||
{
|
||||
if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < os->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", opp[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else
|
||||
/* print the normal dump */
|
||||
{
|
||||
if (!nl) {
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp, opp,
|
||||
((dump == -1 || dump >
|
||||
os->length) ? os->length : dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl = 1;
|
||||
}
|
||||
}
|
||||
if (os != NULL) {
|
||||
M_ASN1_OCTET_STRING_free(os);
|
||||
os = NULL;
|
||||
}
|
||||
} else if (tag == V_ASN1_INTEGER) {
|
||||
ASN1_INTEGER *bs;
|
||||
int i;
|
||||
|
||||
opp=op;
|
||||
bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
|
||||
if (bs != NULL)
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
if (bs->type == V_ASN1_NEG_INTEGER)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i=0; i<bs->length; i++)
|
||||
{
|
||||
if (BIO_printf(bp,"%02X",
|
||||
bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0)
|
||||
{
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_puts(bp, "BAD INTEGER") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_INTEGER_free(bs);
|
||||
}
|
||||
else if (tag == V_ASN1_ENUMERATED)
|
||||
{
|
||||
ASN1_ENUMERATED *bs;
|
||||
int i;
|
||||
opp = op;
|
||||
bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
|
||||
if (bs != NULL) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (bs->type == V_ASN1_NEG_INTEGER)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < bs->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0) {
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (BIO_puts(bp, "BAD INTEGER") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_INTEGER_free(bs);
|
||||
} else if (tag == V_ASN1_ENUMERATED) {
|
||||
ASN1_ENUMERATED *bs;
|
||||
int i;
|
||||
|
||||
opp=op;
|
||||
bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
|
||||
if (bs != NULL)
|
||||
{
|
||||
if (BIO_puts(bp, ":") <= 0) goto end;
|
||||
if (bs->type == V_ASN1_NEG_ENUMERATED)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i=0; i<bs->length; i++)
|
||||
{
|
||||
if (BIO_printf(bp,"%02X",
|
||||
bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0)
|
||||
{
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_ENUMERATED_free(bs);
|
||||
}
|
||||
else if (len > 0 && dump)
|
||||
{
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp,p,
|
||||
((dump == -1 || dump > len)?len:dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl=1;
|
||||
}
|
||||
opp = op;
|
||||
bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
|
||||
if (bs != NULL) {
|
||||
if (BIO_puts(bp, ":") <= 0)
|
||||
goto end;
|
||||
if (bs->type == V_ASN1_NEG_ENUMERATED)
|
||||
if (BIO_puts(bp, "-") <= 0)
|
||||
goto end;
|
||||
for (i = 0; i < bs->length; i++) {
|
||||
if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (bs->length == 0) {
|
||||
if (BIO_puts(bp, "00") <= 0)
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
|
||||
goto end;
|
||||
}
|
||||
M_ASN1_ENUMERATED_free(bs);
|
||||
} else if (len > 0 && dump) {
|
||||
if (!nl) {
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
if (!BIO_hexdump(bp, p,
|
||||
((dump == -1 || dump > len) ? len : dump),
|
||||
dump_indent))
|
||||
goto end;
|
||||
nl = 1;
|
||||
}
|
||||
|
||||
if (!nl)
|
||||
{
|
||||
if (BIO_puts(bp, "\n") <= 0) goto end;
|
||||
}
|
||||
p+=len;
|
||||
if ((tag == V_ASN1_EOC) && (xclass == 0))
|
||||
{
|
||||
ret=2; /* End of sequence */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
length-=len;
|
||||
}
|
||||
ret=1;
|
||||
end:
|
||||
if (o != NULL) ASN1_OBJECT_free(o);
|
||||
if (os != NULL) M_ASN1_OCTET_STRING_free(os);
|
||||
*pp=p;
|
||||
return(ret);
|
||||
}
|
||||
if (!nl) {
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto end;
|
||||
}
|
||||
p += len;
|
||||
if ((tag == V_ASN1_EOC) && (xclass == 0)) {
|
||||
ret = 2; /* End of sequence */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
length -= len;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
if (o != NULL)
|
||||
ASN1_OBJECT_free(o);
|
||||
if (os != NULL)
|
||||
M_ASN1_OCTET_STRING_free(os);
|
||||
*pp = p;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
const char *ASN1_tag2str(int tag)
|
||||
{
|
||||
static const char * const tag2str[] = {
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
|
||||
};
|
||||
static const char *const tag2str[] = {
|
||||
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
|
||||
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
|
||||
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
|
||||
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
|
||||
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
|
||||
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
|
||||
*/
|
||||
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
|
||||
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
|
||||
};
|
||||
|
||||
if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
|
||||
tag &= ~0x100;
|
||||
|
||||
if(tag < 0 || tag > 30) return "(unknown)";
|
||||
return tag2str[tag];
|
||||
if (tag < 0 || tag > 30)
|
||||
return "(unknown)";
|
||||
return tag2str[tag];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/* 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;
|
||||
}
|
||||
+30
-29
@@ -59,46 +59,47 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* ASN1_ITEM versions of the above */
|
||||
|
||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
|
||||
{
|
||||
ASN1_STRING *octmp;
|
||||
ASN1_STRING *octmp;
|
||||
|
||||
if (!oct || !*oct) {
|
||||
if (!(octmp = ASN1_STRING_new ())) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (oct) *oct = octmp;
|
||||
} else octmp = *oct;
|
||||
if (!oct || !*oct) {
|
||||
if (!(octmp = ASN1_STRING_new())) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
if (oct)
|
||||
*oct = octmp;
|
||||
} else
|
||||
octmp = *oct;
|
||||
|
||||
if(octmp->data) {
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
}
|
||||
|
||||
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return octmp;
|
||||
if (octmp->data) {
|
||||
OPENSSL_free(octmp->data);
|
||||
octmp->data = NULL;
|
||||
}
|
||||
|
||||
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
if (!octmp->data) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
return octmp;
|
||||
}
|
||||
|
||||
/* Extract an ASN1 object from an ASN1_STRING */
|
||||
|
||||
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
|
||||
{
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
const unsigned char *p;
|
||||
void *ret;
|
||||
|
||||
p = oct->data;
|
||||
if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
p = oct->data;
|
||||
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+329
-348
@@ -62,53 +62,48 @@
|
||||
#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);
|
||||
@@ -119,378 +114,364 @@ static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
|
||||
|
||||
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
|
||||
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next);
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next);
|
||||
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state);
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state);
|
||||
|
||||
static const BIO_METHOD methods_asn1=
|
||||
{
|
||||
BIO_TYPE_ASN1,
|
||||
"asn1",
|
||||
asn1_bio_write,
|
||||
asn1_bio_read,
|
||||
asn1_bio_puts,
|
||||
asn1_bio_gets,
|
||||
asn1_bio_ctrl,
|
||||
asn1_bio_new,
|
||||
asn1_bio_free,
|
||||
asn1_bio_callback_ctrl,
|
||||
};
|
||||
static const BIO_METHOD methods_asn1 = {
|
||||
BIO_TYPE_ASN1,
|
||||
"asn1",
|
||||
asn1_bio_write,
|
||||
asn1_bio_read,
|
||||
asn1_bio_puts,
|
||||
asn1_bio_gets,
|
||||
asn1_bio_ctrl,
|
||||
asn1_bio_new,
|
||||
asn1_bio_free,
|
||||
asn1_bio_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_asn1(void)
|
||||
{
|
||||
return(&methods_asn1);
|
||||
}
|
||||
|
||||
{
|
||||
return (&methods_asn1);
|
||||
}
|
||||
|
||||
static int asn1_bio_new(BIO *b)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
|
||||
if (!ctx)
|
||||
return 0;
|
||||
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
b->init = 1;
|
||||
b->ptr = (char *)ctx;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
|
||||
if (!ctx)
|
||||
return 0;
|
||||
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
b->init = 1;
|
||||
b->ptr = (char *)ctx;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
|
||||
{
|
||||
ctx->buf = OPENSSL_malloc(size);
|
||||
if (!ctx->buf)
|
||||
return 0;
|
||||
ctx->bufsize = size;
|
||||
ctx->bufpos = 0;
|
||||
ctx->buflen = 0;
|
||||
ctx->copylen = 0;
|
||||
ctx->asn1_class = V_ASN1_UNIVERSAL;
|
||||
ctx->asn1_tag = V_ASN1_OCTET_STRING;
|
||||
ctx->ex_buf = 0;
|
||||
ctx->ex_pos = 0;
|
||||
ctx->ex_len = 0;
|
||||
ctx->state = ASN1_STATE_START;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
ctx->buf = OPENSSL_malloc(size);
|
||||
if (!ctx->buf)
|
||||
return 0;
|
||||
ctx->bufsize = size;
|
||||
ctx->bufpos = 0;
|
||||
ctx->buflen = 0;
|
||||
ctx->copylen = 0;
|
||||
ctx->asn1_class = V_ASN1_UNIVERSAL;
|
||||
ctx->asn1_tag = V_ASN1_OCTET_STRING;
|
||||
ctx->ex_buf = 0;
|
||||
ctx->ex_pos = 0;
|
||||
ctx->ex_len = 0;
|
||||
ctx->state = ASN1_STATE_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_free(BIO *b)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
if (ctx->buf)
|
||||
OPENSSL_free(ctx->buf);
|
||||
OPENSSL_free(ctx);
|
||||
b->init = 0;
|
||||
b->ptr = NULL;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
if (ctx->buf)
|
||||
OPENSSL_free(ctx->buf);
|
||||
OPENSSL_free(ctx);
|
||||
b->init = 0;
|
||||
b->ptr = NULL;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_write(BIO *b, const char *in , int inl)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
int wrmax, wrlen, ret;
|
||||
unsigned char *p;
|
||||
if (!in || (inl < 0) || (b->next_bio == NULL))
|
||||
return 0;
|
||||
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
static int asn1_bio_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
int wrmax, wrlen, ret;
|
||||
unsigned char *p;
|
||||
if (!in || (inl < 0) || (b->next_bio == NULL))
|
||||
return 0;
|
||||
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
|
||||
wrlen = 0;
|
||||
ret = -1;
|
||||
wrlen = 0;
|
||||
ret = -1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
switch (ctx->state)
|
||||
{
|
||||
for (;;) {
|
||||
switch (ctx->state) {
|
||||
|
||||
/* Setup prefix data, call it */
|
||||
case ASN1_STATE_START:
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
|
||||
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
|
||||
return 0;
|
||||
break;
|
||||
/* Setup prefix data, call it */
|
||||
case ASN1_STATE_START:
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
|
||||
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
/* Copy any pre data first */
|
||||
case ASN1_STATE_PRE_COPY:
|
||||
/* Copy any pre data first */
|
||||
case ASN1_STATE_PRE_COPY:
|
||||
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
|
||||
ASN1_STATE_HEADER);
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
|
||||
ASN1_STATE_HEADER);
|
||||
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ASN1_STATE_HEADER:
|
||||
ctx->buflen =
|
||||
ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
|
||||
assert(ctx->buflen <= ctx->bufsize);
|
||||
p = ctx->buf;
|
||||
ASN1_put_object(&p, 0, inl,
|
||||
ctx->asn1_tag, ctx->asn1_class);
|
||||
ctx->copylen = inl;
|
||||
ctx->state = ASN1_STATE_HEADER_COPY;
|
||||
case ASN1_STATE_HEADER:
|
||||
ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
|
||||
assert(ctx->buflen <= ctx->bufsize);
|
||||
p = ctx->buf;
|
||||
ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
|
||||
ctx->copylen = inl;
|
||||
ctx->state = ASN1_STATE_HEADER_COPY;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ASN1_STATE_HEADER_COPY:
|
||||
ret = BIO_write(b->next_bio,
|
||||
ctx->buf + ctx->bufpos, ctx->buflen);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
case ASN1_STATE_HEADER_COPY:
|
||||
ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
ctx->buflen -= ret;
|
||||
if (ctx->buflen)
|
||||
ctx->bufpos += ret;
|
||||
else
|
||||
{
|
||||
ctx->bufpos = 0;
|
||||
ctx->state = ASN1_STATE_DATA_COPY;
|
||||
}
|
||||
ctx->buflen -= ret;
|
||||
if (ctx->buflen)
|
||||
ctx->bufpos += ret;
|
||||
else {
|
||||
ctx->bufpos = 0;
|
||||
ctx->state = ASN1_STATE_DATA_COPY;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case ASN1_STATE_DATA_COPY:
|
||||
case ASN1_STATE_DATA_COPY:
|
||||
|
||||
if (inl > ctx->copylen)
|
||||
wrmax = ctx->copylen;
|
||||
else
|
||||
wrmax = inl;
|
||||
ret = BIO_write(b->next_bio, in, wrmax);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
wrlen += ret;
|
||||
ctx->copylen -= ret;
|
||||
in += ret;
|
||||
inl -= ret;
|
||||
if (inl > ctx->copylen)
|
||||
wrmax = ctx->copylen;
|
||||
else
|
||||
wrmax = inl;
|
||||
ret = BIO_write(b->next_bio, in, wrmax);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
wrlen += ret;
|
||||
ctx->copylen -= ret;
|
||||
in += ret;
|
||||
inl -= ret;
|
||||
|
||||
if (ctx->copylen == 0)
|
||||
ctx->state = ASN1_STATE_HEADER;
|
||||
if (ctx->copylen == 0)
|
||||
ctx->state = ASN1_STATE_HEADER;
|
||||
|
||||
if (inl == 0)
|
||||
goto done;
|
||||
if (inl == 0)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
default:
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
done:
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
|
||||
return (wrlen > 0) ? wrlen : ret;
|
||||
return (wrlen > 0) ? wrlen : ret;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next)
|
||||
{
|
||||
int ret;
|
||||
if (ctx->ex_len <= 0)
|
||||
return 1;
|
||||
for(;;)
|
||||
{
|
||||
ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
|
||||
ctx->ex_len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ctx->ex_len -= ret;
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->ex_pos += ret;
|
||||
else
|
||||
{
|
||||
if(cleanup)
|
||||
cleanup(b, &ctx->ex_buf, &ctx->ex_len,
|
||||
&ctx->ex_arg);
|
||||
ctx->state = next;
|
||||
ctx->ex_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
asn1_ps_func *cleanup, asn1_bio_state_t next)
|
||||
{
|
||||
int ret;
|
||||
if (ctx->ex_len <= 0)
|
||||
return 1;
|
||||
for (;;) {
|
||||
ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ctx->ex_len -= ret;
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->ex_pos += ret;
|
||||
else {
|
||||
if (cleanup)
|
||||
cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
|
||||
ctx->state = next;
|
||||
ctx->ex_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state)
|
||||
{
|
||||
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
|
||||
{
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->state = ex_state;
|
||||
else
|
||||
ctx->state = other_state;
|
||||
return 1;
|
||||
}
|
||||
asn1_ps_func *setup,
|
||||
asn1_bio_state_t ex_state,
|
||||
asn1_bio_state_t other_state)
|
||||
{
|
||||
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->ex_len > 0)
|
||||
ctx->state = ex_state;
|
||||
else
|
||||
ctx->state = other_state;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int asn1_bio_read(BIO *b, char *in , int inl)
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_read(b->next_bio, in , inl);
|
||||
}
|
||||
static int asn1_bio_read(BIO *b, char *in, int inl)
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_read(b->next_bio, in, inl);
|
||||
}
|
||||
|
||||
static int asn1_bio_puts(BIO *b, const char *str)
|
||||
{
|
||||
return asn1_bio_write(b, str, strlen(str));
|
||||
}
|
||||
{
|
||||
return asn1_bio_write(b, str, strlen(str));
|
||||
}
|
||||
|
||||
static int asn1_bio_gets(BIO *b, char *str, int size)
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_gets(b->next_bio, str , size);
|
||||
}
|
||||
{
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_gets(b->next_bio, str, size);
|
||||
}
|
||||
|
||||
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
|
||||
{
|
||||
if (b->next_bio == NULL) return(0);
|
||||
return BIO_callback_ctrl(b->next_bio,cmd,fp);
|
||||
}
|
||||
{
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
return BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
}
|
||||
|
||||
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
BIO_ASN1_EX_FUNCS *ex_func;
|
||||
long ret = 1;
|
||||
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
switch(cmd)
|
||||
{
|
||||
{
|
||||
BIO_ASN1_BUF_CTX *ctx;
|
||||
BIO_ASN1_EX_FUNCS *ex_func;
|
||||
long ret = 1;
|
||||
ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
switch (cmd) {
|
||||
|
||||
case BIO_C_SET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ctx->prefix = ex_func->ex_func;
|
||||
ctx->prefix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
case BIO_C_SET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ctx->prefix = ex_func->ex_func;
|
||||
ctx->prefix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->prefix;
|
||||
ex_func->ex_free_func = ctx->prefix_free;
|
||||
break;
|
||||
case BIO_C_GET_PREFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->prefix;
|
||||
ex_func->ex_free_func = ctx->prefix_free;
|
||||
break;
|
||||
|
||||
case BIO_C_SET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ctx->suffix = ex_func->ex_func;
|
||||
ctx->suffix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
case BIO_C_SET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ctx->suffix = ex_func->ex_func;
|
||||
ctx->suffix_free = ex_func->ex_free_func;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->suffix;
|
||||
ex_func->ex_free_func = ctx->suffix_free;
|
||||
break;
|
||||
case BIO_C_GET_SUFFIX:
|
||||
ex_func = arg2;
|
||||
ex_func->ex_func = ctx->suffix;
|
||||
ex_func->ex_free_func = ctx->suffix_free;
|
||||
break;
|
||||
|
||||
case BIO_C_SET_EX_ARG:
|
||||
ctx->ex_arg = arg2;
|
||||
break;
|
||||
case BIO_C_SET_EX_ARG:
|
||||
ctx->ex_arg = arg2;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_EX_ARG:
|
||||
*(void **)arg2 = ctx->ex_arg;
|
||||
break;
|
||||
case BIO_C_GET_EX_ARG:
|
||||
*(void **)arg2 = ctx->ex_arg;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
|
||||
/* Call post function if possible */
|
||||
if (ctx->state == ASN1_STATE_HEADER)
|
||||
{
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
|
||||
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
|
||||
return 0;
|
||||
}
|
||||
/* Call post function if possible */
|
||||
if (ctx->state == ASN1_STATE_HEADER) {
|
||||
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
|
||||
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->state == ASN1_STATE_POST_COPY)
|
||||
{
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
|
||||
ASN1_STATE_DONE);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
if (ctx->state == ASN1_STATE_POST_COPY) {
|
||||
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
|
||||
ASN1_STATE_DONE);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ctx->state == ASN1_STATE_DONE)
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
else
|
||||
{
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
if (ctx->state == ASN1_STATE_DONE)
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
else {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
|
||||
default:
|
||||
if (!b->next_bio)
|
||||
return 0;
|
||||
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int asn1_bio_set_ex(BIO *b, int cmd,
|
||||
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
extmp.ex_func = ex_func;
|
||||
extmp.ex_free_func = ex_free_func;
|
||||
return BIO_ctrl(b, cmd, 0, &extmp);
|
||||
}
|
||||
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
extmp.ex_func = ex_func;
|
||||
extmp.ex_free_func = ex_free_func;
|
||||
return BIO_ctrl(b, cmd, 0, &extmp);
|
||||
}
|
||||
|
||||
static int asn1_bio_get_ex(BIO *b, int cmd,
|
||||
asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
int ret;
|
||||
ret = BIO_ctrl(b, cmd, 0, &extmp);
|
||||
if (ret > 0)
|
||||
{
|
||||
*ex_func = extmp.ex_func;
|
||||
*ex_free_func = extmp.ex_free_func;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
asn1_ps_func **ex_func,
|
||||
asn1_ps_func **ex_free_func)
|
||||
{
|
||||
BIO_ASN1_EX_FUNCS extmp;
|
||||
int ret;
|
||||
ret = BIO_ctrl(b, cmd, 0, &extmp);
|
||||
if (ret > 0) {
|
||||
*ex_func = extmp.ex_func;
|
||||
*ex_free_func = extmp.ex_free_func;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
|
||||
}
|
||||
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
|
||||
asn1_ps_func *prefix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
|
||||
}
|
||||
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
|
||||
asn1_ps_func **pprefix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
|
||||
}
|
||||
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
|
||||
asn1_ps_func *suffix_free)
|
||||
{
|
||||
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
|
||||
}
|
||||
|
||||
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
|
||||
}
|
||||
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
|
||||
asn1_ps_func **psuffix_free)
|
||||
{
|
||||
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
|
||||
}
|
||||
|
||||
+138
-141
@@ -63,192 +63,189 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* Experimental NDEF ASN1 BIO support routines */
|
||||
|
||||
/* The usage is quite simple, initialize an ASN1 structure,
|
||||
* get a BIO from it then any data written through the BIO
|
||||
* will end up translated to approptiate format on the fly.
|
||||
* The data is streamed out and does *not* need to be
|
||||
* all held in memory at once.
|
||||
*
|
||||
* When the BIO is flushed the output is finalized and any
|
||||
* signatures etc written out.
|
||||
*
|
||||
* The BIO is a 'proper' BIO and can handle non blocking I/O
|
||||
* correctly.
|
||||
*
|
||||
* The usage is simple. The implementation is *not*...
|
||||
/*
|
||||
* The usage is quite simple, initialize an ASN1 structure, get a BIO from it
|
||||
* then any data written through the BIO will end up translated to
|
||||
* approptiate format on the fly. The data is streamed out and does *not*
|
||||
* need to be all held in memory at once. When the BIO is flushed the output
|
||||
* is finalized and any signatures etc written out. The BIO is a 'proper'
|
||||
* BIO and can handle non blocking I/O correctly. The usage is simple. The
|
||||
* implementation is *not*...
|
||||
*/
|
||||
|
||||
/* BIO support data stored in the ASN1 BIO ex_arg */
|
||||
|
||||
typedef struct ndef_aux_st
|
||||
{
|
||||
/* ASN1 structure this BIO refers to */
|
||||
ASN1_VALUE *val;
|
||||
const ASN1_ITEM *it;
|
||||
/* Top of the BIO chain */
|
||||
BIO *ndef_bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} NDEF_SUPPORT;
|
||||
typedef struct ndef_aux_st {
|
||||
/* ASN1 structure this BIO refers to */
|
||||
ASN1_VALUE *val;
|
||||
const ASN1_ITEM *it;
|
||||
/* Top of the BIO chain */
|
||||
BIO *ndef_bio;
|
||||
/* Output BIO */
|
||||
BIO *out;
|
||||
/* Boundary where content is inserted */
|
||||
unsigned char **boundary;
|
||||
/* DER buffer start */
|
||||
unsigned char *derbuf;
|
||||
} NDEF_SUPPORT;
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg);
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg);
|
||||
|
||||
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux = NULL;
|
||||
BIO *asn_bio = NULL;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!aux || !aux->asn1_cb)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
if (!aux || !aux->asn1_cb) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
|
||||
asn_bio = BIO_new(BIO_f_asn1());
|
||||
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
/* ASN1 bio needs to be next to output BIO */
|
||||
|
||||
out = BIO_push(asn_bio, out);
|
||||
out = BIO_push(asn_bio, out);
|
||||
|
||||
if (!ndef_aux || !asn_bio || !out)
|
||||
goto err;
|
||||
if (!ndef_aux || !asn_bio || !out)
|
||||
goto err;
|
||||
|
||||
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
|
||||
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
|
||||
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
|
||||
|
||||
/* Now let callback prepend any digest, cipher etc BIOs
|
||||
* ASN1 structure needs.
|
||||
*/
|
||||
/*
|
||||
* Now let callback prepend any digest, cipher etc BIOs ASN1 structure
|
||||
* needs.
|
||||
*/
|
||||
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
sarg.out = out;
|
||||
sarg.ndef_bio = NULL;
|
||||
sarg.boundary = NULL;
|
||||
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
|
||||
goto err;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
|
||||
goto err;
|
||||
|
||||
ndef_aux->val = val;
|
||||
ndef_aux->it = it;
|
||||
ndef_aux->ndef_bio = sarg.ndef_bio;
|
||||
ndef_aux->boundary = sarg.boundary;
|
||||
ndef_aux->out = out;
|
||||
ndef_aux->val = val;
|
||||
ndef_aux->it = it;
|
||||
ndef_aux->ndef_bio = sarg.ndef_bio;
|
||||
ndef_aux->boundary = sarg.boundary;
|
||||
ndef_aux->out = out;
|
||||
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
|
||||
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
|
||||
|
||||
return sarg.ndef_bio;
|
||||
return sarg.ndef_bio;
|
||||
|
||||
err:
|
||||
if (asn_bio)
|
||||
BIO_free(asn_bio);
|
||||
if (ndef_aux)
|
||||
OPENSSL_free(ndef_aux);
|
||||
return NULL;
|
||||
}
|
||||
err:
|
||||
if (asn_bio)
|
||||
BIO_free(asn_bio);
|
||||
if (ndef_aux)
|
||||
OPENSSL_free(ndef_aux);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
|
||||
*plen = *ndef_aux->boundary - *pbuf;
|
||||
*plen = *ndef_aux->boundary - *pbuf;
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
if (ndef_aux->derbuf)
|
||||
OPENSSL_free(ndef_aux->derbuf);
|
||||
if (ndef_aux->derbuf)
|
||||
OPENSSL_free(ndef_aux->derbuf);
|
||||
|
||||
ndef_aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
ndef_aux->derbuf = NULL;
|
||||
*pbuf = NULL;
|
||||
*plen = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
|
||||
if (!ndef_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pndef_aux);
|
||||
*pndef_aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
|
||||
void *parg)
|
||||
{
|
||||
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
|
||||
if (!ndef_prefix_free(b, pbuf, plen, parg))
|
||||
return 0;
|
||||
OPENSSL_free(*pndef_aux);
|
||||
*pndef_aux = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
const ASN1_AUX *aux;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
{
|
||||
NDEF_SUPPORT *ndef_aux;
|
||||
unsigned char *p;
|
||||
int derlen;
|
||||
const ASN1_AUX *aux;
|
||||
ASN1_STREAM_ARG sarg;
|
||||
|
||||
if (!parg)
|
||||
return 0;
|
||||
if (!parg)
|
||||
return 0;
|
||||
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
ndef_aux = *(NDEF_SUPPORT **)parg;
|
||||
|
||||
aux = ndef_aux->it->funcs;
|
||||
aux = ndef_aux->it->funcs;
|
||||
|
||||
/* Finalize structures */
|
||||
sarg.ndef_bio = ndef_aux->ndef_bio;
|
||||
sarg.out = ndef_aux->out;
|
||||
sarg.boundary = ndef_aux->boundary;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
|
||||
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
|
||||
return 0;
|
||||
/* Finalize structures */
|
||||
sarg.ndef_bio = ndef_aux->ndef_bio;
|
||||
sarg.out = ndef_aux->out;
|
||||
sarg.boundary = ndef_aux->boundary;
|
||||
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
|
||||
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
|
||||
return 0;
|
||||
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
|
||||
p = OPENSSL_malloc(derlen);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
ndef_aux->derbuf = p;
|
||||
*pbuf = p;
|
||||
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
|
||||
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *ndef_aux->boundary;
|
||||
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
|
||||
if (!*ndef_aux->boundary)
|
||||
return 0;
|
||||
*pbuf = *ndef_aux->boundary;
|
||||
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+128
-134
@@ -62,145 +62,139 @@
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
}
|
||||
for (j = 0; j < i; j++) {
|
||||
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F')))) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err_sl;
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if ((bufp[0] == '0') && (buf[1] == '0')) {
|
||||
bufp += 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
if (s == NULL)
|
||||
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
|
||||
i * 2);
|
||||
else
|
||||
sp = (unsigned char *)OPENSSL_realloc(s,
|
||||
(unsigned int)num +
|
||||
i * 2);
|
||||
if (sp == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = bufp[k + n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m -= '0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m = m - 'a' + 10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m = m - 'A' + 10;
|
||||
else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
ret = 1;
|
||||
err:
|
||||
if (0) {
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+131
-139
@@ -59,152 +59,144 @@
|
||||
#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;
|
||||
|
||||
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);
|
||||
}
|
||||
for (j = 0; j < i; j++) {
|
||||
if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
|
||||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
|
||||
((buf[j] >= 'A') && (buf[j] <= 'F')))) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
/*
|
||||
* We have now cleared all the crap off the end of the line
|
||||
*/
|
||||
if (i < 2)
|
||||
goto err_sl;
|
||||
|
||||
bufp = (unsigned char *)buf;
|
||||
if (first) {
|
||||
first = 0;
|
||||
if ((bufp[0] == '0') && (buf[1] == '0')) {
|
||||
bufp += 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
k = 0;
|
||||
i -= again;
|
||||
if (i % 2 != 0) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i /= 2;
|
||||
if (num + i > slen) {
|
||||
if (s == NULL)
|
||||
sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
|
||||
i * 2);
|
||||
else
|
||||
sp = OPENSSL_realloc_clean(s, slen, num + i * 2);
|
||||
if (sp == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s = sp;
|
||||
slen = num + i * 2;
|
||||
}
|
||||
for (j = 0; j < i; j++, k += 2) {
|
||||
for (n = 0; n < 2; n++) {
|
||||
m = bufp[k + n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m -= '0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m = m - 'a' + 10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m = m - 'A' + 10;
|
||||
else {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num + j] <<= 4;
|
||||
s[num + j] |= m;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
if (again)
|
||||
bufsize = BIO_gets(bp, buf, size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length = num;
|
||||
bs->data = s;
|
||||
ret = 1;
|
||||
err:
|
||||
if (0) {
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+125
-133
@@ -59,146 +59,138 @@
|
||||
#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;
|
||||
|
||||
k=0;
|
||||
i-=again;
|
||||
if (i%2 != 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
|
||||
goto err;
|
||||
}
|
||||
i/=2;
|
||||
if (num+i > slen)
|
||||
{
|
||||
if (s == NULL)
|
||||
sp=(unsigned char *)OPENSSL_malloc(
|
||||
(unsigned int)num+i*2);
|
||||
else
|
||||
sp=(unsigned char *)OPENSSL_realloc(s,
|
||||
(unsigned int)num+i*2);
|
||||
if (sp == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s=sp;
|
||||
slen=num+i*2;
|
||||
}
|
||||
for (j=0; j<i; j++,k+=2)
|
||||
{
|
||||
for (n=0; n<2; n++)
|
||||
{
|
||||
m=bufp[k+n];
|
||||
if ((m >= '0') && (m <= '9'))
|
||||
m-='0';
|
||||
else if ((m >= 'a') && (m <= 'f'))
|
||||
m=m-'a'+10;
|
||||
else if ((m >= 'A') && (m <= 'F'))
|
||||
m=m-'A'+10;
|
||||
else
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
|
||||
goto err;
|
||||
}
|
||||
s[num+j]<<=4;
|
||||
s[num+j]|=m;
|
||||
}
|
||||
}
|
||||
num+=i;
|
||||
if (again)
|
||||
bufsize=BIO_gets(bp,buf,size);
|
||||
else
|
||||
break;
|
||||
}
|
||||
bs->length=num;
|
||||
bs->data=s;
|
||||
ret=1;
|
||||
err:
|
||||
if (0)
|
||||
{
|
||||
err_sl:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
|
||||
}
|
||||
if (s != NULL)
|
||||
OPENSSL_free(s);
|
||||
return(ret);
|
||||
}
|
||||
bufp = (unsigned char *)buf;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+30
-29
@@ -60,43 +60,44 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
+45
-47
@@ -59,54 +59,52 @@
|
||||
#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 (buf[1] & 0x80)
|
||||
n++;
|
||||
else buf++;
|
||||
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]);
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
+1033
-1148
File diff suppressed because it is too large
Load Diff
+508
-544
File diff suppressed because it is too large
Load Diff
+162
-180
@@ -59,206 +59,188 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
|
||||
/* Free up an ASN1 structure */
|
||||
|
||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(&val, it, 0);
|
||||
}
|
||||
{
|
||||
asn1_item_combine_free(&val, it, 0);
|
||||
}
|
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
asn1_item_combine_free(pval, it, 0);
|
||||
}
|
||||
{
|
||||
asn1_item_combine_free(pval, it, 0);
|
||||
}
|
||||
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL, *seqtt;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
int i;
|
||||
if (!pval)
|
||||
return;
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
|
||||
return;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
switch(it->itype)
|
||||
{
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
ASN1_template_free(pval, it->templates);
|
||||
else
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
ASN1_template_free(pval, it->templates);
|
||||
else
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
ASN1_primitive_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount))
|
||||
{
|
||||
ASN1_VALUE **pchval;
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
ASN1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine)
|
||||
{
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
i = asn1_get_choice_selector(pval, it);
|
||||
if ((i >= 0) && (i < it->tcount)) {
|
||||
ASN1_VALUE **pchval;
|
||||
tt = it->templates + i;
|
||||
pchval = asn1_get_field_ptr(pval, tt);
|
||||
ASN1_template_free(pchval, tt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_free)
|
||||
cf->asn1_free(*pval);
|
||||
break;
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_free)
|
||||
cf->asn1_free(*pval);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_free)
|
||||
ef->asn1_ex_free(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (!asn1_refcount_dec_and_test_zero(pval, it))
|
||||
return;
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/* If we free up as normal we will invalidate any
|
||||
* ANY DEFINED BY field and we wont be able to
|
||||
* determine the type of the field it defines. So
|
||||
* free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount - 1;
|
||||
for (i = 0; i < it->tcount; tt--, i++)
|
||||
{
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
ASN1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine)
|
||||
{
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (!asn1_refcount_dec_and_test_zero(pval, it))
|
||||
return;
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
|
||||
if (i == 2)
|
||||
return;
|
||||
}
|
||||
asn1_enc_free(pval, it);
|
||||
/*
|
||||
* If we free up as normal we will invalidate any ANY DEFINED BY
|
||||
* field and we wont be able to determine the type of the field it
|
||||
* defines. So free up in reverse order.
|
||||
*/
|
||||
tt = it->templates + it->tcount - 1;
|
||||
for (i = 0; i < it->tcount; tt--, i++) {
|
||||
ASN1_VALUE **pseqval;
|
||||
seqtt = asn1_do_adb(pval, tt, 0);
|
||||
if (!seqtt)
|
||||
continue;
|
||||
pseqval = asn1_get_field_ptr(pval, seqtt);
|
||||
ASN1_template_free(pseqval, seqtt);
|
||||
}
|
||||
if (asn1_cb)
|
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
|
||||
if (!combine) {
|
||||
OPENSSL_free(*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
size_t i;
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK)
|
||||
{
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
|
||||
{
|
||||
ASN1_VALUE *vtmp;
|
||||
vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item),
|
||||
0);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
}
|
||||
else
|
||||
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
|
||||
tt->flags & ASN1_TFLG_COMBINE);
|
||||
}
|
||||
{
|
||||
size_t i;
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
|
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
|
||||
ASN1_VALUE *vtmp;
|
||||
vtmp = sk_ASN1_VALUE_value(sk, i);
|
||||
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
|
||||
}
|
||||
sk_ASN1_VALUE_free(sk);
|
||||
*pval = NULL;
|
||||
} else
|
||||
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
|
||||
tt->flags & ASN1_TFLG_COMBINE);
|
||||
}
|
||||
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it)
|
||||
{
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_free)
|
||||
{
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
|
||||
if (!it)
|
||||
{
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
}
|
||||
else if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
{
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
{
|
||||
int utype;
|
||||
if (it) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf;
|
||||
pf = it->funcs;
|
||||
if (pf && pf->prim_free) {
|
||||
pf->prim_free(pval, it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
|
||||
if (!it) {
|
||||
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
|
||||
utype = typ->type;
|
||||
pval = &typ->value.asn1_value;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else if (it->itype == ASN1_ITYPE_MSTRING) {
|
||||
utype = -1;
|
||||
if (!*pval)
|
||||
return;
|
||||
} else {
|
||||
utype = it->utype;
|
||||
if ((utype != V_ASN1_BOOLEAN) && !*pval)
|
||||
return;
|
||||
}
|
||||
|
||||
switch(utype)
|
||||
{
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
|
||||
break;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
case V_ASN1_BOOLEAN:
|
||||
if (it)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*(ASN1_BOOLEAN *)pval = -1;
|
||||
return;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
case V_ASN1_NULL:
|
||||
break;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
ASN1_primitive_free(pval, NULL);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
case V_ASN1_ANY:
|
||||
ASN1_primitive_free(pval, NULL);
|
||||
OPENSSL_free(*pval);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASN1_STRING_free((ASN1_STRING *)*pval);
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
default:
|
||||
ASN1_STRING_free((ASN1_STRING *)*pval);
|
||||
*pval = NULL;
|
||||
break;
|
||||
}
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
+251
-268
@@ -63,336 +63,319 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine);
|
||||
int combine);
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
ASN1_VALUE *ret = NULL;
|
||||
if (ASN1_item_ex_new(&ret, it) > 0)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate an ASN1 structure */
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
return asn1_item_ex_combine_new(pval, it, 0);
|
||||
}
|
||||
{
|
||||
return asn1_item_ex_combine_new(pval, it, 0);
|
||||
}
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
int combine)
|
||||
{
|
||||
const ASN1_TEMPLATE *tt = NULL;
|
||||
const ASN1_COMPAT_FUNCS *cf;
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
const ASN1_AUX *aux = it->funcs;
|
||||
ASN1_aux_cb *asn1_cb;
|
||||
ASN1_VALUE **pseqval;
|
||||
int i;
|
||||
if (aux && aux->asn1_cb)
|
||||
asn1_cb = aux->asn1_cb;
|
||||
else
|
||||
asn1_cb = 0;
|
||||
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_push_info(it->sname);
|
||||
if (it->sname)
|
||||
CRYPTO_push_info(it->sname);
|
||||
#endif
|
||||
|
||||
switch(it->itype)
|
||||
{
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new)
|
||||
{
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_new) {
|
||||
if (!ef->asn1_ex_new(pval, it))
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_new) {
|
||||
*pval = cf->asn1_new();
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
case ASN1_ITYPE_COMPAT:
|
||||
cf = it->funcs;
|
||||
if (cf && cf->asn1_new) {
|
||||
*pval = cf->asn1_new();
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
{
|
||||
if (!ASN1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
}
|
||||
else if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates) {
|
||||
if (!ASN1_template_new(pval, it->templates))
|
||||
goto memerr;
|
||||
} else if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
case ASN1_ITYPE_MSTRING:
|
||||
if (!ASN1_primitive_new(pval, it))
|
||||
goto memerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i==2)
|
||||
{
|
||||
case ASN1_ITYPE_CHOICE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine)
|
||||
{
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
memset(*pval, 0, it->size);
|
||||
}
|
||||
asn1_set_choice_selector(pval, -1, it);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr;
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
memset(*pval, 0, it->size);
|
||||
}
|
||||
asn1_set_choice_selector(pval, -1, it);
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb)
|
||||
{
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i==2)
|
||||
{
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE:
|
||||
case ASN1_ITYPE_SEQUENCE:
|
||||
if (asn1_cb) {
|
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
|
||||
if (!i)
|
||||
goto auxerr;
|
||||
if (i == 2) {
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine)
|
||||
{
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
memset(*pval, 0, it->size);
|
||||
asn1_refcount_set_one(pval, it);
|
||||
asn1_enc_init(pval, it);
|
||||
}
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
|
||||
{
|
||||
pseqval = asn1_get_field_ptr(pval, tt);
|
||||
if (!ASN1_template_new(pseqval, tt))
|
||||
goto memerr;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!combine) {
|
||||
*pval = OPENSSL_malloc(it->size);
|
||||
if (!*pval)
|
||||
goto memerr;
|
||||
memset(*pval, 0, it->size);
|
||||
asn1_refcount_set_one(pval, it);
|
||||
asn1_enc_init(pval, it);
|
||||
}
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
|
||||
pseqval = asn1_get_field_ptr(pval, tt);
|
||||
if (!ASN1_template_new(pseqval, tt))
|
||||
goto memerr;
|
||||
}
|
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
|
||||
goto auxerr;
|
||||
break;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname) CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
memerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ASN1_item_ex_free(pval, it);
|
||||
memerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ASN1_item_ex_free(pval, it);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname) CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
auxerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
|
||||
ASN1_item_ex_free(pval, it);
|
||||
auxerr:
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
|
||||
ASN1_item_ex_free(pval, it);
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname) CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
{
|
||||
const ASN1_EXTERN_FUNCS *ef;
|
||||
|
||||
switch(it->itype)
|
||||
{
|
||||
switch (it->itype) {
|
||||
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else *pval = NULL;
|
||||
break;
|
||||
case ASN1_ITYPE_EXTERN:
|
||||
ef = it->funcs;
|
||||
if (ef && ef->asn1_ex_clear)
|
||||
ef->asn1_ex_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_PRIMITIVE:
|
||||
if (it->templates)
|
||||
asn1_template_clear(pval, it->templates);
|
||||
else
|
||||
asn1_primitive_clear(pval, it);
|
||||
break;
|
||||
|
||||
case ASN1_ITYPE_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_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;
|
||||
}
|
||||
}
|
||||
|
||||
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int ret;
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL)
|
||||
{
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
{
|
||||
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
|
||||
int ret;
|
||||
if (tt->flags & ASN1_TFLG_OPTIONAL) {
|
||||
asn1_template_clear(pval, tt);
|
||||
return 1;
|
||||
}
|
||||
/* If ANY DEFINED BY nothing to do */
|
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK)
|
||||
{
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) {
|
||||
*pval = NULL;
|
||||
return 1;
|
||||
}
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (tt->field_name)
|
||||
CRYPTO_push_info(tt->field_name);
|
||||
if (tt->field_name)
|
||||
CRYPTO_push_info(tt->field_name);
|
||||
#endif
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK)
|
||||
{
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
|
||||
done:
|
||||
/* If SET OF or SEQUENCE OF, its a STACK */
|
||||
if (tt->flags & ASN1_TFLG_SK_MASK) {
|
||||
STACK_OF(ASN1_VALUE) *skval;
|
||||
skval = sk_ASN1_VALUE_new_null();
|
||||
if (!skval) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
*pval = (ASN1_VALUE *)skval;
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* Otherwise pass it back to the item routine */
|
||||
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
|
||||
done:
|
||||
#ifdef CRYPTO_MDEBUG
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
if (it->sname)
|
||||
CRYPTO_pop_info();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
{
|
||||
/* If ADB or STACK just NULL the field */
|
||||
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
|
||||
*pval = NULL;
|
||||
else
|
||||
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
|
||||
}
|
||||
|
||||
|
||||
/* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
/*
|
||||
* NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
* all the old functions.
|
||||
*/
|
||||
|
||||
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
{
|
||||
ASN1_TYPE *typ;
|
||||
ASN1_STRING *str;
|
||||
int utype;
|
||||
|
||||
if (!it)
|
||||
return 0;
|
||||
if (!it)
|
||||
return 0;
|
||||
|
||||
if (it->funcs)
|
||||
{
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_new)
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
if (it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_new)
|
||||
return pf->prim_new(pval, it);
|
||||
}
|
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch(utype)
|
||||
{
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
if (it->itype == ASN1_ITYPE_MSTRING)
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
switch (utype) {
|
||||
case V_ASN1_OBJECT:
|
||||
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
|
||||
return 1;
|
||||
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
case V_ASN1_BOOLEAN:
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
case V_ASN1_NULL:
|
||||
*pval = (ASN1_VALUE *)1;
|
||||
return 1;
|
||||
|
||||
case V_ASN1_ANY:
|
||||
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
|
||||
if (!typ)
|
||||
return 0;
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
case V_ASN1_ANY:
|
||||
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
|
||||
if (!typ)
|
||||
return 0;
|
||||
typ->value.ptr = NULL;
|
||||
typ->type = -1;
|
||||
*pval = (ASN1_VALUE *)typ;
|
||||
break;
|
||||
|
||||
default:
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
str = ASN1_STRING_type_new(utype);
|
||||
if (it->itype == ASN1_ITYPE_MSTRING && str)
|
||||
str->flags |= ASN1_STRING_FLAG_MSTRING;
|
||||
*pval = (ASN1_VALUE *)str;
|
||||
break;
|
||||
}
|
||||
if (*pval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs)
|
||||
{
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else *pval = NULL;
|
||||
}
|
||||
{
|
||||
int utype;
|
||||
if (it && it->funcs) {
|
||||
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
|
||||
if (pf->prim_clear)
|
||||
pf->prim_clear(pval, it);
|
||||
else
|
||||
*pval = NULL;
|
||||
return;
|
||||
}
|
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
|
||||
utype = -1;
|
||||
else
|
||||
utype = it->utype;
|
||||
if (utype == V_ASN1_BOOLEAN)
|
||||
*(ASN1_BOOLEAN *)pval = it->size;
|
||||
else
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
+437
-483
File diff suppressed because it is too large
Load Diff
+28
-21
@@ -58,20 +58,19 @@
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
|
||||
|
||||
/* Declarations for string types */
|
||||
|
||||
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
|
||||
sname *sname##_new(void) \
|
||||
{ \
|
||||
return ASN1_STRING_type_new(V_##sname); \
|
||||
} \
|
||||
void sname##_free(sname *x) \
|
||||
{ \
|
||||
ASN1_STRING_free(x); \
|
||||
}
|
||||
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
|
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
|
||||
@@ -95,12 +94,16 @@ IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
|
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY);
|
||||
|
||||
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
|
||||
/*
|
||||
* Just swallow an ASN1_SEQUENCE in an ASN1_STRING
|
||||
*/ ;
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE);
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE);
|
||||
|
||||
/* Multistring types */;
|
||||
/*
|
||||
* Multistring types
|
||||
*/ ;
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE);
|
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE);
|
||||
@@ -111,18 +114,23 @@ 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,
|
||||
@@ -131,7 +139,6 @@ 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);
|
||||
|
||||
+62
-52
@@ -59,85 +59,95 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
|
||||
/* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER as a
|
||||
* BIGNUM directly. Currently it ignores the sign which isn't a problem since all
|
||||
* BIGNUMs used are non negative and anything that looks negative is normally due
|
||||
* to an encoding error.
|
||||
/*
|
||||
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
|
||||
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
|
||||
* since all BIGNUMs used are non negative and anything that looks negative
|
||||
* is normally due to an encoding error.
|
||||
*/
|
||||
|
||||
#define BN_SENSITIVE 1
|
||||
#define BN_SENSITIVE 1
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c,
|
||||
NULL /* prim_print */,
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c,
|
||||
NULL /* prim_print */ ,
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(BIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||
ASN1_ITEM_end(BIGNUM)
|
||||
|
||||
ASN1_ITEM_start(CBIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
|
||||
ASN1_ITEM_end(CBIGNUM)
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*pval = (ASN1_VALUE *)BN_new();
|
||||
if(*pval) return 1;
|
||||
else return 0;
|
||||
*pval = (ASN1_VALUE *)BN_new();
|
||||
if (*pval)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if(!*pval) return;
|
||||
if(it->size & BN_SENSITIVE) BN_clear_free((BIGNUM *)*pval);
|
||||
else BN_free((BIGNUM *)*pval);
|
||||
*pval = NULL;
|
||||
if (!*pval)
|
||||
return;
|
||||
if (it->size & BN_SENSITIVE)
|
||||
BN_clear_free((BIGNUM *)*pval);
|
||||
else
|
||||
BN_free((BIGNUM *)*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
int pad;
|
||||
if(!*pval) return -1;
|
||||
bn = (BIGNUM *)*pval;
|
||||
/* If MSB set in an octet we need a padding byte */
|
||||
if(BN_num_bits(bn) & 0x7) pad = 0;
|
||||
else pad = 1;
|
||||
if(cont) {
|
||||
if(pad) *cont++ = 0;
|
||||
BN_bn2bin(bn, cont);
|
||||
}
|
||||
return pad + BN_num_bytes(bn);
|
||||
BIGNUM *bn;
|
||||
int pad;
|
||||
if (!*pval)
|
||||
return -1;
|
||||
bn = (BIGNUM *)*pval;
|
||||
/* If MSB set in an octet we need a padding byte */
|
||||
if (BN_num_bits(bn) & 0x7)
|
||||
pad = 0;
|
||||
else
|
||||
pad = 1;
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = 0;
|
||||
BN_bn2bin(bn, cont);
|
||||
}
|
||||
return pad + BN_num_bytes(bn);
|
||||
}
|
||||
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
if(!*pval)
|
||||
{
|
||||
if (!bn_new(pval, it))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if(!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
BIGNUM *bn;
|
||||
if (!*pval) {
|
||||
if (!bn_new(pval, it)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if (!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+97
-82
@@ -63,120 +63,135 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
/* Custom primitive type for long handling. This converts between an ASN1_INTEGER
|
||||
* and a long directly.
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
*/
|
||||
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx);
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS long_pf = {
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(LONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_ITEM_end(LONG)
|
||||
|
||||
ASN1_ITEM_start(ZLONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
|
||||
ASN1_ITEM_end(ZLONG)
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
return 1;
|
||||
*(long *)pval = it->size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
*(long *)pval = it->size;
|
||||
}
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
long ltmp;
|
||||
unsigned long utmp;
|
||||
int clen, pad, i;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)pval;
|
||||
long ltmp;
|
||||
unsigned long utmp;
|
||||
int clen, pad, i;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)pval;
|
||||
|
||||
/* use memcpy, because we may not be long aligned */
|
||||
memcpy(<mp, cp, sizeof(long));
|
||||
/* use memcpy, because we may not be long aligned */
|
||||
memcpy(<mp, cp, sizeof(long));
|
||||
|
||||
if(ltmp == it->size) return -1;
|
||||
/* Convert the long to positive: we subtract one if negative so
|
||||
* we can cleanly handle the padding if only the MSB of the leading
|
||||
* octet is set.
|
||||
*/
|
||||
if(ltmp < 0) utmp = -ltmp - 1;
|
||||
else utmp = ltmp;
|
||||
clen = BN_num_bits_word(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if(!(clen & 0x7)) pad = 1;
|
||||
else pad = 0;
|
||||
if (ltmp == it->size)
|
||||
return -1;
|
||||
/*
|
||||
* Convert the long to positive: we subtract one if negative so we can
|
||||
* cleanly handle the padding if only the MSB of the leading octet is
|
||||
* set.
|
||||
*/
|
||||
if (ltmp < 0)
|
||||
utmp = -ltmp - 1;
|
||||
else
|
||||
utmp = ltmp;
|
||||
clen = BN_num_bits_word(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if (!(clen & 0x7))
|
||||
pad = 1;
|
||||
else
|
||||
pad = 0;
|
||||
|
||||
/* Convert number of bits to number of octets */
|
||||
clen = (clen + 7) >> 3;
|
||||
/* Convert number of bits to number of octets */
|
||||
clen = (clen + 7) >> 3;
|
||||
|
||||
if(cont) {
|
||||
if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
|
||||
for(i = clen - 1; i >= 0; i--) {
|
||||
cont[i] = (unsigned char)(utmp & 0xff);
|
||||
if(ltmp < 0) cont[i] ^= 0xff;
|
||||
utmp >>= 8;
|
||||
}
|
||||
}
|
||||
return clen + pad;
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = (ltmp < 0) ? 0xff : 0;
|
||||
for (i = clen - 1; i >= 0; i--) {
|
||||
cont[i] = (unsigned char)(utmp & 0xff);
|
||||
if (ltmp < 0)
|
||||
cont[i] ^= 0xff;
|
||||
utmp >>= 8;
|
||||
}
|
||||
}
|
||||
return clen + pad;
|
||||
}
|
||||
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
int neg, i;
|
||||
long ltmp;
|
||||
unsigned long utmp = 0;
|
||||
char *cp = (char *)pval;
|
||||
if(len > (int)sizeof(long)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* Is it negative? */
|
||||
if(len && (cont[0] & 0x80)) neg = 1;
|
||||
else neg = 0;
|
||||
utmp = 0;
|
||||
for(i = 0; i < len; i++) {
|
||||
utmp <<= 8;
|
||||
if(neg) utmp |= cont[i] ^ 0xff;
|
||||
else utmp |= cont[i];
|
||||
}
|
||||
ltmp = (long)utmp;
|
||||
if(neg) {
|
||||
ltmp++;
|
||||
ltmp = -ltmp;
|
||||
}
|
||||
if(ltmp == it->size) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
memcpy(cp, <mp, sizeof(long));
|
||||
return 1;
|
||||
int neg, i;
|
||||
long ltmp;
|
||||
unsigned long utmp = 0;
|
||||
char *cp = (char *)pval;
|
||||
if (len > (int)sizeof(long)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* Is it negative? */
|
||||
if (len && (cont[0] & 0x80))
|
||||
neg = 1;
|
||||
else
|
||||
neg = 0;
|
||||
utmp = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
utmp <<= 8;
|
||||
if (neg)
|
||||
utmp |= cont[i] ^ 0xff;
|
||||
else
|
||||
utmp |= cont[i];
|
||||
}
|
||||
ltmp = (long)utmp;
|
||||
if (neg) {
|
||||
ltmp++;
|
||||
ltmp = -ltmp;
|
||||
}
|
||||
if (ltmp == it->size) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
memcpy(cp, <mp, sizeof(long));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
return BIO_printf(out, "%ld\n", *(long *)pval);
|
||||
}
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
return BIO_printf(out, "%ld\n", *(long *)pval);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,6 @@ static bool TestDecode() {
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
if (!TestEncode() ||
|
||||
!TestDecode()) {
|
||||
|
||||
@@ -412,7 +412,6 @@ static bool TestASN1() {
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
|
||||
+3
-3
@@ -100,7 +100,7 @@ static int buffer_new(BIO *bio) {
|
||||
if (ctx->ibuf == NULL) {
|
||||
goto err1;
|
||||
}
|
||||
ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->obuf == NULL) {
|
||||
goto err2;
|
||||
}
|
||||
@@ -340,13 +340,13 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
p1 = ctx->ibuf;
|
||||
p2 = ctx->obuf;
|
||||
if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
|
||||
p1 = (char *)OPENSSL_malloc(ibs);
|
||||
p1 = OPENSSL_malloc(ibs);
|
||||
if (p1 == NULL) {
|
||||
goto malloc_error;
|
||||
}
|
||||
}
|
||||
if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
|
||||
p2 = (char *)OPENSSL_malloc(obs);
|
||||
p2 = OPENSSL_malloc(obs);
|
||||
if (p2 == NULL) {
|
||||
if (p1 != ctx->ibuf) {
|
||||
OPENSSL_free(p1);
|
||||
|
||||
+4
-21
@@ -56,6 +56,8 @@
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -311,27 +313,8 @@ int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (dif > 0 && rp != ap) {
|
||||
memcpy(rp, ap, sizeof(*rp) * dif);
|
||||
}
|
||||
|
||||
r->top = max;
|
||||
|
||||
@@ -91,7 +91,6 @@ $code=<<___;
|
||||
#endif
|
||||
|
||||
.global bn_mul_mont
|
||||
.hidden bn_mul_mont
|
||||
.type bn_mul_mont,%function
|
||||
|
||||
.align 5
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
/* x86_64 BIGNUM accelerator version 0.1, December 2002.
|
||||
*
|
||||
* Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
|
||||
@@ -56,7 +50,13 @@
|
||||
* machine.
|
||||
*/
|
||||
|
||||
/* TODO(davidben): Get this file working on Windows x64. */
|
||||
#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"
|
||||
|
||||
|
||||
#undef mul
|
||||
#undef mul_add
|
||||
@@ -220,7 +220,6 @@ 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;
|
||||
@@ -246,65 +245,6 @@ 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) */
|
||||
@@ -596,4 +536,4 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
#endif /* !NO_ASM && X86_64 && !WINDOWS */
|
||||
#endif /* !NO_ASM && X86_64 && __GNUC__ */
|
||||
|
||||
@@ -1770,6 +1770,15 @@ 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
|
||||
@@ -3116,6 +3125,15 @@ 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
|
||||
@@ -3159,13 +3177,11 @@ my ($rptr,$nptr)=("%rdx","%rbp");
|
||||
my @ri=map("%r$_",(10..13));
|
||||
my @ni=map("%r$_",(14..15));
|
||||
$code.=<<___;
|
||||
xor %rbx,%rbx
|
||||
xor %ebx,%ebx
|
||||
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
|
||||
|
||||
+4
-5
@@ -166,11 +166,10 @@ void BN_clear(BIGNUM *bn) {
|
||||
}
|
||||
|
||||
const BIGNUM *BN_value_one(void) {
|
||||
static const BN_ULONG data_one = 1;
|
||||
static const BIGNUM const_one = {(BN_ULONG *)&data_one, 1, 1, 0,
|
||||
BN_FLG_STATIC_DATA};
|
||||
static const BN_ULONG kOneLimbs[1] = { 1 };
|
||||
static const BIGNUM kOne = STATIC_BIGNUM(kOneLimbs);
|
||||
|
||||
return &const_one;
|
||||
return &kOne;
|
||||
}
|
||||
|
||||
void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
|
||||
@@ -296,7 +295,7 @@ BIGNUM *bn_wexpand(BIGNUM *bn, size_t words) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * words);
|
||||
a = OPENSSL_malloc(sizeof(BN_ULONG) * words);
|
||||
if (a == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
|
||||
+9
-22
@@ -18,7 +18,7 @@
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
CBS child;
|
||||
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
|
||||
CBS_len(&child) == 0) {
|
||||
@@ -42,7 +42,7 @@ int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
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) {
|
||||
@@ -58,7 +58,7 @@ int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) {
|
||||
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);
|
||||
@@ -66,28 +66,15 @@ int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) {
|
||||
}
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* The number must be padded with a leading zero if the high bit would
|
||||
* otherwise be set (or |bn| is zero). */
|
||||
if (BN_num_bits(bn) % 8 == 0 &&
|
||||
!CBB_add_u8(&child, 0x00)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *out;
|
||||
if (!CBB_add_space(&child, &out, BN_num_bytes(bn))) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
BN_bn2bin(bn, out);
|
||||
if (!CBB_flush(cbb)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+55
-34
@@ -330,6 +330,13 @@ int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
|
||||
BIGNUM *raw = NULL;
|
||||
int ret = BN_hex2bn(&raw, in);
|
||||
out->reset(raw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_add(FILE *fp) {
|
||||
ScopedBIGNUM a(BN_new());
|
||||
ScopedBIGNUM b(BN_new());
|
||||
@@ -1107,6 +1114,27 @@ static bool test_mod_exp(FILE *fp, BN_CTX *ctx) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Regression test for carry propagation bug in sqr8x_reduction.
|
||||
if (!HexToBIGNUM(&a, "050505050505") ||
|
||||
!HexToBIGNUM(&b, "02") ||
|
||||
!HexToBIGNUM(
|
||||
&c,
|
||||
"4141414141414141414141274141414141414141414141414141414141414141"
|
||||
"4141414141414141414141414141414141414141414141414141414141414141"
|
||||
"4141414141414141414141800000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000001") ||
|
||||
!BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) ||
|
||||
!BN_mul(e.get(), a.get(), a.get(), ctx)) {
|
||||
return false;
|
||||
}
|
||||
if (BN_cmp(d.get(), e.get()) != 0) {
|
||||
fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1288,23 +1316,23 @@ static bool test_exp(FILE *fp, BN_CTX *ctx) {
|
||||
|
||||
// test_exp_mod_zero tests that 1**0 mod 1 == 0.
|
||||
static bool test_exp_mod_zero(void) {
|
||||
ScopedBIGNUM zero(BN_new());
|
||||
if (!zero) {
|
||||
ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new());
|
||||
if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) {
|
||||
return false;
|
||||
}
|
||||
BN_zero(zero.get());
|
||||
|
||||
ScopedBN_CTX ctx(BN_CTX_new());
|
||||
ScopedBIGNUM r(BN_new());
|
||||
if (!ctx || !r ||
|
||||
!BN_mod_exp(r.get(), BN_value_one(), zero.get(), BN_value_one(), ctx.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BN_is_zero(r.get())) {
|
||||
fprintf(stderr, "1**0 mod 1 = ");
|
||||
BN_print_fp(stderr, r.get());
|
||||
fprintf(stderr, ", should be 0\n");
|
||||
if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) ||
|
||||
!BN_is_zero(r.get()) ||
|
||||
!BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr,
|
||||
nullptr) ||
|
||||
!BN_is_zero(r.get()) ||
|
||||
!BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(),
|
||||
nullptr, nullptr) ||
|
||||
!BN_is_zero(r.get()) ||
|
||||
!BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr,
|
||||
nullptr) ||
|
||||
!BN_is_zero(r.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1545,13 +1573,6 @@ static bool test_dec2bn(BN_CTX *ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
|
||||
BIGNUM *raw = NULL;
|
||||
int ret = BN_hex2bn(&raw, in);
|
||||
out->reset(raw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_hex2bn(BN_CTX *ctx) {
|
||||
ScopedBIGNUM bn;
|
||||
int ret = HexToBIGNUM(&bn, "0");
|
||||
@@ -1778,8 +1799,8 @@ static const ASN1InvalidTest kASN1InvalidTests[] = {
|
||||
{"\x02\x00", 2},
|
||||
};
|
||||
|
||||
// kASN1BuggyTests are incorrect encodings and how |BN_cbs2unsigned_buggy|
|
||||
// should interpret them.
|
||||
// kASN1BuggyTests contains incorrect encodings and the corresponding, expected
|
||||
// results of |BN_parse_asn1_unsigned_buggy| given that input.
|
||||
static const ASN1Test kASN1BuggyTests[] = {
|
||||
// Negative numbers.
|
||||
{"128", "\x02\x01\x80", 3},
|
||||
@@ -1802,7 +1823,7 @@ static bool test_asn1() {
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (!BN_cbs2unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
if (!BN_parse_asn1_unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1817,7 +1838,7 @@ static bool test_asn1() {
|
||||
size_t der_len;
|
||||
CBB_zero(&cbb);
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
!BN_bn2cbb(&cbb, bn.get()) ||
|
||||
!BN_marshal_asn1(&cbb, bn.get()) ||
|
||||
!CBB_finish(&cbb, &der, &der_len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return false;
|
||||
@@ -1829,9 +1850,9 @@ static bool test_asn1() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// |BN_cbs2unsigned_buggy| parses all valid input.
|
||||
// |BN_parse_asn1_unsigned_buggy| parses all valid input.
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (!BN_cbs2unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
if (!BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
|
||||
fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1848,16 +1869,16 @@ static bool test_asn1() {
|
||||
}
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (BN_cbs2unsigned(&cbs, bn.get())) {
|
||||
if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
|
||||
fprintf(stderr, "Parsed invalid input.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// All tests in kASN1InvalidTests are also rejected by
|
||||
// |BN_cbs2unsigned_buggy|.
|
||||
// |BN_parse_asn1_unsigned_buggy|.
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (BN_cbs2unsigned_buggy(&cbs, bn.get())) {
|
||||
if (BN_parse_asn1_unsigned_buggy(&cbs, bn.get())) {
|
||||
fprintf(stderr, "Parsed invalid input.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1865,7 +1886,7 @@ static bool test_asn1() {
|
||||
}
|
||||
|
||||
for (const ASN1Test &test : kASN1BuggyTests) {
|
||||
// These broken encodings are rejected by |BN_cbs2unsigned|.
|
||||
// These broken encodings are rejected by |BN_parse_asn1_unsigned|.
|
||||
ScopedBIGNUM bn(BN_new());
|
||||
if (!bn) {
|
||||
return false;
|
||||
@@ -1873,20 +1894,20 @@ static bool test_asn1() {
|
||||
|
||||
CBS cbs;
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (BN_cbs2unsigned(&cbs, bn.get())) {
|
||||
if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
|
||||
fprintf(stderr, "Parsed invalid input.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// However |BN_cbs2unsigned_buggy| accepts them.
|
||||
// However |BN_parse_asn1_unsigned_buggy| accepts them.
|
||||
ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii);
|
||||
if (!bn2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
|
||||
if (!BN_cbs2unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
|
||||
if (!BN_parse_asn1_unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
|
||||
fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1905,7 +1926,7 @@ static bool test_asn1() {
|
||||
CBB cbb;
|
||||
CBB_zero(&cbb);
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
BN_bn2cbb(&cbb, bn.get())) {
|
||||
BN_marshal_asn1(&cbb, bn.get())) {
|
||||
fprintf(stderr, "Serialized negative number.\n");
|
||||
CBB_cleanup(&cbb);
|
||||
return false;
|
||||
|
||||
+9
-4
@@ -63,6 +63,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
@@ -195,6 +196,11 @@ int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
|
||||
uint8_t *ptr;
|
||||
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
|
||||
}
|
||||
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
|
||||
char *BN_bn2hex(const BIGNUM *bn) {
|
||||
@@ -202,7 +208,7 @@ char *BN_bn2hex(const BIGNUM *bn) {
|
||||
char *buf;
|
||||
char *p;
|
||||
|
||||
buf = (char *)OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
|
||||
buf = OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
@@ -379,9 +385,8 @@ char *BN_bn2dec(const BIGNUM *a) {
|
||||
*/
|
||||
i = BN_num_bits(a) * 3;
|
||||
num = i / 10 + i / 1000 + 1 + 1;
|
||||
bn_data =
|
||||
(BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
|
||||
buf = (char *)OPENSSL_malloc(num + 3);
|
||||
bn_data = OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
|
||||
buf = OPENSSL_malloc(num + 3);
|
||||
if ((buf == NULL) || (bn_data == NULL)) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
|
||||
+6
-26
@@ -260,10 +260,10 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
q = BN_MASK2;
|
||||
} else {
|
||||
/* n0 < d0 */
|
||||
#ifdef BN_LLONG
|
||||
#ifdef BN_ULLONG
|
||||
BN_ULLONG t2;
|
||||
|
||||
#if defined(BN_LLONG) && !defined(div_asm)
|
||||
#if defined(BN_ULLONG) && !defined(div_asm)
|
||||
q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
|
||||
#else
|
||||
q = div_asm(n0, n1, d0);
|
||||
@@ -288,34 +288,14 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
}
|
||||
t2 -= d1;
|
||||
}
|
||||
#else /* !BN_LLONG */
|
||||
#else /* !BN_ULLONG */
|
||||
BN_ULONG t2l, t2h;
|
||||
|
||||
#if defined(div_asm)
|
||||
q = div_asm(n0, n1, d0);
|
||||
#else
|
||||
q = bn_div_words(n0, n1, d0);
|
||||
#endif
|
||||
|
||||
#ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
#endif
|
||||
|
||||
#if defined(BN_UMULT_LOHI)
|
||||
BN_UMULT_LOHI(t2l, t2h, d1, q);
|
||||
#elif defined(BN_UMULT_HIGH)
|
||||
t2l = d1 * q;
|
||||
t2h = BN_UMULT_HIGH(d1, q);
|
||||
#else
|
||||
{
|
||||
BN_ULONG ql, qh;
|
||||
t2l = LBITS(d1);
|
||||
t2h = HBITS(d1);
|
||||
ql = LBITS(q);
|
||||
qh = HBITS(q);
|
||||
mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
|
||||
@@ -331,7 +311,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
}
|
||||
t2l -= d1;
|
||||
}
|
||||
#endif /* !BN_LLONG */
|
||||
#endif /* !BN_ULLONG */
|
||||
}
|
||||
|
||||
l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
|
||||
@@ -601,7 +581,7 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) {
|
||||
}
|
||||
|
||||
BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
|
||||
#ifndef BN_LLONG
|
||||
#ifndef BN_ULLONG
|
||||
BN_ULONG ret = 0;
|
||||
#else
|
||||
BN_ULLONG ret = 0;
|
||||
@@ -614,7 +594,7 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
|
||||
|
||||
w &= BN_MASK2;
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
#ifndef BN_LLONG
|
||||
#ifndef BN_ULLONG
|
||||
ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w;
|
||||
ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
|
||||
#else
|
||||
|
||||
+22
-13
@@ -445,8 +445,12 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
bits = BN_num_bits(p);
|
||||
|
||||
if (bits == 0) {
|
||||
ret = BN_one(r);
|
||||
return ret;
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(r);
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
@@ -632,8 +636,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
}
|
||||
bits = BN_num_bits(p);
|
||||
if (bits == 0) {
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(rr);
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
@@ -875,8 +883,12 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
|
||||
bits = BN_num_bits(p);
|
||||
if (bits == 0) {
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(rr);
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
@@ -942,7 +954,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
|
||||
if ((powerbufFree = OPENSSL_malloc(
|
||||
powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
@@ -1230,17 +1242,14 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
ret = 1;
|
||||
BN_zero(rr);
|
||||
} else {
|
||||
ret = BN_one(rr);
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
return BN_one(rr);
|
||||
}
|
||||
if (a == 0) {
|
||||
BN_zero(rr);
|
||||
ret = 1;
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
+1
-1
@@ -279,7 +279,7 @@ BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
|
||||
* sign*Y*a == A (mod |n|).
|
||||
*/
|
||||
|
||||
if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) {
|
||||
if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS2 <= 32 ? 450 : 2048))) {
|
||||
/* Binary inversion algorithm; requires odd modulus.
|
||||
* This is faster than the general algorithm if the modulus
|
||||
* is sufficiently small (about 400 .. 500 bits on 32-bit
|
||||
|
||||
+15
-257
@@ -61,21 +61,12 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
/* Generic implementations of most operations are needed for:
|
||||
* - Configurations without inline assembly.
|
||||
* - Architectures other than x86 or x86_64.
|
||||
* - Windows x84_64; x86_64-gcc.c does not build on MSVC. */
|
||||
/* This file has two other implementations: x86 assembly language in
|
||||
* asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */
|
||||
#if defined(OPENSSL_NO_ASM) || \
|
||||
(!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || \
|
||||
(defined(OPENSSL_X86_64) && defined(OPENSSL_WINDOWS))
|
||||
!(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
#define alloca _alloca
|
||||
#else
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#ifdef BN_LLONG
|
||||
#ifdef BN_ULLONG
|
||||
#define mul_add(r, a, w, c) \
|
||||
{ \
|
||||
BN_ULLONG t; \
|
||||
@@ -100,7 +91,8 @@
|
||||
(r1) = Hw(t); \
|
||||
}
|
||||
|
||||
#elif defined(BN_UMULT_LOHI)
|
||||
#else
|
||||
|
||||
#define mul_add(r, a, w, c) \
|
||||
{ \
|
||||
BN_ULONG high, low, ret, tmp = (a); \
|
||||
@@ -130,101 +122,7 @@
|
||||
BN_UMULT_LOHI(r0, r1, tmp, tmp); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*************************************************************
|
||||
* No long long type
|
||||
*/
|
||||
|
||||
#define LBITS(a) ((a) & BN_MASK2l)
|
||||
#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
|
||||
#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
|
||||
|
||||
#define LLBITS(a) ((a) & BN_MASKl)
|
||||
#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
|
||||
#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
|
||||
|
||||
#define mul64(l, h, bl, bh) \
|
||||
{ \
|
||||
BN_ULONG m, m1, lt, ht; \
|
||||
\
|
||||
lt = l; \
|
||||
ht = h; \
|
||||
m = (bh) * (lt); \
|
||||
lt = (bl) * (lt); \
|
||||
m1 = (bl) * (ht); \
|
||||
ht = (bh) * (ht); \
|
||||
m = (m + m1) & BN_MASK2; \
|
||||
if (m < m1) \
|
||||
ht += L2HBITS((BN_ULONG)1); \
|
||||
ht += HBITS(m); \
|
||||
m1 = L2HBITS(m); \
|
||||
lt = (lt + m1) & BN_MASK2; \
|
||||
if (lt < m1) \
|
||||
ht++; \
|
||||
(l) = lt; \
|
||||
(h) = ht; \
|
||||
}
|
||||
|
||||
#define sqr64(lo, ho, in) \
|
||||
{ \
|
||||
BN_ULONG l, h, m; \
|
||||
\
|
||||
h = (in); \
|
||||
l = LBITS(h); \
|
||||
h = HBITS(h); \
|
||||
m = (l) * (h); \
|
||||
l *= l; \
|
||||
h *= h; \
|
||||
h += (m & BN_MASK2h1) >> (BN_BITS4 - 1); \
|
||||
m = (m & BN_MASK2l) << (BN_BITS4 + 1); \
|
||||
l = (l + m) & BN_MASK2; \
|
||||
if (l < m) \
|
||||
h++; \
|
||||
(lo) = l; \
|
||||
(ho) = h; \
|
||||
}
|
||||
|
||||
#define mul_add(r, a, bl, bh, c) \
|
||||
{ \
|
||||
BN_ULONG l, h; \
|
||||
\
|
||||
h = (a); \
|
||||
l = LBITS(h); \
|
||||
h = HBITS(h); \
|
||||
mul64(l, h, (bl), (bh)); \
|
||||
\
|
||||
/* non-multiply part */ \
|
||||
l = (l + (c)) & BN_MASK2; \
|
||||
if (l < (c)) \
|
||||
h++; \
|
||||
(c) = (r); \
|
||||
l = (l + (c)) & BN_MASK2; \
|
||||
if (l < (c)) \
|
||||
h++; \
|
||||
(c) = h & BN_MASK2; \
|
||||
(r) = l; \
|
||||
}
|
||||
|
||||
#define mul(r, a, bl, bh, c) \
|
||||
{ \
|
||||
BN_ULONG l, h; \
|
||||
\
|
||||
h = (a); \
|
||||
l = LBITS(h); \
|
||||
h = HBITS(h); \
|
||||
mul64(l, h, (bl), (bh)); \
|
||||
\
|
||||
/* non-multiply part */ \
|
||||
l += (c); \
|
||||
if ((l & BN_MASK2) < (c)) \
|
||||
h++; \
|
||||
(c) = h & BN_MASK2; \
|
||||
(r) = l & BN_MASK2; \
|
||||
}
|
||||
#endif /* !BN_LLONG */
|
||||
|
||||
#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
|
||||
#endif /* !BN_ULLONG */
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w) {
|
||||
@@ -304,95 +202,7 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w) {
|
||||
BN_ULONG c = 0;
|
||||
BN_ULONG bl, bh;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0) {
|
||||
return (BN_ULONG)0;
|
||||
}
|
||||
|
||||
bl = LBITS(w);
|
||||
bh = HBITS(w);
|
||||
|
||||
while (num & ~3) {
|
||||
mul_add(rp[0], ap[0], bl, bh, c);
|
||||
mul_add(rp[1], ap[1], bl, bh, c);
|
||||
mul_add(rp[2], ap[2], bl, bh, c);
|
||||
mul_add(rp[3], ap[3], bl, bh, c);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
while (num) {
|
||||
mul_add(rp[0], ap[0], bl, bh, c);
|
||||
ap++;
|
||||
rp++;
|
||||
num--;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
|
||||
BN_ULONG carry = 0;
|
||||
BN_ULONG bl, bh;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0) {
|
||||
return (BN_ULONG)0;
|
||||
}
|
||||
|
||||
bl = LBITS(w);
|
||||
bh = HBITS(w);
|
||||
|
||||
while (num & ~3) {
|
||||
mul(rp[0], ap[0], bl, bh, carry);
|
||||
mul(rp[1], ap[1], bl, bh, carry);
|
||||
mul(rp[2], ap[2], bl, bh, carry);
|
||||
mul(rp[3], ap[3], bl, bh, carry);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
while (num) {
|
||||
mul(rp[0], ap[0], bl, bh, carry);
|
||||
ap++;
|
||||
rp++;
|
||||
num--;
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
assert(n >= 0);
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (n & ~3) {
|
||||
sqr64(r[0], r[1], a[0]);
|
||||
sqr64(r[2], r[3], a[1]);
|
||||
sqr64(r[4], r[5], a[2]);
|
||||
sqr64(r[6], r[7], a[3]);
|
||||
a += 4;
|
||||
r += 8;
|
||||
n -= 4;
|
||||
}
|
||||
while (n) {
|
||||
sqr64(r[0], r[1], a[0]);
|
||||
a++;
|
||||
r += 2;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(defined(BN_LLONG) || defined(BN_UMULT_HIGH)) */
|
||||
|
||||
#if defined(BN_LLONG)
|
||||
#if defined(BN_ULLONG)
|
||||
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
return (BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2) | l) / (BN_ULLONG)d);
|
||||
@@ -470,9 +280,9 @@ BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !defined(BN_LLONG) */
|
||||
#endif /* !defined(BN_ULLONG) */
|
||||
|
||||
#ifdef BN_LLONG
|
||||
#ifdef BN_ULLONG
|
||||
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n) {
|
||||
BN_ULLONG ll = 0;
|
||||
@@ -512,7 +322,7 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
return (BN_ULONG)ll;
|
||||
}
|
||||
|
||||
#else /* !BN_LLONG */
|
||||
#else /* !BN_ULLONG */
|
||||
|
||||
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n) {
|
||||
@@ -569,7 +379,7 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
return (BN_ULONG)c;
|
||||
}
|
||||
|
||||
#endif /* !BN_LLONG */
|
||||
#endif /* !BN_ULLONG */
|
||||
|
||||
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n) {
|
||||
@@ -631,7 +441,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
|
||||
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
|
||||
|
||||
#ifdef BN_LLONG
|
||||
#ifdef BN_ULLONG
|
||||
|
||||
/* Keep in mind that additions to multiplication result can not overflow,
|
||||
* because its high half cannot be all-ones. */
|
||||
@@ -679,7 +489,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#elif defined(BN_UMULT_LOHI)
|
||||
#else
|
||||
|
||||
/* Keep in mind that additions to hi can not overflow, because the high word of
|
||||
* a multiplication result cannot be all-ones. */
|
||||
@@ -722,59 +532,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
#else /* !BN_LLONG */
|
||||
|
||||
/* Keep in mind that additions to hi can not overflow, because
|
||||
* the high word of a multiplication result cannot be all-ones. */
|
||||
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
|
||||
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
|
||||
mul64(lo, hi, bl, bh); \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG tt; \
|
||||
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
|
||||
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
|
||||
mul64(lo, hi, bl, bh); \
|
||||
tt = hi; \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
tt++; \
|
||||
c1 = (c1 + tt) & BN_MASK2; \
|
||||
if (c1 < tt) \
|
||||
c2++; \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG lo, hi; \
|
||||
sqr64(lo, hi, (a)[i]); \
|
||||
c0 = (c0 + lo) & BN_MASK2; \
|
||||
if (c0 < lo) \
|
||||
hi++; \
|
||||
c1 = (c1 + hi) & BN_MASK2; \
|
||||
if (c1 < hi) \
|
||||
c2++; \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
#endif /* !BN_LLONG */
|
||||
#endif /* !BN_ULLONG */
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
+29
-87
@@ -125,13 +125,15 @@
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#pragma warning(push, 3)
|
||||
#include <intrin.h>
|
||||
#pragma warning(pop)
|
||||
#pragma intrinsic(__umulh, _umul128)
|
||||
#endif
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -144,53 +146,48 @@ BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
/* MSVC doesn't support two-word integers on 64-bit. */
|
||||
#define BN_LLONG __int128_t
|
||||
#define BN_ULLONG __uint128_t
|
||||
#define BN_ULLONG uint128_t
|
||||
#endif
|
||||
|
||||
#define BN_BITS 128
|
||||
#define BN_BITS2 64
|
||||
#define BN_BYTES 8
|
||||
#define BN_BITS4 32
|
||||
#define BN_MASK (0xffffffffffffffffffffffffffffffffLL)
|
||||
#define BN_MASK2 (0xffffffffffffffffL)
|
||||
#define BN_MASK2l (0xffffffffL)
|
||||
#define BN_MASK2h (0xffffffff00000000L)
|
||||
#define BN_MASK2h1 (0xffffffff80000000L)
|
||||
#define BN_TBIT (0x8000000000000000L)
|
||||
#define BN_MASK2 (0xffffffffffffffffUL)
|
||||
#define BN_MASK2l (0xffffffffUL)
|
||||
#define BN_MASK2h (0xffffffff00000000UL)
|
||||
#define BN_MASK2h1 (0xffffffff80000000UL)
|
||||
#define BN_TBIT (0x8000000000000000UL)
|
||||
#define BN_DEC_CONV (10000000000000000000UL)
|
||||
#define BN_DEC_NUM 19
|
||||
#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo)
|
||||
|
||||
#elif defined(OPENSSL_32_BIT)
|
||||
|
||||
#define BN_LLONG int64_t
|
||||
#define BN_ULLONG uint64_t
|
||||
#define BN_MASK (0xffffffffffffffffLL)
|
||||
#define BN_BITS 64
|
||||
#define BN_BITS2 32
|
||||
#define BN_BYTES 4
|
||||
#define BN_BITS4 16
|
||||
#define BN_MASK2 (0xffffffffL)
|
||||
#define BN_MASK2l (0xffff)
|
||||
#define BN_MASK2h1 (0xffff8000L)
|
||||
#define BN_MASK2h (0xffff0000L)
|
||||
#define BN_TBIT (0x80000000L)
|
||||
#define BN_DEC_CONV (1000000000L)
|
||||
#define BN_MASK2 (0xffffffffUL)
|
||||
#define BN_MASK2l (0xffffUL)
|
||||
#define BN_MASK2h1 (0xffff8000UL)
|
||||
#define BN_MASK2h (0xffff0000UL)
|
||||
#define BN_TBIT (0x80000000UL)
|
||||
#define BN_DEC_CONV (1000000000UL)
|
||||
#define BN_DEC_NUM 9
|
||||
#define TOBN(hi, lo) lo, hi
|
||||
|
||||
#else
|
||||
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
|
||||
#endif
|
||||
|
||||
/* Pentium pro 16,16,16,32,64 */
|
||||
/* Alpha 16,16,16,16.64 */
|
||||
#define BN_MULL_SIZE_NORMAL (16) /* 32 */
|
||||
#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 less than */
|
||||
#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */
|
||||
#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
|
||||
#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */
|
||||
|
||||
#if defined(BN_LLONG)
|
||||
#define STATIC_BIGNUM(x) \
|
||||
{ \
|
||||
(BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG), \
|
||||
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
|
||||
}
|
||||
|
||||
#if defined(BN_ULLONG)
|
||||
#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
|
||||
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
|
||||
#endif
|
||||
@@ -220,67 +217,12 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
|
||||
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
const BN_ULONG *np, const BN_ULONG *n0, int num);
|
||||
|
||||
#if !defined(BN_LLONG)
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
#endif
|
||||
|
||||
#define LBITS(a) ((a) & BN_MASK2l)
|
||||
#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
|
||||
#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
|
||||
|
||||
#define LLBITS(a) ((a) & BN_MASKl)
|
||||
#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
|
||||
#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
|
||||
|
||||
#define mul64(l, h, bl, bh) \
|
||||
{ \
|
||||
BN_ULONG m, m1, lt, ht; \
|
||||
\
|
||||
lt = l; \
|
||||
ht = h; \
|
||||
m = (bh) * (lt); \
|
||||
lt = (bl) * (lt); \
|
||||
m1 = (bl) * (ht); \
|
||||
ht = (bh) * (ht); \
|
||||
m = (m + m1) & BN_MASK2; \
|
||||
if (m < m1) \
|
||||
ht += L2HBITS((BN_ULONG)1); \
|
||||
ht += HBITS(m); \
|
||||
m1 = L2HBITS(m); \
|
||||
lt = (lt + m1) & BN_MASK2; \
|
||||
if (lt < m1) \
|
||||
ht++; \
|
||||
(l) = lt; \
|
||||
(h) = ht; \
|
||||
}
|
||||
|
||||
#endif /* !defined(BN_LLONG) */
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
|
||||
# if defined(__GNUC__) && __GNUC__ >= 2
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret,discard; \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(discard),"=d"(ret) \
|
||||
: "a"(a), "g"(b) \
|
||||
: "cc"); \
|
||||
ret; })
|
||||
# define BN_UMULT_LOHI(low,high,a,b) \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(low),"=d"(high) \
|
||||
: "a"(a),"g"(b) \
|
||||
: "cc");
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
# define BN_UMULT_HIGH(a, b) __umulh((a), (b))
|
||||
# define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
# endif
|
||||
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64)
|
||||
# if defined(__GNUC__) && __GNUC__>=2
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret; \
|
||||
__asm__ ("umulh %0,%1,%2" \
|
||||
: "=r"(ret) \
|
||||
: "r"(a), "r"(b)); \
|
||||
ret; })
|
||||
# endif
|
||||
#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
|
||||
#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+5
-11
@@ -134,7 +134,6 @@ BN_MONT_CTX *BN_MONT_CTX_new(void) {
|
||||
memset(ret, 0, sizeof(BN_MONT_CTX));
|
||||
BN_init(&ret->RR);
|
||||
BN_init(&ret->N);
|
||||
BN_init(&ret->Ni);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -146,7 +145,6 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont) {
|
||||
|
||||
BN_free(&mont->RR);
|
||||
BN_free(&mont->N);
|
||||
BN_free(&mont->Ni);
|
||||
OPENSSL_free(mont);
|
||||
}
|
||||
|
||||
@@ -156,11 +154,9 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) {
|
||||
}
|
||||
|
||||
if (!BN_copy(&to->RR, &from->RR) ||
|
||||
!BN_copy(&to->N, &from->N) ||
|
||||
!BN_copy(&to->Ni, &from->Ni)) {
|
||||
!BN_copy(&to->N, &from->N)) {
|
||||
return NULL;
|
||||
}
|
||||
to->ri = from->ri;
|
||||
to->n0[0] = from->n0[0];
|
||||
to->n0[1] = from->n0[1];
|
||||
return to;
|
||||
@@ -193,8 +189,6 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
|
||||
tmod.dmax = 2;
|
||||
tmod.neg = 0;
|
||||
|
||||
mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
|
||||
|
||||
#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
|
||||
/* Only certain BN_BITS2<=32 platforms actually make use of
|
||||
* n0[1], and we could use the #else case (with a shorter R
|
||||
@@ -278,9 +272,10 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
|
||||
mont->n0[1] = 0;
|
||||
#endif
|
||||
|
||||
/* setup RR for conversions */
|
||||
/* RR = (2^ri)^2 == 2^(ri*2) == 1 << (ri*2), which has its (ri*2)th bit set. */
|
||||
int ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
|
||||
BN_zero(&(mont->RR));
|
||||
if (!BN_set_bit(&(mont->RR), mont->ri * 2)) {
|
||||
if (!BN_set_bit(&(mont->RR), ri * 2)) {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
|
||||
@@ -422,11 +417,10 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
|
||||
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
|
||||
{
|
||||
BIGNUM *n;
|
||||
BN_ULONG *ap,*np,*rp,n0,v,carry;
|
||||
int nl,max,i;
|
||||
|
||||
n= (BIGNUM*) &(mont->N);
|
||||
const BIGNUM *n = &mont->N;
|
||||
nl=n->top;
|
||||
if (nl == 0) { ret->top=0; return(1); }
|
||||
|
||||
|
||||
+6
-26
@@ -62,6 +62,10 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#define BN_MUL_RECURSIVE_SIZE_NORMAL 16
|
||||
#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL
|
||||
|
||||
|
||||
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
|
||||
BN_ULONG *rr;
|
||||
|
||||
@@ -107,31 +111,6 @@ void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
|
||||
bn_mul_words(r, a, n, b[0]);
|
||||
|
||||
for (;;) {
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[1]), a, n, b[1]);
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[2]), a, n, b[2]);
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[3]), a, n, b[3]);
|
||||
if (--n <= 0) {
|
||||
return;
|
||||
}
|
||||
bn_mul_add_words(&(r[4]), a, n, b[4]);
|
||||
r += 4;
|
||||
b += 4;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
|
||||
/* Here follows specialised variants of bn_add_words() and bn_sub_words(). They
|
||||
* have the property performing operations on arrays of different sizes. The
|
||||
@@ -618,7 +597,8 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
|
||||
static const int kMulNormalSize = 16;
|
||||
if (al >= kMulNormalSize && bl >= kMulNormalSize) {
|
||||
if (i >= -1 && i <= 1) {
|
||||
/* Find out the power of two lower or equal
|
||||
to the longest of the two numbers */
|
||||
|
||||
+21
-28
@@ -48,6 +48,9 @@
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* See crypto/bn/asm/rsaz-avx2.pl for further details.
|
||||
*/
|
||||
@@ -58,42 +61,30 @@ void rsaz_1024_scatter5_avx2(void *tbl,const void *val,int i);
|
||||
void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i);
|
||||
void rsaz_1024_red2norm_avx2(void *norm,const void *red);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define ALIGN64 __attribute__((aligned(64)))
|
||||
#elif defined(_MSC_VER)
|
||||
# define ALIGN64 __declspec(align(64))
|
||||
#elif defined(__SUNPRO_C)
|
||||
# define ALIGN64
|
||||
# pragma align 64(one,two80)
|
||||
#else
|
||||
# define ALIGN64 /* not fatal, might hurt performance a little */
|
||||
#endif
|
||||
|
||||
ALIGN64 static const BN_ULONG one[40] =
|
||||
alignas(64) static const BN_ULONG one[40] =
|
||||
{1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
ALIGN64 static const BN_ULONG two80[40] =
|
||||
alignas(64) static const BN_ULONG two80[40] =
|
||||
{0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
|
||||
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0)
|
||||
{
|
||||
unsigned char storage[320*3+32*9*16+64]; /* 5.5KB */
|
||||
unsigned char *p_str = storage + (64-((size_t)storage%64));
|
||||
alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */
|
||||
unsigned char *a_inv, *m, *result,
|
||||
*table_s = p_str+320*3,
|
||||
*table_s = storage + (320 * 3),
|
||||
*R2 = table_s; /* borrow */
|
||||
int index;
|
||||
int wvalue;
|
||||
|
||||
if ((((size_t)p_str&4095)+320)>>12) {
|
||||
result = p_str;
|
||||
a_inv = p_str + 320;
|
||||
m = p_str + 320*2; /* should not cross page */
|
||||
if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) {
|
||||
result = storage;
|
||||
a_inv = storage + 320;
|
||||
m = storage + (320 * 2); /* should not cross page */
|
||||
} else {
|
||||
m = p_str; /* should not cross page */
|
||||
result = p_str + 320;
|
||||
a_inv = p_str + 320*2;
|
||||
m = storage; /* should not cross page */
|
||||
result = storage + 320;
|
||||
a_inv = storage + (320 * 2);
|
||||
}
|
||||
|
||||
rsaz_1024_norm2red_avx2(m, m_norm);
|
||||
@@ -224,8 +215,9 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
rsaz_1024_scatter5_avx2(table_s,result,31);
|
||||
#endif
|
||||
|
||||
const uint8_t *p_str = (const uint8_t *)exponent;
|
||||
|
||||
/* load first window */
|
||||
p_str = (unsigned char*)exponent;
|
||||
wvalue = p_str[127] >> 3;
|
||||
rsaz_1024_gather5_avx2(result,table_s,wvalue);
|
||||
|
||||
@@ -235,7 +227,7 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
|
||||
|
||||
rsaz_1024_sqr_avx2(result, result, m, k0, 5);
|
||||
|
||||
wvalue = *((unsigned short*)&p_str[index/8]);
|
||||
wvalue = *((const unsigned short*)&p_str[index / 8]);
|
||||
wvalue = (wvalue>> (index%8)) & 31;
|
||||
index-=5;
|
||||
|
||||
@@ -274,11 +266,10 @@ void RSAZ_512_mod_exp(BN_ULONG result[8],
|
||||
const BN_ULONG base[8], const BN_ULONG exponent[8],
|
||||
const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8])
|
||||
{
|
||||
unsigned char storage[16*8*8+64*2+64]; /* 1.2KB */
|
||||
unsigned char *table = storage + (64-((size_t)storage%64));
|
||||
alignas(64) uint8_t storage[(16*8*8) + (64 * 2)]; /* 1.2KB */
|
||||
unsigned char *table = storage;
|
||||
BN_ULONG *a_inv = (BN_ULONG *)(table+16*8*8),
|
||||
*temp = (BN_ULONG *)(table+16*8*8+8*8);
|
||||
unsigned char *p_str = (unsigned char*)exponent;
|
||||
int index;
|
||||
unsigned int wvalue;
|
||||
|
||||
@@ -300,6 +291,8 @@ void RSAZ_512_mod_exp(BN_ULONG result[8],
|
||||
for (index=3; index<16; index++)
|
||||
rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index);
|
||||
|
||||
const uint8_t *p_str = (const uint8_t *)exponent;
|
||||
|
||||
/* load first window */
|
||||
wvalue = p_str[63];
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ add_library(
|
||||
|
||||
OBJECT
|
||||
|
||||
asn1_compat.c
|
||||
ber.c
|
||||
cbs.c
|
||||
cbb.c
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
/* 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
|
||||
@@ -12,6 +12,40 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
/* This header is linked to under the names of several headers that have been
|
||||
* removed. It's possible to put a #error in here in order to catch that an
|
||||
* clean up older code. */
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
assert(cbb->base->can_resize);
|
||||
|
||||
uint8_t *der;
|
||||
size_t der_len;
|
||||
if (!CBB_finish(cbb, &der, &der_len)) {
|
||||
CBB_cleanup(cbb);
|
||||
return -1;
|
||||
}
|
||||
if (der_len > INT_MAX) {
|
||||
OPENSSL_free(der);
|
||||
return -1;
|
||||
}
|
||||
if (outp != NULL) {
|
||||
if (*outp == NULL) {
|
||||
*outp = der;
|
||||
der = NULL;
|
||||
} else {
|
||||
memcpy(*outp, der, der_len);
|
||||
*outp += der_len;
|
||||
}
|
||||
}
|
||||
OPENSSL_free(der);
|
||||
return (int)der_len;
|
||||
}
|
||||
+129
-88
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
@@ -24,11 +25,36 @@
|
||||
* input could otherwise cause the stack to overflow. */
|
||||
static const unsigned kMaxDepth = 2048;
|
||||
|
||||
/* is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
* ignores the constructed bit. */
|
||||
static int is_string_type(unsigned tag) {
|
||||
if ((tag & 0xc0) != 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (tag & 0x1f) {
|
||||
case CBS_ASN1_BITSTRING:
|
||||
case CBS_ASN1_OCTETSTRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T16STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
case CBS_ASN1_VISIBLESTRING:
|
||||
case CBS_ASN1_GENERALSTRING:
|
||||
case CBS_ASN1_UNIVERSALSTRING:
|
||||
case CBS_ASN1_BMPSTRING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
* depending on whether an indefinite length element was found. The value of
|
||||
* |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
|
||||
* and zero on error. */
|
||||
static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
* depending on whether an indefinite length element or constructed string was
|
||||
* found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
* |*ber_found| was set) and zero on error. */
|
||||
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
CBS in;
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
@@ -49,10 +75,16 @@ static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
if (CBS_len(&contents) == header_len &&
|
||||
header_len > 0 &&
|
||||
CBS_data(&contents)[header_len-1] == 0x80) {
|
||||
/* Found an indefinite-length element. */
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (is_string_type(tag)) {
|
||||
/* Constructed strings are only legal in BER and require conversion. */
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (!CBS_skip(&contents, header_len) ||
|
||||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
|
||||
return 0;
|
||||
@@ -63,16 +95,6 @@ static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is_primitive_type returns true if |tag| likely a primitive type. Normally
|
||||
* one can just test the "constructed" bit in the tag but, in BER, even
|
||||
* primitive tags can have the constructed bit if they have indefinite
|
||||
* length. */
|
||||
static char is_primitive_type(unsigned tag) {
|
||||
return (tag & 0xc0) == 0 &&
|
||||
(tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
|
||||
(tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
|
||||
}
|
||||
|
||||
/* is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
* |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
@@ -81,111 +103,86 @@ static char is_eoc(size_t header_len, CBS *contents) {
|
||||
}
|
||||
|
||||
/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
* |squash_header| is set then the top-level of elements from |in| will not
|
||||
* have their headers written. This is used when concatenating the fragments of
|
||||
* an indefinite length, primitive value. If |looking_for_eoc| is set then any
|
||||
* EOC elements found will cause the function to return after consuming it.
|
||||
* It returns one on success and zero on error. */
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
|
||||
* |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
* constructed bit and primitive element bodies are written to |out| without
|
||||
* element headers. This is used when concatenating the fragments of a
|
||||
* constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
* will cause the function to return after consuming it. It returns one on
|
||||
* success and zero on error. */
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
char looking_for_eoc, unsigned depth) {
|
||||
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (CBS_len(in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag;
|
||||
unsigned tag, child_string_tag = string_tag;
|
||||
size_t header_len;
|
||||
CBB *out_contents, out_contents_storage;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
|
||||
if (CBS_len(&contents) == header_len) {
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
}
|
||||
|
||||
if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
/* This is an indefinite length element. If it's a SEQUENCE or SET then
|
||||
* we just need to write the out the contents as normal, but with a
|
||||
* concrete length prefix.
|
||||
*
|
||||
* If it's a something else then the contents will be a series of BER
|
||||
* elements of the same type which need to be concatenated. */
|
||||
const char context_specific = (tag & 0xc0) == 0x80;
|
||||
char squash_child_headers = is_primitive_type(tag);
|
||||
|
||||
/* This is a hack, but it sufficies to handle NSS's output. If we find
|
||||
* an indefinite length, context-specific tag with a definite, primitive
|
||||
* tag inside it, then we assume that the context-specific tag is
|
||||
* implicit and the tags within are fragments of a primitive type that
|
||||
* need to be concatenated. */
|
||||
if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
|
||||
CBS in_copy, inner_contents;
|
||||
unsigned inner_tag;
|
||||
size_t inner_header_len;
|
||||
|
||||
CBS_init(&in_copy, CBS_data(in), CBS_len(in));
|
||||
if (!CBS_get_any_ber_asn1_element(&in_copy, &inner_contents,
|
||||
&inner_tag, &inner_header_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CBS_len(&inner_contents) > inner_header_len &&
|
||||
is_primitive_type(inner_tag)) {
|
||||
squash_child_headers = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!squash_header) {
|
||||
unsigned out_tag = tag;
|
||||
if (squash_child_headers) {
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (!cbs_convert_ber(in, out_contents,
|
||||
squash_child_headers,
|
||||
1 /* looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
if (out_contents != out && !CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
}
|
||||
|
||||
if (!squash_header) {
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
|
||||
if (string_tag != 0) {
|
||||
/* This is part of a constructed string. All elements must match
|
||||
* |string_tag| up to the constructed bit and get appended to |out|
|
||||
* without a child element. */
|
||||
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
} else {
|
||||
unsigned out_tag = tag;
|
||||
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
|
||||
/* If a constructed string, clear the constructed bit and inform
|
||||
* children to concatenate bodies. */
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
child_string_tag = out_tag;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (CBS_len(&contents) == header_len && header_len > 0 &&
|
||||
CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
/* This is an indefinite length element. */
|
||||
if (!cbs_convert_ber(in, out_contents, child_string_tag,
|
||||
1 /* looking for eoc */, depth + 1) ||
|
||||
!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CBS_skip(&contents, header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
|
||||
/* Recurse into children. */
|
||||
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
|
||||
0 /* not looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Copy primitive contents as-is. */
|
||||
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
|
||||
CBS_len(&contents))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_contents != out && !CBB_flush(out)) {
|
||||
if (!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -209,13 +206,57 @@ int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!CBB_init(&cbb, CBS_len(in))) {
|
||||
return 0;
|
||||
}
|
||||
if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
|
||||
if (!CBB_init(&cbb, CBS_len(in)) ||
|
||||
!cbs_convert_ber(in, &cbb, 0, 0, 0) ||
|
||||
!CBB_finish(&cbb, out, out_len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CBB_finish(&cbb, out, out_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
|
||||
unsigned outer_tag, unsigned inner_tag) {
|
||||
assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(is_string_type(inner_tag));
|
||||
|
||||
if (CBS_peek_asn1_tag(in, outer_tag)) {
|
||||
/* Normal implicitly-tagged string. */
|
||||
*out_storage = NULL;
|
||||
return CBS_get_asn1(in, out, outer_tag);
|
||||
}
|
||||
|
||||
/* Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
* |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
* of nesting. */
|
||||
CBB result;
|
||||
CBS child;
|
||||
if (!CBB_init(&result, CBS_len(in)) ||
|
||||
!CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (CBS_len(&child) > 0) {
|
||||
CBS chunk;
|
||||
if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
|
||||
!CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&result, &data, &len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS_init(out, data, len);
|
||||
*out_storage = data;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
CBB_cleanup(&result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#if !defined(__STDC_CONSTANT_MACROS)
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -22,7 +26,6 @@
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
#include "../test/scoped_types.h"
|
||||
|
||||
|
||||
@@ -341,12 +344,14 @@ static bool TestCBBPrefixed() {
|
||||
size_t buf_len;
|
||||
CBB cbb, contents, inner_contents, inner_inner_contents;
|
||||
|
||||
if (!CBB_init(&cbb, 0)) {
|
||||
return false;
|
||||
}
|
||||
if (!CBB_add_u8_length_prefixed(&cbb, &contents) ||
|
||||
if (!CBB_init(&cbb, 0) ||
|
||||
CBB_len(&cbb) != 0 ||
|
||||
!CBB_add_u8_length_prefixed(&cbb, &contents) ||
|
||||
!CBB_add_u8_length_prefixed(&cbb, &contents) ||
|
||||
!CBB_add_u8(&contents, 1) ||
|
||||
CBB_len(&contents) != 1 ||
|
||||
!CBB_flush(&cbb) ||
|
||||
CBB_len(&cbb) != 3 ||
|
||||
!CBB_add_u16_length_prefixed(&cbb, &contents) ||
|
||||
!CBB_add_u16(&contents, 0x203) ||
|
||||
!CBB_add_u24_length_prefixed(&cbb, &contents) ||
|
||||
@@ -574,7 +579,7 @@ static bool TestBerConvert() {
|
||||
static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
|
||||
static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
|
||||
|
||||
// kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
|
||||
// kOctetStringBER contains an indefinite length OCTET STRING with two parts.
|
||||
// These parts need to be concatenated in DER form.
|
||||
static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
|
||||
0x04, 0x02, 2, 3, 0x00, 0x00};
|
||||
@@ -604,6 +609,16 @@ static bool TestBerConvert() {
|
||||
0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
|
||||
};
|
||||
|
||||
// kConstructedStringBER contains a deeply-nested constructed OCTET STRING.
|
||||
// The BER conversion collapses this to one level deep, but not completely.
|
||||
static const uint8_t kConstructedStringBER[] = {
|
||||
0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01,
|
||||
0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03,
|
||||
};
|
||||
static const uint8_t kConstructedStringDER[] = {
|
||||
0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03,
|
||||
};
|
||||
|
||||
return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
|
||||
kSimpleBER, sizeof(kSimpleBER)) &&
|
||||
DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
|
||||
@@ -612,7 +627,59 @@ static bool TestBerConvert() {
|
||||
sizeof(kOctetStringDER), kOctetStringBER,
|
||||
sizeof(kOctetStringBER)) &&
|
||||
DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
|
||||
sizeof(kNSSBER));
|
||||
sizeof(kNSSBER)) &&
|
||||
DoBerConvert("kConstructedStringBER", kConstructedStringDER,
|
||||
sizeof(kConstructedStringDER), kConstructedStringBER,
|
||||
sizeof(kConstructedStringBER));
|
||||
}
|
||||
|
||||
struct ImplicitStringTest {
|
||||
const char *in;
|
||||
size_t in_len;
|
||||
bool ok;
|
||||
const char *out;
|
||||
size_t out_len;
|
||||
};
|
||||
|
||||
static const ImplicitStringTest kImplicitStringTests[] = {
|
||||
// A properly-encoded string.
|
||||
{"\x80\x03\x61\x61\x61", 5, true, "aaa", 3},
|
||||
// An implicit-tagged string.
|
||||
{"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3},
|
||||
// |CBS_get_asn1_implicit_string| only accepts one level deep of nesting.
|
||||
{"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr,
|
||||
0},
|
||||
// The outer tag must match.
|
||||
{"\x81\x03\x61\x61\x61", 5, false, nullptr, 0},
|
||||
{"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0},
|
||||
// The inner tag must match.
|
||||
{"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0},
|
||||
};
|
||||
|
||||
static bool TestImplicitString() {
|
||||
for (const auto &test : kImplicitStringTests) {
|
||||
uint8_t *storage = nullptr;
|
||||
CBS in, out;
|
||||
CBS_init(&in, reinterpret_cast<const uint8_t *>(test.in), test.in_len);
|
||||
int ok = CBS_get_asn1_implicit_string(&in, &out, &storage,
|
||||
CBS_ASN1_CONTEXT_SPECIFIC | 0,
|
||||
CBS_ASN1_OCTETSTRING);
|
||||
ScopedOpenSSLBytes scoper(storage);
|
||||
|
||||
if (static_cast<bool>(ok) != test.ok) {
|
||||
fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n",
|
||||
ok ? "succeeded" : "failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ok && (CBS_len(&out) != test.out_len ||
|
||||
memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
|
||||
fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ASN1Uint64Test {
|
||||
@@ -627,9 +694,9 @@ static const ASN1Uint64Test kASN1Uint64Tests[] = {
|
||||
{127, "\x02\x01\x7f", 3},
|
||||
{128, "\x02\x02\x00\x80", 4},
|
||||
{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
|
||||
{OPENSSL_U64(0x0102030405060708),
|
||||
{UINT64_C(0x0102030405060708),
|
||||
"\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
|
||||
{OPENSSL_U64(0xffffffffffffffff),
|
||||
{UINT64_C(0xffffffffffffffff),
|
||||
"\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
|
||||
};
|
||||
|
||||
@@ -698,12 +765,32 @@ static bool TestASN1Uint64() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int TestZero() {
|
||||
static bool TestZero() {
|
||||
CBB cbb;
|
||||
CBB_zero(&cbb);
|
||||
// Calling |CBB_cleanup| on a zero-state |CBB| must not crash.
|
||||
CBB_cleanup(&cbb);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCBBReserve() {
|
||||
uint8_t buf[10];
|
||||
uint8_t *ptr;
|
||||
size_t len;
|
||||
ScopedCBB cbb;
|
||||
if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
|
||||
// Too large.
|
||||
CBB_reserve(cbb.get(), &ptr, 11) ||
|
||||
// Successfully reserve the entire space.
|
||||
!CBB_reserve(cbb.get(), &ptr, 10) ||
|
||||
ptr != buf ||
|
||||
// Advancing under the maximum bytes is legal.
|
||||
!CBB_did_write(cbb.get(), 5) ||
|
||||
!CBB_finish(cbb.get(), NULL, &len) ||
|
||||
len != 5) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -722,9 +809,11 @@ int main(void) {
|
||||
!TestCBBDiscardChild() ||
|
||||
!TestCBBASN1() ||
|
||||
!TestBerConvert() ||
|
||||
!TestImplicitString() ||
|
||||
!TestASN1Uint64() ||
|
||||
!TestGetOptionalASN1Bool() ||
|
||||
!TestZero()) {
|
||||
!TestZero() ||
|
||||
!TestCBBReserve()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+63
-29
@@ -25,6 +25,7 @@ void CBB_zero(CBB *cbb) {
|
||||
}
|
||||
|
||||
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
|
||||
/* This assumes that |cbb| has already been zeroed. */
|
||||
struct cbb_buffer_st *base;
|
||||
|
||||
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
|
||||
@@ -37,16 +38,15 @@ static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
|
||||
base->cap = cap;
|
||||
base->can_resize = 1;
|
||||
|
||||
memset(cbb, 0, sizeof(CBB));
|
||||
cbb->base = base;
|
||||
cbb->is_top_level = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_init(CBB *cbb, size_t initial_capacity) {
|
||||
uint8_t *buf;
|
||||
CBB_zero(cbb);
|
||||
|
||||
buf = OPENSSL_malloc(initial_capacity);
|
||||
uint8_t *buf = OPENSSL_malloc(initial_capacity);
|
||||
if (initial_capacity > 0 && buf == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -60,6 +60,8 @@ int CBB_init(CBB *cbb, size_t initial_capacity) {
|
||||
}
|
||||
|
||||
int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
|
||||
CBB_zero(cbb);
|
||||
|
||||
if (!cbb_init(cbb, buf, len)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -82,8 +84,8 @@ void CBB_cleanup(CBB *cbb) {
|
||||
cbb->base = NULL;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
size_t newlen;
|
||||
|
||||
if (base == NULL) {
|
||||
@@ -119,7 +121,17 @@ static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
if (out) {
|
||||
*out = base->buf + base->len;
|
||||
}
|
||||
base->len = newlen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
if (!cbb_buffer_reserve(base, out, len)) {
|
||||
return 0;
|
||||
}
|
||||
/* This will not overflow or |cbb_buffer_reserve| would have failed. */
|
||||
base->len += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -177,28 +189,28 @@ int CBB_flush(CBB *cbb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbb->child == NULL || cbb->pending_len_len == 0) {
|
||||
if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
child_start = cbb->offset + cbb->pending_len_len;
|
||||
child_start = cbb->child->offset + cbb->child->pending_len_len;
|
||||
|
||||
if (!CBB_flush(cbb->child) ||
|
||||
child_start < cbb->offset ||
|
||||
child_start < cbb->child->offset ||
|
||||
cbb->base->len < child_start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = cbb->base->len - child_start;
|
||||
|
||||
if (cbb->pending_is_asn1) {
|
||||
if (cbb->child->pending_is_asn1) {
|
||||
/* For ASN.1 we assume that we'll only need a single byte for the length.
|
||||
* If that turned out to be incorrect, we have to move the contents along
|
||||
* in order to make space. */
|
||||
size_t len_len;
|
||||
uint8_t initial_length_byte;
|
||||
|
||||
assert (cbb->pending_len_len == 1);
|
||||
assert (cbb->child->pending_len_len == 1);
|
||||
|
||||
if (len > 0xfffffffe) {
|
||||
/* Too large. */
|
||||
@@ -230,12 +242,13 @@ int CBB_flush(CBB *cbb) {
|
||||
memmove(cbb->base->buf + child_start + extra_bytes,
|
||||
cbb->base->buf + child_start, len);
|
||||
}
|
||||
cbb->base->buf[cbb->offset++] = initial_length_byte;
|
||||
cbb->pending_len_len = len_len - 1;
|
||||
cbb->base->buf[cbb->child->offset++] = initial_length_byte;
|
||||
cbb->child->pending_len_len = len_len - 1;
|
||||
}
|
||||
|
||||
for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
|
||||
cbb->base->buf[cbb->offset + i] = len;
|
||||
for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
|
||||
i--) {
|
||||
cbb->base->buf[cbb->child->offset + i] = len;
|
||||
len >>= 8;
|
||||
}
|
||||
if (len != 0) {
|
||||
@@ -244,17 +257,20 @@ int CBB_flush(CBB *cbb) {
|
||||
|
||||
cbb->child->base = NULL;
|
||||
cbb->child = NULL;
|
||||
cbb->pending_len_len = 0;
|
||||
cbb->pending_is_asn1 = 0;
|
||||
cbb->offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t *CBB_data(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
return cbb->base->buf + cbb->offset + cbb->pending_len_len;
|
||||
}
|
||||
|
||||
size_t CBB_len(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
|
||||
|
||||
return cbb->base->len;
|
||||
return cbb->base->len - cbb->offset - cbb->pending_len_len;
|
||||
}
|
||||
|
||||
static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
|
||||
@@ -265,7 +281,7 @@ static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
|
||||
return 0;
|
||||
}
|
||||
|
||||
cbb->offset = cbb->base->len;
|
||||
size_t offset = cbb->base->len;
|
||||
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -274,8 +290,9 @@ static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
|
||||
memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
cbb->child = out_contents;
|
||||
cbb->pending_len_len = len_len;
|
||||
cbb->pending_is_asn1 = 0;
|
||||
cbb->child->offset = offset;
|
||||
cbb->child->pending_len_len = len_len;
|
||||
cbb->child->pending_is_asn1 = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -303,7 +320,7 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cbb->offset = cbb->base->len;
|
||||
size_t offset = cbb->base->len;
|
||||
if (!CBB_add_u8(cbb, 0)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -311,8 +328,9 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
|
||||
memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
cbb->child = out_contents;
|
||||
cbb->pending_len_len = 1;
|
||||
cbb->pending_is_asn1 = 1;
|
||||
cbb->child->offset = offset;
|
||||
cbb->child->pending_len_len = 1;
|
||||
cbb->child->pending_is_asn1 = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -336,6 +354,25 @@ int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_reserve(cbb->base, out_data, len)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_did_write(CBB *cbb, size_t len) {
|
||||
size_t newlen = cbb->base->len + len;
|
||||
if (cbb->child != NULL ||
|
||||
newlen < cbb->base->len ||
|
||||
newlen > cbb->base->cap) {
|
||||
return 0;
|
||||
}
|
||||
cbb->base->len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_u8(CBB *cbb, uint8_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
@@ -365,13 +402,10 @@ void CBB_discard_child(CBB *cbb) {
|
||||
return;
|
||||
}
|
||||
|
||||
cbb->base->len = cbb->offset;
|
||||
cbb->base->len = cbb->child->offset;
|
||||
|
||||
cbb->child->base = NULL;
|
||||
cbb->child = NULL;
|
||||
cbb->pending_len_len = 0;
|
||||
cbb->pending_is_asn1 = 0;
|
||||
cbb->offset = 0;
|
||||
}
|
||||
|
||||
int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
|
||||
|
||||
@@ -22,22 +22,51 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
|
||||
* indefinite-length elements then it attempts to convert the BER data to DER
|
||||
* and sets |*out| and |*out_length| to describe a malloced buffer containing
|
||||
* the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
|
||||
/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
|
||||
* indefinite-length elements or constructed strings then it converts the BER
|
||||
* data to DER and sets |*out| and |*out_length| to describe a malloced buffer
|
||||
* containing the DER data. Additionally, |*in| will be advanced over the BER
|
||||
* element.
|
||||
*
|
||||
* If it doesn't find any indefinite-length elements then it sets |*out| to
|
||||
* NULL and |*in| is unmodified.
|
||||
* If it doesn't find any indefinite-length elements or constructed strings then
|
||||
* it sets |*out| to NULL and |*in| is unmodified.
|
||||
*
|
||||
* A sufficiently complex ASN.1 structure will break this function because it's
|
||||
* not possible to generically convert BER to DER without knowledge of the
|
||||
* structure itself. However, this sufficies to handle the PKCS#7 and #12 output
|
||||
* from NSS.
|
||||
* This function should successfully process any valid BER input, however it
|
||||
* will not convert all of BER's deviations from DER. BER is ambiguous between
|
||||
* implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
|
||||
* strings. Implicitly-tagged strings must be parsed with
|
||||
* |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
|
||||
* must also account for BER variations in the contents of a primitive.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
|
||||
|
||||
/* CBS_get_asn1_implicit_string parses a BER string of primitive type
|
||||
* |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
|
||||
* contents. If concatenation was needed, it sets |*out_storage| to a buffer
|
||||
* which the caller must release with |OPENSSL_free|. Otherwise, it sets
|
||||
* |*out_storage| to NULL.
|
||||
*
|
||||
* This function does not parse all of BER. It requires the string be
|
||||
* definite-length. Constructed strings are allowed, but all children of the
|
||||
* outermost element must be primitive. The caller should use
|
||||
* |CBS_asn1_ber_to_der| before running this function.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
|
||||
uint8_t **out_storage,
|
||||
unsigned outer_tag,
|
||||
unsigned inner_tag);
|
||||
|
||||
/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
|
||||
* with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
|
||||
* and |*outp| is advanced just past the output. It returns the number of bytes
|
||||
* in the result, whether written or not, or a negative value on error. On
|
||||
* error, it calls |CBB_cleanup| on |cbb|.
|
||||
*
|
||||
* This function may be used to help implement legacy i2d ASN.1 functions. */
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
|
||||
+18
-13
@@ -25,6 +25,9 @@
|
||||
|
||||
#include <openssl/chacha.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#if defined(ASM_GEN) || \
|
||||
!defined(OPENSSL_WINDOWS) && \
|
||||
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
|
||||
@@ -80,8 +83,8 @@ typedef unsigned vec __attribute__((vector_size(16)));
|
||||
#define VBPI 3
|
||||
#endif
|
||||
#define ONE (vec) _mm_set_epi32(0, 0, 0, 1)
|
||||
#define LOAD(m) (vec) _mm_loadu_si128((__m128i *)(m))
|
||||
#define LOAD_ALIGNED(m) (vec) _mm_load_si128((__m128i *)(m))
|
||||
#define LOAD(m) (vec) _mm_loadu_si128((const __m128i *)(m))
|
||||
#define LOAD_ALIGNED(m) (vec) _mm_load_si128((const __m128i *)(m))
|
||||
#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r))
|
||||
#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1))
|
||||
#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2))
|
||||
@@ -157,26 +160,28 @@ void CRYPTO_chacha_20(
|
||||
const uint8_t nonce[12],
|
||||
uint32_t counter)
|
||||
{
|
||||
unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
|
||||
unsigned iters, i;
|
||||
unsigned *op = (unsigned *)out;
|
||||
const unsigned *ip = (const unsigned *)in;
|
||||
const unsigned *kp = (const unsigned *)key;
|
||||
#if defined(__ARM_NEON__)
|
||||
uint32_t np[3];
|
||||
uint8_t alignment_buffer[16] __attribute__((aligned(16)));
|
||||
alignas(16) uint8_t alignment_buffer[16];
|
||||
#endif
|
||||
vec s0, s1, s2, s3;
|
||||
__attribute__ ((aligned (16))) unsigned chacha_const[] =
|
||||
alignas(16) unsigned chacha_const[] =
|
||||
{0x61707865,0x3320646E,0x79622D32,0x6B206574};
|
||||
kp = (unsigned *)key;
|
||||
#if defined(__ARM_NEON__)
|
||||
memcpy(np, nonce, 12);
|
||||
#endif
|
||||
s0 = LOAD_ALIGNED(chacha_const);
|
||||
s1 = LOAD(&((vec*)kp)[0]);
|
||||
s2 = LOAD(&((vec*)kp)[1]);
|
||||
s1 = LOAD(&((const vec*)kp)[0]);
|
||||
s2 = LOAD(&((const vec*)kp)[1]);
|
||||
s3 = (vec){
|
||||
counter,
|
||||
((uint32_t*)nonce)[0],
|
||||
((uint32_t*)nonce)[1],
|
||||
((uint32_t*)nonce)[2]
|
||||
((const uint32_t*)nonce)[0],
|
||||
((const uint32_t*)nonce)[1],
|
||||
((const uint32_t*)nonce)[2]
|
||||
};
|
||||
|
||||
for (iters = 0; iters < inlen/(BPI*64); iters++)
|
||||
@@ -286,7 +291,7 @@ void CRYPTO_chacha_20(
|
||||
inlen = inlen % 64;
|
||||
if (inlen)
|
||||
{
|
||||
__attribute__ ((aligned (16))) vec buf[4];
|
||||
alignas(16) vec buf[4];
|
||||
vec v0,v1,v2,v3;
|
||||
v0 = s0; v1 = s1; v2 = s2; v3 = s3;
|
||||
for (i = CHACHA_RNDS/2; i; i--)
|
||||
@@ -316,7 +321,7 @@ void CRYPTO_chacha_20(
|
||||
buf[0] = REVV_BE(v0 + s0);
|
||||
|
||||
for (i=inlen & ~15; i<inlen; i++)
|
||||
((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i];
|
||||
((char *)op)[i] = ((const char *)ip)[i] ^ ((const char *)buf)[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ struct AEADName {
|
||||
static const struct AEADName kAEADs[] = {
|
||||
{ "aes-128-gcm", EVP_aead_aes_128_gcm },
|
||||
{ "aes-256-gcm", EVP_aead_aes_256_gcm },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305_rfc7539 },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305 },
|
||||
{ "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old },
|
||||
{ "rc4-md5-tls", EVP_aead_rc4_md5_tls },
|
||||
{ "rc4-sha1-tls", EVP_aead_rc4_sha1_tls },
|
||||
|
||||
@@ -138,7 +138,7 @@ static bool TestOperation(FileTest *t,
|
||||
iv.size(), 0)) {
|
||||
return false;
|
||||
}
|
||||
} else if (iv.size() != (size_t)EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
} else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
t->PrintLine("Bad IV length.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
|
||||
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
size_t len) {
|
||||
unsigned int num = ctx->num;
|
||||
unsigned num = (unsigned)ctx->num;
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
if (dat->stream.ctr) {
|
||||
@@ -394,7 +394,7 @@ static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
|
||||
dat->block);
|
||||
}
|
||||
ctx->num = (size_t)num;
|
||||
ctx->num = (int)num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1652,7 +1652,7 @@ static int aead_aes_ctr_hmac_sha256_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
|
||||
if (in_len + aes_ctx->tag_len < in_len ||
|
||||
/* This input is so large it would overflow the 32-bit block counter. */
|
||||
in_len_64 >= (OPENSSL_U64(1) << 32) * AES_BLOCK_SIZE) {
|
||||
in_len_64 >= (UINT64_C(1) << 32) * AES_BLOCK_SIZE) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <openssl/poly1305.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define POLY1305_TAG_LEN 16
|
||||
@@ -79,12 +80,6 @@ static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
|
||||
CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
|
||||
}
|
||||
|
||||
#if defined(__arm__)
|
||||
#define ALIGNED __attribute__((aligned(16)))
|
||||
#else
|
||||
#define ALIGNED
|
||||
#endif
|
||||
|
||||
typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad,
|
||||
size_t ad_len, const uint8_t *ciphertext,
|
||||
size_t ciphertext_len);
|
||||
@@ -98,7 +93,7 @@ static void aead_poly1305(aead_poly1305_update update,
|
||||
const uint8_t nonce[12], const uint8_t *ad,
|
||||
size_t ad_len, const uint8_t *ciphertext,
|
||||
size_t ciphertext_len) {
|
||||
uint8_t poly1305_key[32] ALIGNED;
|
||||
alignas(16) uint8_t poly1305_key[32];
|
||||
memset(poly1305_key, 0, sizeof(poly1305_key));
|
||||
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
|
||||
c20_ctx->key, nonce, 0);
|
||||
@@ -108,10 +103,11 @@ static void aead_poly1305(aead_poly1305_update update,
|
||||
CRYPTO_poly1305_finish(&ctx, tag);
|
||||
}
|
||||
|
||||
static int seal(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
|
||||
uint8_t *out, size_t *out_len, size_t max_out_len,
|
||||
const uint8_t nonce[12], const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
static int seal_impl(aead_poly1305_update poly1305_update,
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t nonce[12],
|
||||
const uint8_t *in, size_t in_len, const uint8_t *ad,
|
||||
size_t ad_len) {
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
|
||||
@@ -138,7 +134,7 @@ static int seal(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
|
||||
|
||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||
|
||||
uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
|
||||
alignas(16) uint8_t tag[POLY1305_TAG_LEN];
|
||||
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len);
|
||||
|
||||
memcpy(out + in_len, tag, c20_ctx->tag_len);
|
||||
@@ -146,10 +142,11 @@ static int seal(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int open(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
|
||||
uint8_t *out, size_t *out_len, size_t max_out_len,
|
||||
const uint8_t nonce[12], const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
static int open_impl(aead_poly1305_update poly1305_update,
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t nonce[12],
|
||||
const uint8_t *in, size_t in_len, const uint8_t *ad,
|
||||
size_t ad_len) {
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
size_t plaintext_len;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
@@ -171,7 +168,7 @@ static int open(aead_poly1305_update poly1305_update, const EVP_AEAD_CTX *ctx,
|
||||
}
|
||||
|
||||
plaintext_len = in_len - c20_ctx->tag_len;
|
||||
uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
|
||||
alignas(16) uint8_t tag[POLY1305_TAG_LEN];
|
||||
aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in,
|
||||
plaintext_len);
|
||||
if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
|
||||
@@ -212,8 +209,8 @@ static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
return seal(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
|
||||
in_len, ad, ad_len);
|
||||
return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
|
||||
in_len, ad, ad_len);
|
||||
}
|
||||
|
||||
static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
@@ -225,8 +222,8 @@ static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
return open(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
|
||||
in_len, ad, ad_len);
|
||||
return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
|
||||
in_len, ad, ad_len);
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_chacha20_poly1305 = {
|
||||
@@ -243,10 +240,14 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
|
||||
return &aead_chacha20_poly1305;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
|
||||
return EVP_aead_chacha20_poly1305();
|
||||
}
|
||||
|
||||
static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
|
||||
size_t ad_len, const uint8_t *ciphertext,
|
||||
size_t ciphertext_len) {
|
||||
@@ -267,8 +268,8 @@ static int aead_chacha20_poly1305_old_seal(
|
||||
uint8_t nonce_96[12];
|
||||
memset(nonce_96, 0, 4);
|
||||
memcpy(nonce_96 + 4, nonce, 8);
|
||||
return seal(poly1305_update_old, ctx, out, out_len, max_out_len, nonce_96, in,
|
||||
in_len, ad, ad_len);
|
||||
return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
|
||||
nonce_96, in, in_len, ad, ad_len);
|
||||
}
|
||||
|
||||
static int aead_chacha20_poly1305_old_open(
|
||||
@@ -282,8 +283,8 @@ static int aead_chacha20_poly1305_old_open(
|
||||
uint8_t nonce_96[12];
|
||||
memset(nonce_96, 0, 4);
|
||||
memcpy(nonce_96 + 4, nonce, 8);
|
||||
return open(poly1305_update_old, ctx, out, out_len, max_out_len, nonce_96, in,
|
||||
in_len, ad, ad_len);
|
||||
return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
|
||||
nonce_96, in, in_len, ad, ad_len);
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_chacha20_poly1305_old = {
|
||||
@@ -303,7 +304,3 @@ static const EVP_AEAD aead_chacha20_poly1305_old = {
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) {
|
||||
return &aead_chacha20_poly1305_old;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
|
||||
return &aead_chacha20_poly1305_old;
|
||||
}
|
||||
|
||||
@@ -54,21 +54,13 @@
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/aead.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/cpu.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/rc4.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static int rc4_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
const uint8_t *iv, int enc) {
|
||||
@@ -93,306 +85,3 @@ static const EVP_CIPHER rc4 = {
|
||||
NULL /* cleanup */, NULL /* ctrl */, };
|
||||
|
||||
const EVP_CIPHER *EVP_rc4(void) { return &rc4; }
|
||||
|
||||
|
||||
struct aead_rc4_md5_tls_ctx {
|
||||
RC4_KEY rc4;
|
||||
MD5_CTX head, tail, md;
|
||||
size_t payload_length;
|
||||
unsigned char tag_len;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
|
||||
size_t tag_len) {
|
||||
struct aead_rc4_md5_tls_ctx *rc4_ctx;
|
||||
size_t i;
|
||||
uint8_t hmac_key[MD5_CBLOCK];
|
||||
|
||||
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
|
||||
tag_len = MD5_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
if (tag_len > MD5_DIGEST_LENGTH) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The keys consists of |MD5_DIGEST_LENGTH| bytes of HMAC(MD5) key followed
|
||||
* by some number of bytes of RC4 key. */
|
||||
if (key_len <= MD5_DIGEST_LENGTH) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc4_ctx = OPENSSL_malloc(sizeof(struct aead_rc4_md5_tls_ctx));
|
||||
if (rc4_ctx == NULL) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memset(rc4_ctx, 0, sizeof(struct aead_rc4_md5_tls_ctx));
|
||||
|
||||
RC4_set_key(&rc4_ctx->rc4, key_len - MD5_DIGEST_LENGTH,
|
||||
key + MD5_DIGEST_LENGTH);
|
||||
|
||||
memset(hmac_key, 0, sizeof(hmac_key));
|
||||
memcpy(hmac_key, key, MD5_DIGEST_LENGTH);
|
||||
for (i = 0; i < sizeof(hmac_key); i++) {
|
||||
hmac_key[i] ^= 0x36;
|
||||
}
|
||||
MD5_Init(&rc4_ctx->head);
|
||||
MD5_Update(&rc4_ctx->head, hmac_key, sizeof(hmac_key));
|
||||
for (i = 0; i < sizeof(hmac_key); i++) {
|
||||
hmac_key[i] ^= 0x36 ^ 0x5c;
|
||||
}
|
||||
MD5_Init(&rc4_ctx->tail);
|
||||
MD5_Update(&rc4_ctx->tail, hmac_key, sizeof(hmac_key));
|
||||
|
||||
rc4_ctx->tag_len = tag_len;
|
||||
ctx->aead_state = rc4_ctx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_rc4_md5_tls_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
|
||||
OPENSSL_cleanse(rc4_ctx, sizeof(struct aead_rc4_md5_tls_ctx));
|
||||
OPENSSL_free(rc4_ctx);
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
|
||||
#define STITCHED_CALL
|
||||
|
||||
/* rc4_md5_enc is defined in rc4_md5-x86_64.pl */
|
||||
void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out, MD5_CTX *ctx,
|
||||
const void *inp, size_t blocks);
|
||||
#endif
|
||||
|
||||
static int aead_rc4_md5_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
|
||||
MD5_CTX md;
|
||||
#if defined(STITCHED_CALL)
|
||||
size_t rc4_off, md5_off, blocks;
|
||||
#else
|
||||
const size_t rc4_off = 0;
|
||||
const size_t md5_off = 0;
|
||||
#endif
|
||||
uint8_t digest[MD5_DIGEST_LENGTH];
|
||||
|
||||
if (in_len + rc4_ctx->tag_len < in_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len + rc4_ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
|
||||
/* The MAC's payload begins with the additional data. See
|
||||
* https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
|
||||
MD5_Update(&md, ad, ad_len);
|
||||
|
||||
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
|
||||
* length for legacy ciphers. */
|
||||
uint8_t ad_extra[2];
|
||||
ad_extra[0] = (uint8_t)(in_len >> 8);
|
||||
ad_extra[1] = (uint8_t)(in_len & 0xff);
|
||||
MD5_Update(&md, ad_extra, sizeof(ad_extra));
|
||||
|
||||
#if defined(STITCHED_CALL)
|
||||
/* 32 is $MOD from rc4_md5-x86_64.pl. */
|
||||
rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
|
||||
md5_off = MD5_CBLOCK - md.num;
|
||||
/* Ensure RC4 is behind MD5. */
|
||||
if (rc4_off > md5_off) {
|
||||
md5_off += MD5_CBLOCK;
|
||||
}
|
||||
assert(md5_off >= rc4_off);
|
||||
|
||||
if (in_len > md5_off && (blocks = (in_len - md5_off) / MD5_CBLOCK) &&
|
||||
(OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
|
||||
/* Process the initial portions of the plaintext normally. */
|
||||
MD5_Update(&md, in, md5_off);
|
||||
RC4(&rc4_ctx->rc4, rc4_off, in, out);
|
||||
|
||||
/* Process the next |blocks| blocks of plaintext with stitched routines. */
|
||||
rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, in + md5_off,
|
||||
blocks);
|
||||
blocks *= MD5_CBLOCK;
|
||||
rc4_off += blocks;
|
||||
md5_off += blocks;
|
||||
md.Nh += blocks >> 29;
|
||||
md.Nl += blocks <<= 3;
|
||||
if (md.Nl < (unsigned int)blocks) {
|
||||
md.Nh++;
|
||||
}
|
||||
} else {
|
||||
rc4_off = 0;
|
||||
md5_off = 0;
|
||||
}
|
||||
#endif
|
||||
/* Finish computing the MAC. */
|
||||
MD5_Update(&md, in + md5_off, in_len - md5_off);
|
||||
MD5_Final(digest, &md);
|
||||
|
||||
memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
|
||||
MD5_Update(&md, digest, sizeof(digest));
|
||||
if (rc4_ctx->tag_len == MD5_DIGEST_LENGTH) {
|
||||
MD5_Final(out + in_len, &md);
|
||||
} else {
|
||||
MD5_Final(digest, &md);
|
||||
memcpy(out + in_len, digest, rc4_ctx->tag_len);
|
||||
}
|
||||
|
||||
/* Encrypt the remainder of the plaintext and the MAC. */
|
||||
RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
|
||||
RC4(&rc4_ctx->rc4, MD5_DIGEST_LENGTH, out + in_len, out + in_len);
|
||||
|
||||
*out_len = in_len + rc4_ctx->tag_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_rc4_md5_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
|
||||
MD5_CTX md;
|
||||
size_t plaintext_len;
|
||||
#if defined(STITCHED_CALL)
|
||||
unsigned int l;
|
||||
size_t rc4_off, md5_off, blocks;
|
||||
extern unsigned int OPENSSL_ia32cap_P[];
|
||||
#else
|
||||
const size_t rc4_off = 0;
|
||||
const size_t md5_off = 0;
|
||||
#endif
|
||||
uint8_t digest[MD5_DIGEST_LENGTH];
|
||||
|
||||
if (in_len < rc4_ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
plaintext_len = in_len - rc4_ctx->tag_len;
|
||||
|
||||
if (nonce_len != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len) {
|
||||
/* This requires that the caller provide space for the MAC, even though it
|
||||
* will always be removed on return. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
|
||||
/* The MAC's payload begins with the additional data. See
|
||||
* https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
|
||||
MD5_Update(&md, ad, ad_len);
|
||||
|
||||
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
|
||||
* length for legacy ciphers. */
|
||||
uint8_t ad_extra[2];
|
||||
ad_extra[0] = (uint8_t)(plaintext_len >> 8);
|
||||
ad_extra[1] = (uint8_t)(plaintext_len & 0xff);
|
||||
MD5_Update(&md, ad_extra, sizeof(ad_extra));
|
||||
|
||||
#if defined(STITCHED_CALL)
|
||||
rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
|
||||
md5_off = MD5_CBLOCK - md.num;
|
||||
/* Ensure MD5 is a full block behind RC4 so it has plaintext to operate on in
|
||||
* both normal and stitched routines. */
|
||||
if (md5_off > rc4_off) {
|
||||
rc4_off += 2 * MD5_CBLOCK;
|
||||
} else {
|
||||
rc4_off += MD5_CBLOCK;
|
||||
}
|
||||
|
||||
if (in_len > rc4_off && (blocks = (in_len - rc4_off) / MD5_CBLOCK) &&
|
||||
(OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
|
||||
/* Decrypt the initial portion of the ciphertext and digest the plaintext
|
||||
* normally. */
|
||||
RC4(&rc4_ctx->rc4, rc4_off, in, out);
|
||||
MD5_Update(&md, out, md5_off);
|
||||
|
||||
/* Decrypt and digest the next |blocks| blocks of ciphertext with the
|
||||
* stitched routines. */
|
||||
rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, out + md5_off,
|
||||
blocks);
|
||||
blocks *= MD5_CBLOCK;
|
||||
rc4_off += blocks;
|
||||
md5_off += blocks;
|
||||
l = (md.Nl + (blocks << 3)) & 0xffffffffU;
|
||||
if (l < md.Nl) {
|
||||
md.Nh++;
|
||||
}
|
||||
md.Nl = l;
|
||||
md.Nh += blocks >> 29;
|
||||
} else {
|
||||
md5_off = 0;
|
||||
rc4_off = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Process the remainder of the input. */
|
||||
RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
|
||||
MD5_Update(&md, out + md5_off, plaintext_len - md5_off);
|
||||
MD5_Final(digest, &md);
|
||||
|
||||
/* Calculate HMAC and verify it */
|
||||
memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
|
||||
MD5_Update(&md, digest, MD5_DIGEST_LENGTH);
|
||||
MD5_Final(digest, &md);
|
||||
|
||||
if (CRYPTO_memcmp(out + plaintext_len, digest, rc4_ctx->tag_len)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_len = plaintext_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_rc4_md5_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
|
||||
const RC4_KEY **out_key) {
|
||||
struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
|
||||
*out_key = &rc4_ctx->rc4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_rc4_md5_tls = {
|
||||
16 + MD5_DIGEST_LENGTH, /* key len (RC4 + MD5) */
|
||||
0, /* nonce len */
|
||||
MD5_DIGEST_LENGTH, /* overhead */
|
||||
MD5_DIGEST_LENGTH, /* max tag length */
|
||||
aead_rc4_md5_tls_init,
|
||||
NULL, /* init_with_direction */
|
||||
aead_rc4_md5_tls_cleanup,
|
||||
aead_rc4_md5_tls_seal,
|
||||
aead_rc4_md5_tls_open,
|
||||
aead_rc4_md5_tls_get_rc4_state,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
|
||||
|
||||
+38
-24
@@ -20,6 +20,7 @@
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/type_check.h>
|
||||
@@ -111,7 +112,6 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
|
||||
@@ -146,17 +146,13 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
* in-place. */
|
||||
uint8_t mac[EVP_MAX_MD_SIZE];
|
||||
unsigned mac_len;
|
||||
HMAC_CTX hmac_ctx;
|
||||
HMAC_CTX_init(&hmac_ctx);
|
||||
if (!HMAC_CTX_copy_ex(&hmac_ctx, &tls_ctx->hmac_ctx) ||
|
||||
!HMAC_Update(&hmac_ctx, ad, ad_len) ||
|
||||
!HMAC_Update(&hmac_ctx, ad_extra, sizeof(ad_extra)) ||
|
||||
!HMAC_Update(&hmac_ctx, in, in_len) ||
|
||||
!HMAC_Final(&hmac_ctx, mac, &mac_len)) {
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) ||
|
||||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) {
|
||||
return 0;
|
||||
}
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
|
||||
/* Configure the explicit IV. */
|
||||
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
|
||||
@@ -216,7 +212,6 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
|
||||
@@ -324,18 +319,14 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
* implemented. */
|
||||
assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE);
|
||||
|
||||
HMAC_CTX hmac_ctx;
|
||||
HMAC_CTX_init(&hmac_ctx);
|
||||
unsigned mac_len_u;
|
||||
if (!HMAC_CTX_copy_ex(&hmac_ctx, &tls_ctx->hmac_ctx) ||
|
||||
!HMAC_Update(&hmac_ctx, ad_fixed, ad_len) ||
|
||||
!HMAC_Update(&hmac_ctx, out, data_len) ||
|
||||
!HMAC_Final(&hmac_ctx, mac, &mac_len_u)) {
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) ||
|
||||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) {
|
||||
return 0;
|
||||
}
|
||||
mac_len = mac_len_u;
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
|
||||
assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
|
||||
record_mac = &out[data_len];
|
||||
@@ -359,6 +350,13 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5(),
|
||||
0);
|
||||
}
|
||||
|
||||
static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
@@ -433,8 +431,8 @@ static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(
|
||||
EVP_sha1(), 1);
|
||||
}
|
||||
|
||||
static int aead_rc4_sha1_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
|
||||
const RC4_KEY **out_key) {
|
||||
static int aead_rc4_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
|
||||
const RC4_KEY **out_key) {
|
||||
const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
|
||||
if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) {
|
||||
return 0;
|
||||
@@ -464,18 +462,32 @@ static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
EVP_sha1(), 1 /* implicit iv */);
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_rc4_md5_tls = {
|
||||
MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */
|
||||
0, /* nonce len */
|
||||
MD5_DIGEST_LENGTH, /* overhead */
|
||||
MD5_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_rc4_md5_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
aead_rc4_tls_get_rc4_state, /* get_rc4_state */
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_rc4_sha1_tls = {
|
||||
SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
|
||||
0, /* nonce len */
|
||||
SHA_DIGEST_LENGTH, /* overhead */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
NULL, /* init */
|
||||
aead_rc4_sha1_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
aead_rc4_sha1_tls_get_rc4_state, /* get_rc4_state */
|
||||
NULL, /* get_iv */
|
||||
aead_rc4_tls_get_rc4_state, /* get_rc4_state */
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
|
||||
@@ -618,6 +630,8 @@ static const EVP_AEAD aead_null_sha1_tls = {
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
|
||||
|
||||
const EVP_AEAD *EVP_aead_rc4_sha1_tls(void) { return &aead_rc4_sha1_tls; }
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
|
||||
|
||||
@@ -418,5 +418,107 @@ AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813
|
||||
CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f
|
||||
TAG: f7d3b58a34a86e99267e5db206f17bbe
|
||||
|
||||
# BoringSSL has additional tests here for truncated tags. *ring* doesn't
|
||||
# support tag truncation, so those tests were removed.
|
||||
KEY: 3304e4917ad7777b86c26a636292c9cc4c10d32003c49e07209eb0ef8505031a
|
||||
NONCE: 4d572d116fbd8c4d
|
||||
IN: 2f242c2ba33790ecef862b0e077ff8b15eb9d10cf2ff621ed65902494431dcbd
|
||||
AD: e699bbf250cdd93d229d0740e433897e2d19132e2b722df8b69bb6a7c2cf3b93
|
||||
CT: fb81e30436e437c7f686f86b1b65c73549a9d09db810d320785c3634934150b3
|
||||
TAG: 8b
|
||||
|
||||
KEY: ed6057bb163f1609ff28b938122f495e3d5ae4ec3dbd7456c9b5c82e28e952dc
|
||||
NONCE: e6ff6852f3a3afde
|
||||
IN: 3c50edc967eb0b3b2355f6400e0a036e796c8b7d72c5e583a86e820d53e76c43
|
||||
AD: 2441db55148e14e9e241d68296eb60d529408f0534143089671bce546db96d88
|
||||
CT: 6ecabccee31519374d4bed11296e7483d1cb759bea3f4446a96bda8b4ca6d7ac
|
||||
TAG: 355f
|
||||
|
||||
KEY: 73568183c1f9725af30e0f2067606ce802c3fe3ab5cff8d02b3db8c35176ee0d
|
||||
NONCE: 0bc9e19321b3d00a
|
||||
IN: ec2590af5ccd226a32ff750c1b029c11e3dd76c469a5579da9418e4c3fdc0d41
|
||||
AD: df30160ae0cbf2cf8992221bd62dffe691dd602afa784ca691479e957af3acf1
|
||||
CT: 9e8d8ac30626f8b831448d6976933aa5bb8c6dbc794e1f4b7eeb0e4a59342c07
|
||||
TAG: 9fd36a
|
||||
|
||||
KEY: 273bcb3f8c067da4ec3418799ad40e7e4aee74ad7e629499d646df4a7e585025
|
||||
NONCE: f60be3eb894b4030
|
||||
IN: 697498ba964d5ef401da4d94844fab1efc635e7157d0831a325bb5a4cf1fbd34
|
||||
AD: 9129715deab14f02c76ba8172571b1fa9d50365cd795bfccdfc28e7e7b4f66fc
|
||||
CT: bd4cd5af83be1c13933302675d9fcaf1c4cacdf269f6ff441d1ea2211c54e7ed
|
||||
TAG: 7ab12a37
|
||||
|
||||
KEY: ad39610c2e6a6d0961207390e076e972c2edadca885c92965fa648b2ce34fdbf
|
||||
NONCE: a90db690bba83b78
|
||||
IN: 31c49e3cd3d80a82e6b90316dfb94b38b8a23042519bf40c8181fec873c99002
|
||||
AD: ddbd7d821d18d44c66295abf245b227b5cf4366811b7b34c07679600abdbfc29
|
||||
CT: 94628fc303a0546edd51e966f2bd87968f37800c607d5e5a91f727fc1fec406f
|
||||
TAG: c22ec4e4c8
|
||||
|
||||
KEY: 29984954060ba06ece1bcfc0e50195f4632c6df48da1e02ae6c14f7065668971
|
||||
NONCE: cce53a25aeeaf747
|
||||
IN: b9b87433a9894f3c9ca8212623d62369a565a2edcddd276e07d611eda3597426
|
||||
AD: 19fa9aa59697559d8b46d9cd49c3b763c0b73b26b9e334a3eeac2c86fdbaca8d
|
||||
CT: b68c83397770c36f073710882fa86d43b0e54e8efef0ff75075604d0d7ec4e1b
|
||||
TAG: 40d4ab752f3d
|
||||
|
||||
KEY: 5c3b838b84100b2a818c0842e9fe19a7c50cf5f3ea73364c816ef588e500ff3f
|
||||
NONCE: fdf6b0229e4bcc2a
|
||||
IN: 2ba91904c143be99297b39f52856904af41705c176c8c6554b6bc89bddffbcc1
|
||||
AD: 3539d9dd821f004f4ced1637071f4be6abd7fe98f017f0a8ce3f49dc8d496f46
|
||||
CT: ff9d6d924e737a1df8c2bd3047e40ab401f903aa0e5b51acb991bac38ac2cc4d
|
||||
TAG: 1bcaa415a6a3c7
|
||||
|
||||
KEY: 6d65e627cab6d5eb1a088b25bd6c3a8a004a7a19cccae909d62fed3559c812f7
|
||||
NONCE: 7ff00a8798b792de
|
||||
IN: 6848ee4ac820291a2e1dc3baad97f1ad8b7160dfeaa1bc83b2700ae42b5a366b
|
||||
AD: d2437b1306bf0ea211449fac863ca0d1074d84caee9009c5d54b9e9bdc8de6b1
|
||||
CT: 2da0abe2a71e1c0b1ab309c160a8cebe45c6e16170aa5561806484ba2b5b9a9a
|
||||
TAG: 566003e1f78d2a90
|
||||
|
||||
KEY: 63401046a96efbc8c6483a2c396b2a593d3fae0db565525b85999fae13a46b6a
|
||||
NONCE: 051393d775e635ee
|
||||
IN: 2b4b6477580382aae782f8b5772c0948a444d8d95caacd85c0856c7e4393fe09
|
||||
AD: 3d84d2e70e9c062d1f511eb685a9a90c8d5fa50eadf8455c7148666b3e7155e0
|
||||
CT: 880c1123e54fd8ffb3c293720dd174913572e619ef46504cdaa64fc451b0ec1c
|
||||
TAG: 339274339c88d50ac0
|
||||
|
||||
KEY: 291fccfce0782f1787d62d4b9293d2ada4c04d37a8288ba9ba9aae0d31aad204
|
||||
NONCE: 7450bbd62e4aba7b
|
||||
IN: adc251e793181e5d4c4bd983b853eb13f2096ccb340996b6eca4cd2157efcec7
|
||||
AD: 4c598f6deedc8c1d97da33654763495cca3517430eec4edb006b10c95e031ae6
|
||||
CT: 28bda22e4922cd8ff6739cd8a6bdafce036d9c61a145a65ca1b86f6d4d3206a1
|
||||
TAG: d98fd43fe7ac74d4b016
|
||||
|
||||
KEY: fa3a9674d4a0eb36b2f7547c956443d09e6b4e4acfc9deda838eb7ebdb999a8d
|
||||
NONCE: 0a2572592c3bbbf6
|
||||
IN: ae27f70fda9f5a5be0f704a27f0b8a9c04ce83d3c2e0d7ec152da25f473b0c8a
|
||||
AD: 6ee8705a9a3655d198497ad410da02005872ecbe397824851b80f4050bfdd311
|
||||
CT: f356cbd88e4e2aff62d91e3f914032085388955bbba995fde013758b8702e38f
|
||||
TAG: 00324c76fecd3f50e1e3b8
|
||||
|
||||
KEY: 471ec87b992b104d369748d96856b5f66149cb45ca05c17f29d24eb9526fe6db
|
||||
NONCE: 23a2df9ed0b47439
|
||||
IN: 2b9452bca0f48e5519ec3d0736597608df6ad9ce799eba913cff71573d79c092
|
||||
AD: a56722ddfaee5f1b64398c225ee8bcdcfde5c2127101c363bfac52bc409c1082
|
||||
CT: 7bbc464aac5dd29c25262fe0b116c176d827c2cc8dd63428393b0a9110f3c194
|
||||
TAG: 2e87f4a6663a62e47c7e197f
|
||||
|
||||
KEY: a29d1cfd4ccdc18803fbca9500f4bb29ce99cfcbf8acc41b8208dae4b7ee5d64
|
||||
NONCE: 634f99e88e237ef0
|
||||
IN: 09ee5982c5743f396d0c29c13e3fbb8fb89f61705da05466291e010effd51a5c
|
||||
AD: 564dddfcc3227b413244f1105b610f192decf15c4cfa067f4d7fcd6bd7af11b8
|
||||
CT: 32916b67a6f32733623344c98c49773f3e721dc2ded105fb245799525bc9c84c
|
||||
TAG: ff463c07e7ef831321d3fd775f
|
||||
|
||||
KEY: 08ba23616d911188f91da063278bef1237dcbf17f52585e53c2c4b6cf3ac9f0d
|
||||
NONCE: 989ae593eddd3874
|
||||
IN: 749152c9478944c8271c0c11e07bc1c569eec01493e65b3b94842a1bf5d721f8
|
||||
AD: a12d1a45b7c9b91ab08751a70b753714052ad24e0b2619fe8c3be303c65f2dbc
|
||||
CT: 34c40538ee1d22ddf8ac290dd7d423dfc622b5cf8f3412a5343e277822aea713
|
||||
TAG: 014c7c678e0949e88071d1fe3531
|
||||
|
||||
KEY: c2ba8bed8634156afc6bfe3754c91744d4131de39d059f3a866399f916553b5c
|
||||
NONCE: 80fbf7b433a4cd9c
|
||||
IN: 419be6623e7964f9f26068dd969e4a139617e67c5ffb269b3013c433fe771c77
|
||||
AD: 3937592db78a61ff469691b6800792019bc2b3d42512f23c1b1a66a8274495cb
|
||||
CT: 9d5bd1c7e766763eb00684c038043111d8c6390a8d6e17a15ef97c02ab16f09c
|
||||
TAG: a64d0eeb4a01481ec0cee8c1c357e3
|
||||
|
||||
@@ -47,8 +47,8 @@ AD: "123456789abcdef0"
|
||||
CT: e275aeb341e1fc9a70c4fd4496fc7cdb
|
||||
TAG: 41acd0560ea6843d3e5d4e5babf6e946
|
||||
|
||||
# Test vectors from chacha20_poly1305_deprecated_tests.txt, modified for the
|
||||
# RFC 7539 AEAD construction.
|
||||
# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539
|
||||
# AEAD construction.
|
||||
|
||||
KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
|
||||
NONCE: 000000003de9c0da2bd7f91e
|
||||
@@ -470,5 +470,109 @@ AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813
|
||||
CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f
|
||||
TAG: 296a397d280d026fc3627f4718971be9
|
||||
|
||||
# BoringSSL has additional tests here for truncated tags. *ring* doesn't
|
||||
# support tag truncation, so those tests were removed.
|
||||
# Tag truncation tests.
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c2
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f3
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f37465
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a84
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a8413
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a841386
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a84138648
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a84138648a5
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 000000005d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: d3f7b9c295f374651a84138648a591
|
||||
|
||||
+39
-10
@@ -146,7 +146,6 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
* the MAC's position can only vary by 255 bytes. */
|
||||
unsigned scan_start = 0;
|
||||
unsigned i, j;
|
||||
unsigned div_spoiler;
|
||||
unsigned rotate_offset;
|
||||
|
||||
assert(orig_len >= in_len);
|
||||
@@ -161,16 +160,46 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
if (orig_len > md_size + 255 + 1) {
|
||||
scan_start = orig_len - (md_size + 255 + 1);
|
||||
}
|
||||
/* div_spoiler contains a multiple of md_size that is used to cause the
|
||||
* modulo operation to be constant time. Without this, the time varies
|
||||
* based on the amount of padding when running on Intel chips at least.
|
||||
|
||||
/* Ideally the next statement would be:
|
||||
*
|
||||
* The aim of right-shifting md_size is so that the compiler doesn't
|
||||
* figure out that it can remove div_spoiler as that would require it
|
||||
* to prove that md_size is always even, which I hope is beyond it. */
|
||||
div_spoiler = md_size >> 1;
|
||||
div_spoiler <<= (sizeof(div_spoiler) - 1) * 8;
|
||||
rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
|
||||
* rotate_offset = (mac_start - scan_start) % md_size;
|
||||
*
|
||||
* However, division is not a constant-time operation (at least on Intel
|
||||
* chips). Thus we enumerate the possible values of md_size and handle each
|
||||
* separately. The value of |md_size| is public information (it's determined
|
||||
* by the cipher suite in the ServerHello) so our timing can vary based on
|
||||
* its value. */
|
||||
|
||||
rotate_offset = mac_start - scan_start;
|
||||
/* rotate_offset can be, at most, 255 (bytes of padding) + 1 (padding length)
|
||||
* + md_size = 256 + 48 (since SHA-384 is the largest hash) = 304. */
|
||||
assert(rotate_offset <= 304);
|
||||
|
||||
if (md_size == 16) {
|
||||
rotate_offset &= 15;
|
||||
} else if (md_size == 20) {
|
||||
/* 1/20 is approximated as 25/512 and then Barrett reduction is used.
|
||||
* Analytically, this is correct for 0 <= rotate_offset <= 853. */
|
||||
unsigned q = (rotate_offset * 25) >> 9;
|
||||
rotate_offset -= q * 20;
|
||||
rotate_offset -=
|
||||
constant_time_select(constant_time_ge(rotate_offset, 20), 20, 0);
|
||||
} else if (md_size == 32) {
|
||||
rotate_offset &= 31;
|
||||
} else if (md_size == 48) {
|
||||
/* 1/48 is approximated as 10/512 and then Barrett reduction is used.
|
||||
* Analytically, this is correct for 0 <= rotate_offset <= 768. */
|
||||
unsigned q = (rotate_offset * 10) >> 9;
|
||||
rotate_offset -= q * 48;
|
||||
rotate_offset -=
|
||||
constant_time_select(constant_time_ge(rotate_offset, 48), 48, 0);
|
||||
} else {
|
||||
/* This should be impossible therefore this path doesn't run in constant
|
||||
* time. */
|
||||
assert(0);
|
||||
rotate_offset = rotate_offset % md_size;
|
||||
}
|
||||
|
||||
memset(rotated_mac, 0, md_size);
|
||||
for (i = scan_start, j = 0; i < orig_len; i++) {
|
||||
|
||||
@@ -776,3 +776,12 @@ int CONF_parse_list(const char *list, char sep, int remove_whitespace,
|
||||
lstart = p + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, const char *appname,
|
||||
unsigned long flags) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CONF_modules_free(void) {}
|
||||
|
||||
void OPENSSL_config(CONF_MUST_BE_NULL *config_name) {}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ unsigned long getauxval(unsigned long type) __attribute__((weak));
|
||||
|
||||
extern uint32_t OPENSSL_armcap_P;
|
||||
|
||||
char CRYPTO_is_NEON_capable(void) {
|
||||
char CRYPTO_is_NEON_capable_at_runtime(void) {
|
||||
return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ static void handle_cpu_env(uint32_t *out, const char *in) {
|
||||
const int invert = in[0] == '~';
|
||||
uint64_t v;
|
||||
|
||||
if (!sscanf(in + invert, "%" PRIi64, &v)) {
|
||||
if (!sscanf(in + invert, "%" PRIu64, &v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+12
-8
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include <openssl/cpu.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
@@ -86,22 +88,22 @@ uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_NO_STATIC_INITIALIZER)
|
||||
#define OPENSSL_CDECL __cdecl
|
||||
#else
|
||||
#define OPENSSL_CDECL
|
||||
#endif
|
||||
|
||||
#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static void do_library_init(void) __attribute__ ((constructor));
|
||||
#else
|
||||
#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
|
||||
static CRYPTO_once_t once = CRYPTO_ONCE_INIT;
|
||||
#elif defined(OPENSSL_WINDOWS)
|
||||
#pragma section(".CRT$XCU", read)
|
||||
static void __cdecl do_library_init(void);
|
||||
__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
|
||||
do_library_init;
|
||||
#else
|
||||
static void do_library_init(void) __attribute__ ((constructor));
|
||||
#endif
|
||||
#endif /* !BORINGSSL_NO_STATIC_INITIALIZER */
|
||||
|
||||
/* do_library_init is the actual initialization function. If
|
||||
* BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
|
||||
@@ -117,9 +119,9 @@ static void OPENSSL_CDECL do_library_init(void) {
|
||||
void CRYPTO_library_init(void) {
|
||||
/* TODO(davidben): It would be tidier if this build knob could be replaced
|
||||
* with an internal lazy-init mechanism that would handle things correctly
|
||||
* in-library. */
|
||||
* in-library. https://crbug.com/542879 */
|
||||
#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
|
||||
do_library_init();
|
||||
CRYPTO_once(&once, do_library_init);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -136,3 +138,5 @@ int CRYPTO_malloc_init(void) {
|
||||
}
|
||||
|
||||
void ENGINE_load_builtin_engines(void) {}
|
||||
|
||||
void OPENSSL_load_builtin_modules(void) {}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
include_directories(../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
CURVE25519_ARCH_SOURCES
|
||||
|
||||
asm/x25519-asm-arm.S
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CURVE25519_ARCH_SOURCES
|
||||
|
||||
asm/x25519-asm-x86_64.S
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
curve25519
|
||||
|
||||
OBJECT
|
||||
|
||||
curve25519.c
|
||||
x25519-x86_64.c
|
||||
|
||||
${CURVE25519_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
add_executable(
|
||||
ed25519_test
|
||||
|
||||
ed25519_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(ed25519_test crypto)
|
||||
add_dependencies(all_tests ed25519_test)
|
||||
|
||||
add_executable(
|
||||
x25519_test
|
||||
|
||||
x25519_test.cc
|
||||
)
|
||||
|
||||
target_link_libraries(x25519_test crypto)
|
||||
add_dependencies(all_tests x25519_test)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
/* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/curve25519.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
|
||||
|
||||
static bool TestSignature(FileTest *t, void *arg) {
|
||||
std::vector<uint8_t> private_key, public_key, message, expected_signature;
|
||||
if (!t->GetBytes(&private_key, "PRIV") ||
|
||||
private_key.size() != 64 ||
|
||||
!t->GetBytes(&public_key, "PUB") ||
|
||||
public_key.size() != 32 ||
|
||||
!t->GetBytes(&message, "MESSAGE") ||
|
||||
!t->GetBytes(&expected_signature, "SIG") ||
|
||||
expected_signature.size() != 64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t signature[64];
|
||||
if (!ED25519_sign(signature, message.data(), message.size(),
|
||||
private_key.data())) {
|
||||
t->PrintLine("ED25519_sign failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!t->ExpectBytesEqual(expected_signature.data(), expected_signature.size(),
|
||||
signature, sizeof(signature))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ED25519_verify(message.data(), message.size(), signature,
|
||||
public_key.data())) {
|
||||
t->PrintLine("ED25519_verify failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test input.txt>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestSignature, nullptr, argv[1]);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_CURVE25519_INTERNAL_H
|
||||
#define OPENSSL_HEADER_CURVE25519_INTERNAL_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \
|
||||
!defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM)
|
||||
#define BORINGSSL_X25519_X86_64
|
||||
|
||||
void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
|
||||
const uint8_t point[32]);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
|
||||
#define BORINGSSL_X25519_NEON
|
||||
|
||||
/* x25519_NEON is defined in asm/x25519-arm.S. */
|
||||
void x25519_NEON(uint8_t out[32], const uint8_t scalar[32],
|
||||
const uint8_t point[32]);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_CURVE25519_INTERNAL_H */
|
||||
@@ -0,0 +1,225 @@
|
||||
#include <openssl/curve25519.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#if defined(BORINGSSL_X25519_X86_64)
|
||||
|
||||
typedef struct { uint64_t v[5]; } fe25519;
|
||||
|
||||
/* These functions are defined in asm/x25519-x86_64.S */
|
||||
void x25519_x86_64_work_cswap(fe25519 *, uint64_t);
|
||||
void x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b);
|
||||
void x25519_x86_64_square(fe25519 *out, const fe25519 *a);
|
||||
void x25519_x86_64_freeze(fe25519 *);
|
||||
void x25519_x86_64_ladderstep(fe25519 *work);
|
||||
|
||||
static void fe25519_setint(fe25519 *r, unsigned v) {
|
||||
r->v[0] = v;
|
||||
r->v[1] = 0;
|
||||
r->v[2] = 0;
|
||||
r->v[3] = 0;
|
||||
r->v[4] = 0;
|
||||
}
|
||||
|
||||
/* Assumes input x being reduced below 2^255 */
|
||||
static void fe25519_pack(unsigned char r[32], const fe25519 *x) {
|
||||
fe25519 t;
|
||||
t = *x;
|
||||
x25519_x86_64_freeze(&t);
|
||||
|
||||
r[0] = (uint8_t)(t.v[0] & 0xff);
|
||||
r[1] = (uint8_t)((t.v[0] >> 8) & 0xff);
|
||||
r[2] = (uint8_t)((t.v[0] >> 16) & 0xff);
|
||||
r[3] = (uint8_t)((t.v[0] >> 24) & 0xff);
|
||||
r[4] = (uint8_t)((t.v[0] >> 32) & 0xff);
|
||||
r[5] = (uint8_t)((t.v[0] >> 40) & 0xff);
|
||||
r[6] = (uint8_t)((t.v[0] >> 48));
|
||||
|
||||
r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8);
|
||||
r[7] = (uint8_t)((t.v[1] >> 5) & 0xff);
|
||||
r[8] = (uint8_t)((t.v[1] >> 13) & 0xff);
|
||||
r[9] = (uint8_t)((t.v[1] >> 21) & 0xff);
|
||||
r[10] = (uint8_t)((t.v[1] >> 29) & 0xff);
|
||||
r[11] = (uint8_t)((t.v[1] >> 37) & 0xff);
|
||||
r[12] = (uint8_t)((t.v[1] >> 45));
|
||||
|
||||
r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0);
|
||||
r[13] = (uint8_t)((t.v[2] >> 2) & 0xff);
|
||||
r[14] = (uint8_t)((t.v[2] >> 10) & 0xff);
|
||||
r[15] = (uint8_t)((t.v[2] >> 18) & 0xff);
|
||||
r[16] = (uint8_t)((t.v[2] >> 26) & 0xff);
|
||||
r[17] = (uint8_t)((t.v[2] >> 34) & 0xff);
|
||||
r[18] = (uint8_t)((t.v[2] >> 42) & 0xff);
|
||||
r[19] = (uint8_t)((t.v[2] >> 50));
|
||||
|
||||
r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe);
|
||||
r[20] = (uint8_t)((t.v[3] >> 7) & 0xff);
|
||||
r[21] = (uint8_t)((t.v[3] >> 15) & 0xff);
|
||||
r[22] = (uint8_t)((t.v[3] >> 23) & 0xff);
|
||||
r[23] = (uint8_t)((t.v[3] >> 31) & 0xff);
|
||||
r[24] = (uint8_t)((t.v[3] >> 39) & 0xff);
|
||||
r[25] = (uint8_t)((t.v[3] >> 47));
|
||||
|
||||
r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0);
|
||||
r[26] = (uint8_t)((t.v[4] >> 4) & 0xff);
|
||||
r[27] = (uint8_t)((t.v[4] >> 12) & 0xff);
|
||||
r[28] = (uint8_t)((t.v[4] >> 20) & 0xff);
|
||||
r[29] = (uint8_t)((t.v[4] >> 28) & 0xff);
|
||||
r[30] = (uint8_t)((t.v[4] >> 36) & 0xff);
|
||||
r[31] = (uint8_t)((t.v[4] >> 44));
|
||||
}
|
||||
|
||||
static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) {
|
||||
r->v[0] = x[0];
|
||||
r->v[0] += (uint64_t)x[1] << 8;
|
||||
r->v[0] += (uint64_t)x[2] << 16;
|
||||
r->v[0] += (uint64_t)x[3] << 24;
|
||||
r->v[0] += (uint64_t)x[4] << 32;
|
||||
r->v[0] += (uint64_t)x[5] << 40;
|
||||
r->v[0] += ((uint64_t)x[6] & 7) << 48;
|
||||
|
||||
r->v[1] = x[6] >> 3;
|
||||
r->v[1] += (uint64_t)x[7] << 5;
|
||||
r->v[1] += (uint64_t)x[8] << 13;
|
||||
r->v[1] += (uint64_t)x[9] << 21;
|
||||
r->v[1] += (uint64_t)x[10] << 29;
|
||||
r->v[1] += (uint64_t)x[11] << 37;
|
||||
r->v[1] += ((uint64_t)x[12] & 63) << 45;
|
||||
|
||||
r->v[2] = x[12] >> 6;
|
||||
r->v[2] += (uint64_t)x[13] << 2;
|
||||
r->v[2] += (uint64_t)x[14] << 10;
|
||||
r->v[2] += (uint64_t)x[15] << 18;
|
||||
r->v[2] += (uint64_t)x[16] << 26;
|
||||
r->v[2] += (uint64_t)x[17] << 34;
|
||||
r->v[2] += (uint64_t)x[18] << 42;
|
||||
r->v[2] += ((uint64_t)x[19] & 1) << 50;
|
||||
|
||||
r->v[3] = x[19] >> 1;
|
||||
r->v[3] += (uint64_t)x[20] << 7;
|
||||
r->v[3] += (uint64_t)x[21] << 15;
|
||||
r->v[3] += (uint64_t)x[22] << 23;
|
||||
r->v[3] += (uint64_t)x[23] << 31;
|
||||
r->v[3] += (uint64_t)x[24] << 39;
|
||||
r->v[3] += ((uint64_t)x[25] & 15) << 47;
|
||||
|
||||
r->v[4] = x[25] >> 4;
|
||||
r->v[4] += (uint64_t)x[26] << 4;
|
||||
r->v[4] += (uint64_t)x[27] << 12;
|
||||
r->v[4] += (uint64_t)x[28] << 20;
|
||||
r->v[4] += (uint64_t)x[29] << 28;
|
||||
r->v[4] += (uint64_t)x[30] << 36;
|
||||
r->v[4] += ((uint64_t)x[31] & 127) << 44;
|
||||
}
|
||||
|
||||
static void fe25519_invert(fe25519 *r, const fe25519 *x) {
|
||||
fe25519 z2;
|
||||
fe25519 z9;
|
||||
fe25519 z11;
|
||||
fe25519 z2_5_0;
|
||||
fe25519 z2_10_0;
|
||||
fe25519 z2_20_0;
|
||||
fe25519 z2_50_0;
|
||||
fe25519 z2_100_0;
|
||||
fe25519 t;
|
||||
int i;
|
||||
|
||||
/* 2 */ x25519_x86_64_square(&z2, x);
|
||||
/* 4 */ x25519_x86_64_square(&t, &z2);
|
||||
/* 8 */ x25519_x86_64_square(&t, &t);
|
||||
/* 9 */ x25519_x86_64_mul(&z9, &t, x);
|
||||
/* 11 */ x25519_x86_64_mul(&z11, &z9, &z2);
|
||||
/* 22 */ x25519_x86_64_square(&t, &z11);
|
||||
/* 2^5 - 2^0 = 31 */ x25519_x86_64_mul(&z2_5_0, &t, &z9);
|
||||
|
||||
/* 2^6 - 2^1 */ x25519_x86_64_square(&t, &z2_5_0);
|
||||
/* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { x25519_x86_64_square(&t, &t); }
|
||||
/* 2^10 - 2^0 */ x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0);
|
||||
|
||||
/* 2^11 - 2^1 */ x25519_x86_64_square(&t, &z2_10_0);
|
||||
/* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
|
||||
/* 2^20 - 2^0 */ x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0);
|
||||
|
||||
/* 2^21 - 2^1 */ x25519_x86_64_square(&t, &z2_20_0);
|
||||
/* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { x25519_x86_64_square(&t, &t); }
|
||||
/* 2^40 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_20_0);
|
||||
|
||||
/* 2^41 - 2^1 */ x25519_x86_64_square(&t, &t);
|
||||
/* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { x25519_x86_64_square(&t, &t); }
|
||||
/* 2^50 - 2^0 */ x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0);
|
||||
|
||||
/* 2^51 - 2^1 */ x25519_x86_64_square(&t, &z2_50_0);
|
||||
/* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
|
||||
/* 2^100 - 2^0 */ x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0);
|
||||
|
||||
/* 2^101 - 2^1 */ x25519_x86_64_square(&t, &z2_100_0);
|
||||
/* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
|
||||
x25519_x86_64_square(&t, &t);
|
||||
}
|
||||
/* 2^200 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_100_0);
|
||||
|
||||
/* 2^201 - 2^1 */ x25519_x86_64_square(&t, &t);
|
||||
/* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { x25519_x86_64_square(&t, &t); }
|
||||
/* 2^250 - 2^0 */ x25519_x86_64_mul(&t, &t, &z2_50_0);
|
||||
|
||||
/* 2^251 - 2^1 */ x25519_x86_64_square(&t, &t);
|
||||
/* 2^252 - 2^2 */ x25519_x86_64_square(&t, &t);
|
||||
/* 2^253 - 2^3 */ x25519_x86_64_square(&t, &t);
|
||||
|
||||
/* 2^254 - 2^4 */ x25519_x86_64_square(&t, &t);
|
||||
|
||||
/* 2^255 - 2^5 */ x25519_x86_64_square(&t, &t);
|
||||
/* 2^255 - 21 */ x25519_x86_64_mul(r, &t, &z11);
|
||||
}
|
||||
|
||||
static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) {
|
||||
fe25519 work[5];
|
||||
|
||||
work[0] = *xr;
|
||||
fe25519_setint(work + 1, 1);
|
||||
fe25519_setint(work + 2, 0);
|
||||
work[3] = *xr;
|
||||
fe25519_setint(work + 4, 1);
|
||||
|
||||
int i, j;
|
||||
uint8_t prevbit = 0;
|
||||
|
||||
j = 6;
|
||||
for (i = 31; i >= 0; i--) {
|
||||
while (j >= 0) {
|
||||
const uint8_t bit = 1 & (s[i] >> j);
|
||||
const uint64_t swap = bit ^ prevbit;
|
||||
prevbit = bit;
|
||||
x25519_x86_64_work_cswap(work + 1, swap);
|
||||
x25519_x86_64_ladderstep(work);
|
||||
j -= 1;
|
||||
}
|
||||
j = 7;
|
||||
}
|
||||
|
||||
*xr = work[1];
|
||||
*zr = work[2];
|
||||
}
|
||||
|
||||
void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
|
||||
const uint8_t point[32]) {
|
||||
uint8_t e[32];
|
||||
memcpy(e, scalar, sizeof(e));
|
||||
|
||||
e[0] &= 248;
|
||||
e[31] &= 127;
|
||||
e[31] |= 64;
|
||||
|
||||
fe25519 t;
|
||||
fe25519 z;
|
||||
fe25519_unpack(&t, point);
|
||||
mladder(&t, &z, e);
|
||||
fe25519_invert(&z, &z);
|
||||
x25519_x86_64_mul(&t, &t, &z);
|
||||
fe25519_pack(out, &t);
|
||||
}
|
||||
|
||||
#endif /* BORINGSSL_X25519_X86_64 */
|
||||
@@ -0,0 +1,126 @@
|
||||
/* 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/curve25519.h>
|
||||
|
||||
|
||||
static bool TestX25519() {
|
||||
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
|
||||
static const uint8_t kScalar1[32] = {
|
||||
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
|
||||
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
|
||||
0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4,
|
||||
};
|
||||
static const uint8_t kPoint1[32] = {
|
||||
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1,
|
||||
0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3,
|
||||
0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
|
||||
};
|
||||
|
||||
uint8_t out[32];
|
||||
X25519(out, kScalar1, kPoint1);
|
||||
|
||||
static const uint8_t kExpected1[32] = {
|
||||
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
|
||||
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
|
||||
0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
|
||||
};
|
||||
if (memcmp(kExpected1, out, sizeof(out)) != 0) {
|
||||
fprintf(stderr, "X25519 test one failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint8_t kScalar2[32] = {
|
||||
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
|
||||
0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea,
|
||||
0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d,
|
||||
};
|
||||
static const uint8_t kPoint2[32] = {
|
||||
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95,
|
||||
0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0,
|
||||
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
|
||||
};
|
||||
|
||||
X25519(out, kScalar2, kPoint2);
|
||||
|
||||
static const uint8_t kExpected2[32] = {
|
||||
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
|
||||
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
|
||||
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
|
||||
};
|
||||
if (memcmp(kExpected2, out, sizeof(out)) != 0) {
|
||||
fprintf(stderr, "X25519 test two failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestX25519SmallOrder() {
|
||||
static const uint8_t kSmallOrderPoint[32] = {
|
||||
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
|
||||
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
|
||||
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8,
|
||||
};
|
||||
|
||||
uint8_t out[32], private_key[32];
|
||||
memset(private_key, 0x11, sizeof(private_key));
|
||||
|
||||
if (X25519(out, private_key, kSmallOrderPoint)) {
|
||||
fprintf(stderr, "X25519 returned success with a small-order input.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestX25519Iterated() {
|
||||
/* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */
|
||||
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < 1000; i++) {
|
||||
X25519(out, scalar, point);
|
||||
memcpy(point, scalar, sizeof(point));
|
||||
memcpy(scalar, out, sizeof(scalar));
|
||||
}
|
||||
|
||||
static const uint8_t kExpected[32] = {
|
||||
0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef,
|
||||
0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60,
|
||||
0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
|
||||
};
|
||||
|
||||
if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
|
||||
fprintf(stderr, "Iterated X25519 test failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (!TestX25519() ||
|
||||
!TestX25519Iterated() ||
|
||||
!TestX25519SmallOrder()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -202,24 +202,7 @@ how to use xors :-) I got it to its final state.
|
||||
#define ITERATIONS 16
|
||||
#define HALF_ITERATIONS 8
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ROTATE(a, n) (_lrotr(a, n))
|
||||
#elif defined(__ICC)
|
||||
#define ROTATE(a, n) (_rotr(a, n))
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 2 && !defined(OPENSSL_NO_ASM) && \
|
||||
!defined(__STRICT_ANSI__) && \
|
||||
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
|
||||
#define ROTATE(a, n) \
|
||||
({ \
|
||||
unsigned int ret; \
|
||||
asm("rorl %1,%0" : "=r"(ret) : "I"(n), "0"(a) : "cc"); \
|
||||
ret; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef ROTATE
|
||||
#define ROTATE(a, n) (((a) >> (n)) + ((a) << (32 - (n))))
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
+33
-11
@@ -62,30 +62,52 @@
|
||||
|
||||
|
||||
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
|
||||
int ok = 0;
|
||||
BIGNUM q;
|
||||
|
||||
*ret = 0;
|
||||
BN_init(&q);
|
||||
if (!BN_set_word(&q, 1)) {
|
||||
|
||||
BN_CTX *ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
int ok = 0;
|
||||
|
||||
/* Check |pub_key| is greater than 1. */
|
||||
BIGNUM *tmp = BN_CTX_get(ctx);
|
||||
if (tmp == NULL ||
|
||||
!BN_set_word(tmp, 1)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_cmp(pub_key, &q) <= 0) {
|
||||
if (BN_cmp(pub_key, tmp) <= 0) {
|
||||
*ret |= DH_CHECK_PUBKEY_TOO_SMALL;
|
||||
}
|
||||
if (!BN_copy(&q, dh->p) ||
|
||||
!BN_sub_word(&q, 1)) {
|
||||
|
||||
/* Check |pub_key| is less than |dh->p| - 1. */
|
||||
if (!BN_copy(tmp, dh->p) ||
|
||||
!BN_sub_word(tmp, 1)) {
|
||||
goto err;
|
||||
}
|
||||
if (BN_cmp(pub_key, &q) >= 0) {
|
||||
if (BN_cmp(pub_key, tmp) >= 0) {
|
||||
*ret |= DH_CHECK_PUBKEY_TOO_LARGE;
|
||||
}
|
||||
|
||||
if (dh->q != NULL) {
|
||||
/* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
|
||||
* groups which are not safe primes but pick a generator on a prime-order
|
||||
* subgroup of size |dh->q|. */
|
||||
if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_is_one(tmp)) {
|
||||
*ret |= DH_CHECK_PUBKEY_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_free(&q);
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
+5
-9
@@ -74,7 +74,7 @@
|
||||
static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
|
||||
|
||||
DH *DH_new(void) {
|
||||
DH *dh = (DH *)OPENSSL_malloc(sizeof(DH));
|
||||
DH *dh = OPENSSL_malloc(sizeof(DH));
|
||||
if (dh == NULL) {
|
||||
OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
@@ -85,11 +85,7 @@ DH *DH_new(void) {
|
||||
CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
|
||||
|
||||
dh->references = 1;
|
||||
if (!CRYPTO_new_ex_data(&g_ex_data_class, dh, &dh->ex_data)) {
|
||||
CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
|
||||
OPENSSL_free(dh);
|
||||
return NULL;
|
||||
}
|
||||
CRYPTO_new_ex_data(&dh->ex_data);
|
||||
|
||||
return dh;
|
||||
}
|
||||
@@ -448,11 +444,11 @@ DH *DHparams_dup(const DH *dh) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
|
||||
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
|
||||
int index;
|
||||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
|
||||
dup_func, free_func)) {
|
||||
if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func,
|
||||
free_func)) {
|
||||
return -1;
|
||||
}
|
||||
return index;
|
||||
|
||||
+57
-1
@@ -72,12 +72,14 @@
|
||||
|
||||
static bool RunBasicTests();
|
||||
static bool RunRFC5114Tests();
|
||||
static bool TestBadY();
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!RunBasicTests() ||
|
||||
!RunRFC5114Tests()) {
|
||||
!RunRFC5114Tests() ||
|
||||
!TestBadY()) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
@@ -477,3 +479,57 @@ static bool RunRFC5114Tests() {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP
|
||||
// Group with 224-bit Prime Order Subgroup (section 2.2).
|
||||
static const uint8_t kRFC5114_2048_224BadY[] = {
|
||||
0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3,
|
||||
0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad,
|
||||
0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20,
|
||||
0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67,
|
||||
0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88,
|
||||
0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83,
|
||||
0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f,
|
||||
0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8,
|
||||
0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2,
|
||||
0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70,
|
||||
0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f,
|
||||
0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66,
|
||||
0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22,
|
||||
0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44,
|
||||
0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d,
|
||||
0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed,
|
||||
0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01,
|
||||
0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a,
|
||||
0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72,
|
||||
0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2,
|
||||
0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89,
|
||||
0x93, 0x74, 0x89, 0x59,
|
||||
};
|
||||
|
||||
static bool TestBadY() {
|
||||
ScopedDH dh(DH_get_2048_224(nullptr));
|
||||
ScopedBIGNUM pub_key(
|
||||
BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr));
|
||||
if (!dh || !pub_key || !DH_generate_key(dh.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int flags;
|
||||
if (!DH_check_pub_key(dh.get(), pub_key.get(), &flags)) {
|
||||
return false;
|
||||
}
|
||||
if (!(flags & DH_CHECK_PUBKEY_INVALID)) {
|
||||
fprintf(stderr, "DH_check_pub_key did not reject the key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> result(DH_size(dh.get()));
|
||||
if (DH_compute_key(result.data(), pub_key.get(), dh.get()) >= 0) {
|
||||
fprintf(stderr, "DH_compute_key unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+119
-132
@@ -55,182 +55,169 @@
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../bn/internal.h"
|
||||
|
||||
|
||||
#if BN_BITS2 == 32
|
||||
#define TOBN(lo, hi) lo, hi
|
||||
#elif BN_BITS2 == 64
|
||||
#define TOBN(lo, hi) ((BN_ULONG)hi << 32 | lo)
|
||||
#else
|
||||
#error "unsupported BN_BITS2"
|
||||
#endif
|
||||
|
||||
static const BN_ULONG dh1024_160_p[] = {
|
||||
TOBN(0x2E4A4371, 0xDF1FB2BC), TOBN(0x6D4DA708, 0xE68CFDA7),
|
||||
TOBN(0x365C1A65, 0x45BF37DF), TOBN(0x0DC8B4BD, 0xA151AF5F),
|
||||
TOBN(0xF55BCCC0, 0xFAA31A4F), TOBN(0xE5644738, 0x4EFFD6FA),
|
||||
TOBN(0x219A7372, 0x98488E9C), TOBN(0x90C4BD70, 0xACCBDD7D),
|
||||
TOBN(0xD49B83BF, 0x24975C3C), TOBN(0xA9061123, 0x13ECB4AE),
|
||||
TOBN(0x2EE652C0, 0x9838EF1E), TOBN(0x75A23D18, 0x6073E286),
|
||||
TOBN(0x52D23B61, 0x9A6A9DCA), TOBN(0xFB06A3C6, 0x52C99FBC),
|
||||
TOBN(0xAE5D54EC, 0xDE92DE5E), TOBN(0xA080E01D, 0xB10B8F96),
|
||||
TOBN(0xDF1FB2BC, 0x2E4A4371), TOBN(0xE68CFDA7, 0x6D4DA708),
|
||||
TOBN(0x45BF37DF, 0x365C1A65), TOBN(0xA151AF5F, 0x0DC8B4BD),
|
||||
TOBN(0xFAA31A4F, 0xF55BCCC0), TOBN(0x4EFFD6FA, 0xE5644738),
|
||||
TOBN(0x98488E9C, 0x219A7372), TOBN(0xACCBDD7D, 0x90C4BD70),
|
||||
TOBN(0x24975C3C, 0xD49B83BF), TOBN(0x13ECB4AE, 0xA9061123),
|
||||
TOBN(0x9838EF1E, 0x2EE652C0), TOBN(0x6073E286, 0x75A23D18),
|
||||
TOBN(0x9A6A9DCA, 0x52D23B61), TOBN(0x52C99FBC, 0xFB06A3C6),
|
||||
TOBN(0xDE92DE5E, 0xAE5D54EC), TOBN(0xB10B8F96, 0xA080E01D),
|
||||
};
|
||||
static const BN_ULONG dh1024_160_g[] = {
|
||||
TOBN(0x22B3B2E5, 0x855E6EEB), TOBN(0xF97C2A24, 0x858F4DCE),
|
||||
TOBN(0x18D08BC8, 0x2D779D59), TOBN(0x8E73AFA3, 0xD662A4D1),
|
||||
TOBN(0x69B6A28A, 0x1DBF0A01), TOBN(0x7A091F53, 0xA6A24C08),
|
||||
TOBN(0x63F80A76, 0x909D0D22), TOBN(0xB9A92EE1, 0xD7FBD7D3),
|
||||
TOBN(0x9E2749F4, 0x5E91547F), TOBN(0xB01B886A, 0x160217B4),
|
||||
TOBN(0x5504F213, 0x777E690F), TOBN(0x5C41564B, 0x266FEA1E),
|
||||
TOBN(0x14266D31, 0xD6406CFF), TOBN(0x58AC507F, 0xF8104DD2),
|
||||
TOBN(0xEFB99905, 0x6765A442), TOBN(0xC3FD3412, 0xA4D1CBD5),
|
||||
TOBN(0x855E6EEB, 0x22B3B2E5), TOBN(0x858F4DCE, 0xF97C2A24),
|
||||
TOBN(0x2D779D59, 0x18D08BC8), TOBN(0xD662A4D1, 0x8E73AFA3),
|
||||
TOBN(0x1DBF0A01, 0x69B6A28A), TOBN(0xA6A24C08, 0x7A091F53),
|
||||
TOBN(0x909D0D22, 0x63F80A76), TOBN(0xD7FBD7D3, 0xB9A92EE1),
|
||||
TOBN(0x5E91547F, 0x9E2749F4), TOBN(0x160217B4, 0xB01B886A),
|
||||
TOBN(0x777E690F, 0x5504F213), TOBN(0x266FEA1E, 0x5C41564B),
|
||||
TOBN(0xD6406CFF, 0x14266D31), TOBN(0xF8104DD2, 0x58AC507F),
|
||||
TOBN(0x6765A442, 0xEFB99905), TOBN(0xA4D1CBD5, 0xC3FD3412),
|
||||
};
|
||||
static const BN_ULONG dh1024_160_q[] = {
|
||||
TOBN(0x49462353, 0x64B7CB9D), TOBN(0x8ABA4E7D, 0x81A8DF27), 0xF518AA87,
|
||||
TOBN(0x64B7CB9D, 0x49462353), TOBN(0x81A8DF27, 0x8ABA4E7D), 0xF518AA87,
|
||||
};
|
||||
|
||||
static const BN_ULONG dh2048_224_p[] = {
|
||||
TOBN(0x0C10E64F, 0x0AC4DFFE), TOBN(0x4E71B81C, 0xCF9DE538),
|
||||
TOBN(0xFFA31F71, 0x7EF363E2), TOBN(0x6B8E75B9, 0xE3FB73C1),
|
||||
TOBN(0x4BA80A29, 0xC9B53DCF), TOBN(0x16E79763, 0x23F10B0E),
|
||||
TOBN(0x13042E9B, 0xC52172E4), TOBN(0xC928B2B9, 0xBE60E69C),
|
||||
TOBN(0xB9E587E8, 0x80CD86A1), TOBN(0x98C641A4, 0x315D75E1),
|
||||
TOBN(0x44328387, 0xCDF93ACC), TOBN(0xDC0A486D, 0x15987D9A),
|
||||
TOBN(0x1FD5A074, 0x7310F712), TOBN(0xDE31EFDC, 0x278273C7),
|
||||
TOBN(0x415D9330, 0x1602E714), TOBN(0xBC8985DB, 0x81286130),
|
||||
TOBN(0x70918836, 0xB3BF8A31), TOBN(0xB9C49708, 0x6A00E0A0),
|
||||
TOBN(0x8BBC27BE, 0xC6BA0B2C), TOBN(0xED34DBF6, 0xC9F98D11),
|
||||
TOBN(0xB6C12207, 0x7AD5B7D0), TOBN(0x55B7394B, 0xD91E8FEF),
|
||||
TOBN(0xEFDA4DF8, 0x9037C9ED), TOBN(0xAD6AC212, 0x6D3F8152),
|
||||
TOBN(0x1274A0A6, 0x1DE6B85A), TOBN(0x309C180E, 0xEB3D688A),
|
||||
TOBN(0x7BA1DF15, 0xAF9A3C40), TOBN(0xF95A56DB, 0xE6FA141D),
|
||||
TOBN(0xB61D0A75, 0xB54B1597), TOBN(0x683B9FD1, 0xA20D64E5),
|
||||
TOBN(0x9559C51F, 0xD660FAA7), TOBN(0x9123A9D0, 0xAD107E1E),
|
||||
TOBN(0x0AC4DFFE, 0x0C10E64F), TOBN(0xCF9DE538, 0x4E71B81C),
|
||||
TOBN(0x7EF363E2, 0xFFA31F71), TOBN(0xE3FB73C1, 0x6B8E75B9),
|
||||
TOBN(0xC9B53DCF, 0x4BA80A29), TOBN(0x23F10B0E, 0x16E79763),
|
||||
TOBN(0xC52172E4, 0x13042E9B), TOBN(0xBE60E69C, 0xC928B2B9),
|
||||
TOBN(0x80CD86A1, 0xB9E587E8), TOBN(0x315D75E1, 0x98C641A4),
|
||||
TOBN(0xCDF93ACC, 0x44328387), TOBN(0x15987D9A, 0xDC0A486D),
|
||||
TOBN(0x7310F712, 0x1FD5A074), TOBN(0x278273C7, 0xDE31EFDC),
|
||||
TOBN(0x1602E714, 0x415D9330), TOBN(0x81286130, 0xBC8985DB),
|
||||
TOBN(0xB3BF8A31, 0x70918836), TOBN(0x6A00E0A0, 0xB9C49708),
|
||||
TOBN(0xC6BA0B2C, 0x8BBC27BE), TOBN(0xC9F98D11, 0xED34DBF6),
|
||||
TOBN(0x7AD5B7D0, 0xB6C12207), TOBN(0xD91E8FEF, 0x55B7394B),
|
||||
TOBN(0x9037C9ED, 0xEFDA4DF8), TOBN(0x6D3F8152, 0xAD6AC212),
|
||||
TOBN(0x1DE6B85A, 0x1274A0A6), TOBN(0xEB3D688A, 0x309C180E),
|
||||
TOBN(0xAF9A3C40, 0x7BA1DF15), TOBN(0xE6FA141D, 0xF95A56DB),
|
||||
TOBN(0xB54B1597, 0xB61D0A75), TOBN(0xA20D64E5, 0x683B9FD1),
|
||||
TOBN(0xD660FAA7, 0x9559C51F), TOBN(0xAD107E1E, 0x9123A9D0),
|
||||
};
|
||||
|
||||
static const BN_ULONG dh2048_224_g[] = {
|
||||
TOBN(0x191F2BFA, 0x84B890D3), TOBN(0x2A7065B3, 0x81BC087F),
|
||||
TOBN(0xF6EC0179, 0x19C418E1), TOBN(0x71CFFF4C, 0x7B5A0F1C),
|
||||
TOBN(0x9B6AA4BD, 0xEDFE72FE), TOBN(0x94B30269, 0x81E1BCFE),
|
||||
TOBN(0x8D6C0191, 0x566AFBB4), TOBN(0x409D13CD, 0xB539CCE3),
|
||||
TOBN(0x5F2FF381, 0x6AA21E7F), TOBN(0x770589EF, 0xD9E263E4),
|
||||
TOBN(0xD19963DD, 0x10E183ED), TOBN(0x150B8EEB, 0xB70A8137),
|
||||
TOBN(0x28C8F8AC, 0x051AE3D4), TOBN(0x0C1AB15B, 0xBB77A86F),
|
||||
TOBN(0x16A330EF, 0x6E3025E3), TOBN(0xD6F83456, 0x19529A45),
|
||||
TOBN(0x118E98D1, 0xF180EB34), TOBN(0x50717CBE, 0xB5F6C6B2),
|
||||
TOBN(0xDA7460CD, 0x09939D54), TOBN(0x22EA1ED4, 0xE2471504),
|
||||
TOBN(0x521BC98A, 0xB8A762D0), TOBN(0x5AC1348B, 0xF4D02727),
|
||||
TOBN(0x1999024A, 0xC1766910), TOBN(0xA8D66AD7, 0xBE5E9001),
|
||||
TOBN(0x620A8652, 0xC57DB17C), TOBN(0x00C29F52, 0xAB739D77),
|
||||
TOBN(0xA70C4AFA, 0xDD921F01), TOBN(0x10B9A6F0, 0xA6824A4E),
|
||||
TOBN(0xCFE4FFE3, 0x74866A08), TOBN(0x89998CAF, 0x6CDEBE7B),
|
||||
TOBN(0x8FFDAC50, 0x9DF30B5C), TOBN(0x4F2D9AE3, 0xAC4032EF),
|
||||
TOBN(0x84B890D3, 0x191F2BFA), TOBN(0x81BC087F, 0x2A7065B3),
|
||||
TOBN(0x19C418E1, 0xF6EC0179), TOBN(0x7B5A0F1C, 0x71CFFF4C),
|
||||
TOBN(0xEDFE72FE, 0x9B6AA4BD), TOBN(0x81E1BCFE, 0x94B30269),
|
||||
TOBN(0x566AFBB4, 0x8D6C0191), TOBN(0xB539CCE3, 0x409D13CD),
|
||||
TOBN(0x6AA21E7F, 0x5F2FF381), TOBN(0xD9E263E4, 0x770589EF),
|
||||
TOBN(0x10E183ED, 0xD19963DD), TOBN(0xB70A8137, 0x150B8EEB),
|
||||
TOBN(0x051AE3D4, 0x28C8F8AC), TOBN(0xBB77A86F, 0x0C1AB15B),
|
||||
TOBN(0x6E3025E3, 0x16A330EF), TOBN(0x19529A45, 0xD6F83456),
|
||||
TOBN(0xF180EB34, 0x118E98D1), TOBN(0xB5F6C6B2, 0x50717CBE),
|
||||
TOBN(0x09939D54, 0xDA7460CD), TOBN(0xE2471504, 0x22EA1ED4),
|
||||
TOBN(0xB8A762D0, 0x521BC98A), TOBN(0xF4D02727, 0x5AC1348B),
|
||||
TOBN(0xC1766910, 0x1999024A), TOBN(0xBE5E9001, 0xA8D66AD7),
|
||||
TOBN(0xC57DB17C, 0x620A8652), TOBN(0xAB739D77, 0x00C29F52),
|
||||
TOBN(0xDD921F01, 0xA70C4AFA), TOBN(0xA6824A4E, 0x10B9A6F0),
|
||||
TOBN(0x74866A08, 0xCFE4FFE3), TOBN(0x6CDEBE7B, 0x89998CAF),
|
||||
TOBN(0x9DF30B5C, 0x8FFDAC50), TOBN(0xAC4032EF, 0x4F2D9AE3),
|
||||
};
|
||||
|
||||
static const BN_ULONG dh2048_224_q[] = {
|
||||
TOBN(0xB36371EB, 0xBF389A99), TOBN(0x4738CEBC, 0x1F80535A),
|
||||
TOBN(0x99717710, 0xC58D93FE), 0x801C0D34,
|
||||
TOBN(0xBF389A99, 0xB36371EB), TOBN(0x1F80535A, 0x4738CEBC),
|
||||
TOBN(0xC58D93FE, 0x99717710), 0x801C0D34,
|
||||
};
|
||||
|
||||
static const BN_ULONG dh2048_256_p[] = {
|
||||
TOBN(0x1E1A1597, 0xDB094AE9), TOBN(0xD7EF09CA, 0x693877FA),
|
||||
TOBN(0x6E11715F, 0x6116D227), TOBN(0xC198AF12, 0xA4B54330),
|
||||
TOBN(0xD7014103, 0x75F26375), TOBN(0x54E710C3, 0xC3A3960A),
|
||||
TOBN(0xBD0BE621, 0xDED4010A), TOBN(0x89962856, 0xC0B857F6),
|
||||
TOBN(0x71506026, 0xB3CA3F79), TOBN(0xE6B486F6, 0x1CCACB83),
|
||||
TOBN(0x14056425, 0x67E144E5), TOBN(0xA41825D9, 0xF6A167B5),
|
||||
TOBN(0x96524D8E, 0x3AD83477), TOBN(0x51BFA4AB, 0xF13C6D9A),
|
||||
TOBN(0x35488A0E, 0x2D525267), TOBN(0xCAA6B790, 0xB63ACAE1),
|
||||
TOBN(0x81B23F76, 0x4FDB70C5), TOBN(0x12307F5C, 0xBC39A0BF),
|
||||
TOBN(0xB1E59BB8, 0xB941F54E), TOBN(0xD45F9088, 0x6C5BFC11),
|
||||
TOBN(0x4275BF7B, 0x22E0B1EF), TOBN(0x5B4758C0, 0x91F9E672),
|
||||
TOBN(0x6BCF67ED, 0x5A8A9D30), TOBN(0x97517ABD, 0x209E0C64),
|
||||
TOBN(0x830E9A7C, 0x3BF4296D), TOBN(0x34096FAA, 0x16C3D911),
|
||||
TOBN(0x61B2AA30, 0xFAF7DF45), TOBN(0xD61957D4, 0xE00DF8F1),
|
||||
TOBN(0x435E3B00, 0x5D2CEED4), TOBN(0x660DD0F2, 0x8CEEF608),
|
||||
TOBN(0x65195999, 0xFFBBD19C), TOBN(0xB4B6663C, 0x87A8E61D),
|
||||
TOBN(0xDB094AE9, 0x1E1A1597), TOBN(0x693877FA, 0xD7EF09CA),
|
||||
TOBN(0x6116D227, 0x6E11715F), TOBN(0xA4B54330, 0xC198AF12),
|
||||
TOBN(0x75F26375, 0xD7014103), TOBN(0xC3A3960A, 0x54E710C3),
|
||||
TOBN(0xDED4010A, 0xBD0BE621), TOBN(0xC0B857F6, 0x89962856),
|
||||
TOBN(0xB3CA3F79, 0x71506026), TOBN(0x1CCACB83, 0xE6B486F6),
|
||||
TOBN(0x67E144E5, 0x14056425), TOBN(0xF6A167B5, 0xA41825D9),
|
||||
TOBN(0x3AD83477, 0x96524D8E), TOBN(0xF13C6D9A, 0x51BFA4AB),
|
||||
TOBN(0x2D525267, 0x35488A0E), TOBN(0xB63ACAE1, 0xCAA6B790),
|
||||
TOBN(0x4FDB70C5, 0x81B23F76), TOBN(0xBC39A0BF, 0x12307F5C),
|
||||
TOBN(0xB941F54E, 0xB1E59BB8), TOBN(0x6C5BFC11, 0xD45F9088),
|
||||
TOBN(0x22E0B1EF, 0x4275BF7B), TOBN(0x91F9E672, 0x5B4758C0),
|
||||
TOBN(0x5A8A9D30, 0x6BCF67ED), TOBN(0x209E0C64, 0x97517ABD),
|
||||
TOBN(0x3BF4296D, 0x830E9A7C), TOBN(0x16C3D911, 0x34096FAA),
|
||||
TOBN(0xFAF7DF45, 0x61B2AA30), TOBN(0xE00DF8F1, 0xD61957D4),
|
||||
TOBN(0x5D2CEED4, 0x435E3B00), TOBN(0x8CEEF608, 0x660DD0F2),
|
||||
TOBN(0xFFBBD19C, 0x65195999), TOBN(0x87A8E61D, 0xB4B6663C),
|
||||
};
|
||||
static const BN_ULONG dh2048_256_g[] = {
|
||||
TOBN(0x6CC41659, 0x664B4C0F), TOBN(0xEF98C582, 0x5E2327CF),
|
||||
TOBN(0xD4795451, 0xD647D148), TOBN(0x90F00EF8, 0x2F630784),
|
||||
TOBN(0x1DB246C3, 0x184B523D), TOBN(0xCDC67EB6, 0xC7891428),
|
||||
TOBN(0x0DF92B52, 0x7FD02837), TOBN(0x64E0EC37, 0xB3353BBB),
|
||||
TOBN(0x57CD0915, 0xECD06E15), TOBN(0xDF016199, 0xB7D2BBD2),
|
||||
TOBN(0x052588B9, 0xC8484B1E), TOBN(0x13D3FE14, 0xDB2A3B73),
|
||||
TOBN(0xD182EA0A, 0xD052B985), TOBN(0xE83B9C80, 0xA4BD1BFF),
|
||||
TOBN(0xFB3F2E55, 0xDFC967C1), TOBN(0x767164E1, 0xB5045AF2),
|
||||
TOBN(0x6F2F9193, 0x1D14348F), TOBN(0x428EBC83, 0x64E67982),
|
||||
TOBN(0x82D6ED38, 0x8AC376D2), TOBN(0xAAB8A862, 0x777DE62A),
|
||||
TOBN(0xE9EC144B, 0xDDF463E5), TOBN(0xC77A57F2, 0x0196F931),
|
||||
TOBN(0x41000A65, 0xA55AE313), TOBN(0xC28CBB18, 0x901228F8),
|
||||
TOBN(0x7E8C6F62, 0xBC3773BF), TOBN(0x0C6B47B1, 0xBE3A6C1B),
|
||||
TOBN(0xAC0BB555, 0xFF4FED4A), TOBN(0x77BE463F, 0x10DBC150),
|
||||
TOBN(0x1A0BA125, 0x07F4793A), TOBN(0x21EF2054, 0x4CA7B18F),
|
||||
TOBN(0x60EDBD48, 0x2E775066), TOBN(0x73134D0B, 0x3FB32C9B),
|
||||
TOBN(0x664B4C0F, 0x6CC41659), TOBN(0x5E2327CF, 0xEF98C582),
|
||||
TOBN(0xD647D148, 0xD4795451), TOBN(0x2F630784, 0x90F00EF8),
|
||||
TOBN(0x184B523D, 0x1DB246C3), TOBN(0xC7891428, 0xCDC67EB6),
|
||||
TOBN(0x7FD02837, 0x0DF92B52), TOBN(0xB3353BBB, 0x64E0EC37),
|
||||
TOBN(0xECD06E15, 0x57CD0915), TOBN(0xB7D2BBD2, 0xDF016199),
|
||||
TOBN(0xC8484B1E, 0x052588B9), TOBN(0xDB2A3B73, 0x13D3FE14),
|
||||
TOBN(0xD052B985, 0xD182EA0A), TOBN(0xA4BD1BFF, 0xE83B9C80),
|
||||
TOBN(0xDFC967C1, 0xFB3F2E55), TOBN(0xB5045AF2, 0x767164E1),
|
||||
TOBN(0x1D14348F, 0x6F2F9193), TOBN(0x64E67982, 0x428EBC83),
|
||||
TOBN(0x8AC376D2, 0x82D6ED38), TOBN(0x777DE62A, 0xAAB8A862),
|
||||
TOBN(0xDDF463E5, 0xE9EC144B), TOBN(0x0196F931, 0xC77A57F2),
|
||||
TOBN(0xA55AE313, 0x41000A65), TOBN(0x901228F8, 0xC28CBB18),
|
||||
TOBN(0xBC3773BF, 0x7E8C6F62), TOBN(0xBE3A6C1B, 0x0C6B47B1),
|
||||
TOBN(0xFF4FED4A, 0xAC0BB555), TOBN(0x10DBC150, 0x77BE463F),
|
||||
TOBN(0x07F4793A, 0x1A0BA125), TOBN(0x4CA7B18F, 0x21EF2054),
|
||||
TOBN(0x2E775066, 0x60EDBD48), TOBN(0x3FB32C9B, 0x73134D0B),
|
||||
};
|
||||
static const BN_ULONG dh2048_256_q[] = {
|
||||
TOBN(0x64F5FBD3, 0xA308B0FE), TOBN(0x1EB3750B, 0x99B1A47D),
|
||||
TOBN(0x40129DA2, 0xB4479976), TOBN(0xA709A097, 0x8CF83642),
|
||||
TOBN(0xA308B0FE, 0x64F5FBD3), TOBN(0x99B1A47D, 0x1EB3750B),
|
||||
TOBN(0xB4479976, 0x40129DA2), TOBN(0x8CF83642, 0xA709A097),
|
||||
};
|
||||
|
||||
/* dh1024_safe_prime_1 is hard-coded in Apache httpd 2.2,
|
||||
* modules/ssl/ssl_engine_dh.c. */
|
||||
static const BN_ULONG dh1024_safe_prime_1[] = {
|
||||
TOBN(0x24218EB3, 0xE7393E0F), TOBN(0xE2BD68B0, 0x7DE0F4D6),
|
||||
TOBN(0x88AEAA74, 0x07DD62DB), TOBN(0x9DDD3305, 0x10EA9FCC),
|
||||
TOBN(0x74087D15, 0xA7DBCA78), TOBN(0x78045B07, 0xDAE88600),
|
||||
TOBN(0x1AAD3B72, 0x33168A46), TOBN(0x7BEDDCFD, 0xFF590137),
|
||||
TOBN(0x7A635E81, 0xFE324A46), TOBN(0x420B2A29, 0x5AC179BA),
|
||||
TOBN(0x177E16D5, 0x13B4B4D7), TOBN(0x639C72FB, 0x849F912E),
|
||||
TOBN(0x98BCE951, 0xB88174CB), TOBN(0xA45F520B, 0x0C84D239),
|
||||
TOBN(0x4AFD0AD5, 0x36D693D3), TOBN(0xCBBBDC19, 0xD67DE440),
|
||||
TOBN(0xE7393E0F, 0x24218EB3), TOBN(0x7DE0F4D6, 0xE2BD68B0),
|
||||
TOBN(0x07DD62DB, 0x88AEAA74), TOBN(0x10EA9FCC, 0x9DDD3305),
|
||||
TOBN(0xA7DBCA78, 0x74087D15), TOBN(0xDAE88600, 0x78045B07),
|
||||
TOBN(0x33168A46, 0x1AAD3B72), TOBN(0xFF590137, 0x7BEDDCFD),
|
||||
TOBN(0xFE324A46, 0x7A635E81), TOBN(0x5AC179BA, 0x420B2A29),
|
||||
TOBN(0x13B4B4D7, 0x177E16D5), TOBN(0x849F912E, 0x639C72FB),
|
||||
TOBN(0xB88174CB, 0x98BCE951), TOBN(0x0C84D239, 0xA45F520B),
|
||||
TOBN(0x36D693D3, 0x4AFD0AD5), TOBN(0xD67DE440, 0xCBBBDC19),
|
||||
};
|
||||
|
||||
/* dh1024_safe_prime_2 is hard-coded in nginx,
|
||||
* src/event/ngx_event_openssl.c. */
|
||||
static const BN_ULONG dh1024_safe_prime_2[] = {
|
||||
TOBN(0xCFE16B9B, 0x071DF045), TOBN(0x146757DA, 0x88D0F65D),
|
||||
TOBN(0x58FAFD49, 0x4A63AB1E), TOBN(0xEF9EA027, 0x35D8CECE),
|
||||
TOBN(0x70CC9A50, 0x25ECE662), TOBN(0x81DC2CA7, 0xF29BA5DF),
|
||||
TOBN(0xF7D36CC8, 0x8F68B076), TOBN(0xA757E304, 0x60E91A92),
|
||||
TOBN(0x9BE67780, 0x87A2BC04), TOBN(0xA5FDF1D2, 0xBEECA565),
|
||||
TOBN(0x922614C5, 0x5CCBBAA8), TOBN(0xE710800C, 0x6C030276),
|
||||
TOBN(0x0FB3504C, 0x08EED4EB), TOBN(0x68B42D4B, 0xD958A3F5),
|
||||
TOBN(0x80E9CFDB, 0x7C43FCF5), TOBN(0xD8467490, 0xBBBC2DCA),
|
||||
TOBN(0x071DF045, 0xCFE16B9B), TOBN(0x88D0F65D, 0x146757DA),
|
||||
TOBN(0x4A63AB1E, 0x58FAFD49), TOBN(0x35D8CECE, 0xEF9EA027),
|
||||
TOBN(0x25ECE662, 0x70CC9A50), TOBN(0xF29BA5DF, 0x81DC2CA7),
|
||||
TOBN(0x8F68B076, 0xF7D36CC8), TOBN(0x60E91A92, 0xA757E304),
|
||||
TOBN(0x87A2BC04, 0x9BE67780), TOBN(0xBEECA565, 0xA5FDF1D2),
|
||||
TOBN(0x5CCBBAA8, 0x922614C5), TOBN(0x6C030276, 0xE710800C),
|
||||
TOBN(0x08EED4EB, 0x0FB3504C), TOBN(0xD958A3F5, 0x68B42D4B),
|
||||
TOBN(0x7C43FCF5, 0x80E9CFDB), TOBN(0xBBBC2DCA, 0xD8467490),
|
||||
};
|
||||
|
||||
/* dh1024_safe_prime_3 is offered as a parameter by several high-traffic sites,
|
||||
* including mozilla.org, as of Jan 2015. */
|
||||
static const BN_ULONG dh1024_safe_prime_3[] = {
|
||||
TOBN(0x349E721B, 0x671746AE), TOBN(0xD75E93B2, 0x258A0655),
|
||||
TOBN(0x25592EB6, 0xD425E6FB), TOBN(0xBF7CDD9A, 0x0C46AB04),
|
||||
TOBN(0x28968680, 0x0AD0BC99), TOBN(0xD0B7EB49, 0xF53907FB),
|
||||
TOBN(0xEBC85C1D, 0x202EABB3), TOBN(0x364D8C71, 0x3129C693),
|
||||
TOBN(0x2D46F195, 0x53728351), TOBN(0x8C76CC85, 0xDF326DD6),
|
||||
TOBN(0x9188E24E, 0xF898B3F9), TOBN(0x2855DFD2, 0x95EFB13C),
|
||||
TOBN(0x7B2241FE, 0x1F5DAC48), TOBN(0x99A13D9F, 0x117B6BF7),
|
||||
TOBN(0x3A3468C7, 0x0F97CDDA), TOBN(0x74A8297B, 0xC9BBF5F7)};
|
||||
TOBN(0x671746AE, 0x349E721B), TOBN(0x258A0655, 0xD75E93B2),
|
||||
TOBN(0xD425E6FB, 0x25592EB6), TOBN(0x0C46AB04, 0xBF7CDD9A),
|
||||
TOBN(0x0AD0BC99, 0x28968680), TOBN(0xF53907FB, 0xD0B7EB49),
|
||||
TOBN(0x202EABB3, 0xEBC85C1D), TOBN(0x3129C693, 0x364D8C71),
|
||||
TOBN(0x53728351, 0x2D46F195), TOBN(0xDF326DD6, 0x8C76CC85),
|
||||
TOBN(0xF898B3F9, 0x9188E24E), TOBN(0x95EFB13C, 0x2855DFD2),
|
||||
TOBN(0x1F5DAC48, 0x7B2241FE), TOBN(0x117B6BF7, 0x99A13D9F),
|
||||
TOBN(0x0F97CDDA, 0x3A3468C7), TOBN(0xC9BBF5F7, 0x74A8297B)};
|
||||
|
||||
/* dh1024_safe_prime_4 is hard-coded in Apache httpd 2.0,
|
||||
* modules/ssl/ssl_engine_dh.c. */
|
||||
static const BN_ULONG dh1024_safe_prime_4[] = {
|
||||
TOBN(0x0DD5C86B, 0x5085E21F), TOBN(0xD823C650, 0x871538DF),
|
||||
TOBN(0x262E56A8, 0x125136F7), TOBN(0x839EB5DB, 0x974E9EF1),
|
||||
TOBN(0x1B13A63C, 0xEA9BAD99), TOBN(0x3D76E05E, 0x6044CF02),
|
||||
TOBN(0x1BAC9B5C, 0x611EBBBE), TOBN(0x4E5327DF, 0x3E371D79),
|
||||
TOBN(0x061CBC05, 0x000E6EDD), TOBN(0x20129B48, 0x2F971F3C),
|
||||
TOBN(0x3048D5A2, 0xA6EF09C4), TOBN(0xCBD523A6, 0xFA15A259),
|
||||
TOBN(0x4A79A770, 0x2A206490), TOBN(0x51BB055E, 0x91B78182),
|
||||
TOBN(0xBDD4798E, 0x7CF180C3), TOBN(0x495BE32C, 0xE6969D3D)};
|
||||
TOBN(0x5085E21F, 0x0DD5C86B), TOBN(0x871538DF, 0xD823C650),
|
||||
TOBN(0x125136F7, 0x262E56A8), TOBN(0x974E9EF1, 0x839EB5DB),
|
||||
TOBN(0xEA9BAD99, 0x1B13A63C), TOBN(0x6044CF02, 0x3D76E05E),
|
||||
TOBN(0x611EBBBE, 0x1BAC9B5C), TOBN(0x3E371D79, 0x4E5327DF),
|
||||
TOBN(0x000E6EDD, 0x061CBC05), TOBN(0x2F971F3C, 0x20129B48),
|
||||
TOBN(0xA6EF09C4, 0x3048D5A2), TOBN(0xFA15A259, 0xCBD523A6),
|
||||
TOBN(0x2A206490, 0x4A79A770), TOBN(0x91B78182, 0x51BB055E),
|
||||
TOBN(0x7CF180C3, 0xBDD4798E), TOBN(0xE6969D3D, 0x495BE32C)};
|
||||
|
||||
static const BN_ULONG bn_two_data[] = {2};
|
||||
|
||||
#define STATIC_BIGNUM(x) \
|
||||
{ \
|
||||
(BN_ULONG *) x, sizeof(x) / sizeof(BN_ULONG), \
|
||||
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
|
||||
}
|
||||
|
||||
struct standard_parameters {
|
||||
BIGNUM p, q, g;
|
||||
};
|
||||
@@ -260,7 +247,7 @@ static const BIGNUM dh1024_safe_prime[] = {
|
||||
STATIC_BIGNUM(dh1024_safe_prime_4)
|
||||
};
|
||||
|
||||
BIGNUM bn_two = STATIC_BIGNUM(bn_two_data);
|
||||
static BIGNUM bn_two = STATIC_BIGNUM(bn_two_data);
|
||||
|
||||
static DH *get_standard_parameters(const struct standard_parameters *params,
|
||||
const ENGINE *engine) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user