chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"b222fef140d597c2936a7a55613c73c393992ed88c84f63ec461e7f29a7ba528","Cargo.lock":"c05be5a858c08c3fd6e0843ea6757c8eaaa9426561f4996f2cec6a3e4efed472","Cargo.toml":"3717cf4d56d306ecf967653857cd0d71ed044d998c1c506ca93420dea21e44ea","Cargo.toml.orig":"0028334f98d10df6559fcb5559f94267ed39432b20dc290e3b95b7f143082513","LICENSE-APACHE":"45fd05c4865e7c350b98ad7ac50e1b15462d49af4a91e9b0c9dd933dc9a69742","LICENSE-MIT":"9117d922e667125508dde62b02c1f57ed22f5ad21eb536aa2e2d99e1c796e639","README.md":"52ab92f5b204b89f9ad02b778ca2b6ad6d32c7f94916e1917dae4e95569d0b92","src/alg_id.rs":"16ad8158a1d9ac992262ba0dd6c63dcefa64930de4d1c0ce229d7e78ce7ad8b3","src/base64.rs":"b72362a35405bde9709ff31e6e96689d19f2bc593c0ee08f5e9f452d8d647479","src/data/README.md":"a20436d042d01819b65817bde6872147da740ac726016bdd6121a3f773b8ceb3","src/data/alg-ecdsa-p256.der":"431ab0da5859f972141d7a6b17bfff1006ec2465878890eecacf4764748f999a","src/data/alg-ecdsa-p256k1.der":"00905fc68a9ba09041e71c6f12869f8e9d4cb3adfd90d8439f540e7ccf516dcd","src/data/alg-ecdsa-p384.der":"a6307e2efeff1b4db45622b626b9a0f2b6395be5dd4024a899c057e512a0207e","src/data/alg-ecdsa-p521.der":"1fe6d1f888400adc8b5775a63d1e2738246eec45c36bf0cd3060eb1c420b4cc2","src/data/alg-ecdsa-sha256.der":"8748ad98184c8f81b5db874ef1b7d3599afe05e2f92dac215a77f45e9b0699bc","src/data/alg-ecdsa-sha384.der":"5f6e0dc69f6930ca890ebcafaf7677254640b931439cd5bcad7688b1a06aaf92","src/data/alg-ecdsa-sha512.der":"c09d17b3609dc0987bc81b2b990f9a461697aea0258fb565501da4f2c8caf6f0","src/data/alg-ed25519.der":"0b6d661fe75a1ce7a832d515b39b504032f1a6cbb67a5113fa74d635d038f4d9","src/data/alg-ed448.der":"173f629fc725926a0af1bff26907a3850e19e9a2763fa7f3bea3f2ff8319a2f0","src/data/alg-ml-dsa-44.der":"cc050f14a811907c1c1186ce00447580344e379ff7679ab7359beefbeeac5c13","src/data/alg-ml-dsa-65.der":"f7ab8e2df130b24fed009839ca3f961ebbcbe3a567e591c2354fe397f849f861","src/data/alg-ml-dsa-87.der":"2a3fe7ce00d5707ae6ec5d310dd648050599a94b27baa02f6daac72b9cf553a0","src/data/alg-rsa-encryption.der":"7bc023427767a2f2e156f8ae030d06d19f862e326b952116649b423c3ff7110e","src/data/alg-rsa-pkcs1-sha256.der":"c0d1c5108d05adfdf58c73697af5c4e644d1a09fb2e4a76361c048eb0ec7a219","src/data/alg-rsa-pkcs1-sha384.der":"d3e50513620bac7e02f5c1821c569cf4fc2ca5a891fd1103e36574c77e6a888a","src/data/alg-rsa-pkcs1-sha512.der":"3705399877ad5d5bb559e5b5ed3cd80b352166511c2fd2b8f8959e1176ed72f8","src/data/alg-rsa-pss-sha256.der":"6eeb65499d8c64c3ef3e74305f2daaca0d947e7fca735ad072b5581392d73068","src/data/alg-rsa-pss-sha384.der":"b6e27adae679feb8f49925f4457da316657a6b7a55a1bfd164c66eec59d7d090","src/data/alg-rsa-pss-sha512.der":"60cea04c0dcb23c248eb644fe036d1b6b883004f73c68785895c885c8fa5d688","src/lib.rs":"8946e5024c684256e15418bffed2aaa553befcc6270b098db293fb67e0a8e25d","src/pem.rs":"0da320e26748162dd7d02df043c911155eb498307a27ec543bd7e00baaed4b77","src/server_name.rs":"87ae29a98c974bad006e71a0dba41d8b764615c97dc7855f65c3adf954ad81f1"},"package":"be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"}

View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "b829c966d2fcda87f2687af107051ae4770bef50"
},
"path_in_vcs": ""
}

195
vendor/rustls-pki-types/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,195 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bumpalo"
version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "cc"
version = "1.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
dependencies = [
"jobserver",
"libc",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crabgrind"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdbd43e4f32a9681a504577db2d4ea7d3f7b1bf2e97955561af98501ab600508"
dependencies = [
"cc",
]
[[package]]
name = "jobserver"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "once_cell"
version = "1.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
[[package]]
name = "proc-macro2"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustls-pki-types"
version = "1.14.0"
dependencies = [
"crabgrind",
"web-time",
"zeroize",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-time"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

86
vendor/rustls-pki-types/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,86 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.60"
name = "rustls-pki-types"
version = "1.14.0"
build = false
include = [
"Cargo.toml",
"LICENSE-APACHE",
"LICENSE-MIT",
"src/**/*.rs",
"README.md",
"src/data/*.der",
]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Shared types for the rustls PKI ecosystem"
homepage = "https://github.com/rustls/pki-types"
documentation = "https://docs.rs/rustls-pki-types"
readme = "README.md"
categories = [
"network-programming",
"data-structures",
"cryptography",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rustls/pki-types"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"rustls_pki_types_docsrs",
]
[package.metadata.cargo_check_external_types]
allowed_external_types = ["zeroize::Zeroize"]
[features]
alloc = ["dep:zeroize"]
default = ["alloc"]
std = ["alloc"]
web = ["web-time"]
[lib]
name = "rustls_pki_types"
path = "src/lib.rs"
[dependencies.zeroize]
version = "1"
optional = true
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies.web-time]
version = "1"
optional = true
[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dev-dependencies.crabgrind]
version = "=0.1.9"
[lints.rust]
elided_lifetimes_in_paths = "warn"
trivial_numeric_casts = "warn"
unnameable_types = "warn"
unreachable_pub = "warn"
unused_extern_crates = "warn"
unused_import_braces = "warn"
unused_qualifications = "warn"
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ["cfg(rustls_pki_types_docsrs)"]

201
vendor/rustls-pki-types/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023 Dirkjan Ochtman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
vendor/rustls-pki-types/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2023 Dirkjan Ochtman <dirkjan@ochtman.nl>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

53
vendor/rustls-pki-types/README.md vendored Normal file
View File

@@ -0,0 +1,53 @@
# rustls-pki-types
[![Build Status](https://github.com/rustls/pki-types/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/rustls/pki-types/actions/workflows/ci.yml?query=branch%3Amain)
[![Documentation](https://docs.rs/rustls-pki-types/badge.svg)](https://docs.rs/rustls-pki-types/)
[![Chat](https://img.shields.io/discord/976380008299917365?logo=discord)](https://discord.gg/MCSB76RU96)
This crate provides types for representing X.509 certificates, keys and other types as commonly
used in the rustls ecosystem. It is intended to be used by crates that need to work with such X.509
types, such as [rustls](https://crates.io/crates/rustls),
[rustls-webpki](https://crates.io/crates/rustls-webpki),
and others.
Some of these crates used to define their own trivial wrappers around DER-encoded bytes.
However, in order to avoid inconvenient dependency edges, these were all disconnected. By
using a common low-level crate of types with long-term stable API, we hope to avoid the
downsides of unnecessary dependency edges while providing interoperability between crates.
## Features
- Interoperability between different crates in the rustls ecosystem
- Long-term stable API
- No dependencies
- Support for `no_std` contexts, with optional support for `alloc`
## DER and PEM
Many of the types defined in this crate represent DER-encoded data. DER is a binary encoding of
the ASN.1 format commonly used in web PKI specifications. It is a binary encoding, so it is
relatively compact when stored in memory. However, as a binary format, it is not very easy to
work with for humans and in contexts where binary data is inconvenient. For this reason,
many tools and protocols use a ASCII-based encoding of DER, called PEM. In addition to the
base64-encoded DER, PEM objects are delimited by header and footer lines which indicate the type
of object contained in the PEM blob.
This crate's types can be created from both DER and PEM encodings.
## Creating new certificates and keys
This crate does not provide any functionality for creating new certificates or keys. However,
the [rcgen](https://docs.rs/rcgen) crate can be used to create new certificates and keys.
## Cloning private keys
This crate intentionally **does not** implement `Clone` on private key types in
order to minimize the exposure of private key data in memory.
If you want to extend the lifetime of a `PrivateKeyDer<'_>`, consider [`PrivateKeyDer::clone_key()`].
Alternatively since these types are immutable, consider wrapping the `PrivateKeyDer<'_>` in a [`Rc`]
or an [`Arc`].
[`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
[`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
[`PrivateKeyDer::clone_key()`]: https://docs.rs/rustls-pki-types/latest/rustls_pki_types/enum.PrivateKeyDer.html#method.clone_key

395
vendor/rustls-pki-types/src/alg_id.rs vendored Normal file
View File

@@ -0,0 +1,395 @@
//! The PKIX [`AlgorithmIdentifier`] type, and common values.
//!
//! If you need to use an [`AlgorithmIdentifier`] not defined here,
//! you can define it locally.
use core::fmt;
use core::ops::Deref;
// See src/data/README.md.
/// AlgorithmIdentifier for `id-ml-dsa-44`.
///
/// This is:
///
/// ```text
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.3.17 }
/// ```
///
/// <https://www.ietf.org/archive/id/draft-ietf-lamps-dilithium-certificates-07.html#name-identifiers>
pub const ML_DSA_44: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ml-dsa-44.der"));
/// AlgorithmIdentifier for `id-ml-dsa-65`.
///
/// This is:
///
/// ```text
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.3.18 }
/// ```
///
/// <https://www.ietf.org/archive/id/draft-ietf-lamps-dilithium-certificates-07.html#name-identifiers>
pub const ML_DSA_65: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ml-dsa-65.der"));
/// AlgorithmIdentifier for `id-ml-dsa-87`.
///
/// This is:
///
/// ```text
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.3.19 }
/// ```
///
/// <https://www.ietf.org/archive/id/draft-ietf-lamps-dilithium-certificates-07.html#name-identifiers>
pub const ML_DSA_87: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ml-dsa-87.der"));
/// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp256k1`.
///
/// This is:
///
/// ```text
/// # ecPublicKey
/// OBJECT_IDENTIFIER { 1.2.840.10045.2.1 }
/// # secp256k1
/// OBJECT_IDENTIFIER { 1.3.132.0.10 }
/// ```
pub const ECDSA_P256K1: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p256k1.der"));
/// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp256r1`.
///
/// This is:
///
/// ```text
/// # ecPublicKey
/// OBJECT_IDENTIFIER { 1.2.840.10045.2.1 }
/// # secp256r1
/// OBJECT_IDENTIFIER { 1.2.840.10045.3.1.7 }
/// ```
pub const ECDSA_P256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p256.der"));
/// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp384r1`.
///
/// This is:
///
/// ```text
/// # ecPublicKey
/// OBJECT_IDENTIFIER { 1.2.840.10045.2.1 }
/// # secp384r1
/// OBJECT_IDENTIFIER { 1.3.132.0.34 }
/// ```
pub const ECDSA_P384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p384.der"));
/// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp521r1`.
///
/// This is:
///
/// ```text
/// # ecPublicKey
/// OBJECT_IDENTIFIER { 1.2.840.10045.2.1 }
/// # secp521r1
/// OBJECT_IDENTIFIER { 1.3.132.0.35 }
/// ```
pub const ECDSA_P521: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p521.der"));
/// AlgorithmIdentifier for `ecdsa-with-SHA256`.
///
/// This is:
///
/// ```text
/// # ecdsa-with-SHA256
/// OBJECT_IDENTIFIER { 1.2.840.10045.4.3.2 }
/// ```
pub const ECDSA_SHA256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha256.der"));
/// AlgorithmIdentifier for `ecdsa-with-SHA384`.
///
/// This is:
///
/// ```text
/// # ecdsa-with-SHA384
/// OBJECT_IDENTIFIER { 1.2.840.10045.4.3.3 }
/// ```
pub const ECDSA_SHA384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha384.der"));
/// AlgorithmIdentifier for `ecdsa-with-SHA512`.
///
/// This is:
///
/// ```text
/// # ecdsa-with-SHA512
/// OBJECT_IDENTIFIER { 1.2.840.10045.4.3.4 }
/// ```
pub const ECDSA_SHA512: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha512.der"));
/// AlgorithmIdentifier for `rsaEncryption`.
///
/// This is:
///
/// ```text
/// # rsaEncryption
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.1 }
/// NULL {}
/// ```
pub const RSA_ENCRYPTION: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-encryption.der"));
/// AlgorithmIdentifier for `sha256WithRSAEncryption`.
///
/// This is:
///
/// ```text
/// # sha256WithRSAEncryption
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.11 }
/// NULL {}
/// ```
pub const RSA_PKCS1_SHA256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha256.der"));
/// AlgorithmIdentifier for `sha384WithRSAEncryption`.
///
/// This is:
///
/// ```text
/// # sha384WithRSAEncryption
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.12 }
/// NULL {}
/// ```
pub const RSA_PKCS1_SHA384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha384.der"));
/// AlgorithmIdentifier for `sha512WithRSAEncryption`.
///
/// This is:
///
/// ```text
/// # sha512WithRSAEncryption
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.13 }
/// NULL {}
/// ```
pub const RSA_PKCS1_SHA512: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha512.der"));
/// AlgorithmIdentifier for `rsassaPss` with:
///
/// - hashAlgorithm: sha256
/// - maskGenAlgorithm: mgf1 with sha256
/// - saltLength: 32
///
/// This is:
///
/// ```text
/// # rsassa-pss
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.10 }
/// SEQUENCE {
/// # hashAlgorithm:
/// [0] {
/// SEQUENCE {
/// # sha256
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.2.1 }
/// NULL {}
/// }
/// }
/// # maskGenAlgorithm:
/// [1] {
/// SEQUENCE {
/// # mgf1
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.8 }
/// SEQUENCE {
/// # sha256
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.2.1 }
/// NULL {}
/// }
/// }
/// }
/// # saltLength:
/// [2] {
/// INTEGER { 32 }
/// }
/// }
/// ```
///
/// See <https://datatracker.ietf.org/doc/html/rfc4055#section-3.1> for
/// the meaning of the context-specific tags.
pub const RSA_PSS_SHA256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha256.der"));
/// AlgorithmIdentifier for `rsassaPss` with:
///
/// - hashAlgorithm: sha384
/// - maskGenAlgorithm: mgf1 with sha384
/// - saltLength: 48
///
/// This is:
///
/// ```text
/// # rsassa-pss
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.10 }
/// SEQUENCE {
/// # hashAlgorithm:
/// [0] {
/// SEQUENCE {
/// # sha384
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.2.2 }
/// NULL {}
/// }
/// }
/// # maskGenAlgorithm:
/// [1] {
/// SEQUENCE {
/// # mgf1
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.8 }
/// SEQUENCE {
/// # sha384
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.2.2 }
/// NULL {}
/// }
/// }
/// }
/// # saltLength:
/// [2] {
/// INTEGER { 48 }
/// }
/// }
/// ```
///
/// See <https://datatracker.ietf.org/doc/html/rfc4055#section-3.1> for
/// the meaning of the context-specific tags.
pub const RSA_PSS_SHA384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha384.der"));
/// AlgorithmIdentifier for `rsassaPss` with:
///
/// - hashAlgorithm: sha512
/// - maskGenAlgorithm: mgf1 with sha512
/// - saltLength: 64
///
/// This is:
///
/// ```text
/// # rsassa-pss
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.10 }
/// SEQUENCE {
/// # hashAlgorithm:
/// [0] {
/// SEQUENCE {
/// # sha512
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.2.3 }
/// NULL {}
/// }
/// }
/// # maskGenAlgorithm:
/// [1] {
/// SEQUENCE {
/// # mgf1
/// OBJECT_IDENTIFIER { 1.2.840.113549.1.1.8 }
/// SEQUENCE {
/// # sha512
/// OBJECT_IDENTIFIER { 2.16.840.1.101.3.4.2.3 }
/// NULL {}
/// }
/// }
/// }
/// # saltLength:
/// [2] {
/// INTEGER { 64 }
/// }
/// }
/// ```
///
/// See <https://datatracker.ietf.org/doc/html/rfc4055#section-3.1> for
/// the meaning of the context-specific tags.
pub const RSA_PSS_SHA512: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha512.der"));
/// AlgorithmIdentifier for `ED25519`.
///
/// This is:
///
/// ```text
/// # ed25519
/// OBJECT_IDENTIFIER { 1.3.101.112 }
/// ```
pub const ED25519: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ed25519.der"));
/// AlgorithmIdentifier for `ED448`.
///
/// This is:
///
/// ```text
/// # ed448
/// OBJECT_IDENTIFIER { 1.3.101.113 }
/// ```
pub const ED448: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ed448.der"));
/// A DER encoding of the PKIX AlgorithmIdentifier type:
///
/// ```ASN.1
/// AlgorithmIdentifier ::= SEQUENCE {
/// algorithm OBJECT IDENTIFIER,
/// parameters ANY DEFINED BY algorithm OPTIONAL }
/// -- contains a value of the type
/// -- registered for use with the
/// -- algorithm object identifier value
/// ```
/// (from <https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.2>)
///
/// The outer sequence encoding is *not included*, so this is the DER encoding
/// of an OID for `algorithm` plus the `parameters` value.
///
/// For example, this is the `rsaEncryption` algorithm (but prefer to use the constant
/// [`RSA_ENCRYPTION`] instead):
///
/// ```
/// let rsa_encryption = rustls_pki_types::AlgorithmIdentifier::from_slice(
/// &[
/// // algorithm: 1.2.840.113549.1.1.1
/// 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
/// // parameters: NULL
/// 0x05, 0x00
/// ]
/// );
/// assert_eq!(rustls_pki_types::alg_id::RSA_ENCRYPTION, rsa_encryption);
/// ```
///
/// Common values for this type are provided in this module.
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct AlgorithmIdentifier(&'static [u8]);
impl AlgorithmIdentifier {
/// Makes a new `AlgorithmIdentifier` from a static octet slice.
///
/// This does not validate the contents of the slice.
pub const fn from_slice(bytes: &'static [u8]) -> Self {
Self(bytes)
}
}
impl AsRef<[u8]> for AlgorithmIdentifier {
fn as_ref(&self) -> &[u8] {
self.0
}
}
impl fmt::Debug for AlgorithmIdentifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
super::hex(f, self.0)
}
}
impl Deref for AlgorithmIdentifier {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}

750
vendor/rustls-pki-types/src/base64.rs vendored Normal file
View File

@@ -0,0 +1,750 @@
/// Decode base64 `input`, writing the result into `output`.
///
/// `input` is treated as secret, so efforts are made to avoid
/// leaking its value via side channels, such as timing,
/// memory accesses, and execution trace.
///
/// The following is deemed non-secret information:
///
/// - Appearance of whitespace in `input`
/// - Erroneous characters in `input` (indeed, the first illegal
/// character is quoted in the error type)
/// - The length of `input`
/// - The length of `output`
///
/// Returns the prefix of `output` that was written to.
pub(crate) fn decode_secret<'a>(input: &[u8], output: &'a mut [u8]) -> Result<&'a [u8], Error> {
decode(input, output, CodePoint::decode_secret)
}
/// Decode base64 `input`, writing the result into `output`.
///
/// `input` is treated as public information, so its value may
/// be leaked via side channels.
///
/// Returns the prefix of `output` that was written to.
pub(crate) fn decode_public<'a>(input: &[u8], output: &'a mut [u8]) -> Result<&'a [u8], Error> {
decode(input, output, CodePoint::decode_public)
}
/// Provide an upper limit on how much space could be required
/// to decode a base64 encoding of len `base64_len`.
pub(crate) const fn decoded_length(base64_len: usize) -> usize {
((base64_len + 3) / 4) * 3
}
fn decode<'a>(
input: &[u8],
output: &'a mut [u8],
decode_byte: impl Fn(u8) -> CodePoint,
) -> Result<&'a [u8], Error> {
let mut buffer = 0u64;
let mut used = 0;
let mut shift = SHIFT_INITIAL;
let mut pad_mask = 0;
let mut output_offset = 0;
const SHIFT_INITIAL: i32 = (8 - 1) * 6;
for byte in input.iter().copied() {
let (item, pad) = match decode_byte(byte) {
CodePoint::WHITESPACE => continue,
CodePoint::INVALID => return Err(Error::InvalidCharacter(byte)),
CodePoint::PAD => (0, 1),
CodePoint(n) => (n, 0),
};
// we collect 8 code points (therefore: 6 output bytes) into
// `buffer`. this keeps this loop as tight as possible.
if used == 8 {
if pad_mask != 0b0000_0000 {
return Err(Error::PrematurePadding);
}
let chunk = output
.get_mut(output_offset..output_offset + 6)
.ok_or(Error::InsufficientOutputSpace)?;
chunk[0] = (buffer >> 40) as u8;
chunk[1] = (buffer >> 32) as u8;
chunk[2] = (buffer >> 24) as u8;
chunk[3] = (buffer >> 16) as u8;
chunk[4] = (buffer >> 8) as u8;
chunk[5] = buffer as u8;
output_offset += 6;
buffer = 0;
used = 0;
pad_mask = 0;
shift = SHIFT_INITIAL;
}
buffer |= (item as u64) << shift;
shift -= 6;
pad_mask |= pad << used;
used += 1;
}
// reduce to final block
if used > 4 {
if pad_mask & 0b0000_1111 != 0 {
return Err(Error::PrematurePadding);
}
let chunk = output
.get_mut(output_offset..output_offset + 3)
.ok_or(Error::InsufficientOutputSpace)?;
chunk[0] = (buffer >> 40) as u8;
chunk[1] = (buffer >> 32) as u8;
chunk[2] = (buffer >> 24) as u8;
buffer <<= 24;
pad_mask >>= 4;
used -= 4;
output_offset += 3;
}
match (used, pad_mask) {
// no trailing bytes
(0, 0b0000) => {}
// 4 trailing bytes, no padding
(4, 0b0000) => {
let chunk = output
.get_mut(output_offset..output_offset + 3)
.ok_or(Error::InsufficientOutputSpace)?;
chunk[0] = (buffer >> 40) as u8;
chunk[1] = (buffer >> 32) as u8;
chunk[2] = (buffer >> 24) as u8;
output_offset += 3;
}
// 4 trailing bytes with one padding char, or 3 trailing bytes
(4, 0b1000) | (3, 0b0000) => {
let chunk = output
.get_mut(output_offset..output_offset + 2)
.ok_or(Error::InsufficientOutputSpace)?;
chunk[0] = (buffer >> 40) as u8;
chunk[1] = (buffer >> 32) as u8;
output_offset += 2;
}
// 4 trailing bytes with two padding char, or 2 trailing bytes
(4, 0b1100) | (2, 0b0000) => {
let chunk = output
.get_mut(output_offset..output_offset + 1)
.ok_or(Error::InsufficientOutputSpace)?;
chunk[0] = (buffer >> 40) as u8;
output_offset += 1;
}
// everything else is illegal
_ => return Err(Error::InvalidTrailingPadding),
}
Ok(&output[..output_offset])
}
#[derive(Debug, PartialEq)]
pub(crate) enum Error {
/// Given character is not valid in base64 alphabet.
InvalidCharacter(u8),
/// A padding character (`=`) appeared outside the final
/// block of 4 characters.
PrematurePadding,
/// The padding characters at the end of the input were invalid.
InvalidTrailingPadding,
/// Not enough space in output buffer.
///
/// Use `decoded_length` to get an upper bound.
InsufficientOutputSpace,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct CodePoint(u8);
impl CodePoint {
const WHITESPACE: Self = Self(0xf0);
const PAD: Self = Self(0xf1);
const INVALID: Self = Self(0xf2);
}
impl CodePoint {
/// Side-channel rules:
///
/// - code paths that produce `CodePoint(n)` must not make
/// `n` observable via a side channel.
/// - other code paths -- whitespace, padding or invalid -- need not,
/// these are not considered secret conditions.
fn decode_secret(b: u8) -> Self {
let is_upper = u8_in_range(b, b'A', b'Z');
let is_lower = u8_in_range(b, b'a', b'z');
let is_digit = u8_in_range(b, b'0', b'9');
let is_plus = u8_equals(b, b'+');
let is_slash = u8_equals(b, b'/');
let is_pad = u8_equals(b, b'=');
let is_space = u8_in_range(b, b'\t', b'\r') | u8_equals(b, b' ');
let is_invalid = !(is_lower | is_upper | is_digit | is_plus | is_slash | is_pad | is_space);
Self(
(is_upper & b.wrapping_sub(b'A'))
| (is_lower & (b.wrapping_sub(b'a').wrapping_add(26)))
| (is_digit & (b.wrapping_sub(b'0').wrapping_add(52)))
| (is_plus & 62)
| (is_slash & 63)
| (is_space & Self::WHITESPACE.0)
| (is_pad & Self::PAD.0)
| (is_invalid & Self::INVALID.0),
)
}
const fn decode_public(a: u8) -> Self {
const TABLE: [CodePoint; 256] = [
// 0x00..0x0f
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::WHITESPACE,
CodePoint::WHITESPACE,
CodePoint::WHITESPACE,
CodePoint::WHITESPACE,
CodePoint::WHITESPACE,
CodePoint::INVALID,
CodePoint::INVALID,
// 0x10..0x1f
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0x20..0x2f
CodePoint::WHITESPACE,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint(62),
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint(63),
// 0x30..0x3f
CodePoint(52),
CodePoint(53),
CodePoint(54),
CodePoint(55),
CodePoint(56),
CodePoint(57),
CodePoint(58),
CodePoint(59),
CodePoint(60),
CodePoint(61),
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::PAD,
CodePoint::INVALID,
CodePoint::INVALID,
// 0x40..0x4f
CodePoint::INVALID,
CodePoint(0),
CodePoint(1),
CodePoint(2),
CodePoint(3),
CodePoint(4),
CodePoint(5),
CodePoint(6),
CodePoint(7),
CodePoint(8),
CodePoint(9),
CodePoint(10),
CodePoint(11),
CodePoint(12),
CodePoint(13),
CodePoint(14),
// 0x50..0x5f
CodePoint(15),
CodePoint(16),
CodePoint(17),
CodePoint(18),
CodePoint(19),
CodePoint(20),
CodePoint(21),
CodePoint(22),
CodePoint(23),
CodePoint(24),
CodePoint(25),
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0x60..0x6f
CodePoint::INVALID,
CodePoint(26),
CodePoint(27),
CodePoint(28),
CodePoint(29),
CodePoint(30),
CodePoint(31),
CodePoint(32),
CodePoint(33),
CodePoint(34),
CodePoint(35),
CodePoint(36),
CodePoint(37),
CodePoint(38),
CodePoint(39),
CodePoint(40),
// 0x70..0x7f
CodePoint(41),
CodePoint(42),
CodePoint(43),
CodePoint(44),
CodePoint(45),
CodePoint(46),
CodePoint(47),
CodePoint(48),
CodePoint(49),
CodePoint(50),
CodePoint(51),
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0x80..0x8f
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0x90..0x9f
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0xa0..0xaf
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0xb0..0xbf
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0xc0..0xcf
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0xd0..0xdf
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0xe0..0xef
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
// 0xf0..0xff
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
CodePoint::INVALID,
];
TABLE[a as usize]
}
}
/// Returns 0xff if `a` in `lo..=hi`.
///
/// lo..=hi must not be 0..=255. Callers in this file have constant
/// `lo` and `hi`, and this function is private to this file.
fn u8_in_range(a: u8, lo: u8, hi: u8) -> u8 {
debug_assert!(lo <= hi);
debug_assert!(hi - lo != 255);
let a = a.wrapping_sub(lo);
u8_less_than(a, (hi - lo).wrapping_add(1))
}
/// Returns 0xff if a < b, 0 otherwise.
fn u8_less_than(a: u8, b: u8) -> u8 {
let a = u16::from(a);
let b = u16::from(b);
u8_broadcast16(a.wrapping_sub(b))
}
/// Returns 0xff if a == b, 0 otherwise.
const fn u8_equals(a: u8, b: u8) -> u8 {
let diff = a ^ b;
u8_nonzero(diff)
}
/// Returns 0xff if a != 0, 0 otherwise.
const fn u8_nonzero(x: u8) -> u8 {
u8_broadcast8(!x & x.wrapping_sub(1))
}
/// Broadcasts the top bit of `x`
///
/// In other words, if the top bit of `x` is set,
/// returns 0xff else 0x00.
const fn u8_broadcast8(x: u8) -> u8 {
let msb = x >> 7;
0u8.wrapping_sub(msb)
}
/// Broadcasts the top bit of `x`
///
/// In other words, if the top bit of `x` is set,
/// returns 0xff else 0x00.
const fn u8_broadcast16(x: u16) -> u8 {
let msb = x >> 15;
0u8.wrapping_sub(msb as u8)
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use alloc::vec::Vec;
use super::*;
#[test]
fn decode_test() {
assert_eq!(
decode(b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),
b"\x00\x10\x83\x10\x51\x87\x20\x92\x8b\x30\xd3\x8f\x41\x14\x93\x51\x55\x97\
\x61\x96\x9b\x71\xd7\x9f\x82\x18\xa3\x92\x59\xa7\xa2\x9a\xab\xb2\xdb\xaf\
\xc3\x1c\xb3\xd3\x5d\xb7\xe3\x9e\xbb\xf3\xdf\xbf"
);
assert_eq!(decode(b"aGVsbG8="), b"hello");
assert_eq!(decode(b"aGVsbG8gd29ybGQ="), b"hello world");
assert_eq!(decode(b"aGVsbG8gd29ybGQh"), b"hello world!");
assert_eq!(decode(b"////"), b"\xff\xff\xff");
assert_eq!(decode(b"++++"), b"\xfb\xef\xbe");
assert_eq!(decode(b"AAAA"), b"\x00\x00\x00");
assert_eq!(decode(b"AAA="), b"\x00\x00");
assert_eq!(decode(b"AA=="), b"\x00");
// like our previous use of rust-base64, we don't require padding
// if the encoding is otherwise valid given the length
assert_eq!(decode(b"AAA"), b"\x00\x00");
assert_eq!(decode(b"AA"), b"\x00");
assert_eq!(decode(b""), b"");
}
#[test]
fn decode_errors() {
let mut buf = [0u8; 6];
// illegal trailing padding
assert_eq!(
decode_both(b"A===", &mut buf),
Err(Error::InvalidTrailingPadding)
);
assert_eq!(
decode_both(b"====", &mut buf),
Err(Error::InvalidTrailingPadding)
);
assert_eq!(
decode_both(b"A==", &mut buf),
Err(Error::InvalidTrailingPadding)
);
assert_eq!(
decode_both(b"AA=", &mut buf),
Err(Error::InvalidTrailingPadding)
);
assert_eq!(
decode_both(b"A", &mut buf),
Err(Error::InvalidTrailingPadding)
);
// padding before final block
assert_eq!(
decode_both(b"=AAAAA==", &mut buf),
Err(Error::PrematurePadding)
);
assert_eq!(
decode_both(b"A=AAAA==", &mut buf),
Err(Error::PrematurePadding)
);
assert_eq!(
decode_both(b"AA=AAA==", &mut buf),
Err(Error::PrematurePadding)
);
assert_eq!(
decode_both(b"AAA=AA==", &mut buf),
Err(Error::PrematurePadding)
);
// illegal inputs
assert_eq!(
decode_both(b"%AAA", &mut buf),
Err(Error::InvalidCharacter(b'%'))
);
assert_eq!(
decode_both(b"A%AA", &mut buf),
Err(Error::InvalidCharacter(b'%'))
);
assert_eq!(
decode_both(b"AA%A", &mut buf),
Err(Error::InvalidCharacter(b'%'))
);
assert_eq!(
decode_both(b"AAA%", &mut buf),
Err(Error::InvalidCharacter(b'%'))
);
// output sizing
assert_eq!(decode_both(b"am9lIGJw", &mut [0u8; 7]), Ok(&b"joe bp"[..]));
assert_eq!(decode_both(b"am9lIGJw", &mut [0u8; 6]), Ok(&b"joe bp"[..]));
assert_eq!(
decode_both(b"am9lIGJw", &mut [0u8; 5]),
Err(Error::InsufficientOutputSpace)
);
assert_eq!(
decode_both(b"am9lIGJw", &mut [0u8; 4]),
Err(Error::InsufficientOutputSpace)
);
assert_eq!(
decode_both(b"am9lIGJw", &mut [0u8; 3]),
Err(Error::InsufficientOutputSpace)
);
// output sizing is not pessimistic when padding is valid
assert_eq!(decode_both(b"am9=", &mut [0u8; 2]), Ok(&b"jo"[..]));
assert_eq!(decode_both(b"am==", &mut [0u8; 1]), Ok(&b"j"[..]));
assert_eq!(decode_both(b"am9", &mut [0u8; 2]), Ok(&b"jo"[..]));
assert_eq!(decode_both(b"am", &mut [0u8; 1]), Ok(&b"j"[..]));
}
#[test]
fn check_models() {
fn u8_broadcast8_model(x: u8) -> u8 {
match x & 0x80 {
0x80 => 0xff,
_ => 0x00,
}
}
fn u8_broadcast16_model(x: u16) -> u8 {
match x & 0x8000 {
0x8000 => 0xff,
_ => 0x00,
}
}
fn u8_nonzero_model(x: u8) -> u8 {
match x {
0 => 0xff,
_ => 0x00,
}
}
fn u8_equals_model(x: u8, y: u8) -> u8 {
match x == y {
true => 0xff,
false => 0x00,
}
}
fn u8_in_range_model(x: u8, y: u8, z: u8) -> u8 {
match (y..=z).contains(&x) {
true => 0xff,
false => 0x00,
}
}
for x in u8::MIN..=u8::MAX {
assert_eq!(u8_broadcast8(x), u8_broadcast8_model(x));
assert_eq!(u8_nonzero(x), u8_nonzero_model(x));
assert_eq!(CodePoint::decode_secret(x), CodePoint::decode_public(x));
for y in u8::MIN..=u8::MAX {
assert_eq!(u8_equals(x, y), u8_equals_model(x, y));
let v = (x as u16) | ((y as u16) << 8);
assert_eq!(u8_broadcast16(v), u8_broadcast16_model(v));
for z in y..=u8::MAX {
if z - y == 255 {
continue;
}
assert_eq!(u8_in_range(x, y, z), u8_in_range_model(x, y, z));
}
}
}
}
#[cfg(all(feature = "std", target_os = "linux", target_arch = "x86_64"))]
#[test]
fn codepoint_decode_secret_does_not_branch_or_index_on_secret_input() {
// this is using the same theory as <https://github.com/agl/ctgrind>
use crabgrind as cg;
if matches!(cg::run_mode(), cg::RunMode::Native) {
std::println!("SKIPPED: must be run under valgrind");
return;
}
let input = [b'a'];
cg::monitor_command(format!(
"make_memory undefined {:p} {}",
input.as_ptr(),
input.len()
))
.unwrap();
core::hint::black_box(CodePoint::decode_secret(input[0]));
}
#[track_caller]
fn decode(input: &[u8]) -> Vec<u8> {
let length = decoded_length(input.len());
let mut v = alloc::vec![0u8; length];
let used = decode_both(input, &mut v).unwrap().len();
v.truncate(used);
v
}
fn decode_both<'a>(input: &'_ [u8], output: &'a mut [u8]) -> Result<&'a [u8], Error> {
let mut output_copy = output.to_vec();
let r_pub = decode_public(input, &mut output_copy);
let r_sec = decode_secret(input, output);
assert_eq!(r_pub, r_sec);
r_sec
}
}

View File

@@ -0,0 +1,21 @@
These files contain the binary DER encoding of the *values* of some
ASN.1 [`AlgorithmIdentifier`]s, without the outer `SEQUENCE` tag or the outer
length component.
These files were encoded with the help of [der-ascii]. They can be decoded
using:
```sh
go install github.com/google/der-ascii/cmd/der2ascii@latest
der2ascii -i <filename> -o <filename>.ascii
```
New or modified der-ascii files can be encoded using:
```sh
go install github.com/google/der-ascii/cmd/ascii2der@latest
ascii2der i <filename>.ascii -o <filename>
```
[`AlgorithmIdentifier`]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2]
[der-ascii]: https://github.com/google/der-ascii

View File

@@ -0,0 +1 @@
*<2A>ホ=*<2A>ホ=

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
*<2A>ホ=

View File

@@ -0,0 +1 @@
*<2A>ホ=

View File

@@ -0,0 +1 @@
*<2A>ホ=

View File

@@ -0,0 +1 @@
+ep

View File

@@ -0,0 +1 @@
+eq

View File

@@ -0,0 +1 @@
 `†He

View File

@@ -0,0 +1 @@
 `†He

View File

@@ -0,0 +1 @@
 `†He

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1157
vendor/rustls-pki-types/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

551
vendor/rustls-pki-types/src/pem.rs vendored Normal file
View File

@@ -0,0 +1,551 @@
use alloc::format;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use core::fmt;
use core::marker::PhantomData;
use core::ops::ControlFlow;
#[cfg(feature = "std")]
use std::fs::File;
#[cfg(feature = "std")]
use std::io::{self, ErrorKind};
use crate::base64;
/// Items that can be decoded from PEM data.
pub trait PemObject: Sized {
/// Decode the first section of this type from PEM contained in
/// a byte slice.
///
/// [`Error::NoItemsFound`] is returned if no such items are found.
fn from_pem_slice(pem: &[u8]) -> Result<Self, Error> {
Self::pem_slice_iter(pem)
.next()
.unwrap_or(Err(Error::NoItemsFound))
}
/// Iterate over all sections of this type from PEM contained in
/// a byte slice.
fn pem_slice_iter(pem: &[u8]) -> SliceIter<'_, Self> {
SliceIter::new(pem)
}
/// Decode the first section of this type from the PEM contents of the named file.
///
/// [`Error::NoItemsFound`] is returned if no such items are found.
#[cfg(feature = "std")]
fn from_pem_file(file_name: impl AsRef<std::path::Path>) -> Result<Self, Error> {
Self::pem_file_iter(file_name)?
.next()
.unwrap_or(Err(Error::NoItemsFound))
}
/// Iterate over all sections of this type from the PEM contents of the named file.
///
/// This reports errors in two phases:
///
/// - errors opening the file are reported from this function directly,
/// - errors reading from the file are reported from the returned iterator,
#[cfg(feature = "std")]
fn pem_file_iter(
file_name: impl AsRef<std::path::Path>,
) -> Result<ReadIter<io::BufReader<File>, Self>, Error> {
Ok(ReadIter::new(io::BufReader::new(
File::open(file_name).map_err(Error::Io)?,
)))
}
/// Decode the first section of this type from PEM read from an [`io::Read`].
#[cfg(feature = "std")]
fn from_pem_reader(rd: impl io::Read) -> Result<Self, Error> {
Self::pem_reader_iter(rd)
.next()
.unwrap_or(Err(Error::NoItemsFound))
}
/// Iterate over all sections of this type from PEM present in an [`io::Read`].
#[cfg(feature = "std")]
fn pem_reader_iter<R: io::Read>(rd: R) -> ReadIter<io::BufReader<R>, Self> {
ReadIter::new(io::BufReader::new(rd))
}
/// Conversion from a PEM [`SectionKind`] and body data.
///
/// This inspects `kind`, and if it matches this type's PEM section kind,
/// converts `der` into this type.
fn from_pem(kind: SectionKind, der: Vec<u8>) -> Option<Self>;
}
pub(crate) trait PemObjectFilter: PemObject + From<Vec<u8>> {
const KIND: SectionKind;
}
impl<T: PemObjectFilter + From<Vec<u8>>> PemObject for T {
fn from_pem(kind: SectionKind, der: Vec<u8>) -> Option<Self> {
match Self::KIND == kind {
true => Some(Self::from(der)),
false => None,
}
}
}
/// Extract and return all PEM sections by reading `rd`.
#[cfg(feature = "std")]
pub struct ReadIter<R, T> {
rd: R,
_ty: PhantomData<T>,
line: Vec<u8>,
b64_buf: Vec<u8>,
/// Used to fuse the iterator on I/O errors
done: bool,
}
#[cfg(feature = "std")]
impl<R: io::BufRead, T: PemObject> ReadIter<R, T> {
/// Create a new iterator.
pub fn new(rd: R) -> Self {
Self {
rd,
_ty: PhantomData,
line: Vec::with_capacity(80),
b64_buf: Vec::with_capacity(1024),
done: false,
}
}
}
#[cfg(feature = "std")]
impl<R: io::BufRead, T: PemObject> Iterator for ReadIter<R, T> {
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
loop {
self.b64_buf.clear();
return match from_buf_inner(&mut self.rd, &mut self.line, &mut self.b64_buf) {
Ok(Some((sec, item))) => match T::from_pem(sec, item) {
Some(res) => Some(Ok(res)),
None => continue,
},
Ok(None) => return None,
Err(Error::Io(error)) => {
self.done = true;
Some(Err(Error::Io(error)))
}
Err(err) => Some(Err(err)),
};
}
}
}
/// Iterator over all PEM sections in a `&[u8]` slice.
pub struct SliceIter<'a, T> {
current: &'a [u8],
_ty: PhantomData<T>,
b64_buf: Vec<u8>,
}
impl<'a, T: PemObject> SliceIter<'a, T> {
/// Create a new iterator.
pub fn new(current: &'a [u8]) -> Self {
Self {
current,
_ty: PhantomData,
b64_buf: Vec::with_capacity(1024),
}
}
/// Extract and decode the next supported PEM section from `input`
///
/// - `Ok(None)` is returned if there is no PEM section to read from `input`
/// - Syntax errors and decoding errors produce a `Err(...)`
/// - Otherwise each decoded section is returned with a `Ok(Some((..., remainder)))` where
/// `remainder` is the part of the `input` that follows the returned section
fn read_section(&mut self) -> Result<Option<(SectionKind, Vec<u8>)>, Error> {
self.b64_buf.clear();
let mut section = None;
loop {
let next_line = if let Some(index) = self
.current
.iter()
.position(|byte| *byte == b'\n' || *byte == b'\r')
{
let (line, newline_plus_remainder) = self.current.split_at(index);
self.current = &newline_plus_remainder[1..];
Some(line)
} else if !self.current.is_empty() {
let next_line = self.current;
self.current = &[];
Some(next_line)
} else {
None
};
match read(next_line, &mut section, &mut self.b64_buf)? {
ControlFlow::Continue(()) => continue,
ControlFlow::Break(item) => return Ok(item),
}
}
}
/// Returns the rest of the unparsed data.
///
/// This is the slice immediately following the most
/// recently returned item from `next()`.
#[doc(hidden)]
pub fn remainder(&self) -> &'a [u8] {
self.current
}
}
impl<T: PemObject> Iterator for SliceIter<'_, T> {
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
loop {
return match self.read_section() {
Ok(Some((sec, item))) => match T::from_pem(sec, item) {
Some(res) => Some(Ok(res)),
None => continue,
},
Ok(None) => return None,
Err(err) => Some(Err(err)),
};
}
}
}
impl PemObject for (SectionKind, Vec<u8>) {
fn from_pem(kind: SectionKind, der: Vec<u8>) -> Option<Self> {
Some((kind, der))
}
}
/// Extract and decode the next supported PEM section from `rd`.
///
/// - Ok(None) is returned if there is no PEM section read from `rd`.
/// - Underlying IO errors produce a `Err(...)`
/// - Otherwise each decoded section is returned with a `Ok(Some(...))`
#[cfg(feature = "std")]
pub fn from_buf(rd: &mut dyn io::BufRead) -> Result<Option<(SectionKind, Vec<u8>)>, Error> {
let mut b64buf = Vec::with_capacity(1024);
let mut line = Vec::with_capacity(80);
from_buf_inner(rd, &mut line, &mut b64buf)
}
#[cfg(feature = "std")]
fn from_buf_inner(
rd: &mut dyn io::BufRead,
line: &mut Vec<u8>,
b64buf: &mut Vec<u8>,
) -> Result<Option<(SectionKind, Vec<u8>)>, Error> {
let mut section = None;
loop {
line.clear();
let len = read_until_newline(rd, line).map_err(Error::Io)?;
let next_line = if len == 0 {
None
} else {
Some(line.as_slice())
};
match read(next_line, &mut section, b64buf) {
Ok(ControlFlow::Break(opt)) => return Ok(opt),
Ok(ControlFlow::Continue(())) => continue,
Err(e) => return Err(e),
}
}
}
#[allow(clippy::type_complexity)]
fn read(
next_line: Option<&[u8]>,
section: &mut Option<SectionLabel>,
b64buf: &mut Vec<u8>,
) -> Result<ControlFlow<Option<(SectionKind, Vec<u8>)>, ()>, Error> {
let line = if let Some(line) = next_line {
line
} else {
// EOF
return match section.take() {
Some(label) => Err(Error::MissingSectionEnd {
end_marker: label.as_ref().to_vec(),
}),
None => Ok(ControlFlow::Break(None)),
};
};
if line.starts_with(b"-----BEGIN ") {
let (mut trailer, mut pos) = (0, line.len());
for (i, &b) in line.iter().enumerate().rev() {
match b {
b'-' => {
trailer += 1;
pos = i;
}
b'\n' | b'\r' | b' ' => continue,
_ => break,
}
}
if trailer != 5 {
return Err(Error::IllegalSectionStart {
line: line.to_vec(),
});
}
let ty = &line[11..pos];
*section = Some(SectionLabel::from(ty));
return Ok(ControlFlow::Continue(()));
}
if let Some(label) = section.as_ref() {
if label.is_end(line) {
let kind = match label {
SectionLabel::Known(kind) => *kind,
// unhandled section: have caller try again
SectionLabel::Unknown(_) => {
*section = None;
b64buf.clear();
return Ok(ControlFlow::Continue(()));
}
};
let mut der = vec![0u8; base64::decoded_length(b64buf.len())];
let der_len = match kind.secret() {
true => base64::decode_secret(b64buf, &mut der),
false => base64::decode_public(b64buf, &mut der),
}
.map_err(|err| Error::Base64Decode(format!("{err:?}")))?
.len();
der.truncate(der_len);
return Ok(ControlFlow::Break(Some((kind, der))));
}
}
if section.is_some() {
b64buf.extend(line);
}
Ok(ControlFlow::Continue(()))
}
enum SectionLabel {
Known(SectionKind),
Unknown(Vec<u8>),
}
impl SectionLabel {
fn is_end(&self, line: &[u8]) -> bool {
let rest = match line.strip_prefix(b"-----END ") {
Some(rest) => rest,
None => return false,
};
let ty = match self {
Self::Known(kind) => kind.as_slice(),
Self::Unknown(ty) => ty,
};
let rest = match rest.strip_prefix(ty) {
Some(rest) => rest,
None => return false,
};
rest.starts_with(b"-----")
}
}
impl From<&[u8]> for SectionLabel {
fn from(value: &[u8]) -> Self {
match SectionKind::try_from(value) {
Ok(kind) => Self::Known(kind),
Err(_) => Self::Unknown(value.to_vec()),
}
}
}
impl AsRef<[u8]> for SectionLabel {
fn as_ref(&self) -> &[u8] {
match self {
Self::Known(kind) => kind.as_slice(),
Self::Unknown(ty) => ty,
}
}
}
/// A single recognised section in a PEM file.
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SectionKind {
/// A DER-encoded x509 certificate.
///
/// Appears as "CERTIFICATE" in PEM files.
Certificate,
/// A DER-encoded Subject Public Key Info; as specified in RFC 7468.
///
/// Appears as "PUBLIC KEY" in PEM files.
PublicKey,
/// A DER-encoded plaintext RSA private key; as specified in PKCS #1/RFC 3447
///
/// Appears as "RSA PRIVATE KEY" in PEM files.
RsaPrivateKey,
/// A DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958
///
/// Appears as "PRIVATE KEY" in PEM files.
PrivateKey,
/// A Sec1-encoded plaintext private key; as specified in RFC 5915
///
/// Appears as "EC PRIVATE KEY" in PEM files.
EcPrivateKey,
/// A Certificate Revocation List; as specified in RFC 5280
///
/// Appears as "X509 CRL" in PEM files.
Crl,
/// A Certificate Signing Request; as specified in RFC 2986
///
/// Appears as "CERTIFICATE REQUEST" in PEM files.
Csr,
/// An EchConfigList structure, as specified in
/// <https://www.ietf.org/archive/id/draft-farrell-tls-pemesni-05.html>.
///
/// Appears as "ECHCONFIG" in PEM files.
EchConfigList,
}
impl SectionKind {
const fn secret(&self) -> bool {
match self {
Self::RsaPrivateKey | Self::PrivateKey | Self::EcPrivateKey => true,
Self::Certificate | Self::PublicKey | Self::Crl | Self::Csr | Self::EchConfigList => {
false
}
}
}
fn as_slice(&self) -> &'static [u8] {
match self {
Self::Certificate => b"CERTIFICATE",
Self::PublicKey => b"PUBLIC KEY",
Self::RsaPrivateKey => b"RSA PRIVATE KEY",
Self::PrivateKey => b"PRIVATE KEY",
Self::EcPrivateKey => b"EC PRIVATE KEY",
Self::Crl => b"X509 CRL",
Self::Csr => b"CERTIFICATE REQUEST",
Self::EchConfigList => b"ECHCONFIG",
}
}
}
impl TryFrom<&[u8]> for SectionKind {
type Error = ();
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
Ok(match value {
b"CERTIFICATE" => Self::Certificate,
b"PUBLIC KEY" => Self::PublicKey,
b"RSA PRIVATE KEY" => Self::RsaPrivateKey,
b"PRIVATE KEY" => Self::PrivateKey,
b"EC PRIVATE KEY" => Self::EcPrivateKey,
b"X509 CRL" => Self::Crl,
b"CERTIFICATE REQUEST" => Self::Csr,
b"ECHCONFIG" => Self::EchConfigList,
_ => return Err(()),
})
}
}
/// Errors that may arise when parsing the contents of a PEM file
#[non_exhaustive]
#[derive(Debug)]
pub enum Error {
/// a section is missing its "END marker" line
MissingSectionEnd {
/// the expected "END marker" line that was not found
end_marker: Vec<u8>,
},
/// syntax error found in the line that starts a new section
IllegalSectionStart {
/// line that contains the syntax error
line: Vec<u8>,
},
/// base64 decode error
Base64Decode(String),
/// I/O errors, from APIs that accept `std::io` types.
#[cfg(feature = "std")]
Io(io::Error),
/// No items found of desired type
NoItemsFound,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingSectionEnd { end_marker } => {
write!(f, "missing section end marker: {end_marker:?}")
}
Self::IllegalSectionStart { line } => {
write!(f, "illegal section start: {line:?}")
}
Self::Base64Decode(e) => write!(f, "base64 decode error: {e}"),
#[cfg(feature = "std")]
Self::Io(e) => write!(f, "I/O error: {e}"),
Self::NoItemsFound => write!(f, "no items found"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
// Ported from https://github.com/rust-lang/rust/blob/91cfcb021935853caa06698b759c293c09d1e96a/library/std/src/io/mod.rs#L1990 and
// modified to look for our accepted newlines.
#[cfg(feature = "std")]
fn read_until_newline<R: io::BufRead + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut read = 0;
loop {
let (done, used) = {
let available = match r.fill_buf() {
Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
match available
.iter()
.copied()
.position(|b| b == b'\n' || b == b'\r')
{
Some(i) => {
buf.extend_from_slice(&available[..=i]);
(true, i + 1)
}
None => {
buf.extend_from_slice(available);
(false, available.len())
}
}
};
r.consume(used);
read += used;
if done || used == 0 {
return Ok(read);
}
}
}

1214
vendor/rustls-pki-types/src/server_name.rs vendored Normal file

File diff suppressed because it is too large Load Diff