Compare commits
No commits in common. 'master' and '3239' have entirely different histories.
9422 changed files with 338390 additions and 1617594 deletions
@ -1,2 +0,0 @@ |
||||
third_party/googletest |
||||
util/bazel-example |
@ -1,50 +0,0 @@ |
||||
# Copyright 2024 The BoringSSL Authors |
||||
# |
||||
# Permission to use, copy, modify, and/or distribute this software for any |
||||
# purpose with or without fee is hereby granted, provided that the above |
||||
# copyright notice and this permission notice appear in all copies. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
||||
# This is a bazelrc file, documented in https://bazel.build/run/bazelrc and |
||||
# specifies default flags when BoringSSL is the root project. It has no effect |
||||
# on downstream projects, which define their own toolchains and configs. |
||||
|
||||
# See https://bazel.build/run/bazelrc#enable_platform_specific_config. |
||||
# This expands to --config=osname which, in turn, expands to the options |
||||
# specified below. |
||||
build --enable_platform_specific_config |
||||
|
||||
# Enable additional checks. |
||||
build --features=layering_check |
||||
build --features=parse_headers |
||||
|
||||
# Bazel has no abstractions for setting C++ versions and expects the root |
||||
# project to use the compiler-specific options for their toolchains. (Bazel only |
||||
# wants the root to set the C++ version for the sake of projects like Abseil |
||||
# whose ABI depends on the C++ version.) |
||||
build:linux --cxxopt=-std=c++17 |
||||
build:macos --cxxopt=-std=c++17 |
||||
build:windows --cxxopt=/std:c++17 |
||||
|
||||
# Our own builds should strictly build without warnings, but we don't add those |
||||
# in targets like other flags because we can't assume all users will have clean |
||||
# builds too. |
||||
build:linux --cxxopt=-Werror |
||||
build:macos --cxxopt=-Werror |
||||
|
||||
# Without setting a minimum macOS version, std::optional does not work. |
||||
build:macos --cxxopt=-mmacosx-version-min=10.15 |
||||
|
||||
# Without /Zc:__cplusplus, MSVC does not define the right value for |
||||
# __cplusplus. See https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ |
||||
build:windows --cxxopt=/Zc:__cplusplus |
||||
|
||||
# https://bazel.build/configure/best-practices#bazelrc-file |
||||
try-import %workspace%/user.bazelrc |
@ -1 +0,0 @@ |
||||
7.4.1 |
@ -1,6 +0,0 @@ |
||||
# BCR Configuration |
||||
|
||||
This directory contains configuration information for BCR. It is patterned after |
||||
the [Publish to BCR app](https://github.com/bazel-contrib/publish-to-bcr/tree/main/templates), |
||||
which we have [opted not to use](https://github.com/bazel-contrib/publish-to-bcr/issues/157). |
||||
However, `presubmit.yml` is used by [our own BCR tooling](../docs/releasing.md). |
@ -1,25 +0,0 @@ |
||||
{ |
||||
"homepage": "https://boringssl.googlesource.com/boringssl/", |
||||
"maintainers": [ |
||||
{ |
||||
"email": "agl@google.com", |
||||
"github": "agl", |
||||
"name": "Adam Langley" |
||||
}, |
||||
{ |
||||
"email": "bbe@google.com", |
||||
"github": "bob-beck", |
||||
"name": "Bob Beck" |
||||
}, |
||||
{ |
||||
"email": "davidben@google.com", |
||||
"github": "davidben", |
||||
"name": "David Benjamin" |
||||
} |
||||
], |
||||
"repository": [ |
||||
"github:google/boringssl" |
||||
], |
||||
"versions": [], |
||||
"yanked_versions": {} |
||||
} |
@ -1,61 +0,0 @@ |
||||
build_targets: &build_targets |
||||
- "@boringssl//:crypto" |
||||
- "@boringssl//:ssl" |
||||
|
||||
matrix: &matrix |
||||
linux_platforms: |
||||
- debian11 |
||||
- ubuntu2204 |
||||
bazel: [7.x] |
||||
tasks: |
||||
verify_targets_on_linux: |
||||
name: Verify build targets on Linux |
||||
platform: ${{ linux_platforms }} |
||||
bazel: ${{ bazel }} |
||||
build_targets: *build_targets |
||||
build_flags: |
||||
- '--cxxopt=-std=c++17' |
||||
verify_targets_on_windows: |
||||
name: Verify build targets on Windows |
||||
platform: windows |
||||
bazel: ${{ bazel }} |
||||
build_targets: *build_targets |
||||
build_flags: |
||||
- '--cxxopt=/std:c++17' |
||||
# Work around https://github.com/bazelbuild/bazel/issues/10472 |
||||
verify_targets_on_macos: |
||||
name: Verify build targets on macOS |
||||
platform: macos |
||||
bazel: ${{ bazel }} |
||||
build_targets: *build_targets |
||||
build_flags: &macos_workaround |
||||
- '--cxxopt=-std=c++17' |
||||
- '--sandbox_block_path=/usr/local' |
||||
bcr_test_module: |
||||
module_path: util/bazel-example |
||||
matrix: *matrix |
||||
tasks: |
||||
run_test_module_on_linux: |
||||
name: Run test module on Linux |
||||
platform: ${{ linux_platforms }} |
||||
bazel: ${{ bazel }} |
||||
build_targets: |
||||
- //... |
||||
build_flags: |
||||
- '--cxxopt=-std=c++17' |
||||
run_test_module_on_windows: |
||||
name: Run test module on Windows |
||||
platform: windows |
||||
bazel: ${{ bazel }} |
||||
build_targets: |
||||
- //... |
||||
build_flags: |
||||
- '--cxxopt=/std:c++17' |
||||
# Work around https://github.com/bazelbuild/bazel/issues/10472 |
||||
run_test_module_on_macos: |
||||
name: Run test module on macOS |
||||
platform: macos |
||||
bazel: ${{ bazel }} |
||||
build_targets: |
||||
- //... |
||||
build_flags: *macos_workaround |
@ -1,5 +0,0 @@ |
||||
{ |
||||
"integrity": "", |
||||
"strip_prefix": "{REPO}-{VERSION}", |
||||
"url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/{REPO}-{TAG}.tar.gz" |
||||
} |
@ -1,41 +1,24 @@ |
||||
/bazel-* |
||||
/build |
||||
/build32 |
||||
/build64 |
||||
/ssl/test/runner/runner |
||||
*.pyc |
||||
build/ |
||||
ssl/test/runner/runner |
||||
*.swp |
||||
*.swo |
||||
/doc/*.html |
||||
/doc/doc.css |
||||
/rust/Cargo.lock |
||||
/rust/bssl-crypto/Cargo.lock |
||||
/rust/target |
||||
/user.bazelrc |
||||
doc/*.html |
||||
doc/doc.css |
||||
|
||||
/util/bazel-example/bazel-* |
||||
/util/bazel-example/MODULE.bazel.lock |
||||
|
||||
/util/bot/android_ndk |
||||
/util/bot/android_sdk/public |
||||
/util/bot/cmake |
||||
/util/bot/golang |
||||
/util/bot/libFuzzer |
||||
/util/bot/libcxx |
||||
/util/bot/libcxxabi |
||||
/util/bot/llvm-build |
||||
/util/bot/llvm-libc |
||||
/util/bot/nasm-win32.exe |
||||
/util/bot/ninja |
||||
/util/bot/perl-win32 |
||||
/util/bot/qemu-static |
||||
/util/bot/sde-linux64 |
||||
/util/bot/sde-linux64.tar.xz |
||||
/util/bot/sde-win32 |
||||
/util/bot/sde-win32.tar.xz |
||||
/util/bot/tools |
||||
/util/bot/win_toolchain |
||||
/util/bot/win_toolchain.json |
||||
|
||||
# Ignore target under any directory. |
||||
target/ |
||||
util/bot/android_tools |
||||
util/bot/cmake-linux64 |
||||
util/bot/cmake-linux64.tar.gz |
||||
util/bot/cmake-mac |
||||
util/bot/cmake-mac.tar.gz |
||||
util/bot/cmake-win32 |
||||
util/bot/cmake-win32.zip |
||||
util/bot/golang |
||||
util/bot/gyp |
||||
util/bot/libFuzzer |
||||
util/bot/llvm-build |
||||
util/bot/perl-win32 |
||||
util/bot/perl-win32.zip |
||||
util/bot/sde-linux64 |
||||
util/bot/sde-linux64.tar.bz2 |
||||
util/bot/win_toolchain.json |
||||
util/bot/yasm-win32.exe |
||||
|
@ -1,50 +0,0 @@ |
||||
# This is the list of BoringSSL's significant contributors. |
||||
# |
||||
# This does not necessarily list everyone who has contributed code, |
||||
# especially since many employees of one corporation may be contributing. |
||||
# To see the full list of contributors, see the revision history in |
||||
# source control. |
||||
Google LLC |
||||
Brian Smith |
||||
Apple Inc |
||||
|
||||
# Additionally, much of the code in BoringSSL is derived from code in the |
||||
# OpenSSL project. We thank the OpenSSL project’s contributors for their |
||||
# work. Some of these contributors are listed below. For the full list of |
||||
# these contributors, see AUTHORS.md in OpenSSL and the revision history |
||||
# in OpenSSL’s source control. |
||||
OpenSSL Software Services, Inc. |
||||
OpenSSL Software Foundation, Inc. |
||||
Andy Polyakov |
||||
Ben Laurie |
||||
Ben Kaduk |
||||
Bernd Edlinger |
||||
Bodo Möller |
||||
David Benjamin |
||||
David von Oheimb |
||||
Dmitry Belyavskiy (Дмитрий Белявский) |
||||
Emilia Käsper |
||||
Eric Young |
||||
Geoff Thorpe |
||||
Holger Reif |
||||
Kurt Roeckx |
||||
Lutz Jänicke |
||||
Mark J. Cox |
||||
Matt Caswell |
||||
Matthias St. Pierre |
||||
Nicola Tuveri |
||||
Nils Larsch |
||||
Patrick Steuer |
||||
Paul Dale |
||||
Paul C. Sutton |
||||
Paul Yang |
||||
Ralf S. Engelschall |
||||
Rich Salz |
||||
Richard Levitte |
||||
Shane Lontis |
||||
Stephen Henson |
||||
Steve Marquess |
||||
Tim Hudson |
||||
Tomáš Mráz |
||||
Ulf Möller |
||||
Viktor Dukhovni |
@ -1,88 +0,0 @@ |
||||
# How to change BoringSSL's API |
||||
|
||||
BoringSSL has more flexibility in changing things than many other library projects because we have a reasonable idea of who our users are. Still, breaking changes require some care. We depend on tight feedback loops with our consumers so that we can learn about mistakes and fix them. For that to work, updating BoringSSL must be smooth. |
||||
|
||||
Ultimately, the strategy for each breaking change is decided on a case-by-case basis. This document provides guidelines and techniques to help with a smooth transition. |
||||
|
||||
## Breakage risk |
||||
|
||||
Traditionally, breaking changes are defined in terms of API or ABI surface. Exposed symbols and type signatures cannot change, etc. But this is a poor approximation of the true impact. Removing an API may not a breaking change if no one is using it. Conversely, [Hyrum's Law](http://www.hyrumslaw.com/) applies. Fixing a bug may be a breaking change for some consumer which was depending on that bug. |
||||
|
||||
Thus, we do not think about whether a change is formally a breaking change, but about the *risk* of it breaking someone. |
||||
|
||||
Some changes, such as internal cleanups or bug-fixes, are low risk and do not need special measures. Any problems can be handled when the affected consumer updates BoringSSL and notices. |
||||
|
||||
Other changes, such as removing an API, forbidding some edge case, or adjusting some behavior, are more likely to break things. To help the consumer triage any resulting failures, include some text in the commit message, prefixed by `Update-Note: `. This can include what this change may break and instructions on how to fix the issue. |
||||
|
||||
## Code Search |
||||
|
||||
The vast majority of BoringSSL consumers are conveniently indexed in various Code Search instances. This can predict the impact of a risky change and identify code to fix ahead of time. The document “How to Code Search” in the (Google-only) [go/boringssl-folder](https://goto.google.com/boringssl-folder) includes notes on this. |
||||
|
||||
## Evaluate a change's cost |
||||
|
||||
If some change has high cost (from having to fix consumers) and relatively little benefit to BoringSSL, it may not be worth the trouble. For instance, it is likely not worth removing a small compatibility function in the corner of the library that is easily dropped by the static linker. |
||||
|
||||
Conversely, a change that leads to a major improvement to all BoringSSL consumers, at the cost of fixing one or two consumers, is typically worth it. |
||||
|
||||
## Fixing consumers |
||||
|
||||
If code search reveals call sites that are definitely going to break, prefer to handle these before making the change. While unexpected breakage is always possible, we generally consider it the responsibility of the developer or group making a change to handle impact of that change. Teams are generally unhappy to be surprised by new migration work but happy to have migration work done for them. |
||||
|
||||
In most cases, this is straightforward: |
||||
|
||||
1. Add the replacement API. |
||||
2. As the replacement API enters each consuming repository, migrate callers to it. |
||||
3. Remove the original API once all consumers have been migrated. |
||||
|
||||
The removal should still include an `Update-Note` tag, in case some were missed. |
||||
|
||||
In some cases, this kind of staged approach is not feasible: perhaps the same code cannot simultaneously work before and after the change, or perhaps there are too many different versions in play. For instance, [Conscrypt](https://github.com/google/conscrypt) feeds into three different repositories. The GitHub repository consumes BoringSSL's `master` branch directly. It is pushed into Android, where it consumes Android's `external/boringssl`. Yet another copy is pushed into the internal repository, where it consumes that copy of BoringSSL. As each of these Conscrypts are updated independently from their corresponding BoringSSLs, Conscrypt upstream cannot rely on a new BoringSSL API until it is present in all copies of BoringSSL its downstreams rely on. |
||||
|
||||
In that case, a multi-sided change may be more appropriate: |
||||
|
||||
1. Upload the breaking change to Gerrit, but do not submit it yet. Increment the `BORINGSSL_API_VERSION` symbol. |
||||
2. Update the consuming repository with `#if BORINGSSL_API_VERSION < N` preprocessor logic. Leave a comment to remove this later, linking to your BoringSSL change. |
||||
3. When the `BORINGSSL_API_VERSION` check has propagated to relevant copies of the consuming repository, submit the BoringSSL change. |
||||
4. When the BoringSSL change has propagated to relevant copies of BoringSSL, remove the staging logic from the consumer. |
||||
|
||||
Finally, in some cases, the consumer's change may be committed atomically with the BoringSSL update. This can only be done for code which only consumes one instance of BoringSSL (so the Conscrypt example above is not eligible). Check with that project's maintainer first or, better, be that project's maintainer. |
||||
|
||||
If more complex changes are needed in some consumer, communicate with the relevant maintainers to plan the transition. |
||||
|
||||
## Fail early, fail closed |
||||
|
||||
When breaking changes do occur, they should fail as early and as detectably as possible. |
||||
|
||||
Ideally, problematic consumers fail to compile. Prefer to remove functions completely over leaving an always failing stub function. Sometimes this is not possible due to other consumers, particularly bindings libraries. Alternatively, if a stub function can be reasonably justified as still satisfying the API constraints, consider adding one to improve compatibility. For example, BoringSSL has many no-op stubs corresponding to OpenSSL's many initialization functions. |
||||
|
||||
If some parameter now must be `NULL`, change the type to an opaque struct pointer. Consumers passing non-`NULL` pointers will then fail to compile. |
||||
|
||||
If breaking the compile is not feasible, break at runtime, in the hope that consumers have some amount of test coverage. When doing so, try to fail on the common case. In particular, do not rely on consumers adequately testing or even checking for failure cases. One strategy is to bring the object into a “poison” state: if an illegal operation occurs, set a flag to fail all subsequent ones. |
||||
|
||||
In other functions, it may be appropriate to simply call `abort()`. |
||||
|
||||
## Unexpected breakage |
||||
|
||||
While we try to avoid breaking things, sometimes things unexpectedly break. Depending on the impact, we may fix the consumer, make a small fix to BoringSSL, or revert the change to either try again later or revise the approach. |
||||
|
||||
If we do not ultimately fix the consumer, add a test in BoringSSL to capture the unexpected API contract, so future regressions are caught quickly. |
||||
|
||||
## Canary changes and bake time |
||||
|
||||
When planning a large project that depends on a breaking change, prefer to make the breaking change first—before committing larger changes. Or, when changing toolchain or language requirements, add a small instance of the dependency somewhere first then wait a couple of weeks for the change to appear in consumers. This ensures that reverting the change is still feasible if necessary. |
||||
|
||||
While we rely on a tight feedback loop with our consumers, there are a few consumers which update less frequently. For extremely risky changes, such as introducing C++ to a target, it may be prudent to wait much longer. |
||||
|
||||
## Third-party code |
||||
|
||||
In many cases, we are interested in changing behavior which came from OpenSSL. OpenSSL's API surface is huge, but only a small subset is actually used. So we can and occasionally do change these behaviors. This is more complex than changing BoringSSL-only behavior due to third-party code. |
||||
|
||||
We use BoringSSL with many third-party projects that normally use OpenSSL. Generally, we consider this our burden to make this work and do not encourage external projects to depend on BoringSSL. While we can and do maintain patches for this as necessary, it has overhead and so the cost of breaking third-party code is higher. |
||||
|
||||
We lean fairly strongly towards making changes to BoringSSL over patching third-party code, unless the third-party change fixes a security problem. |
||||
|
||||
Additionally, changing an OpenSSL API will not only affect third-party code we use today, but also any third-party code we use in the future. Thus Code Search is less useful as an absolute predictor, and the various other considerations in this document are more important. |
||||
|
||||
If the patch to support a BoringSSL change can be generally useful to the third-party project, send it upstream. For instance, it may use the APIs better, clean up code, or help support newer versions of OpenSSL. In general, we try to target compatibility with “most” “well-behaved” OpenSSL consumers. |
||||
|
||||
Finally, if some particular OpenSSL API or pattern is problematic to BoringSSL, it is likely problematic to OpenSSL too. Consider filing a bug with them to suggest a change, either in new code going forward or for the next API break. OpenSSL's release cycles and feedback loops are much longer than BoringSSL's, so this is usually not immediately useful, but it keeps the ecosystem moving in the right direction. |
@ -1,206 +0,0 @@ |
||||
# Copyright 2024 The BoringSSL Authors |
||||
# |
||||
# 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. |
||||
|
||||
load( |
||||
":gen/sources.bzl", |
||||
"bcm_internal_headers", |
||||
"bcm_sources", |
||||
"bcm_sources_asm", |
||||
"bssl_internal_headers", |
||||
"bssl_sources", |
||||
"crypto_headers", |
||||
"crypto_internal_headers", |
||||
"crypto_sources", |
||||
"crypto_sources_asm", |
||||
"crypto_test_data", |
||||
"crypto_test_sources", |
||||
"decrepit_internal_headers", |
||||
"decrepit_sources", |
||||
"decrepit_test_sources", |
||||
"pki_headers", |
||||
"pki_internal_headers", |
||||
"pki_sources", |
||||
"pki_test_data", |
||||
"pki_test_sources", |
||||
"ssl_headers", |
||||
"ssl_internal_headers", |
||||
"ssl_sources", |
||||
"ssl_test_sources", |
||||
"test_support_internal_headers", |
||||
"test_support_sources", |
||||
"test_support_sources_asm", |
||||
"urandom_test_sources", |
||||
) |
||||
load(":util/util.bzl", "bssl_cc_binary", "bssl_cc_library", "bssl_cc_test") |
||||
load("@rules_license//rules:license.bzl", "license") |
||||
|
||||
package( |
||||
default_applicable_licenses = [":license"], |
||||
# Disable the parse_headers feature. It does not work well in C right now. |
||||
# See https://github.com/bazelbuild/bazel/issues/23460 for details. When |
||||
# that is fixed, if enabled, we likely also need to rename some headers to |
||||
# .inc per |
||||
# https://google.github.io/styleguide/cppguide.html#Self_contained_Headers |
||||
features = ["-parse_headers"], |
||||
) |
||||
|
||||
license( |
||||
name = "license", |
||||
package_name = "BoringSSL", |
||||
# TODO(crbug.com/364634028): Update this once we've aligned with OpenSSL's |
||||
# new license. |
||||
license_kinds = [ |
||||
"@rules_license//licenses/spdx:ISC", |
||||
"@rules_license//licenses/spdx:OpenSSL", |
||||
"@rules_license//licenses/spdx:MIT", |
||||
"@rules_license//licenses/spdx:SSLeay-standalone", |
||||
], |
||||
license_text = "LICENSE", |
||||
) |
||||
|
||||
exports_files(["LICENSE"]) |
||||
|
||||
bssl_cc_library( |
||||
name = "crypto", |
||||
srcs = bcm_sources + crypto_sources, |
||||
hdrs = crypto_headers, |
||||
asm_srcs = bcm_sources_asm + crypto_sources_asm, |
||||
copts = ["-DBORINGSSL_IMPLEMENTATION"], |
||||
includes = ["include"], |
||||
internal_hdrs = bcm_internal_headers + crypto_internal_headers, |
||||
linkopts = select({ |
||||
"@platforms//os:windows": [ |
||||
"-defaultlib:advapi32.lib", |
||||
"-defaultlib:ws2_32.lib", |
||||
], |
||||
"//conditions:default": ["-pthread"], |
||||
}), |
||||
visibility = ["//visibility:public"], |
||||
) |
||||
|
||||
bssl_cc_library( |
||||
name = "ssl", |
||||
srcs = ssl_sources, |
||||
hdrs = ssl_headers, |
||||
copts = ["-DBORINGSSL_IMPLEMENTATION"], |
||||
internal_hdrs = ssl_internal_headers, |
||||
visibility = ["//visibility:public"], |
||||
deps = [":crypto_internal"], |
||||
) |
||||
|
||||
bssl_cc_library( |
||||
name = "test_support", |
||||
testonly = True, |
||||
srcs = test_support_sources, |
||||
asm_srcs = test_support_sources_asm, |
||||
copts = ["-DBORINGSSL_USE_BAZEL_RUNFILES"], |
||||
internal_hdrs = test_support_internal_headers, |
||||
deps = [ |
||||
":crypto_internal", |
||||
"@bazel_tools//tools/cpp/runfiles", |
||||
"@googletest//:gtest", |
||||
], |
||||
) |
||||
|
||||
bssl_cc_test( |
||||
name = "crypto_test", |
||||
size = "large", |
||||
srcs = crypto_test_sources, |
||||
data = crypto_test_data, |
||||
# crypto_test references assembly symbols directly and thus must be linked |
||||
# statically. |
||||
linkstatic = True, |
||||
shard_count = 32, |
||||
deps = [ |
||||
":crypto_internal", |
||||
":test_support", |
||||
"@googletest//:gtest", |
||||
], |
||||
) |
||||
|
||||
bssl_cc_test( |
||||
name = "urandom_test", |
||||
srcs = urandom_test_sources, |
||||
deps = [ |
||||
":crypto_internal", |
||||
":test_support", |
||||
"@googletest//:gtest", |
||||
], |
||||
) |
||||
|
||||
bssl_cc_test( |
||||
name = "ssl_test", |
||||
srcs = ssl_test_sources, |
||||
deps = [ |
||||
":crypto_internal", |
||||
":ssl_internal", |
||||
":test_support", |
||||
"@googletest//:gtest", |
||||
], |
||||
) |
||||
|
||||
bssl_cc_binary( |
||||
name = "bssl", |
||||
srcs = bssl_sources + bssl_internal_headers, |
||||
visibility = ["//visibility:public"], |
||||
deps = [ |
||||
":crypto_internal", |
||||
":ssl_internal", |
||||
], |
||||
) |
||||
|
||||
# Build, but do not export libdecrepit. |
||||
bssl_cc_library( |
||||
name = "decrepit", |
||||
srcs = decrepit_sources, |
||||
copts = ["-DBORINGSSL_IMPLEMENTATION"], |
||||
internal_hdrs = decrepit_internal_headers, |
||||
deps = [ |
||||
":crypto_internal", |
||||
":ssl_internal", |
||||
], |
||||
) |
||||
|
||||
bssl_cc_test( |
||||
name = "decrepit_test", |
||||
srcs = decrepit_test_sources, |
||||
deps = [ |
||||
":crypto_internal", |
||||
":decrepit", |
||||
":test_support", |
||||
"@googletest//:gtest", |
||||
], |
||||
) |
||||
|
||||
# Build, but do not (yet) export libpki. |
||||
bssl_cc_library( |
||||
name = "pki", |
||||
srcs = pki_sources, |
||||
hdrs = pki_headers, |
||||
copts = ["-DBORINGSSL_IMPLEMENTATION"], |
||||
internal_hdrs = pki_internal_headers, |
||||
deps = [":crypto"], |
||||
) |
||||
|
||||
bssl_cc_test( |
||||
name = "pki_test", |
||||
srcs = pki_test_sources, |
||||
data = pki_test_data, |
||||
deps = [ |
||||
":crypto_internal", |
||||
":pki", |
||||
":test_support", |
||||
"@googletest//:gtest", |
||||
], |
||||
) |
File diff suppressed because it is too large
Load Diff
@ -1,37 +0,0 @@ |
||||
# Copyright 2024 The BoringSSL Authors |
||||
# |
||||
# Permission to use, copy, modify, and/or distribute this software for any |
||||
# purpose with or without fee is hereby granted, provided that the above |
||||
# copyright notice and this permission notice appear in all copies. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
||||
# When tagging a new periodic snapshot, bump the version here and then tag at |
||||
# the revision where we bump the version. |
||||
module( |
||||
name = "boringssl", |
||||
version = "0.20250114.0", |
||||
compatibility_level = 2, |
||||
) |
||||
|
||||
# Periodically update the following dependencies to their latest versions |
||||
# listed on https://registry.bazel.build/. When doing so, run |
||||
# `bazelisk test ...` to update the hashes in MODULE.bazel.lock. |
||||
|
||||
# In principle, googletest is only needed for tests and could be a |
||||
# dev_dependency. But it would then be impossible for downstream modules to run |
||||
# BoringSSL's tests. The downstream module provides the toolchain, so we may |
||||
# need to request they run tests when triaging issues. If |
||||
# https://github.com/bazelbuild/bazel/issues/22187 is ever fixed, we can change |
||||
# this. |
||||
bazel_dep(name = "googletest", version = "1.15.2") |
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.11") |
||||
bazel_dep(name = "rules_cc", version = "0.1.0") |
||||
bazel_dep(name = "rules_license", version = "1.0.0") |
@ -1,126 +0,0 @@ |
||||
{ |
||||
"lockFileVersion": 11, |
||||
"registryFileHashes": { |
||||
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", |
||||
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", |
||||
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", |
||||
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", |
||||
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", |
||||
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", |
||||
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/source.json": "750d5e29326fb59cbe61116a7b803c8a1d0a7090a9c8ed89888d188e3c473fc7", |
||||
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", |
||||
"https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", |
||||
"https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", |
||||
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", |
||||
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", |
||||
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", |
||||
"https://bcr.bazel.build/modules/bazel_features/1.19.0/source.json": "d7bf14517c1b25b9d9c580b0f8795fceeae08a7590f507b76aace528e941375d", |
||||
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", |
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", |
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", |
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", |
||||
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", |
||||
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", |
||||
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", |
||||
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", |
||||
"https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", |
||||
"https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470", |
||||
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", |
||||
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", |
||||
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", |
||||
"https://bcr.bazel.build/modules/protobuf/21.7/source.json": "bbe500720421e582ff2d18b0802464205138c06056f443184de39fbb8187b09b", |
||||
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", |
||||
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", |
||||
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", |
||||
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", |
||||
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", |
||||
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", |
||||
"https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", |
||||
"https://bcr.bazel.build/modules/re2/2024-07-02/source.json": "547d0111a9d4f362db32196fef805abbf3676e8d6afbe44d395d87816c1130ca", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.1.0/MODULE.bazel": "2fef03775b9ba995ec543868840041cc69e8bc705eb0cb6604a36eee18c87d8b", |
||||
"https://bcr.bazel.build/modules/rules_cc/0.1.0/source.json": "8a4e832d75e073ab56c74dd77008cf7a81e107dec4544019eb1eefc1320d55be", |
||||
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", |
||||
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", |
||||
"https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1", |
||||
"https://bcr.bazel.build/modules/rules_java/7.6.5/source.json": "a805b889531d1690e3c72a7a7e47a870d00323186a9904b36af83aa3d053ee8d", |
||||
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", |
||||
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/source.json": "a075731e1b46bc8425098512d038d416e966ab19684a10a34f4741295642fc35", |
||||
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", |
||||
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", |
||||
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", |
||||
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", |
||||
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", |
||||
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c", |
||||
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", |
||||
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", |
||||
"https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", |
||||
"https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/source.json": "8d8448e71706df7450ced227ca6b3812407ff5e2ccad74a43a9fbe79c84e34e0", |
||||
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", |
||||
"https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", |
||||
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", |
||||
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", |
||||
"https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", |
||||
"https://bcr.bazel.build/modules/rules_python/0.33.2/source.json": "e539592cd3aae4492032cecea510e46ca16eeb972271560b922cae9893944e2f", |
||||
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", |
||||
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", |
||||
"https://bcr.bazel.build/modules/stardoc/0.5.1/source.json": "a96f95e02123320aa015b956f29c00cb818fa891ef823d55148e1a362caacf29", |
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", |
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json": "f1ef7d3f9e0e26d4b23d1c39b5f5de71f584dd7d1b4ef83d9bbba6ec7a6a6459", |
||||
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", |
||||
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", |
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", |
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d" |
||||
}, |
||||
"selectedYankedVersions": {}, |
||||
"moduleExtensions": { |
||||
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": { |
||||
"general": { |
||||
"bzlTransitiveDigest": "ltCGFbl/LQQZXn/LEMXfKX7pGwyqNiOCHcmiQW0tmjM=", |
||||
"usagesDigest": "2Jj0sTGzjx2KfYRjWYbL6DZ1bi8HL2roIAGfOViiul8=", |
||||
"recordedFileInputs": {}, |
||||
"recordedDirentsInputs": {}, |
||||
"envVariables": {}, |
||||
"generatedRepoSpecs": { |
||||
"local_config_apple_cc_toolchains": { |
||||
"bzlFile": "@@apple_support~//crosstool:setup.bzl", |
||||
"ruleClassName": "_apple_cc_autoconf_toolchains", |
||||
"attributes": {} |
||||
}, |
||||
"local_config_apple_cc": { |
||||
"bzlFile": "@@apple_support~//crosstool:setup.bzl", |
||||
"ruleClassName": "_apple_cc_autoconf", |
||||
"attributes": {} |
||||
} |
||||
}, |
||||
"recordedRepoMappingEntries": [ |
||||
[ |
||||
"apple_support~", |
||||
"bazel_tools", |
||||
"bazel_tools" |
||||
] |
||||
] |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,21 +0,0 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
|
||||
<!-- |
||||
This file is for using BoringSSL in Apple ecosystems. You may have to point |
||||
Xcode at it yourself. See |
||||
https://developer.apple.com/documentation/bundleresources/privacy_manifest_files |
||||
--> |
||||
|
||||
<dict> |
||||
<key>NSPrivacyTracking</key> |
||||
<false/> |
||||
<key>NSPrivacyTrackingDomains</key> |
||||
<array/> |
||||
<key>NSPrivacyCollectedDataTypes</key> |
||||
<array/> |
||||
<key>NSPrivacyAccessedAPITypes</key> |
||||
<array/> |
||||
</dict> |
||||
</plist> |
@ -1,140 +0,0 @@ |
||||
# Using BoringSSL in a Sandbox |
||||
|
||||
Sandboxes are a valuable tool for securing applications, so BoringSSL aims to |
||||
support them. However, it is difficult to make concrete API guarantees with |
||||
sandboxes. Sandboxes remove low-level OS resources and system calls, which |
||||
breaks platform abstractions. A syscall-filtering sandbox may, for instance, be |
||||
sensitive to otherwise non-breaking changes to use newer syscalls |
||||
in either BoringSSL or the C library. |
||||
|
||||
Some functions in BoringSSL, such as `BIO_new_file`, inherently need OS |
||||
resources like the filesystem. We assume that sandboxed consumers either avoid |
||||
those functions or make necessary resources available. Other functions like |
||||
`RSA_sign` are purely computational, but still have some baseline OS |
||||
dependencies. |
||||
|
||||
Sandboxes which drop privileges partway through a process's lifetime are |
||||
additionally sensitive to OS resources retained across the transitions. For |
||||
instance, if a library function internally opened and retained a handle to the |
||||
user's home directory, and then the application called `chroot`, that handle |
||||
would be a sandbox escape. |
||||
|
||||
This document attempts to describe these baseline OS dependencies and long-lived |
||||
internal resources. These dependencies may change over time, but we aim to |
||||
[work with sandboxed consumers](./BREAKING-CHANGES.md) when they do. However, |
||||
each sandbox imposes different constraints, so, above all, sandboxed consumers |
||||
must have ample test coverage to detect issues as they arise. |
||||
|
||||
## Baseline dependencies |
||||
|
||||
Callers must assume that any BoringSSL function may perform one of the following |
||||
operations: |
||||
|
||||
### Memory allocation |
||||
|
||||
Any BoringSSL function may allocate memory via `malloc` and related functions. |
||||
|
||||
### Thread synchronization |
||||
|
||||
Any BoringSSL function may call into the platform's thread synchronization |
||||
primitives, including read/write locks and the equivalent of `pthread_once`. |
||||
These must succeed, or BoringSSL will abort the process. Callers, however, can |
||||
assume that BoringSSL functions will not spawn internal threads, unless |
||||
otherwise documented. |
||||
|
||||
Syscall-filtering sandboxes should note that BoringSSL uses `pthread_rwlock_t` |
||||
on POSIX systems, which is less common and may not be part of other libraries' |
||||
syscall surface. Additionally, thread synchronization primitives usually have an |
||||
atomics-based fast path. If a sandbox blocks a necessary pthreads syscall, it |
||||
may not show up in testing without lock contention. |
||||
|
||||
### Standard error |
||||
|
||||
Any BoringSSL function may write to `stderr` or file descriptor |
||||
`STDERR_FILENO` (2), either via `FILE` APIs or low-level functions like `write`. |
||||
Writes to `stderr` may fail, but there must some file at `STDERR_FILENO` which |
||||
will tolerate error messages from BoringSSL. (The file descriptor must be |
||||
allocated so calls to `open` do not accidentally open something else there.) |
||||
|
||||
Note some C standard library implementations also log to `stderr`, so callers |
||||
should ensure this regardless. |
||||
|
||||
### Entropy |
||||
|
||||
Any BoringSSL function may draw entropy from the OS. On Windows, this uses |
||||
`RtlGenRandom` and, on POSIX systems, this uses `getrandom`, `getentropy`, or a |
||||
`read` from a file descriptor to `/dev/urandom`. These operations must succeed |
||||
or BoringSSL will abort the process. BoringSSL only probes for `getrandom` |
||||
support once and assumes support is consistent for the lifetime of the address |
||||
space (and any copies made via `fork`). If a syscall-filtering sandbox is |
||||
enabled partway through this lifetime and changes whether `getrandom` works, |
||||
BoringSSL may abort the process. Sandboxes are recommended to allow |
||||
`getrandom`. |
||||
|
||||
Note even deterministic algorithms may require OS entropy. For example, |
||||
RSASSA-PKCS1-v1_5 is deterministic, but BoringSSL draws entropy to implement |
||||
RSA blinding. |
||||
|
||||
Entropy gathering additionally has some initialization dependencies described in |
||||
the following section. |
||||
|
||||
## Initialization |
||||
|
||||
BoringSSL has some uncommon OS dependencies which are only used once to |
||||
initialize some state. Sandboxes which drop privileges after some setup work may |
||||
use `CRYPTO_pre_sandbox_init` to initialize this state ahead of time. Otherwise, |
||||
callers must assume any BoringSSL function may depend on these resources, in |
||||
addition to the operations above. |
||||
|
||||
### CPU capabilities |
||||
|
||||
On Linux ARM platforms, BoringSSL depends on OS APIs to query CPU capabilities. |
||||
32-bit and 64-bit ARM both depend on the `getauxval` function. 32-bit ARM, to |
||||
work around bugs in older Android devices, may additionally read |
||||
`/proc/cpuinfo`. |
||||
|
||||
On 64-bit Apple ARM platforms, BoringSSL needs to query `hw.optional.*` sysctls. |
||||
|
||||
If querying CPU capabilities fails, BoringSSL will still function, but may not |
||||
perform as well. |
||||
|
||||
### Entropy |
||||
|
||||
On Linux systems without a working `getrandom`, drawing entropy from the OS |
||||
additionally requires opening `/dev/urandom`. If this fails, BoringSSL will |
||||
abort the process. BoringSSL retains the resulting file descriptor, even across |
||||
privilege transitions. |
||||
|
||||
### Fork protection |
||||
|
||||
On Linux, BoringSSL allocates a page and calls `madvise` with `MADV_WIPEONFORK` |
||||
to protect single-use state from `fork`. This operation must not crash, but if |
||||
it fails, BoringSSL will use alternate fork-safety strategies, potentially at a |
||||
performance cost. If it succeeds, BoringSSL assumes `MADV_WIPEONFORK` is |
||||
functional and relies on it for fork-safety. Sandboxes must not report success |
||||
if they ignore the `MADV_WIPEONFORK` flag. As of writing, QEMU will ignore |
||||
`madvise` calls and report success, so BoringSSL detects this by calling |
||||
`madvise` with -1. Sandboxes must cleanly report an error instead of crashing. |
||||
|
||||
Once initialized, this mechanism does not require system calls in the steady |
||||
state, though note the configured page will be inherited across privilege |
||||
transitions. |
||||
|
||||
## C and C++ standard library |
||||
|
||||
BoringSSL depends on the C and C++ standard libraries which, themselves, do not |
||||
make any guarantees about sandboxes. If it produces the correct answer and has |
||||
no observable invalid side effects, it is possible, though unreasonable, for |
||||
`memcmp` to create and close a socket. |
||||
|
||||
BoringSSL assumes that functions in the C and C++ library only have the platform |
||||
dependencies which would be "reasonable". For instance, a function in BoringSSL |
||||
which aims not to open files will still freely call any libc memory and |
||||
string functions. |
||||
|
||||
Note some C functions, such as `strerror`, may read files relating to the user's |
||||
locale. BoringSSL may trigger these paths and assumes the sandbox environment |
||||
will tolerate this. BoringSSL additionally cannot make guarantees about which |
||||
system calls are used by standard library's syscall wrappers. In some cases, the |
||||
compiler may add dependencies. (Some C++ language features emit locking code.) |
||||
Syscall-filtering sandboxes may need updates as these dependencies change. |
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@ |
||||
# Copyright 2022 The BoringSSL Authors |
||||
# |
||||
# 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(${CMAKE_CURRENT_LIST_DIR}/OpenSSLTargets.cmake) |
||||
|
||||
# Recursively collect dependency locations for the imported targets. |
||||
macro(_openssl_config_libraries libraries target) |
||||
get_property(_DEPS TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES) |
||||
foreach(_DEP ${_DEPS}) |
||||
if(TARGET ${_DEP}) |
||||
_openssl_config_libraries(${libraries} ${_DEP}) |
||||
else() |
||||
list(APPEND ${libraries} ${_DEP}) |
||||
endif() |
||||
endforeach() |
||||
get_property(_LOC TARGET ${target} PROPERTY LOCATION) |
||||
list(APPEND ${libraries} ${_LOC}) |
||||
endmacro() |
||||
|
||||
set(OPENSSL_FOUND YES) |
||||
get_property(OPENSSL_INCLUDE_DIR TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES) |
||||
get_property(OPENSSL_CRYPTO_LIBRARY TARGET OpenSSL::Crypto PROPERTY LOCATION) |
||||
_openssl_config_libraries(OPENSSL_CRYPTO_LIBRARIES OpenSSL::Crypto) |
||||
list(REMOVE_DUPLICATES OPENSSL_CRYPTO_LIBRARIES) |
||||
|
||||
get_property(OPENSSL_SSL_LIBRARY TARGET OpenSSL::Crypto PROPERTY LOCATION) |
||||
_openssl_config_libraries(OPENSSL_SSL_LIBRARIES OpenSSL::SSL) |
||||
list(REMOVE_DUPLICATES OPENSSL_SSL_LIBRARIES) |
||||
|
||||
set(OPENSSL_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}) |
||||
list(REMOVE_DUPLICATES OPENSSL_LIBRARIES) |
||||
|
||||
set(_DEP) |
||||
set(_DEPS) |
||||
set(_LOC) |
@ -1,61 +0,0 @@ |
||||
# Copyright 2023 The BoringSSL Authors |
||||
# |
||||
# 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. |
||||
|
||||
# Go is an optional dependency. It's a necessary dependency if running tests or |
||||
# the FIPS build, which will check these. |
||||
find_program(GO_EXECUTABLE go) |
||||
|
||||
function(require_go) |
||||
if(NOT GO_EXECUTABLE) |
||||
message(FATAL_ERROR "Could not find Go") |
||||
endif() |
||||
endfunction() |
||||
|
||||
function(go_executable dest package) |
||||
require_go() |
||||
set(godeps "${PROJECT_SOURCE_DIR}/util/godeps.go") |
||||
if(NOT CMAKE_GENERATOR STREQUAL "Ninja") |
||||
# The DEPFILE parameter to add_custom_command only works with Ninja. Query |
||||
# the sources at configure time. Additionally, everything depends on go.mod. |
||||
# That affects what external packages to use. |
||||
# |
||||
# TODO(davidben): Starting CMake 3.20, it also works with Make. Starting |
||||
# 3.21, it works with Visual Studio and Xcode too. |
||||
execute_process(COMMAND ${GO_EXECUTABLE} run ${godeps} -format cmake |
||||
-pkg ${package} |
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
||||
OUTPUT_VARIABLE sources |
||||
RESULT_VARIABLE godeps_result) |
||||
add_custom_command(OUTPUT ${dest} |
||||
COMMAND ${GO_EXECUTABLE} build |
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package} |
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
||||
DEPENDS ${sources} ${PROJECT_SOURCE_DIR}/go.mod) |
||||
else() |
||||
# Ninja expects the target in the depfile to match the output. This is a |
||||
# relative path from the build directory. |
||||
binary_dir_relative_path(${dest} target) |
||||
|
||||
set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d") |
||||
add_custom_command(OUTPUT ${dest} |
||||
COMMAND ${GO_EXECUTABLE} build |
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package} |
||||
COMMAND ${GO_EXECUTABLE} run ${godeps} -format depfile |
||||
-target ${target} -pkg ${package} -out ${depfile} |
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
||||
DEPENDS ${godeps} ${PROJECT_SOURCE_DIR}/go.mod |
||||
DEPFILE ${depfile}) |
||||
endif() |
||||
endfunction() |
||||
|
@ -1,37 +0,0 @@ |
||||
# Copyright 2023 The BoringSSL Authors |
||||
# |
||||
# 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. |
||||
|
||||
# binary_dir_relative_path sets outvar to |
||||
# ${CMAKE_CURRENT_BINARY_DIR}/${cur_bin_dir_relative}, but expressed relative to |
||||
# ${CMAKE_BINARY_DIR}. |
||||
# |
||||
# TODO(davidben): When we require CMake 3.20 or later, this can be replaced with |
||||
# the built-in cmake_path(RELATIVE_PATH) function. |
||||
function(binary_dir_relative_path cur_bin_dir_relative outvar) |
||||
string(LENGTH "${CMAKE_BINARY_DIR}/" root_dir_length) |
||||
string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}/${cur_bin_dir_relative}" ${root_dir_length} -1 result) |
||||
set(${outvar} ${result} PARENT_SCOPE) |
||||
endfunction() |
||||
|
||||
# copy_post_build causes targets in ${ARGN} to be copied to |
||||
# ${CMAKE_CURRENT_BINARY_DIR}/${dir} after being built. |
||||
function(copy_post_build dir) |
||||
foreach(target ${ARGN}) |
||||
add_custom_command( |
||||
TARGET ${target} |
||||
POST_BUILD |
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${dir}" |
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${target}> "${CMAKE_CURRENT_BINARY_DIR}/${dir}") |
||||
endforeach() |
||||
endfunction() |
@ -1,4 +1,4 @@ |
||||
# This file is used by "git cl" to get repository specific information. |
||||
# This file is used by gcl to get repository specific information. |
||||
GERRIT_HOST: True |
||||
GERRIT_PORT: True |
||||
CODE_REVIEW_SERVER: https://boringssl-review.googlesource.com |
||||
|
@ -0,0 +1,276 @@ |
||||
include_directories(../include) |
||||
|
||||
if(NOT OPENSSL_NO_ASM) |
||||
if(UNIX) |
||||
if (${ARCH} STREQUAL "aarch64") |
||||
# The "armx" Perl scripts look for "64" in the style argument |
||||
# in order to decide whether to generate 32- or 64-bit asm. |
||||
if (APPLE) |
||||
set(PERLASM_STYLE ios64) |
||||
else() |
||||
set(PERLASM_STYLE linux64) |
||||
endif() |
||||
elseif (${ARCH} STREQUAL "arm") |
||||
if (APPLE) |
||||
set(PERLASM_STYLE ios32) |
||||
else() |
||||
set(PERLASM_STYLE linux32) |
||||
endif() |
||||
elseif (${ARCH} STREQUAL "ppc64le") |
||||
set(PERLASM_STYLE linux64le) |
||||
else() |
||||
if (${ARCH} STREQUAL "x86") |
||||
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2") |
||||
endif() |
||||
if (APPLE) |
||||
set(PERLASM_STYLE macosx) |
||||
else() |
||||
set(PERLASM_STYLE elf) |
||||
endif() |
||||
endif() |
||||
set(ASM_EXT S) |
||||
enable_language(ASM) |
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack") |
||||
|
||||
# Clang's integerated assembler does not support debug symbols. |
||||
if(NOT CMAKE_ASM_COMPILER_ID MATCHES "Clang") |
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g") |
||||
endif() |
||||
|
||||
# CMake does not add -isysroot and -arch flags to assembly. |
||||
if (APPLE) |
||||
if (CMAKE_OSX_SYSROOT) |
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -isysroot \"${CMAKE_OSX_SYSROOT}\"") |
||||
endif() |
||||
foreach(arch ${CMAKE_OSX_ARCHITECTURES}) |
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch ${arch}") |
||||
endforeach() |
||||
endif() |
||||
else() |
||||
if (${ARCH} STREQUAL "x86_64") |
||||
set(PERLASM_STYLE nasm) |
||||
else() |
||||
set(PERLASM_STYLE win32n) |
||||
set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2") |
||||
endif() |
||||
set(CMAKE_ASM_NASM_FLAGS "-g cv8") |
||||
|
||||
# On Windows, we use the NASM output, specifically built with Yasm. |
||||
set(ASM_EXT asm) |
||||
enable_language(ASM_NASM) |
||||
endif() |
||||
endif() |
||||
|
||||
function(perlasm dest src) |
||||
add_custom_command( |
||||
OUTPUT ${dest} |
||||
COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} ${dest} |
||||
DEPENDS |
||||
${src} |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/ppc-xlate.pl |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl |
||||
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl |
||||
WORKING_DIRECTORY . |
||||
) |
||||
endfunction() |
||||
|
||||
# Level 0.1 - depends on nothing outside this set. |
||||
add_subdirectory(stack) |
||||
add_subdirectory(lhash) |
||||
add_subdirectory(err) |
||||
add_subdirectory(buf) |
||||
add_subdirectory(base64) |
||||
add_subdirectory(bytestring) |
||||
add_subdirectory(pool) |
||||
|
||||
# Level 0.2 - depends on nothing but itself |
||||
add_subdirectory(rc4) |
||||
add_subdirectory(conf) |
||||
add_subdirectory(chacha) |
||||
add_subdirectory(poly1305) |
||||
add_subdirectory(curve25519) |
||||
|
||||
# Level 1, depends only on 0.* |
||||
add_subdirectory(digest_extra) |
||||
add_subdirectory(cipher_extra) |
||||
add_subdirectory(rand_extra) |
||||
add_subdirectory(bio) |
||||
add_subdirectory(bn_extra) |
||||
add_subdirectory(obj) |
||||
add_subdirectory(asn1) |
||||
|
||||
# Level 2 |
||||
add_subdirectory(engine) |
||||
add_subdirectory(dh) |
||||
add_subdirectory(dsa) |
||||
add_subdirectory(rsa_extra) |
||||
add_subdirectory(ec_extra) |
||||
add_subdirectory(ecdh) |
||||
add_subdirectory(ecdsa_extra) |
||||
|
||||
# Level 3 |
||||
add_subdirectory(cmac) |
||||
add_subdirectory(evp) |
||||
add_subdirectory(hkdf) |
||||
add_subdirectory(pem) |
||||
add_subdirectory(x509) |
||||
add_subdirectory(x509v3) |
||||
|
||||
# Level 4 |
||||
add_subdirectory(pkcs7) |
||||
add_subdirectory(pkcs8) |
||||
|
||||
# Test support code |
||||
add_subdirectory(test) |
||||
|
||||
add_subdirectory(fipsmodule) |
||||
|
||||
add_library( |
||||
crypto_base |
||||
|
||||
OBJECT |
||||
|
||||
cpu-aarch64-linux.c |
||||
cpu-arm.c |
||||
cpu-arm-linux.c |
||||
cpu-intel.c |
||||
cpu-ppc64le.c |
||||
crypto.c |
||||
ex_data.c |
||||
mem.c |
||||
refcount_c11.c |
||||
refcount_lock.c |
||||
thread.c |
||||
thread_none.c |
||||
thread_pthread.c |
||||
thread_win.c |
||||
) |
||||
|
||||
if(FIPS_DELOCATE) |
||||
SET_SOURCE_FILES_PROPERTIES(fipsmodule/bcm.o PROPERTIES EXTERNAL_OBJECT true) |
||||
SET_SOURCE_FILES_PROPERTIES(fipsmodule/bcm.o PROPERTIES GENERATED true) |
||||
|
||||
set( |
||||
CRYPTO_FIPS_OBJECTS |
||||
|
||||
fipsmodule/bcm.o |
||||
) |
||||
endif() |
||||
|
||||
add_library( |
||||
crypto |
||||
|
||||
$<TARGET_OBJECTS:crypto_base> |
||||
$<TARGET_OBJECTS:stack> |
||||
$<TARGET_OBJECTS:lhash> |
||||
$<TARGET_OBJECTS:err> |
||||
$<TARGET_OBJECTS:base64> |
||||
$<TARGET_OBJECTS:bytestring> |
||||
$<TARGET_OBJECTS:pool> |
||||
$<TARGET_OBJECTS:fipsmodule> |
||||
$<TARGET_OBJECTS:digest_extra> |
||||
$<TARGET_OBJECTS:cipher_extra> |
||||
$<TARGET_OBJECTS:rc4> |
||||
$<TARGET_OBJECTS:conf> |
||||
$<TARGET_OBJECTS:chacha> |
||||
$<TARGET_OBJECTS:poly1305> |
||||
$<TARGET_OBJECTS:curve25519> |
||||
$<TARGET_OBJECTS:buf> |
||||
$<TARGET_OBJECTS:bn_extra> |
||||
$<TARGET_OBJECTS:bio> |
||||
$<TARGET_OBJECTS:rand_extra> |
||||
$<TARGET_OBJECTS:obj> |
||||
$<TARGET_OBJECTS:asn1> |
||||
$<TARGET_OBJECTS:engine> |
||||
$<TARGET_OBJECTS:dh> |
||||
$<TARGET_OBJECTS:dsa> |
||||
$<TARGET_OBJECTS:rsa_extra> |
||||
$<TARGET_OBJECTS:ec_extra> |
||||
$<TARGET_OBJECTS:ecdh> |
||||
$<TARGET_OBJECTS:ecdsa_extra> |
||||
$<TARGET_OBJECTS:cmac> |
||||
$<TARGET_OBJECTS:evp> |
||||
$<TARGET_OBJECTS:hkdf> |
||||
$<TARGET_OBJECTS:pem> |
||||
$<TARGET_OBJECTS:x509> |
||||
$<TARGET_OBJECTS:x509v3> |
||||
$<TARGET_OBJECTS:pkcs7> |
||||
$<TARGET_OBJECTS:pkcs8_lib> |
||||
|
||||
${CRYPTO_FIPS_OBJECTS} |
||||
) |
||||
|
||||
if(FIPS_DELOCATE) |
||||
add_dependencies(crypto bcm_o_target) |
||||
endif() |
||||
|
||||
SET_TARGET_PROPERTIES(crypto PROPERTIES LINKER_LANGUAGE C) |
||||
|
||||
if(NOT MSVC AND NOT ANDROID) |
||||
target_link_libraries(crypto pthread) |
||||
endif() |
||||
|
||||
# TODO(davidben): Convert the remaining tests to GTest. |
||||
add_executable( |
||||
crypto_test |
||||
|
||||
asn1/asn1_test.cc |
||||
base64/base64_test.cc |
||||
bio/bio_test.cc |
||||
bytestring/bytestring_test.cc |
||||
chacha/chacha_test.cc |
||||
cipher_extra/aead_test.cc |
||||
cipher_extra/cipher_test.cc |
||||
cmac/cmac_test.cc |
||||
compiler_test.cc |
||||
constant_time_test.cc |
||||
curve25519/ed25519_test.cc |
||||
curve25519/spake25519_test.cc |
||||
curve25519/x25519_test.cc |
||||
ecdh/ecdh_test.cc |
||||
dh/dh_test.cc |
||||
digest_extra/digest_test.cc |
||||
dsa/dsa_test.cc |
||||
err/err_test.cc |
||||
evp/evp_extra_test.cc |
||||
evp/evp_test.cc |
||||
evp/pbkdf_test.cc |
||||
evp/scrypt_test.cc |
||||
fipsmodule/aes/aes_test.cc |
||||
fipsmodule/bn/bn_test.cc |
||||
fipsmodule/ec/ec_test.cc |
||||
fipsmodule/ec/p256-x86_64_test.cc |
||||
fipsmodule/ecdsa/ecdsa_test.cc |
||||
fipsmodule/modes/gcm_test.cc |
||||
fipsmodule/rand/ctrdrbg_test.cc |
||||
hkdf/hkdf_test.cc |
||||
hmac_extra/hmac_test.cc |
||||
lhash/lhash_test.cc |
||||
obj/obj_test.cc |
||||
pkcs7/pkcs7_test.cc |
||||
pkcs8/pkcs8_test.cc |
||||
pkcs8/pkcs12_test.cc |
||||
poly1305/poly1305_test.cc |
||||
pool/pool_test.cc |
||||
refcount_test.cc |
||||
rsa_extra/rsa_test.cc |
||||
test/file_test_gtest.cc |
||||
thread_test.cc |
||||
x509/x509_test.cc |
||||
x509v3/tab_test.cc |
||||
x509v3/v3name_test.cc |
||||
|
||||
$<TARGET_OBJECTS:crypto_test_data> |
||||
$<TARGET_OBJECTS:gtest_main> |
||||
$<TARGET_OBJECTS:test_support> |
||||
) |
||||
|
||||
target_link_libraries(crypto_test crypto gtest) |
||||
if (WIN32) |
||||
target_link_libraries(crypto_test ws2_32) |
||||
endif() |
||||
add_dependencies(all_tests crypto_test) |
@ -1,523 +0,0 @@ |
||||
/* Copyright 2018 The BoringSSL Authors
|
||||
* |
||||
* 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 <gtest/gtest.h> |
||||
#include <gtest/gtest-spi.h> |
||||
|
||||
#include <openssl/rand.h> |
||||
|
||||
#include "test/abi_test.h" |
||||
|
||||
|
||||
static bool test_function_ok; |
||||
static int TestFunction(int a1, int a2, int a3, int a4, int a5, int a6, int a7, |
||||
int a8) { |
||||
test_function_ok = a1 == 1 || a2 == 2 || a3 == 3 || a4 == 4 || a5 == 5 || |
||||
a6 == 6 || a7 == 7 || a8 == 8; |
||||
return 42; |
||||
} |
||||
|
||||
TEST(ABITest, SanityCheck) { |
||||
EXPECT_NE(0, CHECK_ABI_NO_UNWIND(strcmp, "hello", "world")); |
||||
|
||||
test_function_ok = false; |
||||
EXPECT_EQ(42, CHECK_ABI_SEH(TestFunction, 1, 2, 3, 4, 5, 6, 7, 8)); |
||||
EXPECT_TRUE(test_function_ok); |
||||
|
||||
#if defined(SUPPORTS_ABI_TEST) |
||||
abi_test::internal::CallerState state; |
||||
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); |
||||
crypto_word_t argv[] = { |
||||
1, 2, 3, 4, 5, 6, 7, 8, |
||||
}; |
||||
CHECK_ABI_SEH(abi_test_trampoline, |
||||
reinterpret_cast<crypto_word_t>(TestFunction), &state, argv, 8, |
||||
0 /* no breakpoint */); |
||||
|
||||
#if defined(OPENSSL_X86_64) |
||||
if (abi_test::UnwindTestsEnabled()) { |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_SEH(abi_test_bad_unwind_wrong_register), |
||||
"was not recovered"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_SEH(abi_test_bad_unwind_temporary), |
||||
"was not recovered"); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_bad_unwind_wrong_register); |
||||
CHECK_ABI_NO_UNWIND(abi_test_bad_unwind_temporary); |
||||
|
||||
#if defined(OPENSSL_WINDOWS) |
||||
// The invalid epilog makes Windows believe the epilog starts later than it
|
||||
// actually does. As a result, immediately after the popq, it does not
|
||||
// realize the stack has been unwound and repeats the popq. This will result
|
||||
// in reading the wrong return address and fail to unwind. The exact failure
|
||||
// may vary depending on what was on the stack before.
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_SEH(abi_test_bad_unwind_epilog), ""); |
||||
CHECK_ABI_NO_UNWIND(abi_test_bad_unwind_epilog); |
||||
#endif // OPENSSL_WINDOWS
|
||||
} |
||||
#endif // OPENSSL_X86_64
|
||||
#endif // SUPPORTS_ABI_TEST
|
||||
} |
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(SUPPORTS_ABI_TEST) |
||||
extern "C" { |
||||
void abi_test_clobber_rax(void); |
||||
void abi_test_clobber_rbx(void); |
||||
void abi_test_clobber_rcx(void); |
||||
void abi_test_clobber_rdx(void); |
||||
void abi_test_clobber_rsi(void); |
||||
void abi_test_clobber_rdi(void); |
||||
void abi_test_clobber_rbp(void); |
||||
void abi_test_clobber_r8(void); |
||||
void abi_test_clobber_r9(void); |
||||
void abi_test_clobber_r10(void); |
||||
void abi_test_clobber_r11(void); |
||||
void abi_test_clobber_r12(void); |
||||
void abi_test_clobber_r13(void); |
||||
void abi_test_clobber_r14(void); |
||||
void abi_test_clobber_r15(void); |
||||
void abi_test_clobber_xmm0(void); |
||||
void abi_test_clobber_xmm1(void); |
||||
void abi_test_clobber_xmm2(void); |
||||
void abi_test_clobber_xmm3(void); |
||||
void abi_test_clobber_xmm4(void); |
||||
void abi_test_clobber_xmm5(void); |
||||
void abi_test_clobber_xmm6(void); |
||||
void abi_test_clobber_xmm7(void); |
||||
void abi_test_clobber_xmm8(void); |
||||
void abi_test_clobber_xmm9(void); |
||||
void abi_test_clobber_xmm10(void); |
||||
void abi_test_clobber_xmm11(void); |
||||
void abi_test_clobber_xmm12(void); |
||||
void abi_test_clobber_xmm13(void); |
||||
void abi_test_clobber_xmm14(void); |
||||
void abi_test_clobber_xmm15(void); |
||||
} // extern "C"
|
||||
|
||||
TEST(ABITest, X86_64) { |
||||
// abi_test_trampoline hides unsaved registers from the caller, so we can
|
||||
// safely call the abi_test_clobber_* functions below.
|
||||
abi_test::internal::CallerState state; |
||||
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); |
||||
CHECK_ABI_NO_UNWIND(abi_test_trampoline, |
||||
reinterpret_cast<crypto_word_t>(abi_test_clobber_rbx), |
||||
&state, nullptr, 0, 0 /* no breakpoint */); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_rax); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rbx), |
||||
"rbx was not restored after return"); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_rcx); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_rdx); |
||||
#if defined(OPENSSL_WINDOWS) |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rdi), |
||||
"rdi was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rsi), |
||||
"rsi was not restored after return"); |
||||
#else |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_rdi); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_rsi); |
||||
#endif |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rbp), |
||||
"rbp was not restored after return"); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r8); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r9); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r10); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r11); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r12), |
||||
"r12 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r13), |
||||
"r13 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r14), |
||||
"r14 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r15), |
||||
"r15 was not restored after return"); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm0); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm1); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm2); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm3); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm4); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm5); |
||||
#if defined(OPENSSL_WINDOWS) |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm6), |
||||
"xmm6 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm7), |
||||
"xmm7 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm8), |
||||
"xmm8 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm9), |
||||
"xmm9 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm10), |
||||
"xmm10 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm11), |
||||
"xmm11 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm12), |
||||
"xmm12 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm13), |
||||
"xmm13 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm14), |
||||
"xmm14 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm15), |
||||
"xmm15 was not restored after return"); |
||||
#else |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm6); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm7); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm8); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm9); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm10); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm11); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm12); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm13); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm14); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm15); |
||||
#endif |
||||
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_set_direction_flag), |
||||
"Direction flag set after return"); |
||||
EXPECT_EQ(0, abi_test_get_and_clear_direction_flag()) |
||||
<< "CHECK_ABI did not insulate the caller from direction flag errors"; |
||||
} |
||||
#endif // OPENSSL_X86_64 && SUPPORTS_ABI_TEST
|
||||
|
||||
#if defined(OPENSSL_X86) && defined(SUPPORTS_ABI_TEST) |
||||
extern "C" { |
||||
void abi_test_clobber_eax(void); |
||||
void abi_test_clobber_ebx(void); |
||||
void abi_test_clobber_ecx(void); |
||||
void abi_test_clobber_edx(void); |
||||
void abi_test_clobber_esi(void); |
||||
void abi_test_clobber_edi(void); |
||||
void abi_test_clobber_ebp(void); |
||||
void abi_test_clobber_xmm0(void); |
||||
void abi_test_clobber_xmm1(void); |
||||
void abi_test_clobber_xmm2(void); |
||||
void abi_test_clobber_xmm3(void); |
||||
void abi_test_clobber_xmm4(void); |
||||
void abi_test_clobber_xmm5(void); |
||||
void abi_test_clobber_xmm6(void); |
||||
void abi_test_clobber_xmm7(void); |
||||
} // extern "C"
|
||||
|
||||
TEST(ABITest, X86) { |
||||
// abi_test_trampoline hides unsaved registers from the caller, so we can
|
||||
// safely call the abi_test_clobber_* functions below.
|
||||
abi_test::internal::CallerState state; |
||||
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); |
||||
CHECK_ABI_NO_UNWIND(abi_test_trampoline, |
||||
reinterpret_cast<crypto_word_t>(abi_test_clobber_ebx), |
||||
&state, nullptr, 0, 0 /* no breakpoint */); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_eax); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_ebx), |
||||
"ebx was not restored after return"); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_ecx); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_edx); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_edi), |
||||
"edi was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_esi), |
||||
"esi was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_ebp), |
||||
"ebp was not restored after return"); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm0); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm1); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm2); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm3); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm4); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm5); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm6); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm7); |
||||
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_set_direction_flag), |
||||
"Direction flag set after return"); |
||||
EXPECT_EQ(0, abi_test_get_and_clear_direction_flag()) |
||||
<< "CHECK_ABI did not insulate the caller from direction flag errors"; |
||||
} |
||||
#endif // OPENSSL_X86 && SUPPORTS_ABI_TEST
|
||||
|
||||
#if defined(OPENSSL_ARM) && defined(SUPPORTS_ABI_TEST) |
||||
extern "C" { |
||||
void abi_test_clobber_r0(void); |
||||
void abi_test_clobber_r1(void); |
||||
void abi_test_clobber_r2(void); |
||||
void abi_test_clobber_r3(void); |
||||
void abi_test_clobber_r4(void); |
||||
void abi_test_clobber_r5(void); |
||||
void abi_test_clobber_r6(void); |
||||
void abi_test_clobber_r7(void); |
||||
void abi_test_clobber_r8(void); |
||||
void abi_test_clobber_r9(void); |
||||
void abi_test_clobber_r10(void); |
||||
void abi_test_clobber_r11(void); |
||||
void abi_test_clobber_r12(void); |
||||
// r13, r14, and r15, are sp, lr, and pc, respectively.
|
||||
|
||||
void abi_test_clobber_d0(void); |
||||
void abi_test_clobber_d1(void); |
||||
void abi_test_clobber_d2(void); |
||||
void abi_test_clobber_d3(void); |
||||
void abi_test_clobber_d4(void); |
||||
void abi_test_clobber_d5(void); |
||||
void abi_test_clobber_d6(void); |
||||
void abi_test_clobber_d7(void); |
||||
void abi_test_clobber_d8(void); |
||||
void abi_test_clobber_d9(void); |
||||
void abi_test_clobber_d10(void); |
||||
void abi_test_clobber_d11(void); |
||||
void abi_test_clobber_d12(void); |
||||
void abi_test_clobber_d13(void); |
||||
void abi_test_clobber_d14(void); |
||||
void abi_test_clobber_d15(void); |
||||
} // extern "C"
|
||||
|
||||
TEST(ABITest, ARM) { |
||||
// abi_test_trampoline hides unsaved registers from the caller, so we can
|
||||
// safely call the abi_test_clobber_* functions below.
|
||||
abi_test::internal::CallerState state; |
||||
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); |
||||
CHECK_ABI_NO_UNWIND(abi_test_trampoline, |
||||
reinterpret_cast<crypto_word_t>(abi_test_clobber_r4), |
||||
&state, nullptr, 0, 0 /* no breakpoint */); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r0); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r1); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r2); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r3); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r4), |
||||
"r4 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r5), |
||||
"r5 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r6), |
||||
"r6 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r7), |
||||
"r7 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r8), |
||||
"r8 was not restored after return"); |
||||
#if defined(OPENSSL_APPLE) |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r9); |
||||
#else |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r9), |
||||
"r9 was not restored after return"); |
||||
#endif |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r10), |
||||
"r10 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r11), |
||||
"r11 was not restored after return"); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_r12); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d0); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d1); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d2); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d3); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d4); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d5); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d6); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d7); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d8), |
||||
"d8 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d9), |
||||
"d9 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d10), |
||||
"d10 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d11), |
||||
"d11 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d12), |
||||
"d12 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d13), |
||||
"d13 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d14), |
||||
"d14 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d15), |
||||
"d15 was not restored after return"); |
||||
} |
||||
#endif // OPENSSL_ARM && SUPPORTS_ABI_TEST
|
||||
|
||||
#if defined(OPENSSL_AARCH64) && defined(SUPPORTS_ABI_TEST) |
||||
extern "C" { |
||||
void abi_test_clobber_x0(void); |
||||
void abi_test_clobber_x1(void); |
||||
void abi_test_clobber_x2(void); |
||||
void abi_test_clobber_x3(void); |
||||
void abi_test_clobber_x4(void); |
||||
void abi_test_clobber_x5(void); |
||||
void abi_test_clobber_x6(void); |
||||
void abi_test_clobber_x7(void); |
||||
void abi_test_clobber_x8(void); |
||||
void abi_test_clobber_x9(void); |
||||
void abi_test_clobber_x10(void); |
||||
void abi_test_clobber_x11(void); |
||||
void abi_test_clobber_x12(void); |
||||
void abi_test_clobber_x13(void); |
||||
void abi_test_clobber_x14(void); |
||||
void abi_test_clobber_x15(void); |
||||
void abi_test_clobber_x16(void); |
||||
void abi_test_clobber_x17(void); |
||||
// x18 is the platform register and off limits.
|
||||
void abi_test_clobber_x19(void); |
||||
void abi_test_clobber_x20(void); |
||||
void abi_test_clobber_x21(void); |
||||
void abi_test_clobber_x22(void); |
||||
void abi_test_clobber_x23(void); |
||||
void abi_test_clobber_x24(void); |
||||
void abi_test_clobber_x25(void); |
||||
void abi_test_clobber_x26(void); |
||||
void abi_test_clobber_x27(void); |
||||
void abi_test_clobber_x28(void); |
||||
void abi_test_clobber_x29(void); |
||||
|
||||
void abi_test_clobber_d0(void); |
||||
void abi_test_clobber_d1(void); |
||||
void abi_test_clobber_d2(void); |
||||
void abi_test_clobber_d3(void); |
||||
void abi_test_clobber_d4(void); |
||||
void abi_test_clobber_d5(void); |
||||
void abi_test_clobber_d6(void); |
||||
void abi_test_clobber_d7(void); |
||||
void abi_test_clobber_d8(void); |
||||
void abi_test_clobber_d9(void); |
||||
void abi_test_clobber_d10(void); |
||||
void abi_test_clobber_d11(void); |
||||
void abi_test_clobber_d12(void); |
||||
void abi_test_clobber_d13(void); |
||||
void abi_test_clobber_d14(void); |
||||
void abi_test_clobber_d15(void); |
||||
void abi_test_clobber_d16(void); |
||||
void abi_test_clobber_d17(void); |
||||
void abi_test_clobber_d18(void); |
||||
void abi_test_clobber_d19(void); |
||||
void abi_test_clobber_d20(void); |
||||
void abi_test_clobber_d21(void); |
||||
void abi_test_clobber_d22(void); |
||||
void abi_test_clobber_d23(void); |
||||
void abi_test_clobber_d24(void); |
||||
void abi_test_clobber_d25(void); |
||||
void abi_test_clobber_d26(void); |
||||
void abi_test_clobber_d27(void); |
||||
void abi_test_clobber_d28(void); |
||||
void abi_test_clobber_d29(void); |
||||
void abi_test_clobber_d30(void); |
||||
void abi_test_clobber_d31(void); |
||||
|
||||
void abi_test_clobber_v8_upper(void); |
||||
void abi_test_clobber_v9_upper(void); |
||||
void abi_test_clobber_v10_upper(void); |
||||
void abi_test_clobber_v11_upper(void); |
||||
void abi_test_clobber_v12_upper(void); |
||||
void abi_test_clobber_v13_upper(void); |
||||
void abi_test_clobber_v14_upper(void); |
||||
void abi_test_clobber_v15_upper(void); |
||||
} // extern "C"
|
||||
|
||||
TEST(ABITest, AArch64) { |
||||
// abi_test_trampoline hides unsaved registers from the caller, so we can
|
||||
// safely call the abi_test_clobber_* functions below.
|
||||
abi_test::internal::CallerState state; |
||||
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); |
||||
CHECK_ABI_NO_UNWIND(abi_test_trampoline, |
||||
reinterpret_cast<crypto_word_t>(abi_test_clobber_x19), |
||||
&state, nullptr, 0, 0 /* no breakpoint */); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x0); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x1); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x2); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x3); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x4); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x5); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x6); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x7); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x8); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x9); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x10); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x11); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x12); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x13); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x14); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x15); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x16); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_x17); |
||||
|
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x19), |
||||
"x19 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x20), |
||||
"x20 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x21), |
||||
"x21 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x22), |
||||
"x22 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x23), |
||||
"x23 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x24), |
||||
"x24 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x25), |
||||
"x25 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x26), |
||||
"x26 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x27), |
||||
"x27 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x28), |
||||
"x28 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_x29), |
||||
"x29 was not restored after return"); |
||||
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d0); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d1); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d2); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d3); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d4); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d5); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d6); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d7); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d8), |
||||
"d8 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d9), |
||||
"d9 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d10), |
||||
"d10 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d11), |
||||
"d11 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d12), |
||||
"d12 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d13), |
||||
"d13 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d14), |
||||
"d14 was not restored after return"); |
||||
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_d15), |
||||
"d15 was not restored after return"); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d16); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d18); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d19); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d20); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d21); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d22); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d23); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d24); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d25); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d26); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d27); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d28); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d29); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d30); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_d31); |
||||
|
||||
// The lower halves of v8-v15 (accessed as d8-d15) must be preserved, but not
|
||||
// the upper halves.
|
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v8_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v9_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v10_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v11_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v12_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v13_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v14_upper); |
||||
CHECK_ABI_NO_UNWIND(abi_test_clobber_v15_upper); |
||||
} |
||||
#endif // OPENSSL_AARCH64 && SUPPORTS_ABI_TEST
|
@ -0,0 +1,38 @@ |
||||
include_directories(../../include) |
||||
|
||||
add_library( |
||||
asn1 |
||||
|
||||
OBJECT |
||||
|
||||
a_bitstr.c |
||||
a_bool.c |
||||
a_d2i_fp.c |
||||
a_dup.c |
||||
a_enum.c |
||||
a_gentm.c |
||||
a_i2d_fp.c |
||||
a_int.c |
||||
a_mbstr.c |
||||
a_object.c |
||||
a_octet.c |
||||
a_print.c |
||||
a_strnid.c |
||||
a_time.c |
||||
a_type.c |
||||
a_utctm.c |
||||
a_utf8.c |
||||
asn1_lib.c |
||||
asn1_par.c |
||||
asn_pack.c |
||||
f_enum.c |
||||
f_int.c |
||||
f_string.c |
||||
tasn_dec.c |
||||
tasn_enc.c |
||||
tasn_fre.c |
||||
tasn_new.c |
||||
tasn_typ.c |
||||
tasn_utl.c |
||||
time_support.c |
||||
) |
@ -0,0 +1,271 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) |
||||
{ |
||||
return M_ASN1_BIT_STRING_set(x, d, len); |
||||
} |
||||
|
||||
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) |
||||
{ |
||||
int ret, j, bits, len; |
||||
unsigned char *p, *d; |
||||
|
||||
if (a == NULL) |
||||
return (0); |
||||
|
||||
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; |
||||
|
||||
ret = 1 + len; |
||||
if (pp == NULL) |
||||
return (ret); |
||||
|
||||
p = *pp; |
||||
|
||||
*(p++) = (unsigned char)bits; |
||||
d = a->data; |
||||
OPENSSL_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; |
||||
|
||||
if (len < 1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); |
||||
goto err; |
||||
} |
||||
|
||||
if (len > INT_MAX) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); |
||||
goto err; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
/*
|
||||
* 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; |
||||
} |
||||
OPENSSL_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(a->data, w + 1); |
||||
if (c == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
||||
return 0; |
||||
} |
||||
if (w + 1 - a->length > 0) |
||||
OPENSSL_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; |
||||
|
||||
/*
|
||||
* 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; |
||||
} |
@ -1,238 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, const unsigned char *d, |
||||
ossl_ssize_t len) { |
||||
return ASN1_STRING_set(x, d, len); |
||||
} |
||||
|
||||
int asn1_bit_string_length(const ASN1_BIT_STRING *str, |
||||
uint8_t *out_padding_bits) { |
||||
int len = str->length; |
||||
if (str->flags & ASN1_STRING_FLAG_BITS_LEFT) { |
||||
// If the string is already empty, it cannot have padding bits.
|
||||
*out_padding_bits = len == 0 ? 0 : str->flags & 0x07; |
||||
return len; |
||||
} |
||||
|
||||
// TODO(https://crbug.com/boringssl/447): If we move this logic to
|
||||
// |ASN1_BIT_STRING_set_bit|, can we remove this representation?
|
||||
while (len > 0 && str->data[len - 1] == 0) { |
||||
len--; |
||||
} |
||||
uint8_t padding_bits = 0; |
||||
if (len > 0) { |
||||
uint8_t last = str->data[len - 1]; |
||||
assert(last != 0); |
||||
for (; padding_bits < 7; padding_bits++) { |
||||
if (last & (1 << padding_bits)) { |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
*out_padding_bits = padding_bits; |
||||
return len; |
||||
} |
||||
|
||||
int ASN1_BIT_STRING_num_bytes(const ASN1_BIT_STRING *str, size_t *out) { |
||||
uint8_t padding_bits; |
||||
int len = asn1_bit_string_length(str, &padding_bits); |
||||
if (padding_bits != 0) { |
||||
return 0; |
||||
} |
||||
*out = len; |
||||
return 1; |
||||
} |
||||
|
||||
int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp) { |
||||
if (a == NULL) { |
||||
return 0; |
||||
} |
||||
|
||||
uint8_t bits; |
||||
int len = asn1_bit_string_length(a, &bits); |
||||
if (len > INT_MAX - 1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); |
||||
return 0; |
||||
} |
||||
int ret = 1 + len; |
||||
if (pp == NULL) { |
||||
return ret; |
||||
} |
||||
|
||||
uint8_t *p = *pp; |
||||
*(p++) = bits; |
||||
OPENSSL_memcpy(p, a->data, len); |
||||
if (len > 0) { |
||||
p[len - 1] &= (0xff << bits); |
||||
} |
||||
p += len; |
||||
*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; |
||||
uint8_t padding_mask; |
||||
|
||||
if (len < 1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); |
||||
goto err; |
||||
} |
||||
|
||||
if (len > INT_MAX) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); |
||||
goto err; |
||||
} |
||||
|
||||
if ((a == NULL) || ((*a) == NULL)) { |
||||
if ((ret = ASN1_BIT_STRING_new()) == NULL) { |
||||
return NULL; |
||||
} |
||||
} else { |
||||
ret = (*a); |
||||
} |
||||
|
||||
p = *pp; |
||||
padding = *(p++); |
||||
len--; |
||||
if (padding > 7) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); |
||||
goto err; |
||||
} |
||||
|
||||
// Unused bits in a BIT STRING must be zero.
|
||||
padding_mask = (1 << padding) - 1; |
||||
if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING); |
||||
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
|
||||
|
||||
if (len > 0) { |
||||
s = reinterpret_cast<uint8_t *>(OPENSSL_memdup(p, len)); |
||||
if (s == NULL) { |
||||
goto err; |
||||
} |
||||
p += len; |
||||
} else { |
||||
s = NULL; |
||||
} |
||||
|
||||
ret->length = (int)len; |
||||
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))) { |
||||
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(a->data, w + 1); |
||||
} |
||||
if (c == NULL) { |
||||
return 0; |
||||
} |
||||
if (w + 1 - a->length > 0) { |
||||
OPENSSL_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(const 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(const ASN1_BIT_STRING *a, const 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; |
||||
} |
@ -0,0 +1,110 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp) |
||||
{ |
||||
int r; |
||||
unsigned char *p; |
||||
|
||||
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); |
||||
} |
||||
|
||||
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; |
||||
|
||||
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 (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); |
||||
} |
@ -1,48 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
|
||||
#include "../bytestring/internal.h" |
||||
|
||||
|
||||
int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **outp) { |
||||
CBB cbb; |
||||
if (!CBB_init(&cbb, 3) || //
|
||||
!CBB_add_asn1_bool(&cbb, a != ASN1_BOOLEAN_FALSE)) { |
||||
CBB_cleanup(&cbb); |
||||
return -1; |
||||
} |
||||
return CBB_finish_i2d(&cbb, outp); |
||||
} |
||||
|
||||
ASN1_BOOLEAN d2i_ASN1_BOOLEAN(ASN1_BOOLEAN *out, const unsigned char **inp, |
||||
long len) { |
||||
if (len < 0) { |
||||
return ASN1_BOOLEAN_NONE; |
||||
} |
||||
|
||||
CBS cbs; |
||||
CBS_init(&cbs, *inp, (size_t)len); |
||||
int val; |
||||
if (!CBS_get_asn1_bool(&cbs, &val)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
||||
return ASN1_BOOLEAN_NONE; |
||||
} |
||||
|
||||
ASN1_BOOLEAN ret = val ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE; |
||||
if (out != NULL) { |
||||
*out = ret; |
||||
} |
||||
*inp = CBS_data(&cbs); |
||||
return ret; |
||||
} |
@ -0,0 +1,297 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
|
||||
#include <openssl/buf.h> |
||||
#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 |
||||
|
||||
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 |
||||
|
||||
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; |
||||
|
||||
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; |
||||
|
||||
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); |
||||
} |
||||
|
||||
#ifndef OPENSSL_NO_FP_API |
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) |
||||
{ |
||||
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); |
||||
} |
||||
#endif |
||||
|
||||
typedef struct asn1_const_ctx_st |
||||
{ |
||||
const unsigned char *p;/* work char pointer */ |
||||
int eos; /* end of sequence read for indefinite encoding */ |
||||
int error; /* error code to use when returning an error */ |
||||
int inf; /* constructed if 0x20, indefinite is 0x21 */ |
||||
int tag; /* tag from last 'get object' */ |
||||
int xclass; /* class from last 'get object' */ |
||||
long slen; /* length of last 'get object' */ |
||||
const unsigned char *max; /* largest value of p allowed */ |
||||
const unsigned char *q;/* temporary variable */ |
||||
const unsigned char **pp;/* variable */ |
||||
int line; /* used in error processing */ |
||||
} ASN1_const_CTX; |
||||
|
||||
#define HEADER_SIZE 8 |
||||
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) |
||||
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; |
||||
|
||||
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); |
||||
|
||||
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; |
||||
|
||||
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)) { |
||||
size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; |
||||
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; |
||||
} |
||||
while (want > 0) { |
||||
/*
|
||||
* Read content in chunks of increasing size |
||||
* so we can return an error for EOF without |
||||
* having to allocate the entire content length |
||||
* in one go. |
||||
*/ |
||||
size_t chunk = want > chunk_max ? chunk_max : want; |
||||
|
||||
if (!BUF_MEM_grow_clean(b, len + chunk)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
||||
goto err; |
||||
} |
||||
want -= chunk; |
||||
while (chunk > 0) { |
||||
i = BIO_read(in, &(b->data[len]), chunk); |
||||
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; |
||||
chunk -= i; |
||||
} |
||||
if (chunk_max < INT_MAX/2) |
||||
chunk_max *= 2; |
||||
} |
||||
} |
||||
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; |
||||
} |
||||
|
||||
*pb = b; |
||||
return off; |
||||
err: |
||||
if (b != NULL) |
||||
BUF_MEM_free(b); |
||||
return -1; |
||||
} |
@ -1,42 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
|
||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) { |
||||
uint8_t *data; |
||||
size_t len; |
||||
// Historically, this function did not impose a limit in OpenSSL and is used
|
||||
// to read CRLs, so we leave this without an external bound.
|
||||
if (!BIO_read_asn1(in, &data, &len, INT_MAX)) { |
||||
return NULL; |
||||
} |
||||
const uint8_t *ptr = data; |
||||
void *ret = ASN1_item_d2i(reinterpret_cast<ASN1_VALUE **>(x), &ptr, len, it); |
||||
OPENSSL_free(data); |
||||
return ret; |
||||
} |
||||
|
||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) { |
||||
BIO *b = BIO_new_fp(in, BIO_NOCLOSE); |
||||
if (b == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); |
||||
return NULL; |
||||
} |
||||
void *ret = ASN1_item_d2i_bio(it, b, x); |
||||
BIO_free(b); |
||||
return ret; |
||||
} |
@ -0,0 +1,111 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <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; |
||||
|
||||
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); |
||||
} |
||||
|
||||
/*
|
||||
* 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; |
||||
|
||||
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); |
||||
} |
@ -1,37 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
// 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; |
||||
|
||||
if (x == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
i = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE *>(x), &b, it); |
||||
if (b == NULL) { |
||||
return NULL; |
||||
} |
||||
p = b; |
||||
ret = ASN1_item_d2i(NULL, &p, i, it); |
||||
OPENSSL_free(b); |
||||
return ret; |
||||
} |
@ -0,0 +1,184 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
/*
|
||||
* Code for ENUMERATED type: identical to INTEGER apart from a different tag. |
||||
* for comments on encoding see a_int.c |
||||
*/ |
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) |
||||
{ |
||||
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) |
||||
OPENSSL_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); |
||||
} |
||||
|
||||
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a) |
||||
{ |
||||
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; |
||||
|
||||
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; |
||||
|
||||
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); |
||||
} |
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn) |
||||
{ |
||||
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); |
||||
} |
@ -0,0 +1,261 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "asn1_locl.h" |
||||
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) |
||||
{ |
||||
static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; |
||||
static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; |
||||
char *a; |
||||
int n, i, l, o; |
||||
|
||||
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 ((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); |
||||
} |
||||
|
||||
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) |
||||
{ |
||||
return asn1_generalizedtime_to_tm(NULL, d); |
||||
} |
||||
|
||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) |
||||
{ |
||||
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); |
||||
} |
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, |
||||
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; |
||||
ASN1_GENERALIZEDTIME *tmps = NULL; |
||||
|
||||
if (s == NULL) |
||||
tmps = ASN1_GENERALIZEDTIME_new(); |
||||
else |
||||
tmps = s; |
||||
if (tmps == NULL) |
||||
return NULL; |
||||
|
||||
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; |
||||
} |
||||
|
||||
p = (char *)tmps->data; |
||||
if ((p == NULL) || ((size_t)tmps->length < len)) { |
||||
p = OPENSSL_malloc(len); |
||||
if (p == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
||||
goto err; |
||||
} |
||||
OPENSSL_free(tmps->data); |
||||
tmps->data = (unsigned char *)p; |
||||
} |
||||
|
||||
BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, |
||||
ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, |
||||
ts->tm_sec); |
||||
tmps->length = strlen(p); |
||||
tmps->type = V_ASN1_GENERALIZEDTIME; |
||||
return tmps; |
||||
err: |
||||
if (s == NULL) |
||||
ASN1_GENERALIZEDTIME_free(tmps); |
||||
return NULL; |
||||
} |
@ -1,104 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/posix_time.h> |
||||
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include "internal.h" |
||||
|
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) { |
||||
if (d->type != V_ASN1_GENERALIZEDTIME) { |
||||
return 0; |
||||
} |
||||
CBS cbs; |
||||
CBS_init(&cbs, d->data, (size_t)d->length); |
||||
if (!CBS_parse_generalized_time(&cbs, tm, /*allow_timezone_offset=*/0)) { |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) { |
||||
return asn1_generalizedtime_to_tm(NULL, d); |
||||
} |
||||
|
||||
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) { |
||||
size_t len = strlen(str); |
||||
CBS cbs; |
||||
CBS_init(&cbs, (const uint8_t *)str, len); |
||||
if (!CBS_parse_generalized_time(&cbs, /*out_tm=*/NULL, |
||||
/*allow_timezone_offset=*/0)) { |
||||
return 0; |
||||
} |
||||
if (s != NULL) { |
||||
if (!ASN1_STRING_set(s, str, len)) { |
||||
return 0; |
||||
} |
||||
s->type = V_ASN1_GENERALIZEDTIME; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, |
||||
int64_t posix_time) { |
||||
return ASN1_GENERALIZEDTIME_adj(s, posix_time, 0, 0); |
||||
} |
||||
|
||||
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, |
||||
int64_t posix_time, |
||||
int offset_day, |
||||
long offset_sec) { |
||||
struct tm data; |
||||
if (!OPENSSL_posix_to_tm(posix_time, &data)) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (offset_day || offset_sec) { |
||||
if (!OPENSSL_gmtime_adj(&data, offset_day, offset_sec)) { |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
if (data.tm_year < 0 - 1900 || data.tm_year > 9999 - 1900) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE); |
||||
return NULL; |
||||
} |
||||
|
||||
char buf[16]; |
||||
int ret = snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02dZ", |
||||
data.tm_year + 1900, data.tm_mon + 1, data.tm_mday, |
||||
data.tm_hour, data.tm_min, data.tm_sec); |
||||
// |snprintf| must write exactly 15 bytes (plus the NUL) to the buffer.
|
||||
BSSL_CHECK(ret == static_cast<int>(sizeof(buf) - 1)); |
||||
|
||||
int free_s = 0; |
||||
if (s == NULL) { |
||||
free_s = 1; |
||||
s = ASN1_UTCTIME_new(); |
||||
if (s == NULL) { |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
if (!ASN1_STRING_set(s, buf, strlen(buf))) { |
||||
if (free_s) { |
||||
ASN1_UTCTIME_free(s); |
||||
} |
||||
return NULL; |
||||
} |
||||
s->type = V_ASN1_GENERALIZEDTIME; |
||||
return s; |
||||
} |
@ -0,0 +1,147 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) |
||||
{ |
||||
BIO *b; |
||||
int ret; |
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); |
||||
return (0); |
||||
} |
||||
BIO_set_fp(b, out, BIO_NOCLOSE); |
||||
ret = ASN1_i2d_bio(i2d, b, x); |
||||
BIO_free(b); |
||||
return (ret); |
||||
} |
||||
|
||||
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x) |
||||
{ |
||||
char *b; |
||||
unsigned char *p; |
||||
int i, j = 0, n, ret = 1; |
||||
|
||||
n = i2d(x, NULL); |
||||
b = (char *)OPENSSL_malloc(n); |
||||
if (b == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
||||
return (0); |
||||
} |
||||
|
||||
p = (unsigned char *)b; |
||||
i2d(x, &p); |
||||
|
||||
for (;;) { |
||||
i = BIO_write(out, &(b[j]), n); |
||||
if (i == n) |
||||
break; |
||||
if (i <= 0) { |
||||
ret = 0; |
||||
break; |
||||
} |
||||
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; |
||||
|
||||
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; |
||||
|
||||
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); |
||||
} |
@ -1,38 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
|
||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) { |
||||
BIO *b = BIO_new_fp(out, BIO_NOCLOSE); |
||||
if (b == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); |
||||
return 0; |
||||
} |
||||
int 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 n = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE *>(x), &b, it); |
||||
if (b == NULL) { |
||||
return 0; |
||||
} |
||||
|
||||
int ret = BIO_write_all(out, b, n); |
||||
OPENSSL_free(b); |
||||
return ret; |
||||
} |
@ -0,0 +1,463 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *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; |
||||
} |
||||
|
||||
ret = ASN1_STRING_cmp(x, y); |
||||
|
||||
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. |
||||
* |
||||
* 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 |
||||
* 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 |
||||
* 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. |
||||
* |
||||
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad |
||||
* with 0xff. However if the first byte is 0x80 and one of the following bytes |
||||
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80 |
||||
* followed by optional zeros isn't padded. |
||||
*/ |
||||
|
||||
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) |
||||
{ |
||||
int pad = 0, ret, i, neg; |
||||
unsigned char *p, *n, pb = 0; |
||||
|
||||
if (a == NULL) |
||||
return (0); |
||||
neg = a->type & V_ASN1_NEG; |
||||
if (a->length == 0) |
||||
ret = 1; |
||||
else { |
||||
ret = a->length; |
||||
i = a->data[0]; |
||||
if (ret == 1 && i == 0) |
||||
neg = 0; |
||||
if (!neg && (i > 127)) { |
||||
pad = 1; |
||||
pb = 0; |
||||
} else if (neg) { |
||||
if (i > 128) { |
||||
pad = 1; |
||||
pb = 0xFF; |
||||
} else if (i == 128) { |
||||
/*
|
||||
* Special case: if any other bytes non zero we pad: |
||||
* otherwise we don't. |
||||
*/ |
||||
for (i = 1; i < a->length; i++) |
||||
if (a->data[i]) { |
||||
pad = 1; |
||||
pb = 0xFF; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
ret += pad; |
||||
} |
||||
if (pp == NULL) |
||||
return (ret); |
||||
p = *pp; |
||||
|
||||
if (pad) |
||||
*(p++) = pb; |
||||
if (a->length == 0) |
||||
*(p++) = 0; |
||||
else if (!neg) |
||||
OPENSSL_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); |
||||
} |
||||
|
||||
/* 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; |
||||
|
||||
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; |
||||
|
||||
/*
|
||||
* 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--; |
||||
} |
||||
OPENSSL_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); |
||||
} |
||||
|
||||
/*
|
||||
* 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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
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--; |
||||
} |
||||
OPENSSL_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); |
||||
} |
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) |
||||
{ |
||||
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) |
||||
OPENSSL_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); |
||||
} |
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a) |
||||
{ |
||||
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; |
||||
|
||||
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; |
||||
|
||||
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; |
||||
|
||||
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); |
||||
} |
@ -1,419 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) { |
||||
return ASN1_STRING_dup(x); |
||||
} |
||||
|
||||
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) { |
||||
// Compare signs.
|
||||
int neg = x->type & V_ASN1_NEG; |
||||
if (neg != (y->type & V_ASN1_NEG)) { |
||||
return neg ? -1 : 1; |
||||
} |
||||
|
||||
int ret = ASN1_STRING_cmp(x, y); |
||||
if (neg) { |
||||
// This could be |-ret|, but |ASN1_STRING_cmp| is not forbidden from
|
||||
// returning |INT_MIN|.
|
||||
if (ret < 0) { |
||||
return 1; |
||||
} else if (ret > 0) { |
||||
return -1; |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
// negate_twos_complement negates |len| bytes from |buf| in-place, interpreted
|
||||
// as a signed, big-endian two's complement value.
|
||||
static void negate_twos_complement(uint8_t *buf, size_t len) { |
||||
uint8_t borrow = 0; |
||||
for (size_t i = len - 1; i < len; i--) { |
||||
uint8_t t = buf[i]; |
||||
buf[i] = 0u - borrow - t; |
||||
borrow |= t != 0; |
||||
} |
||||
} |
||||
|
||||
static int is_all_zeros(const uint8_t *in, size_t len) { |
||||
for (size_t i = 0; i < len; i++) { |
||||
if (in[i] != 0) { |
||||
return 0; |
||||
} |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) { |
||||
if (in == NULL) { |
||||
return 0; |
||||
} |
||||
|
||||
// |ASN1_INTEGER|s should be represented minimally, but it is possible to
|
||||
// construct invalid ones. Skip leading zeros so this does not produce an
|
||||
// invalid encoding or break invariants.
|
||||
CBS cbs; |
||||
CBS_init(&cbs, in->data, in->length); |
||||
while (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0) { |
||||
CBS_skip(&cbs, 1); |
||||
} |
||||
|
||||
int is_negative = (in->type & V_ASN1_NEG) != 0; |
||||
size_t pad; |
||||
CBS copy = cbs; |
||||
uint8_t msb; |
||||
if (!CBS_get_u8(©, &msb)) { |
||||
// Zero is represented as a single byte.
|
||||
is_negative = 0; |
||||
pad = 1; |
||||
} else if (is_negative) { |
||||
// 0x80...01 through 0xff...ff have a two's complement of 0x7f...ff
|
||||
// through 0x00...01 and need an extra byte to be negative.
|
||||
// 0x01...00 through 0x80...00 have a two's complement of 0xfe...ff
|
||||
// through 0x80...00 and can be negated as-is.
|
||||
pad = msb > 0x80 || |
||||
(msb == 0x80 && !is_all_zeros(CBS_data(©), CBS_len(©))); |
||||
} else { |
||||
// If the high bit is set, the signed representation needs an extra
|
||||
// byte to be positive.
|
||||
pad = (msb & 0x80) != 0; |
||||
} |
||||
|
||||
if (CBS_len(&cbs) > INT_MAX - pad) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); |
||||
return 0; |
||||
} |
||||
int len = (int)(pad + CBS_len(&cbs)); |
||||
assert(len > 0); |
||||
if (outp == NULL) { |
||||
return len; |
||||
} |
||||
|
||||
if (pad) { |
||||
(*outp)[0] = 0; |
||||
} |
||||
OPENSSL_memcpy(*outp + pad, CBS_data(&cbs), CBS_len(&cbs)); |
||||
if (is_negative) { |
||||
negate_twos_complement(*outp, len); |
||||
assert((*outp)[0] >= 0x80); |
||||
} else { |
||||
assert((*outp)[0] < 0x80); |
||||
} |
||||
*outp += len; |
||||
return len; |
||||
} |
||||
|
||||
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp, |
||||
long len) { |
||||
// This function can handle lengths up to INT_MAX - 1, but the rest of the
|
||||
// legacy ASN.1 code mixes integer types, so avoid exposing it to
|
||||
// ASN1_INTEGERS with larger lengths.
|
||||
if (len < 0 || len > INT_MAX / 2) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); |
||||
return NULL; |
||||
} |
||||
|
||||
CBS cbs; |
||||
CBS_init(&cbs, *inp, (size_t)len); |
||||
int is_negative; |
||||
if (!CBS_is_valid_asn1_integer(&cbs, &is_negative)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); |
||||
return NULL; |
||||
} |
||||
|
||||
ASN1_INTEGER *ret = NULL; |
||||
if (out == NULL || *out == NULL) { |
||||
ret = ASN1_INTEGER_new(); |
||||
if (ret == NULL) { |
||||
return NULL; |
||||
} |
||||
} else { |
||||
ret = *out; |
||||
} |
||||
|
||||
// Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First,
|
||||
// determine the size needed for a minimal result.
|
||||
if (is_negative) { |
||||
// 0xff00...01 through 0xff7f..ff have a two's complement of 0x00ff...ff
|
||||
// through 0x000100...001 and need one leading zero removed. 0x8000...00
|
||||
// through 0xff00...00 have a two's complement of 0x8000...00 through
|
||||
// 0x0100...00 and will be minimally-encoded as-is.
|
||||
if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0xff && |
||||
!is_all_zeros(CBS_data(&cbs) + 1, CBS_len(&cbs) - 1)) { |
||||
CBS_skip(&cbs, 1); |
||||
} |
||||
} else { |
||||
// Remove the leading zero byte, if any.
|
||||
if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0x00) { |
||||
CBS_skip(&cbs, 1); |
||||
} |
||||
} |
||||
|
||||
if (!ASN1_STRING_set(ret, CBS_data(&cbs), CBS_len(&cbs))) { |
||||
goto err; |
||||
} |
||||
|
||||
if (is_negative) { |
||||
ret->type = V_ASN1_NEG_INTEGER; |
||||
negate_twos_complement(ret->data, ret->length); |
||||
} else { |
||||
ret->type = V_ASN1_INTEGER; |
||||
} |
||||
|
||||
// The value should be minimally-encoded.
|
||||
assert(ret->length == 0 || ret->data[0] != 0); |
||||
// Zero is not negative.
|
||||
assert(!is_negative || ret->length > 0); |
||||
|
||||
*inp += len; |
||||
if (out != NULL) { |
||||
*out = ret; |
||||
} |
||||
return ret; |
||||
|
||||
err: |
||||
if (ret != NULL && (out == NULL || *out != ret)) { |
||||
ASN1_INTEGER_free(ret); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t v) { |
||||
if (v >= 0) { |
||||
return ASN1_INTEGER_set_uint64(a, (uint64_t)v); |
||||
} |
||||
|
||||
if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t)v)) { |
||||
return 0; |
||||
} |
||||
|
||||
a->type = V_ASN1_NEG_INTEGER; |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t v) { |
||||
if (v >= 0) { |
||||
return ASN1_ENUMERATED_set_uint64(a, (uint64_t)v); |
||||
} |
||||
|
||||
if (!ASN1_ENUMERATED_set_uint64(a, 0 - (uint64_t)v)) { |
||||
return 0; |
||||
} |
||||
|
||||
a->type = V_ASN1_NEG_ENUMERATED; |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) { |
||||
static_assert(sizeof(long) <= sizeof(int64_t), "long fits in int64_t"); |
||||
return ASN1_INTEGER_set_int64(a, v); |
||||
} |
||||
|
||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) { |
||||
static_assert(sizeof(long) <= sizeof(int64_t), "long fits in int64_t"); |
||||
return ASN1_ENUMERATED_set_int64(a, v); |
||||
} |
||||
|
||||
static int asn1_string_set_uint64(ASN1_STRING *out, uint64_t v, int type) { |
||||
uint8_t buf[sizeof(uint64_t)]; |
||||
CRYPTO_store_u64_be(buf, v); |
||||
size_t leading_zeros; |
||||
for (leading_zeros = 0; leading_zeros < sizeof(buf); leading_zeros++) { |
||||
if (buf[leading_zeros] != 0) { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!ASN1_STRING_set(out, buf + leading_zeros, sizeof(buf) - leading_zeros)) { |
||||
return 0; |
||||
} |
||||
out->type = type; |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v) { |
||||
return asn1_string_set_uint64(out, v, V_ASN1_INTEGER); |
||||
} |
||||
|
||||
int ASN1_ENUMERATED_set_uint64(ASN1_ENUMERATED *out, uint64_t v) { |
||||
return asn1_string_set_uint64(out, v, V_ASN1_ENUMERATED); |
||||
} |
||||
|
||||
static int asn1_string_get_abs_uint64(uint64_t *out, const ASN1_STRING *a, |
||||
int type) { |
||||
if ((a->type & ~V_ASN1_NEG) != type) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE); |
||||
return 0; |
||||
} |
||||
uint8_t buf[sizeof(uint64_t)] = {0}; |
||||
if (a->length > (int)sizeof(buf)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); |
||||
return 0; |
||||
} |
||||
OPENSSL_memcpy(buf + sizeof(buf) - a->length, a->data, a->length); |
||||
*out = CRYPTO_load_u64_be(buf); |
||||
return 1; |
||||
} |
||||
|
||||
static int asn1_string_get_uint64(uint64_t *out, const ASN1_STRING *a, |
||||
int type) { |
||||
if (!asn1_string_get_abs_uint64(out, a, type)) { |
||||
return 0; |
||||
} |
||||
if (a->type & V_ASN1_NEG) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_INTEGER_get_uint64(uint64_t *out, const ASN1_INTEGER *a) { |
||||
return asn1_string_get_uint64(out, a, V_ASN1_INTEGER); |
||||
} |
||||
|
||||
int ASN1_ENUMERATED_get_uint64(uint64_t *out, const ASN1_ENUMERATED *a) { |
||||
return asn1_string_get_uint64(out, a, V_ASN1_ENUMERATED); |
||||
} |
||||
|
||||
static int asn1_string_get_int64(int64_t *out, const ASN1_STRING *a, int type) { |
||||
uint64_t v; |
||||
if (!asn1_string_get_abs_uint64(&v, a, type)) { |
||||
return 0; |
||||
} |
||||
int64_t i64; |
||||
int fits_in_i64; |
||||
// Check |v != 0| to handle manually-constructed negative zeros.
|
||||
if ((a->type & V_ASN1_NEG) && v != 0) { |
||||
i64 = (int64_t)(0u - v); |
||||
fits_in_i64 = i64 < 0; |
||||
} else { |
||||
i64 = (int64_t)v; |
||||
fits_in_i64 = i64 >= 0; |
||||
} |
||||
if (!fits_in_i64) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER); |
||||
return 0; |
||||
} |
||||
*out = i64; |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_INTEGER_get_int64(int64_t *out, const ASN1_INTEGER *a) { |
||||
return asn1_string_get_int64(out, a, V_ASN1_INTEGER); |
||||
} |
||||
|
||||
int ASN1_ENUMERATED_get_int64(int64_t *out, const ASN1_ENUMERATED *a) { |
||||
return asn1_string_get_int64(out, a, V_ASN1_ENUMERATED); |
||||
} |
||||
|
||||
static long asn1_string_get_long(const ASN1_STRING *a, int type) { |
||||
if (a == NULL) { |
||||
return 0; |
||||
} |
||||
|
||||
int64_t v; |
||||
if (!asn1_string_get_int64(&v, a, type) || //
|
||||
v < LONG_MIN || v > LONG_MAX) { |
||||
// This function's return value does not distinguish overflow from -1.
|
||||
ERR_clear_error(); |
||||
return -1; |
||||
} |
||||
|
||||
return (long)v; |
||||
} |
||||
|
||||
long ASN1_INTEGER_get(const ASN1_INTEGER *a) { |
||||
return asn1_string_get_long(a, V_ASN1_INTEGER); |
||||
} |
||||
|
||||
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a) { |
||||
return asn1_string_get_long(a, V_ASN1_ENUMERATED); |
||||
} |
||||
|
||||
static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai, |
||||
int type) { |
||||
ASN1_INTEGER *ret; |
||||
if (ai == NULL) { |
||||
ret = ASN1_STRING_type_new(type); |
||||
} else { |
||||
ret = ai; |
||||
} |
||||
int len; |
||||
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 = type | V_ASN1_NEG; |
||||
} else { |
||||
ret->type = type; |
||||
} |
||||
|
||||
len = BN_num_bytes(bn); |
||||
if (!ASN1_STRING_set(ret, NULL, len) || |
||||
!BN_bn2bin_padded(ret->data, len, bn)) { |
||||
goto err; |
||||
} |
||||
return ret; |
||||
|
||||
err: |
||||
if (ret != ai) { |
||||
ASN1_STRING_free(ret); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) { |
||||
return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER); |
||||
} |
||||
|
||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) { |
||||
return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED); |
||||
} |
||||
|
||||
static BIGNUM *asn1_string_to_bn(const ASN1_STRING *ai, BIGNUM *bn, int type) { |
||||
if ((ai->type & ~V_ASN1_NEG) != type) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE); |
||||
return NULL; |
||||
} |
||||
|
||||
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) { |
||||
BN_set_negative(ret, 1); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) { |
||||
return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER); |
||||
} |
||||
|
||||
BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) { |
||||
return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED); |
||||
} |
@ -0,0 +1,409 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <openssl/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); |
||||
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); |
||||
static int cpy_asc(unsigned long value, void *arg); |
||||
static int cpy_bmp(unsigned long value, void *arg); |
||||
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. |
||||
*/ |
||||
|
||||
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, |
||||
int inform, unsigned long mask) |
||||
{ |
||||
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 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) { |
||||
|
||||
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_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; |
||||
|
||||
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 ((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 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; |
||||
|
||||
case MBSTRING_BMP: |
||||
outlen = nchar << 1; |
||||
cpyfunc = cpy_bmp; |
||||
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; |
||||
} |
||||
|
||||
/*
|
||||
* 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) |
||||
{ |
||||
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 */ |
||||
|
||||
/* Just count number of characters */ |
||||
|
||||
static int in_utf8(unsigned long value, void *arg) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
/*
|
||||
* 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
@ -1,234 +0,0 @@ |
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../bytestring/internal.h" |
||||
#include "internal.h" |
||||
|
||||
// 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, |
||||
ossl_ssize_t len, int inform, unsigned long mask) { |
||||
return ASN1_mbstring_ncopy(out, in, len, inform, mask, /*minsize=*/0, |
||||
/*maxsize=*/0); |
||||
} |
||||
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING) |
||||
|
||||
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, |
||||
ossl_ssize_t len, int inform, unsigned long mask, |
||||
ossl_ssize_t minsize, ossl_ssize_t maxsize) { |
||||
if (len == -1) { |
||||
len = strlen((const char *)in); |
||||
} |
||||
if (!mask) { |
||||
mask = DIRSTRING_TYPE; |
||||
} |
||||
|
||||
int (*decode_func)(CBS *, uint32_t *); |
||||
int error; |
||||
switch (inform) { |
||||
case MBSTRING_BMP: |
||||
decode_func = CBS_get_ucs2_be; |
||||
error = ASN1_R_INVALID_BMPSTRING; |
||||
break; |
||||
|
||||
case MBSTRING_UNIV: |
||||
decode_func = CBS_get_utf32_be; |
||||
error = ASN1_R_INVALID_UNIVERSALSTRING; |
||||
break; |
||||
|
||||
case MBSTRING_UTF8: |
||||
decode_func = CBS_get_utf8; |
||||
error = ASN1_R_INVALID_UTF8STRING; |
||||
break; |
||||
|
||||
case MBSTRING_ASC: |
||||
decode_func = CBS_get_latin1; |
||||
error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid.
|
||||
break; |
||||
|
||||
default: |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT); |
||||
return -1; |
||||
} |
||||
|
||||
// Check |minsize| and |maxsize| and work out the minimal type, if any.
|
||||
CBS cbs; |
||||
CBS_init(&cbs, in, len); |
||||
size_t utf8_len = 0, nchar = 0; |
||||
while (CBS_len(&cbs) != 0) { |
||||
uint32_t c; |
||||
if (!decode_func(&cbs, &c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, error); |
||||
return -1; |
||||
} |
||||
if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) && |
||||
c == 0xfeff) { |
||||
// Reject byte-order mark. We could drop it but that would mean
|
||||
// adding ambiguity around whether a BOM was included or not when
|
||||
// matching strings.
|
||||
//
|
||||
// For a little-endian UCS-2 string, the BOM will appear as 0xfffe
|
||||
// and will be rejected as noncharacter, below.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); |
||||
return -1; |
||||
} |
||||
|
||||
// Update which output formats are still possible.
|
||||
if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) { |
||||
mask &= ~B_ASN1_PRINTABLESTRING; |
||||
} |
||||
if ((mask & B_ASN1_IA5STRING) && (c > 127)) { |
||||
mask &= ~B_ASN1_IA5STRING; |
||||
} |
||||
if ((mask & B_ASN1_T61STRING) && (c > 0xff)) { |
||||
mask &= ~B_ASN1_T61STRING; |
||||
} |
||||
if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) { |
||||
mask &= ~B_ASN1_BMPSTRING; |
||||
} |
||||
if (!mask) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); |
||||
return -1; |
||||
} |
||||
|
||||
nchar++; |
||||
utf8_len += CBB_get_utf8_len(c); |
||||
if (maxsize > 0 && nchar > (size_t)maxsize) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); |
||||
ERR_add_error_dataf("maxsize=%zu", (size_t)maxsize); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
if (minsize > 0 && nchar < (size_t)minsize) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT); |
||||
ERR_add_error_dataf("minsize=%zu", (size_t)minsize); |
||||
return -1; |
||||
} |
||||
|
||||
// Now work out output format and string type
|
||||
int str_type; |
||||
int (*encode_func)(CBB *, uint32_t) = CBB_add_latin1; |
||||
size_t size_estimate = nchar; |
||||
int 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; |
||||
encode_func = CBB_add_ucs2_be; |
||||
size_estimate = 2 * nchar; |
||||
} else if (mask & B_ASN1_UNIVERSALSTRING) { |
||||
str_type = V_ASN1_UNIVERSALSTRING; |
||||
encode_func = CBB_add_utf32_be; |
||||
size_estimate = 4 * nchar; |
||||
outform = MBSTRING_UNIV; |
||||
} else if (mask & B_ASN1_UTF8STRING) { |
||||
str_type = V_ASN1_UTF8STRING; |
||||
outform = MBSTRING_UTF8; |
||||
encode_func = CBB_add_utf8; |
||||
size_estimate = utf8_len; |
||||
} else { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS); |
||||
return -1; |
||||
} |
||||
|
||||
if (!out) { |
||||
return str_type; |
||||
} |
||||
|
||||
int free_dest = 0; |
||||
ASN1_STRING *dest; |
||||
if (*out) { |
||||
dest = *out; |
||||
} else { |
||||
free_dest = 1; |
||||
dest = ASN1_STRING_type_new(str_type); |
||||
if (!dest) { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
CBB cbb; |
||||
CBB_zero(&cbb); |
||||
// If both the same type just copy across
|
||||
uint8_t *data = NULL; |
||||
size_t data_len = 0; |
||||
if (inform == outform) { |
||||
if (!ASN1_STRING_set(dest, in, len)) { |
||||
goto err; |
||||
} |
||||
dest->type = str_type; |
||||
*out = dest; |
||||
return str_type; |
||||
} |
||||
if (!CBB_init(&cbb, size_estimate + 1)) { |
||||
goto err; |
||||
} |
||||
CBS_init(&cbs, in, len); |
||||
while (CBS_len(&cbs) != 0) { |
||||
uint32_t c; |
||||
if (!decode_func(&cbs, &c) || !encode_func(&cbb, c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); |
||||
goto err; |
||||
} |
||||
} |
||||
if (/* OpenSSL historically NUL-terminated this value with a single byte,
|
||||
* even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */ |
||||
!CBB_add_u8(&cbb, 0) || //
|
||||
!CBB_finish(&cbb, &data, &data_len) || //
|
||||
data_len < 1 || //
|
||||
data_len > INT_MAX) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); |
||||
OPENSSL_free(data); |
||||
goto err; |
||||
} |
||||
dest->type = str_type; |
||||
ASN1_STRING_set0(dest, data, (int)data_len - 1); |
||||
*out = dest; |
||||
return str_type; |
||||
|
||||
err: |
||||
if (free_dest) { |
||||
ASN1_STRING_free(dest); |
||||
} |
||||
CBB_cleanup(&cbb); |
||||
return -1; |
||||
} |
||||
|
||||
int asn1_is_printable(uint32_t value) { |
||||
if (value > 0x7f) { |
||||
return 0; |
||||
} |
||||
return OPENSSL_isalnum(value) || //
|
||||
value == ' ' || value == '\'' || value == '(' || value == ')' || |
||||
value == '+' || value == ',' || value == '-' || value == '.' || |
||||
value == '/' || value == ':' || value == '=' || value == '?'; |
||||
} |
@ -0,0 +1,403 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) |
||||
{ |
||||
unsigned char *p; |
||||
int objsize; |
||||
|
||||
if ((a == NULL) || (a->data == NULL)) |
||||
return (0); |
||||
|
||||
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); |
||||
if (pp == NULL || objsize == -1) |
||||
return objsize; |
||||
|
||||
p = *pp; |
||||
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); |
||||
OPENSSL_memcpy(p, a->data, a->length); |
||||
p += a->length; |
||||
|
||||
*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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
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--) { |
||||
BN_ULONG t = BN_div_word(bl, 0x80L); |
||||
if (t == (BN_ULONG)-1) |
||||
goto err; |
||||
tmp[i++] = (unsigned char)t; |
||||
} |
||||
} else { |
||||
|
||||
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); |
||||
} |
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a) |
||||
{ |
||||
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); |
||||
} |
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, |
||||
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; |
||||
} |
||||
|
||||
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; |
||||
|
||||
/*
|
||||
* 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); |
||||
|
||||
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; |
||||
} |
||||
OPENSSL_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); |
||||
} |
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void) |
||||
{ |
||||
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); |
||||
} |
||||
|
||||
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); |
||||
#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); |
||||
} |
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, |
||||
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)); |
||||
} |
@ -1,188 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
|
||||
#include "../bytestring/internal.h" |
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
int i2d_ASN1_OBJECT(const ASN1_OBJECT *in, unsigned char **outp) { |
||||
if (in == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER); |
||||
return -1; |
||||
} |
||||
|
||||
if (in->length <= 0) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); |
||||
return -1; |
||||
} |
||||
|
||||
CBB cbb, child; |
||||
if (!CBB_init(&cbb, (size_t)in->length + 2) || |
||||
!CBB_add_asn1(&cbb, &child, CBS_ASN1_OBJECT) || |
||||
!CBB_add_bytes(&child, in->data, in->length)) { |
||||
CBB_cleanup(&cbb); |
||||
return -1; |
||||
} |
||||
|
||||
return CBB_finish_i2d(&cbb, outp); |
||||
} |
||||
|
||||
int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) { |
||||
return OBJ_obj2txt(buf, buf_len, a, 0); |
||||
} |
||||
|
||||
static int write_str(BIO *bp, const char *str) { |
||||
size_t len = strlen(str); |
||||
if (len > INT_MAX) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); |
||||
return -1; |
||||
} |
||||
return BIO_write(bp, str, (int)len) == (int)len ? (int)len : -1; |
||||
} |
||||
|
||||
int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) { |
||||
if (a == NULL || a->data == NULL) { |
||||
return write_str(bp, "NULL"); |
||||
} |
||||
|
||||
char buf[80], *allocated = NULL; |
||||
const char *str = buf; |
||||
int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a); |
||||
if (len > (int)sizeof(buf) - 1) { |
||||
// The input was truncated. Allocate a buffer that fits.
|
||||
allocated = reinterpret_cast<char *>(OPENSSL_malloc(len + 1)); |
||||
if (allocated == NULL) { |
||||
return -1; |
||||
} |
||||
len = i2t_ASN1_OBJECT(allocated, len + 1, a); |
||||
str = allocated; |
||||
} |
||||
if (len <= 0) { |
||||
str = "<INVALID>"; |
||||
} |
||||
|
||||
int ret = write_str(bp, str); |
||||
OPENSSL_free(allocated); |
||||
return ret; |
||||
} |
||||
|
||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp, |
||||
long len) { |
||||
if (len < 0) { |
||||
return NULL; |
||||
} |
||||
|
||||
CBS cbs, child; |
||||
CBS_init(&cbs, *inp, (size_t)len); |
||||
if (!CBS_get_asn1(&cbs, &child, CBS_ASN1_OBJECT)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
||||
return NULL; |
||||
} |
||||
|
||||
const uint8_t *contents = CBS_data(&child); |
||||
ASN1_OBJECT *ret = c2i_ASN1_OBJECT(out, &contents, CBS_len(&child)); |
||||
if (ret != NULL) { |
||||
// |c2i_ASN1_OBJECT| should have consumed the entire input.
|
||||
assert(CBS_data(&cbs) == contents); |
||||
*inp = CBS_data(&cbs); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp, |
||||
long len) { |
||||
if (len < 0) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); |
||||
return NULL; |
||||
} |
||||
|
||||
CBS cbs; |
||||
CBS_init(&cbs, *inp, (size_t)len); |
||||
if (!CBS_is_valid_asn1_oid(&cbs)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); |
||||
return NULL; |
||||
} |
||||
|
||||
ASN1_OBJECT *ret = ASN1_OBJECT_create(NID_undef, *inp, (size_t)len, |
||||
/*sn=*/NULL, /*ln=*/NULL); |
||||
if (ret == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (out != NULL) { |
||||
ASN1_OBJECT_free(*out); |
||||
*out = ret; |
||||
} |
||||
*inp += len; // All bytes were consumed.
|
||||
return ret; |
||||
} |
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void) { |
||||
ASN1_OBJECT *ret; |
||||
|
||||
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); |
||||
if (ret == NULL) { |
||||
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) { |
||||
OPENSSL_free((void *)a->sn); |
||||
OPENSSL_free((void *)a->ln); |
||||
a->sn = a->ln = NULL; |
||||
} |
||||
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { |
||||
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, const unsigned char *data, size_t len, |
||||
const char *sn, const char *ln) { |
||||
if (len > INT_MAX) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); |
||||
return NULL; |
||||
} |
||||
|
||||
ASN1_OBJECT o; |
||||
o.sn = sn; |
||||
o.ln = ln; |
||||
o.data = data; |
||||
o.nid = nid; |
||||
o.length = (int)len; |
||||
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | |
||||
ASN1_OBJECT_FLAG_DYNAMIC_DATA; |
||||
return OBJ_dup(&o); |
||||
} |
@ -0,0 +1,77 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <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); |
||||
} |
||||
|
||||
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); |
||||
} |
@ -1,27 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) { |
||||
return ASN1_STRING_dup(x); |
||||
} |
||||
|
||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, |
||||
const ASN1_OCTET_STRING *b) { |
||||
return ASN1_STRING_cmp(a, b); |
||||
} |
||||
|
||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, |
||||
int len) { |
||||
return ASN1_STRING_set(x, d, len); |
||||
} |
@ -0,0 +1,93 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <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; |
||||
|
||||
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); |
||||
} |
@ -1,410 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
#include <ctype.h> |
||||
#include <inttypes.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../bytestring/internal.h" |
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
#define ESC_FLAGS \ |
||||
(ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_QUOTE | ASN1_STRFLGS_ESC_CTRL | \
|
||||
ASN1_STRFLGS_ESC_MSB) |
||||
|
||||
static int maybe_write(BIO *out, const void *buf, int len) { |
||||
// If |out| is NULL, ignore the output but report the length.
|
||||
return out == NULL || BIO_write(out, buf, len) == len; |
||||
} |
||||
|
||||
static int is_control_character(unsigned char c) { return c < 32 || c == 127; } |
||||
|
||||
static int do_esc_char(uint32_t c, unsigned long flags, char *do_quotes, |
||||
BIO *out, int is_first, int is_last) { |
||||
// |c| is a |uint32_t| because, depending on |ASN1_STRFLGS_UTF8_CONVERT|,
|
||||
// we may be escaping bytes or Unicode codepoints.
|
||||
char buf[16]; // Large enough for "\\W01234567".
|
||||
unsigned char u8 = (unsigned char)c; |
||||
if (c > 0xffff) { |
||||
snprintf(buf, sizeof(buf), "\\W%08" PRIX32, c); |
||||
} else if (c > 0xff) { |
||||
snprintf(buf, sizeof(buf), "\\U%04" PRIX32, c); |
||||
} else if ((flags & ASN1_STRFLGS_ESC_MSB) && c > 0x7f) { |
||||
snprintf(buf, sizeof(buf), "\\%02X", c); |
||||
} else if ((flags & ASN1_STRFLGS_ESC_CTRL) && is_control_character(c)) { |
||||
snprintf(buf, sizeof(buf), "\\%02X", c); |
||||
} else if (flags & ASN1_STRFLGS_ESC_2253) { |
||||
// See RFC 2253, sections 2.4 and 4.
|
||||
if (c == '\\' || c == '"') { |
||||
// Quotes and backslashes are always escaped, quoted or not.
|
||||
snprintf(buf, sizeof(buf), "\\%c", (int)c); |
||||
} else if (c == ',' || c == '+' || c == '<' || c == '>' || c == ';' || |
||||
(is_first && (c == ' ' || c == '#')) || |
||||
(is_last && (c == ' '))) { |
||||
if (flags & ASN1_STRFLGS_ESC_QUOTE) { |
||||
// No need to escape, just tell the caller to quote.
|
||||
if (do_quotes != NULL) { |
||||
*do_quotes = 1; |
||||
} |
||||
return maybe_write(out, &u8, 1) ? 1 : -1; |
||||
} |
||||
snprintf(buf, sizeof(buf), "\\%c", (int)c); |
||||
} else { |
||||
return maybe_write(out, &u8, 1) ? 1 : -1; |
||||
} |
||||
} else if ((flags & ESC_FLAGS) && c == '\\') { |
||||
// If any escape flags are set, also escape backslashes.
|
||||
snprintf(buf, sizeof(buf), "\\%c", (int)c); |
||||
} else { |
||||
return maybe_write(out, &u8, 1) ? 1 : -1; |
||||
} |
||||
|
||||
static_assert(sizeof(buf) < INT_MAX, "len may not fit in int"); |
||||
int len = (int)strlen(buf); |
||||
return maybe_write(out, buf, len) ? len : -1; |
||||
} |
||||
|
||||
// This function sends each character in a buffer to do_esc_char(). It
|
||||
// interprets the content formats and converts to or from UTF8 as
|
||||
// appropriate.
|
||||
|
||||
static int do_buf(const unsigned char *buf, int buflen, int encoding, |
||||
unsigned long flags, char *quotes, BIO *out) { |
||||
int (*get_char)(CBS *cbs, uint32_t *out); |
||||
int get_char_error; |
||||
switch (encoding) { |
||||
case MBSTRING_UNIV: |
||||
get_char = CBS_get_utf32_be; |
||||
get_char_error = ASN1_R_INVALID_UNIVERSALSTRING; |
||||
break; |
||||
case MBSTRING_BMP: |
||||
get_char = CBS_get_ucs2_be; |
||||
get_char_error = ASN1_R_INVALID_BMPSTRING; |
||||
break; |
||||
case MBSTRING_ASC: |
||||
get_char = CBS_get_latin1; |
||||
get_char_error = ERR_R_INTERNAL_ERROR; // Should not be possible.
|
||||
break; |
||||
case MBSTRING_UTF8: |
||||
get_char = CBS_get_utf8; |
||||
get_char_error = ASN1_R_INVALID_UTF8STRING; |
||||
break; |
||||
default: |
||||
assert(0); |
||||
return -1; |
||||
} |
||||
|
||||
CBS cbs; |
||||
CBS_init(&cbs, buf, buflen); |
||||
int outlen = 0; |
||||
while (CBS_len(&cbs) != 0) { |
||||
const int is_first = CBS_data(&cbs) == buf; |
||||
uint32_t c; |
||||
if (!get_char(&cbs, &c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, get_char_error); |
||||
return -1; |
||||
} |
||||
const int is_last = CBS_len(&cbs) == 0; |
||||
if (flags & ASN1_STRFLGS_UTF8_CONVERT) { |
||||
uint8_t utf8_buf[6]; |
||||
CBB utf8_cbb; |
||||
CBB_init_fixed(&utf8_cbb, utf8_buf, sizeof(utf8_buf)); |
||||
if (!CBB_add_utf8(&utf8_cbb, c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); |
||||
return 1; |
||||
} |
||||
size_t utf8_len = CBB_len(&utf8_cbb); |
||||
for (size_t i = 0; i < utf8_len; i++) { |
||||
int len = do_esc_char(utf8_buf[i], flags, quotes, out, |
||||
is_first && i == 0, is_last && i == utf8_len - 1); |
||||
if (len < 0) { |
||||
return -1; |
||||
} |
||||
outlen += len; |
||||
} |
||||
} else { |
||||
int len = do_esc_char(c, flags, quotes, out, is_first, is_last); |
||||
if (len < 0) { |
||||
return -1; |
||||
} |
||||
outlen += len; |
||||
} |
||||
} |
||||
return outlen; |
||||
} |
||||
|
||||
// This function hex dumps a buffer of characters
|
||||
|
||||
static int do_hex_dump(BIO *out, unsigned char *buf, int buflen) { |
||||
static const char hexdig[] = "0123456789ABCDEF"; |
||||
unsigned char *p, *q; |
||||
char hextmp[2]; |
||||
if (out) { |
||||
p = buf; |
||||
q = buf + buflen; |
||||
while (p != q) { |
||||
hextmp[0] = hexdig[*p >> 4]; |
||||
hextmp[1] = hexdig[*p & 0xf]; |
||||
if (!maybe_write(out, hextmp, 2)) { |
||||
return -1; |
||||
} |
||||
p++; |
||||
} |
||||
} |
||||
return buflen << 1; |
||||
} |
||||
|
||||
// "dump" a string. This is done when the type is unknown, or the flags
|
||||
// request it. We can either dump the content octets or the entire DER
|
||||
// encoding. This uses the RFC 2253 #01234 format.
|
||||
|
||||
static int do_dump(unsigned long flags, BIO *out, const ASN1_STRING *str) { |
||||
if (!maybe_write(out, "#", 1)) { |
||||
return -1; |
||||
} |
||||
|
||||
// If we don't dump DER encoding just dump content octets
|
||||
if (!(flags & ASN1_STRFLGS_DUMP_DER)) { |
||||
int outlen = do_hex_dump(out, str->data, str->length); |
||||
if (outlen < 0) { |
||||
return -1; |
||||
} |
||||
return outlen + 1; |
||||
} |
||||
|
||||
// Placing the ASN1_STRING in a temporary ASN1_TYPE allows the DER encoding
|
||||
// to readily obtained.
|
||||
ASN1_TYPE t; |
||||
OPENSSL_memset(&t, 0, sizeof(ASN1_TYPE)); |
||||
asn1_type_set0_string(&t, (ASN1_STRING *)str); |
||||
unsigned char *der_buf = NULL; |
||||
int der_len = i2d_ASN1_TYPE(&t, &der_buf); |
||||
if (der_len < 0) { |
||||
return -1; |
||||
} |
||||
int outlen = do_hex_dump(out, der_buf, der_len); |
||||
OPENSSL_free(der_buf); |
||||
if (outlen < 0) { |
||||
return -1; |
||||
} |
||||
return outlen + 1; |
||||
} |
||||
|
||||
// string_type_to_encoding returns the |MBSTRING_*| constant for the encoding
|
||||
// used by the |ASN1_STRING| type |type|, or -1 if |tag| is not a string
|
||||
// type.
|
||||
static int string_type_to_encoding(int type) { |
||||
// This function is sometimes passed ASN.1 universal types and sometimes
|
||||
// passed |ASN1_STRING| type values
|
||||
switch (type) { |
||||
case V_ASN1_UTF8STRING: |
||||
return MBSTRING_UTF8; |
||||
case V_ASN1_NUMERICSTRING: |
||||
case V_ASN1_PRINTABLESTRING: |
||||
case V_ASN1_T61STRING: |
||||
case V_ASN1_IA5STRING: |
||||
case V_ASN1_UTCTIME: |
||||
case V_ASN1_GENERALIZEDTIME: |
||||
case V_ASN1_ISO64STRING: |
||||
// |MBSTRING_ASC| refers to Latin-1, not ASCII.
|
||||
return MBSTRING_ASC; |
||||
case V_ASN1_UNIVERSALSTRING: |
||||
return MBSTRING_UNIV; |
||||
case V_ASN1_BMPSTRING: |
||||
return MBSTRING_BMP; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
// This is the main function, print out an ASN1_STRING taking note of various
|
||||
// escape and display options. Returns number of characters written or -1 if
|
||||
// an error occurred.
|
||||
|
||||
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, |
||||
unsigned long flags) { |
||||
int type = str->type; |
||||
int outlen = 0; |
||||
if (flags & ASN1_STRFLGS_SHOW_TYPE) { |
||||
const char *tagname = ASN1_tag2str(type); |
||||
outlen += strlen(tagname); |
||||
if (!maybe_write(out, tagname, outlen) || !maybe_write(out, ":", 1)) { |
||||
return -1; |
||||
} |
||||
outlen++; |
||||
} |
||||
|
||||
// Decide what to do with |str|, either dump the contents or display it.
|
||||
int encoding; |
||||
if (flags & ASN1_STRFLGS_DUMP_ALL) { |
||||
// Dump everything.
|
||||
encoding = -1; |
||||
} else if (flags & ASN1_STRFLGS_IGNORE_TYPE) { |
||||
// Ignore the string type and interpret the contents as Latin-1.
|
||||
encoding = MBSTRING_ASC; |
||||
} else { |
||||
encoding = string_type_to_encoding(type); |
||||
if (encoding == -1 && (flags & ASN1_STRFLGS_DUMP_UNKNOWN) == 0) { |
||||
encoding = MBSTRING_ASC; |
||||
} |
||||
} |
||||
|
||||
if (encoding == -1) { |
||||
int len = do_dump(flags, out, str); |
||||
if (len < 0) { |
||||
return -1; |
||||
} |
||||
outlen += len; |
||||
return outlen; |
||||
} |
||||
|
||||
// Measure the length.
|
||||
char quotes = 0; |
||||
int len = do_buf(str->data, str->length, encoding, flags, "es, NULL); |
||||
if (len < 0) { |
||||
return -1; |
||||
} |
||||
outlen += len; |
||||
if (quotes) { |
||||
outlen += 2; |
||||
} |
||||
if (!out) { |
||||
return outlen; |
||||
} |
||||
|
||||
// Encode the value.
|
||||
if ((quotes && !maybe_write(out, "\"", 1)) || |
||||
do_buf(str->data, str->length, encoding, flags, NULL, out) < 0 || |
||||
(quotes && !maybe_write(out, "\"", 1))) { |
||||
return -1; |
||||
} |
||||
return outlen; |
||||
} |
||||
|
||||
int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, |
||||
unsigned long flags) { |
||||
BIO *bio = NULL; |
||||
if (fp != NULL) { |
||||
// If |fp| is NULL, this function returns the number of bytes without
|
||||
// writing.
|
||||
bio = BIO_new_fp(fp, BIO_NOCLOSE); |
||||
if (bio == NULL) { |
||||
return -1; |
||||
} |
||||
} |
||||
int ret = ASN1_STRING_print_ex(bio, str, flags); |
||||
BIO_free(bio); |
||||
return ret; |
||||
} |
||||
|
||||
int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) { |
||||
if (!in) { |
||||
return -1; |
||||
} |
||||
int mbflag = string_type_to_encoding(in->type); |
||||
if (mbflag == -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG); |
||||
return -1; |
||||
} |
||||
ASN1_STRING stmp, *str = &stmp; |
||||
stmp.data = NULL; |
||||
stmp.length = 0; |
||||
stmp.flags = 0; |
||||
int ret = |
||||
ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING); |
||||
if (ret < 0) { |
||||
return ret; |
||||
} |
||||
*out = stmp.data; |
||||
return stmp.length; |
||||
} |
||||
|
||||
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) { |
||||
int i, n; |
||||
char buf[80]; |
||||
const char *p; |
||||
|
||||
if (v == NULL) { |
||||
return 0; |
||||
} |
||||
n = 0; |
||||
p = (const char *)v->data; |
||||
for (i = 0; i < v->length; i++) { |
||||
if ((p[i] > '~') || ((p[i] < ' ') && (p[i] != '\n') && (p[i] != '\r'))) { |
||||
buf[n] = '.'; |
||||
} else { |
||||
buf[n] = p[i]; |
||||
} |
||||
n++; |
||||
if (n >= 80) { |
||||
if (BIO_write(bp, buf, n) <= 0) { |
||||
return 0; |
||||
} |
||||
n = 0; |
||||
} |
||||
} |
||||
if (n > 0) { |
||||
if (BIO_write(bp, buf, n) <= 0) { |
||||
return 0; |
||||
} |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) { |
||||
if (tm->type == V_ASN1_UTCTIME) { |
||||
return ASN1_UTCTIME_print(bp, tm); |
||||
} |
||||
if (tm->type == V_ASN1_GENERALIZEDTIME) { |
||||
return ASN1_GENERALIZEDTIME_print(bp, tm); |
||||
} |
||||
BIO_puts(bp, "Bad time value"); |
||||
return 0; |
||||
} |
||||
|
||||
static const char *const mon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; |
||||
|
||||
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) { |
||||
CBS cbs; |
||||
CBS_init(&cbs, tm->data, tm->length); |
||||
struct tm utc; |
||||
if (!CBS_parse_generalized_time(&cbs, &utc, /*allow_timezone_offset=*/0)) { |
||||
BIO_puts(bp, "Bad time value"); |
||||
return 0; |
||||
} |
||||
|
||||
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d GMT", mon[utc.tm_mon], |
||||
utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec, |
||||
utc.tm_year + 1900) > 0; |
||||
} |
||||
|
||||
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) { |
||||
CBS cbs; |
||||
CBS_init(&cbs, tm->data, tm->length); |
||||
struct tm utc; |
||||
if (!CBS_parse_utc_time(&cbs, &utc, /*allow_timezone_offset=*/0)) { |
||||
BIO_puts(bp, "Bad time value"); |
||||
return 0; |
||||
} |
||||
|
||||
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d GMT", mon[utc.tm_mon], |
||||
utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec, |
||||
utc.tm_year + 1900) > 0; |
||||
} |
@ -0,0 +1,312 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <stdlib.h> /* For bsearch */ |
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
#include <openssl/stack.h> |
||||
|
||||
DEFINE_STACK_OF(ASN1_STRING_TABLE) |
||||
|
||||
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. |
||||
*/ |
||||
|
||||
static unsigned long global_mask = B_ASN1_UTF8STRING; |
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask) |
||||
{ |
||||
global_mask = mask; |
||||
} |
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void) |
||||
{ |
||||
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. |
||||
*/ |
||||
|
||||
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; |
||||
} |
||||
|
||||
/*
|
||||
* 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_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: |
||||
*/ |
||||
|
||||
/* 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 |
||||
|
||||
/* 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} |
||||
}; |
||||
|
||||
static int sk_table_cmp(const ASN1_STRING_TABLE **a, |
||||
const ASN1_STRING_TABLE **b) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
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; |
||||
|
||||
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) |
||||
{ |
||||
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; |
||||
tmp->minsize = tmp->maxsize = -1; |
||||
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); |
||||
} |
||||
|
||||
static void st_free(ASN1_STRING_TABLE *tbl) |
||||
{ |
||||
if (tbl->flags & STABLE_FLAGS_MALLOC) |
||||
OPENSSL_free(tbl); |
||||
} |
||||
|
||||
#ifdef STRING_TABLE_TEST |
||||
|
||||
int main(void) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
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)); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#endif |
@ -1,201 +0,0 @@ |
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
|
||||
#include "../internal.h" |
||||
#include "../lhash/internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
DEFINE_LHASH_OF(ASN1_STRING_TABLE) |
||||
|
||||
static LHASH_OF(ASN1_STRING_TABLE) *string_tables = NULL; |
||||
static CRYPTO_MUTEX string_tables_lock = CRYPTO_MUTEX_INIT; |
||||
|
||||
void ASN1_STRING_set_default_mask(unsigned long mask) {} |
||||
|
||||
unsigned long ASN1_STRING_get_default_mask(void) { return B_ASN1_UTF8STRING; } |
||||
|
||||
int ASN1_STRING_set_default_mask_asc(const char *p) { return 1; } |
||||
|
||||
static const ASN1_STRING_TABLE *asn1_string_table_get(int nid); |
||||
|
||||
// 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, |
||||
ossl_ssize_t len, int inform, int nid) { |
||||
ASN1_STRING *str = NULL; |
||||
int ret; |
||||
if (!out) { |
||||
out = &str; |
||||
} |
||||
const ASN1_STRING_TABLE *tbl = asn1_string_table_get(nid); |
||||
if (tbl != NULL) { |
||||
unsigned long mask = tbl->mask; |
||||
if (!(tbl->flags & STABLE_NO_MASK)) { |
||||
mask &= B_ASN1_UTF8STRING; |
||||
} |
||||
ret = ASN1_mbstring_ncopy(out, in, len, inform, mask, tbl->minsize, |
||||
tbl->maxsize); |
||||
} else { |
||||
ret = ASN1_mbstring_copy(out, in, len, inform, B_ASN1_UTF8STRING); |
||||
} |
||||
if (ret <= 0) { |
||||
return NULL; |
||||
} |
||||
return *out; |
||||
} |
||||
|
||||
// Now the tables and helper functions for the string table:
|
||||
|
||||
// See RFC 5280.
|
||||
#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_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}}; |
||||
|
||||
static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) { |
||||
if (a->nid < b->nid) { |
||||
return -1; |
||||
} |
||||
if (a->nid > b->nid) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int table_cmp_void(const void *a, const void *b) { |
||||
return table_cmp(reinterpret_cast<const ASN1_STRING_TABLE *>(a), |
||||
reinterpret_cast<const ASN1_STRING_TABLE *>(b)); |
||||
} |
||||
|
||||
static uint32_t table_hash(const ASN1_STRING_TABLE *tbl) { |
||||
return OPENSSL_hash32(&tbl->nid, sizeof(tbl->nid)); |
||||
} |
||||
|
||||
static const ASN1_STRING_TABLE *asn1_string_table_get(int nid) { |
||||
ASN1_STRING_TABLE key; |
||||
key.nid = nid; |
||||
const ASN1_STRING_TABLE *tbl = reinterpret_cast<ASN1_STRING_TABLE *>( |
||||
bsearch(&key, tbl_standard, OPENSSL_ARRAY_SIZE(tbl_standard), |
||||
sizeof(ASN1_STRING_TABLE), table_cmp_void)); |
||||
if (tbl != NULL) { |
||||
return tbl; |
||||
} |
||||
|
||||
CRYPTO_MUTEX_lock_read(&string_tables_lock); |
||||
if (string_tables != NULL) { |
||||
tbl = lh_ASN1_STRING_TABLE_retrieve(string_tables, &key); |
||||
} |
||||
CRYPTO_MUTEX_unlock_read(&string_tables_lock); |
||||
// Note returning |tbl| without the lock is only safe because
|
||||
// |ASN1_STRING_TABLE_add| cannot modify or delete existing entries. If we
|
||||
// wish to support that, this function must copy the result under a lock.
|
||||
return tbl; |
||||
} |
||||
|
||||
int ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, |
||||
unsigned long mask, unsigned long flags) { |
||||
// Existing entries cannot be overwritten.
|
||||
if (asn1_string_table_get(nid) != NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
||||
return 0; |
||||
} |
||||
|
||||
int ret = 0; |
||||
CRYPTO_MUTEX_lock_write(&string_tables_lock); |
||||
|
||||
ASN1_STRING_TABLE *tbl = NULL; |
||||
if (string_tables == NULL) { |
||||
string_tables = lh_ASN1_STRING_TABLE_new(table_hash, table_cmp); |
||||
if (string_tables == NULL) { |
||||
goto err; |
||||
} |
||||
} else { |
||||
// Check again for an existing entry. One may have been added while
|
||||
// unlocked.
|
||||
ASN1_STRING_TABLE key; |
||||
key.nid = nid; |
||||
if (lh_ASN1_STRING_TABLE_retrieve(string_tables, &key) != NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
||||
goto err; |
||||
} |
||||
} |
||||
|
||||
tbl = reinterpret_cast<ASN1_STRING_TABLE *>( |
||||
OPENSSL_malloc(sizeof(ASN1_STRING_TABLE))); |
||||
if (tbl == NULL) { |
||||
goto err; |
||||
} |
||||
tbl->nid = nid; |
||||
tbl->flags = flags; |
||||
tbl->minsize = minsize; |
||||
tbl->maxsize = maxsize; |
||||
tbl->mask = mask; |
||||
ASN1_STRING_TABLE *old_tbl; |
||||
if (!lh_ASN1_STRING_TABLE_insert(string_tables, &old_tbl, tbl)) { |
||||
OPENSSL_free(tbl); |
||||
goto err; |
||||
} |
||||
assert(old_tbl == NULL); |
||||
ret = 1; |
||||
|
||||
err: |
||||
CRYPTO_MUTEX_unlock_write(&string_tables_lock); |
||||
return ret; |
||||
} |
||||
|
||||
void ASN1_STRING_TABLE_cleanup(void) {} |
||||
|
||||
void asn1_get_string_table_for_testing(const ASN1_STRING_TABLE **out_ptr, |
||||
size_t *out_len) { |
||||
*out_ptr = tbl_standard; |
||||
*out_len = OPENSSL_ARRAY_SIZE(tbl_standard); |
||||
} |
@ -0,0 +1,213 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/buf.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#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. |
||||
*/ |
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) |
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) |
||||
|
||||
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) |
||||
{ |
||||
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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
/* Convert an ASN1_TIME structure to GeneralizedTime */ |
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, |
||||
ASN1_GENERALIZEDTIME **out) |
||||
{ |
||||
ASN1_GENERALIZEDTIME *ret = NULL; |
||||
char *str; |
||||
int newlen; |
||||
|
||||
if (!ASN1_TIME_check(t)) |
||||
return NULL; |
||||
|
||||
if (!out || !*out) { |
||||
if (!(ret = ASN1_GENERALIZEDTIME_new())) |
||||
goto err; |
||||
} else { |
||||
ret = *out; |
||||
} |
||||
|
||||
/* If already GeneralizedTime just copy across */ |
||||
if (t->type == V_ASN1_GENERALIZEDTIME) { |
||||
if (!ASN1_STRING_set(ret, t->data, t->length)) |
||||
goto err; |
||||
goto done; |
||||
} |
||||
|
||||
/* grow the string */ |
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2)) |
||||
goto err; |
||||
/* 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); |
||||
|
||||
done: |
||||
if (out != NULL && *out == NULL) |
||||
*out = ret; |
||||
return ret; |
||||
|
||||
err: |
||||
if (out == NULL || *out != ret) |
||||
ASN1_GENERALIZEDTIME_free(ret); |
||||
return NULL; |
||||
} |
||||
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) |
||||
{ |
||||
ASN1_TIME t; |
||||
|
||||
t.length = strlen(str); |
||||
t.data = (unsigned char *)str; |
||||
t.flags = 0; |
||||
|
||||
t.type = V_ASN1_UTCTIME; |
||||
|
||||
if (!ASN1_TIME_check(&t)) { |
||||
t.type = V_ASN1_GENERALIZEDTIME; |
||||
if (!ASN1_TIME_check(&t)) |
||||
return 0; |
||||
} |
||||
|
||||
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) |
||||
return 0; |
||||
|
||||
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); |
||||
|
||||
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); |
||||
} |
@ -1,219 +0,0 @@ |
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
#include <openssl/posix_time.h> |
||||
|
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "internal.h" |
||||
|
||||
// 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) |
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const(ASN1_TIME) |
||||
|
||||
ASN1_TIME *ASN1_TIME_set_posix(ASN1_TIME *s, int64_t posix_time) { |
||||
return ASN1_TIME_adj(s, posix_time, 0, 0); |
||||
} |
||||
|
||||
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t time) { |
||||
return ASN1_TIME_adj(s, time, 0, 0); |
||||
} |
||||
|
||||
static int fits_in_utc_time(const struct tm *tm) { |
||||
return 50 <= tm->tm_year && tm->tm_year < 150; |
||||
} |
||||
|
||||
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, int64_t posix_time, int offset_day, |
||||
long offset_sec) { |
||||
struct tm tm; |
||||
|
||||
if (!OPENSSL_posix_to_tm(posix_time, &tm)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME); |
||||
return NULL; |
||||
} |
||||
if (offset_day || offset_sec) { |
||||
if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec)) { |
||||
return NULL; |
||||
} |
||||
} |
||||
if (fits_in_utc_time(&tm)) { |
||||
return ASN1_UTCTIME_adj(s, posix_time, offset_day, offset_sec); |
||||
} |
||||
return ASN1_GENERALIZEDTIME_adj(s, posix_time, offset_day, offset_sec); |
||||
} |
||||
|
||||
int ASN1_TIME_check(const 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; |
||||
} |
||||
|
||||
// Convert an ASN1_TIME structure to GeneralizedTime
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *in, |
||||
ASN1_GENERALIZEDTIME **out) { |
||||
if (!ASN1_TIME_check(in)) { |
||||
return NULL; |
||||
} |
||||
|
||||
ASN1_GENERALIZEDTIME *ret = NULL; |
||||
if (!out || !*out) { |
||||
if (!(ret = ASN1_GENERALIZEDTIME_new())) { |
||||
goto err; |
||||
} |
||||
} else { |
||||
ret = *out; |
||||
} |
||||
|
||||
// If already GeneralizedTime just copy across
|
||||
if (in->type == V_ASN1_GENERALIZEDTIME) { |
||||
if (!ASN1_STRING_set(ret, in->data, in->length)) { |
||||
goto err; |
||||
} |
||||
goto done; |
||||
} |
||||
|
||||
// Grow the string to accomodate the two-digit century.
|
||||
if (!ASN1_STRING_set(ret, NULL, in->length + 2)) { |
||||
goto err; |
||||
} |
||||
|
||||
{ |
||||
char *const out_str = (char *)ret->data; |
||||
// |ASN1_STRING_set| also allocates an additional byte for a trailing NUL.
|
||||
const size_t out_str_capacity = in->length + 2 + 1; |
||||
// Work out the century and prepend
|
||||
if (in->data[0] >= '5') { |
||||
OPENSSL_strlcpy(out_str, "19", out_str_capacity); |
||||
} else { |
||||
OPENSSL_strlcpy(out_str, "20", out_str_capacity); |
||||
} |
||||
OPENSSL_strlcat(out_str, (const char *)in->data, out_str_capacity); |
||||
} |
||||
|
||||
done: |
||||
if (out != NULL && *out == NULL) { |
||||
*out = ret; |
||||
} |
||||
return ret; |
||||
|
||||
err: |
||||
if (out == NULL || *out != ret) { |
||||
ASN1_GENERALIZEDTIME_free(ret); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) { |
||||
return ASN1_UTCTIME_set_string(s, str) || |
||||
ASN1_GENERALIZEDTIME_set_string(s, str); |
||||
} |
||||
|
||||
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str) { |
||||
CBS cbs; |
||||
CBS_init(&cbs, (const uint8_t *)str, strlen(str)); |
||||
int type; |
||||
struct tm tm; |
||||
if (CBS_parse_utc_time(&cbs, /*out_tm=*/NULL, |
||||
/*allow_timezone_offset=*/0)) { |
||||
type = V_ASN1_UTCTIME; |
||||
} else if (CBS_parse_generalized_time(&cbs, &tm, |
||||
/*allow_timezone_offset=*/0)) { |
||||
type = V_ASN1_GENERALIZEDTIME; |
||||
if (fits_in_utc_time(&tm)) { |
||||
type = V_ASN1_UTCTIME; |
||||
CBS_skip(&cbs, 2); |
||||
} |
||||
} else { |
||||
return 0; |
||||
} |
||||
|
||||
if (s != NULL) { |
||||
if (!ASN1_STRING_set(s, CBS_data(&cbs), CBS_len(&cbs))) { |
||||
return 0; |
||||
} |
||||
s->type = type; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t, |
||||
int allow_timezone_offset) { |
||||
if (t == NULL) { |
||||
if (OPENSSL_posix_to_tm(time(NULL), tm)) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
if (t->type == V_ASN1_UTCTIME) { |
||||
return asn1_utctime_to_tm(tm, t, allow_timezone_offset); |
||||
} else if (t->type == V_ASN1_GENERALIZEDTIME) { |
||||
return asn1_generalizedtime_to_tm(tm, t); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int ASN1_TIME_diff(int *out_days, int *out_seconds, const ASN1_TIME *from, |
||||
const ASN1_TIME *to) { |
||||
struct tm tm_from, tm_to; |
||||
if (!asn1_time_to_tm(&tm_from, from, /*allow_timezone_offset=*/1)) { |
||||
return 0; |
||||
} |
||||
if (!asn1_time_to_tm(&tm_to, to, /*allow_timezone_offset=*/1)) { |
||||
return 0; |
||||
} |
||||
return OPENSSL_gmtime_diff(out_days, out_seconds, &tm_from, &tm_to); |
||||
} |
||||
|
||||
int ASN1_TIME_to_posix_nonstandard(const ASN1_TIME *t, int64_t *out_time) { |
||||
struct tm tm; |
||||
if (!asn1_time_to_tm(&tm, t, /*allow_timezone_offset=*/1)) { |
||||
return 0; |
||||
} |
||||
return OPENSSL_tm_to_posix(&tm, out_time); |
||||
} |
||||
|
||||
// The functions below do *not* permissively allow the use of four digit
|
||||
// timezone offsets in UTC times, as is done elsewhere in the code. They are
|
||||
// both new API, and used internally to X509_cmp_time. This is to discourage the
|
||||
// use of nonstandard times in new code, and to ensure that this code behaves
|
||||
// correctly in X509_cmp_time which historically did its own time validations
|
||||
// slightly different than the many other copies of X.509 time validation
|
||||
// sprinkled through the codebase. The custom checks in X509_cmp_time meant that
|
||||
// it did not allow four digit timezone offsets in UTC times.
|
||||
int ASN1_TIME_to_time_t(const ASN1_TIME *t, time_t *out_time) { |
||||
struct tm tm; |
||||
if (!asn1_time_to_tm(&tm, t, /*allow_timezone_offset=*/0)) { |
||||
return 0; |
||||
} |
||||
return OPENSSL_timegm(&tm, out_time); |
||||
} |
||||
|
||||
int ASN1_TIME_to_posix(const ASN1_TIME *t, int64_t *out_time) { |
||||
struct tm tm; |
||||
if (!asn1_time_to_tm(&tm, t, /*allow_timezone_offset=*/0)) { |
||||
return 0; |
||||
} |
||||
return OPENSSL_tm_to_posix(&tm, out_time); |
||||
} |
@ -0,0 +1,151 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/err.h> |
||||
#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); |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
/* Returns 0 if they are equal, != 0 otherwise. */ |
||||
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) |
||||
{ |
||||
int result = -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_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; |
||||
} |
@ -1,167 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
|
||||
#include "internal.h" |
||||
|
||||
|
||||
int ASN1_TYPE_get(const ASN1_TYPE *a) { |
||||
switch (a->type) { |
||||
case V_ASN1_NULL: |
||||
case V_ASN1_BOOLEAN: |
||||
return a->type; |
||||
case V_ASN1_OBJECT: |
||||
return a->value.object != NULL ? a->type : 0; |
||||
default: |
||||
return a->value.asn1_string != NULL ? a->type : 0; |
||||
} |
||||
} |
||||
|
||||
const void *asn1_type_value_as_pointer(const ASN1_TYPE *a) { |
||||
switch (a->type) { |
||||
case V_ASN1_NULL: |
||||
return NULL; |
||||
case V_ASN1_BOOLEAN: |
||||
return a->value.boolean ? (void *)0xff : NULL; |
||||
case V_ASN1_OBJECT: |
||||
return a->value.object; |
||||
default: |
||||
return a->value.asn1_string; |
||||
} |
||||
} |
||||
|
||||
void asn1_type_set0_string(ASN1_TYPE *a, ASN1_STRING *str) { |
||||
// |ASN1_STRING| types are almost the same as |ASN1_TYPE| types, except that
|
||||
// the negative flag is not reflected into |ASN1_TYPE|.
|
||||
int type = str->type; |
||||
if (type == V_ASN1_NEG_INTEGER) { |
||||
type = V_ASN1_INTEGER; |
||||
} else if (type == V_ASN1_NEG_ENUMERATED) { |
||||
type = V_ASN1_ENUMERATED; |
||||
} |
||||
|
||||
// These types are not |ASN1_STRING| types and use a different
|
||||
// representation when stored in |ASN1_TYPE|.
|
||||
assert(type != V_ASN1_NULL && type != V_ASN1_OBJECT && |
||||
type != V_ASN1_BOOLEAN); |
||||
ASN1_TYPE_set(a, type, str); |
||||
} |
||||
|
||||
void asn1_type_cleanup(ASN1_TYPE *a) { |
||||
switch (a->type) { |
||||
case V_ASN1_NULL: |
||||
a->value.ptr = NULL; |
||||
break; |
||||
case V_ASN1_BOOLEAN: |
||||
a->value.boolean = ASN1_BOOLEAN_NONE; |
||||
break; |
||||
case V_ASN1_OBJECT: |
||||
ASN1_OBJECT_free(a->value.object); |
||||
a->value.object = NULL; |
||||
break; |
||||
default: |
||||
ASN1_STRING_free(a->value.asn1_string); |
||||
a->value.asn1_string = NULL; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) { |
||||
asn1_type_cleanup(a); |
||||
a->type = type; |
||||
switch (type) { |
||||
case V_ASN1_NULL: |
||||
a->value.ptr = NULL; |
||||
break; |
||||
case V_ASN1_BOOLEAN: |
||||
a->value.boolean = value ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE; |
||||
break; |
||||
case V_ASN1_OBJECT: |
||||
a->value.object = reinterpret_cast<ASN1_OBJECT *>(value); |
||||
break; |
||||
default: |
||||
a->value.asn1_string = reinterpret_cast<ASN1_STRING *>(value); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
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(reinterpret_cast<const ASN1_OBJECT *>(value)); |
||||
if (!odup) { |
||||
return 0; |
||||
} |
||||
ASN1_TYPE_set(a, type, odup); |
||||
} else { |
||||
ASN1_STRING *sdup; |
||||
sdup = ASN1_STRING_dup(reinterpret_cast<const ASN1_STRING *>(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; |
||||
|
||||
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_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(a->value.asn1_string, b->value.asn1_string); |
||||
break; |
||||
} |
||||
|
||||
return result; |
||||
} |
@ -0,0 +1,303 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "asn1_locl.h" |
||||
|
||||
|
||||
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; |
||||
|
||||
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 ((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; |
||||
} |
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) |
||||
{ |
||||
return asn1_utctime_to_tm(NULL, d); |
||||
} |
||||
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) |
||||
{ |
||||
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); |
||||
} |
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) |
||||
{ |
||||
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; |
||||
|
||||
if (s == NULL) { |
||||
free_s = 1; |
||||
s = M_ASN1_UTCTIME_new(); |
||||
} |
||||
if (s == NULL) |
||||
goto err; |
||||
|
||||
ts = OPENSSL_gmtime(&t, &data); |
||||
if (ts == NULL) |
||||
goto err; |
||||
|
||||
if (offset_day || offset_sec) { |
||||
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) |
||||
goto err; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) |
||||
{ |
||||
struct tm stm, ttm; |
||||
int day, sec; |
||||
|
||||
if (!asn1_utctime_to_tm(&stm, s)) |
||||
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 0 |
||||
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s) |
||||
{ |
||||
struct tm tm; |
||||
int offset; |
||||
|
||||
OPENSSL_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 |
||||
|
||||
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 |
@ -1,104 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/posix_time.h> |
||||
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include "internal.h" |
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d, |
||||
int allow_timezone_offset) { |
||||
if (d->type != V_ASN1_UTCTIME) { |
||||
return 0; |
||||
} |
||||
CBS cbs; |
||||
CBS_init(&cbs, d->data, (size_t)d->length); |
||||
if (!CBS_parse_utc_time(&cbs, tm, allow_timezone_offset)) { |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) { |
||||
return asn1_utctime_to_tm(NULL, d, /*allow_timezone_offset=*/1); |
||||
} |
||||
|
||||
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) { |
||||
// Although elsewhere we allow timezone offsets with UTCTime, to be compatible
|
||||
// with some existing misissued certificates, this function is used to
|
||||
// construct new certificates and can be stricter.
|
||||
size_t len = strlen(str); |
||||
CBS cbs; |
||||
CBS_init(&cbs, (const uint8_t *)str, len); |
||||
if (!CBS_parse_utc_time(&cbs, /*out_tm=*/NULL, |
||||
/*allow_timezone_offset=*/0)) { |
||||
return 0; |
||||
} |
||||
if (s != NULL) { |
||||
if (!ASN1_STRING_set(s, str, len)) { |
||||
return 0; |
||||
} |
||||
s->type = V_ASN1_UTCTIME; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, int64_t posix_time) { |
||||
return ASN1_UTCTIME_adj(s, posix_time, 0, 0); |
||||
} |
||||
|
||||
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, int64_t posix_time, |
||||
int offset_day, long offset_sec) { |
||||
struct tm data; |
||||
if (!OPENSSL_posix_to_tm(posix_time, &data)) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (offset_day || offset_sec) { |
||||
if (!OPENSSL_gmtime_adj(&data, offset_day, offset_sec)) { |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
if (data.tm_year < 50 || data.tm_year >= 150) { |
||||
return NULL; |
||||
} |
||||
|
||||
char buf[14]; |
||||
int ret = snprintf(buf, sizeof(buf), "%02d%02d%02d%02d%02d%02dZ", |
||||
data.tm_year % 100, data.tm_mon + 1, data.tm_mday, |
||||
data.tm_hour, data.tm_min, data.tm_sec); |
||||
// |snprintf| must write exactly 15 bytes (plus the NUL) to the buffer.
|
||||
BSSL_CHECK(ret == static_cast<int>(sizeof(buf) - 1)); |
||||
|
||||
int free_s = 0; |
||||
if (s == NULL) { |
||||
free_s = 1; |
||||
s = ASN1_UTCTIME_new(); |
||||
if (s == NULL) { |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
if (!ASN1_STRING_set(s, buf, strlen(buf))) { |
||||
if (free_s) { |
||||
ASN1_UTCTIME_free(s); |
||||
} |
||||
return NULL; |
||||
} |
||||
s->type = V_ASN1_UTCTIME; |
||||
return s; |
||||
} |
@ -0,0 +1,234 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <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). |
||||
*/ |
||||
|
||||
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; |
||||
|
||||
/* 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. |
||||
*/ |
||||
|
||||
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; |
||||
} |
@ -0,0 +1,442 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1_mac.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
/* Cross-module errors from crypto/x509/i2d_pr.c. */ |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE) |
||||
|
||||
/* Cross-module errors from crypto/x509/algorithm.c. */ |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE) |
||||
/*
|
||||
* Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove |
||||
* these once asn1_gen.c is gone. |
||||
*/ |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE) |
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, |
||||
long max); |
||||
static void asn1_put_length(unsigned char **pp, int length); |
||||
|
||||
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; |
||||
|
||||
if (!max) |
||||
goto err; |
||||
ret = (*p & V_ASN1_CONSTRUCTED); |
||||
xclass = (*p & V_ASN1_PRIVATE); |
||||
i = *p & V_ASN1_PRIMITIVE_TAG; |
||||
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ |
||||
p++; |
||||
if (--max == 0) |
||||
goto err; |
||||
l = 0; |
||||
while (*p & 0x80) { |
||||
l <<= 7L; |
||||
l |= *(p++) & 0x7f; |
||||
if (--max == 0) |
||||
goto err; |
||||
if (l > (INT_MAX >> 7L)) |
||||
goto err; |
||||
} |
||||
l <<= 7L; |
||||
l |= *(p++) & 0x7f; |
||||
tag = (int)l; |
||||
if (--max == 0) |
||||
goto err; |
||||
} else { |
||||
tag = i; |
||||
p++; |
||||
if (--max == 0) |
||||
goto err; |
||||
} |
||||
|
||||
/* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ |
||||
if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL) |
||||
goto err; |
||||
|
||||
*ptag = tag; |
||||
*pclass = xclass; |
||||
if (!asn1_get_length(&p, &inf, plength, 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)); |
||||
|
||||
#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); |
||||
} |
||||
|
||||
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, |
||||
long max) |
||||
{ |
||||
const unsigned char *p = *pp; |
||||
unsigned long ret = 0; |
||||
unsigned long 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(ret) || max < (long)i) |
||||
return 0; |
||||
while (i-- > 0) { |
||||
ret <<= 8L; |
||||
ret |= *(p++); |
||||
} |
||||
} 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 |
||||
*/ |
||||
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, |
||||
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; |
||||
} |
||||
|
||||
int ASN1_put_eoc(unsigned char **pp) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag) |
||||
{ |
||||
int ret = 1; |
||||
if (length < 0) |
||||
return -1; |
||||
if (tag >= 31) { |
||||
while (tag > 0) { |
||||
tag >>= 7; |
||||
ret++; |
||||
} |
||||
} |
||||
if (constructed == 2) { |
||||
ret += 3; |
||||
} else { |
||||
ret++; |
||||
if (length > 127) { |
||||
int tmplen = length; |
||||
while (tmplen > 0) { |
||||
tmplen >>= 8; |
||||
ret++; |
||||
} |
||||
} |
||||
} |
||||
if (ret >= INT_MAX - length) |
||||
return -1; |
||||
return ret + length; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) |
||||
{ |
||||
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 (str->data == NULL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
||||
str->data = c; |
||||
return (0); |
||||
} |
||||
} |
||||
str->length = len; |
||||
if (data != NULL) { |
||||
OPENSSL_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; |
||||
} |
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void) |
||||
{ |
||||
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); |
||||
} |
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type) |
||||
{ |
||||
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); |
||||
} |
||||
|
||||
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); |
||||
} |
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) |
||||
{ |
||||
int i; |
||||
|
||||
i = (a->length - b->length); |
||||
if (i == 0) { |
||||
i = OPENSSL_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); |
||||
} |
||||
|
||||
void ASN1_STRING_length_set(ASN1_STRING *x, int len) |
||||
{ |
||||
M_ASN1_STRING_length_set(x, len); |
||||
return; |
||||
} |
||||
|
||||
int ASN1_STRING_type(ASN1_STRING *x) |
||||
{ |
||||
return M_ASN1_STRING_type(x); |
||||
} |
||||
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *x) |
||||
{ |
||||
return M_ASN1_STRING_data(x); |
||||
} |
||||
|
||||
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) |
||||
{ |
||||
return x->data; |
||||
} |
@ -1,350 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
// Cross-module errors from crypto/x509/i2d_pr.c.
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE) |
||||
|
||||
// Cross-module errors from crypto/x509/algorithm.c.
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE) |
||||
// Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
|
||||
// these once asn1_gen.c is gone.
|
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG) |
||||
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE) |
||||
|
||||
// Limit |ASN1_STRING|s to 64 MiB of data. Most of this module, as well as
|
||||
// downstream code, does not correctly handle overflow. We cap string fields
|
||||
// more tightly than strictly necessary to fit in |int|. This is not expected to
|
||||
// impact real world uses of this field.
|
||||
//
|
||||
// In particular, this limit is small enough that the bit count of a BIT STRING
|
||||
// comfortably fits in an |int|, with room for arithmetic.
|
||||
#define ASN1_STRING_MAX (64 * 1024 * 1024) |
||||
|
||||
static void asn1_put_length(unsigned char **pp, int length); |
||||
|
||||
int ASN1_get_object(const unsigned char **inp, long *out_len, int *out_tag, |
||||
int *out_class, long in_len) { |
||||
if (in_len < 0) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); |
||||
return 0x80; |
||||
} |
||||
|
||||
CBS_ASN1_TAG tag; |
||||
CBS cbs, body; |
||||
CBS_init(&cbs, *inp, (size_t)in_len); |
||||
if (!CBS_get_any_asn1(&cbs, &body, &tag) || |
||||
// Bound the length to comfortably fit in an int. Lengths in this
|
||||
// module often switch between int and long without overflow checks.
|
||||
CBS_len(&body) > INT_MAX / 2) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); |
||||
return 0x80; |
||||
} |
||||
|
||||
// Convert between tag representations.
|
||||
int tag_class = (tag & CBS_ASN1_CLASS_MASK) >> CBS_ASN1_TAG_SHIFT; |
||||
int constructed = (tag & CBS_ASN1_CONSTRUCTED) >> CBS_ASN1_TAG_SHIFT; |
||||
int tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK; |
||||
|
||||
// To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags.
|
||||
if (tag_class == V_ASN1_UNIVERSAL && tag_number > V_ASN1_MAX_UNIVERSAL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); |
||||
return 0x80; |
||||
} |
||||
|
||||
*inp = CBS_data(&body); |
||||
*out_len = CBS_len(&body); |
||||
*out_tag = tag_number; |
||||
*out_class = tag_class; |
||||
return 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; |
||||
|
||||
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) { |
||||
// This function is no longer used in the library, but some external code
|
||||
// uses it.
|
||||
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; |
||||
} |
||||
|
||||
int ASN1_object_size(int constructed, int length, int tag) { |
||||
int ret = 1; |
||||
if (length < 0) { |
||||
return -1; |
||||
} |
||||
if (tag >= 31) { |
||||
while (tag > 0) { |
||||
tag >>= 7; |
||||
ret++; |
||||
} |
||||
} |
||||
if (constructed == 2) { |
||||
ret += 3; |
||||
} else { |
||||
ret++; |
||||
if (length > 127) { |
||||
int tmplen = length; |
||||
while (tmplen > 0) { |
||||
tmplen >>= 8; |
||||
ret++; |
||||
} |
||||
} |
||||
} |
||||
if (ret >= INT_MAX - length) { |
||||
return -1; |
||||
} |
||||
return ret + length; |
||||
} |
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) { |
||||
if (str == NULL) { |
||||
return 0; |
||||
} |
||||
if (!ASN1_STRING_set(dst, str->data, str->length)) { |
||||
return 0; |
||||
} |
||||
dst->type = str->type; |
||||
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; |
||||
} |
||||
|
||||
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, ossl_ssize_t len_s) { |
||||
const char *data = reinterpret_cast<const char *>(_data); |
||||
size_t len; |
||||
if (len_s < 0) { |
||||
if (data == NULL) { |
||||
return 0; |
||||
} |
||||
len = strlen(data); |
||||
} else { |
||||
len = (size_t)len_s; |
||||
} |
||||
|
||||
static_assert(ASN1_STRING_MAX < INT_MAX, "len will not overflow int"); |
||||
if (len > ASN1_STRING_MAX) { |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); |
||||
return 0; |
||||
} |
||||
|
||||
if (str->length <= (int)len || str->data == NULL) { |
||||
unsigned char *c = str->data; |
||||
if (c == NULL) { |
||||
str->data = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len + 1)); |
||||
} else { |
||||
str->data = reinterpret_cast<uint8_t *>(OPENSSL_realloc(c, len + 1)); |
||||
} |
||||
|
||||
if (str->data == NULL) { |
||||
str->data = c; |
||||
return 0; |
||||
} |
||||
} |
||||
str->length = (int)len; |
||||
if (data != NULL) { |
||||
OPENSSL_memcpy(str->data, data, len); |
||||
// Historically, OpenSSL would NUL-terminate most (but not all)
|
||||
// |ASN1_STRING|s, in case anyone accidentally passed |str->data| into a
|
||||
// function expecting a C string. We retain this behavior for compatibility,
|
||||
// but code must not rely on this. See CVE-2021-3712.
|
||||
str->data[len] = '\0'; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) { |
||||
OPENSSL_free(str->data); |
||||
str->data = reinterpret_cast<uint8_t *>(data); |
||||
str->length = len; |
||||
} |
||||
|
||||
ASN1_STRING *ASN1_STRING_new(void) { |
||||
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); |
||||
} |
||||
|
||||
ASN1_STRING *ASN1_STRING_type_new(int type) { |
||||
ASN1_STRING *ret; |
||||
|
||||
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); |
||||
if (ret == NULL) { |
||||
return NULL; |
||||
} |
||||
ret->length = 0; |
||||
ret->type = type; |
||||
ret->data = NULL; |
||||
ret->flags = 0; |
||||
return ret; |
||||
} |
||||
|
||||
void ASN1_STRING_free(ASN1_STRING *str) { |
||||
if (str == NULL) { |
||||
return; |
||||
} |
||||
OPENSSL_free(str->data); |
||||
OPENSSL_free(str); |
||||
} |
||||
|
||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) { |
||||
// Capture padding bits and implicit truncation in BIT STRINGs.
|
||||
int a_length = a->length, b_length = b->length; |
||||
uint8_t a_padding = 0, b_padding = 0; |
||||
if (a->type == V_ASN1_BIT_STRING) { |
||||
a_length = asn1_bit_string_length(a, &a_padding); |
||||
} |
||||
if (b->type == V_ASN1_BIT_STRING) { |
||||
b_length = asn1_bit_string_length(b, &b_padding); |
||||
} |
||||
|
||||
if (a_length < b_length) { |
||||
return -1; |
||||
} |
||||
if (a_length > b_length) { |
||||
return 1; |
||||
} |
||||
// In a BIT STRING, the number of bits is 8 * length - padding. Invert this
|
||||
// comparison so we compare by lengths.
|
||||
if (a_padding > b_padding) { |
||||
return -1; |
||||
} |
||||
if (a_padding < b_padding) { |
||||
return 1; |
||||
} |
||||
|
||||
int ret = OPENSSL_memcmp(a->data, b->data, a_length); |
||||
if (ret != 0) { |
||||
return ret; |
||||
} |
||||
|
||||
// Comparing the type first is more natural, but this matches OpenSSL.
|
||||
if (a->type < b->type) { |
||||
return -1; |
||||
} |
||||
if (a->type > b->type) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int ASN1_STRING_length(const ASN1_STRING *str) { return str->length; } |
||||
|
||||
int ASN1_STRING_type(const ASN1_STRING *str) { return str->type; } |
||||
|
||||
unsigned char *ASN1_STRING_data(ASN1_STRING *str) { return str->data; } |
||||
|
||||
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *str) { |
||||
return str->data; |
||||
} |
@ -0,0 +1,98 @@ |
||||
/* asn1t.h */ |
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project |
||||
* 2006. |
||||
*/ |
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in |
||||
* the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* |
||||
* 3. All advertising materials mentioning features or use of this |
||||
* software must display the following acknowledgment: |
||||
* "This product includes software developed by the OpenSSL Project |
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
* |
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
||||
* endorse or promote products derived from this software without |
||||
* prior written permission. For written permission, please contact |
||||
* licensing@OpenSSL.org. |
||||
* |
||||
* 5. Products derived from this software may not be called "OpenSSL" |
||||
* nor may "OpenSSL" appear in their names without prior written |
||||
* permission of the OpenSSL Project. |
||||
* |
||||
* 6. Redistributions of any form whatsoever must retain the following |
||||
* acknowledgment: |
||||
* "This product includes software developed by the OpenSSL Project |
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
||||
* OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* ==================================================================== |
||||
* |
||||
* This product includes cryptographic software written by Eric Young |
||||
* (eay@cryptsoft.com). This product includes software written by Tim |
||||
* Hudson (tjh@cryptsoft.com). |
||||
* |
||||
*/ |
||||
|
||||
#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H |
||||
#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H |
||||
|
||||
#include <time.h> |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#if defined(__cplusplus) |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
/* Wrapper functions for time functions. */ |
||||
|
||||
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */ |
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result); |
||||
|
||||
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
|
||||
* seconds. */ |
||||
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); |
||||
|
||||
/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
|
||||
* outputs the difference as a number of days and seconds in |*out_days| and |
||||
* |*out_secs|. */ |
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from, |
||||
const struct tm *to); |
||||
|
||||
|
||||
/* Internal ASN1 structures and functions: not for application use */ |
||||
|
||||
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); |
||||
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); |
||||
|
||||
|
||||
#if defined(__cplusplus) |
||||
} /* extern C */ |
||||
#endif |
||||
|
||||
#endif /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */ |
@ -0,0 +1,80 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
|
||||
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 */ |
||||
}; |
||||
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) |
||||
tag &= ~0x100; |
||||
|
||||
if (tag < 0 || tag > 30) |
||||
return "(unknown)"; |
||||
return tag2str[tag]; |
||||
} |
@ -1,56 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
|
||||
const char *ASN1_tag2str(int tag) { |
||||
static const char *const tag2str[] = { |
||||
"EOC", |
||||
"BOOLEAN", |
||||
"INTEGER", |
||||
"BIT STRING", |
||||
"OCTET STRING", |
||||
"NULL", |
||||
"OBJECT", |
||||
"OBJECT DESCRIPTOR", |
||||
"EXTERNAL", |
||||
"REAL", |
||||
"ENUMERATED", |
||||
"<ASN1 11>", |
||||
"UTF8STRING", |
||||
"<ASN1 13>", |
||||
"<ASN1 14>", |
||||
"<ASN1 15>", |
||||
"SEQUENCE", |
||||
"SET", |
||||
"NUMERICSTRING", |
||||
"PRINTABLESTRING", |
||||
"T61STRING", |
||||
"VIDEOTEXSTRING", |
||||
"IA5STRING", |
||||
"UTCTIME", |
||||
"GENERALIZEDTIME", |
||||
"GRAPHICSTRING", |
||||
"VISIBLESTRING", |
||||
"GENERALSTRING", |
||||
"UNIVERSALSTRING", |
||||
"<ASN1 29>", |
||||
"BMPSTRING", |
||||
}; |
||||
|
||||
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) { |
||||
tag &= ~V_ASN1_NEG; |
||||
} |
||||
|
||||
if (tag < 0 || tag > 30) { |
||||
return "(unknown)"; |
||||
} |
||||
return tag2str[tag]; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,105 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
/* 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; |
||||
|
||||
p = oct->data; |
||||
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it))) |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
||||
return ret; |
||||
} |
@ -1,51 +0,0 @@ |
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
|
||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **out) { |
||||
uint8_t *new_data = NULL; |
||||
int len = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE *>(obj), &new_data, it); |
||||
if (len <= 0) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR); |
||||
return NULL; |
||||
} |
||||
|
||||
ASN1_STRING *ret = NULL; |
||||
if (out == NULL || *out == NULL) { |
||||
ret = ASN1_STRING_new(); |
||||
if (ret == NULL) { |
||||
OPENSSL_free(new_data); |
||||
return NULL; |
||||
} |
||||
} else { |
||||
ret = *out; |
||||
} |
||||
|
||||
ASN1_STRING_set0(ret, new_data, len); |
||||
if (out != NULL) { |
||||
*out = ret; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) { |
||||
const unsigned char *p = oct->data; |
||||
void *ret = ASN1_item_d2i(NULL, &p, oct->length, it); |
||||
if (ret == NULL || p != oct->data + oct->length) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
||||
ASN1_item_free(reinterpret_cast<ASN1_VALUE *>(ret), it); |
||||
return NULL; |
||||
} |
||||
return ret; |
||||
} |
@ -0,0 +1,135 @@ |
||||
#!/usr/local/bin/perl -w |
||||
|
||||
# Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project |
||||
# 2000. |
||||
# |
||||
# ==================================================================== |
||||
# Copyright (c) 2000 The OpenSSL Project. All rights reserved. |
||||
# |
||||
# Redistribution and use in source and binary forms, with or without |
||||
# modification, are permitted provided that the following conditions |
||||
# are met: |
||||
# |
||||
# 1. Redistributions of source code must retain the above copyright |
||||
# notice, this list of conditions and the following disclaimer. |
||||
# |
||||
# 2. Redistributions in binary form must reproduce the above copyright |
||||
# notice, this list of conditions and the following disclaimer in |
||||
# the documentation and/or other materials provided with the |
||||
# distribution. |
||||
# |
||||
# 3. All advertising materials mentioning features or use of this |
||||
# software must display the following acknowledgment: |
||||
# "This product includes software developed by the OpenSSL Project |
||||
# for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
||||
# |
||||
# 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
||||
# endorse or promote products derived from this software without |
||||
# prior written permission. For written permission, please contact |
||||
# licensing@OpenSSL.org. |
||||
# |
||||
# 5. Products derived from this software may not be called "OpenSSL" |
||||
# nor may "OpenSSL" appear in their names without prior written |
||||
# permission of the OpenSSL Project. |
||||
# |
||||
# 6. Redistributions of any form whatsoever must retain the following |
||||
# acknowledgment: |
||||
# "This product includes software developed by the OpenSSL Project |
||||
# for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
||||
# |
||||
# THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
||||
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
||||
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
||||
# OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
# ==================================================================== |
||||
# |
||||
# This product includes cryptographic software written by Eric Young |
||||
# (eay@cryptsoft.com). This product includes software written by Tim |
||||
# Hudson (tjh@cryptsoft.com). |
||||
|
||||
use strict; |
||||
|
||||
my ($i, @arr); |
||||
|
||||
# Set up an array with the type of ASCII characters |
||||
# Each set bit represents a character property. |
||||
|
||||
# RFC2253 character properties |
||||
my $RFC2253_ESC = 1; # Character escaped with \ |
||||
my $ESC_CTRL = 2; # Escaped control character |
||||
# These are used with RFC1779 quoting using " |
||||
my $NOESC_QUOTE = 8; # Not escaped if quoted |
||||
my $PSTRING_CHAR = 0x10; # Valid PrintableString character |
||||
my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character |
||||
my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character |
||||
|
||||
for($i = 0; $i < 128; $i++) { |
||||
# Set the RFC2253 escape characters (control) |
||||
$arr[$i] = 0; |
||||
if(($i < 32) || ($i > 126)) { |
||||
$arr[$i] |= $ESC_CTRL; |
||||
} |
||||
|
||||
# Some PrintableString characters |
||||
if( ( ( $i >= ord("a")) && ( $i <= ord("z")) ) |
||||
|| ( ( $i >= ord("A")) && ( $i <= ord("Z")) ) |
||||
|| ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) { |
||||
$arr[$i] |= $PSTRING_CHAR; |
||||
} |
||||
} |
||||
|
||||
# Now setup the rest |
||||
|
||||
# Remaining RFC2253 escaped characters |
||||
|
||||
$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC; |
||||
$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC; |
||||
|
||||
$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC; |
||||
$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC; |
||||
$arr[ord("\"")] |= $RFC2253_ESC; |
||||
$arr[ord("\\")] |= $RFC2253_ESC; |
||||
$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC; |
||||
$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC; |
||||
$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC; |
||||
|
||||
# Remaining PrintableString characters |
||||
|
||||
$arr[ord(" ")] |= $PSTRING_CHAR; |
||||
$arr[ord("'")] |= $PSTRING_CHAR; |
||||
$arr[ord("(")] |= $PSTRING_CHAR; |
||||
$arr[ord(")")] |= $PSTRING_CHAR; |
||||
$arr[ord("+")] |= $PSTRING_CHAR; |
||||
$arr[ord(",")] |= $PSTRING_CHAR; |
||||
$arr[ord("-")] |= $PSTRING_CHAR; |
||||
$arr[ord(".")] |= $PSTRING_CHAR; |
||||
$arr[ord("/")] |= $PSTRING_CHAR; |
||||
$arr[ord(":")] |= $PSTRING_CHAR; |
||||
$arr[ord("=")] |= $PSTRING_CHAR; |
||||
$arr[ord("?")] |= $PSTRING_CHAR; |
||||
|
||||
# Now generate the C code |
||||
|
||||
print <<EOF; |
||||
/* Auto generated with chartype.pl script. |
||||
* Mask of various character properties |
||||
*/ |
||||
|
||||
static const unsigned char char_type[] = { |
||||
EOF |
||||
|
||||
for($i = 0; $i < 128; $i++) { |
||||
print("\n") if($i && (($i % 16) == 0)); |
||||
printf("%2d", $arr[$i]); |
||||
print(",") if ($i != 127); |
||||
} |
||||
print("\n};\n\n"); |
||||
|
@ -0,0 +1,93 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
|
||||
/* 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]; |
||||
|
||||
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); |
||||
} |
@ -0,0 +1,97 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a) |
||||
{ |
||||
int i, n = 0; |
||||
static const char *h = "0123456789ABCDEF"; |
||||
char buf[2]; |
||||
|
||||
if (a == NULL) |
||||
return (0); |
||||
|
||||
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); |
||||
} |
@ -1,58 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
|
||||
int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) { |
||||
int i, n = 0; |
||||
static const char *h = "0123456789ABCDEF"; |
||||
char buf[2]; |
||||
|
||||
if (a == NULL) { |
||||
return 0; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) { |
||||
return i2a_ASN1_INTEGER(bp, a); |
||||
} |
@ -0,0 +1,91 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type) |
||||
{ |
||||
int i, n = 0; |
||||
static const char *h = "0123456789ABCDEF"; |
||||
char buf[2]; |
||||
|
||||
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); |
||||
} |
@ -1,47 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/bio.h> |
||||
|
||||
int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) { |
||||
int i, n = 0; |
||||
static const char *h = "0123456789ABCDEF"; |
||||
char buf[2]; |
||||
|
||||
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; |
||||
} |
@ -1,217 +0,0 @@ |
||||
/*
|
||||
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#ifndef OPENSSL_HEADER_ASN1_INTERNAL_H |
||||
#define OPENSSL_HEADER_ASN1_INTERNAL_H |
||||
|
||||
#include <time.h> |
||||
|
||||
#include <openssl/asn1.h> |
||||
#include <openssl/asn1t.h> |
||||
|
||||
#if defined(__cplusplus) |
||||
extern "C" { |
||||
#endif |
||||
|
||||
|
||||
// Wrapper functions for time functions.
|
||||
|
||||
// OPENSSL_gmtime converts a time_t value in |time| which must be in the range
|
||||
// of year 0000 to 9999 to a broken out time value in |tm|. On success |tm| is
|
||||
// returned. On failure NULL is returned.
|
||||
OPENSSL_EXPORT struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result); |
||||
|
||||
// OPENSSL_gmtime_adj returns one on success, and updates |tm| by adding
|
||||
// |offset_day| days and |offset_sec| seconds. It returns zero on failure. |tm|
|
||||
// must be in the range of year 0000 to 9999 both before and after the update or
|
||||
// a failure will be returned.
|
||||
OPENSSL_EXPORT int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, |
||||
int64_t offset_sec); |
||||
|
||||
// OPENSSL_gmtime_diff calculates the difference between |from| and |to|. It
|
||||
// returns one, and outputs the difference as a number of days and seconds in
|
||||
// |*out_days| and |*out_secs| on success. It returns zero on failure. Both
|
||||
// |from| and |to| must be in the range of year 0000 to 9999 or a failure will
|
||||
// be returned.
|
||||
OPENSSL_EXPORT int OPENSSL_gmtime_diff(int *out_days, int *out_secs, |
||||
const struct tm *from, |
||||
const struct tm *to); |
||||
|
||||
// Internal ASN1 structures and functions: not for application use
|
||||
|
||||
// These are used internally in the ASN1_OBJECT to keep track of
|
||||
// whether the names and data need to be free()ed
|
||||
#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 // internal use
|
||||
#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 // internal use
|
||||
#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 // internal use
|
||||
|
||||
// An asn1_object_st (aka |ASN1_OBJECT|) represents an ASN.1 OBJECT IDENTIFIER.
|
||||
// Note: Mutating an |ASN1_OBJECT| is only permitted when initializing it. The
|
||||
// library maintains a table of static |ASN1_OBJECT|s, which may be referenced
|
||||
// by non-const |ASN1_OBJECT| pointers. Code which receives an |ASN1_OBJECT|
|
||||
// pointer externally must assume it is immutable, even if the pointer is not
|
||||
// const.
|
||||
struct asn1_object_st { |
||||
const char *sn, *ln; |
||||
int nid; |
||||
int length; |
||||
const unsigned char *data; // data remains const after init
|
||||
int flags; // Should we free this one
|
||||
}; |
||||
|
||||
ASN1_OBJECT *ASN1_OBJECT_new(void); |
||||
|
||||
// ASN1_ENCODING is used to save the received encoding of an ASN.1 type. This
|
||||
// avoids problems with invalid encodings that break signatures.
|
||||
typedef struct ASN1_ENCODING_st { |
||||
// enc is the saved DER encoding. Its ownership is determined by |buf|.
|
||||
uint8_t *enc; |
||||
// len is the length of |enc|. If zero, there is no saved encoding.
|
||||
size_t len; |
||||
// buf, if non-NULL, is the |CRYPTO_BUFFER| that |enc| points into. If NULL,
|
||||
// |enc| must be released with |OPENSSL_free|.
|
||||
CRYPTO_BUFFER *buf; |
||||
} ASN1_ENCODING; |
||||
|
||||
OPENSSL_EXPORT int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d, |
||||
int allow_timezone_offset); |
||||
OPENSSL_EXPORT int asn1_generalizedtime_to_tm(struct tm *tm, |
||||
const ASN1_GENERALIZEDTIME *d); |
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
||||
|
||||
// ASN1_item_ex_d2i parses |len| bytes from |*in| as a structure of type |it|
|
||||
// and writes the result to |*pval|. If |tag| is non-negative, |it| is
|
||||
// implicitly tagged with the tag specified by |tag| and |aclass|. If |opt| is
|
||||
// non-zero, the value is optional. If |buf| is non-NULL, |*in| must point into
|
||||
// |buf|.
|
||||
//
|
||||
// This function returns one and advances |*in| if an object was successfully
|
||||
// parsed, -1 if an optional value was successfully skipped, and zero on error.
|
||||
int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
||||
const ASN1_ITEM *it, int tag, int aclass, char opt, |
||||
CRYPTO_BUFFER *buf); |
||||
|
||||
// ASN1_item_ex_i2d encodes |*pval| as a value of type |it| to |out| under the
|
||||
// i2d output convention. It returns a non-zero length on success and -1 on
|
||||
// error. If |tag| is -1. the tag and class come from |it|. Otherwise, the tag
|
||||
// number is |tag| and the class is |aclass|. This is used for implicit tagging.
|
||||
// This function treats a missing value as an error, not an optional field.
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass); |
||||
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
|
||||
// asn1_get_choice_selector returns the CHOICE selector value for |*pval|, which
|
||||
// must of type |it|.
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); |
||||
|
||||
// asn1_get_field_ptr returns a pointer to the field in |*pval| corresponding to
|
||||
// |tt|.
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
||||
|
||||
// asn1_do_adb returns the |ASN1_TEMPLATE| for the ANY DEFINED BY field |tt|,
|
||||
// based on the selector INTEGER or OID in |*pval|. If |tt| is not an ADB field,
|
||||
// it returns |tt|. If the selector does not match any value, it returns NULL.
|
||||
// If |nullerr| is non-zero, it will additionally push an error to the error
|
||||
// queue when there is no match.
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, |
||||
int nullerr); |
||||
|
||||
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
|
||||
// asn1_enc_restore, if |*pval| has a saved encoding, writes it to |out| under
|
||||
// the i2d output convention, sets |*len| to the length, and returns one. If it
|
||||
// has no saved encoding, it returns zero.
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, |
||||
const ASN1_ITEM *it); |
||||
|
||||
// asn1_enc_save saves |inlen| bytes from |in| as |*pval|'s saved encoding. It
|
||||
// returns one on success and zero on error. If |buf| is non-NULL, |in| must
|
||||
// point into |buf|.
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t inlen, |
||||
const ASN1_ITEM *it, CRYPTO_BUFFER *buf); |
||||
|
||||
// asn1_encoding_clear clears the cached encoding in |enc|.
|
||||
void asn1_encoding_clear(ASN1_ENCODING *enc); |
||||
|
||||
// asn1_type_value_as_pointer returns |a|'s value in pointer form. This is
|
||||
// usually the value object but, for BOOLEAN values, is 0 or 0xff cast to
|
||||
// a pointer.
|
||||
const void *asn1_type_value_as_pointer(const ASN1_TYPE *a); |
||||
|
||||
// asn1_type_set0_string sets |a|'s value to the object represented by |str| and
|
||||
// takes ownership of |str|.
|
||||
void asn1_type_set0_string(ASN1_TYPE *a, ASN1_STRING *str); |
||||
|
||||
// asn1_type_cleanup releases memory associated with |a|'s value, without
|
||||
// freeing |a| itself.
|
||||
void asn1_type_cleanup(ASN1_TYPE *a); |
||||
|
||||
// asn1_is_printable returns one if |value| is a valid Unicode codepoint for an
|
||||
// ASN.1 PrintableString, and zero otherwise.
|
||||
int asn1_is_printable(uint32_t value); |
||||
|
||||
// asn1_bit_string_length returns the number of bytes in |str| and sets
|
||||
// |*out_padding_bits| to the number of padding bits.
|
||||
//
|
||||
// This function should be used instead of |ASN1_STRING_length| to correctly
|
||||
// handle the non-|ASN1_STRING_FLAG_BITS_LEFT| case.
|
||||
int asn1_bit_string_length(const ASN1_BIT_STRING *str, |
||||
uint8_t *out_padding_bits); |
||||
|
||||
typedef struct { |
||||
int nid; |
||||
long minsize; |
||||
long maxsize; |
||||
unsigned long mask; |
||||
unsigned long flags; |
||||
} ASN1_STRING_TABLE; |
||||
|
||||
// asn1_get_string_table_for_testing sets |*out_ptr| and |*out_len| to the table
|
||||
// of built-in |ASN1_STRING_TABLE| values. It is exported for testing.
|
||||
OPENSSL_EXPORT void asn1_get_string_table_for_testing( |
||||
const ASN1_STRING_TABLE **out_ptr, size_t *out_len); |
||||
|
||||
typedef ASN1_VALUE *ASN1_new_func(void); |
||||
typedef void ASN1_free_func(ASN1_VALUE *a); |
||||
typedef ASN1_VALUE *ASN1_d2i_func(ASN1_VALUE **a, const unsigned char **in, |
||||
long length); |
||||
typedef int ASN1_i2d_func(ASN1_VALUE *a, unsigned char **in); |
||||
|
||||
typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
||||
const ASN1_ITEM *it, int opt, ASN1_TLC *ctx); |
||||
|
||||
typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it); |
||||
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
|
||||
typedef struct ASN1_EXTERN_FUNCS_st { |
||||
ASN1_ex_new_func *asn1_ex_new; |
||||
ASN1_ex_free_func *asn1_ex_free; |
||||
ASN1_ex_d2i *asn1_ex_d2i; |
||||
ASN1_ex_i2d *asn1_ex_i2d; |
||||
} ASN1_EXTERN_FUNCS; |
||||
|
||||
|
||||
#if defined(__cplusplus) |
||||
} // extern C
|
||||
#endif |
||||
|
||||
#endif // OPENSSL_HEADER_ASN1_INTERNAL_H
|
@ -1,241 +0,0 @@ |
||||
/* Copyright 2022 The BoringSSL Authors
|
||||
* |
||||
* 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. */ |
||||
|
||||
// Time conversion to/from POSIX time_t and struct tm, with no support
|
||||
// for time zones other than UTC
|
||||
|
||||
#include <openssl/posix_time.h> |
||||
|
||||
#include <assert.h> |
||||
#include <inttypes.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include "internal.h" |
||||
|
||||
#define SECS_PER_HOUR (60 * 60) |
||||
#define SECS_PER_DAY (INT64_C(24) * SECS_PER_HOUR) |
||||
|
||||
|
||||
// Is a year/month/day combination valid, in the range from year 0000
|
||||
// to 9999?
|
||||
static int is_valid_date(int64_t year, int64_t month, int64_t day) { |
||||
if (day < 1 || month < 1 || year < 0 || year > 9999) { |
||||
return 0; |
||||
} |
||||
switch (month) { |
||||
case 1: |
||||
case 3: |
||||
case 5: |
||||
case 7: |
||||
case 8: |
||||
case 10: |
||||
case 12: |
||||
return day > 0 && day <= 31; |
||||
case 4: |
||||
case 6: |
||||
case 9: |
||||
case 11: |
||||
return day > 0 && day <= 30; |
||||
case 2: |
||||
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { |
||||
return day > 0 && day <= 29; |
||||
} else { |
||||
return day > 0 && day <= 28; |
||||
} |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
// Is a time valid? Leap seconds of 60 are not considered valid, as
|
||||
// the POSIX time in seconds does not include them.
|
||||
static int is_valid_time(int64_t hours, int64_t minutes, int64_t seconds) { |
||||
if (hours < 0 || minutes < 0 || seconds < 0 || hours > 23 || minutes > 59 || |
||||
seconds > 59) { |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
// 0000-01-01 00:00:00 UTC
|
||||
#define MIN_POSIX_TIME INT64_C(-62167219200) |
||||
// 9999-12-31 23:59:59 UTC
|
||||
#define MAX_POSIX_TIME INT64_C(253402300799) |
||||
|
||||
// Is an int64 time within our expected range?
|
||||
static int is_valid_posix_time(int64_t time) { |
||||
return MIN_POSIX_TIME <= time && time <= MAX_POSIX_TIME; |
||||
} |
||||
|
||||
// Inspired by algorithms presented in
|
||||
// https://howardhinnant.github.io/date_algorithms.html
|
||||
// (Public Domain)
|
||||
static int posix_time_from_utc(int64_t year, int64_t month, int64_t day, |
||||
int64_t hours, int64_t minutes, int64_t seconds, |
||||
int64_t *out_time) { |
||||
if (!is_valid_date(year, month, day) || |
||||
!is_valid_time(hours, minutes, seconds)) { |
||||
return 0; |
||||
} |
||||
if (month <= 2) { |
||||
year--; // Start years on Mar 1, so leap days always finish a year.
|
||||
} |
||||
// At this point year will be in the range -1 and 9999.
|
||||
assert(-1 <= year && year <= 9999); |
||||
int64_t era = (year >= 0 ? year : year - 399) / 400; |
||||
int64_t year_of_era = year - era * 400; |
||||
int64_t day_of_year = |
||||
(153 * (month > 2 ? month - 3 : month + 9) + 2) / 5 + day - 1; |
||||
int64_t day_of_era = |
||||
year_of_era * 365 + year_of_era / 4 - year_of_era / 100 + day_of_year; |
||||
int64_t posix_days = era * 146097 + day_of_era - 719468; |
||||
*out_time = posix_days * SECS_PER_DAY + hours * SECS_PER_HOUR + minutes * 60 + |
||||
seconds; |
||||
return 1; |
||||
} |
||||
|
||||
// Inspired by algorithms presented in
|
||||
// https://howardhinnant.github.io/date_algorithms.html
|
||||
// (Public Domain)
|
||||
static int utc_from_posix_time(int64_t time, int *out_year, int *out_month, |
||||
int *out_day, int *out_hours, int *out_minutes, |
||||
int *out_seconds) { |
||||
if (!is_valid_posix_time(time)) { |
||||
return 0; |
||||
} |
||||
int64_t days = time / SECS_PER_DAY; |
||||
int64_t leftover_seconds = time % SECS_PER_DAY; |
||||
if (leftover_seconds < 0) { |
||||
days--; |
||||
leftover_seconds += SECS_PER_DAY; |
||||
} |
||||
days += 719468; // Shift to starting epoch of Mar 1 0000.
|
||||
// At this point, days will be in the range -61 and 3652364.
|
||||
assert(-61 <= days && days <= 3652364); |
||||
int64_t era = (days > 0 ? days : days - 146096) / 146097; |
||||
int64_t day_of_era = days - era * 146097; |
||||
int64_t year_of_era = (day_of_era - day_of_era / 1460 + day_of_era / 36524 - |
||||
day_of_era / 146096) / |
||||
365; |
||||
*out_year = (int)(year_of_era + era * 400); // Year starting on Mar 1.
|
||||
int64_t day_of_year = |
||||
day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100); |
||||
int64_t month_of_year = (5 * day_of_year + 2) / 153; |
||||
*out_month = |
||||
(int)(month_of_year < 10 ? month_of_year + 3 : month_of_year - 9); |
||||
if (*out_month <= 2) { |
||||
(*out_year)++; // Adjust year back to Jan 1 start of year.
|
||||
} |
||||
*out_day = (int)(day_of_year - (153 * month_of_year + 2) / 5 + 1); |
||||
*out_hours = (int)(leftover_seconds / SECS_PER_HOUR); |
||||
leftover_seconds %= SECS_PER_HOUR; |
||||
*out_minutes = (int)(leftover_seconds / 60); |
||||
*out_seconds = (int)(leftover_seconds % 60); |
||||
return 1; |
||||
} |
||||
|
||||
int OPENSSL_tm_to_posix(const struct tm *tm, int64_t *out) { |
||||
return posix_time_from_utc(tm->tm_year + INT64_C(1900), |
||||
tm->tm_mon + INT64_C(1), tm->tm_mday, tm->tm_hour, |
||||
tm->tm_min, tm->tm_sec, out); |
||||
} |
||||
|
||||
int OPENSSL_posix_to_tm(int64_t time, struct tm *out_tm) { |
||||
struct tm tmp_tm = {}; |
||||
if (!utc_from_posix_time(time, &tmp_tm.tm_year, &tmp_tm.tm_mon, |
||||
&tmp_tm.tm_mday, &tmp_tm.tm_hour, &tmp_tm.tm_min, |
||||
&tmp_tm.tm_sec)) { |
||||
return 0; |
||||
} |
||||
tmp_tm.tm_year -= 1900; |
||||
tmp_tm.tm_mon -= 1; |
||||
*out_tm = tmp_tm; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int OPENSSL_timegm(const struct tm *tm, time_t *out) { |
||||
static_assert( |
||||
sizeof(time_t) == sizeof(int32_t) || sizeof(time_t) == sizeof(int64_t), |
||||
"time_t is broken"); |
||||
int64_t posix_time; |
||||
if (!OPENSSL_tm_to_posix(tm, &posix_time)) { |
||||
return 0; |
||||
} |
||||
if (sizeof(time_t) == sizeof(int32_t) && |
||||
(posix_time > INT32_MAX || posix_time < INT32_MIN)) { |
||||
return 0; |
||||
} |
||||
*out = (time_t)posix_time; |
||||
return 1; |
||||
} |
||||
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *out_tm) { |
||||
static_assert( |
||||
sizeof(time_t) == sizeof(int32_t) || sizeof(time_t) == sizeof(int64_t), |
||||
"time_t is broken"); |
||||
int64_t posix_time = *time; |
||||
if (!OPENSSL_posix_to_tm(posix_time, out_tm)) { |
||||
return NULL; |
||||
} |
||||
return out_tm; |
||||
} |
||||
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, int64_t offset_sec) { |
||||
int64_t posix_time; |
||||
if (!OPENSSL_tm_to_posix(tm, &posix_time)) { |
||||
return 0; |
||||
} |
||||
static_assert(INT_MAX <= INT64_MAX / SECS_PER_DAY, |
||||
"day offset in seconds cannot overflow"); |
||||
static_assert(MAX_POSIX_TIME <= INT64_MAX - INT_MAX * SECS_PER_DAY, |
||||
"addition cannot overflow"); |
||||
static_assert(MIN_POSIX_TIME >= INT64_MIN - INT_MIN * SECS_PER_DAY, |
||||
"addition cannot underflow"); |
||||
posix_time += offset_day * SECS_PER_DAY; |
||||
if (posix_time > 0 && offset_sec > INT64_MAX - posix_time) { |
||||
return 0; |
||||
} |
||||
if (posix_time < 0 && offset_sec < INT64_MIN - posix_time) { |
||||
return 0; |
||||
} |
||||
posix_time += offset_sec; |
||||
|
||||
if (!OPENSSL_posix_to_tm(posix_time, tm)) { |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from, |
||||
const struct tm *to) { |
||||
int64_t time_to, time_from; |
||||
if (!OPENSSL_tm_to_posix(to, &time_to) || |
||||
!OPENSSL_tm_to_posix(from, &time_from)) { |
||||
return 0; |
||||
} |
||||
// Times are in range, so these calculations can not overflow.
|
||||
static_assert(SECS_PER_DAY <= INT_MAX, "seconds per day does not fit in int"); |
||||
static_assert((MAX_POSIX_TIME - MIN_POSIX_TIME) / SECS_PER_DAY <= INT_MAX, |
||||
"range of valid POSIX times, in days, does not fit in int"); |
||||
int64_t timediff = time_to - time_from; |
||||
int64_t daydiff = timediff / SECS_PER_DAY; |
||||
timediff %= SECS_PER_DAY; |
||||
*out_secs = (int)timediff; |
||||
*out_days = (int)daydiff; |
||||
return 1; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,927 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/bytestring.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/pool.h> |
||||
|
||||
#include <assert.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include "../bytestring/internal.h" |
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
// Constructed types with a recursive definition (such as can be found in PKCS7)
|
||||
// could eventually exceed the stack given malicious input with excessive
|
||||
// recursion. Therefore we limit the stack depth. This is the maximum number of
|
||||
// recursive invocations of asn1_item_embed_d2i().
|
||||
#define ASN1_MAX_CONSTRUCTED_NEST 30 |
||||
|
||||
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, |
||||
char *cst, const unsigned char **in, long len, |
||||
int exptag, int expclass, char opt); |
||||
|
||||
static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
||||
long len, const ASN1_TEMPLATE *tt, char opt, |
||||
CRYPTO_BUFFER *buf, int depth); |
||||
static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, |
||||
long len, const ASN1_TEMPLATE *tt, char opt, |
||||
CRYPTO_BUFFER *buf, int depth); |
||||
static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, |
||||
int utype, const ASN1_ITEM *it); |
||||
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, |
||||
long len, const ASN1_ITEM *it, int tag, |
||||
int aclass, char opt); |
||||
static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
||||
long len, const ASN1_ITEM *it, int tag, int aclass, |
||||
char opt, CRYPTO_BUFFER *buf, int depth); |
||||
|
||||
// Table to convert tags to bit values, used for MSTRING type
|
||||
static const unsigned long tag2bit[31] = { |
||||
0, // (reserved)
|
||||
0, // BOOLEAN
|
||||
0, // INTEGER
|
||||
B_ASN1_BIT_STRING, |
||||
B_ASN1_OCTET_STRING, |
||||
0, // NULL
|
||||
0, // OBJECT IDENTIFIER
|
||||
B_ASN1_UNKNOWN, // ObjectDescriptor
|
||||
B_ASN1_UNKNOWN, // EXTERNAL
|
||||
B_ASN1_UNKNOWN, // REAL
|
||||
B_ASN1_UNKNOWN, // ENUMERATED
|
||||
B_ASN1_UNKNOWN, // EMBEDDED PDV
|
||||
B_ASN1_UTF8STRING, |
||||
B_ASN1_UNKNOWN, // RELATIVE-OID
|
||||
B_ASN1_UNKNOWN, // TIME
|
||||
B_ASN1_UNKNOWN, // (reserved)
|
||||
B_ASN1_SEQUENCE, |
||||
0, // SET
|
||||
B_ASN1_NUMERICSTRING, |
||||
B_ASN1_PRINTABLESTRING, |
||||
B_ASN1_T61STRING, |
||||
B_ASN1_VIDEOTEXSTRING, |
||||
B_ASN1_IA5STRING, |
||||
B_ASN1_UTCTIME, |
||||
B_ASN1_GENERALIZEDTIME, |
||||
B_ASN1_GRAPHICSTRING, |
||||
B_ASN1_ISO64STRING, |
||||
B_ASN1_GENERALSTRING, |
||||
B_ASN1_UNIVERSALSTRING, |
||||
B_ASN1_UNKNOWN, // CHARACTER STRING
|
||||
B_ASN1_BMPSTRING, |
||||
}; |
||||
|
||||
unsigned long ASN1_tag2bit(int tag) { |
||||
if (tag < 0 || tag > 30) { |
||||
return 0; |
||||
} |
||||
return tag2bit[tag]; |
||||
} |
||||
|
||||
static int is_supported_universal_type(int tag, int aclass) { |
||||
if (aclass != V_ASN1_UNIVERSAL) { |
||||
return 0; |
||||
} |
||||
return tag == V_ASN1_OBJECT || tag == V_ASN1_NULL || tag == V_ASN1_BOOLEAN || |
||||
tag == V_ASN1_BIT_STRING || tag == V_ASN1_INTEGER || |
||||
tag == V_ASN1_ENUMERATED || tag == V_ASN1_OCTET_STRING || |
||||
tag == V_ASN1_NUMERICSTRING || tag == V_ASN1_PRINTABLESTRING || |
||||
tag == V_ASN1_T61STRING || tag == V_ASN1_VIDEOTEXSTRING || |
||||
tag == V_ASN1_IA5STRING || tag == V_ASN1_UTCTIME || |
||||
tag == V_ASN1_GENERALIZEDTIME || tag == V_ASN1_GRAPHICSTRING || |
||||
tag == V_ASN1_VISIBLESTRING || tag == V_ASN1_GENERALSTRING || |
||||
tag == V_ASN1_UNIVERSALSTRING || tag == V_ASN1_BMPSTRING || |
||||
tag == V_ASN1_UTF8STRING || tag == V_ASN1_SET || |
||||
tag == V_ASN1_SEQUENCE; |
||||
} |
||||
|
||||
// Macro to initialize and invalidate the cache
|
||||
|
||||
// Decode an ASN1 item, this currently behaves just like a standard 'd2i'
|
||||
// function. 'in' points to a buffer to read the data from, in future we
|
||||
// will have more advanced versions that can input data a piece at a time and
|
||||
// this will simply be a special case.
|
||||
|
||||
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
||||
const ASN1_ITEM *it) { |
||||
ASN1_VALUE *ret = NULL; |
||||
if (asn1_item_ex_d2i(&ret, in, len, it, /*tag=*/-1, /*aclass=*/0, /*opt=*/0, |
||||
/*buf=*/NULL, /*depth=*/0) <= 0) { |
||||
// Clean up, in case the caller left a partial object.
|
||||
//
|
||||
// TODO(davidben): I don't think it can leave one, but the codepaths below
|
||||
// are a bit inconsistent. Revisit this when rewriting this function.
|
||||
ASN1_item_ex_free(&ret, it); |
||||
} |
||||
|
||||
// If the caller supplied an output pointer, free the old one and replace it
|
||||
// with |ret|. This differs from OpenSSL slightly in that we don't support
|
||||
// object reuse. We run this on both success and failure. On failure, even
|
||||
// with object reuse, OpenSSL destroys the previous object.
|
||||
if (pval != NULL) { |
||||
ASN1_item_ex_free(pval, it); |
||||
*pval = ret; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
// Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
|
||||
// tag mismatch return -1 to handle OPTIONAL
|
||||
//
|
||||
// TODO(davidben): Historically, all functions in this file had to account for
|
||||
// |*pval| containing an arbitrary existing value. This is no longer the case
|
||||
// because |ASN1_item_d2i| now always starts from NULL. As part of rewriting
|
||||
// this function, take the simplified assumptions into account. Though we must
|
||||
// still account for the internal calls to |ASN1_item_ex_new|.
|
||||
|
||||
static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
||||
long len, const ASN1_ITEM *it, int tag, int aclass, |
||||
char opt, CRYPTO_BUFFER *buf, int depth) { |
||||
const ASN1_TEMPLATE *tt, *errtt = NULL; |
||||
const unsigned char *p = NULL, *q; |
||||
unsigned char oclass; |
||||
char cst, isopt; |
||||
int i; |
||||
int otag; |
||||
int ret = 0; |
||||
ASN1_VALUE **pchptr; |
||||
if (!pval) { |
||||
return 0; |
||||
} |
||||
|
||||
if (buf != NULL) { |
||||
assert(CRYPTO_BUFFER_data(buf) <= *in && |
||||
*in + len <= CRYPTO_BUFFER_data(buf) + CRYPTO_BUFFER_len(buf)); |
||||
} |
||||
|
||||
// Bound |len| to comfortably fit in an int. Lengths in this module often
|
||||
// switch between int and long without overflow checks.
|
||||
if (len > INT_MAX / 2) { |
||||
len = INT_MAX / 2; |
||||
} |
||||
|
||||
if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_TOO_DEEP); |
||||
goto err; |
||||
} |
||||
|
||||
switch (it->itype) { |
||||
case ASN1_ITYPE_PRIMITIVE: |
||||
if (it->templates) { |
||||
// tagging or OPTIONAL is currently illegal on an item template
|
||||
// because the flags can't get passed down. In practice this
|
||||
// isn't a problem: we include the relevant flags from the item
|
||||
// template in the template itself.
|
||||
if ((tag != -1) || opt) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); |
||||
goto err; |
||||
} |
||||
return asn1_template_ex_d2i(pval, in, len, it->templates, opt, buf, |
||||
depth); |
||||
} |
||||
return asn1_d2i_ex_primitive(pval, in, len, it, tag, aclass, opt); |
||||
break; |
||||
|
||||
case ASN1_ITYPE_MSTRING: |
||||
// It never makes sense for multi-strings to have implicit tagging, so
|
||||
// if tag != -1, then this looks like an error in the template.
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
goto err; |
||||
} |
||||
|
||||
p = *in; |
||||
// Just read in tag and class
|
||||
ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, &p, len, -1, 0, 1); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} |
||||
|
||||
// Must be UNIVERSAL class
|
||||
if (oclass != V_ASN1_UNIVERSAL) { |
||||
// If OPTIONAL, assume this is OK
|
||||
if (opt) { |
||||
return -1; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL); |
||||
goto err; |
||||
} |
||||
// Check tag matches bit map
|
||||
if (!(ASN1_tag2bit(otag) & it->utype)) { |
||||
// If OPTIONAL, assume this is OK
|
||||
if (opt) { |
||||
return -1; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG); |
||||
goto err; |
||||
} |
||||
return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0); |
||||
|
||||
case ASN1_ITYPE_EXTERN: { |
||||
// We don't support implicit tagging with external types.
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
goto err; |
||||
} |
||||
const ASN1_EXTERN_FUNCS *ef = |
||||
reinterpret_cast<const ASN1_EXTERN_FUNCS *>(it->funcs); |
||||
return ef->asn1_ex_d2i(pval, in, len, it, opt, NULL); |
||||
} |
||||
|
||||
case ASN1_ITYPE_CHOICE: { |
||||
// It never makes sense for CHOICE types to have implicit tagging, so if
|
||||
// tag != -1, then this looks like an error in the template.
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
goto err; |
||||
} |
||||
|
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) { |
||||
goto auxerr; |
||||
} |
||||
|
||||
if (*pval) { |
||||
// Free up and zero CHOICE value if initialised
|
||||
i = asn1_get_choice_selector(pval, it); |
||||
if ((i >= 0) && (i < it->tcount)) { |
||||
tt = it->templates + i; |
||||
pchptr = asn1_get_field_ptr(pval, tt); |
||||
ASN1_template_free(pchptr, tt); |
||||
asn1_set_choice_selector(pval, -1, it); |
||||
} |
||||
} else if (!ASN1_item_ex_new(pval, it)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} |
||||
// CHOICE type, try each possibility in turn
|
||||
p = *in; |
||||
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
||||
pchptr = asn1_get_field_ptr(pval, tt); |
||||
// We mark field as OPTIONAL so its absence can be recognised.
|
||||
ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, buf, depth); |
||||
// If field not present, try the next one
|
||||
if (ret == -1) { |
||||
continue; |
||||
} |
||||
// If positive return, read OK, break loop
|
||||
if (ret > 0) { |
||||
break; |
||||
} |
||||
// Otherwise must be an ASN1 parsing error
|
||||
errtt = tt; |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} |
||||
|
||||
// Did we fall off the end without reading anything?
|
||||
if (i == it->tcount) { |
||||
// If OPTIONAL, this is OK
|
||||
if (opt) { |
||||
// Free and zero it
|
||||
ASN1_item_ex_free(pval, it); |
||||
return -1; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); |
||||
goto err; |
||||
} |
||||
|
||||
asn1_set_choice_selector(pval, i, it); |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) { |
||||
goto auxerr; |
||||
} |
||||
*in = p; |
||||
return 1; |
||||
} |
||||
|
||||
case ASN1_ITYPE_SEQUENCE: { |
||||
p = *in; |
||||
|
||||
// If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
|
||||
if (tag == -1) { |
||||
tag = V_ASN1_SEQUENCE; |
||||
aclass = V_ASN1_UNIVERSAL; |
||||
} |
||||
// Get SEQUENCE length and update len, p
|
||||
ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, len, tag, aclass, opt); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} else if (ret == -1) { |
||||
return -1; |
||||
} |
||||
if (!cst) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); |
||||
goto err; |
||||
} |
||||
|
||||
if (!*pval && !ASN1_item_ex_new(pval, it)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} |
||||
|
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) { |
||||
goto auxerr; |
||||
} |
||||
|
||||
// Free up and zero any ADB found
|
||||
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
ASN1_VALUE **pseqval; |
||||
seqtt = asn1_do_adb(pval, tt, 0); |
||||
if (seqtt == NULL) { |
||||
continue; |
||||
} |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
ASN1_template_free(pseqval, seqtt); |
||||
} |
||||
} |
||||
|
||||
// Get each field entry
|
||||
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
ASN1_VALUE **pseqval; |
||||
seqtt = asn1_do_adb(pval, tt, 1); |
||||
if (seqtt == NULL) { |
||||
goto err; |
||||
} |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
// Have we ran out of data?
|
||||
if (!len) { |
||||
break; |
||||
} |
||||
q = p; |
||||
// This determines the OPTIONAL flag value. The field cannot be
|
||||
// omitted if it is the last of a SEQUENCE and there is still
|
||||
// data to be read. This isn't strictly necessary but it
|
||||
// increases efficiency in some cases.
|
||||
if (i == (it->tcount - 1)) { |
||||
isopt = 0; |
||||
} else { |
||||
isopt = (seqtt->flags & ASN1_TFLG_OPTIONAL) != 0; |
||||
} |
||||
// attempt to read in field, allowing each to be OPTIONAL
|
||||
|
||||
ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, buf, depth); |
||||
if (!ret) { |
||||
errtt = seqtt; |
||||
goto err; |
||||
} else if (ret == -1) { |
||||
// OPTIONAL component absent. Free and zero the field.
|
||||
ASN1_template_free(pseqval, seqtt); |
||||
continue; |
||||
} |
||||
// Update length
|
||||
len -= p - q; |
||||
} |
||||
|
||||
// Check all data read
|
||||
if (len) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH); |
||||
goto err; |
||||
} |
||||
|
||||
// If we get here we've got no more data in the SEQUENCE, however we
|
||||
// may not have read all fields so check all remaining are OPTIONAL
|
||||
// and clear any that are.
|
||||
for (; i < it->tcount; tt++, i++) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
seqtt = asn1_do_adb(pval, tt, 1); |
||||
if (seqtt == NULL) { |
||||
goto err; |
||||
} |
||||
if (seqtt->flags & ASN1_TFLG_OPTIONAL) { |
||||
ASN1_VALUE **pseqval; |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
ASN1_template_free(pseqval, seqtt); |
||||
} else { |
||||
errtt = seqtt; |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING); |
||||
goto err; |
||||
} |
||||
} |
||||
// Save encoding
|
||||
if (!asn1_enc_save(pval, *in, p - *in, it, buf)) { |
||||
goto auxerr; |
||||
} |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) { |
||||
goto auxerr; |
||||
} |
||||
*in = p; |
||||
return 1; |
||||
} |
||||
|
||||
default: |
||||
return 0; |
||||
} |
||||
auxerr: |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); |
||||
err: |
||||
ASN1_item_ex_free(pval, it); |
||||
if (errtt) { |
||||
ERR_add_error_data(4, "Field=", errtt->field_name, ", Type=", it->sname); |
||||
} else { |
||||
ERR_add_error_data(2, "Type=", it->sname); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
||||
const ASN1_ITEM *it, int tag, int aclass, char opt, |
||||
CRYPTO_BUFFER *buf) { |
||||
return asn1_item_ex_d2i(pval, in, len, it, tag, aclass, opt, buf, |
||||
/*depth=*/0); |
||||
} |
||||
|
||||
// Templates are handled with two separate functions. One handles any
|
||||
// EXPLICIT tag and the other handles the rest.
|
||||
|
||||
static int asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, |
||||
long inlen, const ASN1_TEMPLATE *tt, char opt, |
||||
CRYPTO_BUFFER *buf, int depth) { |
||||
int aclass; |
||||
int ret; |
||||
long len; |
||||
const unsigned char *p, *q; |
||||
if (!val) { |
||||
return 0; |
||||
} |
||||
uint32_t flags = tt->flags; |
||||
aclass = flags & ASN1_TFLG_TAG_CLASS; |
||||
|
||||
p = *in; |
||||
|
||||
// Check if EXPLICIT tag expected
|
||||
if (flags & ASN1_TFLG_EXPTAG) { |
||||
char cst; |
||||
// Need to work out amount of data available to the inner content and
|
||||
// where it starts: so read in EXPLICIT header to get the info.
|
||||
ret = asn1_check_tlen(&len, NULL, NULL, &cst, &p, inlen, tt->tag, aclass, |
||||
opt); |
||||
q = p; |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
return 0; |
||||
} else if (ret == -1) { |
||||
return -1; |
||||
} |
||||
if (!cst) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); |
||||
return 0; |
||||
} |
||||
// We've found the field so it can't be OPTIONAL now
|
||||
ret = asn1_template_noexp_d2i(val, &p, len, tt, /*opt=*/0, buf, depth); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
return 0; |
||||
} |
||||
// We read the field in OK so update length
|
||||
len -= p - q; |
||||
// Check for trailing data.
|
||||
if (len) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH); |
||||
goto err; |
||||
} |
||||
} else { |
||||
return asn1_template_noexp_d2i(val, in, inlen, tt, opt, buf, depth); |
||||
} |
||||
|
||||
*in = p; |
||||
return 1; |
||||
|
||||
err: |
||||
ASN1_template_free(val, tt); |
||||
return 0; |
||||
} |
||||
|
||||
static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, |
||||
long len, const ASN1_TEMPLATE *tt, char opt, |
||||
CRYPTO_BUFFER *buf, int depth) { |
||||
int aclass; |
||||
int ret; |
||||
const unsigned char *p; |
||||
if (!val) { |
||||
return 0; |
||||
} |
||||
uint32_t flags = tt->flags; |
||||
aclass = flags & ASN1_TFLG_TAG_CLASS; |
||||
|
||||
p = *in; |
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) { |
||||
// SET OF, SEQUENCE OF
|
||||
int sktag, skaclass; |
||||
// First work out expected inner tag value
|
||||
if (flags & ASN1_TFLG_IMPTAG) { |
||||
sktag = tt->tag; |
||||
skaclass = aclass; |
||||
} else { |
||||
skaclass = V_ASN1_UNIVERSAL; |
||||
if (flags & ASN1_TFLG_SET_OF) { |
||||
sktag = V_ASN1_SET; |
||||
} else { |
||||
sktag = V_ASN1_SEQUENCE; |
||||
} |
||||
} |
||||
// Get the tag
|
||||
ret = |
||||
asn1_check_tlen(&len, NULL, NULL, NULL, &p, len, sktag, skaclass, opt); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
return 0; |
||||
} else if (ret == -1) { |
||||
return -1; |
||||
} |
||||
if (!*val) { |
||||
*val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null(); |
||||
} else { |
||||
// We've got a valid STACK: free up any items present
|
||||
STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; |
||||
ASN1_VALUE *vtmp; |
||||
while (sk_ASN1_VALUE_num(sktmp) > 0) { |
||||
vtmp = sk_ASN1_VALUE_pop(sktmp); |
||||
ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); |
||||
} |
||||
} |
||||
|
||||
if (!*val) { |
||||
goto err; |
||||
} |
||||
|
||||
// Read as many items as we can
|
||||
while (len > 0) { |
||||
ASN1_VALUE *skfield; |
||||
const unsigned char *q = p; |
||||
skfield = NULL; |
||||
if (!asn1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), |
||||
/*tag=*/-1, /*aclass=*/0, /*opt=*/0, buf, depth)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} |
||||
len -= p - q; |
||||
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { |
||||
ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item)); |
||||
goto err; |
||||
} |
||||
} |
||||
} else if (flags & ASN1_TFLG_IMPTAG) { |
||||
// IMPLICIT tagging
|
||||
ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, |
||||
aclass, opt, buf, depth); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} else if (ret == -1) { |
||||
return -1; |
||||
} |
||||
} else { |
||||
// Nothing special
|
||||
ret = asn1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), /*tag=*/-1, |
||||
/*aclass=*/0, opt, buf, depth); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
goto err; |
||||
} else if (ret == -1) { |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
*in = p; |
||||
return 1; |
||||
|
||||
err: |
||||
ASN1_template_free(val, tt); |
||||
return 0; |
||||
} |
||||
|
||||
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, |
||||
long inlen, const ASN1_ITEM *it, int tag, |
||||
int aclass, char opt) { |
||||
int ret = 0, utype; |
||||
long plen; |
||||
char cst; |
||||
const unsigned char *p; |
||||
const unsigned char *cont = NULL; |
||||
long len; |
||||
if (!pval) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL); |
||||
return 0; // Should never happen
|
||||
} |
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) { |
||||
utype = tag; |
||||
tag = -1; |
||||
} else { |
||||
utype = it->utype; |
||||
} |
||||
|
||||
if (utype == V_ASN1_ANY) { |
||||
// If type is ANY need to figure out type from tag
|
||||
unsigned char oclass; |
||||
if (tag >= 0) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY); |
||||
return 0; |
||||
} |
||||
if (opt) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY); |
||||
return 0; |
||||
} |
||||
p = *in; |
||||
ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, &p, inlen, -1, 0, 0); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
return 0; |
||||
} |
||||
if (!is_supported_universal_type(utype, oclass)) { |
||||
utype = V_ASN1_OTHER; |
||||
} |
||||
} |
||||
if (tag == -1) { |
||||
tag = utype; |
||||
aclass = V_ASN1_UNIVERSAL; |
||||
} |
||||
p = *in; |
||||
// Check header
|
||||
ret = asn1_check_tlen(&plen, NULL, NULL, &cst, &p, inlen, tag, aclass, opt); |
||||
if (!ret) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR); |
||||
return 0; |
||||
} else if (ret == -1) { |
||||
return -1; |
||||
} |
||||
ret = 0; |
||||
// SEQUENCE, SET and "OTHER" are left in encoded form
|
||||
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || |
||||
(utype == V_ASN1_OTHER)) { |
||||
// SEQUENCE and SET must be constructed
|
||||
if (utype != V_ASN1_OTHER && !cst) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED); |
||||
return 0; |
||||
} |
||||
|
||||
cont = *in; |
||||
len = p - cont + plen; |
||||
p += plen; |
||||
} else if (cst) { |
||||
// This parser historically supported BER constructed strings. We no
|
||||
// longer do and will gradually tighten this parser into a DER
|
||||
// parser. BER types should use |CBS_asn1_ber_to_der|.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE); |
||||
return 0; |
||||
} else { |
||||
cont = p; |
||||
len = plen; |
||||
p += plen; |
||||
} |
||||
|
||||
// We now have content length and type: translate into a structure
|
||||
if (!asn1_ex_c2i(pval, cont, len, utype, it)) { |
||||
goto err; |
||||
} |
||||
|
||||
*in = p; |
||||
ret = 1; |
||||
err: |
||||
return ret; |
||||
} |
||||
|
||||
// Translate ASN1 content octets into a structure
|
||||
|
||||
static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, |
||||
int utype, const ASN1_ITEM *it) { |
||||
ASN1_VALUE **opval = NULL; |
||||
ASN1_STRING *stmp; |
||||
ASN1_TYPE *typ = NULL; |
||||
int ret = 0; |
||||
ASN1_INTEGER **tint; |
||||
|
||||
// Historically, |it->funcs| for primitive types contained an
|
||||
// |ASN1_PRIMITIVE_FUNCS| table of callbacks.
|
||||
assert(it->funcs == NULL); |
||||
|
||||
// If ANY type clear type and set pointer to internal value
|
||||
if (it->utype == V_ASN1_ANY) { |
||||
if (!*pval) { |
||||
typ = ASN1_TYPE_new(); |
||||
if (typ == NULL) { |
||||
goto err; |
||||
} |
||||
*pval = (ASN1_VALUE *)typ; |
||||
} else { |
||||
typ = (ASN1_TYPE *)*pval; |
||||
} |
||||
|
||||
if (utype != typ->type) { |
||||
ASN1_TYPE_set(typ, utype, NULL); |
||||
} |
||||
opval = pval; |
||||
pval = &typ->value.asn1_value; |
||||
} |
||||
switch (utype) { |
||||
case V_ASN1_OBJECT: |
||||
if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) { |
||||
goto err; |
||||
} |
||||
break; |
||||
|
||||
case V_ASN1_NULL: |
||||
if (len) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH); |
||||
goto err; |
||||
} |
||||
*pval = (ASN1_VALUE *)1; |
||||
break; |
||||
|
||||
case V_ASN1_BOOLEAN: |
||||
if (len != 1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); |
||||
goto err; |
||||
} else { |
||||
ASN1_BOOLEAN *tbool; |
||||
tbool = (ASN1_BOOLEAN *)pval; |
||||
*tbool = *cont; |
||||
} |
||||
break; |
||||
|
||||
case V_ASN1_BIT_STRING: |
||||
if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) { |
||||
goto err; |
||||
} |
||||
break; |
||||
|
||||
case V_ASN1_INTEGER: |
||||
case V_ASN1_ENUMERATED: |
||||
tint = (ASN1_INTEGER **)pval; |
||||
if (!c2i_ASN1_INTEGER(tint, &cont, len)) { |
||||
goto err; |
||||
} |
||||
// Fixup type to match the expected form
|
||||
(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); |
||||
break; |
||||
|
||||
case V_ASN1_OCTET_STRING: |
||||
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: |
||||
case V_ASN1_SET: |
||||
case V_ASN1_SEQUENCE: |
||||
// TODO(crbug.com/boringssl/412): This default case should be removed, now
|
||||
// that we've resolved https://crbug.com/boringssl/561. However, it is still
|
||||
// needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE|
|
||||
// broadly doesn't tolerate unrecognized universal tags, but except for
|
||||
// eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the
|
||||
// X509Test.NameAttributeValues test.
|
||||
default: { |
||||
CBS cbs; |
||||
CBS_init(&cbs, cont, (size_t)len); |
||||
if (utype == V_ASN1_BMPSTRING) { |
||||
while (CBS_len(&cbs) != 0) { |
||||
uint32_t c; |
||||
if (!CBS_get_ucs2_be(&cbs, &c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING); |
||||
goto err; |
||||
} |
||||
} |
||||
} |
||||
if (utype == V_ASN1_UNIVERSALSTRING) { |
||||
while (CBS_len(&cbs) != 0) { |
||||
uint32_t c; |
||||
if (!CBS_get_utf32_be(&cbs, &c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING); |
||||
goto err; |
||||
} |
||||
} |
||||
} |
||||
if (utype == V_ASN1_UTF8STRING) { |
||||
while (CBS_len(&cbs) != 0) { |
||||
uint32_t c; |
||||
if (!CBS_get_utf8(&cbs, &c)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING); |
||||
goto err; |
||||
} |
||||
} |
||||
} |
||||
if (utype == V_ASN1_UTCTIME) { |
||||
if (!CBS_parse_utc_time(&cbs, NULL, /*allow_timezone_offset=*/1)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); |
||||
goto err; |
||||
} |
||||
} |
||||
if (utype == V_ASN1_GENERALIZEDTIME) { |
||||
if (!CBS_parse_generalized_time(&cbs, NULL, |
||||
/*allow_timezone_offset=*/0)) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT); |
||||
goto err; |
||||
} |
||||
} |
||||
// TODO(https://crbug.com/boringssl/427): Check other string types.
|
||||
|
||||
// All based on ASN1_STRING and handled the same
|
||||
if (!*pval) { |
||||
stmp = ASN1_STRING_type_new(utype); |
||||
if (!stmp) { |
||||
goto err; |
||||
} |
||||
*pval = (ASN1_VALUE *)stmp; |
||||
} else { |
||||
stmp = (ASN1_STRING *)*pval; |
||||
stmp->type = utype; |
||||
} |
||||
if (!ASN1_STRING_set(stmp, cont, len)) { |
||||
ASN1_STRING_free(stmp); |
||||
*pval = NULL; |
||||
goto err; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
// If ASN1_ANY and NULL type fix up value
|
||||
if (typ && (utype == V_ASN1_NULL)) { |
||||
typ->value.ptr = NULL; |
||||
} |
||||
|
||||
ret = 1; |
||||
err: |
||||
if (!ret) { |
||||
ASN1_TYPE_free(typ); |
||||
if (opval) { |
||||
*opval = NULL; |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
// Check an ASN1 tag and length: a bit like ASN1_get_object but it
|
||||
// checks the expected tag.
|
||||
|
||||
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, |
||||
char *cst, const unsigned char **in, long len, |
||||
int exptag, int expclass, char opt) { |
||||
int i; |
||||
int ptag, pclass; |
||||
long plen; |
||||
const unsigned char *p; |
||||
p = *in; |
||||
|
||||
i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); |
||||
if (i & 0x80) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER); |
||||
return 0; |
||||
} |
||||
if (exptag >= 0) { |
||||
if ((exptag != ptag) || (expclass != pclass)) { |
||||
// If type is OPTIONAL, not an error: indicate missing type.
|
||||
if (opt) { |
||||
return -1; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
if (cst) { |
||||
*cst = i & V_ASN1_CONSTRUCTED; |
||||
} |
||||
|
||||
if (olen) { |
||||
*olen = plen; |
||||
} |
||||
|
||||
if (oclass) { |
||||
*oclass = pclass; |
||||
} |
||||
|
||||
if (otag) { |
||||
*otag = ptag; |
||||
} |
||||
|
||||
*in = p; |
||||
return 1; |
||||
} |
@ -0,0 +1,662 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass); |
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
||||
int skcontlen, const ASN1_ITEM *item, |
||||
int do_sort, int iclass); |
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_TEMPLATE *tt, int tag, int aclass); |
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, |
||||
const ASN1_ITEM *it, int flags); |
||||
|
||||
/*
|
||||
* Top level i2d equivalents: the 'ndef' variant instructs the encoder to use |
||||
* indefinite length constructed encoding, where appropriate |
||||
*/ |
||||
|
||||
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, |
||||
const ASN1_ITEM *it) |
||||
{ |
||||
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); |
||||
} |
||||
|
||||
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) |
||||
{ |
||||
return asn1_item_flags_i2d(val, out, it, 0); |
||||
} |
||||
|
||||
/*
|
||||
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out' |
||||
* points to a buffer to output the data to. The new i2d has one additional |
||||
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is |
||||
* allocated and populated with the encoding. |
||||
*/ |
||||
|
||||
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, |
||||
const ASN1_ITEM *it, int flags) |
||||
{ |
||||
if (out && !*out) { |
||||
unsigned char *p, *buf; |
||||
int len; |
||||
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); |
||||
if (len <= 0) |
||||
return len; |
||||
buf = OPENSSL_malloc(len); |
||||
if (!buf) |
||||
return -1; |
||||
p = buf; |
||||
ASN1_item_ex_i2d(&val, &p, it, -1, flags); |
||||
*out = buf; |
||||
return len; |
||||
} |
||||
|
||||
return ASN1_item_ex_i2d(&val, out, it, -1, flags); |
||||
} |
||||
|
||||
/*
|
||||
* Encode an item, taking care of IMPLICIT tagging (if any). This function |
||||
* performs the normal item handling: it can be used in external types. |
||||
*/ |
||||
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass) |
||||
{ |
||||
const ASN1_TEMPLATE *tt = NULL; |
||||
unsigned char *p = NULL; |
||||
int i, seqcontlen, seqlen, ndef = 1; |
||||
const ASN1_COMPAT_FUNCS *cf; |
||||
const ASN1_EXTERN_FUNCS *ef; |
||||
const ASN1_AUX *aux = it->funcs; |
||||
ASN1_aux_cb *asn1_cb = 0; |
||||
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) |
||||
return 0; |
||||
|
||||
if (aux && aux->asn1_cb) |
||||
asn1_cb = aux->asn1_cb; |
||||
|
||||
switch (it->itype) { |
||||
|
||||
case ASN1_ITYPE_PRIMITIVE: |
||||
if (it->templates) |
||||
return asn1_template_ex_i2d(pval, out, it->templates, |
||||
tag, aclass); |
||||
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); |
||||
break; |
||||
|
||||
case ASN1_ITYPE_MSTRING: |
||||
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); |
||||
|
||||
case ASN1_ITYPE_CHOICE: |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) |
||||
return 0; |
||||
i = asn1_get_choice_selector(pval, it); |
||||
if ((i >= 0) && (i < it->tcount)) { |
||||
ASN1_VALUE **pchval; |
||||
const ASN1_TEMPLATE *chtt; |
||||
chtt = it->templates + i; |
||||
pchval = asn1_get_field_ptr(pval, chtt); |
||||
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); |
||||
} |
||||
/* Fixme: error condition if selector out of range */ |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) |
||||
return 0; |
||||
break; |
||||
|
||||
case ASN1_ITYPE_EXTERN: |
||||
/* If new style i2d it does all the work */ |
||||
ef = it->funcs; |
||||
return ef->asn1_ex_i2d(pval, out, it, tag, aclass); |
||||
|
||||
case ASN1_ITYPE_COMPAT: |
||||
/* old style hackery... */ |
||||
cf = it->funcs; |
||||
if (out) |
||||
p = *out; |
||||
i = cf->asn1_i2d(*pval, out); |
||||
/*
|
||||
* Fixup for IMPLICIT tag: note this messes up for tags > 30, but so |
||||
* did the old code. Tags > 30 are very rare anyway. |
||||
*/ |
||||
if (out && (tag != -1)) |
||||
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); |
||||
return i; |
||||
|
||||
case ASN1_ITYPE_NDEF_SEQUENCE: |
||||
/* Use indefinite length constructed if requested */ |
||||
if (aclass & ASN1_TFLG_NDEF) |
||||
ndef = 2; |
||||
/* fall through */ |
||||
|
||||
case ASN1_ITYPE_SEQUENCE: |
||||
i = asn1_enc_restore(&seqcontlen, out, pval, it); |
||||
/* An error occurred */ |
||||
if (i < 0) |
||||
return 0; |
||||
/* We have a valid cached encoding... */ |
||||
if (i > 0) |
||||
return seqcontlen; |
||||
/* Otherwise carry on */ |
||||
seqcontlen = 0; |
||||
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ |
||||
if (tag == -1) { |
||||
tag = V_ASN1_SEQUENCE; |
||||
/* Retain any other flags in aclass */ |
||||
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) |
||||
| V_ASN1_UNIVERSAL; |
||||
} |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) |
||||
return 0; |
||||
/* First work out sequence content length */ |
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
ASN1_VALUE **pseqval; |
||||
int tmplen; |
||||
seqtt = asn1_do_adb(pval, tt, 1); |
||||
if (!seqtt) |
||||
return 0; |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); |
||||
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) |
||||
return -1; |
||||
seqcontlen += tmplen; |
||||
} |
||||
|
||||
seqlen = ASN1_object_size(ndef, seqcontlen, tag); |
||||
if (!out || seqlen == -1) |
||||
return seqlen; |
||||
/* Output SEQUENCE header */ |
||||
ASN1_put_object(out, ndef, seqcontlen, tag, aclass); |
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
ASN1_VALUE **pseqval; |
||||
seqtt = asn1_do_adb(pval, tt, 1); |
||||
if (!seqtt) |
||||
return 0; |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
/* FIXME: check for errors in enhanced version */ |
||||
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); |
||||
} |
||||
if (ndef == 2) |
||||
ASN1_put_eoc(out); |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) |
||||
return 0; |
||||
return seqlen; |
||||
|
||||
default: |
||||
return 0; |
||||
|
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_TEMPLATE *tt, int tag, int iclass) |
||||
{ |
||||
int i, ret, flags, ttag, tclass, ndef; |
||||
size_t j; |
||||
flags = tt->flags; |
||||
/*
|
||||
* Work out tag and class to use: tagging may come either from the |
||||
* template or the arguments, not both because this would create |
||||
* ambiguity. Additionally the iclass argument may contain some |
||||
* additional flags which should be noted and passed down to other |
||||
* levels. |
||||
*/ |
||||
if (flags & ASN1_TFLG_TAG_MASK) { |
||||
/* Error if argument and template tagging */ |
||||
if (tag != -1) |
||||
/* FIXME: error code here */ |
||||
return -1; |
||||
/* Get tagging from template */ |
||||
ttag = tt->tag; |
||||
tclass = flags & ASN1_TFLG_TAG_CLASS; |
||||
} else if (tag != -1) { |
||||
/* No template tagging, get from arguments */ |
||||
ttag = tag; |
||||
tclass = iclass & ASN1_TFLG_TAG_CLASS; |
||||
} else { |
||||
ttag = -1; |
||||
tclass = 0; |
||||
} |
||||
/*
|
||||
* Remove any class mask from iflag. |
||||
*/ |
||||
iclass &= ~ASN1_TFLG_TAG_CLASS; |
||||
|
||||
/*
|
||||
* At this point 'ttag' contains the outer tag to use, 'tclass' is the |
||||
* class and iclass is any flags passed to this function. |
||||
*/ |
||||
|
||||
/* if template and arguments require ndef, use it */ |
||||
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) |
||||
ndef = 2; |
||||
else |
||||
ndef = 1; |
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) { |
||||
/* SET OF, SEQUENCE OF */ |
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; |
||||
int isset, sktag, skaclass; |
||||
int skcontlen, sklen; |
||||
ASN1_VALUE *skitem; |
||||
|
||||
if (!*pval) |
||||
return 0; |
||||
|
||||
if (flags & ASN1_TFLG_SET_OF) { |
||||
isset = 1; |
||||
/* 2 means we reorder */ |
||||
if (flags & ASN1_TFLG_SEQUENCE_OF) |
||||
isset = 2; |
||||
} else |
||||
isset = 0; |
||||
|
||||
/*
|
||||
* Work out inner tag value: if EXPLICIT or no tagging use underlying |
||||
* type. |
||||
*/ |
||||
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { |
||||
sktag = ttag; |
||||
skaclass = tclass; |
||||
} else { |
||||
skaclass = V_ASN1_UNIVERSAL; |
||||
if (isset) |
||||
sktag = V_ASN1_SET; |
||||
else |
||||
sktag = V_ASN1_SEQUENCE; |
||||
} |
||||
|
||||
/* Determine total length of items */ |
||||
skcontlen = 0; |
||||
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { |
||||
int tmplen; |
||||
skitem = sk_ASN1_VALUE_value(sk, j); |
||||
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), |
||||
-1, iclass); |
||||
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) |
||||
return -1; |
||||
skcontlen += tmplen; |
||||
} |
||||
sklen = ASN1_object_size(ndef, skcontlen, sktag); |
||||
if (sklen == -1) |
||||
return -1; |
||||
/* If EXPLICIT need length of surrounding tag */ |
||||
if (flags & ASN1_TFLG_EXPTAG) |
||||
ret = ASN1_object_size(ndef, sklen, ttag); |
||||
else |
||||
ret = sklen; |
||||
|
||||
if (!out || ret == -1) |
||||
return ret; |
||||
|
||||
/* Now encode this lot... */ |
||||
/* EXPLICIT tag */ |
||||
if (flags & ASN1_TFLG_EXPTAG) |
||||
ASN1_put_object(out, ndef, sklen, ttag, tclass); |
||||
/* SET or SEQUENCE and IMPLICIT tag */ |
||||
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); |
||||
/* And the stuff itself */ |
||||
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), |
||||
isset, iclass); |
||||
if (ndef == 2) { |
||||
ASN1_put_eoc(out); |
||||
if (flags & ASN1_TFLG_EXPTAG) |
||||
ASN1_put_eoc(out); |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
if (flags & ASN1_TFLG_EXPTAG) { |
||||
/* EXPLICIT tagging */ |
||||
/* Find length of tagged item */ |
||||
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); |
||||
if (!i) |
||||
return 0; |
||||
/* Find length of EXPLICIT tag */ |
||||
ret = ASN1_object_size(ndef, i, ttag); |
||||
if (out && ret != -1) { |
||||
/* Output tag and item */ |
||||
ASN1_put_object(out, ndef, i, ttag, tclass); |
||||
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); |
||||
if (ndef == 2) |
||||
ASN1_put_eoc(out); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
/* Either normal or IMPLICIT tagging: combine class and flags */ |
||||
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), |
||||
ttag, tclass | iclass); |
||||
|
||||
} |
||||
|
||||
/* Temporary structure used to hold DER encoding of items for SET OF */ |
||||
|
||||
typedef struct { |
||||
unsigned char *data; |
||||
int length; |
||||
ASN1_VALUE *field; |
||||
} DER_ENC; |
||||
|
||||
static int der_cmp(const void *a, const void *b) |
||||
{ |
||||
const DER_ENC *d1 = a, *d2 = b; |
||||
int cmplen, i; |
||||
cmplen = (d1->length < d2->length) ? d1->length : d2->length; |
||||
i = OPENSSL_memcmp(d1->data, d2->data, cmplen); |
||||
if (i) |
||||
return i; |
||||
return d1->length - d2->length; |
||||
} |
||||
|
||||
/* Output the content octets of SET OF or SEQUENCE OF */ |
||||
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
||||
int skcontlen, const ASN1_ITEM *item, |
||||
int do_sort, int iclass) |
||||
{ |
||||
size_t i; |
||||
ASN1_VALUE *skitem; |
||||
unsigned char *tmpdat = NULL, *p = NULL; |
||||
DER_ENC *derlst = NULL, *tder; |
||||
if (do_sort) { |
||||
/* Don't need to sort less than 2 items */ |
||||
if (sk_ASN1_VALUE_num(sk) < 2) |
||||
do_sort = 0; |
||||
else { |
||||
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) |
||||
* sizeof(*derlst)); |
||||
if (!derlst) |
||||
return 0; |
||||
tmpdat = OPENSSL_malloc(skcontlen); |
||||
if (!tmpdat) { |
||||
OPENSSL_free(derlst); |
||||
return 0; |
||||
} |
||||
} |
||||
} |
||||
/* If not sorting just output each item */ |
||||
if (!do_sort) { |
||||
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
||||
skitem = sk_ASN1_VALUE_value(sk, i); |
||||
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); |
||||
} |
||||
return 1; |
||||
} |
||||
p = tmpdat; |
||||
|
||||
/* Doing sort: build up a list of each member's DER encoding */ |
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { |
||||
skitem = sk_ASN1_VALUE_value(sk, i); |
||||
tder->data = p; |
||||
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); |
||||
tder->field = skitem; |
||||
} |
||||
|
||||
/* Now sort them */ |
||||
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); |
||||
/* Output sorted DER encoding */ |
||||
p = *out; |
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { |
||||
OPENSSL_memcpy(p, tder->data, tder->length); |
||||
p += tder->length; |
||||
} |
||||
*out = p; |
||||
/* If do_sort is 2 then reorder the STACK */ |
||||
if (do_sort == 2) { |
||||
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) |
||||
(void)sk_ASN1_VALUE_set(sk, i, tder->field); |
||||
} |
||||
OPENSSL_free(derlst); |
||||
OPENSSL_free(tmpdat); |
||||
return 1; |
||||
} |
||||
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass) |
||||
{ |
||||
int len; |
||||
int utype; |
||||
int usetag; |
||||
int ndef = 0; |
||||
|
||||
utype = it->utype; |
||||
|
||||
/*
|
||||
* Get length of content octets and maybe find out the underlying type. |
||||
*/ |
||||
|
||||
len = asn1_ex_i2c(pval, NULL, &utype, it); |
||||
|
||||
/*
|
||||
* If SEQUENCE, SET or OTHER then header is included in pseudo content |
||||
* octets so don't include tag+length. We need to check here because the |
||||
* call to asn1_ex_i2c() could change utype. |
||||
*/ |
||||
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || |
||||
(utype == V_ASN1_OTHER)) |
||||
usetag = 0; |
||||
else |
||||
usetag = 1; |
||||
|
||||
/* -1 means omit type */ |
||||
|
||||
if (len == -1) |
||||
return 0; |
||||
|
||||
/* -2 return is special meaning use ndef */ |
||||
if (len == -2) { |
||||
ndef = 2; |
||||
len = 0; |
||||
} |
||||
|
||||
/* If not implicitly tagged get tag from underlying type */ |
||||
if (tag == -1) |
||||
tag = utype; |
||||
|
||||
/* Output tag+length followed by content octets */ |
||||
if (out) { |
||||
if (usetag) |
||||
ASN1_put_object(out, ndef, len, tag, aclass); |
||||
asn1_ex_i2c(pval, *out, &utype, it); |
||||
if (ndef) |
||||
ASN1_put_eoc(out); |
||||
else |
||||
*out += len; |
||||
} |
||||
|
||||
if (usetag) |
||||
return ASN1_object_size(ndef, len, tag); |
||||
return len; |
||||
} |
||||
|
||||
/* Produce content octets from a structure */ |
||||
|
||||
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, |
||||
const ASN1_ITEM *it) |
||||
{ |
||||
ASN1_BOOLEAN *tbool = NULL; |
||||
ASN1_STRING *strtmp; |
||||
ASN1_OBJECT *otmp; |
||||
int utype; |
||||
const unsigned char *cont; |
||||
unsigned char c; |
||||
int len; |
||||
const ASN1_PRIMITIVE_FUNCS *pf; |
||||
pf = it->funcs; |
||||
if (pf && pf->prim_i2c) |
||||
return pf->prim_i2c(pval, cout, putype, it); |
||||
|
||||
/* Should type be omitted? */ |
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) |
||||
|| (it->utype != V_ASN1_BOOLEAN)) { |
||||
if (!*pval) |
||||
return -1; |
||||
} |
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) { |
||||
/* If MSTRING type set the underlying type */ |
||||
strtmp = (ASN1_STRING *)*pval; |
||||
utype = strtmp->type; |
||||
*putype = utype; |
||||
} else if (it->utype == V_ASN1_ANY) { |
||||
/* If ANY set type and pointer to value */ |
||||
ASN1_TYPE *typ; |
||||
typ = (ASN1_TYPE *)*pval; |
||||
utype = typ->type; |
||||
*putype = utype; |
||||
pval = &typ->value.asn1_value; |
||||
} else |
||||
utype = *putype; |
||||
|
||||
switch (utype) { |
||||
case V_ASN1_OBJECT: |
||||
otmp = (ASN1_OBJECT *)*pval; |
||||
cont = otmp->data; |
||||
len = otmp->length; |
||||
break; |
||||
|
||||
case V_ASN1_NULL: |
||||
cont = NULL; |
||||
len = 0; |
||||
break; |
||||
|
||||
case V_ASN1_BOOLEAN: |
||||
tbool = (ASN1_BOOLEAN *)pval; |
||||
if (*tbool == -1) |
||||
return -1; |
||||
if (it->utype != V_ASN1_ANY) { |
||||
/*
|
||||
* Default handling if value == size field then omit |
||||
*/ |
||||
if (*tbool && (it->size > 0)) |
||||
return -1; |
||||
if (!*tbool && !it->size) |
||||
return -1; |
||||
} |
||||
c = (unsigned char)*tbool; |
||||
cont = &c; |
||||
len = 1; |
||||
break; |
||||
|
||||
case V_ASN1_BIT_STRING: |
||||
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, |
||||
cout ? &cout : NULL); |
||||
break; |
||||
|
||||
case V_ASN1_INTEGER: |
||||
case V_ASN1_ENUMERATED: |
||||
/*
|
||||
* These are all have the same content format as ASN1_INTEGER |
||||
*/ |
||||
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); |
||||
break; |
||||
|
||||
case V_ASN1_OCTET_STRING: |
||||
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_SEQUENCE: |
||||
case V_ASN1_SET: |
||||
default: |
||||
/* All based on ASN1_STRING and handled the same */ |
||||
strtmp = (ASN1_STRING *)*pval; |
||||
/* Special handling for NDEF */ |
||||
if ((it->size == ASN1_TFLG_NDEF) |
||||
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { |
||||
if (cout) { |
||||
strtmp->data = cout; |
||||
strtmp->length = 0; |
||||
} |
||||
/* Special return code */ |
||||
return -2; |
||||
} |
||||
cont = strtmp->data; |
||||
len = strtmp->length; |
||||
|
||||
break; |
||||
|
||||
} |
||||
if (cout && len) |
||||
OPENSSL_memcpy(cout, cont, len); |
||||
return len; |
||||
} |
@ -1,664 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
static int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass, |
||||
int optional); |
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass, |
||||
int optional); |
||||
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *out_omit, |
||||
int *putype, const ASN1_ITEM *it); |
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
||||
int skcontlen, const ASN1_ITEM *item, int do_sort); |
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_TEMPLATE *tt, int tag, int aclass, |
||||
int optional); |
||||
|
||||
// Top level i2d equivalents
|
||||
|
||||
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) { |
||||
if (out && !*out) { |
||||
unsigned char *p, *buf; |
||||
int len = ASN1_item_ex_i2d(&val, NULL, it, /*tag=*/-1, /*aclass=*/0); |
||||
if (len <= 0) { |
||||
return len; |
||||
} |
||||
buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len)); |
||||
if (!buf) { |
||||
return -1; |
||||
} |
||||
p = buf; |
||||
int len2 = ASN1_item_ex_i2d(&val, &p, it, /*tag=*/-1, /*aclass=*/0); |
||||
if (len2 <= 0) { |
||||
OPENSSL_free(buf); |
||||
return len2; |
||||
} |
||||
assert(len == len2); |
||||
*out = buf; |
||||
return len; |
||||
} |
||||
|
||||
return ASN1_item_ex_i2d(&val, out, it, /*tag=*/-1, /*aclass=*/0); |
||||
} |
||||
|
||||
// Encode an item, taking care of IMPLICIT tagging (if any). This function
|
||||
// performs the normal item handling: it can be used in external types.
|
||||
|
||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass) { |
||||
int ret = asn1_item_ex_i2d_opt(pval, out, it, tag, aclass, /*optional=*/0); |
||||
assert(ret != 0); |
||||
return ret; |
||||
} |
||||
|
||||
// asn1_item_ex_i2d_opt behaves like |ASN1_item_ex_i2d| but, if |optional| is
|
||||
// non-zero and |*pval| is omitted, it returns zero and writes no bytes.
|
||||
int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass, |
||||
int optional) { |
||||
const ASN1_TEMPLATE *tt = NULL; |
||||
int i, seqcontlen, seqlen; |
||||
|
||||
// Historically, |aclass| was repurposed to pass additional flags into the
|
||||
// encoding process.
|
||||
assert((aclass & ASN1_TFLG_TAG_CLASS) == aclass); |
||||
// If not overridding the tag, |aclass| is ignored and should be zero.
|
||||
assert(tag != -1 || aclass == 0); |
||||
|
||||
// All fields are pointers, except for boolean |ASN1_ITYPE_PRIMITIVE|s.
|
||||
// Optional primitives are handled later.
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { |
||||
if (optional) { |
||||
return 0; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
||||
return -1; |
||||
} |
||||
|
||||
switch (it->itype) { |
||||
case ASN1_ITYPE_PRIMITIVE: |
||||
if (it->templates) { |
||||
// This is an |ASN1_ITEM_TEMPLATE|.
|
||||
if (it->templates->flags & ASN1_TFLG_OPTIONAL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
return asn1_template_ex_i2d(pval, out, it->templates, tag, aclass, |
||||
optional); |
||||
} |
||||
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass, optional); |
||||
|
||||
case ASN1_ITYPE_MSTRING: |
||||
// It never makes sense for multi-strings to have implicit tagging, so
|
||||
// if tag != -1, then this looks like an error in the template.
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
return asn1_i2d_ex_primitive(pval, out, it, -1, 0, optional); |
||||
|
||||
case ASN1_ITYPE_CHOICE: { |
||||
// It never makes sense for CHOICE types to have implicit tagging, so if
|
||||
// tag != -1, then this looks like an error in the template.
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
i = asn1_get_choice_selector(pval, it); |
||||
if (i < 0 || i >= it->tcount) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE); |
||||
return -1; |
||||
} |
||||
const ASN1_TEMPLATE *chtt = it->templates + i; |
||||
if (chtt->flags & ASN1_TFLG_OPTIONAL) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
ASN1_VALUE **pchval = asn1_get_field_ptr(pval, chtt); |
||||
return asn1_template_ex_i2d(pchval, out, chtt, -1, 0, /*optional=*/0); |
||||
} |
||||
|
||||
case ASN1_ITYPE_EXTERN: { |
||||
// We don't support implicit tagging with external types.
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
const ASN1_EXTERN_FUNCS *ef = |
||||
reinterpret_cast<const ASN1_EXTERN_FUNCS *>(it->funcs); |
||||
int ret = ef->asn1_ex_i2d(pval, out, it); |
||||
if (ret == 0) { |
||||
// |asn1_ex_i2d| should never return zero. We have already checked
|
||||
// for optional values generically, and |ASN1_ITYPE_EXTERN| fields
|
||||
// must be pointers.
|
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); |
||||
return -1; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
case ASN1_ITYPE_SEQUENCE: { |
||||
i = asn1_enc_restore(&seqcontlen, out, pval, it); |
||||
// An error occurred
|
||||
if (i < 0) { |
||||
return -1; |
||||
} |
||||
// We have a valid cached encoding...
|
||||
if (i > 0) { |
||||
return seqcontlen; |
||||
} |
||||
// Otherwise carry on
|
||||
seqcontlen = 0; |
||||
// If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL
|
||||
if (tag == -1) { |
||||
tag = V_ASN1_SEQUENCE; |
||||
aclass = V_ASN1_UNIVERSAL; |
||||
} |
||||
// First work out sequence content length
|
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
ASN1_VALUE **pseqval; |
||||
int tmplen; |
||||
seqtt = asn1_do_adb(pval, tt, 1); |
||||
if (!seqtt) { |
||||
return -1; |
||||
} |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
tmplen = |
||||
asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, 0, /*optional=*/0); |
||||
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) { |
||||
return -1; |
||||
} |
||||
seqcontlen += tmplen; |
||||
} |
||||
|
||||
seqlen = ASN1_object_size(/*constructed=*/1, seqcontlen, tag); |
||||
if (!out || seqlen == -1) { |
||||
return seqlen; |
||||
} |
||||
// Output SEQUENCE header
|
||||
ASN1_put_object(out, /*constructed=*/1, seqcontlen, tag, aclass); |
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
||||
const ASN1_TEMPLATE *seqtt; |
||||
ASN1_VALUE **pseqval; |
||||
seqtt = asn1_do_adb(pval, tt, 1); |
||||
if (!seqtt) { |
||||
return -1; |
||||
} |
||||
pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
if (asn1_template_ex_i2d(pseqval, out, seqtt, -1, 0, /*optional=*/0) < |
||||
0) { |
||||
return -1; |
||||
} |
||||
} |
||||
return seqlen; |
||||
} |
||||
|
||||
default: |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
// asn1_template_ex_i2d behaves like |asn1_item_ex_i2d_opt| but uses an
|
||||
// |ASN1_TEMPLATE| instead of an |ASN1_ITEM|. An |ASN1_TEMPLATE| wraps an
|
||||
// |ASN1_ITEM| with modifiers such as tagging, SEQUENCE or SET, etc.
|
||||
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_TEMPLATE *tt, int tag, int iclass, |
||||
int optional) { |
||||
int i, ret, ttag, tclass; |
||||
size_t j; |
||||
uint32_t flags = tt->flags; |
||||
|
||||
// Historically, |iclass| was repurposed to pass additional flags into the
|
||||
// encoding process.
|
||||
assert((iclass & ASN1_TFLG_TAG_CLASS) == iclass); |
||||
// If not overridding the tag, |iclass| is ignored and should be zero.
|
||||
assert(tag != -1 || iclass == 0); |
||||
|
||||
// Work out tag and class to use: tagging may come either from the
|
||||
// template or the arguments, not both because this would create
|
||||
// ambiguity.
|
||||
if (flags & ASN1_TFLG_TAG_MASK) { |
||||
// Error if argument and template tagging
|
||||
if (tag != -1) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
||||
return -1; |
||||
} |
||||
// Get tagging from template
|
||||
ttag = tt->tag; |
||||
tclass = flags & ASN1_TFLG_TAG_CLASS; |
||||
} else if (tag != -1) { |
||||
// No template tagging, get from arguments
|
||||
ttag = tag; |
||||
tclass = iclass & ASN1_TFLG_TAG_CLASS; |
||||
} else { |
||||
ttag = -1; |
||||
tclass = 0; |
||||
} |
||||
|
||||
// The template may itself by marked as optional, or this may be the template
|
||||
// of an |ASN1_ITEM_TEMPLATE| type which was contained inside an outer
|
||||
// optional template. (They cannot both be true because the
|
||||
// |ASN1_ITEM_TEMPLATE| codepath rejects optional templates.)
|
||||
assert(!optional || (flags & ASN1_TFLG_OPTIONAL) == 0); |
||||
optional = optional || (flags & ASN1_TFLG_OPTIONAL) != 0; |
||||
|
||||
// At this point 'ttag' contains the outer tag to use, and 'tclass' is the
|
||||
// class.
|
||||
|
||||
if (flags & ASN1_TFLG_SK_MASK) { |
||||
// SET OF, SEQUENCE OF
|
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; |
||||
int isset, sktag, skaclass; |
||||
int skcontlen, sklen; |
||||
ASN1_VALUE *skitem; |
||||
|
||||
if (!*pval) { |
||||
if (optional) { |
||||
return 0; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
||||
return -1; |
||||
} |
||||
|
||||
if (flags & ASN1_TFLG_SET_OF) { |
||||
isset = 1; |
||||
// Historically, types with both bits set were mutated when
|
||||
// serialized to apply the sort. We no longer support this.
|
||||
assert((flags & ASN1_TFLG_SEQUENCE_OF) == 0); |
||||
} else { |
||||
isset = 0; |
||||
} |
||||
|
||||
// Work out inner tag value: if EXPLICIT or no tagging use underlying
|
||||
// type.
|
||||
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { |
||||
sktag = ttag; |
||||
skaclass = tclass; |
||||
} else { |
||||
skaclass = V_ASN1_UNIVERSAL; |
||||
if (isset) { |
||||
sktag = V_ASN1_SET; |
||||
} else { |
||||
sktag = V_ASN1_SEQUENCE; |
||||
} |
||||
} |
||||
|
||||
// Determine total length of items
|
||||
skcontlen = 0; |
||||
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) { |
||||
int tmplen; |
||||
skitem = sk_ASN1_VALUE_value(sk, j); |
||||
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0); |
||||
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) { |
||||
return -1; |
||||
} |
||||
skcontlen += tmplen; |
||||
} |
||||
sklen = ASN1_object_size(/*constructed=*/1, skcontlen, sktag); |
||||
if (sklen == -1) { |
||||
return -1; |
||||
} |
||||
// If EXPLICIT need length of surrounding tag
|
||||
if (flags & ASN1_TFLG_EXPTAG) { |
||||
ret = ASN1_object_size(/*constructed=*/1, sklen, ttag); |
||||
} else { |
||||
ret = sklen; |
||||
} |
||||
|
||||
if (!out || ret == -1) { |
||||
return ret; |
||||
} |
||||
|
||||
// Now encode this lot...
|
||||
// EXPLICIT tag
|
||||
if (flags & ASN1_TFLG_EXPTAG) { |
||||
ASN1_put_object(out, /*constructed=*/1, sklen, ttag, tclass); |
||||
} |
||||
// SET or SEQUENCE and IMPLICIT tag
|
||||
ASN1_put_object(out, /*constructed=*/1, skcontlen, sktag, skaclass); |
||||
// And the stuff itself
|
||||
if (!asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset)) { |
||||
return -1; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
if (flags & ASN1_TFLG_EXPTAG) { |
||||
// EXPLICIT tagging
|
||||
// Find length of tagged item
|
||||
i = asn1_item_ex_i2d_opt(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0, |
||||
optional); |
||||
if (i <= 0) { |
||||
return i; |
||||
} |
||||
// Find length of EXPLICIT tag
|
||||
ret = ASN1_object_size(/*constructed=*/1, i, ttag); |
||||
if (out && ret != -1) { |
||||
// Output tag and item
|
||||
ASN1_put_object(out, /*constructed=*/1, i, ttag, tclass); |
||||
if (ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0) < 0) { |
||||
return -1; |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
// Either normal or IMPLICIT tagging
|
||||
return asn1_item_ex_i2d_opt(pval, out, ASN1_ITEM_ptr(tt->item), ttag, tclass, |
||||
optional); |
||||
} |
||||
|
||||
// Temporary structure used to hold DER encoding of items for SET OF
|
||||
|
||||
typedef struct { |
||||
unsigned char *data; |
||||
int length; |
||||
} DER_ENC; |
||||
|
||||
static int der_cmp(const void *a, const void *b) { |
||||
const DER_ENC *d1 = reinterpret_cast<const DER_ENC *>(a), |
||||
*d2 = reinterpret_cast<const DER_ENC *>(b); |
||||
int cmplen, i; |
||||
cmplen = (d1->length < d2->length) ? d1->length : d2->length; |
||||
i = OPENSSL_memcmp(d1->data, d2->data, cmplen); |
||||
if (i) { |
||||
return i; |
||||
} |
||||
return d1->length - d2->length; |
||||
} |
||||
|
||||
// asn1_set_seq_out writes |sk| to |out| under the i2d output convention,
|
||||
// excluding the tag and length. It returns one on success and zero on error.
|
||||
// |skcontlen| must be the total encoded size. If |do_sort| is non-zero, the
|
||||
// elements are sorted for a SET OF type. Each element of |sk| has type
|
||||
// |item|.
|
||||
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, |
||||
int skcontlen, const ASN1_ITEM *item, int do_sort) { |
||||
// No need to sort if there are fewer than two items.
|
||||
if (!do_sort || sk_ASN1_VALUE_num(sk) < 2) { |
||||
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
||||
ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); |
||||
if (ASN1_item_ex_i2d(&skitem, out, item, -1, 0) < 0) { |
||||
return 0; |
||||
} |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
int ret = 0; |
||||
uint8_t *const buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(skcontlen)); |
||||
DER_ENC *encoded = reinterpret_cast<DER_ENC *>( |
||||
OPENSSL_calloc(sk_ASN1_VALUE_num(sk), sizeof(*encoded))); |
||||
uint8_t *p = buf; |
||||
if (encoded == NULL || buf == NULL) { |
||||
goto err; |
||||
} |
||||
|
||||
// Encode all the elements into |buf| and populate |encoded|.
|
||||
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
||||
ASN1_VALUE *skitem = sk_ASN1_VALUE_value(sk, i); |
||||
encoded[i].data = p; |
||||
encoded[i].length = ASN1_item_ex_i2d(&skitem, &p, item, -1, 0); |
||||
if (encoded[i].length < 0) { |
||||
goto err; |
||||
} |
||||
assert(p - buf <= skcontlen); |
||||
} |
||||
|
||||
qsort(encoded, sk_ASN1_VALUE_num(sk), sizeof(*encoded), der_cmp); |
||||
|
||||
// Output the elements in sorted order.
|
||||
p = *out; |
||||
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
||||
OPENSSL_memcpy(p, encoded[i].data, encoded[i].length); |
||||
p += encoded[i].length; |
||||
} |
||||
*out = p; |
||||
|
||||
ret = 1; |
||||
|
||||
err: |
||||
OPENSSL_free(encoded); |
||||
OPENSSL_free(buf); |
||||
return ret; |
||||
} |
||||
|
||||
// asn1_i2d_ex_primitive behaves like |ASN1_item_ex_i2d| but |item| must be a
|
||||
// a PRIMITIVE or MSTRING type that is not an |ASN1_ITEM_TEMPLATE|.
|
||||
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, |
||||
const ASN1_ITEM *it, int tag, int aclass, |
||||
int optional) { |
||||
// Get length of content octets and maybe find out the underlying type.
|
||||
int omit; |
||||
int utype = it->utype; |
||||
int len = asn1_ex_i2c(pval, NULL, &omit, &utype, it); |
||||
if (len < 0) { |
||||
return -1; |
||||
} |
||||
if (omit) { |
||||
if (optional) { |
||||
return 0; |
||||
} |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
||||
return -1; |
||||
} |
||||
|
||||
// If SEQUENCE, SET or OTHER then header is included in pseudo content
|
||||
// octets so don't include tag+length. We need to check here because the
|
||||
// call to asn1_ex_i2c() could change utype.
|
||||
int usetag = |
||||
utype != V_ASN1_SEQUENCE && utype != V_ASN1_SET && utype != V_ASN1_OTHER; |
||||
|
||||
// If not implicitly tagged get tag from underlying type
|
||||
if (tag == -1) { |
||||
tag = utype; |
||||
} |
||||
|
||||
// Output tag+length followed by content octets
|
||||
if (out) { |
||||
if (usetag) { |
||||
ASN1_put_object(out, /*constructed=*/0, len, tag, aclass); |
||||
} |
||||
int len2 = asn1_ex_i2c(pval, *out, &omit, &utype, it); |
||||
if (len2 < 0) { |
||||
return -1; |
||||
} |
||||
assert(len == len2); |
||||
assert(!omit); |
||||
*out += len; |
||||
} |
||||
|
||||
if (usetag) { |
||||
return ASN1_object_size(/*constructed=*/0, len, tag); |
||||
} |
||||
return len; |
||||
} |
||||
|
||||
// asn1_ex_i2c writes the |*pval| to |cout| under the i2d output convention,
|
||||
// excluding the tag and length. It returns the number of bytes written,
|
||||
// possibly zero, on success or -1 on error. If |*pval| should be omitted, it
|
||||
// returns zero and sets |*out_omit| to true.
|
||||
//
|
||||
// If |it| is an MSTRING or ANY type, it gets the underlying type from |*pval|,
|
||||
// which must be an |ASN1_STRING| or |ASN1_TYPE|, respectively. It then updates
|
||||
// |*putype| with the tag number of type used, or |V_ASN1_OTHER| if it was not a
|
||||
// universal type. If |*putype| is set to |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or
|
||||
// |V_ASN1_OTHER|, it additionally outputs the tag and length, so the caller
|
||||
// must not do so.
|
||||
//
|
||||
// Otherwise, |*putype| must contain |it->utype|.
|
||||
//
|
||||
// WARNING: Unlike most functions in this file, |asn1_ex_i2c| can return zero
|
||||
// without omitting the element. ASN.1 values may have empty contents.
|
||||
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *out_omit, |
||||
int *putype, const ASN1_ITEM *it) { |
||||
ASN1_BOOLEAN *tbool = NULL; |
||||
ASN1_STRING *strtmp; |
||||
ASN1_OBJECT *otmp; |
||||
int utype; |
||||
const unsigned char *cont; |
||||
unsigned char c; |
||||
int len; |
||||
|
||||
// Historically, |it->funcs| for primitive types contained an
|
||||
// |ASN1_PRIMITIVE_FUNCS| table of callbacks.
|
||||
assert(it->funcs == NULL); |
||||
|
||||
*out_omit = 0; |
||||
|
||||
// Should type be omitted?
|
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) { |
||||
if (!*pval) { |
||||
*out_omit = 1; |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
if (it->itype == ASN1_ITYPE_MSTRING) { |
||||
// If MSTRING type set the underlying type
|
||||
strtmp = (ASN1_STRING *)*pval; |
||||
utype = strtmp->type; |
||||
if (utype < 0 && utype != V_ASN1_OTHER) { |
||||
// MSTRINGs can have type -1 when default-constructed.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); |
||||
return -1; |
||||
} |
||||
// Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values
|
||||
// that do not match their corresponding utype values. INTEGERs cannot
|
||||
// participate in MSTRING types, but ENUMERATEDs can.
|
||||
//
|
||||
// TODO(davidben): Is this a bug? Although arguably one of the MSTRING
|
||||
// types should contain more values, rather than less. See
|
||||
// https://crbug.com/boringssl/412. But it is not possible to fit all
|
||||
// possible ANY values into an |ASN1_STRING|, so matching the spec here
|
||||
// is somewhat hopeless.
|
||||
if (utype == V_ASN1_NEG_INTEGER) { |
||||
utype = V_ASN1_INTEGER; |
||||
} else if (utype == V_ASN1_NEG_ENUMERATED) { |
||||
utype = V_ASN1_ENUMERATED; |
||||
} |
||||
*putype = utype; |
||||
} else if (it->utype == V_ASN1_ANY) { |
||||
// If ANY set type and pointer to value
|
||||
ASN1_TYPE *typ; |
||||
typ = (ASN1_TYPE *)*pval; |
||||
utype = typ->type; |
||||
if (utype < 0 && utype != V_ASN1_OTHER) { |
||||
// |ASN1_TYPE|s can have type -1 when default-constructed.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE); |
||||
return -1; |
||||
} |
||||
*putype = utype; |
||||
pval = &typ->value.asn1_value; |
||||
} else { |
||||
utype = *putype; |
||||
} |
||||
|
||||
switch (utype) { |
||||
case V_ASN1_OBJECT: |
||||
otmp = (ASN1_OBJECT *)*pval; |
||||
cont = otmp->data; |
||||
len = otmp->length; |
||||
if (len == 0) { |
||||
// Some |ASN1_OBJECT|s do not have OIDs and cannot be serialized.
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); |
||||
return -1; |
||||
} |
||||
break; |
||||
|
||||
case V_ASN1_NULL: |
||||
cont = NULL; |
||||
len = 0; |
||||
break; |
||||
|
||||
case V_ASN1_BOOLEAN: |
||||
tbool = (ASN1_BOOLEAN *)pval; |
||||
if (*tbool == ASN1_BOOLEAN_NONE) { |
||||
*out_omit = 1; |
||||
return 0; |
||||
} |
||||
if (it->utype != V_ASN1_ANY) { |
||||
// Default handling if value == size field then omit
|
||||
if ((*tbool && (it->size > 0)) || (!*tbool && !it->size)) { |
||||
*out_omit = 1; |
||||
return 0; |
||||
} |
||||
} |
||||
c = *tbool ? 0xff : 0x00; |
||||
cont = &c; |
||||
len = 1; |
||||
break; |
||||
|
||||
case V_ASN1_BIT_STRING: { |
||||
int ret = |
||||
i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL); |
||||
// |i2c_ASN1_BIT_STRING| returns zero on error instead of -1.
|
||||
return ret <= 0 ? -1 : ret; |
||||
} |
||||
|
||||
case V_ASN1_INTEGER: |
||||
case V_ASN1_ENUMERATED: { |
||||
// |i2c_ASN1_INTEGER| also handles ENUMERATED.
|
||||
int ret = i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); |
||||
// |i2c_ASN1_INTEGER| returns zero on error instead of -1.
|
||||
return ret <= 0 ? -1 : ret; |
||||
} |
||||
|
||||
case V_ASN1_OCTET_STRING: |
||||
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_SEQUENCE: |
||||
case V_ASN1_SET: |
||||
// This is not a valid |ASN1_ITEM| type, but it appears in |ASN1_TYPE|.
|
||||
case V_ASN1_OTHER: |
||||
// TODO(crbug.com/boringssl/412): This default case should be removed, now
|
||||
// that we've resolved https://crbug.com/boringssl/561. However, it is still
|
||||
// needed to support some edge cases in |ASN1_PRINTABLE|. |ASN1_PRINTABLE|
|
||||
// broadly doesn't tolerate unrecognized universal tags, but except for
|
||||
// eight values that map to |B_ASN1_UNKNOWN| instead of zero. See the
|
||||
// X509Test.NameAttributeValues test.
|
||||
default: |
||||
// All based on ASN1_STRING and handled the same
|
||||
strtmp = (ASN1_STRING *)*pval; |
||||
cont = strtmp->data; |
||||
len = strtmp->length; |
||||
break; |
||||
} |
||||
if (cout && len) { |
||||
OPENSSL_memcpy(cout, cont, len); |
||||
} |
||||
return len; |
||||
} |
@ -0,0 +1,246 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
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); |
||||
} |
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) |
||||
{ |
||||
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; |
||||
|
||||
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_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_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_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); |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
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_NULL: |
||||
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; |
||||
} |
@ -1,159 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/mem.h> |
||||
|
||||
#include "internal.h" |
||||
|
||||
// Free up an ASN1 structure
|
||||
|
||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) { |
||||
ASN1_item_ex_free(&val, it); |
||||
} |
||||
|
||||
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
if (!pval) { |
||||
return; |
||||
} |
||||
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) { |
||||
return; |
||||
} |
||||
|
||||
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_MSTRING: |
||||
ASN1_primitive_free(pval, it); |
||||
break; |
||||
|
||||
case ASN1_ITYPE_CHOICE: { |
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; |
||||
if (asn1_cb) { |
||||
if (asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL) == 2) { |
||||
return; |
||||
} |
||||
} |
||||
int i = asn1_get_choice_selector(pval, it); |
||||
if ((i >= 0) && (i < it->tcount)) { |
||||
const ASN1_TEMPLATE *tt = it->templates + i; |
||||
ASN1_VALUE **pchval = asn1_get_field_ptr(pval, tt); |
||||
ASN1_template_free(pchval, tt); |
||||
} |
||||
if (asn1_cb) { |
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); |
||||
} |
||||
OPENSSL_free(*pval); |
||||
*pval = NULL; |
||||
break; |
||||
} |
||||
|
||||
case ASN1_ITYPE_EXTERN: { |
||||
const ASN1_EXTERN_FUNCS *ef = |
||||
reinterpret_cast<const ASN1_EXTERN_FUNCS *>(it->funcs); |
||||
if (ef && ef->asn1_ex_free) { |
||||
ef->asn1_ex_free(pval, it); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
case ASN1_ITYPE_SEQUENCE: { |
||||
if (!asn1_refcount_dec_and_test_zero(pval, it)) { |
||||
return; |
||||
} |
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; |
||||
if (asn1_cb) { |
||||
if (asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL) == 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.
|
||||
for (int i = it->tcount - 1; i >= 0; i--) { |
||||
const ASN1_TEMPLATE *seqtt = asn1_do_adb(pval, &it->templates[i], 0); |
||||
if (!seqtt) { |
||||
continue; |
||||
} |
||||
ASN1_VALUE **pseqval = asn1_get_field_ptr(pval, seqtt); |
||||
ASN1_template_free(pseqval, seqtt); |
||||
} |
||||
if (asn1_cb) { |
||||
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); |
||||
} |
||||
OPENSSL_free(*pval); |
||||
*pval = NULL; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { |
||||
if (tt->flags & ASN1_TFLG_SK_MASK) { |
||||
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; |
||||
for (size_t i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
||||
ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i); |
||||
ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); |
||||
} |
||||
sk_ASN1_VALUE_free(sk); |
||||
*pval = NULL; |
||||
} else { |
||||
ASN1_item_ex_free(pval, ASN1_ITEM_ptr(tt->item)); |
||||
} |
||||
} |
||||
|
||||
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
// Historically, |it->funcs| for primitive types contained an
|
||||
// |ASN1_PRIMITIVE_FUNCS| table of calbacks.
|
||||
assert(it->funcs == NULL); |
||||
|
||||
int utype = it->itype == ASN1_ITYPE_MSTRING ? -1 : it->utype; |
||||
switch (utype) { |
||||
case V_ASN1_OBJECT: |
||||
ASN1_OBJECT_free((ASN1_OBJECT *)*pval); |
||||
break; |
||||
|
||||
case V_ASN1_BOOLEAN: |
||||
if (it) { |
||||
*(ASN1_BOOLEAN *)pval = (ASN1_BOOLEAN)it->size; |
||||
} else { |
||||
*(ASN1_BOOLEAN *)pval = ASN1_BOOLEAN_NONE; |
||||
} |
||||
return; |
||||
|
||||
case V_ASN1_NULL: |
||||
break; |
||||
|
||||
case V_ASN1_ANY: |
||||
if (*pval != NULL) { |
||||
asn1_type_cleanup((ASN1_TYPE *)*pval); |
||||
OPENSSL_free(*pval); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
ASN1_STRING_free((ASN1_STRING *)*pval); |
||||
*pval = NULL; |
||||
break; |
||||
} |
||||
*pval = NULL; |
||||
} |
@ -0,0 +1,386 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
||||
int combine); |
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
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; |
||||
} |
||||
|
||||
/* 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); |
||||
} |
||||
|
||||
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; |
||||
|
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_push_info(it->sname); |
||||
#endif |
||||
|
||||
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_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_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) { |
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_pop_info(); |
||||
#endif |
||||
return 1; |
||||
} |
||||
} |
||||
if (!combine) { |
||||
*pval = OPENSSL_malloc(it->size); |
||||
if (!*pval) |
||||
goto memerr; |
||||
OPENSSL_memset(*pval, 0, it->size); |
||||
} |
||||
asn1_set_choice_selector(pval, -1, it); |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) |
||||
goto auxerr2; |
||||
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) { |
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_pop_info(); |
||||
#endif |
||||
return 1; |
||||
} |
||||
} |
||||
if (!combine) { |
||||
*pval = OPENSSL_malloc(it->size); |
||||
if (!*pval) |
||||
goto memerr; |
||||
OPENSSL_memset(*pval, 0, it->size); |
||||
asn1_refcount_set_one(pval, it); |
||||
asn1_enc_init(pval, it); |
||||
} |
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
||||
pseqval = asn1_get_field_ptr(pval, tt); |
||||
if (!ASN1_template_new(pseqval, tt)) |
||||
goto memerr2; |
||||
} |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) |
||||
goto auxerr2; |
||||
break; |
||||
} |
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_pop_info(); |
||||
#endif |
||||
return 1; |
||||
|
||||
memerr2: |
||||
ASN1_item_ex_free(pval, it); |
||||
memerr: |
||||
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_pop_info(); |
||||
#endif |
||||
return 0; |
||||
|
||||
auxerr2: |
||||
ASN1_item_ex_free(pval, it); |
||||
auxerr: |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); |
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_pop_info(); |
||||
#endif |
||||
return 0; |
||||
|
||||
} |
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) |
||||
{ |
||||
const ASN1_EXTERN_FUNCS *ef; |
||||
|
||||
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_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; |
||||
} |
||||
} |
||||
|
||||
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 */ |
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) { |
||||
*pval = NULL; |
||||
return 1; |
||||
} |
||||
#ifdef CRYPTO_MDEBUG |
||||
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: |
||||
#ifdef CRYPTO_MDEBUG |
||||
if (it->sname) |
||||
CRYPTO_pop_info(); |
||||
#endif |
||||
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)); |
||||
} |
||||
|
||||
/*
|
||||
* 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; |
||||
|
||||
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->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_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; |
||||
|
||||
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; |
||||
} |
@ -1,271 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
|
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
static int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
||||
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
||||
static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it); |
||||
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; |
||||
} |
||||
|
||||
// Allocate an ASN1 structure
|
||||
|
||||
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
const ASN1_TEMPLATE *tt = NULL; |
||||
const ASN1_EXTERN_FUNCS *ef; |
||||
ASN1_VALUE **pseqval; |
||||
int i; |
||||
|
||||
switch (it->itype) { |
||||
case ASN1_ITYPE_EXTERN: |
||||
ef = reinterpret_cast<const ASN1_EXTERN_FUNCS *>(it->funcs); |
||||
if (ef && ef->asn1_ex_new) { |
||||
if (!ef->asn1_ex_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_CHOICE: { |
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; |
||||
if (asn1_cb) { |
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); |
||||
if (!i) { |
||||
goto auxerr; |
||||
} |
||||
if (i == 2) { |
||||
return 1; |
||||
} |
||||
} |
||||
*pval = reinterpret_cast<ASN1_VALUE *>(OPENSSL_zalloc(it->size)); |
||||
if (!*pval) { |
||||
goto memerr; |
||||
} |
||||
asn1_set_choice_selector(pval, -1, it); |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) { |
||||
goto auxerr2; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
case ASN1_ITYPE_SEQUENCE: { |
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
ASN1_aux_cb *asn1_cb = aux != NULL ? aux->asn1_cb : NULL; |
||||
if (asn1_cb) { |
||||
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); |
||||
if (!i) { |
||||
goto auxerr; |
||||
} |
||||
if (i == 2) { |
||||
return 1; |
||||
} |
||||
} |
||||
*pval = reinterpret_cast<ASN1_VALUE *>(OPENSSL_zalloc(it->size)); |
||||
if (!*pval) { |
||||
goto memerr; |
||||
} |
||||
asn1_refcount_set_one(pval, it); |
||||
asn1_enc_init(pval, it); |
||||
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
||||
pseqval = asn1_get_field_ptr(pval, tt); |
||||
if (!ASN1_template_new(pseqval, tt)) { |
||||
goto memerr2; |
||||
} |
||||
} |
||||
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) { |
||||
goto auxerr2; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
return 1; |
||||
|
||||
memerr2: |
||||
ASN1_item_ex_free(pval, it); |
||||
memerr: |
||||
return 0; |
||||
|
||||
auxerr2: |
||||
ASN1_item_ex_free(pval, it); |
||||
auxerr: |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR); |
||||
return 0; |
||||
} |
||||
|
||||
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
switch (it->itype) { |
||||
case ASN1_ITYPE_EXTERN: |
||||
*pval = NULL; |
||||
break; |
||||
|
||||
case ASN1_ITYPE_PRIMITIVE: |
||||
if (it->templates) { |
||||
asn1_template_clear(pval, it->templates); |
||||
} else { |
||||
asn1_primitive_clear(pval, it); |
||||
} |
||||
break; |
||||
|
||||
case ASN1_ITYPE_MSTRING: |
||||
asn1_primitive_clear(pval, it); |
||||
break; |
||||
|
||||
case ASN1_ITYPE_CHOICE: |
||||
case ASN1_ITYPE_SEQUENCE: |
||||
*pval = NULL; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static 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
|
||||
|
||||
if (tt->flags & ASN1_TFLG_ADB_MASK) { |
||||
*pval = NULL; |
||||
return 1; |
||||
} |
||||
// 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) { |
||||
ret = 0; |
||||
goto done; |
||||
} |
||||
*pval = (ASN1_VALUE *)skval; |
||||
ret = 1; |
||||
goto done; |
||||
} |
||||
// Otherwise pass it back to the item routine
|
||||
ret = ASN1_item_ex_new(pval, it); |
||||
done: |
||||
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)); |
||||
} |
||||
} |
||||
|
||||
// NB: could probably combine most of the real XXX_new() behaviour and junk
|
||||
// all the old functions.
|
||||
|
||||
static int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
if (!it) { |
||||
return 0; |
||||
} |
||||
|
||||
// Historically, |it->funcs| for primitive types contained an
|
||||
// |ASN1_PRIMITIVE_FUNCS| table of calbacks.
|
||||
assert(it->funcs == NULL); |
||||
|
||||
int utype; |
||||
if (it->itype == ASN1_ITYPE_MSTRING) { |
||||
utype = -1; |
||||
} else { |
||||
utype = it->utype; |
||||
} |
||||
switch (utype) { |
||||
case V_ASN1_OBJECT: |
||||
*pval = (ASN1_VALUE *)OBJ_get_undef(); |
||||
return 1; |
||||
|
||||
case V_ASN1_BOOLEAN: |
||||
*(ASN1_BOOLEAN *)pval = (ASN1_BOOLEAN)it->size; |
||||
return 1; |
||||
|
||||
case V_ASN1_NULL: |
||||
*pval = (ASN1_VALUE *)1; |
||||
return 1; |
||||
|
||||
case V_ASN1_ANY: { |
||||
ASN1_TYPE *typ = |
||||
reinterpret_cast<ASN1_TYPE *>(OPENSSL_malloc(sizeof(ASN1_TYPE))); |
||||
if (!typ) { |
||||
return 0; |
||||
} |
||||
typ->value.ptr = NULL; |
||||
typ->type = -1; |
||||
*pval = (ASN1_VALUE *)typ; |
||||
break; |
||||
} |
||||
|
||||
default: |
||||
*pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype); |
||||
break; |
||||
} |
||||
if (*pval) { |
||||
return 1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
int utype; |
||||
// Historically, |it->funcs| for primitive types contained an
|
||||
// |ASN1_PRIMITIVE_FUNCS| table of calbacks.
|
||||
assert(it == NULL || it->funcs == NULL); |
||||
if (!it || (it->itype == ASN1_ITYPE_MSTRING)) { |
||||
utype = -1; |
||||
} else { |
||||
utype = it->utype; |
||||
} |
||||
if (utype == V_ASN1_BOOLEAN) { |
||||
*(ASN1_BOOLEAN *)pval = (ASN1_BOOLEAN)it->size; |
||||
} else { |
||||
*pval = NULL; |
||||
} |
||||
} |
@ -0,0 +1,131 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <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_STRING_FUNCTIONS(ASN1_OCTET_STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING) |
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_NULL) |
||||
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL) |
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT) |
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY) |
||||
|
||||
/* 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 */ |
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE) |
||||
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) |
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT) |
||||
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 */ |
||||
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 */ |
||||
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, 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_END(ASN1_SEQUENCE_ANY) |
||||
|
||||
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = |
||||
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY) |
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) |
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) |
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) |
@ -1,79 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
|
||||
// Declarations for string types
|
||||
|
||||
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ |
||||
IMPLEMENT_ASN1_TYPE(sname) \
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_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) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING) |
||||
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING) |
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_NULL) |
||||
IMPLEMENT_ASN1_FUNCTIONS_const(ASN1_NULL) |
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT) |
||||
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_ANY) |
||||
|
||||
// Just swallow an ASN1_SEQUENCE in an ASN1_STRING
|
||||
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE) |
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) |
||||
|
||||
// Multistring types
|
||||
|
||||
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE) |
||||
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, ASN1_PRINTABLE, |
||||
ASN1_PRINTABLE) |
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT) |
||||
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, DISPLAYTEXT, DISPLAYTEXT) |
||||
|
||||
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING) |
||||
IMPLEMENT_ASN1_FUNCTIONS_const_fname(ASN1_STRING, DIRECTORYSTRING, |
||||
DIRECTORYSTRING) |
||||
|
||||
// Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE
|
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, ASN1_BOOLEAN_NONE) |
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, ASN1_BOOLEAN_TRUE) |
||||
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, ASN1_BOOLEAN_FALSE) |
||||
|
||||
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, |
||||
ASN1_SET_ANY, ASN1_ANY) |
||||
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) |
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, |
||||
ASN1_SEQUENCE_ANY, |
||||
ASN1_SEQUENCE_ANY) |
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, |
||||
ASN1_SET_ANY) |
@ -0,0 +1,280 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/thread.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
/* Utility functions for manipulating fields and offsets */ |
||||
|
||||
/* Add 'offset' to 'addr' */ |
||||
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset)) |
||||
|
||||
/* Given an ASN1_ITEM CHOICE type return the selector value */ |
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
int *sel = offset2ptr(*pval, it->utype); |
||||
return *sel; |
||||
} |
||||
|
||||
/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */ |
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value, |
||||
const ASN1_ITEM *it) { |
||||
int *sel, ret; |
||||
sel = offset2ptr(*pval, it->utype); |
||||
ret = *sel; |
||||
*sel = value; |
||||
return ret; |
||||
} |
||||
|
||||
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval, |
||||
const ASN1_ITEM *it) { |
||||
if (it->itype != ASN1_ITYPE_SEQUENCE && |
||||
it->itype != ASN1_ITYPE_NDEF_SEQUENCE) { |
||||
return NULL; |
||||
} |
||||
const ASN1_AUX *aux = it->funcs; |
||||
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) { |
||||
return NULL; |
||||
} |
||||
return offset2ptr(*pval, aux->ref_offset); |
||||
} |
||||
|
||||
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it); |
||||
if (references != NULL) { |
||||
*references = 1; |
||||
} |
||||
} |
||||
|
||||
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it); |
||||
if (references != NULL) { |
||||
return CRYPTO_refcount_dec_and_test_zero(references); |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
const ASN1_AUX *aux; |
||||
if (!pval || !*pval) { |
||||
return NULL; |
||||
} |
||||
aux = it->funcs; |
||||
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) { |
||||
return NULL; |
||||
} |
||||
return offset2ptr(*pval, aux->enc_offset); |
||||
} |
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc; |
||||
enc = asn1_get_enc_ptr(pval, it); |
||||
if (enc) { |
||||
enc->enc = NULL; |
||||
enc->len = 0; |
||||
enc->alias_only = 0; |
||||
enc->alias_only_on_next_parse = 0; |
||||
enc->modified = 1; |
||||
} |
||||
} |
||||
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc; |
||||
enc = asn1_get_enc_ptr(pval, it); |
||||
if (enc) { |
||||
if (enc->enc && !enc->alias_only) { |
||||
OPENSSL_free(enc->enc); |
||||
} |
||||
enc->enc = NULL; |
||||
enc->len = 0; |
||||
enc->alias_only = 0; |
||||
enc->alias_only_on_next_parse = 0; |
||||
enc->modified = 1; |
||||
} |
||||
} |
||||
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, |
||||
const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc; |
||||
enc = asn1_get_enc_ptr(pval, it); |
||||
if (!enc) { |
||||
return 1; |
||||
} |
||||
|
||||
if (!enc->alias_only) { |
||||
OPENSSL_free(enc->enc); |
||||
} |
||||
|
||||
enc->alias_only = enc->alias_only_on_next_parse; |
||||
enc->alias_only_on_next_parse = 0; |
||||
|
||||
if (enc->alias_only) { |
||||
enc->enc = (uint8_t *) in; |
||||
} else { |
||||
enc->enc = OPENSSL_malloc(inlen); |
||||
if (!enc->enc) { |
||||
return 0; |
||||
} |
||||
OPENSSL_memcpy(enc->enc, in, inlen); |
||||
} |
||||
|
||||
enc->len = inlen; |
||||
enc->modified = 0; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, |
||||
const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc; |
||||
enc = asn1_get_enc_ptr(pval, it); |
||||
if (!enc || enc->modified) { |
||||
return 0; |
||||
} |
||||
if (out) { |
||||
OPENSSL_memcpy(*out, enc->enc, enc->len); |
||||
*out += enc->len; |
||||
} |
||||
if (len) { |
||||
*len = enc->len; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
/* Given an ASN1_TEMPLATE get a pointer to a field */ |
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { |
||||
ASN1_VALUE **pvaltmp; |
||||
if (tt->flags & ASN1_TFLG_COMBINE) { |
||||
return pval; |
||||
} |
||||
pvaltmp = offset2ptr(*pval, tt->offset); |
||||
/* NOTE for BOOLEAN types the field is just a plain int so we can't return
|
||||
* int **, so settle for (int *). */ |
||||
return pvaltmp; |
||||
} |
||||
|
||||
/* Handle ANY DEFINED BY template, find the selector, look up the relevant
|
||||
* ASN1_TEMPLATE in the table and return it. */ |
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, |
||||
int nullerr) { |
||||
const ASN1_ADB *adb; |
||||
const ASN1_ADB_TABLE *atbl; |
||||
long selector; |
||||
ASN1_VALUE **sfld; |
||||
int i; |
||||
if (!(tt->flags & ASN1_TFLG_ADB_MASK)) { |
||||
return tt; |
||||
} |
||||
|
||||
/* Else ANY DEFINED BY ... get the table */ |
||||
adb = ASN1_ADB_ptr(tt->item); |
||||
|
||||
/* Get the selector field */ |
||||
sfld = offset2ptr(*pval, adb->offset); |
||||
|
||||
/* Check if NULL */ |
||||
if (*sfld == NULL) { |
||||
if (!adb->null_tt) { |
||||
goto err; |
||||
} |
||||
return adb->null_tt; |
||||
} |
||||
|
||||
/* Convert type to a long:
|
||||
* NB: don't check for NID_undef here because it |
||||
* might be a legitimate value in the table */ |
||||
if (tt->flags & ASN1_TFLG_ADB_OID) { |
||||
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); |
||||
} else { |
||||
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); |
||||
} |
||||
|
||||
/* Try to find matching entry in table Maybe should check application types
|
||||
* first to allow application override? Might also be useful to have a flag |
||||
* which indicates table is sorted and we can do a binary search. For now |
||||
* stick to a linear search. */ |
||||
|
||||
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) { |
||||
if (atbl->value == selector) { |
||||
return &atbl->tt; |
||||
} |
||||
} |
||||
|
||||
/* FIXME: need to search application table too */ |
||||
|
||||
/* No match, return default type */ |
||||
if (!adb->default_tt) { |
||||
goto err; |
||||
} |
||||
return adb->default_tt; |
||||
|
||||
err: |
||||
/* FIXME: should log the value or OID of unsupported type */ |
||||
if (nullerr) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); |
||||
} |
||||
return NULL; |
||||
} |
@ -1,224 +0,0 @@ |
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/asn1.h> |
||||
|
||||
#include <assert.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/asn1t.h> |
||||
#include <openssl/err.h> |
||||
#include <openssl/mem.h> |
||||
#include <openssl/obj.h> |
||||
#include <openssl/pool.h> |
||||
#include <openssl/thread.h> |
||||
|
||||
#include "../internal.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
// Utility functions for manipulating fields and offsets
|
||||
|
||||
// Add 'offset' to 'addr'
|
||||
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset)) |
||||
|
||||
// Given an ASN1_ITEM CHOICE type return the selector value
|
||||
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
int *sel = reinterpret_cast<int *>(offset2ptr(*pval, it->utype)); |
||||
return *sel; |
||||
} |
||||
|
||||
// Given an ASN1_ITEM CHOICE type set the selector value, return old value.
|
||||
int asn1_set_choice_selector(ASN1_VALUE **pval, int value, |
||||
const ASN1_ITEM *it) { |
||||
int *sel, ret; |
||||
sel = reinterpret_cast<int *>(offset2ptr(*pval, it->utype)); |
||||
ret = *sel; |
||||
*sel = value; |
||||
return ret; |
||||
} |
||||
|
||||
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval, |
||||
const ASN1_ITEM *it) { |
||||
if (it->itype != ASN1_ITYPE_SEQUENCE) { |
||||
return NULL; |
||||
} |
||||
const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) { |
||||
return NULL; |
||||
} |
||||
return reinterpret_cast<CRYPTO_refcount_t *>( |
||||
offset2ptr(*pval, aux->ref_offset)); |
||||
} |
||||
|
||||
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it); |
||||
if (references != NULL) { |
||||
*references = 1; |
||||
} |
||||
} |
||||
|
||||
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
CRYPTO_refcount_t *references = asn1_get_references(pval, it); |
||||
if (references != NULL) { |
||||
return CRYPTO_refcount_dec_and_test_zero(references); |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
assert(it->itype == ASN1_ITYPE_SEQUENCE); |
||||
const ASN1_AUX *aux; |
||||
if (!pval || !*pval) { |
||||
return NULL; |
||||
} |
||||
aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
||||
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) { |
||||
return NULL; |
||||
} |
||||
return reinterpret_cast<ASN1_ENCODING *>(offset2ptr(*pval, aux->enc_offset)); |
||||
} |
||||
|
||||
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); |
||||
if (enc) { |
||||
enc->enc = NULL; |
||||
enc->len = 0; |
||||
enc->buf = NULL; |
||||
} |
||||
} |
||||
|
||||
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); |
||||
if (enc) { |
||||
asn1_encoding_clear(enc); |
||||
} |
||||
} |
||||
|
||||
int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len, |
||||
const ASN1_ITEM *it, CRYPTO_BUFFER *buf) { |
||||
ASN1_ENCODING *enc; |
||||
enc = asn1_get_enc_ptr(pval, it); |
||||
if (!enc) { |
||||
return 1; |
||||
} |
||||
|
||||
asn1_encoding_clear(enc); |
||||
if (buf != NULL) { |
||||
assert(CRYPTO_BUFFER_data(buf) <= in && |
||||
in + in_len <= CRYPTO_BUFFER_data(buf) + CRYPTO_BUFFER_len(buf)); |
||||
CRYPTO_BUFFER_up_ref(buf); |
||||
enc->buf = buf; |
||||
enc->enc = (uint8_t *)in; |
||||
} else { |
||||
enc->enc = reinterpret_cast<uint8_t *>(OPENSSL_memdup(in, in_len)); |
||||
if (!enc->enc) { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
enc->len = in_len; |
||||
return 1; |
||||
} |
||||
|
||||
void asn1_encoding_clear(ASN1_ENCODING *enc) { |
||||
if (enc->buf != NULL) { |
||||
CRYPTO_BUFFER_free(enc->buf); |
||||
} else { |
||||
OPENSSL_free(enc->enc); |
||||
} |
||||
enc->enc = NULL; |
||||
enc->len = 0; |
||||
enc->buf = NULL; |
||||
} |
||||
|
||||
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, |
||||
const ASN1_ITEM *it) { |
||||
ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); |
||||
if (!enc || enc->len == 0) { |
||||
return 0; |
||||
} |
||||
if (out) { |
||||
OPENSSL_memcpy(*out, enc->enc, enc->len); |
||||
*out += enc->len; |
||||
} |
||||
if (len) { |
||||
*len = enc->len; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
// Given an ASN1_TEMPLATE get a pointer to a field
|
||||
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) { |
||||
ASN1_VALUE **pvaltmp = |
||||
reinterpret_cast<ASN1_VALUE **>(offset2ptr(*pval, tt->offset)); |
||||
// NOTE for BOOLEAN types the field is just a plain int so we can't return
|
||||
// int **, so settle for (int *).
|
||||
return pvaltmp; |
||||
} |
||||
|
||||
// Handle ANY DEFINED BY template, find the selector, look up the relevant
|
||||
// ASN1_TEMPLATE in the table and return it.
|
||||
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, |
||||
int nullerr) { |
||||
const ASN1_ADB *adb; |
||||
const ASN1_ADB_TABLE *atbl; |
||||
ASN1_VALUE **sfld; |
||||
int i; |
||||
if (!(tt->flags & ASN1_TFLG_ADB_MASK)) { |
||||
return tt; |
||||
} |
||||
|
||||
// Else ANY DEFINED BY ... get the table
|
||||
adb = ASN1_ADB_ptr(tt->item); |
||||
|
||||
// Get the selector field
|
||||
sfld = reinterpret_cast<ASN1_VALUE **>(offset2ptr(*pval, adb->offset)); |
||||
|
||||
// Check if NULL
|
||||
int selector; |
||||
if (*sfld == NULL) { |
||||
if (!adb->null_tt) { |
||||
goto err; |
||||
} |
||||
return adb->null_tt; |
||||
} |
||||
|
||||
// Convert type to a NID:
|
||||
// NB: don't check for NID_undef here because it
|
||||
// might be a legitimate value in the table
|
||||
assert(tt->flags & ASN1_TFLG_ADB_OID); |
||||
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); |
||||
|
||||
// Try to find matching entry in table Maybe should check application types
|
||||
// first to allow application override? Might also be useful to have a flag
|
||||
// which indicates table is sorted and we can do a binary search. For now
|
||||
// stick to a linear search.
|
||||
|
||||
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) { |
||||
if (atbl->value == selector) { |
||||
return &atbl->tt; |
||||
} |
||||
} |
||||
|
||||
// FIXME: need to search application table too
|
||||
|
||||
// No match, return default type
|
||||
if (!adb->default_tt) { |
||||
goto err; |
||||
} |
||||
return adb->default_tt; |
||||
|
||||
err: |
||||
// FIXME: should log the value or OID of unsupported type
|
||||
if (nullerr) { |
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); |
||||
} |
||||
return NULL; |
||||
} |
@ -0,0 +1,206 @@ |
||||
/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
|
||||
* project 2001. |
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
||||
* project 2008. |
||||
*/ |
||||
/* ====================================================================
|
||||
* Copyright (c) 2001 The OpenSSL Project. All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in |
||||
* the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* |
||||
* 3. All advertising materials mentioning features or use of this |
||||
* software must display the following acknowledgment: |
||||
* "This product includes software developed by the OpenSSL Project |
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
* |
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
||||
* endorse or promote products derived from this software without |
||||
* prior written permission. For written permission, please contact |
||||
* licensing@OpenSSL.org. |
||||
* |
||||
* 5. Products derived from this software may not be called "OpenSSL" |
||||
* nor may "OpenSSL" appear in their names without prior written |
||||
* permission of the OpenSSL Project. |
||||
* |
||||
* 6. Redistributions of any form whatsoever must retain the following |
||||
* acknowledgment: |
||||
* "This product includes software developed by the OpenSSL Project |
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
||||
* OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* ==================================================================== |
||||
* |
||||
* This product includes cryptographic software written by Eric Young |
||||
* (eay@cryptsoft.com). This product includes software written by Tim |
||||
* Hudson (tjh@cryptsoft.com). */ |
||||
|
||||
#if !defined(_POSIX_C_SOURCE) |
||||
#define _POSIX_C_SOURCE 201410L /* for gmtime_r */ |
||||
#endif |
||||
|
||||
#include "asn1_locl.h" |
||||
|
||||
#include <time.h> |
||||
|
||||
|
||||
#define SECS_PER_DAY (24 * 60 * 60) |
||||
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result) { |
||||
#if defined(OPENSSL_WINDOWS) |
||||
if (gmtime_s(result, time)) { |
||||
return NULL; |
||||
} |
||||
return result; |
||||
#else |
||||
return gmtime_r(time, result); |
||||
#endif |
||||
} |
||||
|
||||
/* Convert date to and from julian day Uses Fliegel & Van Flandern algorithm */ |
||||
static long date_to_julian(int y, int m, int d) { |
||||
return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + |
||||
(367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - |
||||
(3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075; |
||||
} |
||||
|
||||
static void julian_to_date(long jd, int *y, int *m, int *d) { |
||||
long L = jd + 68569; |
||||
long n = (4 * L) / 146097; |
||||
long i, j; |
||||
|
||||
L = L - (146097 * n + 3) / 4; |
||||
i = (4000 * (L + 1)) / 1461001; |
||||
L = L - (1461 * i) / 4 + 31; |
||||
j = (80 * L) / 2447; |
||||
*d = L - (2447 * j) / 80; |
||||
L = j / 11; |
||||
*m = j + 2 - (12 * L); |
||||
*y = 100 * (n - 49) + i + L; |
||||
} |
||||
|
||||
/* Convert tm structure and offset into julian day and seconds */ |
||||
static int julian_adj(const struct tm *tm, int off_day, long offset_sec, |
||||
long *pday, int *psec) { |
||||
int offset_hms, offset_day; |
||||
long time_jd; |
||||
int time_year, time_month, time_day; |
||||
/* split offset into days and day seconds */ |
||||
offset_day = offset_sec / SECS_PER_DAY; |
||||
/* Avoid sign issues with % operator */ |
||||
offset_hms = offset_sec - (offset_day * SECS_PER_DAY); |
||||
offset_day += off_day; |
||||
/* Add current time seconds to offset */ |
||||
offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; |
||||
/* Adjust day seconds if overflow */ |
||||
if (offset_hms >= SECS_PER_DAY) { |
||||
offset_day++; |
||||
offset_hms -= SECS_PER_DAY; |
||||
} else if (offset_hms < 0) { |
||||
offset_day--; |
||||
offset_hms += SECS_PER_DAY; |
||||
} |
||||
|
||||
/* Convert date of time structure into a Julian day number. */ |
||||
|
||||
time_year = tm->tm_year + 1900; |
||||
time_month = tm->tm_mon + 1; |
||||
time_day = tm->tm_mday; |
||||
|
||||
time_jd = date_to_julian(time_year, time_month, time_day); |
||||
|
||||
/* Work out Julian day of new date */ |
||||
time_jd += offset_day; |
||||
|
||||
if (time_jd < 0) { |
||||
return 0; |
||||
} |
||||
|
||||
*pday = time_jd; |
||||
*psec = offset_hms; |
||||
return 1; |
||||
} |
||||
|
||||
int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) { |
||||
int time_sec, time_year, time_month, time_day; |
||||
long time_jd; |
||||
|
||||
/* Convert time and offset into julian day and seconds */ |
||||
if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec)) { |
||||
return 0; |
||||
} |
||||
|
||||
/* Convert Julian day back to date */ |
||||
|
||||
julian_to_date(time_jd, &time_year, &time_month, &time_day); |
||||
|
||||
if (time_year < 1900 || time_year > 9999) { |
||||
return 0; |
||||
} |
||||
|
||||
/* Update tm structure */ |
||||
|
||||
tm->tm_year = time_year - 1900; |
||||
tm->tm_mon = time_month - 1; |
||||
tm->tm_mday = time_day; |
||||
|
||||
tm->tm_hour = time_sec / 3600; |
||||
tm->tm_min = (time_sec / 60) % 60; |
||||
tm->tm_sec = time_sec % 60; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from, |
||||
const struct tm *to) { |
||||
int from_sec, to_sec, diff_sec; |
||||
long from_jd, to_jd, diff_day; |
||||
|
||||
if (!julian_adj(from, 0, 0, &from_jd, &from_sec)) { |
||||
return 0; |
||||
} |
||||
if (!julian_adj(to, 0, 0, &to_jd, &to_sec)) { |
||||
return 0; |
||||
} |
||||
|
||||
diff_day = to_jd - from_jd; |
||||
diff_sec = to_sec - from_sec; |
||||
/* Adjust differences so both positive or both negative */ |
||||
if (diff_day > 0 && diff_sec < 0) { |
||||
diff_day--; |
||||
diff_sec += SECS_PER_DAY; |
||||
} |
||||
if (diff_day < 0 && diff_sec > 0) { |
||||
diff_day++; |
||||
diff_sec -= SECS_PER_DAY; |
||||
} |
||||
|
||||
if (out_days) { |
||||
*out_days = (int)diff_day; |
||||
} |
||||
if (out_secs) { |
||||
*out_secs = diff_sec; |
||||
} |
||||
|
||||
return 1; |
||||
} |
@ -0,0 +1,9 @@ |
||||
include_directories(../../include) |
||||
|
||||
add_library( |
||||
base64 |
||||
|
||||
OBJECT |
||||
|
||||
base64.c |
||||
) |
@ -0,0 +1,466 @@ |
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved. |
||||
* |
||||
* This package is an SSL implementation written |
||||
* by Eric Young (eay@cryptsoft.com). |
||||
* The implementation was written so as to conform with Netscapes SSL. |
||||
* |
||||
* This library is free for commercial and non-commercial use as long as |
||||
* the following conditions are aheared to. The following conditions |
||||
* apply to all code found in this distribution, be it the RC4, RSA, |
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
||||
* included with this distribution is covered by the same copyright terms |
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
||||
* |
||||
* Copyright remains Eric Young's, and as such any Copyright notices in |
||||
* the code are not to be removed. |
||||
* If this package is used in a product, Eric Young should be given attribution |
||||
* as the author of the parts of the library used. |
||||
* This can be in the form of a textual message at program startup or |
||||
* in documentation (online or textual) provided with the package. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. All advertising materials mentioning features or use of this software |
||||
* must display the following acknowledgement: |
||||
* "This product includes cryptographic software written by |
||||
* Eric Young (eay@cryptsoft.com)" |
||||
* The word 'cryptographic' can be left out if the rouines from the library |
||||
* being used are not cryptographic related :-). |
||||
* 4. If you include any Windows specific code (or a derivative thereof) from |
||||
* the apps directory (application code) you must include an acknowledgement: |
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
* |
||||
* The licence and distribution terms for any publically available version or |
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be |
||||
* copied and put under another distribution licence |
||||
* [including the GNU Public Licence.] */ |
||||
|
||||
#include <openssl/base64.h> |
||||
|
||||
#include <assert.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include <openssl/type_check.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t|
|
||||
// arguments for a slightly simpler implementation.
|
||||
static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) { |
||||
crypto_word_t aw = a; |
||||
crypto_word_t bw = b; |
||||
// |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same
|
||||
// MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1.
|
||||
return constant_time_msb_w(aw - bw); |
||||
} |
||||
|
||||
// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max|
|
||||
// and |CONSTTIME_FALSE_8| otherwise.
|
||||
static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min, |
||||
uint8_t max) { |
||||
a -= min; |
||||
return constant_time_lt_args_8(a, max - min + 1); |
||||
} |
||||
|
||||
// Encoding.
|
||||
|
||||
static uint8_t conv_bin2ascii(uint8_t a) { |
||||
// Since PEM is sometimes used to carry private keys, we encode base64 data
|
||||
// itself in constant-time.
|
||||
a &= 0x3f; |
||||
uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/'); |
||||
ret = |
||||
constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret); |
||||
ret = |
||||
constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret); |
||||
ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret); |
||||
return ret; |
||||
} |
||||
|
||||
OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0, |
||||
data_length_must_be_multiple_of_base64_chunk_size); |
||||
|
||||
int EVP_EncodedLength(size_t *out_len, size_t len) { |
||||
if (len + 2 < len) { |
||||
return 0; |
||||
} |
||||
len += 2; |
||||
len /= 3; |
||||
|
||||
if (((len << 2) >> 2) != len) { |
||||
return 0; |
||||
} |
||||
len <<= 2; |
||||
|
||||
if (len + 1 < len) { |
||||
return 0; |
||||
} |
||||
len++; |
||||
|
||||
*out_len = len; |
||||
return 1; |
||||
} |
||||
|
||||
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { |
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); |
||||
} |
||||
|
||||
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, |
||||
const uint8_t *in, size_t in_len) { |
||||
size_t total = 0; |
||||
|
||||
*out_len = 0; |
||||
if (in_len == 0) { |
||||
return; |
||||
} |
||||
|
||||
assert(ctx->data_used < sizeof(ctx->data)); |
||||
|
||||
if (sizeof(ctx->data) - ctx->data_used > in_len) { |
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len); |
||||
ctx->data_used += (unsigned)in_len; |
||||
return; |
||||
} |
||||
|
||||
if (ctx->data_used != 0) { |
||||
const size_t todo = sizeof(ctx->data) - ctx->data_used; |
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo); |
||||
in += todo; |
||||
in_len -= todo; |
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data)); |
||||
ctx->data_used = 0; |
||||
|
||||
out += encoded; |
||||
*(out++) = '\n'; |
||||
*out = '\0'; |
||||
|
||||
total = encoded + 1; |
||||
} |
||||
|
||||
while (in_len >= sizeof(ctx->data)) { |
||||
size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data)); |
||||
in += sizeof(ctx->data); |
||||
in_len -= sizeof(ctx->data); |
||||
|
||||
out += encoded; |
||||
*(out++) = '\n'; |
||||
*out = '\0'; |
||||
|
||||
if (total + encoded + 1 < total) { |
||||
*out_len = 0; |
||||
return; |
||||
} |
||||
|
||||
total += encoded + 1; |
||||
} |
||||
|
||||
if (in_len != 0) { |
||||
OPENSSL_memcpy(ctx->data, in, in_len); |
||||
} |
||||
|
||||
ctx->data_used = (unsigned)in_len; |
||||
|
||||
if (total > INT_MAX) { |
||||
// We cannot signal an error, but we can at least avoid making *out_len
|
||||
// negative.
|
||||
total = 0; |
||||
} |
||||
*out_len = (int)total; |
||||
} |
||||
|
||||
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { |
||||
if (ctx->data_used == 0) { |
||||
*out_len = 0; |
||||
return; |
||||
} |
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used); |
||||
out[encoded++] = '\n'; |
||||
out[encoded] = '\0'; |
||||
ctx->data_used = 0; |
||||
|
||||
// ctx->data_used is bounded by sizeof(ctx->data), so this does not
|
||||
// overflow.
|
||||
assert(encoded <= INT_MAX); |
||||
*out_len = (int)encoded; |
||||
} |
||||
|
||||
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { |
||||
uint32_t l; |
||||
size_t remaining = src_len, ret = 0; |
||||
|
||||
while (remaining) { |
||||
if (remaining >= 3) { |
||||
l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2]; |
||||
*(dst++) = conv_bin2ascii(l >> 18L); |
||||
*(dst++) = conv_bin2ascii(l >> 12L); |
||||
*(dst++) = conv_bin2ascii(l >> 6L); |
||||
*(dst++) = conv_bin2ascii(l); |
||||
remaining -= 3; |
||||
} else { |
||||
l = ((uint32_t)src[0]) << 16L; |
||||
if (remaining == 2) { |
||||
l |= ((uint32_t)src[1] << 8L); |
||||
} |
||||
|
||||
*(dst++) = conv_bin2ascii(l >> 18L); |
||||
*(dst++) = conv_bin2ascii(l >> 12L); |
||||
*(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L); |
||||
*(dst++) = '='; |
||||
remaining = 0; |
||||
} |
||||
ret += 4; |
||||
src += 3; |
||||
} |
||||
|
||||
*dst = '\0'; |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
// Decoding.
|
||||
|
||||
int EVP_DecodedLength(size_t *out_len, size_t len) { |
||||
if (len % 4 != 0) { |
||||
return 0; |
||||
} |
||||
|
||||
*out_len = (len / 4) * 3; |
||||
return 1; |
||||
} |
||||
|
||||
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { |
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); |
||||
} |
||||
|
||||
static uint8_t base64_ascii_to_bin(uint8_t a) { |
||||
// Since PEM is sometimes used to carry private keys, we decode base64 data
|
||||
// itself in constant-time.
|
||||
const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z'); |
||||
const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z'); |
||||
const uint8_t is_digit = constant_time_in_range_8(a, '0', '9'); |
||||
const uint8_t is_plus = constant_time_eq_8(a, '+'); |
||||
const uint8_t is_slash = constant_time_eq_8(a, '/'); |
||||
const uint8_t is_equals = constant_time_eq_8(a, '='); |
||||
|
||||
uint8_t ret = 0xff; // 0xff signals invalid.
|
||||
ret = constant_time_select_8(is_upper, a - 'A', ret); // [0,26)
|
||||
ret = constant_time_select_8(is_lower, a - 'a' + 26, ret); // [26,52)
|
||||
ret = constant_time_select_8(is_digit, a - '0' + 52, ret); // [52,62)
|
||||
ret = constant_time_select_8(is_plus, 62, ret); |
||||
ret = constant_time_select_8(is_slash, 63, ret); |
||||
// Padding maps to zero, to be further handled by the caller.
|
||||
ret = constant_time_select_8(is_equals, 0, ret); |
||||
return ret; |
||||
} |
||||
|
||||
// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
|
||||
// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
|
||||
// number of bytes written, which will be less than three if the quad ended
|
||||
// with padding. It returns one on success or zero on error.
|
||||
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, |
||||
const uint8_t *in) { |
||||
const uint8_t a = base64_ascii_to_bin(in[0]); |
||||
const uint8_t b = base64_ascii_to_bin(in[1]); |
||||
const uint8_t c = base64_ascii_to_bin(in[2]); |
||||
const uint8_t d = base64_ascii_to_bin(in[3]); |
||||
if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) { |
||||
return 0; |
||||
} |
||||
|
||||
const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 | |
||||
((uint32_t)c) << 6 | (uint32_t)d; |
||||
|
||||
const unsigned padding_pattern = (in[0] == '=') << 3 | |
||||
(in[1] == '=') << 2 | |
||||
(in[2] == '=') << 1 | |
||||
(in[3] == '='); |
||||
|
||||
switch (padding_pattern) { |
||||
case 0: |
||||
// The common case of no padding.
|
||||
*out_num_bytes = 3; |
||||
out[0] = v >> 16; |
||||
out[1] = v >> 8; |
||||
out[2] = v; |
||||
break; |
||||
|
||||
case 1: // xxx=
|
||||
*out_num_bytes = 2; |
||||
out[0] = v >> 16; |
||||
out[1] = v >> 8; |
||||
break; |
||||
|
||||
case 3: // xx==
|
||||
*out_num_bytes = 1; |
||||
out[0] = v >> 16; |
||||
break; |
||||
|
||||
default: |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, |
||||
const uint8_t *in, size_t in_len) { |
||||
*out_len = 0; |
||||
|
||||
if (ctx->error_encountered) { |
||||
return -1; |
||||
} |
||||
|
||||
size_t bytes_out = 0, i; |
||||
for (i = 0; i < in_len; i++) { |
||||
const char c = in[i]; |
||||
switch (c) { |
||||
case ' ': |
||||
case '\t': |
||||
case '\r': |
||||
case '\n': |
||||
continue; |
||||
} |
||||
|
||||
if (ctx->eof_seen) { |
||||
ctx->error_encountered = 1; |
||||
return -1; |
||||
} |
||||
|
||||
ctx->data[ctx->data_used++] = c; |
||||
if (ctx->data_used == 4) { |
||||
size_t num_bytes_resulting; |
||||
if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) { |
||||
ctx->error_encountered = 1; |
||||
return -1; |
||||
} |
||||
|
||||
ctx->data_used = 0; |
||||
bytes_out += num_bytes_resulting; |
||||
out += num_bytes_resulting; |
||||
|
||||
if (num_bytes_resulting < 3) { |
||||
ctx->eof_seen = 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (bytes_out > INT_MAX) { |
||||
ctx->error_encountered = 1; |
||||
*out_len = 0; |
||||
return -1; |
||||
} |
||||
*out_len = (int)bytes_out; |
||||
|
||||
if (ctx->eof_seen) { |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { |
||||
*out_len = 0; |
||||
if (ctx->error_encountered || ctx->data_used != 0) { |
||||
return -1; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, |
||||
const uint8_t *in, size_t in_len) { |
||||
*out_len = 0; |
||||
|
||||
if (in_len % 4 != 0) { |
||||
return 0; |
||||
} |
||||
|
||||
size_t max_len; |
||||
if (!EVP_DecodedLength(&max_len, in_len) || |
||||
max_out < max_len) { |
||||
return 0; |
||||
} |
||||
|
||||
size_t i, bytes_out = 0; |
||||
for (i = 0; i < in_len; i += 4) { |
||||
size_t num_bytes_resulting; |
||||
|
||||
if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) { |
||||
return 0; |
||||
} |
||||
|
||||
bytes_out += num_bytes_resulting; |
||||
out += num_bytes_resulting; |
||||
if (num_bytes_resulting != 3 && i != in_len - 4) { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
*out_len = bytes_out; |
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { |
||||
// Trim spaces and tabs from the beginning of the input.
|
||||
while (src_len > 0) { |
||||
if (src[0] != ' ' && src[0] != '\t') { |
||||
break; |
||||
} |
||||
|
||||
src++; |
||||
src_len--; |
||||
} |
||||
|
||||
// Trim newlines, spaces and tabs from the end of the line.
|
||||
while (src_len > 0) { |
||||
switch (src[src_len-1]) { |
||||
case ' ': |
||||
case '\t': |
||||
case '\r': |
||||
case '\n': |
||||
src_len--; |
||||
continue; |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
size_t dst_len; |
||||
if (!EVP_DecodedLength(&dst_len, src_len) || |
||||
dst_len > INT_MAX || |
||||
!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) { |
||||
return -1; |
||||
} |
||||
|
||||
// EVP_DecodeBlock does not take padding into account, so put the
|
||||
// NULs back in... so the caller can strip them back out.
|
||||
while (dst_len % 3 != 0) { |
||||
dst[dst_len++] = '\0'; |
||||
} |
||||
assert(dst_len <= INT_MAX); |
||||
|
||||
return (int)dst_len; |
||||
} |
@ -1,429 +0,0 @@ |
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
||||
* |
||||
* Licensed under the OpenSSL license (the "License"). You may not use |
||||
* this file except in compliance with the License. You can obtain a copy |
||||
* in the file LICENSE in the source distribution or at |
||||
* https://www.openssl.org/source/license.html
|
||||
*/ |
||||
|
||||
#include <openssl/base64.h> |
||||
|
||||
#include <assert.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
#include "../internal.h" |
||||
|
||||
|
||||
// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t|
|
||||
// arguments for a slightly simpler implementation.
|
||||
static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) { |
||||
crypto_word_t aw = a; |
||||
crypto_word_t bw = b; |
||||
// |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same
|
||||
// MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1.
|
||||
return constant_time_msb_w(aw - bw); |
||||
} |
||||
|
||||
// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max|
|
||||
// and |CONSTTIME_FALSE_8| otherwise.
|
||||
static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min, |
||||
uint8_t max) { |
||||
a -= min; |
||||
return constant_time_lt_args_8(a, max - min + 1); |
||||
} |
||||
|
||||
// Encoding.
|
||||
|
||||
static uint8_t conv_bin2ascii(uint8_t a) { |
||||
// Since PEM is sometimes used to carry private keys, we encode base64 data
|
||||
// itself in constant-time.
|
||||
a &= 0x3f; |
||||
uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/'); |
||||
ret = |
||||
constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret); |
||||
ret = |
||||
constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret); |
||||
ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret); |
||||
return ret; |
||||
} |
||||
|
||||
static_assert(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0, |
||||
"data length must be a multiple of base64 chunk size"); |
||||
|
||||
int EVP_EncodedLength(size_t *out_len, size_t len) { |
||||
if (len + 2 < len) { |
||||
return 0; |
||||
} |
||||
len += 2; |
||||
len /= 3; |
||||
|
||||
if (((len << 2) >> 2) != len) { |
||||
return 0; |
||||
} |
||||
len <<= 2; |
||||
|
||||
if (len + 1 < len) { |
||||
return 0; |
||||
} |
||||
len++; |
||||
|
||||
*out_len = len; |
||||
return 1; |
||||
} |
||||
|
||||
EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) { |
||||
return reinterpret_cast<EVP_ENCODE_CTX *>( |
||||
OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX))); |
||||
} |
||||
|
||||
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) { OPENSSL_free(ctx); } |
||||
|
||||
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) { |
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); |
||||
} |
||||
|
||||
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, |
||||
const uint8_t *in, size_t in_len) { |
||||
size_t total = 0; |
||||
|
||||
*out_len = 0; |
||||
if (in_len == 0) { |
||||
return; |
||||
} |
||||
|
||||
assert(ctx->data_used < sizeof(ctx->data)); |
||||
|
||||
if (sizeof(ctx->data) - ctx->data_used > in_len) { |
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len); |
||||
ctx->data_used += (unsigned)in_len; |
||||
return; |
||||
} |
||||
|
||||
if (ctx->data_used != 0) { |
||||
const size_t todo = sizeof(ctx->data) - ctx->data_used; |
||||
OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo); |
||||
in += todo; |
||||
in_len -= todo; |
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data)); |
||||
ctx->data_used = 0; |
||||
|
||||
out += encoded; |
||||
*(out++) = '\n'; |
||||
*out = '\0'; |
||||
|
||||
total = encoded + 1; |
||||
} |
||||
|
||||
while (in_len >= sizeof(ctx->data)) { |
||||
size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data)); |
||||
in += sizeof(ctx->data); |
||||
in_len -= sizeof(ctx->data); |
||||
|
||||
out += encoded; |
||||
*(out++) = '\n'; |
||||
*out = '\0'; |
||||
|
||||
if (total + encoded + 1 < total) { |
||||
*out_len = 0; |
||||
return; |
||||
} |
||||
|
||||
total += encoded + 1; |
||||
} |
||||
|
||||
if (in_len != 0) { |
||||
OPENSSL_memcpy(ctx->data, in, in_len); |
||||
} |
||||
|
||||
ctx->data_used = (unsigned)in_len; |
||||
|
||||
if (total > INT_MAX) { |
||||
// We cannot signal an error, but we can at least avoid making *out_len
|
||||
// negative.
|
||||
total = 0; |
||||
} |
||||
*out_len = (int)total; |
||||
} |
||||
|
||||
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { |
||||
if (ctx->data_used == 0) { |
||||
*out_len = 0; |
||||
return; |
||||
} |
||||
|
||||
size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used); |
||||
out[encoded++] = '\n'; |
||||
out[encoded] = '\0'; |
||||
ctx->data_used = 0; |
||||
|
||||
// ctx->data_used is bounded by sizeof(ctx->data), so this does not
|
||||
// overflow.
|
||||
assert(encoded <= INT_MAX); |
||||
*out_len = (int)encoded; |
||||
} |
||||
|
||||
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { |
||||
uint32_t l; |
||||
size_t remaining = src_len, ret = 0; |
||||
|
||||
while (remaining) { |
||||
if (remaining >= 3) { |
||||
l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2]; |
||||
*(dst++) = conv_bin2ascii(l >> 18L); |
||||
*(dst++) = conv_bin2ascii(l >> 12L); |
||||
*(dst++) = conv_bin2ascii(l >> 6L); |
||||
*(dst++) = conv_bin2ascii(l); |
||||
remaining -= 3; |
||||
} else { |
||||
l = ((uint32_t)src[0]) << 16L; |
||||
if (remaining == 2) { |
||||
l |= ((uint32_t)src[1] << 8L); |
||||
} |
||||
|
||||
*(dst++) = conv_bin2ascii(l >> 18L); |
||||
*(dst++) = conv_bin2ascii(l >> 12L); |
||||
*(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L); |
||||
*(dst++) = '='; |
||||
remaining = 0; |
||||
} |
||||
ret += 4; |
||||
src += 3; |
||||
} |
||||
|
||||
*dst = '\0'; |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
// Decoding.
|
||||
|
||||
int EVP_DecodedLength(size_t *out_len, size_t len) { |
||||
if (len % 4 != 0) { |
||||
return 0; |
||||
} |
||||
|
||||
*out_len = (len / 4) * 3; |
||||
return 1; |
||||
} |
||||
|
||||
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { |
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX)); |
||||
} |
||||
|
||||
static uint8_t base64_ascii_to_bin(uint8_t a) { |
||||
// Since PEM is sometimes used to carry private keys, we decode base64 data
|
||||
// itself in constant-time.
|
||||
const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z'); |
||||
const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z'); |
||||
const uint8_t is_digit = constant_time_in_range_8(a, '0', '9'); |
||||
const uint8_t is_plus = constant_time_eq_8(a, '+'); |
||||
const uint8_t is_slash = constant_time_eq_8(a, '/'); |
||||
const uint8_t is_equals = constant_time_eq_8(a, '='); |
||||
|
||||
uint8_t ret = 0; |
||||
ret |= is_upper & (a - 'A'); // [0,26)
|
||||
ret |= is_lower & (a - 'a' + 26); // [26,52)
|
||||
ret |= is_digit & (a - '0' + 52); // [52,62)
|
||||
ret |= is_plus & 62; |
||||
ret |= is_slash & 63; |
||||
// Invalid inputs, 'A', and '=' have all been mapped to zero. Map invalid
|
||||
// inputs to 0xff. Note '=' is padding and handled separately by the caller.
|
||||
const uint8_t is_valid = |
||||
is_upper | is_lower | is_digit | is_plus | is_slash | is_equals; |
||||
ret |= ~is_valid; |
||||
return ret; |
||||
} |
||||
|
||||
// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
|
||||
// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
|
||||
// number of bytes written, which will be less than three if the quad ended
|
||||
// with padding. It returns one on success or zero on error.
|
||||
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, |
||||
const uint8_t *in) { |
||||
const uint8_t a = base64_ascii_to_bin(in[0]); |
||||
const uint8_t b = base64_ascii_to_bin(in[1]); |
||||
const uint8_t c = base64_ascii_to_bin(in[2]); |
||||
const uint8_t d = base64_ascii_to_bin(in[3]); |
||||
if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) { |
||||
return 0; |
||||
} |
||||
|
||||
const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 | |
||||
((uint32_t)c) << 6 | (uint32_t)d; |
||||
|
||||
const unsigned padding_pattern = (in[0] == '=') << 3 | //
|
||||
(in[1] == '=') << 2 | //
|
||||
(in[2] == '=') << 1 | //
|
||||
(in[3] == '='); |
||||
|
||||
// In presence of padding, the lowest bits of v are unused. Canonical encoding
|
||||
// (RFC 4648, section 3.5) requires that these bits all be set to zero. Common
|
||||
// PEM parsers accept noncanonical base64, adding to the malleability of the
|
||||
// format. This decoder follows OpenSSL's and Go's PEM parsers and accepts it.
|
||||
switch (padding_pattern) { |
||||
case 0: |
||||
// The common case of no padding.
|
||||
*out_num_bytes = 3; |
||||
out[0] = v >> 16; |
||||
out[1] = v >> 8; |
||||
out[2] = v; |
||||
break; |
||||
|
||||
case 1: // xxx=
|
||||
*out_num_bytes = 2; |
||||
out[0] = v >> 16; |
||||
out[1] = v >> 8; |
||||
break; |
||||
|
||||
case 3: // xx==
|
||||
*out_num_bytes = 1; |
||||
out[0] = v >> 16; |
||||
break; |
||||
|
||||
default: |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len, |
||||
const uint8_t *in, size_t in_len) { |
||||
*out_len = 0; |
||||
|
||||
if (ctx->error_encountered) { |
||||
return -1; |
||||
} |
||||
|
||||
size_t bytes_out = 0, i; |
||||
for (i = 0; i < in_len; i++) { |
||||
const char c = in[i]; |
||||
switch (c) { |
||||
case ' ': |
||||
case '\t': |
||||
case '\r': |
||||
case '\n': |
||||
continue; |
||||
} |
||||
|
||||
if (ctx->eof_seen) { |
||||
ctx->error_encountered = 1; |
||||
return -1; |
||||
} |
||||
|
||||
ctx->data[ctx->data_used++] = c; |
||||
if (ctx->data_used == 4) { |
||||
size_t num_bytes_resulting; |
||||
if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) { |
||||
ctx->error_encountered = 1; |
||||
return -1; |
||||
} |
||||
|
||||
ctx->data_used = 0; |
||||
bytes_out += num_bytes_resulting; |
||||
out += num_bytes_resulting; |
||||
|
||||
if (num_bytes_resulting < 3) { |
||||
ctx->eof_seen = 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (bytes_out > INT_MAX) { |
||||
ctx->error_encountered = 1; |
||||
*out_len = 0; |
||||
return -1; |
||||
} |
||||
*out_len = (int)bytes_out; |
||||
|
||||
if (ctx->eof_seen) { |
||||
return 0; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) { |
||||
*out_len = 0; |
||||
if (ctx->error_encountered || ctx->data_used != 0) { |
||||
return -1; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out, |
||||
const uint8_t *in, size_t in_len) { |
||||
*out_len = 0; |
||||
|
||||
if (in_len % 4 != 0) { |
||||
return 0; |
||||
} |
||||
|
||||
size_t max_len; |
||||
if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) { |
||||
return 0; |
||||
} |
||||
|
||||
size_t i, bytes_out = 0; |
||||
for (i = 0; i < in_len; i += 4) { |
||||
size_t num_bytes_resulting; |
||||
|
||||
if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) { |
||||
return 0; |
||||
} |
||||
|
||||
bytes_out += num_bytes_resulting; |
||||
out += num_bytes_resulting; |
||||
if (num_bytes_resulting != 3 && i != in_len - 4) { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
*out_len = bytes_out; |
||||
return 1; |
||||
} |
||||
|
||||
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) { |
||||
// Trim spaces and tabs from the beginning of the input.
|
||||
while (src_len > 0) { |
||||
if (src[0] != ' ' && src[0] != '\t') { |
||||
break; |
||||
} |
||||
|
||||
src++; |
||||
src_len--; |
||||
} |
||||
|
||||
// Trim newlines, spaces and tabs from the end of the line.
|
||||
while (src_len > 0) { |
||||
switch (src[src_len - 1]) { |
||||
case ' ': |
||||
case '\t': |
||||
case '\r': |
||||
case '\n': |
||||
src_len--; |
||||
continue; |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
size_t dst_len; |
||||
if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX || |
||||
!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) { |
||||
return -1; |
||||
} |
||||
|
||||
// EVP_DecodeBlock does not take padding into account, so put the
|
||||
// NULs back in... so the caller can strip them back out.
|
||||
while (dst_len % 3 != 0) { |
||||
dst[dst_len++] = '\0'; |
||||
} |
||||
assert(dst_len <= INT_MAX); |
||||
|
||||
return (int)dst_len; |
||||
} |
@ -1,119 +0,0 @@ |
||||
/* Copyright 2024 The BoringSSL Authors
|
||||
* |
||||
* 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_CRYPTO_BCM_SUPPORT_H |
||||
#define OPENSSL_HEADER_CRYPTO_BCM_SUPPORT_H |
||||
|
||||
#include <openssl/base.h> |
||||
|
||||
#include <stdio.h> |
||||
|
||||
// Provided by libcrypto, called from BCM
|
||||
|
||||
#if defined(__cplusplus) |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#if defined(OPENSSL_LINUX) |
||||
// On linux we use MADVISE instead of pthread_atfork(), due
|
||||
// to concerns about clone() being used for address space
|
||||
// duplication.
|
||||
#define OPENSSL_FORK_DETECTION |
||||
#define OPENSSL_FORK_DETECTION_MADVISE |
||||
#elif defined(OPENSSL_MACOS) || defined(OPENSSL_IOS) || \ |
||||
defined(OPENSSL_OPENBSD) || defined(OPENSSL_FREEBSD) |
||||
// These platforms may detect address space duplication with pthread_atfork.
|
||||
// iOS doesn't normally allow fork in apps, but it's there.
|
||||
#define OPENSSL_FORK_DETECTION |
||||
#define OPENSSL_FORK_DETECTION_PTHREAD_ATFORK |
||||
#elif defined(OPENSSL_WINDOWS) || defined(OPENSSL_TRUSTY) || \ |
||||
defined(__ZEPHYR__) || defined(CROS_EC) |
||||
// These platforms do not fork.
|
||||
#define OPENSSL_DOES_NOT_FORK |
||||
#endif |
||||
|
||||
#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) |
||||
#define OPENSSL_RAND_DETERMINISTIC |
||||
#elif defined(OPENSSL_TRUSTY) |
||||
#define OPENSSL_RAND_TRUSTY |
||||
#elif defined(OPENSSL_WINDOWS) |
||||
#define OPENSSL_RAND_WINDOWS |
||||
#elif defined(OPENSSL_LINUX) |
||||
#define OPENSSL_RAND_URANDOM |
||||
#elif defined(OPENSSL_APPLE) && !defined(OPENSSL_MACOS) |
||||
// Unlike macOS, iOS and similar hide away getentropy().
|
||||
#define OPENSSL_RAND_IOS |
||||
#else |
||||
// By default if you are integrating BoringSSL we expect you to
|
||||
// provide getentropy from the <unistd.h> header file.
|
||||
#define OPENSSL_RAND_GETENTROPY |
||||
#endif |
||||
|
||||
// Provided by libcrypto, called from BCM
|
||||
|
||||
// CRYPTO_init_sysrand initializes long-lived resources needed to draw entropy
|
||||
// from the operating system, if the operating system requires initialization.
|
||||
void CRYPTO_init_sysrand(void); |
||||
|
||||
// CRYPTO_sysrand fills |len| bytes at |buf| with entropy from the operating
|
||||
// system.
|
||||
void CRYPTO_sysrand(uint8_t *buf, size_t len); |
||||
|
||||
// CRYPTO_sysrand_if_available fills |len| bytes at |buf| with entropy from the
|
||||
// operating system, or early /dev/urandom data, and returns 1, _if_ the entropy
|
||||
// pool is initialized or if getrandom() is not available and not in FIPS mode.
|
||||
// Otherwise it will not block and will instead fill |buf| with all zeros and
|
||||
// return 0.
|
||||
int CRYPTO_sysrand_if_available(uint8_t *buf, size_t len); |
||||
|
||||
// CRYPTO_sysrand_for_seed fills |len| bytes at |buf| with entropy from the
|
||||
// operating system. It may draw from the |GRND_RANDOM| pool on Android,
|
||||
// depending on the vendor's configuration.
|
||||
void CRYPTO_sysrand_for_seed(uint8_t *buf, size_t len); |
||||
|
||||
// RAND_need_entropy is called whenever the BCM module has stopped because it
|
||||
// has run out of entropy.
|
||||
void RAND_need_entropy(size_t bytes_needed); |
||||
|
||||
// crypto_get_fork_generation returns the fork generation number for the current
|
||||
// process, or zero if not supported on the platform. The fork generation number
|
||||
// is a non-zero, strictly-monotonic counter with the property that, if queried
|
||||
// in an address space and then again in a subsequently forked copy, the forked
|
||||
// address space will observe a greater value.
|
||||
//
|
||||
// This function may be used to clear cached values across a fork. When
|
||||
// initializing a cache, record the fork generation. Before using the cache,
|
||||
// check if the fork generation has changed. If so, drop the cache and update
|
||||
// the save fork generation. Note this logic transparently handles platforms
|
||||
// which always return zero.
|
||||
//
|
||||
// This is not reliably supported on all platforms which implement |fork|, so it
|
||||
// should only be used as a hardening measure.
|
||||
OPENSSL_EXPORT uint64_t CRYPTO_get_fork_generation(void); |
||||
|
||||
// CRYPTO_fork_detect_force_madv_wipeonfork_for_testing is an internal detail
|
||||
// used for testing purposes.
|
||||
OPENSSL_EXPORT void CRYPTO_fork_detect_force_madv_wipeonfork_for_testing( |
||||
int on); |
||||
|
||||
// CRYPTO_get_stderr returns stderr. This function exists to avoid BCM needing
|
||||
// a data dependency on libc.
|
||||
FILE *CRYPTO_get_stderr(void); |
||||
|
||||
|
||||
#if defined(__cplusplus) |
||||
} // extern C
|
||||
#endif |
||||
|
||||
#endif // OPENSSL_HEADER_CRYPTO_BCM_SUPPORT_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue