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

1
vendor/rcgen/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"f8a1dbc4f1ba8b66808fc560b38083905e2226a3a0392f6b2198dfc421dc6554","CHANGELOG.md":"7627cd14712eb404ac6589ae8b6bc0071fdf46019b2a43bcba437000996ad794","Cargo.lock":"d022e96cf2037574d395faec7606d27a238315c51407f4bc6dfebf453633a471","Cargo.toml":"04199b2cc0267714a764a9e02c86608e185b438c85762c061a4628874ee83a9f","Cargo.toml.orig":"ddcbc57044fc1c436237d9ac85049eb60a20fb3dcf57459ba5c04ae73ae4bc84","LICENSE":"debe6fed7ac143217c7f533759c54b14f18cd01d5fe195c51d83c2ae2d136cb4","README.md":"43402f7ece7da232f2d742d358a2b9e8d45d0a4af0810733a524870a7cdf2b74","docs/0.12-to-0.13.md":"a0a68fb4d5eed9c8b8f9661a675e3bdde4ad36747f9cd4f0b80937dde8c74d6c","examples/rsa-irc-openssl.rs":"e137aa44916211d18b407f19e1320706f194b03c56c64c300e8cf76ed2133020","examples/sign-leaf-with-ca.rs":"8d9c59e10c452d92ca5b2cb07257695672f5fd3628220669f9e1cd7558933284","examples/sign-leaf-with-pem-files.rs":"d7ca848554ea7b72487ccb880b23e4147dbb47829dc18ea45d145cc4250cc65f","examples/simple.rs":"b523bc93efb512439512039f89275e72b1db55268ec7c3026eaeb3feb20147fd","src/certificate.rs":"9bdeed136344b679a1363a0f3b028a481ef46188f535b135a6492bdcd625be6d","src/crl.rs":"e2f97090e5b137017ba0872cb374b30e60b7a7afd97ae6bf937a726f3270c87f","src/csr.rs":"97c749b7554a52a6e74bb8c46abd16f8d9b7b544dac6cde9c1c9b173e6eca142","src/error.rs":"a1d0b1605d8f8fcfc1d383ea6a05d93b685f6d8f56b5e40b327a6e5c8475b2f3","src/key_pair.rs":"32346bce539525de4b517c7e747fd28e90c0550845b2098ccc53c85a0672973d","src/lib.rs":"41ba45823e750863886a51175767a3178c0b0b6ecb72bec2c8cc9b2fc08c7d4a","src/oid.rs":"e06a9776a0f6e292188fb5c3fa6b1d6f11c18ab20d7b7fef731640f67f5b547c","src/ring_like.rs":"dcfa1df7092fa2533022e02d88eacccc667799c064a9cc68ffc37fced4ed3cef","src/sign_algo.rs":"69b457fcf434246e2cd79d261c1d450ef190e840fc6ea058a2c7000aed1d4868","src/string.rs":"6807effb64b46cfcdee728168d9c81f95feebfc042a364f9ef504a40db1b0f29"},"package":"10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e"}

6
vendor/rcgen/.cargo_vcs_info.json vendored Normal file
View File

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

296
vendor/rcgen/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,296 @@
# Changes
Newer releases can be found [on GitHub](https://github.com/rustls/rcgen/releases).
## Release 0.13.1 - April 4th, 2024
Fixed:
- Fixed incorrect usage of the subject certificate's parameter's key identifier
method when computing the key identifier of the issuer for the subject's
authority key identifier (AKI) extension.
## Release 0.13.0 - March 28th, 2024
Breaking changes:
- The API used to create/issue key pairs, certificates, certificate signing
requests (CSRs), and certificate revocation lists (CRLs) has been
restructured to emphasize consistency and avoid common errors with
serialization.
For each concrete type (cert, CSR, CRL) the process is now the same:
0. generate or load a key pair and any information about issuers required.
1. create parameters, customizing as appropriate.
2. call a generation `fn` on the parameters, providing subject key pair and
issuer information and as appropriate.
3. call serialization `fn`s on the finalized type, obtaining DER or PEM.
For more information, see [rcgen/docs/0.12-to-0.13.md].
- Throughout the API DER inputs are now represented using types from the Rustls
`rustls-pki-types` crate, e.g. `PrivateKeyDer`, `CertificateDer`,
`CertificateSigningRequestDer`. Contributed by
[Tudyx](https://github.com/tudyx).
- String types used in `SanType` and `DnValue` enums for non-UTF8 string types
have been replaced with more specific types that prevent representation of
illegal values. E.g. `Ia5String`, `BmpString`, `PrintableString`,
`TeletexString`, and `UniversalString`. Contributed by
[Tudyx](https://github.com/tudyx).
- Method names starting with `get_` have been renamed to match Rust convention:
`CertificateRevocationList::get_params()` -> `params()`
`Certificate::get_params()` -> `params()`
`Certificate::get_key_identifier()` -> `Certificate::key_identifier()`
`Certificate::get_times()` -> `Certificate::times()`
Added:
- RSA key generation support has been added. This support requires using the
`aws-lc-rs` feature. By default using `KeyPair::generate_for()` with
an RSA `SignatureAlgorithm` will generate an RSA 2048 keypair. See
`KeyPair::generate_rsa_for()` for support for RSA 2048, 3072 and 4096 key sizes.
- Support for ECDSA P521 signatures and key generation has been added when using
the `aws-lc-rs` feature. Contributed by [Alvenix](https://github.com/alvenix).
- Support for loading private keys that may be PKCS8, PKCS1, or SEC1 has been
added when using the `aws-lc-rs` feature. Without this feature private keys
must be PKCS8. See `KeyPair::from_pem_and_sign_algo()` and
`KeyPair::from_der_and_sign_algo()` for more information. Contributed by
[Alvenix](https://github.com/alvenix).
- Support has been added for Subject Alternative Name (SAN) names of type
`OtherName`. Contributed by [Tudyx](https://github.com/tudyx).
- Support has been added for specifying custom "other" OIDs in extended key
usage. Contributed by [Tudyx](https://github.com/tudyx).
- Support has been added for building rcgen _without_ cryptography by omitting
the new (default-enabled) `crypto` feature flag. Contributed by
[corrideat](https://github.com/corrideat).
- Support for using `aws-lc-rs` in `fips` mode can now be activated by using the
`fips` feature in combination with the `aws-lc-rs` feature. Contributed by
[BiagioFesta](https://github.com/biagiofesta).
- A small command-line tool for certificate generation (`rustls-cert-gen`) was
added. Contributed by [tbro](https://github.com/tbro).
## Release 0.12.1 - January 25th, 2024
- RFC 5280 specifies that a serial number must not be larger than 20 octets in
length. Prior to this release an unintended interaction between rcgen and its
underlying DER encoding library could result in 21 octet serials. This has now
been fixed.
- A regression that caused build errors when the optional `pem` feature was
omitted has been fixed.
## Release 0.12.0 - December 16, 2023
- Rename `RcgenError` to `Error`. Contributed by [thomaseizinger](https://github.com/thomaseizinger).
- The public interface of `Error` has been made not expose external library types: `Error::PemError` now holds a `String` value, and the `Error` type doesn't support `From<_>` based conversion any more. This allows rcgen to update dependencies without impacting downstream users.
- Upgrade to `ring` `v0.17`. Contributed by [thomaseizinger](https://github.com/thomaseizinger).
- Make dependency on `ring` optional and allow usage of `aws-lc-rs` via a cargo feature. Ring remains the default. Contributed by [BiagioFesta](https://github.com/BiagioFesta).
- Add `Ia5String` support for `DistinguishedName`s.
- Add a `KeyIdMethod::PreSpecified` variant to set, and not generate the SKI. `CertificateParams::from_ca_cert_pem` now uses it when building params from an existing CA certificate. Contributed by [Brocar](https://github.com/Brocar).
## Release 0.11.3 - October 1, 2023
- Fix for import errors building without the optional `pem` feature.
## Release 0.11.2 - September 21, 2023
- `rcgen` has joined the umbrella of the [rustls](https://github.com/rustls) organization.
- Support for retrieving signature algorithm from `KeyPair`s. Contributed by [tindzk](https://github.com/tindzk).
- Fix for writing certificate signing requests (CSRs) with custom extensions from parameters without subject alternative names.
- Support for certificate CRL distribution points extension.
- Corrected OID for `ExtendedKeyUsagePurpose::Any`. Contributed by [jgallagher](https://github.com/jgallagher).
- Support for creating certificate revocation lists (CRLs).
## Release 0.11.1 - June 17, 2023
- Make botan a dev-dependency again. Contributed by [mbrubeck](https://github.com/mbrubeck).
## Release 0.11.0 - June 15, 2023
- Parse IP-address subject alternative names. Contributed by [iamjpotts](https://github.com/iamjpotts).
- Emit platform-apropriate line endings. Contributed by [frjonsen](https://github.com/frjonsen).
- Support larger serial numbers. Contributed by [andrenth](https://github.com/andrenth).
- Parse more certificate parameters. Contributed by [andrenth](https://github.com/andrenth).
- Output `SanType::IpAddress` when calling `CertificateParams::new` or `generate_simple_self_signed`. Contributed by [rukai](https://github.com/rukai).
- Update pem to 2.0. Contributed by [koushiro](https://github.com/koushiro).
## Release 0.10.0 - September 29, 2022
- Update x509-parser to 0.14.
- Increase minimum supported Rust version to 1.58.1.
- Update edition to 2021.
- Change `IsCa` enum to have `NoCa` and `ExplicitNoCa` and `Ca(...)`. Contributed by [doraneko94](https://github.com/doraneko94).
## Release 0.9.4 - September 28, 2022
* yanked due to breaking API changes, see 0.10.0 instead.
## Release 0.9.3 - July 16, 2022
- Add a `KeyPair::serialized_der` function. Contributed by [jean-airoldie](https://github.com/jean-airoldie).
## Release 0.9.2 - February 21, 2022
- Update x509-parser to 0.13. Contributed by [matze](https://github.com/matze).
## Release 0.9.1 - February 9, 2022
- Change edition to 2018 in order to support Rust 1.53.0.
## Release 0.9.0 - February 2, 2022
- Add RemoteKeyError for usage by remote keys.
- Support non utf8 strings. Contributed by [omjadas](https://github.com/omjadas).
- Switch from chrono to time. Contributed by [connec](https://github.com/connec).
- Update edition to 2021.
## Release 0.8.14 - October 14, 2021
- Update pem to 1.0.
- Update x509-parser to 0.12.
## Release 0.8.13 - August 22, 2021
- Bugfix release to make Certificate `Send` and `Sync` again.
## Release 0.8.12 - August 22, 2021
- Use public key as default serial number. Contributed by [jpastuszek](https://github.com/jpastuszek).
- Add support for `PKCS_RSA_SHA512` and `PKCS_RSA_SHA384` signature algorithms.
- Add support for the keyUsage extension. Contributed by [jaredwolff](https://github.com/jaredwolff).
- Ability to use remote keys. Contributed by [daxpedda](https://github.com/daxpedda).
## Release 0.8.11 - April 28, 2021
- Add getters for the criticality, content, and `oid_components` of a `CustomExtension`
- Update yasna to 0.4
## Release 0.8.10 - April 15, 2021
- Implement some additional traits for some of the types. Contributed by [zurborg](https://github.com/zurborg).
- Adoption of intra-doc-links
- Addition of the ability to zero key pairs. Contributed by [didier-wenzek](https://github.com/didier-wenzek).
## Release 0.8.9 - December 4, 2020
- Switch CI to Github Actions.
- Strip nanos from `DateTime` as well. Contributed by [@trevor-crypto](https://github.com/trevor-crypto).
## Release 0.8.7 - December 1, 2020
- Turn `botan` back into a dev-dependency. Contributed by [@nthuemmel](https://github.com/nthuemmel).
- Fix signing when CA uses different signing algorithm . Contributed by [@nthuemmel](https://github.com/nthuemmel).
## Release 0.8.6 - December 1, 2020
- Add `KeyPair::from_der`
- Add botan based test to the testsuite
- Update x509-parser to 0.9. Contributed by [@djc](https://github.com/djc).
- Ability to create certificates from CSRs. Contributed by [@djc](https://github.com/djc).
## Release 0.8.5 - June 29, 2020
- Add some more `DnType`s: `OrganizationalUnitName`, `LocalityName`, `StateOrProvinceName`
- Add `remove` function to `DistinguishedName`
- Add ability to specify `NameConstraints`
## Release 0.8.4 - June 5, 2020
- Improve spec compliance in the `notBefore`/`notAfter` fields generated by using `UTCTime` if needed
## Release 0.8.3 - May 24, 2020
- Fix regression of `0.8.1` that generated standards non compliant CSRs
and broke Go toolchain parsers. Contributed by [@thomastaylor312](https://github.com/thomastaylor312).
## Release 0.8.2 - May 18, 2020
- Disable `chrono` default features to get rid of time crate
- Improve `openssl` tests to do a full handshake with the generated cert
## Release 0.8.1 - April 2, 2020
- Fix non-standard-compliant SubjectKeyIdentifier X.509v3 extension format
- BasicConstraints X.509v3 extension is now marked as critical
- Use RFC 7093 to calculate calculate subject key identifiers
- Add option to insert AuthorityKeyIdentifier X.509v3 extension into non-self-signed certificates
- Update to x509-parser 0.7
## Release 0.8.0 - March 12, 2020
- Update to pem 0.7
- Correct number of nanoseconds per second. Contributed by [@samlich](https://github.com/samlich).
- Adoption of the `non_exhaustive` feature in the API
## Release 0.7.0 - September 14, 2019
- Bugfix release for ip address subject alternative names.
Turns out they aren't CIDR subnets after all :)
## Release 0.6.0 - September 12, 2019
- Support for email and cidr subnet (ip address) subject alternative names
- Support for the extended key usage extension
## Release 0.5.1 - August 19, 2019
- Update to x509-parser 0.6
## Release 0.5.0 - July 19, 2019
- Update to ring 0.16 and webpki 0.21
- Update to x509-parser 0.5
- Expose an API to get the raw public key of a key pair
## Release 0.4.1 - June 28, 2019
- Allow inspection of `DistinguishedName` via iterators and get functions
- Fix a bug in `is_compatible` not saying false. Contributed by [@fzgregor](https://github.com/fzgregor).
- Extend the public interface of `KeyPair`. Contributed by [@fzgregor](https://github.com/fzgregor).
## Release 0.4.0 - June 18, 2019
- Support for user supplied keypairs. Contributed by [@fzgregor](https://github.com/fzgregor).
- Support for signing with user supplied CA certificates. Contributed by [@fzgregor](https://github.com/fzgregor).
- Correct a bug with distinguished name serialization ([PR link](https://github.com/est31/rcgen/pull/13)). Contributed by [@fzgregor](https://github.com/fzgregor).
- Addition of limited (no key generation) RSA support
- Proper error handling with `Result` and our own Error type
- Improvements of the testsuite
## Release 0.3.1 - June 6, 2019
- Ability to disable the dependency on the `pem` crate
- Support for creating CSRs (Certificate Signing Requests). Contributed by [@djc](https://github.com/djc).
- Ability to specify custom extensions for certificates
- Ability to craft `acmeIdentifier` extensions
- Update yasna to 0.3.0
## Release 0.3.0 - May 18, 2019
- Support for CA certificate generation. Contributed by [@djc](https://github.com/djc).
- Support for certificate signing. Contributed by [@djc](https://github.com/djc).
- Support for ED25519 certificates
- Support for SHA-384 certificates
- API cleanups (Future proofing CertificateParams, public constant renames)
## Release 0.2.1 - April 26, 2019
- Updated to pem 0.6
## Release 0.2 - January 10, 2019
- Updated to ring 0.14.0
## Release 0.1 - January 7, 2019
Initial release. Ability to generate self-signed ECDSA keys.

971
vendor/rcgen/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,971 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "asn1-rs"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60"
dependencies = [
"asn1-rs-derive",
"asn1-rs-impl",
"displaydoc",
"nom",
"num-traits",
"rusticata-macros",
"thiserror",
"time",
]
[[package]]
name = "asn1-rs-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "asn1-rs-impl"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "aws-lc-fips-sys"
version = "0.13.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2608e5a7965cc9d58c56234d346c9c89b824c4c8652b6f047b3bd0a777c0644f"
dependencies = [
"bindgen",
"cc",
"cmake",
"dunce",
"fs_extra",
"regex",
]
[[package]]
name = "aws-lc-rs"
version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba"
dependencies = [
"aws-lc-fips-sys",
"aws-lc-sys",
"untrusted 0.7.1",
"zeroize",
]
[[package]]
name = "aws-lc-sys"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff"
dependencies = [
"bindgen",
"cc",
"cmake",
"dunce",
"fs_extra",
]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bindgen"
version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"itertools",
"lazy_static",
"lazycell",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
"which",
]
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "cc"
version = "1.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
dependencies = [
"jobserver",
"libc",
"shlex",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "cmake"
version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
dependencies = [
"cc",
]
[[package]]
name = "data-encoding"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
[[package]]
name = "der-parser"
version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6"
dependencies = [
"asn1-rs",
"displaydoc",
"nom",
"num-bigint",
"num-traits",
"rusticata-macros",
]
[[package]]
name = "deranged"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
dependencies = [
"powerfmt",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "dunce"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "errno"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [
"libc",
"windows-sys 0.60.2",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.1+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
]
[[package]]
name = "glob"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "home"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jobserver"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
dependencies = [
"getrandom 0.3.3",
"libc",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "libloading"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.53.2",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "oid-registry"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7"
dependencies = [
"asn1-rs",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "openssl"
version = "0.10.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "pem"
version = "3.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3"
dependencies = [
"base64",
"serde",
]
[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "prettyplease"
version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
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 = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rcgen"
version = "0.14.7"
dependencies = [
"aws-lc-rs",
"openssl",
"pem",
"ring",
"rustls-pki-types",
"time",
"x509-parser",
"yasna",
"zeroize",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.16",
"libc",
"untrusted 0.9.0",
"windows-sys 0.52.0",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rusticata-macros"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
dependencies = [
"nom",
]
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
]
[[package]]
name = "rustls-pki-types"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
dependencies = [
"zeroize",
]
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[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.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
[[package]]
name = "time-macros"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.2",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags",
]
[[package]]
name = "x509-parser"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3e137310115a65136898d2079f003ce33331a6c4b0d51f1531d1be082b6425"
dependencies = [
"asn1-rs",
"aws-lc-rs",
"data-encoding",
"der-parser",
"lazy_static",
"nom",
"oid-registry",
"ring",
"rusticata-macros",
"thiserror",
"time",
]
[[package]]
name = "yasna"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
dependencies = [
"time",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

158
vendor/rcgen/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,158 @@
# 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.71"
name = "rcgen"
version = "0.14.7"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Rust X.509 certificate generator"
documentation = "https://docs.rs/rcgen"
readme = "README.md"
keywords = [
"mkcert",
"ca",
"certificate",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rustls/rcgen"
[package.metadata.docs.rs]
features = [
"aws_lc_rs",
"aws_lc_rs_unstable",
"crypto",
"ring",
"x509-parser",
]
rustdoc-args = [
"--cfg",
"rcgen_docsrs",
]
[package.metadata.cargo_check_external_types]
allowed_external_types = [
"time::offset_date_time::OffsetDateTime",
"zeroize::Zeroize",
"rustls_pki_types::*",
]
[features]
aws_lc_rs = [
"crypto",
"dep:aws-lc-rs",
"aws-lc-rs/aws-lc-sys",
"x509-parser?/verify-aws",
]
aws_lc_rs_unstable = [
"aws_lc_rs",
"aws-lc-rs/unstable",
"x509-parser?/verify-aws",
]
crypto = []
default = [
"crypto",
"pem",
"ring",
]
fips = [
"crypto",
"dep:aws-lc-rs",
"aws-lc-rs/fips",
]
ring = [
"crypto",
"dep:ring",
"x509-parser?/verify",
]
[lib]
name = "rcgen"
path = "src/lib.rs"
[[example]]
name = "rsa-irc-openssl"
path = "examples/rsa-irc-openssl.rs"
required-features = ["pem"]
[[example]]
name = "sign-leaf-with-ca"
path = "examples/sign-leaf-with-ca.rs"
required-features = [
"pem",
"x509-parser",
]
[[example]]
name = "sign-leaf-with-pem-files"
path = "examples/sign-leaf-with-pem-files.rs"
required-features = [
"pem",
"x509-parser",
]
[[example]]
name = "simple"
path = "examples/simple.rs"
required-features = [
"crypto",
"pem",
]
[dependencies.aws-lc-rs]
version = "1.13.3"
optional = true
default-features = false
[dependencies.pem]
version = "3.0.2"
optional = true
[dependencies.pki-types]
version = "1.4.1"
package = "rustls-pki-types"
[dependencies.ring]
version = "0.17"
optional = true
[dependencies.time]
version = "0.3.6"
default-features = false
[dependencies.x509-parser]
version = "0.18"
optional = true
[dependencies.yasna]
version = "0.5.2"
features = [
"time",
"std",
]
[dependencies.zeroize]
version = "1.2"
optional = true
[target."cfg(unix)".dev-dependencies.openssl]
version = "0.10"
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ["cfg(rcgen_docsrs)"]

214
vendor/rcgen/LICENSE vendored Normal file
View File

@@ -0,0 +1,214 @@
Copyright (c) 2019-2026 est31 <MTest31@outlook.com> and contributors
Licensed under MIT or Apache License 2.0,
at your option.
The full list of contributors can be obtained by looking
at the VCS log (originally, this crate was git versioned,
there you can do "git shortlog -sn" for this task).
MIT License
-----------
The MIT License (MIT)
Copyright (c) 2019-2026 est31 <MTest31@outlook.com> and contributors
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.
Apache License, version 2.0
---------------------------
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

60
vendor/rcgen/README.md vendored Normal file
View File

@@ -0,0 +1,60 @@
# rcgen
[![docs](https://docs.rs/rcgen/badge.svg)](https://docs.rs/rcgen)
[![crates.io](https://img.shields.io/crates/v/rcgen.svg)](https://crates.io/crates/rcgen)
[![dependency status](https://deps.rs/repo/github/est31/rcgen/status.svg)](https://deps.rs/repo/github/est31/rcgen)
Simple Rust library to generate X.509 certificates.
```Rust
use rcgen::{generate_simple_self_signed, CertifiedKey};
// Generate a certificate that's valid for "localhost" and "hello.world.example"
let subject_alt_names = vec!["hello.world.example".to_string(),
"localhost".to_string()];
let CertifiedKey { cert, key_pair } = generate_simple_self_signed(subject_alt_names).unwrap();
println!("{}", cert.pem());
println!("{}", key_pair.serialize_pem());
```
## Trying it out with openssl
You can do this:
```
cargo run
openssl x509 -in certs/cert.pem -text -noout
```
For debugging, pasting the PEM formatted text
to [this](https://lapo.it/asn1js/) service is very useful.
## Trying it out with quinn
You can use rcgen together with the [quinn](https://github.com/quinn-rs/quinn) crate.
The whole set of commands is:
```
cargo run
cd ../quinn
cargo run --example server -- --cert ../rcgen/certs/cert.pem --key ../rcgen/certs/key.pem ./
cargo run --example client -- --ca ../rcgen/certs/cert.der https://localhost:4433/README.md
```
## MSRV
The MSRV policy is to strive for supporting 7-month old Rust versions.
### License
[license]: #license
This crate is distributed under the terms of both the MIT license
and the Apache License (Version 2.0), at your option.
See [LICENSE](LICENSE) for details.
#### License of your contributions
Unless you explicitly state otherwise, any contribution intentionally submitted for
inclusion in the work by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.

90
vendor/rcgen/docs/0.12-to-0.13.md vendored Normal file
View File

@@ -0,0 +1,90 @@
# Rcgen 0.12 to 0.13 Migration Guide
This document is a meant to be a helpful guide for some of the API changes made
between rcgen 0.12 and 0.13. For information on other changes in 0.13 see
[rcgen/CHANGELOG.md].
## Key Pairs
* Previously it was possible to have certificate generation automatically create
a subject `KeyPair` for you by leaving the `key_pair` field of
`CertificateParams` empty, and retrieving the generated `KeyPair` from
a `Certificate` created with the `CertificateParams` by calling
`Certificate::get_key_pair()`.
To offer more consistency and to keep the `CertificateParams` and `Certificate`
types from holding private key data, the new API requires you handle `KeyPair`
creation yourself. See `CertifiedKey`, `KeyPair::generate()`,
`KeyPair::generate_for()` and `KeyPair::generate_rsa_for()` for more information.
* Serializing a `Certificate`'s `KeyPair` to DER or PEM was previously done by
calling `Certificate::serialize_private_key_der()` or
`Certificate::serialize_private_key_pem()`. This is now handled by calling
`KeyPair::serialize_der()` or `KeyPair::serialize_pem()`.
## Certificates
* For quick-and-easy self-signed certificate issuance,
`generate_simple_self_signed` now returns a `CertifiedKey` in the success case
instead of a `Certificate`. The self-signed `Certificate` can be accessed in
the `cert` field of `CertifiedKey`, and the generated subject key pair in
`key_pair`.
* Custom self-signed certificate issuance was previously done by
constructing `CertificateParams` and calling `Certificate::from_params()` to
create a `Certificate`. This is now done by calling
`CertificateParams::self_signed()`, providing a subject `KeyPair` of your
choosing.
* Custom certificate issuance signed by an issuer was previously done by
constructing `CertificateParams`, calling `Certificate::from_params()` and
then choosing the issuer at serialization time. This is now done ahead of
serialization by calling `CertificateParams::signed_by()` and providing
a subject `KeyPair` as well as an issuer `Certificate` and `KeyPair`.
* Previously certificate serialization was done by calling
`Certificate::serialize_der()`, `Certificate::serialize_pem()`,
`Certificate::serialize_der_with_signer()` or
`Certificate::serialize_pem_with_signer()`. Each time a serialization fn was
called a new certificate was issued, leading to confusion when it was desired
to serialize the same certificate in two formats. In the new API issuance is
handled by `CertificateParams` fns and the generated `Certificate` will not change
when serialized. You can serialize it to PEM by calling `Certificate::pem()`,
or access the DER encoding by calling `Certificate::der()`.
## Certificate Signing Requests (CSRs)
* Previously it was only possible to create a new CSR by first issuing
a `Certificate` from `CertificateParams`, and calling
`Certificate::serialize_request_pem()` or
`Certificate::serialize_request_der()`. In the updated API you can create
a `CertificateSigningRequest` directly from `CertificateParams` by calling
`CertificateParams::serialize_request` and providing a subject `KeyPair`. You
may serialize the CSR to DER or PEM by calling
`CertificateSigningRequest::der()` or `CertificateSingingRequest::pem()`.
* To load a CSR from an existing PEM/DER copy with the old API required
calling `CertificateSingingRequest::from_pem()` or
`CertificateSigningRequest::from_der()`. The new API introduces
a `CertificateSingingRequestParams` type that can be created using
`CertificateSigningRequestParams::from_pem()` or
`CertificateSingingRequest::from_der()`.
* To issue a certificate from an existing CSR with the old API required calling
`CertificateSigningRequest::serialize_der_with_signer()` or
`CertificateSigningRequest::serialize_pem_with_signer()`. In the new API, call
`CertificateSigningRequestParams::signed_by()` and provide an issuer
`Certificate` and `KeyPair`.
## Certificate Revocation Lists (CRLs)
* Previously a `CertificateRevocationList` was created by calling
`CertificateRevocationList::from_params()`. This is now done by calling
`CertificateRevocationListParams::signed_by()` and providing an issuer
`Certificate` and `KeyPair`.
* Previously a created `CertificateRevocationList` could be serialized to DER or
PEM by calling `CertificateRevocationList::serialize_der_with_signer()` or
`CertificateRevocationList::serialize_pem_with_signer()`. This is now done by
calling `CertificateRevocationList::der()` or
`CertificateRevocationList::pem()`.

View File

@@ -0,0 +1,43 @@
#[cfg(unix)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::fmt::Write;
use std::fs;
use rcgen::{date_time_ymd, CertificateParams, DistinguishedName};
let mut params: CertificateParams = Default::default();
params.not_before = date_time_ymd(2021, 5, 19);
params.not_after = date_time_ymd(4096, 1, 1);
params.distinguished_name = DistinguishedName::new();
let pkey: openssl::pkey::PKey<_> = openssl::rsa::Rsa::generate(2048)?.try_into()?;
let key_pair_pem = String::from_utf8(pkey.private_key_to_pem_pkcs8()?)?;
let key_pair = rcgen::KeyPair::from_pem(&key_pair_pem)?;
let cert = params.self_signed(&key_pair)?;
let pem_serialized = cert.pem();
let pem = pem::parse(&pem_serialized)?;
let der_serialized = pem.contents();
let hash = ring::digest::digest(&ring::digest::SHA512, der_serialized);
let hash_hex = hash.as_ref().iter().fold(String::new(), |mut output, b| {
let _ = write!(output, "{b:02x}");
output
});
println!("sha-512 fingerprint: {hash_hex}");
println!("{pem_serialized}");
println!("{}", key_pair.serialize_pem());
std::fs::create_dir_all("certs/")?;
fs::write("certs/cert.pem", pem_serialized.as_bytes())?;
fs::write("certs/cert.der", der_serialized)?;
fs::write("certs/key.pem", key_pair.serialize_pem().as_bytes())?;
fs::write("certs/key.der", key_pair.serialize_der())?;
Ok(())
}
#[cfg(not(unix))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Due to the support burden of running OpenSSL on Windows,
// we only support the OpenSSL backend on Unix-like systems.
// It should still work on Windows if you have OpenSSL installed.
unimplemented!("OpenSSL backend is not supported on Windows");
}

View File

@@ -0,0 +1,66 @@
use rcgen::DnValue::PrintableString;
use rcgen::{
BasicConstraints, Certificate, CertificateParams, DnType, ExtendedKeyUsagePurpose, IsCa,
Issuer, KeyPair, KeyUsagePurpose,
};
use time::{Duration, OffsetDateTime};
/// Example demonstrating signing end-entity certificate with ca
fn main() {
let (ca, issuer) = new_ca();
let end_entity = new_end_entity(&issuer);
let end_entity_pem = end_entity.pem();
println!("directly signed end-entity certificate: {end_entity_pem}");
let ca_cert_pem = ca.pem();
println!("ca certificate: {ca_cert_pem}");
}
fn new_ca() -> (Certificate, Issuer<'static, KeyPair>) {
let mut params =
CertificateParams::new(Vec::default()).expect("empty subject alt name can't produce error");
let (yesterday, tomorrow) = validity_period();
params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
params.distinguished_name.push(
DnType::CountryName,
PrintableString("BR".try_into().unwrap()),
);
params
.distinguished_name
.push(DnType::OrganizationName, "Crab widgits SE");
params.key_usages.push(KeyUsagePurpose::DigitalSignature);
params.key_usages.push(KeyUsagePurpose::KeyCertSign);
params.key_usages.push(KeyUsagePurpose::CrlSign);
params.not_before = yesterday;
params.not_after = tomorrow;
let key_pair = KeyPair::generate().unwrap();
let cert = params.self_signed(&key_pair).unwrap();
(cert, Issuer::new(params, key_pair))
}
fn new_end_entity(issuer: &Issuer<'static, KeyPair>) -> Certificate {
let name = "entity.other.host";
let mut params = CertificateParams::new(vec![name.into()]).expect("we know the name is valid");
let (yesterday, tomorrow) = validity_period();
params.distinguished_name.push(DnType::CommonName, name);
params.use_authority_key_identifier_extension = true;
params.key_usages.push(KeyUsagePurpose::DigitalSignature);
params
.extended_key_usages
.push(ExtendedKeyUsagePurpose::ServerAuth);
params.not_before = yesterday;
params.not_after = tomorrow;
let key_pair = KeyPair::generate().unwrap();
params.signed_by(&key_pair, issuer).unwrap()
}
fn validity_period() -> (OffsetDateTime, OffsetDateTime) {
let day = Duration::new(86400, 0);
let yesterday = OffsetDateTime::now_utc().checked_sub(day).unwrap();
let tomorrow = OffsetDateTime::now_utc().checked_add(day).unwrap();
(yesterday, tomorrow)
}

View File

@@ -0,0 +1,82 @@
//! Generate a new certificate, and sign it with an existing root or
//! intermediate certificate.
//!
//! Requires four positional command line arguments:
//! * File path to PEM containing signer's key pair
//! * File path to PEM containing signer's certificate
//! * File path for generated PEM containing output key pair
//! * File path for generated PEM containing output certificate
use std::error::Error;
use std::fs;
use std::path::PathBuf;
use rcgen::{CertificateParams, DnType, ExtendedKeyUsagePurpose, Issuer, KeyPair, KeyUsagePurpose};
use time::{Duration, OffsetDateTime};
fn main() -> Result<(), Box<dyn Error>> {
let mut args = std::env::args().skip(1);
let signer_keys_file = PathBuf::from(
args.next()
.ok_or("provide signer's pem keys file as 1st argument")?,
);
let signer_cert_file = PathBuf::from(
args.next()
.ok_or("provide signer's pem certificate file as 2nd argument")?,
);
let output_keys_file =
PathBuf::from(args.next().ok_or("output pem keys file as 3rd argument")?);
let output_cert_file = PathBuf::from(args.next().ok_or("output pem cert file as 4th fourth")?);
// Read existing certificate authority
let keys_pem = fs::read_to_string(&signer_keys_file)?;
let cert_pem = fs::read_to_string(&signer_cert_file)?;
let key_pair = KeyPair::from_pem(&keys_pem)?;
let signer = Issuer::from_ca_cert_pem(&cert_pem, key_pair)?;
// Create a new signed server certificate
const DOMAIN: &str = "example.domain";
let sans = vec![DOMAIN.into()];
let mut params = CertificateParams::new(sans)?;
params.distinguished_name.push(DnType::CommonName, DOMAIN);
params.use_authority_key_identifier_extension = true;
params.key_usages.push(KeyUsagePurpose::DigitalSignature);
params
.extended_key_usages
.push(ExtendedKeyUsagePurpose::ServerAuth);
const DAY: Duration = Duration::days(1);
let yesterday = OffsetDateTime::now_utc()
.checked_sub(DAY)
.ok_or("invalid yesterday")?;
let tomorrow = OffsetDateTime::now_utc()
.checked_add(DAY)
.ok_or("invalid tomorrow")?;
params.not_before = yesterday;
params.not_after = tomorrow;
let output_keys = KeyPair::generate()?;
let output_cert = params.signed_by(&output_keys, &signer)?;
// Write new certificate
fs::write(&output_keys_file, output_keys.serialize_pem())?;
fs::write(&output_cert_file, output_cert.pem())?;
println!("Wrote signed leaf certificate:");
println!(" keys: {}", output_keys_file.display());
println!(" cert: {}", output_cert_file.display());
println!();
Ok(())
}

35
vendor/rcgen/examples/simple.rs vendored Normal file
View File

@@ -0,0 +1,35 @@
use std::fs;
use rcgen::{date_time_ymd, CertificateParams, DistinguishedName, DnType, KeyPair, SanType};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut params: CertificateParams = Default::default();
params.not_before = date_time_ymd(1975, 1, 1);
params.not_after = date_time_ymd(4096, 1, 1);
params.distinguished_name = DistinguishedName::new();
params
.distinguished_name
.push(DnType::OrganizationName, "Crab widgits SE");
params
.distinguished_name
.push(DnType::CommonName, "Master Cert");
params.subject_alt_names = vec![
SanType::DnsName("crabs.crabs".try_into()?),
SanType::DnsName("localhost".try_into()?),
];
let key_pair = KeyPair::generate()?;
let cert = params.self_signed(&key_pair)?;
let pem_serialized = cert.pem();
let pem = pem::parse(&pem_serialized)?;
let der_serialized = pem.contents();
println!("{pem_serialized}");
println!("{}", key_pair.serialize_pem());
fs::create_dir_all("certs/")?;
fs::write("certs/cert.pem", pem_serialized.as_bytes())?;
fs::write("certs/cert.der", der_serialized)?;
fs::write("certs/key.pem", key_pair.serialize_pem().as_bytes())?;
fs::write("certs/key.der", key_pair.serialize_der())?;
Ok(())
}

1496
vendor/rcgen/src/certificate.rs vendored Normal file

File diff suppressed because it is too large Load Diff

405
vendor/rcgen/src/crl.rs vendored Normal file
View File

@@ -0,0 +1,405 @@
#[cfg(feature = "pem")]
use pem::Pem;
use pki_types::CertificateRevocationListDer;
use time::OffsetDateTime;
use yasna::{DERWriter, Tag};
use crate::key_pair::sign_der;
#[cfg(feature = "pem")]
use crate::ENCODE_CONFIG;
use crate::{
oid, write_distinguished_name, write_dt_utc_or_generalized,
write_x509_authority_key_identifier, write_x509_extension, Error, Issuer, KeyIdMethod,
KeyUsagePurpose, SerialNumber, SigningKey,
};
/// A certificate revocation list (CRL)
///
/// ## Example
///
/// ```
/// extern crate rcgen;
/// use rcgen::*;
///
/// #[cfg(not(feature = "crypto"))]
/// struct MyKeyPair { public_key: Vec<u8> }
/// #[cfg(not(feature = "crypto"))]
/// impl SigningKey for MyKeyPair {
/// fn sign(&self, _: &[u8]) -> Result<Vec<u8>, rcgen::Error> { Ok(vec![]) }
/// }
/// #[cfg(not(feature = "crypto"))]
/// impl PublicKeyData for MyKeyPair {
/// fn der_bytes(&self) -> &[u8] { &self.public_key }
/// fn algorithm(&self) -> &'static SignatureAlgorithm { &PKCS_ED25519 }
/// }
/// # fn main () {
/// // Generate a CRL issuer.
/// let mut issuer_params = CertificateParams::new(vec!["crl.issuer.example.com".to_string()]).unwrap();
/// issuer_params.serial_number = Some(SerialNumber::from(9999));
/// issuer_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
/// issuer_params.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::DigitalSignature, KeyUsagePurpose::CrlSign];
/// #[cfg(feature = "crypto")]
/// let key_pair = KeyPair::generate().unwrap();
/// #[cfg(not(feature = "crypto"))]
/// let key_pair = MyKeyPair { public_key: vec![] };
/// let issuer = Issuer::new(issuer_params, key_pair);
///
/// // Describe a revoked certificate.
/// let revoked_cert = RevokedCertParams{
/// serial_number: SerialNumber::from(9999),
/// revocation_time: date_time_ymd(2024, 06, 17),
/// reason_code: Some(RevocationReason::KeyCompromise),
/// invalidity_date: None,
/// };
/// // Create a CRL signed by the issuer, revoking revoked_cert.
/// let crl = CertificateRevocationListParams{
/// this_update: date_time_ymd(2023, 06, 17),
/// next_update: date_time_ymd(2024, 06, 17),
/// crl_number: SerialNumber::from(1234),
/// issuing_distribution_point: None,
/// revoked_certs: vec![revoked_cert],
/// #[cfg(feature = "crypto")]
/// key_identifier_method: KeyIdMethod::Sha256,
/// #[cfg(not(feature = "crypto"))]
/// key_identifier_method: KeyIdMethod::PreSpecified(vec![]),
/// }.signed_by(&issuer).unwrap();
///# }
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateRevocationList {
der: CertificateRevocationListDer<'static>,
}
impl CertificateRevocationList {
/// Get the CRL in PEM encoded format.
#[cfg(feature = "pem")]
pub fn pem(&self) -> Result<String, Error> {
let p = Pem::new("X509 CRL", &*self.der);
Ok(pem::encode_config(&p, ENCODE_CONFIG))
}
/// Get the CRL in DER encoded format.
///
/// [`CertificateRevocationListDer`] implements `Deref<Target = [u8]>` and `AsRef<[u8]>`,
/// so you can easily extract the DER bytes from the return value.
pub fn der(&self) -> &CertificateRevocationListDer<'static> {
&self.der
}
}
impl From<CertificateRevocationList> for CertificateRevocationListDer<'static> {
fn from(crl: CertificateRevocationList) -> Self {
crl.der
}
}
/// A certificate revocation list (CRL) distribution point, to be included in a certificate's
/// [distribution points extension](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.13) or
/// a CRL's [issuing distribution point extension](https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5)
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CrlDistributionPoint {
/// One or more URI distribution point names, indicating a place the current CRL can
/// be retrieved. When present, SHOULD include at least one LDAP or HTTP URI.
pub uris: Vec<String>,
}
impl CrlDistributionPoint {
pub(crate) fn write_der(&self, writer: DERWriter) {
// DistributionPoint SEQUENCE
writer.write_sequence(|writer| {
write_distribution_point_name_uris(writer.next(), &self.uris);
});
}
}
fn write_distribution_point_name_uris<'a>(
writer: DERWriter,
uris: impl IntoIterator<Item = &'a String>,
) {
// distributionPoint DistributionPointName
writer.write_tagged_implicit(Tag::context(0), |writer| {
writer.write_sequence(|writer| {
// fullName GeneralNames
writer
.next()
.write_tagged_implicit(Tag::context(0), |writer| {
// GeneralNames
writer.write_sequence(|writer| {
for uri in uris.into_iter() {
// uniformResourceIdentifier [6] IA5String,
writer
.next()
.write_tagged_implicit(Tag::context(6), |writer| {
writer.write_ia5_string(uri)
});
}
})
});
});
});
}
/// Identifies the reason a certificate was revoked.
/// See [RFC 5280 §5.3.1][1]
///
/// [1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[allow(missing_docs)] // Not much to add above the code name.
pub enum RevocationReason {
Unspecified = 0,
KeyCompromise = 1,
CaCompromise = 2,
AffiliationChanged = 3,
Superseded = 4,
CessationOfOperation = 5,
CertificateHold = 6,
// 7 is not defined.
RemoveFromCrl = 8,
PrivilegeWithdrawn = 9,
AaCompromise = 10,
}
/// Parameters used for certificate revocation list (CRL) generation
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateRevocationListParams {
/// Issue date of the CRL.
pub this_update: OffsetDateTime,
/// The date by which the next CRL will be issued.
pub next_update: OffsetDateTime,
/// A monotonically increasing sequence number for a given CRL scope and issuer.
pub crl_number: SerialNumber,
/// An optional CRL extension identifying the CRL distribution point and scope for a
/// particular CRL as described in RFC 5280 Section 5.2.5[^1].
///
/// [^1]: <https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5>
pub issuing_distribution_point: Option<CrlIssuingDistributionPoint>,
/// A list of zero or more parameters describing revoked certificates included in the CRL.
pub revoked_certs: Vec<RevokedCertParams>,
/// Method to generate key identifiers from public keys
///
/// Defaults to SHA-256.
pub key_identifier_method: KeyIdMethod,
}
impl CertificateRevocationListParams {
/// Serializes the certificate revocation list (CRL).
///
/// Including a signature from the issuing certificate authority's key.
pub fn signed_by(
&self,
issuer: &Issuer<'_, impl SigningKey>,
) -> Result<CertificateRevocationList, Error> {
if self.next_update.le(&self.this_update) {
return Err(Error::InvalidCrlNextUpdate);
}
if !issuer.key_usages.is_empty() && !issuer.key_usages.contains(&KeyUsagePurpose::CrlSign) {
return Err(Error::IssuerNotCrlSigner);
}
Ok(CertificateRevocationList {
der: self.serialize_der(issuer)?.into(),
})
}
fn serialize_der(&self, issuer: &Issuer<'_, impl SigningKey>) -> Result<Vec<u8>, Error> {
sign_der(&issuer.signing_key, |writer| {
// Write CRL version.
// RFC 5280 §5.1.2.1:
// This optional field describes the version of the encoded CRL. When
// extensions are used, as required by this profile, this field MUST be
// present and MUST specify version 2 (the integer value is 1).
// RFC 5280 §5.2:
// Conforming CRL issuers are REQUIRED to include the authority key
// identifier (Section 5.2.1) and the CRL number (Section 5.2.3)
// extensions in all CRLs issued.
writer.next().write_u8(1);
// Write algorithm identifier.
// RFC 5280 §5.1.2.2:
// This field MUST contain the same algorithm identifier as the
// signatureAlgorithm field in the sequence CertificateList
issuer
.signing_key
.algorithm()
.write_alg_ident(writer.next());
// Write issuer.
// RFC 5280 §5.1.2.3:
// The issuer field MUST contain a non-empty X.500 distinguished name (DN).
write_distinguished_name(writer.next(), issuer.distinguished_name.as_ref());
// Write thisUpdate date.
// RFC 5280 §5.1.2.4:
// This field indicates the issue date of this CRL. thisUpdate may be
// encoded as UTCTime or GeneralizedTime.
write_dt_utc_or_generalized(writer.next(), self.this_update);
// Write nextUpdate date.
// While OPTIONAL in the ASN.1 module, RFC 5280 §5.1.2.5 says:
// Conforming CRL issuers MUST include the nextUpdate field in all CRLs.
write_dt_utc_or_generalized(writer.next(), self.next_update);
// Write revokedCertificates.
// RFC 5280 §5.1.2.6:
// When there are no revoked certificates, the revoked certificates list
// MUST be absent
if !self.revoked_certs.is_empty() {
writer.next().write_sequence(|writer| {
for revoked_cert in &self.revoked_certs {
revoked_cert.write_der(writer.next());
}
});
}
// Write crlExtensions.
// RFC 5280 §5.1.2.7:
// This field may only appear if the version is 2 (Section 5.1.2.1). If
// present, this field is a sequence of one or more CRL extensions.
// RFC 5280 §5.2:
// Conforming CRL issuers are REQUIRED to include the authority key
// identifier (Section 5.2.1) and the CRL number (Section 5.2.3)
// extensions in all CRLs issued.
writer.next().write_tagged(Tag::context(0), |writer| {
writer.write_sequence(|writer| {
// Write authority key identifier.
write_x509_authority_key_identifier(
writer.next(),
self.key_identifier_method
.derive(issuer.signing_key.subject_public_key_info()),
);
// Write CRL number.
write_x509_extension(writer.next(), oid::CRL_NUMBER, false, |writer| {
writer.write_bigint_bytes(self.crl_number.as_ref(), true);
});
// Write issuing distribution point (if present).
if let Some(issuing_distribution_point) = &self.issuing_distribution_point {
write_x509_extension(
writer.next(),
oid::CRL_ISSUING_DISTRIBUTION_POINT,
true,
|writer| {
issuing_distribution_point.write_der(writer);
},
);
}
});
});
Ok(())
})
}
}
/// A certificate revocation list (CRL) issuing distribution point, to be included in a CRL's
/// [issuing distribution point extension](https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5).
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CrlIssuingDistributionPoint {
/// The CRL's distribution point, containing a sequence of URIs the CRL can be retrieved from.
pub distribution_point: CrlDistributionPoint,
/// An optional description of the CRL's scope. If omitted, the CRL may contain
/// both user certs and CA certs.
pub scope: Option<CrlScope>,
}
impl CrlIssuingDistributionPoint {
fn write_der(&self, writer: DERWriter) {
// IssuingDistributionPoint SEQUENCE
writer.write_sequence(|writer| {
// distributionPoint [0] DistributionPointName OPTIONAL
write_distribution_point_name_uris(writer.next(), &self.distribution_point.uris);
// -- at most one of onlyContainsUserCerts, onlyContainsCACerts,
// -- and onlyContainsAttributeCerts may be set to TRUE.
if let Some(scope) = self.scope {
let tag = match scope {
// onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
CrlScope::UserCertsOnly => Tag::context(1),
// onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
CrlScope::CaCertsOnly => Tag::context(2),
};
writer.next().write_tagged_implicit(tag, |writer| {
writer.write_bool(true);
});
}
});
}
}
/// Describes the scope of a CRL for an issuing distribution point extension.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CrlScope {
/// The CRL contains only end-entity user certificates.
UserCertsOnly,
/// The CRL contains only CA certificates.
CaCertsOnly,
}
/// Parameters used for describing a revoked certificate included in a [`CertificateRevocationList`].
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RevokedCertParams {
/// Serial number identifying the revoked certificate.
pub serial_number: SerialNumber,
/// The date at which the CA processed the revocation.
pub revocation_time: OffsetDateTime,
/// An optional reason code identifying why the certificate was revoked.
pub reason_code: Option<RevocationReason>,
/// An optional field describing the date on which it was known or suspected that the
/// private key was compromised or the certificate otherwise became invalid. This date
/// may be earlier than the [`RevokedCertParams::revocation_time`].
pub invalidity_date: Option<OffsetDateTime>,
}
impl RevokedCertParams {
fn write_der(&self, writer: DERWriter) {
writer.write_sequence(|writer| {
// Write serial number.
// RFC 5280 §4.1.2.2:
// Certificate users MUST be able to handle serialNumber values up to 20 octets.
// Conforming CAs MUST NOT use serialNumber values longer than 20 octets.
//
// Note: Non-conforming CAs may issue certificates with serial numbers
// that are negative or zero. Certificate users SHOULD be prepared to
// gracefully handle such certificates.
writer
.next()
.write_bigint_bytes(self.serial_number.as_ref(), true);
// Write revocation date.
write_dt_utc_or_generalized(writer.next(), self.revocation_time);
// Write extensions if applicable.
// RFC 5280 §5.3:
// Support for the CRL entry extensions defined in this specification is
// optional for conforming CRL issuers and applications. However, CRL
// issuers SHOULD include reason codes (Section 5.3.1) and invalidity
// dates (Section 5.3.2) whenever this information is available.
let has_reason_code =
matches!(self.reason_code, Some(reason) if reason != RevocationReason::Unspecified);
let has_invalidity_date = self.invalidity_date.is_some();
if has_reason_code || has_invalidity_date {
writer.next().write_sequence(|writer| {
// Write reason code if present.
if let Some(reason_code) = self.reason_code {
write_x509_extension(writer.next(), oid::CRL_REASONS, false, |writer| {
writer.write_enum(reason_code as i64);
});
}
// Write invalidity date if present.
if let Some(invalidity_date) = self.invalidity_date {
write_x509_extension(
writer.next(),
oid::CRL_INVALIDITY_DATE,
false,
|writer| {
write_dt_utc_or_generalized(writer, invalidity_date);
},
)
}
});
}
})
}
}

245
vendor/rcgen/src/csr.rs vendored Normal file
View File

@@ -0,0 +1,245 @@
use std::hash::Hash;
#[cfg(feature = "pem")]
use pem::Pem;
use pki_types::CertificateSigningRequestDer;
#[cfg(feature = "pem")]
use crate::ENCODE_CONFIG;
use crate::{
Certificate, CertificateParams, Error, Issuer, PublicKeyData, SignatureAlgorithm, SigningKey,
};
#[cfg(feature = "x509-parser")]
use crate::{DistinguishedName, ExtendedKeyUsagePurpose, KeyUsagePurpose, SanType};
/// A public key, extracted from a CSR
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct PublicKey {
raw: Vec<u8>,
alg: &'static SignatureAlgorithm,
}
impl PublicKey {
/// The algorithm used to generate the public key and sign the CSR.
pub fn algorithm(&self) -> &SignatureAlgorithm {
self.alg
}
}
impl PublicKeyData for PublicKey {
fn der_bytes(&self) -> &[u8] {
&self.raw
}
fn algorithm(&self) -> &'static SignatureAlgorithm {
self.alg
}
}
/// A certificate signing request (CSR) that can be encoded to PEM or DER.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateSigningRequest {
pub(crate) der: CertificateSigningRequestDer<'static>,
}
impl CertificateSigningRequest {
/// Get the PEM-encoded bytes of the certificate signing request.
#[cfg(feature = "pem")]
pub fn pem(&self) -> Result<String, Error> {
let p = Pem::new("CERTIFICATE REQUEST", &*self.der);
Ok(pem::encode_config(&p, ENCODE_CONFIG))
}
/// Get the DER-encoded bytes of the certificate signing request.
///
/// [`CertificateSigningRequestDer`] implements `Deref<Target = [u8]>` and `AsRef<[u8]>`,
/// so you can easily extract the DER bytes from the return value.
pub fn der(&self) -> &CertificateSigningRequestDer<'static> {
&self.der
}
}
impl From<CertificateSigningRequest> for CertificateSigningRequestDer<'static> {
fn from(csr: CertificateSigningRequest) -> Self {
csr.der
}
}
/// Parameters for a certificate signing request
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CertificateSigningRequestParams {
/// Parameters for the certificate to be signed.
pub params: CertificateParams,
/// Public key to include in the certificate signing request.
pub public_key: PublicKey,
}
impl CertificateSigningRequestParams {
/// Parse and verify a certificate signing request from the ASCII PEM format
///
/// See [`from_der`](Self::from_der) for more details.
#[cfg(all(feature = "pem", feature = "x509-parser"))]
pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
let csr = pem::parse(pem_str).map_err(|_| Error::CouldNotParseCertificationRequest)?;
Self::from_der(&csr.contents().into())
}
/// Parse and verify a certificate signing request from DER-encoded bytes
///
/// Currently, this supports the following extensions:
/// - `Subject Alternative Name` (see [`SanType`])
/// - `Key Usage` (see [`KeyUsagePurpose`])
/// - `Extended Key Usage` (see [`ExtendedKeyUsagePurpose`])
///
/// On encountering other extensions, this function will return [`Error::UnsupportedExtension`].
/// If the request's signature is invalid, it will return
/// [`Error::InvalidCertificationRequestSignature`].
///
/// The [`PemObject`] trait is often used to obtain a [`CertificateSigningRequestDer`] from
/// PEM input. If you already have a byte slice containing DER, it can trivially be converted
/// into [`CertificateSigningRequestDer`] using the [`Into`] trait.
///
/// [`PemObject`]: pki_types::pem::PemObject
#[cfg(feature = "x509-parser")]
pub fn from_der(csr: &CertificateSigningRequestDer<'_>) -> Result<Self, Error> {
use x509_parser::prelude::FromDer;
let csr = x509_parser::certification_request::X509CertificationRequest::from_der(csr)
.map_err(|_| Error::CouldNotParseCertificationRequest)?
.1;
csr.verify_signature()
.map_err(|_| Error::InvalidCertificationRequestSignature)?;
let alg_oid = csr
.signature_algorithm
.algorithm
.iter()
.ok_or(Error::CouldNotParseCertificationRequest)?
.collect::<Vec<_>>();
let alg = SignatureAlgorithm::from_oid(&alg_oid)?;
let info = &csr.certification_request_info;
let mut params = CertificateParams {
distinguished_name: DistinguishedName::from_name(&info.subject)?,
..CertificateParams::default()
};
let raw = info.subject_pki.subject_public_key.data.to_vec();
if let Some(extensions) = csr.requested_extensions() {
for ext in extensions {
match ext {
x509_parser::extensions::ParsedExtension::KeyUsage(key_usage) => {
// This x509 parser stores flags in reversed bit BIT STRING order
params.key_usages =
KeyUsagePurpose::from_u16(key_usage.flags.reverse_bits());
},
x509_parser::extensions::ParsedExtension::SubjectAlternativeName(san) => {
for name in &san.general_names {
params
.subject_alt_names
.push(SanType::try_from_general(name)?);
}
},
x509_parser::extensions::ParsedExtension::ExtendedKeyUsage(eku) => {
if eku.any {
params.insert_extended_key_usage(ExtendedKeyUsagePurpose::Any);
}
if eku.server_auth {
params.insert_extended_key_usage(ExtendedKeyUsagePurpose::ServerAuth);
}
if eku.client_auth {
params.insert_extended_key_usage(ExtendedKeyUsagePurpose::ClientAuth);
}
if eku.code_signing {
params.insert_extended_key_usage(ExtendedKeyUsagePurpose::CodeSigning);
}
if eku.email_protection {
params.insert_extended_key_usage(
ExtendedKeyUsagePurpose::EmailProtection,
);
}
if eku.time_stamping {
params.insert_extended_key_usage(ExtendedKeyUsagePurpose::TimeStamping);
}
if eku.ocsp_signing {
params.insert_extended_key_usage(ExtendedKeyUsagePurpose::OcspSigning);
}
if !eku.other.is_empty() {
return Err(Error::UnsupportedExtension);
}
},
_ => return Err(Error::UnsupportedExtension),
}
}
}
// Not yet handled:
// * is_ca
// * name_constraints
// and any other extensions.
Ok(Self {
params,
public_key: PublicKey { alg, raw },
})
}
/// Generate a new certificate based on the requested parameters, signed by the provided
/// issuer.
///
/// The returned certificate will have its issuer field set to the subject of the provided
/// `issuer`, and the authority key identifier extension will be populated using the subject
/// public key of `issuer`. It will be signed by `issuer_key`.
///
/// Note that no validation of the `issuer` certificate is performed. Rcgen will not require
/// the certificate to be a CA certificate, or have key usage extensions that allow signing.
///
/// The returned [`Certificate`] may be serialized using [`Certificate::der`] and
/// [`Certificate::pem`].
pub fn signed_by(&self, issuer: &Issuer<impl SigningKey>) -> Result<Certificate, Error> {
Ok(Certificate {
der: self
.params
.serialize_der_with_signer(&self.public_key, issuer)?,
})
}
}
#[cfg(all(test, feature = "x509-parser"))]
mod tests {
use x509_parser::certification_request::X509CertificationRequest;
use x509_parser::prelude::{FromDer, ParsedExtension};
use crate::{CertificateParams, ExtendedKeyUsagePurpose, KeyPair, KeyUsagePurpose};
#[test]
fn dont_write_sans_extension_if_no_sans_are_present() {
let mut params = CertificateParams::default();
params.key_usages.push(KeyUsagePurpose::DigitalSignature);
let key_pair = KeyPair::generate().unwrap();
let csr = params.serialize_request(&key_pair).unwrap();
let (_, parsed_csr) = X509CertificationRequest::from_der(csr.der()).unwrap();
assert!(!parsed_csr
.requested_extensions()
.unwrap()
.any(|ext| matches!(ext, ParsedExtension::SubjectAlternativeName(_))));
}
#[test]
fn write_extension_request_if_ekus_are_present() {
let mut params = CertificateParams::default();
params
.extended_key_usages
.push(ExtendedKeyUsagePurpose::ClientAuth);
let key_pair = KeyPair::generate().unwrap();
let csr = params.serialize_request(&key_pair).unwrap();
let (_, parsed_csr) = X509CertificationRequest::from_der(csr.der()).unwrap();
let requested_extensions = parsed_csr
.requested_extensions()
.unwrap()
.collect::<Vec<_>>();
assert!(matches!(
requested_extensions.first().unwrap(),
ParsedExtension::ExtendedKeyUsage(_)
));
}
}

148
vendor/rcgen/src/error.rs vendored Normal file
View File

@@ -0,0 +1,148 @@
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
/// The error type of the rcgen crate
pub enum Error {
/// The given certificate couldn't be parsed
CouldNotParseCertificate,
/// The given certificate signing request couldn't be parsed
CouldNotParseCertificationRequest,
/// The given key pair couldn't be parsed
CouldNotParseKeyPair,
/// The CSR signature is invalid
#[cfg(feature = "x509-parser")]
InvalidCertificationRequestSignature,
#[cfg(feature = "x509-parser")]
/// Invalid subject alternative name type
InvalidNameType,
/// Invalid ASN.1 string
InvalidAsn1String(InvalidAsn1String),
/// An IP address was provided as a byte array, but the byte array was an invalid length.
InvalidIpAddressOctetLength(usize),
/// There is no support for generating
/// keys for the given algorithm
KeyGenerationUnavailable,
#[cfg(feature = "x509-parser")]
/// Unsupported extension requested in CSR
UnsupportedExtension,
/// The requested signature algorithm is not supported
UnsupportedSignatureAlgorithm,
/// Unspecified `ring` error
RingUnspecified,
/// The `ring` library rejected the key upon loading
RingKeyRejected(String),
/// Time conversion related errors
Time,
#[cfg(feature = "pem")]
/// Error from the pem crate
PemError(String),
/// Error generated by a remote key operation
RemoteKeyError,
/// Unsupported field when generating a CSR
UnsupportedInCsr,
/// Invalid certificate revocation list (CRL) next update.
InvalidCrlNextUpdate,
/// CRL issuer specifies Key Usages that don't include cRLSign.
IssuerNotCrlSigner,
#[cfg(not(feature = "crypto"))]
/// Missing serial number
MissingSerialNumber,
/// X509 parsing error
#[cfg(feature = "x509-parser")]
X509(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
match self {
CouldNotParseCertificate => write!(f, "Could not parse certificate")?,
CouldNotParseCertificationRequest => write!(
f,
"Could not parse certificate signing \
request"
)?,
CouldNotParseKeyPair => write!(f, "Could not parse key pair")?,
#[cfg(feature = "x509-parser")]
InvalidCertificationRequestSignature => write!(f, "Invalid CSR signature")?,
#[cfg(feature = "x509-parser")]
InvalidNameType => write!(f, "Invalid subject alternative name type")?,
InvalidAsn1String(e) => write!(f, "{e}")?,
InvalidIpAddressOctetLength(actual) => {
write!(f, "Invalid IP address octet length of {actual} bytes")?
},
KeyGenerationUnavailable => write!(
f,
"There is no support for generating \
keys for the given algorithm"
)?,
UnsupportedSignatureAlgorithm => write!(
f,
"The requested signature algorithm \
is not supported"
)?,
#[cfg(feature = "x509-parser")]
UnsupportedExtension => write!(f, "Unsupported extension requested in CSR")?,
RingUnspecified => write!(f, "Unspecified ring error")?,
RingKeyRejected(e) => write!(f, "Key rejected by ring: {e}")?,
Time => write!(f, "Time error")?,
RemoteKeyError => write!(f, "Remote key error")?,
#[cfg(feature = "pem")]
PemError(e) => write!(f, "PEM error: {e}")?,
UnsupportedInCsr => write!(f, "Certificate parameter unsupported in CSR")?,
InvalidCrlNextUpdate => write!(f, "Invalid CRL next update parameter")?,
IssuerNotCrlSigner => write!(
f,
"CRL issuer must specify no key usage, or key usage including cRLSign"
)?,
#[cfg(not(feature = "crypto"))]
MissingSerialNumber => write!(f, "A serial number must be specified")?,
#[cfg(feature = "x509-parser")]
X509(e) => write!(f, "X.509 parsing error: {e}")?,
};
Ok(())
}
}
impl std::error::Error for Error {}
/// Invalid ASN.1 string type
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum InvalidAsn1String {
/// Invalid PrintableString type
PrintableString(String),
/// Invalid UniversalString type
UniversalString(String),
/// Invalid Ia5String type
Ia5String(String),
/// Invalid TeletexString type
TeletexString(String),
/// Invalid BmpString type
BmpString(String),
}
impl fmt::Display for InvalidAsn1String {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use InvalidAsn1String::*;
match self {
PrintableString(s) => write!(f, "Invalid PrintableString: '{s}'")?,
Ia5String(s) => write!(f, "Invalid IA5String: '{s}'")?,
BmpString(s) => write!(f, "Invalid BMPString: '{s}'")?,
UniversalString(s) => write!(f, "Invalid UniversalString: '{s}'")?,
TeletexString(s) => write!(f, "Invalid TeletexString: '{s}'")?,
};
Ok(())
}
}
/// A trait describing an error that can be converted into an `rcgen::Error`.
///
/// We use this trait to avoid leaking external error types into the public API
/// through a `From<x> for Error` implementation.
#[cfg(any(feature = "crypto", feature = "pem"))]
pub(crate) trait ExternalError<T>: Sized {
fn _err(self) -> Result<T, Error>;
}

826
vendor/rcgen/src/key_pair.rs vendored Normal file
View File

@@ -0,0 +1,826 @@
#[cfg(feature = "crypto")]
use std::fmt;
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
use aws_lc_rs::unstable::signature::PqdsaKeyPair;
#[cfg(feature = "pem")]
use pem::Pem;
#[cfg(feature = "crypto")]
use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
use yasna::{DERWriter, DERWriterSeq};
#[cfg(any(feature = "crypto", feature = "pem"))]
use crate::error::ExternalError;
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
use crate::ring_like::ecdsa_from_private_key_der;
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
use crate::ring_like::rsa::KeySize;
#[cfg(feature = "crypto")]
use crate::ring_like::{
error as ring_error,
rand::SystemRandom,
signature::{
self, EcdsaKeyPair, Ed25519KeyPair, KeyPair as RingKeyPair, RsaEncoding, RsaKeyPair,
},
{ecdsa_from_pkcs8, rsa_key_pair_public_modulus_len},
};
use crate::sign_algo::SignatureAlgorithm;
#[cfg(feature = "crypto")]
use crate::sign_algo::{algo::*, SignAlgo};
use crate::Error;
#[cfg(feature = "pem")]
use crate::ENCODE_CONFIG;
/// A key pair variant
#[allow(clippy::large_enum_variant)]
#[cfg(feature = "crypto")]
pub(crate) enum KeyPairKind {
/// A Ecdsa key pair
Ec(EcdsaKeyPair),
/// A Ed25519 key pair
Ed(Ed25519KeyPair),
/// A Pqdsa key pair
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
Pq(PqdsaKeyPair),
/// A RSA key pair
Rsa(RsaKeyPair, &'static dyn RsaEncoding),
}
#[cfg(feature = "crypto")]
impl fmt::Debug for KeyPairKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Ec(key_pair) => write!(f, "{key_pair:?}"),
Self::Ed(key_pair) => write!(f, "{key_pair:?}"),
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
Self::Pq(key_pair) => write!(f, "{key_pair:?}"),
Self::Rsa(key_pair, _) => write!(f, "{key_pair:?}"),
}
}
}
/// A key pair used to sign certificates and CSRs
#[cfg(feature = "crypto")]
pub struct KeyPair {
pub(crate) kind: KeyPairKind,
pub(crate) alg: &'static SignatureAlgorithm,
pub(crate) serialized_der: Vec<u8>,
}
#[cfg(feature = "crypto")]
impl fmt::Debug for KeyPair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("KeyPair")
.field("kind", &self.kind)
.field("alg", &self.alg)
.field("serialized_der", &"[secret key elided]")
.finish()
}
}
#[cfg(feature = "crypto")]
impl KeyPair {
/// Generate a new random [`PKCS_ECDSA_P256_SHA256`] key pair
#[cfg(feature = "crypto")]
pub fn generate() -> Result<Self, Error> {
Self::generate_for(&PKCS_ECDSA_P256_SHA256)
}
/// Generate a new random key pair for the specified signature algorithm
///
/// If you're not sure which algorithm to use, [`PKCS_ECDSA_P256_SHA256`] is a good choice.
/// If passed an RSA signature algorithm, it depends on the backend whether we return
/// a generated key or an error for key generation being unavailable.
/// Currently, only `aws-lc-rs` supports RSA key generation.
#[cfg(feature = "crypto")]
pub fn generate_for(alg: &'static SignatureAlgorithm) -> Result<Self, Error> {
let rng = &SystemRandom::new();
match alg.sign_alg {
SignAlgo::EcDsa(sign_alg) => {
let key_pair_doc = EcdsaKeyPair::generate_pkcs8(sign_alg, rng)._err()?;
let key_pair_serialized = key_pair_doc.as_ref().to_vec();
let key_pair = ecdsa_from_pkcs8(sign_alg, key_pair_doc.as_ref(), rng).unwrap();
Ok(KeyPair {
kind: KeyPairKind::Ec(key_pair),
alg,
serialized_der: key_pair_serialized,
})
},
SignAlgo::EdDsa(_sign_alg) => {
let key_pair_doc = Ed25519KeyPair::generate_pkcs8(rng)._err()?;
let key_pair_serialized = key_pair_doc.as_ref().to_vec();
let key_pair = Ed25519KeyPair::from_pkcs8(key_pair_doc.as_ref()).unwrap();
Ok(KeyPair {
kind: KeyPairKind::Ed(key_pair),
alg,
serialized_der: key_pair_serialized,
})
},
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
SignAlgo::PqDsa(sign_alg) => {
let key_pair = PqdsaKeyPair::generate(sign_alg)._err()?;
let key_pair_serialized = key_pair.to_pkcs8()._err()?.as_ref().to_vec();
Ok(KeyPair {
kind: KeyPairKind::Pq(key_pair),
alg,
serialized_der: key_pair_serialized,
})
},
#[cfg(feature = "aws_lc_rs")]
SignAlgo::Rsa(sign_alg) => Self::generate_rsa_inner(alg, sign_alg, KeySize::Rsa2048),
// Ring doesn't have RSA key generation yet:
// https://github.com/briansmith/ring/issues/219
// https://github.com/briansmith/ring/pull/733
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
SignAlgo::Rsa(_sign_alg) => Err(Error::KeyGenerationUnavailable),
}
}
/// Generates a new random RSA key pair for the specified key size
///
/// If passed a signature algorithm that is not RSA, it will return
/// [`Error::KeyGenerationUnavailable`].
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
pub fn generate_rsa_for(
alg: &'static SignatureAlgorithm,
key_size: RsaKeySize,
) -> Result<Self, Error> {
match alg.sign_alg {
SignAlgo::Rsa(sign_alg) => {
let key_size = match key_size {
RsaKeySize::_2048 => KeySize::Rsa2048,
RsaKeySize::_3072 => KeySize::Rsa3072,
RsaKeySize::_4096 => KeySize::Rsa4096,
};
Self::generate_rsa_inner(alg, sign_alg, key_size)
},
_ => Err(Error::KeyGenerationUnavailable),
}
}
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
fn generate_rsa_inner(
alg: &'static SignatureAlgorithm,
sign_alg: &'static dyn RsaEncoding,
key_size: KeySize,
) -> Result<Self, Error> {
use aws_lc_rs::encoding::AsDer;
let key_pair = RsaKeyPair::generate(key_size)._err()?;
let key_pair_serialized = key_pair.as_der()._err()?.as_ref().to_vec();
Ok(KeyPair {
kind: KeyPairKind::Rsa(key_pair, sign_alg),
alg,
serialized_der: key_pair_serialized,
})
}
/// Returns the key pair's signature algorithm
pub fn algorithm(&self) -> &'static SignatureAlgorithm {
self.alg
}
/// Parses the key pair from the ASCII PEM format
///
/// If `aws_lc_rs` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958, SEC1/RFC 5915, or PKCS#1/RFC 3447;
/// Appears as "PRIVATE KEY", "RSA PRIVATE KEY", or "EC PRIVATE KEY" in PEM files.
///
/// Otherwise if the `ring` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY" in PEM files.
#[cfg(all(feature = "pem", feature = "crypto"))]
pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
let private_key = pem::parse(pem_str)._err()?;
Self::try_from(private_key.contents())
}
/// Obtains the key pair from a DER formatted key
/// using the specified [`SignatureAlgorithm`]
///
/// The key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958;
///
/// Appears as "PRIVATE KEY" in PEM files
/// Same as [from_pkcs8_pem_and_sign_algo](Self::from_pkcs8_pem_and_sign_algo).
#[cfg(all(feature = "pem", feature = "crypto"))]
pub fn from_pkcs8_pem_and_sign_algo(
pem_str: &str,
alg: &'static SignatureAlgorithm,
) -> Result<Self, Error> {
let private_key = pem::parse(pem_str)._err()?;
let private_key_der: &[_] = private_key.contents();
Self::from_pkcs8_der_and_sign_algo(&PrivatePkcs8KeyDer::from(private_key_der), alg)
}
/// Obtains the key pair from a DER formatted key using the specified [`SignatureAlgorithm`]
///
/// If you have a [`PrivatePkcs8KeyDer`], you can usually rely on the [`TryFrom`] implementation
/// to obtain a [`KeyPair`] -- it will determine the correct [`SignatureAlgorithm`] for you.
/// However, sometimes multiple signature algorithms fit for the same DER key. In those instances,
/// you can use this function to precisely specify the `SignatureAlgorithm`.
///
/// [`rustls_pemfile::private_key()`] is often used to obtain a [`PrivateKeyDer`] from PEM
/// input. If the obtained [`PrivateKeyDer`] is a `Pkcs8` variant, you can use its contents
/// as input for this function. Alternatively, if you already have a byte slice containing DER,
/// it can trivially be converted into [`PrivatePkcs8KeyDer`] using the [`Into`] trait.
///
/// [`rustls_pemfile::private_key()`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.private_key.html
/// [`PrivateKeyDer`]: https://docs.rs/rustls-pki-types/latest/rustls_pki_types/enum.PrivateKeyDer.html
#[cfg(feature = "crypto")]
pub fn from_pkcs8_der_and_sign_algo(
pkcs8: &PrivatePkcs8KeyDer<'_>,
alg: &'static SignatureAlgorithm,
) -> Result<Self, Error> {
let rng = &SystemRandom::new();
let serialized_der = pkcs8.secret_pkcs8_der().to_vec();
let kind = if alg == &PKCS_ED25519 {
KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
} else if alg == &PKCS_ECDSA_P256_SHA256 {
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&serialized_der,
rng,
)?)
} else if alg == &PKCS_ECDSA_P384_SHA384 {
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P384_SHA384_ASN1_SIGNING,
&serialized_der,
rng,
)?)
} else if alg == &PKCS_RSA_SHA256 {
let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
} else if alg == &PKCS_RSA_SHA384 {
let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
} else if alg == &PKCS_RSA_SHA512 {
let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
} else if alg == &PKCS_RSA_PSS_SHA256 {
let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
} else {
#[cfg(feature = "aws_lc_rs")]
if alg == &PKCS_ECDSA_P521_SHA256 {
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P521_SHA256_ASN1_SIGNING,
&serialized_der,
rng,
)?)
} else if alg == &PKCS_ECDSA_P521_SHA384 {
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P521_SHA384_ASN1_SIGNING,
&serialized_der,
rng,
)?)
} else if alg == &PKCS_ECDSA_P521_SHA512 {
KeyPairKind::Ec(ecdsa_from_pkcs8(
&signature::ECDSA_P521_SHA512_ASN1_SIGNING,
&serialized_der,
rng,
)?)
} else {
panic!("Unknown SignatureAlgorithm specified!");
}
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
panic!("Unknown SignatureAlgorithm specified!");
};
Ok(KeyPair {
kind,
alg,
serialized_der,
})
}
/// Obtains the key pair from a PEM formatted key
/// using the specified [`SignatureAlgorithm`]
///
/// If `aws_lc_rs` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958, SEC1/RFC 5915, or PKCS#1/RFC 3447;
/// Appears as "PRIVATE KEY", "RSA PRIVATE KEY", or "EC PRIVATE KEY" in PEM files.
///
/// Otherwise if the `ring` feature is used, then the key must be a DER-encoded plaintext private key; as specified in PKCS #8/RFC 5958;
/// Appears as "PRIVATE KEY" in PEM files.
///
/// Same as [from_pem_and_sign_algo](Self::from_pem_and_sign_algo).
#[cfg(all(feature = "pem", feature = "crypto"))]
pub fn from_pem_and_sign_algo(
pem_str: &str,
alg: &'static SignatureAlgorithm,
) -> Result<Self, Error> {
let private_key = pem::parse(pem_str)._err()?;
let private_key: &[_] = private_key.contents();
Self::from_der_and_sign_algo(
&PrivateKeyDer::try_from(private_key).map_err(|_| Error::CouldNotParseKeyPair)?,
alg,
)
}
/// Obtains the key pair from a DER formatted key
/// using the specified [`SignatureAlgorithm`]
///
/// Note that using the `ring` feature, this function only support [`PrivateKeyDer::Pkcs8`] variant.
/// Consider using the `aws_lc_rs` features to support [`PrivateKeyDer`] fully.
///
/// If you have a [`PrivateKeyDer`], you can usually rely on the [`TryFrom`] implementation
/// to obtain a [`KeyPair`] -- it will determine the correct [`SignatureAlgorithm`] for you.
/// However, sometimes multiple signature algorithms fit for the same DER key. In those instances,
/// you can use this function to precisely specify the `SignatureAlgorithm`.
///
/// You can use [`rustls_pemfile::private_key`] to get the `key` input. If
/// you have already a byte slice, just calling `try_into()` will convert it to a [`PrivateKeyDer`].
///
/// [`rustls_pemfile::private_key`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.private_key.html
#[cfg(feature = "crypto")]
pub fn from_der_and_sign_algo(
key: &PrivateKeyDer<'_>,
alg: &'static SignatureAlgorithm,
) -> Result<Self, Error> {
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
{
if let PrivateKeyDer::Pkcs8(key) = key {
Self::from_pkcs8_der_and_sign_algo(key, alg)
} else {
Err(Error::CouldNotParseKeyPair)
}
}
#[cfg(feature = "aws_lc_rs")]
{
let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
let rsa_key_pair_from = if is_pkcs8 {
RsaKeyPair::from_pkcs8
} else {
RsaKeyPair::from_der
};
let serialized_der = key.secret_der().to_vec();
let kind = if alg == &PKCS_ED25519 {
KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
} else if alg == &PKCS_ECDSA_P256_SHA256 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_ECDSA_P384_SHA384 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P384_SHA384_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_ECDSA_P521_SHA512 {
KeyPairKind::Ec(ecdsa_from_private_key_der(
&signature::ECDSA_P521_SHA512_ASN1_SIGNING,
&serialized_der,
)?)
} else if alg == &PKCS_RSA_SHA256 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
} else if alg == &PKCS_RSA_SHA384 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
} else if alg == &PKCS_RSA_SHA512 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
} else if alg == &PKCS_RSA_PSS_SHA256 {
let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
} else {
panic!("Unknown SignatureAlgorithm specified!");
};
Ok(KeyPair {
kind,
alg,
serialized_der,
})
}
}
/// Get the raw public key of this key pair
///
/// The key is in raw format, as how [`KeyPair::public_key()`][public_key]
/// would output, and how [`UnparsedPublicKey::verify()`][verify]
/// would accept.
///
/// [public_key]: crate::ring_like::signature::KeyPair::public_key()
/// [verify]: crate::ring_like::signature::UnparsedPublicKey::verify()
pub fn public_key_raw(&self) -> &[u8] {
self.der_bytes()
}
/// Check if this key pair can be used with the given signature algorithm
pub fn is_compatible(&self, signature_algorithm: &SignatureAlgorithm) -> bool {
self.alg == signature_algorithm
}
/// Returns (possibly multiple) compatible [`SignatureAlgorithm`]'s
/// that the key can be used with
pub fn compatible_algs(&self) -> impl Iterator<Item = &'static SignatureAlgorithm> {
std::iter::once(self.alg)
}
/// Return the key pair's public key in PEM format
///
/// The returned string can be interpreted with `openssl pkey --inform PEM -pubout -pubin -text`
#[cfg(feature = "pem")]
pub fn public_key_pem(&self) -> String {
let contents = self.subject_public_key_info();
let p = Pem::new("PUBLIC KEY", contents);
pem::encode_config(&p, ENCODE_CONFIG)
}
/// Serializes the key pair (including the private key) in PKCS#8 format in DER
pub fn serialize_der(&self) -> Vec<u8> {
self.serialized_der.clone()
}
/// Returns a reference to the serialized key pair (including the private key)
/// in PKCS#8 format in DER
pub fn serialized_der(&self) -> &[u8] {
&self.serialized_der
}
/// Serializes the key pair (including the private key) in PKCS#8 format in PEM
#[cfg(feature = "pem")]
pub fn serialize_pem(&self) -> String {
let contents = self.serialize_der();
let p = Pem::new("PRIVATE KEY", contents);
pem::encode_config(&p, ENCODE_CONFIG)
}
}
#[cfg(feature = "crypto")]
impl SigningKey for KeyPair {
fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
Ok(match &self.kind {
KeyPairKind::Ec(kp) => {
let system_random = SystemRandom::new();
let signature = kp.sign(&system_random, msg)._err()?;
signature.as_ref().to_owned()
},
KeyPairKind::Ed(kp) => kp.sign(msg).as_ref().to_owned(),
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
KeyPairKind::Pq(kp) => {
let mut signature = vec![0; kp.algorithm().signature_len()];
kp.sign(msg, &mut signature)._err()?;
signature
},
KeyPairKind::Rsa(kp, padding_alg) => {
let system_random = SystemRandom::new();
let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
kp.sign(*padding_alg, &system_random, msg, &mut signature)
._err()?;
signature
},
})
}
}
#[cfg(feature = "crypto")]
impl PublicKeyData for KeyPair {
fn der_bytes(&self) -> &[u8] {
match &self.kind {
KeyPairKind::Ec(kp) => kp.public_key().as_ref(),
KeyPairKind::Ed(kp) => kp.public_key().as_ref(),
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
KeyPairKind::Pq(kp) => kp.public_key().as_ref(),
KeyPairKind::Rsa(kp, _) => kp.public_key().as_ref(),
}
}
fn algorithm(&self) -> &'static SignatureAlgorithm {
self.alg
}
}
#[cfg(feature = "crypto")]
impl TryFrom<&[u8]> for KeyPair {
type Error = Error;
fn try_from(key: &[u8]) -> Result<KeyPair, Error> {
let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
key.try_into()
}
}
#[cfg(feature = "crypto")]
impl TryFrom<Vec<u8>> for KeyPair {
type Error = Error;
fn try_from(key: Vec<u8>) -> Result<KeyPair, Error> {
let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
key.try_into()
}
}
#[cfg(feature = "crypto")]
impl TryFrom<&PrivatePkcs8KeyDer<'_>> for KeyPair {
type Error = Error;
fn try_from(key: &PrivatePkcs8KeyDer) -> Result<KeyPair, Error> {
key.secret_pkcs8_der().try_into()
}
}
#[cfg(feature = "crypto")]
impl TryFrom<&PrivateKeyDer<'_>> for KeyPair {
type Error = Error;
fn try_from(key: &PrivateKeyDer) -> Result<KeyPair, Error> {
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
let (kind, alg) = {
let PrivateKeyDer::Pkcs8(pkcs8) = key else {
return Err(Error::CouldNotParseKeyPair);
};
let pkcs8 = pkcs8.secret_pkcs8_der();
let rng = SystemRandom::new();
let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8) {
(KeyPairKind::Ed(edkp), &PKCS_ED25519)
} else if let Ok(eckp) =
ecdsa_from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, &rng)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
} else if let Ok(eckp) =
ecdsa_from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, &rng)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
} else if let Ok(rsakp) = RsaKeyPair::from_pkcs8(pkcs8) {
(
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
&PKCS_RSA_SHA256,
)
} else {
return Err(Error::CouldNotParseKeyPair);
};
(kind, alg)
};
#[cfg(feature = "aws_lc_rs")]
let (kind, alg) = {
let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
let key = key.secret_der();
let rsa_key_pair_from = if is_pkcs8 {
RsaKeyPair::from_pkcs8
} else {
RsaKeyPair::from_der
};
let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(key) {
(KeyPairKind::Ed(edkp), &PKCS_ED25519)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
} else if let Ok(eckp) =
ecdsa_from_private_key_der(&signature::ECDSA_P521_SHA512_ASN1_SIGNING, key)
{
(KeyPairKind::Ec(eckp), &PKCS_ECDSA_P521_SHA512)
} else if let Ok(rsakp) = rsa_key_pair_from(key) {
(
KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
&PKCS_RSA_SHA256,
)
} else {
return Err(Error::CouldNotParseKeyPair);
};
(kind, alg)
};
Ok(KeyPair {
kind,
alg,
serialized_der: key.secret_der().into(),
})
}
}
#[cfg(feature = "crypto")]
impl From<KeyPair> for PrivatePkcs8KeyDer<'static> {
fn from(val: KeyPair) -> Self {
val.serialize_der().into()
}
}
#[cfg(feature = "crypto")]
impl From<KeyPair> for PrivateKeyDer<'static> {
fn from(val: KeyPair) -> Self {
Self::from(PrivatePkcs8KeyDer::from(val))
}
}
/// The key size used for RSA key generation
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RsaKeySize {
/// 2048 bits
_2048,
/// 3072 bits
_3072,
/// 4096 bits
_4096,
}
pub(crate) fn sign_der(
key: &impl SigningKey,
f: impl FnOnce(&mut DERWriterSeq<'_>) -> Result<(), Error>,
) -> Result<Vec<u8>, Error> {
yasna::try_construct_der(|writer| {
writer.write_sequence(|writer| {
let data = yasna::try_construct_der(|writer| writer.write_sequence(f))?;
writer.next().write_der(&data);
// Write signatureAlgorithm
key.algorithm().write_alg_ident(writer.next());
// Write signature
let sig = key.sign(&data)?;
let writer = writer.next();
writer.write_bitvec_bytes(&sig, sig.len() * 8);
Ok(())
})
})
}
impl<S: SigningKey + ?Sized> SigningKey for &S {
fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
(*self).sign(msg)
}
}
/// A key that can be used to sign messages
pub trait SigningKey: PublicKeyData {
/// Signs `msg` using the selected algorithm
fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error>;
}
#[cfg(feature = "crypto")]
impl<T> ExternalError<T> for Result<T, ring_error::KeyRejected> {
fn _err(self) -> Result<T, Error> {
self.map_err(|e| Error::RingKeyRejected(e.to_string()))
}
}
#[cfg(feature = "crypto")]
impl<T> ExternalError<T> for Result<T, ring_error::Unspecified> {
fn _err(self) -> Result<T, Error> {
self.map_err(|_| Error::RingUnspecified)
}
}
#[cfg(feature = "pem")]
impl<T> ExternalError<T> for Result<T, pem::PemError> {
fn _err(self) -> Result<T, Error> {
self.map_err(|e| Error::PemError(e.to_string()))
}
}
/// A public key
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SubjectPublicKeyInfo {
pub(crate) alg: &'static SignatureAlgorithm,
pub(crate) subject_public_key: Vec<u8>,
}
impl SubjectPublicKeyInfo {
/// Create a `SubjectPublicKey` value from a PEM-encoded SubjectPublicKeyInfo string
#[cfg(all(feature = "x509-parser", feature = "pem"))]
pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
Self::from_der(&pem::parse(pem_str)._err()?.into_contents())
}
/// Create a `SubjectPublicKey` value from DER-encoded SubjectPublicKeyInfo bytes
#[cfg(feature = "x509-parser")]
pub fn from_der(spki_der: &[u8]) -> Result<Self, Error> {
use x509_parser::prelude::FromDer;
use x509_parser::x509::{AlgorithmIdentifier, SubjectPublicKeyInfo};
let (rem, spki) =
SubjectPublicKeyInfo::from_der(spki_der).map_err(|e| Error::X509(e.to_string()))?;
if !rem.is_empty() {
return Err(Error::X509(
"trailing bytes in SubjectPublicKeyInfo".to_string(),
));
}
let alg = SignatureAlgorithm::iter()
.find(|alg| {
let bytes = yasna::construct_der(|writer| {
alg.write_oids_sign_alg(writer);
});
let Ok((rest, aid)) = AlgorithmIdentifier::from_der(&bytes) else {
return false;
};
if !rest.is_empty() {
return false;
}
aid == spki.algorithm
})
.ok_or(Error::UnsupportedSignatureAlgorithm)?;
Ok(Self {
alg,
subject_public_key: Vec::from(spki.subject_public_key.as_ref()),
})
}
}
impl PublicKeyData for SubjectPublicKeyInfo {
fn der_bytes(&self) -> &[u8] {
&self.subject_public_key
}
fn algorithm(&self) -> &'static SignatureAlgorithm {
self.alg
}
}
impl<K: PublicKeyData + ?Sized> PublicKeyData for &K {
fn der_bytes(&self) -> &[u8] {
(*self).der_bytes()
}
fn algorithm(&self) -> &'static SignatureAlgorithm {
(*self).algorithm()
}
}
/// The public key data of a key pair
pub trait PublicKeyData {
/// The public key data in DER format
///
/// The key is formatted according to the X.509 SubjectPublicKeyInfo struct.
/// See [RFC 5280 section 4.1](https://tools.ietf.org/html/rfc5280#section-4.1).
fn subject_public_key_info(&self) -> Vec<u8> {
yasna::construct_der(|writer| serialize_public_key_der(self, writer))
}
/// The public key in DER format
fn der_bytes(&self) -> &[u8];
/// The algorithm used by the key pair
fn algorithm(&self) -> &'static SignatureAlgorithm;
}
pub(crate) fn serialize_public_key_der(key: &(impl PublicKeyData + ?Sized), writer: DERWriter) {
writer.write_sequence(|writer| {
key.algorithm().write_oids_sign_alg(writer.next());
let pk = key.der_bytes();
writer.next().write_bitvec_bytes(pk, pk.len() * 8);
})
}
#[cfg(all(test, feature = "crypto"))]
mod test {
use super::*;
use crate::ring_like::rand::SystemRandom;
use crate::ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};
#[cfg(all(feature = "x509-parser", feature = "pem"))]
#[test]
fn test_subject_public_key_parsing() {
for alg in [
&PKCS_ED25519,
&PKCS_ECDSA_P256_SHA256,
&PKCS_ECDSA_P384_SHA384,
#[cfg(feature = "aws_lc_rs")]
&PKCS_ECDSA_P521_SHA512,
#[cfg(feature = "aws_lc_rs")]
&PKCS_RSA_SHA256,
] {
let kp = KeyPair::generate_for(alg).expect("keygen");
let pem = kp.public_key_pem();
let der = kp.subject_public_key_info();
let pkd_pem = SubjectPublicKeyInfo::from_pem(&pem).expect("from pem");
assert_eq!(kp.der_bytes(), pkd_pem.der_bytes());
let pkd_der = SubjectPublicKeyInfo::from_der(&der).expect("from der");
assert_eq!(kp.der_bytes(), pkd_der.der_bytes());
}
}
#[test]
fn test_algorithm() {
let rng = SystemRandom::new();
let pkcs8 = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng).unwrap();
let der = pkcs8.as_ref().to_vec();
let key_pair = KeyPair::try_from(der).unwrap();
assert_eq!(key_pair.algorithm(), &PKCS_ECDSA_P256_SHA256);
}
}

1049
vendor/rcgen/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

79
vendor/rcgen/src/oid.rs vendored Normal file
View File

@@ -0,0 +1,79 @@
/// pkcs-9-at-extensionRequest in [RFC 2985](https://www.rfc-editor.org/rfc/rfc2985#appendix-A)
pub(crate) const PKCS_9_AT_EXTENSION_REQUEST: &[u64] = &[1, 2, 840, 113549, 1, 9, 14];
/// id-at-countryName in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const COUNTRY_NAME: &[u64] = &[2, 5, 4, 6];
/// id-at-localityName in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const LOCALITY_NAME: &[u64] = &[2, 5, 4, 7];
/// id-at-stateOrProvinceName in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const STATE_OR_PROVINCE_NAME: &[u64] = &[2, 5, 4, 8];
/// id-at-organizationName in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const ORG_NAME: &[u64] = &[2, 5, 4, 10];
/// id-at-organizationalUnitName in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const ORG_UNIT_NAME: &[u64] = &[2, 5, 4, 11];
/// id-at-commonName in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const COMMON_NAME: &[u64] = &[2, 5, 4, 3];
/// id-ecPublicKey in [RFC 5480](https://datatracker.ietf.org/doc/html/rfc5480#appendix-A)
pub(crate) const EC_PUBLIC_KEY: &[u64] = &[1, 2, 840, 10045, 2, 1];
/// secp256r1 in [RFC 5480](https://datatracker.ietf.org/doc/html/rfc5480#appendix-A)
pub(crate) const EC_SECP_256_R1: &[u64] = &[1, 2, 840, 10045, 3, 1, 7];
/// secp384r1 in [RFC 5480](https://datatracker.ietf.org/doc/html/rfc5480#appendix-A)
pub(crate) const EC_SECP_384_R1: &[u64] = &[1, 3, 132, 0, 34];
/// secp521r1 in [RFC 5480](https://datatracker.ietf.org/doc/html/rfc5480#appendix-A)
/// Currently this is only supported with the `aws_lc_rs` feature
#[cfg(feature = "aws_lc_rs")]
pub(crate) const EC_SECP_521_R1: &[u64] = &[1, 3, 132, 0, 35];
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
pub(crate) const ML_DSA_44: &[u64] = &[2, 16, 840, 1, 101, 3, 4, 3, 17];
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
pub(crate) const ML_DSA_65: &[u64] = &[2, 16, 840, 1, 101, 3, 4, 3, 18];
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
pub(crate) const ML_DSA_87: &[u64] = &[2, 16, 840, 1, 101, 3, 4, 3, 19];
/// rsaEncryption in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6)
pub(crate) const RSA_ENCRYPTION: &[u64] = &[1, 2, 840, 113549, 1, 1, 1];
/// id-RSASSA-PSS in [RFC 4055](https://www.rfc-editor.org/rfc/rfc4055#section-6)
pub(crate) const RSASSA_PSS: &[u64] = &[1, 2, 840, 113549, 1, 1, 10];
/// id-ce-keyUsage in [RFC 5280](https://tools.ietf.org/html/rfc5280#appendix-A.2)
pub(crate) const KEY_USAGE: &[u64] = &[2, 5, 29, 15];
/// id-ce-subjectAltName in [RFC 5280](https://tools.ietf.org/html/rfc5280#appendix-A.2)
pub(crate) const SUBJECT_ALT_NAME: &[u64] = &[2, 5, 29, 17];
/// id-ce-basicConstraints in [RFC 5280](https://tools.ietf.org/html/rfc5280#appendix-A.2)
pub(crate) const BASIC_CONSTRAINTS: &[u64] = &[2, 5, 29, 19];
/// id-ce-subjectKeyIdentifier in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const SUBJECT_KEY_IDENTIFIER: &[u64] = &[2, 5, 29, 14];
/// id-ce-authorityKeyIdentifier in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const AUTHORITY_KEY_IDENTIFIER: &[u64] = &[2, 5, 29, 35];
/// id-ce-extKeyUsage in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const EXT_KEY_USAGE: &[u64] = &[2, 5, 29, 37];
/// id-ce-nameConstraints in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const NAME_CONSTRAINTS: &[u64] = &[2, 5, 29, 30];
/// id-ce-cRLDistributionPoints in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const CRL_DISTRIBUTION_POINTS: &[u64] = &[2, 5, 29, 31];
/// id-pe-acmeIdentifier in
/// [IANA SMI Numbers registry](https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-1.3.6.1.5.5.7.1)
pub(crate) const PE_ACME: &[u64] = &[1, 3, 6, 1, 5, 5, 7, 1, 31];
/// id-ce-cRLNumber in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const CRL_NUMBER: &[u64] = &[2, 5, 29, 20];
/// id-ce-cRLReasons in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const CRL_REASONS: &[u64] = &[2, 5, 29, 21];
/// id-ce-invalidityDate in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const CRL_INVALIDITY_DATE: &[u64] = &[2, 5, 29, 24];
/// id-ce-issuingDistributionPoint in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#appendix-A)
pub(crate) const CRL_ISSUING_DISTRIBUTION_POINT: &[u64] = &[2, 5, 29, 28];

50
vendor/rcgen/src/ring_like.rs vendored Normal file
View File

@@ -0,0 +1,50 @@
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
pub(crate) use aws_lc_rs::*;
#[cfg(all(feature = "crypto", feature = "ring", not(feature = "aws_lc_rs")))]
pub(crate) use ring::*;
#[cfg(feature = "crypto")]
use crate::error::ExternalError;
#[cfg(feature = "crypto")]
use crate::Error;
#[cfg(feature = "crypto")]
pub(crate) fn ecdsa_from_pkcs8(
alg: &'static signature::EcdsaSigningAlgorithm,
pkcs8: &[u8],
_rng: &dyn rand::SecureRandom,
) -> Result<signature::EcdsaKeyPair, Error> {
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
{
signature::EcdsaKeyPair::from_pkcs8(alg, pkcs8, _rng)._err()
}
#[cfg(feature = "aws_lc_rs")]
{
signature::EcdsaKeyPair::from_pkcs8(alg, pkcs8)._err()
}
}
#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
pub(crate) fn ecdsa_from_private_key_der(
alg: &'static signature::EcdsaSigningAlgorithm,
key: &[u8],
) -> Result<signature::EcdsaKeyPair, Error> {
signature::EcdsaKeyPair::from_private_key_der(alg, key)._err()
}
#[cfg(feature = "crypto")]
pub(crate) fn rsa_key_pair_public_modulus_len(kp: &signature::RsaKeyPair) -> usize {
#[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
{
kp.public().modulus_len()
}
#[cfg(feature = "aws_lc_rs")]
{
kp.public_modulus_len()
}
}
#[cfg(all(feature = "crypto", not(any(feature = "ring", feature = "aws_lc_rs"))))]
compile_error!("At least one of the 'ring' or 'aws_lc_rs' features must be activated when the 'crypto' feature is enabled");

356
vendor/rcgen/src/sign_algo.rs vendored Normal file
View File

@@ -0,0 +1,356 @@
use std::fmt;
use std::hash::{Hash, Hasher};
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
use aws_lc_rs::unstable::signature::{
PqdsaSigningAlgorithm, ML_DSA_44_SIGNING, ML_DSA_65_SIGNING, ML_DSA_87_SIGNING,
};
use yasna::models::ObjectIdentifier;
use yasna::{DERWriter, Tag};
#[cfg(feature = "crypto")]
use crate::ring_like::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters, RsaEncoding};
use crate::Error;
#[cfg(feature = "crypto")]
#[derive(Clone, Copy, Debug)]
pub(crate) enum SignAlgo {
EcDsa(&'static EcdsaSigningAlgorithm),
EdDsa(&'static EdDSAParameters),
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
PqDsa(&'static PqdsaSigningAlgorithm),
Rsa(&'static dyn RsaEncoding),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum SignatureAlgorithmParams {
/// Omit the parameters
None,
/// Write null parameters
Null,
/// RSASSA-PSS-params as per RFC 4055
RsaPss {
hash_algorithm: &'static [u64],
salt_length: u64,
},
}
/// Signature algorithm type
#[derive(Clone)]
pub struct SignatureAlgorithm {
oids_sign_alg: &'static [&'static [u64]],
#[cfg(feature = "crypto")]
pub(crate) sign_alg: SignAlgo,
oid_components: &'static [u64],
params: SignatureAlgorithmParams,
}
impl fmt::Debug for SignatureAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use algo::*;
if self == &PKCS_RSA_SHA256 {
write!(f, "PKCS_RSA_SHA256")
} else if self == &PKCS_RSA_SHA384 {
write!(f, "PKCS_RSA_SHA384")
} else if self == &PKCS_RSA_SHA512 {
write!(f, "PKCS_RSA_SHA512")
} else if self == &PKCS_RSA_PSS_SHA256 {
write!(f, "PKCS_RSA_PSS_SHA256")
} else if self == &PKCS_ECDSA_P256_SHA256 {
write!(f, "PKCS_ECDSA_P256_SHA256")
} else if self == &PKCS_ECDSA_P384_SHA384 {
write!(f, "PKCS_ECDSA_P384_SHA384")
} else if self == &PKCS_ED25519 {
write!(f, "PKCS_ED25519")
} else {
#[cfg(feature = "aws_lc_rs")]
if self == &PKCS_ECDSA_P521_SHA256 {
return write!(f, "PKCS_ECDSA_P521_SHA256");
}
#[cfg(feature = "aws_lc_rs")]
if self == &PKCS_ECDSA_P521_SHA384 {
return write!(f, "PKCS_ECDSA_P521_SHA384");
}
#[cfg(feature = "aws_lc_rs")]
if self == &PKCS_ECDSA_P521_SHA512 {
return write!(f, "PKCS_ECDSA_P521_SHA512");
}
write!(f, "Unknown")
}
}
}
impl PartialEq for SignatureAlgorithm {
fn eq(&self, other: &Self) -> bool {
(self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components)
}
}
impl Eq for SignatureAlgorithm {}
/// The `Hash` trait is not derived, but implemented according to impl of the `PartialEq` trait
impl Hash for SignatureAlgorithm {
fn hash<H: Hasher>(&self, state: &mut H) {
// see SignatureAlgorithm::eq(), just this field is compared
self.oids_sign_alg.hash(state);
}
}
impl SignatureAlgorithm {
pub(crate) fn iter() -> std::slice::Iter<'static, &'static SignatureAlgorithm> {
use algo::*;
static ALGORITHMS: &[&SignatureAlgorithm] = &[
&PKCS_RSA_SHA256,
&PKCS_RSA_SHA384,
&PKCS_RSA_SHA512,
//&PKCS_RSA_PSS_SHA256,
&PKCS_ECDSA_P256_SHA256,
&PKCS_ECDSA_P384_SHA384,
#[cfg(feature = "aws_lc_rs")]
&PKCS_ECDSA_P521_SHA256,
#[cfg(feature = "aws_lc_rs")]
&PKCS_ECDSA_P521_SHA384,
#[cfg(feature = "aws_lc_rs")]
&PKCS_ECDSA_P521_SHA512,
&PKCS_ED25519,
];
ALGORITHMS.iter()
}
/// Retrieve the SignatureAlgorithm for the provided OID
pub fn from_oid(oid: &[u64]) -> Result<&'static SignatureAlgorithm, Error> {
for algo in Self::iter() {
if algo.oid_components == oid {
return Ok(algo);
}
}
Err(Error::UnsupportedSignatureAlgorithm)
}
}
/// The list of supported signature algorithms
pub(crate) mod algo {
use super::*;
use crate::oid::*;
/// RSA signing with PKCS#1 1.5 padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055)
pub static PKCS_RSA_SHA256: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[RSA_ENCRYPTION],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA256),
// sha256WithRSAEncryption in RFC 4055
oid_components: &[1, 2, 840, 113549, 1, 1, 11],
params: SignatureAlgorithmParams::Null,
};
/// RSA signing with PKCS#1 1.5 padding and SHA-384 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055)
pub static PKCS_RSA_SHA384: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[RSA_ENCRYPTION],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA384),
// sha384WithRSAEncryption in RFC 4055
oid_components: &[1, 2, 840, 113549, 1, 1, 12],
params: SignatureAlgorithmParams::Null,
};
/// RSA signing with PKCS#1 1.5 padding and SHA-512 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055)
pub static PKCS_RSA_SHA512: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[RSA_ENCRYPTION],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA512),
// sha512WithRSAEncryption in RFC 4055
oid_components: &[1, 2, 840, 113549, 1, 1, 13],
params: SignatureAlgorithmParams::Null,
};
// TODO: not really sure whether the certs we generate actually work.
// Both openssl and webpki reject them. It *might* be possible that openssl
// accepts the certificate if the key is a proper RSA-PSS key, but ring doesn't
// support those: https://github.com/briansmith/ring/issues/1353
//
/// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055)
pub(crate) static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm {
// We could also use RSA_ENCRYPTION here, but it's recommended
// to use ID-RSASSA-PSS if possible.
oids_sign_alg: &[RSASSA_PSS],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA256),
oid_components: RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13],
// rSASSA-PSS-SHA256-Params in RFC 4055
params: SignatureAlgorithmParams::RsaPss {
// id-sha256 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1
hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 1],
salt_length: 20,
},
};
/// ECDSA signing using the P-256 curves and SHA-256 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2)
pub static PKCS_ECDSA_P256_SHA256: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_256_R1],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P256_SHA256_ASN1_SIGNING),
// ecdsa-with-SHA256 in RFC 5758
oid_components: &[1, 2, 840, 10045, 4, 3, 2],
params: SignatureAlgorithmParams::None,
};
/// ECDSA signing using the P-384 curves and SHA-384 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2)
pub static PKCS_ECDSA_P384_SHA384: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_384_R1],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P384_SHA384_ASN1_SIGNING),
// ecdsa-with-SHA384 in RFC 5758
oid_components: &[1, 2, 840, 10045, 4, 3, 3],
params: SignatureAlgorithmParams::None,
};
/// ECDSA signing using the P-521 curves and SHA-256 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2)
///
/// Note that this algorithm is not widely supported, and is not supported in TLS 1.3.
///
/// Only supported with the `aws_lc_rs` backend.
#[cfg(feature = "aws_lc_rs")]
pub static PKCS_ECDSA_P521_SHA256: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_521_R1],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P521_SHA256_ASN1_SIGNING),
// ecdsa-with-SHA256 in RFC 5758
oid_components: &[1, 2, 840, 10045, 4, 3, 2],
params: SignatureAlgorithmParams::None,
};
/// ECDSA signing using the P-521 curves and SHA-384 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2)
///
/// Note that this algorithm is not widely supported, and is not supported in TLS 1.3.
///
/// Only supported with the `aws_lc_rs` backend.
#[cfg(feature = "aws_lc_rs")]
pub static PKCS_ECDSA_P521_SHA384: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_521_R1],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P521_SHA384_ASN1_SIGNING),
// ecdsa-with-SHA384 in RFC 5758
oid_components: &[1, 2, 840, 10045, 4, 3, 3],
params: SignatureAlgorithmParams::None,
};
/// ECDSA signing using the P-521 curves and SHA-512 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2)
///
/// Only supported with the `aws_lc_rs` backend.
#[cfg(feature = "aws_lc_rs")]
pub static PKCS_ECDSA_P521_SHA512: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_521_R1],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P521_SHA512_ASN1_SIGNING),
// ecdsa-with-SHA512 in RFC 5758
oid_components: &[1, 2, 840, 10045, 4, 3, 4],
params: SignatureAlgorithmParams::None,
};
/// ED25519 curve signing as per [RFC 8410](https://tools.ietf.org/html/rfc8410)
pub static PKCS_ED25519: SignatureAlgorithm = SignatureAlgorithm {
// id-Ed25519 in RFC 8410
oids_sign_alg: &[&[1, 3, 101, 112]],
#[cfg(feature = "crypto")]
sign_alg: SignAlgo::EdDsa(&signature::ED25519),
// id-Ed25519 in RFC 8410
oid_components: &[1, 3, 101, 112],
params: SignatureAlgorithmParams::None,
};
/// ML-DSA-44 signing as per <https://www.ietf.org/archive/id/draft-ietf-lamps-dilithium-certificates-12.html#name-identifiers>.
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
pub static PKCS_ML_DSA_44: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[ML_DSA_44],
#[cfg(all(feature = "crypto", feature = "aws_lc_rs_unstable"))]
sign_alg: SignAlgo::PqDsa(&ML_DSA_44_SIGNING),
oid_components: ML_DSA_44,
params: SignatureAlgorithmParams::None,
};
/// ML-DSA-44 signing as per <https://www.ietf.org/archive/id/draft-ietf-lamps-dilithium-certificates-12.html#name-identifiers>.
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
pub static PKCS_ML_DSA_65: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[ML_DSA_65],
#[cfg(all(feature = "crypto", feature = "aws_lc_rs_unstable"))]
sign_alg: SignAlgo::PqDsa(&ML_DSA_65_SIGNING),
oid_components: ML_DSA_65,
params: SignatureAlgorithmParams::None,
};
/// ML-DSA-44 signing as per <https://www.ietf.org/archive/id/draft-ietf-lamps-dilithium-certificates-12.html#name-identifiers>.
#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
pub static PKCS_ML_DSA_87: SignatureAlgorithm = SignatureAlgorithm {
oids_sign_alg: &[ML_DSA_87],
#[cfg(all(feature = "crypto", feature = "aws_lc_rs_unstable"))]
sign_alg: SignAlgo::PqDsa(&ML_DSA_87_SIGNING),
oid_components: ML_DSA_87,
params: SignatureAlgorithmParams::None,
};
}
// Signature algorithm IDs as per https://tools.ietf.org/html/rfc4055
impl SignatureAlgorithm {
fn alg_ident_oid(&self) -> ObjectIdentifier {
ObjectIdentifier::from_slice(self.oid_components)
}
fn write_params(&self, writer: &mut yasna::DERWriterSeq) {
match self.params {
SignatureAlgorithmParams::None => (),
SignatureAlgorithmParams::Null => {
writer.next().write_null();
},
SignatureAlgorithmParams::RsaPss {
hash_algorithm,
salt_length,
} => {
writer.next().write_sequence(|writer| {
// https://datatracker.ietf.org/doc/html/rfc4055#section-3.1
let oid = ObjectIdentifier::from_slice(hash_algorithm);
// hashAlgorithm
writer.next().write_tagged(Tag::context(0), |writer| {
writer.write_sequence(|writer| {
writer.next().write_oid(&oid);
});
});
// maskGenAlgorithm
writer.next().write_tagged(Tag::context(1), |writer| {
writer.write_sequence(|writer| {
// id-mgf1 in RFC 4055
const ID_MGF1: &[u64] = &[1, 2, 840, 113549, 1, 1, 8];
let oid = ObjectIdentifier::from_slice(ID_MGF1);
writer.next().write_oid(&oid);
writer.next().write_sequence(|writer| {
let oid = ObjectIdentifier::from_slice(hash_algorithm);
writer.next().write_oid(&oid);
writer.next().write_null();
});
});
});
// saltLength
writer.next().write_tagged(Tag::context(2), |writer| {
writer.write_u64(salt_length);
});
// We *must* omit the trailerField element as per RFC 4055 section 3.1
})
},
}
}
/// Writes the algorithm identifier as it appears inside a signature
pub(crate) fn write_alg_ident(&self, writer: DERWriter) {
writer.write_sequence(|writer| {
writer.next().write_oid(&self.alg_ident_oid());
self.write_params(writer);
});
}
/// Writes the algorithm identifier as it appears inside subjectPublicKeyInfo
pub(crate) fn write_oids_sign_alg(&self, writer: DERWriter) {
writer.write_sequence(|writer| {
for oid in self.oids_sign_alg {
let oid = ObjectIdentifier::from_slice(oid);
writer.next().write_oid(&oid);
}
self.write_params(writer);
});
}
}

666
vendor/rcgen/src/string.rs vendored Normal file
View File

@@ -0,0 +1,666 @@
//! ASN.1 string types
use std::fmt;
use std::str::FromStr;
use crate::{Error, InvalidAsn1String};
/// ASN.1 `PrintableString` type.
///
/// Supports a subset of the ASCII printable characters (described below).
///
/// For the full ASCII character set, use
/// [`Ia5String`][`crate::Ia5String`].
///
/// # Examples
///
/// You can create a `PrintableString` from [a literal string][`&str`] with [`PrintableString::try_from`]:
///
/// ```
/// use rcgen::string::PrintableString;
/// let hello = PrintableString::try_from("hello").unwrap();
/// ```
///
/// # Supported characters
///
/// PrintableString is a subset of the [ASCII printable characters].
/// For instance, `'@'` is a printable character as per ASCII but can't be part of [ASN.1's `PrintableString`].
///
/// The following ASCII characters/ranges are supported:
///
/// - `A..Z`
/// - `a..z`
/// - `0..9`
/// - "` `" (i.e. space)
/// - `\`
/// - `(`
/// - `)`
/// - `+`
/// - `,`
/// - `-`
/// - `.`
/// - `/`
/// - `:`
/// - `=`
/// - `?`
///
/// [ASCII printable characters]: https://en.wikipedia.org/wiki/ASCII#Printable_characters
/// [ASN.1's `PrintableString`]: https://en.wikipedia.org/wiki/PrintableString
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct PrintableString(String);
impl PrintableString {
/// Extracts a string slice containing the entire `PrintableString`.
pub fn as_str(&self) -> &str {
&self.0
}
}
impl TryFrom<&str> for PrintableString {
type Error = Error;
/// Converts a `&str` to a [`PrintableString`].
///
/// Any character not in the [`PrintableString`] charset will be rejected.
/// See [`PrintableString`] documentation for more information.
///
/// The result is allocated on the heap.
fn try_from(input: &str) -> Result<Self, Error> {
input.to_string().try_into()
}
}
impl TryFrom<String> for PrintableString {
type Error = Error;
/// Converts a [`String`][`std::string::String`] into a [`PrintableString`]
///
/// Any character not in the [`PrintableString`] charset will be rejected.
/// See [`PrintableString`] documentation for more information.
///
/// This conversion does not allocate or copy memory.
fn try_from(value: String) -> Result<Self, Self::Error> {
for &c in value.as_bytes() {
match c {
b'A'..=b'Z'
| b'a'..=b'z'
| b'0'..=b'9'
| b' '
| b'\''
| b'('
| b')'
| b'+'
| b','
| b'-'
| b'.'
| b'/'
| b':'
| b'='
| b'?' => (),
_ => {
return Err(Error::InvalidAsn1String(
InvalidAsn1String::PrintableString(value),
))
},
}
}
Ok(Self(value))
}
}
impl FromStr for PrintableString {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}
impl AsRef<str> for PrintableString {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for PrintableString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_str(), f)
}
}
impl PartialEq<str> for PrintableString {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<String> for PrintableString {
fn eq(&self, other: &String) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq<&str> for PrintableString {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<&String> for PrintableString {
fn eq(&self, other: &&String) -> bool {
self.as_str() == other.as_str()
}
}
/// ASN.1 `IA5String` type.
///
/// # Examples
///
/// You can create a `Ia5String` from [a literal string][`&str`] with [`Ia5String::try_from`]:
///
/// ```
/// use rcgen::string::Ia5String;
/// let hello = Ia5String::try_from("hello").unwrap();
/// ```
///
/// # Supported characters
///
/// Supports the [International Alphabet No. 5 (IA5)] character encoding, i.e.
/// the 128 characters of the ASCII alphabet. (Note: IA5 is now
/// technically known as the International Reference Alphabet or IRA as
/// specified in the ITU-T's T.50 recommendation).
///
/// For UTF-8, use [`String`][`std::string::String`].
///
/// [International Alphabet No. 5 (IA5)]: https://en.wikipedia.org/wiki/T.50_(standard)
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct Ia5String(String);
impl Ia5String {
/// Extracts a string slice containing the entire `Ia5String`.
pub fn as_str(&self) -> &str {
&self.0
}
}
impl TryFrom<&str> for Ia5String {
type Error = Error;
/// Converts a `&str` to a [`Ia5String`].
///
/// Any character not in the [`Ia5String`] charset will be rejected.
/// See [`Ia5String`] documentation for more information.
///
/// The result is allocated on the heap.
fn try_from(input: &str) -> Result<Self, Error> {
input.to_string().try_into()
}
}
impl TryFrom<String> for Ia5String {
type Error = Error;
/// Converts a [`String`][`std::string::String`] into a [`Ia5String`]
///
/// Any character not in the [`Ia5String`] charset will be rejected.
/// See [`Ia5String`] documentation for more information.
fn try_from(input: String) -> Result<Self, Error> {
if !input.is_ascii() {
return Err(Error::InvalidAsn1String(InvalidAsn1String::Ia5String(
input,
)));
}
Ok(Self(input))
}
}
impl FromStr for Ia5String {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}
impl AsRef<str> for Ia5String {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for Ia5String {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_str(), f)
}
}
impl PartialEq<str> for Ia5String {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<String> for Ia5String {
fn eq(&self, other: &String) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq<&str> for Ia5String {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<&String> for Ia5String {
fn eq(&self, other: &&String) -> bool {
self.as_str() == other.as_str()
}
}
/// ASN.1 `TeletexString` type.
///
/// # Examples
///
/// You can create a `TeletexString` from [a literal string][`&str`] with [`TeletexString::try_from`]:
///
/// ```
/// use rcgen::string::TeletexString;
/// let hello = TeletexString::try_from("hello").unwrap();
/// ```
///
/// # Supported characters
///
/// The standard defines a complex character set allowed in this type. However, quoting the ASN.1
/// [mailing list], "a sizable volume of software in the world treats TeletexString (T61String) as a
/// simple 8-bit string with mostly Windows Latin 1 (superset of iso-8859-1) encoding".
///
/// `TeletexString` is included for backward compatibility, [RFC 5280] say it
/// SHOULD NOT be used for certificates for new subjects.
///
/// [mailing list]: https://www.mail-archive.com/asn1@asn1.org/msg00460.html
/// [RFC 5280]: https://datatracker.ietf.org/doc/html/rfc5280#page-25
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct TeletexString(String);
impl TeletexString {
/// Extracts a string slice containing the entire `TeletexString`.
pub fn as_str(&self) -> &str {
&self.0
}
/// Returns a byte slice of this `TeletexString`s contents.
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl TryFrom<&str> for TeletexString {
type Error = Error;
/// Converts a `&str` to a [`TeletexString`].
///
/// Any character not in the [`TeletexString`] charset will be rejected.
/// See [`TeletexString`] documentation for more information.
///
/// The result is allocated on the heap.
fn try_from(input: &str) -> Result<Self, Error> {
input.to_string().try_into()
}
}
impl TryFrom<String> for TeletexString {
type Error = Error;
/// Converts a [`String`][`std::string::String`] into a [`TeletexString`]
///
/// Any character not in the [`TeletexString`] charset will be rejected.
/// See [`TeletexString`] documentation for more information.
///
/// This conversion does not allocate or copy memory.
fn try_from(input: String) -> Result<Self, Error> {
// Check all bytes are visible
if !input.as_bytes().iter().all(|b| (0x20..=0x7f).contains(b)) {
return Err(Error::InvalidAsn1String(InvalidAsn1String::TeletexString(
input,
)));
}
Ok(Self(input))
}
}
impl FromStr for TeletexString {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}
impl AsRef<str> for TeletexString {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for TeletexString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_str(), f)
}
}
impl PartialEq<str> for TeletexString {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<String> for TeletexString {
fn eq(&self, other: &String) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq<&str> for TeletexString {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<&String> for TeletexString {
fn eq(&self, other: &&String) -> bool {
self.as_str() == other.as_str()
}
}
/// ASN.1 `BMPString` type.
///
/// # Examples
///
/// You can create a `BmpString` from [a literal string][`&str`] with [`BmpString::try_from`]:
///
/// ```
/// use rcgen::string::BmpString;
/// let hello = BmpString::try_from("hello").unwrap();
/// ```
///
/// # Supported characters
///
/// Encodes Basic Multilingual Plane (BMP) subset of Unicode (ISO 10646),
/// a.k.a. UCS-2.
///
/// Bytes are encoded as UTF-16 big-endian.
///
/// `BMPString` is included for backward compatibility, [RFC 5280] say it
/// SHOULD NOT be used for certificates for new subjects.
///
/// [RFC 5280]: https://datatracker.ietf.org/doc/html/rfc5280#page-25
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct BmpString(Vec<u8>);
impl BmpString {
/// Returns a byte slice of this `BmpString`'s contents.
///
/// The inverse of this method is [`from_utf16be`].
///
/// [`from_utf16be`]: BmpString::from_utf16be
///
/// # Examples
///
/// ```
/// use rcgen::string::BmpString;
/// let s = BmpString::try_from("hello").unwrap();
///
/// assert_eq!(&[0, 104, 0, 101, 0, 108, 0, 108, 0, 111], s.as_bytes());
/// ```
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
/// Decode a UTF-16BEencoded vector `vec` into a `BmpString`, returning [Err](`std::result::Result::Err`) if `vec` contains any invalid data.
pub fn from_utf16be(vec: Vec<u8>) -> Result<Self, Error> {
if vec.len() % 2 != 0 {
return Err(Error::InvalidAsn1String(InvalidAsn1String::BmpString(
"Invalid UTF-16 encoding".to_string(),
)));
}
// FIXME: Update this when `array_chunks` is stabilized.
for maybe_char in char::decode_utf16(
vec.chunks_exact(2)
.map(|chunk| u16::from_be_bytes([chunk[0], chunk[1]])),
) {
// We check we only use the BMP subset of Unicode (the first 65 536 code points)
match maybe_char {
// Character is in the Basic Multilingual Plane
Ok(c) if (c as u64) < u64::from(u16::MAX) => (),
// Characters outside Basic Multilingual Plane or unpaired surrogates
_ => {
return Err(Error::InvalidAsn1String(InvalidAsn1String::BmpString(
"Invalid UTF-16 encoding".to_string(),
)));
},
}
}
Ok(Self(vec.to_vec()))
}
}
impl TryFrom<&str> for BmpString {
type Error = Error;
/// Converts a `&str` to a [`BmpString`].
///
/// Any character not in the [`BmpString`] charset will be rejected.
/// See [`BmpString`] documentation for more information.
///
/// The result is allocated on the heap.
fn try_from(value: &str) -> Result<Self, Self::Error> {
let capacity = value.len().checked_mul(2).ok_or_else(|| {
Error::InvalidAsn1String(InvalidAsn1String::BmpString(value.to_string()))
})?;
let mut bytes = Vec::with_capacity(capacity);
for code_point in value.encode_utf16() {
bytes.extend(code_point.to_be_bytes());
}
BmpString::from_utf16be(bytes)
}
}
impl TryFrom<String> for BmpString {
type Error = Error;
/// Converts a [`String`][`std::string::String`] into a [`BmpString`]
///
/// Any character not in the [`BmpString`] charset will be rejected.
/// See [`BmpString`] documentation for more information.
///
/// Parsing a `BmpString` allocates memory since the UTF-8 to UTF-16 conversion requires a memory allocation.
fn try_from(value: String) -> Result<Self, Self::Error> {
value.as_str().try_into()
}
}
impl FromStr for BmpString {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}
/// ASN.1 `UniversalString` type.
///
/// # Examples
///
/// You can create a `UniversalString` from [a literal string][`&str`] with [`UniversalString::try_from`]:
///
/// ```
/// use rcgen::string::UniversalString;
/// let hello = UniversalString::try_from("hello").unwrap();
/// ```
///
/// # Supported characters
///
/// The characters which can appear in the `UniversalString` type are any of the characters allowed by
/// ISO/IEC 10646 (Unicode).
///
/// Bytes are encoded like UTF-32 big-endian.
///
/// `UniversalString` is included for backward compatibility, [RFC 5280] say it
/// SHOULD NOT be used for certificates for new subjects.
///
/// [RFC 5280]: https://datatracker.ietf.org/doc/html/rfc5280#page-25
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct UniversalString(Vec<u8>);
impl UniversalString {
/// Returns a byte slice of this `UniversalString`'s contents.
///
/// The inverse of this method is [`from_utf32be`].
///
/// [`from_utf32be`]: UniversalString::from_utf32be
///
/// # Examples
///
/// ```
/// use rcgen::string::UniversalString;
/// let s = UniversalString::try_from("hello").unwrap();
///
/// assert_eq!(&[0, 0, 0, 104, 0, 0, 0, 101, 0, 0, 0, 108, 0, 0, 0, 108, 0, 0, 0, 111], s.as_bytes());
/// ```
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
/// Decode a UTF-32BEencoded vector `vec` into a `UniversalString`, returning [Err](`std::result::Result::Err`) if `vec` contains any invalid data.
pub fn from_utf32be(vec: Vec<u8>) -> Result<UniversalString, Error> {
if vec.len() % 4 != 0 {
return Err(Error::InvalidAsn1String(
InvalidAsn1String::UniversalString("Invalid UTF-32 encoding".to_string()),
));
}
// FIXME: Update this when `array_chunks` is stabilized.
for maybe_char in vec
.chunks_exact(4)
.map(|chunk| u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]))
{
if core::char::from_u32(maybe_char).is_none() {
return Err(Error::InvalidAsn1String(
InvalidAsn1String::UniversalString("Invalid UTF-32 encoding".to_string()),
));
}
}
Ok(Self(vec))
}
}
impl TryFrom<&str> for UniversalString {
type Error = Error;
/// Converts a `&str` to a [`UniversalString`].
///
/// Any character not in the [`UniversalString`] charset will be rejected.
/// See [`UniversalString`] documentation for more information.
///
/// The result is allocated on the heap.
fn try_from(value: &str) -> Result<Self, Self::Error> {
let capacity = value.len().checked_mul(4).ok_or_else(|| {
Error::InvalidAsn1String(InvalidAsn1String::UniversalString(value.to_string()))
})?;
let mut bytes = Vec::with_capacity(capacity);
// A `char` is any Unicode code point other than a surrogate code point.
// The code units for UTF-32 correspond exactly to Unicode code points.
// (https://www.unicode.org/reports/tr19/tr19-9.html#Introduction)
// So any `char` is a valid UTF-32, we just cast it to perform the conversion.
for char in value.chars().map(|char| char as u32) {
bytes.extend(char.to_be_bytes())
}
UniversalString::from_utf32be(bytes)
}
}
impl TryFrom<String> for UniversalString {
type Error = Error;
/// Converts a [`String`][`std::string::String`] into a [`UniversalString`]
///
/// Any character not in the [`UniversalString`] charset will be rejected.
/// See [`UniversalString`] documentation for more information.
///
/// Parsing a `UniversalString` allocates memory since the UTF-8 to UTF-32 conversion requires a memory allocation.
fn try_from(value: String) -> Result<Self, Self::Error> {
value.as_str().try_into()
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use crate::{BmpString, Ia5String, PrintableString, TeletexString, UniversalString};
#[test]
fn printable_string() {
const EXAMPLE_UTF8: &str = "CertificateTemplate";
let printable_string = PrintableString::try_from(EXAMPLE_UTF8).unwrap();
assert_eq!(printable_string, EXAMPLE_UTF8);
assert!(PrintableString::try_from("@").is_err());
assert!(PrintableString::try_from("*").is_err());
}
#[test]
fn ia5_string() {
const EXAMPLE_UTF8: &str = "CertificateTemplate";
let ia5_string = Ia5String::try_from(EXAMPLE_UTF8).unwrap();
assert_eq!(ia5_string, EXAMPLE_UTF8);
assert!(Ia5String::try_from(String::from('\u{7F}')).is_ok());
assert!(Ia5String::try_from(String::from('\u{8F}')).is_err());
}
#[test]
fn teletext_string() {
const EXAMPLE_UTF8: &str = "CertificateTemplate";
let teletext_string = TeletexString::try_from(EXAMPLE_UTF8).unwrap();
assert_eq!(teletext_string, EXAMPLE_UTF8);
assert!(Ia5String::try_from(String::from('\u{7F}')).is_ok());
assert!(Ia5String::try_from(String::from('\u{8F}')).is_err());
}
#[test]
fn bmp_string() {
const EXPECTED_BYTES: &[u8] = &[
0x00, 0x43, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69,
0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d,
0x00, 0x70, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65,
];
const EXAMPLE_UTF8: &str = "CertificateTemplate";
let bmp_string = BmpString::try_from(EXAMPLE_UTF8).unwrap();
assert_eq!(bmp_string.as_bytes(), EXPECTED_BYTES);
assert!(BmpString::try_from(String::from('\u{FFFE}')).is_ok());
assert!(BmpString::try_from(String::from('\u{FFFF}')).is_err());
}
#[test]
fn universal_string() {
const EXPECTED_BYTES: &[u8] = &[
0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00,
0x00, 0x74, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x69,
0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00,
0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6d,
0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00,
0x00, 0x74, 0x00, 0x00, 0x00, 0x65,
];
const EXAMPLE_UTF8: &str = "CertificateTemplate";
let universal_string = UniversalString::try_from(EXAMPLE_UTF8).unwrap();
assert_eq!(universal_string.as_bytes(), EXPECTED_BYTES);
}
}

Binary file not shown.

View File

View File

@@ -0,0 +1 @@
{"name":"rcgen","vers":"0.14.7","deps":[{"name":"aws-lc-rs","req":"^1.13.3","features":[],"optional":true,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"pem","req":"^3.0.2","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"pki-types","req":"^1.4.1","features":[],"optional":false,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":"rustls-pki-types","public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"ring","req":"^0.17","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"time","req":"^0.3.6","features":[],"optional":false,"default_features":false,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"x509-parser","req":"^0.18","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"yasna","req":"^0.5.2","features":["time","std"],"optional":false,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"zeroize","req":"^1.2","features":[],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"openssl","req":"^0.10","features":[],"optional":false,"default_features":true,"target":"cfg(unix)","kind":"dev","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false}],"features":{"aws_lc_rs":["crypto","dep:aws-lc-rs","aws-lc-rs/aws-lc-sys","x509-parser?/verify-aws"],"aws_lc_rs_unstable":["aws_lc_rs","aws-lc-rs/unstable","x509-parser?/verify-aws"],"crypto":[],"default":["crypto","pem","ring"],"fips":["crypto","dep:aws-lc-rs","aws-lc-rs/fips"],"ring":["crypto","dep:ring","x509-parser?/verify"]},"features2":null,"cksum":"e73f1a54eca788371abc3e58e0e87965f89869d3cb0b8ef27c510609a44c35de","yanked":null,"links":null,"rust_version":null,"v":2}

Binary file not shown.