├── .clang-format ├── .coveralls.yml ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md ├── codecov.yml └── workflows │ └── ci.yml ├── .gitignore ├── AUTHORS ├── BUILDING.md ├── Cargo.toml ├── LICENSE ├── LICENSE-BoringSSL ├── LICENSE-other-bits ├── README.md ├── RELEASES.md ├── SECURITY.md ├── SIDE-CHANNELS.md ├── STYLE.md ├── bench ├── Cargo.toml ├── aead.rs ├── agreement.rs ├── data │ ├── rsa-2048-3-public-key.der │ ├── rsa-2048-3-signature.bin │ ├── rsa-2048-65537-public-key.der │ ├── rsa-2048-65537-signature.bin │ ├── rsa-3072-3-public-key.der │ ├── rsa-3072-3-signature.bin │ ├── rsa-4096-3-public-key.der │ ├── rsa-4096-3-signature.bin │ ├── rsa-8192-3-public-key.der │ ├── rsa-8192-3-signature.bin │ └── rsa-generate.sh ├── digest.rs ├── ecdsa.rs └── rsa.rs ├── build.rs ├── cavp ├── Cargo.toml ├── tests │ └── shavs.rs └── third_party │ └── NIST │ ├── .gitattributes │ ├── README.md │ ├── SHAVS │ ├── SHA1LongMsg.rsp │ ├── SHA1ShortMsg.rsp │ ├── SHA224LongMsg.rsp │ ├── SHA224ShortMsg.rsp │ ├── SHA256LongMsg.rsp │ ├── SHA256ShortMsg.rsp │ ├── SHA384LongMsg.rsp │ ├── SHA384ShortMsg.rsp │ ├── SHA512LongMsg.rsp │ └── SHA512ShortMsg.rsp │ └── sha256sums.txt ├── crypto ├── chacha │ └── asm │ │ ├── chacha-armv4.pl │ │ ├── chacha-armv8.pl │ │ ├── chacha-x86.pl │ │ └── chacha-x86_64.pl ├── cipher │ └── asm │ │ ├── chacha20_poly1305_armv8.pl │ │ └── chacha20_poly1305_x86_64.pl ├── constant_time_test.c ├── crypto.c ├── curve25519 │ ├── .gitattributes │ ├── asm │ │ └── x25519-asm-arm.S │ ├── curve25519.c │ ├── curve25519_64_adx.c │ ├── curve25519_tables.h │ └── internal.h ├── fipsmodule │ ├── aes │ │ └── asm │ │ │ ├── aes-gcm-avx2-x86_64.pl │ │ │ ├── aes-gcm-avx512-x86_64.pl │ │ │ ├── aesni-gcm-x86_64.pl │ │ │ ├── aesni-x86.pl │ │ │ ├── aesni-x86_64.pl │ │ │ ├── aesv8-armx.pl │ │ │ ├── aesv8-gcm-armv8.pl │ │ │ ├── bsaes-armv7.pl │ │ │ ├── ghash-armv4.pl │ │ │ ├── ghash-neon-armv8.pl │ │ │ ├── ghash-ssse3-x86.pl │ │ │ ├── ghash-ssse3-x86_64.pl │ │ │ ├── ghash-x86.pl │ │ │ ├── ghash-x86_64.pl │ │ │ ├── ghashv8-armx.pl │ │ │ ├── make-avx-map-for-old-binutils.py │ │ │ ├── vpaes-armv7.pl │ │ │ ├── vpaes-armv8.pl │ │ │ ├── vpaes-x86.pl │ │ │ └── vpaes-x86_64.pl │ ├── bn │ │ ├── asm │ │ │ ├── armv4-mont.pl │ │ │ ├── armv8-mont.pl │ │ │ ├── bn-armv8.pl │ │ │ ├── x86-mont.pl │ │ │ ├── x86_64-mont.pl │ │ │ └── x86_64-mont5.pl │ │ ├── internal.h │ │ ├── montgomery.c │ │ ├── montgomery_inv.c │ │ └── test │ │ │ ├── mod_exp_tests.txt │ │ │ └── mod_mul_tests.txt │ ├── ec │ │ ├── .gitattributes │ │ ├── asm │ │ │ ├── p256-armv8-asm.pl │ │ │ └── p256-x86_64-asm.pl │ │ ├── ecp_nistz.c │ │ ├── ecp_nistz.h │ │ ├── ecp_nistz384.h │ │ ├── ecp_nistz384.inl │ │ ├── gfp_p256.c │ │ ├── gfp_p384.c │ │ ├── p256-nistz-table.h │ │ ├── p256-nistz.c │ │ ├── p256-nistz.h │ │ ├── p256.c │ │ ├── p256_shared.h │ │ ├── p256_table.h │ │ └── util.h │ ├── ecdsa │ │ └── ecdsa_verify_tests.txt │ └── sha │ │ └── asm │ │ ├── sha256-armv4.pl │ │ ├── sha512-armv4.pl │ │ ├── sha512-armv8.pl │ │ └── sha512-x86_64.pl ├── internal.h ├── limbs │ ├── limbs.c │ ├── limbs.h │ └── limbs.inl ├── mem.c ├── perlasm │ ├── arm-xlate.pl │ ├── readme │ ├── x86_64-xlate.pl │ ├── x86asm.pl │ ├── x86gas.pl │ └── x86nasm.pl └── poly1305 │ ├── poly1305.c │ ├── poly1305_arm.c │ └── poly1305_arm_asm.S ├── deny.toml ├── doc ├── ecdh.pdf └── ecdsa.pdf ├── include └── ring-core │ ├── aes.h │ ├── asm_base.h │ ├── base.h │ ├── check.h │ ├── mem.h │ ├── prefix_symbols.h │ ├── target.h │ └── type_check.h ├── mk ├── cargo.sh ├── check-symbol-prefixes.sh ├── clippy.sh ├── generate_curves.py ├── install-build-tools.ps1 ├── install-build-tools.sh ├── llvm-snapshot.gpg.key ├── package.sh ├── publish.sh └── runner ├── rustfmt.toml ├── src ├── aead.rs ├── aead │ ├── aes.rs │ ├── aes │ │ ├── bs.rs │ │ ├── fallback.rs │ │ ├── ffi.rs │ │ ├── hw.rs │ │ └── vp.rs │ ├── aes_gcm.rs │ ├── aes_gcm │ │ ├── aarch64.rs │ │ ├── aeshwclmulmovbe.rs │ │ └── vaesclmulavx2.rs │ ├── aes_tests.txt │ ├── algorithm.rs │ ├── chacha.rs │ ├── chacha │ │ ├── fallback.rs │ │ └── ffi.rs │ ├── chacha20_poly1305 │ │ ├── integrated.rs │ │ └── mod.rs │ ├── chacha20_poly1305_openssh.rs │ ├── chacha_tests.txt │ ├── gcm.rs │ ├── gcm │ │ ├── clmul.rs │ │ ├── clmulavxmovbe.rs │ │ ├── fallback.rs │ │ ├── ffi.rs │ │ ├── neon.rs │ │ └── vclmulavx2.rs │ ├── less_safe_key.rs │ ├── nonce.rs │ ├── opening_key.rs │ ├── overlapping │ │ ├── array.rs │ │ ├── base.rs │ │ ├── mod.rs │ │ └── partial_block.rs │ ├── poly1305.rs │ ├── poly1305 │ │ ├── ffi_arm_neon.rs │ │ └── ffi_fallback.rs │ ├── poly1305_test.txt │ ├── quic.rs │ ├── sealing_key.rs │ └── unbound_key.rs ├── agreement.rs ├── arithmetic.rs ├── arithmetic │ ├── bigint.rs │ ├── bigint │ │ ├── boxed_limbs.rs │ │ ├── modulus.rs │ │ ├── modulusvalue.rs │ │ └── private_exponent.rs │ ├── bigint_elem_exp_vartime_tests.txt │ ├── bigint_elem_reduced_once_tests.txt │ ├── bigint_elem_reduced_tests.txt │ ├── bigint_elem_squared_tests.txt │ ├── constant.rs │ ├── ffi.rs │ ├── inout.rs │ ├── limbs │ │ ├── aarch64 │ │ │ ├── mod.rs │ │ │ └── mont.rs │ │ ├── mod.rs │ │ └── x86_64 │ │ │ ├── mod.rs │ │ │ └── mont.rs │ ├── limbs512 │ │ ├── mod.rs │ │ └── storage.rs │ ├── montgomery.rs │ └── n0.rs ├── bb │ ├── boolmask.rs │ ├── leaky.rs │ ├── mod.rs │ └── word.rs ├── bits.rs ├── bssl.rs ├── c.rs ├── cpu.rs ├── cpu │ ├── aarch64 │ │ ├── darwin.rs │ │ ├── fuchsia.rs │ │ ├── linux.rs │ │ ├── mod.rs │ │ └── windows.rs │ ├── arm │ │ ├── linux.rs │ │ └── mod.rs │ └── intel.rs ├── data │ └── alg-rsa-encryption.der ├── debug.rs ├── deprecated_constant_time.rs ├── deprecated_test.rs ├── digest.rs ├── digest │ ├── dynstate.rs │ ├── sha1.rs │ └── sha2 │ │ ├── fallback.rs │ │ ├── ffi.rs │ │ ├── mod.rs │ │ ├── sha2_32.rs │ │ └── sha2_64.rs ├── ec.rs ├── ec │ ├── curve25519.rs │ ├── curve25519 │ │ ├── ed25519.rs │ │ ├── ed25519 │ │ │ ├── ed25519_pkcs8_v2_template.der │ │ │ ├── signing.rs │ │ │ └── verification.rs │ │ ├── ops.rs │ │ ├── scalar.rs │ │ └── x25519.rs │ ├── keys.rs │ ├── suite_b.rs │ └── suite_b │ │ ├── curve.rs │ │ ├── ecdh.rs │ │ ├── ecdsa.rs │ │ ├── ecdsa │ │ ├── digest_scalar.rs │ │ ├── ecPublicKey_p256_pkcs8_v1_template.der │ │ ├── ecPublicKey_p384_pkcs8_v1_template.der │ │ ├── ecdsa_digest_scalar_tests.txt │ │ ├── ecdsa_sign_asn1_tests.txt │ │ ├── ecdsa_sign_fixed_tests.txt │ │ ├── signing.rs │ │ └── verification.rs │ │ ├── ops.rs │ │ ├── ops │ │ ├── elem.rs │ │ ├── p256.rs │ │ ├── p256_elem_mul_tests.txt │ │ ├── p256_elem_neg_tests.txt │ │ ├── p256_elem_sum_tests.txt │ │ ├── p256_point_double_tests.txt │ │ ├── p256_point_mul_base_tests.txt │ │ ├── p256_point_mul_serialized_tests.txt │ │ ├── p256_point_sum_mixed_tests.txt │ │ ├── p256_point_sum_tests.txt │ │ ├── p256_scalar_mul_tests.txt │ │ ├── p256_scalar_square_tests.txt │ │ ├── p384.rs │ │ ├── p384_elem_div_by_2_tests.txt │ │ ├── p384_elem_mul_tests.txt │ │ ├── p384_elem_neg_tests.txt │ │ ├── p384_elem_sum_tests.txt │ │ ├── p384_point_double_tests.txt │ │ ├── p384_point_mul_base_tests.txt │ │ ├── p384_point_sum_tests.txt │ │ └── p384_scalar_mul_tests.txt │ │ ├── private_key.rs │ │ ├── public_key.rs │ │ └── suite_b_public_key_tests.txt ├── error │ ├── input_too_long.rs │ ├── into_unspecified.rs │ ├── key_rejected.rs │ ├── mod.rs │ └── unspecified.rs ├── hkdf.rs ├── hmac.rs ├── hmac_generate_serializable_tests.txt ├── io.rs ├── io │ ├── der.rs │ ├── der_writer.rs │ ├── positive.rs │ └── writer.rs ├── lib.rs ├── limb.rs ├── pbkdf2.rs ├── pkcs8.rs ├── polyfill.rs ├── polyfill │ ├── array_flat_map.rs │ ├── array_split_map.rs │ ├── cold_error.rs │ ├── cstr.rs │ ├── leading_zeros_skipped.rs │ ├── notsend.rs │ ├── once_cell │ │ ├── LICENSE-APACHE │ │ ├── LICENSE-MIT │ │ ├── README.txt │ │ └── race.rs │ ├── ptr.rs │ ├── slice.rs │ ├── slice │ │ ├── as_chunks.rs │ │ └── as_chunks_mut.rs │ ├── sliceutil.rs │ ├── test.rs │ └── unwrap_const.rs ├── prefixed.rs ├── rand.rs ├── rsa.rs ├── rsa │ ├── convert_nist_rsa_test_vectors.py │ ├── keypair.rs │ ├── keypair_components.rs │ ├── keypair_private_exponentiate_tests.txt │ ├── padding.rs │ ├── padding │ │ ├── pkcs1.rs │ │ └── pss.rs │ ├── public_exponent.rs │ ├── public_key.rs │ ├── public_key_components.rs │ ├── public_modulus.rs │ ├── rsa_pss_padding_tests.txt │ ├── signature_rsa_example_private_key.der │ ├── signature_rsa_example_public_key.der │ └── verification.rs ├── signature.rs ├── test_1_syntax_error_tests.txt ├── test_1_tests.txt ├── test_3_tests.txt ├── tests │ ├── bits_tests.rs │ └── mod.rs └── testutil.rs ├── tests ├── aead_aes_128_gcm_tests.txt ├── aead_aes_256_gcm_tests.txt ├── aead_chacha20_poly1305_openssh_tests.txt ├── aead_chacha20_poly1305_tests.txt ├── aead_tests.rs ├── agreement_tests.rs ├── agreement_tests.txt ├── constant_time_tests.rs ├── digest_tests.rs ├── digest_tests.txt ├── ecdsa_from_pkcs8_tests.txt ├── ecdsa_test_private_key_p256.p8 ├── ecdsa_test_public_key_p256.der ├── ecdsa_test_public_key_p256_debug.txt ├── ecdsa_tests.rs ├── ecdsa_verify_asn1_tests.txt ├── ecdsa_verify_fixed_tests.txt ├── ed25519_from_pkcs8_tests.txt ├── ed25519_test_private_key.bin ├── ed25519_test_private_key.p8 ├── ed25519_test_public_key.bin ├── ed25519_test_public_key.der ├── ed25519_tests.rs ├── ed25519_tests.txt ├── ed25519_verify_tests.txt ├── error_tests.rs ├── hkdf_tests.rs ├── hkdf_tests.txt ├── hmac_tests.rs ├── hmac_tests.txt ├── pbkdf2_tests.rs ├── pbkdf2_tests.txt ├── quic_aes_128_tests.txt ├── quic_aes_256_tests.txt ├── quic_chacha20_tests.txt ├── quic_tests.rs ├── rand_tests.rs ├── rsa_from_pkcs8_tests.txt ├── rsa_pkcs1_sign_tests.txt ├── rsa_pkcs1_verify_tests.txt ├── rsa_primitive_verify_tests.txt ├── rsa_pss_sign_tests.txt ├── rsa_pss_verify_tests.txt ├── rsa_test_private_key_2048.p8 ├── rsa_test_public_key_2048.der ├── rsa_test_public_key_2048_debug.txt ├── rsa_test_public_modulus.bin ├── rsa_tests.rs └── signature_tests.rs └── third_party └── fiat ├── .gitattributes ├── AUTHORS ├── LICENSE ├── METADATA ├── README.md ├── asm ├── fiat_curve25519_adx_mul.S └── fiat_curve25519_adx_square.S ├── curve25519_32.h ├── curve25519_64.h ├── curve25519_64_adx.h ├── curve25519_64_msvc.h ├── p256_32.h ├── p256_64.h └── p256_64_msvc.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | MaxEmptyLinesToKeep: 3 3 | AllowShortIfStatementsOnASingleLine: false 4 | AllowShortLoopsOnASingleLine: false 5 | DerivePointerAlignment: false 6 | PointerAlignment: Right 7 | # TODO(davidben): The default for Google style is now Regroup, but the default 8 | # IncludeCategories does not recognize . We should 9 | # reconfigure IncludeCategories to match. For now, keep it at Preserve. 10 | IncludeBlocks: Preserve 11 | 12 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-pro 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | # Visual Studio 2017 does this wrong 5 | # https://developercommunity.visualstudio.com/content/problem/22922/editorconfig-support-interprets-charset-utf-8-as-u.html 6 | # charset = utf-8 7 | end_of_line = lf 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.{c,cc,h,inl}] 13 | indent_size = 2 14 | 15 | [*.{py,rs,toml}] 16 | indent_size = 4 17 | 18 | [*.pl] 19 | trim_trailing_whitespace = false 20 | indent_style = tab 21 | indent_size = 4 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol 2 | crypto/**/*.pl linguist-language=Assembly 3 | crypto/perlasm/*.pl linguist-language=Perl 4 | *.bin binary 5 | *.der binary 6 | **/*.h linguist-language=C 7 | **/*.inl linguist-language=C 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: I think I found a bug 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please do report bugs you find, especially if something is calculated 11 | incorrectly, something is rejected when it should be accepted, 12 | something is accepted but should be rejected, etc. 13 | 14 | Email brian@briansmith.org for business inquiries including sponsorships, 15 | funded feature requests, etc. 16 | 17 | If your build was working previously and now fails after updating to a new 18 | version, and the changelog doesn't call out an intended increase in build 19 | tool requirements--i.e. there is a regression in the build system--please DO 20 | report a bug. 21 | 22 | Otherwise, please try to identify the cause and solution of a build failure 23 | before filing an issue. This project isn't as easy to build as most other Rust 24 | projects. Most bug reports are about really asking for help figuring out how to 25 | configure the build. `mk/cargo.sh`, `mk/install-build-tools.{sh,ps1}`, and the 26 | GitHub Actions configuration contain plenty of examples of how to build this. 27 | There is a discussion category 28 | https://github.com/briansmith/ring/discussions/categories/building for 29 | people to help each other with build issues. 30 | 31 | The best way to request a port to a target that we haven't tried to support is 32 | to submit a PR that modifies `mk/cargo.sh` and `mk/install-build-tools.{sh,ps1}` 33 | to make it easy for people to test the port (in QEMU). 34 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | patch: 4 | default: 5 | # Even when coverage hasn't decreased, Codecov would report a reduction 6 | # in coverage of about 0.01%, but only for the patch-level measurement. 7 | # Work around that. 8 | threshold: 0.02% 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # pregenerated/ cannot be here because we need `cargo package` to package stuff 2 | # in it. 3 | 4 | build/ 5 | ssl/test/runner/runner 6 | *.log 7 | *.pyc 8 | *.swp 9 | *.swo 10 | doc/*.html 11 | doc/doc.css 12 | 13 | *.bk 14 | *.orig 15 | *~ 16 | 17 | # Visual Studio Junk 18 | .vs/ 19 | *.opensdf 20 | *.psess 21 | *.sdf 22 | *.sln.docstates 23 | *.suo 24 | *.user 25 | *.userosscache 26 | *.VC.db 27 | *.VC.opendb 28 | *.vsp 29 | *.vspx 30 | *.rsproj 31 | *.sln 32 | *.vcxproj 33 | *.filters 34 | 35 | 36 | # Cargo Junk 37 | Cargo.lock 38 | target/ 39 | 40 | # JetBrains Junk 41 | .idea 42 | *.iml 43 | CMakeLists.txt 44 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of BoringSSL's significant contributors. 2 | # 3 | # This does not necessarily list everyone who has contributed code, 4 | # especially since many employees of one corporation may be contributing. 5 | # To see the full list of contributors, see the revision history in 6 | # source control. 7 | Google LLC 8 | Brian Smith 9 | 10 | # Additionally, much of the code in BoringSSL is derived from code in the 11 | # OpenSSL project. We thank the OpenSSL project’s contributors for their 12 | # work. Some of these contributors are listed below. For the full list of 13 | # these contributors, see AUTHORS.md in OpenSSL and the revision history 14 | # in OpenSSL’s source control. 15 | OpenSSL Software Services, Inc. 16 | OpenSSL Software Foundation, Inc. 17 | Andy Polyakov 18 | Ben Laurie 19 | Ben Kaduk 20 | Bernd Edlinger 21 | Bodo Möller 22 | David Benjamin 23 | David von Oheimb 24 | Dmitry Belyavskiy (Дмитрий Белявский) 25 | Emilia Käsper 26 | Eric Young 27 | Geoff Thorpe 28 | Holger Reif 29 | Kurt Roeckx 30 | Lutz Jänicke 31 | Mark J. Cox 32 | Matt Caswell 33 | Matthias St. Pierre 34 | Nicola Tuveri 35 | Nils Larsch 36 | Patrick Steuer 37 | Paul Dale 38 | Paul C. Sutton 39 | Paul Yang 40 | Ralf S. Engelschall 41 | Rich Salz 42 | Richard Levitte 43 | Shane Lontis 44 | Stephen Henson 45 | Steve Marquess 46 | Tim Hudson 47 | Tomáš Mráz 48 | Ulf Möller 49 | Viktor Dukhovni 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | *ring* uses an "ISC" license, like BoringSSL used to use, for new code 2 | files. See LICENSE-other-bits for the text of that license. 3 | 4 | See LICENSE-BoringSSL for code that was sourced from BoringSSL under the 5 | Apache 2.0 license. Some code that was sourced from BoringSSL under the ISC 6 | license. In each case, the license info is at the top of the file. 7 | 8 | See src/polyfill/once_cell/LICENSE-APACHE and src/polyfill/once_cell/LICENSE-MIT 9 | for the license to code that was sourced from the once_cell project. 10 | -------------------------------------------------------------------------------- /LICENSE-other-bits: -------------------------------------------------------------------------------- 1 | Copyright 2015-2025 Brian Smith. 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | THE SOFTWARE IS PROVIDED "AS IS" AND BRIAN SMITH AND THE AUTHORS DISCLAIM 2 | ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 3 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL BRIAN SMITH OR THE AUTHORS 4 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY 5 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 6 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 7 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 8 | 9 | 10 | Most of the C and assembly language code in *ring* comes from BoringSSL. 11 | BoringSSL is a fork of OpenSSL. This quote from the BoringSSL README.md 12 | discouraging you from using it applies to this project: 13 | 14 | > BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. 15 | > 16 | > Although BoringSSL is an open source project, it is not intended for general 17 | > use, as OpenSSL is. We don't recommend that third parties depend upon it. 18 | 19 | This project was originally shared on GitHub in 2015 as an experiment. It was 20 | put on crates.io shortly to help other people with their experiments. It is an 21 | experiment. 22 | 23 | 24 | Side Channels 25 | ------------- 26 | 27 | See [SIDE-CHANNELS.md](SIDE-CHANNELS.md) for important information regarding 28 | the limitations of the side channel mitigations in this project. 29 | 30 | 31 | Toolchains & Targets 32 | -------------------- 33 | 34 | Be especially weary about using toolchains (C compilers, etc.) or targets 35 | that aren't supported by other projects, especially BoringSSL. The further you 36 | are from using the same version of Clang that Chrome uses, the more weary you 37 | should be. 38 | 39 | 40 | Bug Reporting 41 | ------------- 42 | 43 | For security vulnerabilities, see https://github.com/briansmith/ring/security/policy. 44 | 45 | Please report bugs that aren't security vulnerabilities either as pull requests or as issues in 46 | [the issue tracker](https://github.com/briansmith/ring/issues). 47 | 48 | 49 | 50 | Release Notes 51 | ------------- 52 | It is recommended that you review every commit in this project. Some 53 | particularly noteworthy changes are noted in the [RELEASES.md](RELEASES.md). We could use some 54 | help in making this better. 55 | -------------------------------------------------------------------------------- /RELEASES.md: -------------------------------------------------------------------------------- 1 | Version 0.17.15 (TBD) 2 | ============================ 3 | Support for aarch64-*-linux-uclibc targets was removed, as there do not seem to 4 | be any such targets. 5 | 6 | Version 0.17.14 (2025-03-11) 7 | ============================ 8 | Fixed a performance bug in the AVX2-based AES-GCM implementation added in 9 | *ring* 0.17.13. This will be another notable performance improvement for most 10 | newish x86-64 systems. The performance issue impacted not just AES-GCM. 11 | 12 | Compatibility with GNU binutils 2.29 (used on Amazon Linux 2), and probably 13 | even earlier versions, was restored. It is expected that *ring* 0.17.14 will 14 | build on all the systems that 0.17.12 would build on. 15 | 16 | Version 0.17.13 (2025-03-06) 17 | ============================ 18 | Increased MSRV to 1.66.0 to avoid bugs in earlier versions so that we can 19 | safely use `core::arch::x86_64::__cpuid` and `core::arch::x86::__cpuid` from 20 | Rust in future releases. 21 | 22 | AVX2-based VAES-CLMUL implementation. This will be a notable performance 23 | improvement for most newish x86-64 systems. This will likely raise the minimum 24 | binutils version supported for very old Linux distros. 25 | 26 | Version 0.17.12 (2025-03-05) 27 | ============================ 28 | Bug fix: https://github.com/briansmith/ring/pull/2447 for denial of service (DoS). 29 | 30 | * Fixes a panic in `ring::aead::quic::HeaderProtectionKey::new_mask()` when 31 | integer overflow checking is enabled. In the QUIC protocol, an attacker can 32 | induce this panic by sending a specially-crafted packet. Even unintentionally 33 | it is likely to occur in 1 out of every 2**32 packets sent and/or received. 34 | 35 | * Fixes a panic on 64-bit targets in `ring::aead::{AES_128_GCM, AES_256_GCM}` 36 | when overflow checking is enabled, when encrypting/decrypting approximately 37 | 68,719,476,700 bytes (about 64 gigabytes) of data in a single chunk. Protocols 38 | like TLS and SSH are not affected by this because those protocols break large 39 | amounts of data into small chunks. Similarly, most applications will not 40 | attempt to encrypt/decrypt 64GB of data in one chunk. 41 | 42 | Overflow checking is not enabled in release mode by default, but 43 | `RUSTFLAGS="-C overflow-checks"` or `overflow-checks = true` in the Cargo.toml 44 | profile can override this. Overflow checking is usually enabled by default in 45 | debug mode. 46 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | The latest release of *ring* is supported. The fixes for any security issues found will be included 6 | in the next release. 7 | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Please [use *ring*'s security advisory reporting tool provided by 12 | GitHub](https://github.com/briansmith/ring/security/advisories/new) to report security issues. 13 | 14 | We strive to fix security issues as quickly as possible. Across the industry, often the developers' 15 | slowness in developing and releasing a fix is the biggest delay in the process; we take pride in 16 | minimizing this delay as much as we practically can. We encourage you to also minimize the delay 17 | between when you find an issue and when you contact us. You do not need to convince us to take your 18 | report seriously. You don't need to create a PoC or a patch if that would slow down your reporting. 19 | You don't need an elaborate write-up. A short, informal note about the issue is good. We can always 20 | communicate later to fill in any details we need after that first note is shared with us. 21 | -------------------------------------------------------------------------------- /SIDE-CHANNELS.md: -------------------------------------------------------------------------------- 1 | Side Channels 2 | ============= 3 | 4 | This project uses coding patterns that attempt to reduce the risk that the 5 | compiler will generate machine code that will leak secrets through timing side 6 | channels. This project uses similar mitigations as BoringSSL, but they are not 7 | exactly the same, they are not used in exactly the same way. BoringSSL seems to 8 | have some ways of validating that its mitigations work with specific versions 9 | of specific C/C++ compilers. This project kinda relies on that; this should be 10 | revisited. 11 | 12 | There are some targets where trying to be "constant-time" just isn't going to 13 | work. 14 | 15 | For WebAssembly and WebAssembly-like targets, where there is a JIT, virtual 16 | machine, or similar intermediary involved, the runtime is likely to undo 17 | whatever we do to mitigate timing side channels. Even with the introduction of 18 | blinding, there is a big risk for these targets. WebAssembly itself needs to 19 | develop solutions for solving these problems. 20 | 21 | There are "native" targets that have similar issues. BoringSSL will refuse to 22 | compile for some of them because of its allowlist of targets. *ring* doesn't 23 | use that allowlist, and also the allowlist doesn't completely avoid the 24 | problem. 25 | 26 | *ring* doesn't use any randomizing mitigations like blinding. 27 | 28 | Over time, as compiler evolved, mitigations for compiler-introduced side 29 | channels have had to evolve. What worked years ago with version X of the C 30 | compiler doesn't necessarily work now with version X+1, or even with the same 31 | version of the compiler shipped by a different vendor or configured in a 32 | different way. This probably affects this project's releases and would probably 33 | affect the project more and more over time going forward. 34 | 35 | Over time *ring* and BoringSSL have diverged in various areas. In some cases 36 | *ring* was ahead of BoringSSL regarding mitigations for timing side channels 37 | using our own code. For example, there was a time when we replaced much of the 38 | ECC code and RSA code that was using variable-length `BIGNUM` arithmetic with 39 | similar fixed-length bigint arithmetic. However, since then, BoringSSL has come 40 | up with its own similar but different solution. Similarly, because of our hopes 41 | of eventually getting rid of the C code in *ring*, and the hope of eventually 42 | minimizing the use of external assembly code, and other difficulties, in some 43 | situations this project uses a substantially different implementation of a 44 | primitive than BoringSSL may use. This is something to be investigated. 45 | 46 | Recently, BoringSSL has converted most of its code from C to C++, whereas 47 | *ring* still uses the C variant of that code. This would naturally make sharing 48 | code hard unless we also switch to requiring a C++ compiler for *ring*. And of 49 | course this even further reduces the validity of relying on BoringSSL's testing 50 | for *ring*. 51 | 52 | Besides all of the above, there are many other things to consider regarding 53 | timing side channels and other kinds of side channels. 54 | -------------------------------------------------------------------------------- /bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "ring-bench" 4 | publish = false 5 | version = "0.1.0" 6 | 7 | [dependencies] 8 | ring = { path = "../" } 9 | 10 | [dev-dependencies] 11 | criterion = { version = "0.5.1", default-features = false } 12 | 13 | [[bench]] 14 | name = "aead" 15 | harness = false 16 | path = "aead.rs" 17 | 18 | [[bench]] 19 | name = "agreement" 20 | harness = false 21 | path = "agreement.rs" 22 | 23 | [[bench]] 24 | name = "digest" 25 | harness = false 26 | path = "digest.rs" 27 | 28 | [[bench]] 29 | name = "ecdsa" 30 | harness = false 31 | path = "ecdsa.rs" 32 | 33 | [[bench]] 34 | name = "rsa" 35 | harness = false 36 | path = "rsa.rs" 37 | -------------------------------------------------------------------------------- /bench/data/rsa-2048-3-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-2048-3-public-key.der -------------------------------------------------------------------------------- /bench/data/rsa-2048-3-signature.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-2048-3-signature.bin -------------------------------------------------------------------------------- /bench/data/rsa-2048-65537-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-2048-65537-public-key.der -------------------------------------------------------------------------------- /bench/data/rsa-2048-65537-signature.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-2048-65537-signature.bin -------------------------------------------------------------------------------- /bench/data/rsa-3072-3-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-3072-3-public-key.der -------------------------------------------------------------------------------- /bench/data/rsa-3072-3-signature.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-3072-3-signature.bin -------------------------------------------------------------------------------- /bench/data/rsa-4096-3-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-4096-3-public-key.der -------------------------------------------------------------------------------- /bench/data/rsa-4096-3-signature.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-4096-3-signature.bin -------------------------------------------------------------------------------- /bench/data/rsa-8192-3-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-8192-3-public-key.der -------------------------------------------------------------------------------- /bench/data/rsa-8192-3-signature.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/bench/data/rsa-8192-3-signature.bin -------------------------------------------------------------------------------- /bench/data/rsa-generate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2023 Brian Smith. 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -eux -o pipefail 18 | IFS=$'\n\t' 19 | 20 | truncate --size 0 empty_message 21 | 22 | openssl genpkey -algorithm RSA \ 23 | -pkeyopt rsa_keygen_bits:2048 \ 24 | -pkeyopt rsa_keygen_pubexp:65537 | \ 25 | openssl pkcs8 -topk8 -nocrypt -outform der > rsa-2048-65537.p8 26 | 27 | openssl pkey -pubout -inform der -outform der \ 28 | -in rsa-2048-65537.p8 | \ 29 | openssl rsa -pubin -RSAPublicKey_out -inform DER -outform DER \ 30 | -out rsa-2048-65537-public-key.der 31 | openssl dgst -sha256 -sign rsa-2048-65537.p8 -out rsa-2048-65537-signature.bin empty_message 32 | rm rsa-2048-65537.p8 33 | 34 | m=(2048 3072 4096 8192) 35 | for i in "${m[@]}" 36 | do 37 | echo $i 38 | openssl genpkey -algorithm RSA \ 39 | -pkeyopt rsa_keygen_bits:$i \ 40 | -pkeyopt rsa_keygen_pubexp:3 | \ 41 | openssl pkcs8 -topk8 -nocrypt -outform der > rsa-$i-3.p8 42 | 43 | openssl pkey -pubout -inform der -outform der \ 44 | -in rsa-$i-3.p8 | \ 45 | openssl rsa -pubin -RSAPublicKey_out -inform DER -outform DER \ 46 | -out rsa-$i-3-public-key.der 47 | 48 | openssl dgst -sha256 -sign rsa-$i-3.p8 -out rsa-$i-3-signature.bin empty_message 49 | 50 | rm rsa-$i-3.p8 51 | done 52 | 53 | rm empty_message 54 | -------------------------------------------------------------------------------- /bench/digest.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | #![allow(missing_docs)] 15 | 16 | use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; 17 | use ring::digest; 18 | 19 | static ALGORITHMS: &[(&str, &digest::Algorithm)] = &[ 20 | ("sha256", &digest::SHA256), 21 | ("sha384", &digest::SHA384), 22 | ("sha512", &digest::SHA512), 23 | ]; 24 | 25 | const INPUT_LENGTHS: &[usize] = &[ 26 | // Benchmark that emphasizes overhead. 27 | 0, 28 | 32, 29 | 64, 30 | 128, 31 | 1024, 32 | 2048, 33 | 4096, 34 | 8192, 35 | 1024 * 1024, 36 | ]; 37 | 38 | const SMALL_MAX: usize = 8192; 39 | 40 | #[repr(align(64))] 41 | struct Small([u8; SMALL_MAX]); 42 | 43 | fn oneshot(c: &mut Criterion) { 44 | for &(alg_name, algorithm) in ALGORITHMS { 45 | for input_len in INPUT_LENGTHS { 46 | c.bench_with_input( 47 | BenchmarkId::new(format!("digest::oneshot::{alg_name}"), input_len), 48 | input_len, 49 | |b, &input_len| { 50 | let small; 51 | let v; 52 | let input = if input_len <= SMALL_MAX { 53 | // Use an aligned buffer to minimize alignment-related variance. 54 | small = Small([0; SMALL_MAX]); 55 | &small.0[..input_len] 56 | } else { 57 | // TODO: Align this similarly. 58 | v = vec![0u8; input_len]; 59 | &v[..] 60 | }; 61 | b.iter(|| -> usize { 62 | let digest = digest::digest(algorithm, &input); 63 | black_box(digest.as_ref().len()) 64 | }) 65 | }, 66 | ); 67 | } 68 | } 69 | } 70 | 71 | criterion_group!(digest, oneshot); 72 | criterion_main!(digest); 73 | -------------------------------------------------------------------------------- /bench/ecdsa.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | #![allow(missing_docs)] 15 | 16 | use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; 17 | use ring::{ 18 | rand, 19 | signature::{self, EcdsaKeyPair, EcdsaSigningAlgorithm, EcdsaVerificationAlgorithm, KeyPair}, 20 | }; 21 | 22 | static ALGORITHMS: &[(&str, &EcdsaSigningAlgorithm, &EcdsaVerificationAlgorithm)] = &[ 23 | ( 24 | "p256", 25 | &signature::ECDSA_P256_SHA256_ASN1_SIGNING, 26 | &signature::ECDSA_P256_SHA256_ASN1, 27 | ), 28 | ( 29 | "p384", 30 | &signature::ECDSA_P384_SHA384_ASN1_SIGNING, 31 | &signature::ECDSA_P384_SHA384_ASN1, 32 | ), 33 | ]; 34 | 35 | fn sign(c: &mut Criterion) { 36 | for (alg_name, alg, _) in ALGORITHMS { 37 | c.bench_function(&format!("ecdsa_{alg_name}_sign"), |b| { 38 | let rng = rand::SystemRandom::new(); 39 | let pkcs8_bytes = EcdsaKeyPair::generate_pkcs8(alg, &rng).unwrap(); 40 | let key_pair = EcdsaKeyPair::from_pkcs8(alg, pkcs8_bytes.as_ref(), &rng).unwrap(); 41 | 42 | b.iter(|| { 43 | key_pair.sign(&rng, black_box(&[])).unwrap(); 44 | }) 45 | }); 46 | } 47 | } 48 | 49 | fn verify(c: &mut Criterion) { 50 | for (alg_name, sign_alg, verify_alg) in ALGORITHMS { 51 | c.bench_function(&format!("ecdsa_{alg_name}_verify"), |b| { 52 | let rng = rand::SystemRandom::new(); 53 | let pkcs8_bytes = EcdsaKeyPair::generate_pkcs8(sign_alg, &rng).unwrap(); 54 | let key_pair = EcdsaKeyPair::from_pkcs8(sign_alg, pkcs8_bytes.as_ref(), &rng).unwrap(); 55 | 56 | let public_key = 57 | signature::UnparsedPublicKey::new(*verify_alg, key_pair.public_key().as_ref()); 58 | 59 | b.iter_batched( 60 | || key_pair.sign(&rng, &[]).unwrap(), 61 | |signature| { 62 | public_key 63 | .verify(black_box(&[]), black_box(signature.as_ref())) 64 | .unwrap(); 65 | }, 66 | BatchSize::LargeInput, 67 | ) 68 | }); 69 | } 70 | } 71 | 72 | criterion_group!(ecdsa, sign, verify); 73 | criterion_main!(ecdsa); 74 | -------------------------------------------------------------------------------- /bench/rsa.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | #![allow(missing_docs)] 15 | 16 | use criterion::{criterion_group, criterion_main, Criterion}; 17 | use ring::signature::{UnparsedPublicKey, RSA_PKCS1_2048_8192_SHA256}; 18 | 19 | macro_rules! verify_case { 20 | ( $modulus_bits:expr, $exponent_value:expr ) => { 21 | TestCase { 22 | modulus_bits: $modulus_bits, 23 | exponent_value: $exponent_value, 24 | public_key: include_bytes!(concat!( 25 | "data/rsa-", 26 | stringify!($modulus_bits), 27 | "-", 28 | stringify!($exponent_value), 29 | "-public-key.der" 30 | )), 31 | signature: include_bytes!(concat!( 32 | "data/rsa-", 33 | stringify!($modulus_bits), 34 | "-", 35 | stringify!($exponent_value), 36 | "-signature.bin" 37 | )), 38 | } 39 | }; 40 | } 41 | 42 | fn verify(c: &mut Criterion) { 43 | struct TestCase { 44 | modulus_bits: usize, 45 | exponent_value: usize, 46 | public_key: &'static [u8], 47 | signature: &'static [u8], 48 | } 49 | static TEST_CASES: &[TestCase] = &[ 50 | verify_case!(2048, 65537), 51 | verify_case!(2048, 3), 52 | verify_case!(3072, 3), 53 | verify_case!(4096, 3), 54 | verify_case!(8192, 3), 55 | ]; 56 | 57 | for TestCase { 58 | modulus_bits, 59 | exponent_value, 60 | public_key, 61 | signature, 62 | } in TEST_CASES 63 | { 64 | c.bench_function( 65 | &format!("rsa_verify_{modulus_bits}_{exponent_value}"), 66 | |b| { 67 | const MESSAGE: &[u8] = &[]; 68 | 69 | b.iter(|| { 70 | let public_key = 71 | UnparsedPublicKey::new(&RSA_PKCS1_2048_8192_SHA256, public_key); 72 | public_key.verify(MESSAGE, signature).unwrap(); 73 | }); 74 | }, 75 | ); 76 | } 77 | } 78 | 79 | criterion_group!(rsa, verify); 80 | criterion_main!(rsa); 81 | -------------------------------------------------------------------------------- /cavp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "ring-cavp" 4 | publish = false 5 | version = "0.1.0" 6 | 7 | [dev-dependencies] 8 | ring = { path = ".." } 9 | 10 | [target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dev-dependencies] 11 | wasm-bindgen-test = { version = "0.3.37", default-features = false } 12 | -------------------------------------------------------------------------------- /cavp/third_party/NIST/.gitattributes: -------------------------------------------------------------------------------- 1 | # Preserve the line endings on the NIST test vectors so that we can use 2 | # sha256sum and friends to verify that they haven't been tampered with. 3 | *.rsp eol=crlf 4 | -------------------------------------------------------------------------------- /cavp/third_party/NIST/README.md: -------------------------------------------------------------------------------- 1 | # NIST Test Vectors 2 | 3 | [SHAVS](SHAVS) contains the [SHA Test Vectors for Hashing Byte-Oriented 4 | Messages](http://csrc.nist.gov/groups/STM/cavp/documents/shs/shabytetestvectors.zip) 5 | from [Secure Hash Algorithm Validation System 6 | (SHAVS)](http://csrc.nist.gov/groups/STM/cavp/#03). 7 | 8 | [sha256sums.txt](sha256sums.txt) contains the SHA-256 checksums for the ZIP 9 | files from which the test vectors were extracted. 10 | -------------------------------------------------------------------------------- /cavp/third_party/NIST/sha256sums.txt: -------------------------------------------------------------------------------- 1 | 0ac90b0d5fba398319d8a4697dce0eb88ae3b3eacf69473a9249e6bea46456e4 *shabytetestvectors.zip 2 | -------------------------------------------------------------------------------- /crypto/crypto.c: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The BoringSSL Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | // Our assembly does not use the GOT to reference symbols, which means 18 | // references to visible symbols will often require a TEXTREL. This is 19 | // undesirable, so all assembly-referenced symbols should be hidden. CPU 20 | // capabilities are the only such symbols defined in C. Explicitly hide them, 21 | // rather than rely on being built with -fvisibility=hidden. 22 | #if defined(OPENSSL_WINDOWS) 23 | #define HIDDEN 24 | #else 25 | #define HIDDEN __attribute__((visibility("hidden"))) 26 | #endif 27 | 28 | #if defined(OPENSSL_X86_64) 29 | // These are declared as `AtomicU32` on the Rust side. 30 | HIDDEN uint32_t avx2_available = 0; 31 | HIDDEN uint32_t adx_bmi2_available = 0; 32 | #elif defined(OPENSSL_ARM) 33 | HIDDEN uint32_t neon_available = 0; 34 | #endif 35 | -------------------------------------------------------------------------------- /crypto/curve25519/.gitattributes: -------------------------------------------------------------------------------- 1 | curve25519_tables.h linguist-generated=true 2 | -------------------------------------------------------------------------------- /crypto/curve25519/curve25519_64_adx.c: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The BoringSSL Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "internal.h" 16 | #if defined(BORINGSSL_FE25519_ADX) 17 | 18 | #pragma GCC diagnostic ignored "-Wconversion" 19 | #pragma GCC diagnostic ignored "-Wpedantic" 20 | #pragma GCC diagnostic ignored "-Wsign-conversion" 21 | 22 | #include "../../third_party/fiat/curve25519_64_adx.h" 23 | #endif 24 | -------------------------------------------------------------------------------- /crypto/fipsmodule/aes/asm/make-avx-map-for-old-binutils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse 4 | import subprocess 5 | import re 6 | import sys 7 | 8 | PCLMUL_RE = re.compile(r'^\s+[0-9a-f]+:\s+(?P(?:[0-9a-f][0-9a-f] )+)\s+vpclmul(?P[0-9a-z]+)dq (?P.*%[yz]mm.*)$') 9 | NON_PCLMUL_RE = re.compile(r'^\s+[0-9a-f]+:\s+(?P(?:[0-9a-f][0-9a-f] )+)\s+(?Pvaesenc|vaesenclast) (?P.*%[yz]mm.*)$') 10 | 11 | TYPE_MAP = { 12 | 'lqlq': 0x00, 13 | 'lqhq': 0x10, 14 | 'hqlq': 0x01, 15 | 'hqhq': 0x11, 16 | } 17 | 18 | def hexify_disas(disas): 19 | return (' '+disas.strip()).replace(' ', ',0x')[1:] 20 | 21 | def main(): 22 | parser = argparse.ArgumentParser( 23 | prog='make-avx-map-for-old-binutils', 24 | description='Generate a map file for old binutils from .o files' 25 | ) 26 | parser.add_argument('filename', nargs='+', help='object file to generate map from') 27 | parsed = parser.parse_args() 28 | for filename in parsed.filename: 29 | for line in subprocess.check_output(['objdump', '-d', filename], stderr=sys.stderr).decode('utf-8').split('\n'): 30 | if match := PCLMUL_RE.match(line): 31 | hexified_disas = hexify_disas(match.group('disas')) 32 | ty = TYPE_MAP[match.group('type')] 33 | args = match.group('args').replace(',', ', ') 34 | print(f" 'vpclmulqdq $0x{ty:02x}, {args}' => '.byte {hexified_disas}',") 35 | elif match := NON_PCLMUL_RE.match(line): 36 | hexified_disas = hexify_disas(match.group('disas')) 37 | args = match.group('args').replace(',', ', ') 38 | print(f" '{match.group('instruction')} {args}' => '.byte {hexified_disas}',") 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /crypto/fipsmodule/bn/montgomery.c: -------------------------------------------------------------------------------- 1 | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "internal.h" 16 | #include "../../internal.h" 17 | 18 | #include "../../limbs/limbs.h" 19 | #include "../../limbs/limbs.inl" 20 | 21 | OPENSSL_STATIC_ASSERT(BN_MONT_CTX_N0_LIMBS == 1 || BN_MONT_CTX_N0_LIMBS == 2, 22 | "BN_MONT_CTX_N0_LIMBS value is invalid"); 23 | OPENSSL_STATIC_ASSERT( 24 | sizeof(BN_ULONG) * BN_MONT_CTX_N0_LIMBS == sizeof(uint64_t), 25 | "uint64_t is insufficient precision for n0"); 26 | 27 | int bn_from_montgomery_in_place(BN_ULONG r[], size_t num_r, BN_ULONG a[], 28 | size_t num_a, const BN_ULONG n[], 29 | size_t num_n, 30 | const BN_ULONG n0_[BN_MONT_CTX_N0_LIMBS]) { 31 | if (num_n == 0 || num_r != num_n || num_a != 2 * num_n) { 32 | return 0; 33 | } 34 | 35 | // Add multiples of |n| to |r| until R = 2^(nl * BN_BITS2) divides it. On 36 | // input, we had |r| < |n| * R, so now |r| < 2 * |n| * R. Note that |r| 37 | // includes |carry| which is stored separately. 38 | BN_ULONG n0 = n0_[0]; 39 | BN_ULONG carry = 0; 40 | for (size_t i = 0; i < num_n; i++) { 41 | BN_ULONG v = limbs_mul_add_limb(a + i, n, a[i] * n0, num_n); 42 | v += carry + a[i + num_n]; 43 | carry |= (v != a[i + num_n]); 44 | carry &= (v <= a[i + num_n]); 45 | a[i + num_n] = v; 46 | } 47 | 48 | // Shift |num_n| words to divide by R. We have |a| < 2 * |n|. Note that |a| 49 | // includes |carry| which is stored separately. 50 | a += num_n; 51 | 52 | // |a| thus requires at most one additional subtraction |n| to be reduced. 53 | // Subtract |n| and select the answer in constant time. 54 | BN_ULONG v = limbs_sub(r, a, n, num_n) - carry; 55 | // |v| is one if |a| - |n| underflowed or zero if it did not. Note |v| cannot 56 | // be -1. That would imply the subtraction did not fit in |num_n| words, and 57 | // we know at most one subtraction is needed. 58 | v = 0u - v; 59 | for (size_t i = 0; i < num_n; i++) { 60 | r[i] = constant_time_select_w(v, a[i], r[i]); 61 | a[i] = 0; 62 | } 63 | return 1; 64 | } 65 | -------------------------------------------------------------------------------- /crypto/fipsmodule/ec/.gitattributes: -------------------------------------------------------------------------------- 1 | p256-nistz-table.h linguist-generated=true 2 | p256_table.h linguist-generated=true 3 | -------------------------------------------------------------------------------- /crypto/fipsmodule/ec/ecp_nistz.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014, Intel Corporation. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 | 15 | #include "ecp_nistz.h" 16 | 17 | #if defined(__GNUC__) 18 | #pragma GCC diagnostic ignored "-Wconversion" 19 | #endif 20 | 21 | /* Fills |str| with the bytewise little-endian encoding of |scalar|, where 22 | * |scalar| has |num_limbs| limbs. |str| is padded with zeros at the end up 23 | * to |str_len| bytes. Actually, |str_len| must be exactly one byte more than 24 | * needed to encode |num_limbs| losslessly, so that there is an extra byte at 25 | * the end. The extra byte is useful because the caller will be breaking |str| 26 | * up into windows of a number of bits (5 or 7) that isn't divisible by 8, and 27 | * so it is useful for it to be able to read an extra zero byte. */ 28 | void little_endian_bytes_from_scalar(uint8_t str[], size_t str_len, 29 | const Limb scalar[], 30 | size_t num_limbs) { 31 | debug_assert_nonsecret(str_len == (num_limbs * sizeof(Limb)) + 1); 32 | 33 | size_t i; 34 | for (i = 0; i < num_limbs * sizeof(Limb); i += sizeof(Limb)) { 35 | Limb d = scalar[i / sizeof(Limb)]; 36 | 37 | str[i + 0] = d & 0xff; 38 | str[i + 1] = (d >> 8) & 0xff; 39 | str[i + 2] = (d >> 16) & 0xff; 40 | str[i + 3] = (d >>= 24) & 0xff; 41 | if (sizeof(Limb) == 8) { 42 | d >>= 8; 43 | str[i + 4] = d & 0xff; 44 | str[i + 5] = (d >> 8) & 0xff; 45 | str[i + 6] = (d >> 16) & 0xff; 46 | str[i + 7] = (d >> 24) & 0xff; 47 | } 48 | } 49 | for (; i < str_len; i++) { 50 | str[i] = 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crypto/fipsmodule/ec/ecp_nistz384.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014, Intel Corporation. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 | 15 | #ifndef OPENSSL_HEADER_EC_ECP_NISTZ384_H 16 | #define OPENSSL_HEADER_EC_ECP_NISTZ384_H 17 | 18 | #include "../../limbs/limbs.h" 19 | 20 | #define P384_LIMBS (384u / LIMB_BITS) 21 | 22 | typedef struct { 23 | Limb X[P384_LIMBS]; 24 | Limb Y[P384_LIMBS]; 25 | Limb Z[P384_LIMBS]; 26 | } P384_POINT; 27 | 28 | typedef struct { 29 | Limb X[P384_LIMBS]; 30 | Limb Y[P384_LIMBS]; 31 | } P384_POINT_AFFINE; 32 | 33 | 34 | #endif // OPENSSL_HEADER_EC_ECP_NISTZ384_H 35 | -------------------------------------------------------------------------------- /crypto/fipsmodule/ec/gfp_p256.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 Brian Smith. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 | 15 | #include "./p256_shared.h" 16 | 17 | #include "../../limbs/limbs.h" 18 | 19 | #if !defined(OPENSSL_USE_NISTZ256) 20 | 21 | typedef Limb ScalarMont[P256_LIMBS]; 22 | typedef Limb Scalar[P256_LIMBS]; 23 | 24 | #include "../bn/internal.h" 25 | 26 | static const BN_ULONG N[P256_LIMBS] = { 27 | #if defined(OPENSSL_64_BIT) 28 | 0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000 29 | #else 30 | 0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, 0xffffffff, 0xffffffff, 0, 31 | 0xffffffff 32 | #endif 33 | }; 34 | 35 | static const BN_ULONG N_N0[] = { 36 | BN_MONT_CTX_N0(0xccd1c8aa, 0xee00bc4f) 37 | }; 38 | 39 | void p256_scalar_mul_mont(ScalarMont r, const ScalarMont a, 40 | const ScalarMont b) { 41 | /* XXX: Inefficient. TODO: optimize with dedicated multiplication routine. */ 42 | bn_mul_mont_small(r, a, b, N, N_N0, P256_LIMBS); 43 | } 44 | 45 | /* XXX: Inefficient. TODO: optimize with dedicated squaring routine. */ 46 | void p256_scalar_sqr_rep_mont(ScalarMont r, const ScalarMont a, Limb rep) { 47 | dev_assert_secret(rep >= 1); 48 | p256_scalar_mul_mont(r, a, a); 49 | for (Limb i = 1; i < rep; ++i) { 50 | p256_scalar_mul_mont(r, r, r); 51 | } 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /crypto/fipsmodule/ec/p256_shared.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. 2 | // Copyright (c) 2014, Intel Corporation. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // https://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | // Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) 17 | // (1) Intel Corporation, Israel Development Center, Haifa, Israel 18 | // (2) University of Haifa, Israel 19 | // 20 | // Reference: 21 | // S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with 22 | // 256 Bit Primes" 23 | 24 | #ifndef OPENSSL_HEADER_EC_P256_SHARED_H 25 | #define OPENSSL_HEADER_EC_P256_SHARED_H 26 | 27 | #include "ring-core/base.h" 28 | 29 | #include "../bn/internal.h" 30 | 31 | #if !defined(OPENSSL_NO_ASM) && \ 32 | (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \ 33 | !defined(OPENSSL_SMALL) 34 | # define OPENSSL_USE_NISTZ256 35 | #endif 36 | 37 | // P-256 field operations. 38 | // 39 | // An element mod P in P-256 is represented as a little-endian array of 40 | // |P256_LIMBS| |BN_ULONG|s, spanning the full range of values. 41 | // 42 | // The following functions take fully-reduced inputs mod P and give 43 | // fully-reduced outputs. They may be used in-place. 44 | 45 | #define P256_LIMBS (256 / BN_BITS2) 46 | 47 | // A P256_POINT represents a P-256 point in Jacobian coordinates. 48 | typedef struct { 49 | BN_ULONG X[P256_LIMBS]; 50 | BN_ULONG Y[P256_LIMBS]; 51 | BN_ULONG Z[P256_LIMBS]; 52 | } P256_POINT; 53 | 54 | typedef unsigned char P256_SCALAR_BYTES[33]; 55 | 56 | static inline void p256_scalar_bytes_from_limbs( 57 | P256_SCALAR_BYTES bytes_out, const BN_ULONG limbs[P256_LIMBS]) { 58 | OPENSSL_memcpy(bytes_out, limbs, 32); 59 | bytes_out[32] = 0; 60 | } 61 | 62 | #endif /* !defined(OPENSSL_USE_NISTZ256) */ 63 | -------------------------------------------------------------------------------- /crypto/limbs/limbs.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 Brian Smith. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 | 15 | #ifndef RING_LIMBS_H 16 | #define RING_LIMBS_H 17 | 18 | #include 19 | 20 | #include "../internal.h" 21 | 22 | typedef crypto_word_t Limb; 23 | 24 | #define LIMB_BITS CRYPTO_WORD_BITS 25 | #define LIMB_HIGH_BIT ((Limb)(1) << (LIMB_BITS - 1)) 26 | 27 | 28 | Limb LIMBS_are_zero(const Limb a[], size_t num_limbs); 29 | Limb LIMBS_equal(const Limb a[], const Limb b[], size_t num_limbs); 30 | void LIMBS_reduce_once(Limb r[], const Limb m[], size_t num_limbs); 31 | void LIMBS_add_mod(Limb r[], const Limb a[], const Limb b[], const Limb m[], 32 | size_t num_limbs); 33 | void LIMBS_sub_mod(Limb r[], const Limb a[], const Limb b[], const Limb m[], 34 | size_t num_limbs); 35 | void LIMBS_shl_mod(Limb r[], const Limb a[], const Limb m[], size_t num_limbs); 36 | Limb limbs_mul_add_limb(Limb r[], const Limb a[], Limb b, size_t num_limbs); 37 | 38 | #endif /* RING_LIMBS_H */ 39 | -------------------------------------------------------------------------------- /crypto/mem.c: -------------------------------------------------------------------------------- 1 | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include "internal.h" 17 | 18 | int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) { 19 | const aliasing_uint8_t *a = in_a; 20 | const aliasing_uint8_t *b = in_b; 21 | uint8_t x = 0; 22 | 23 | for (size_t i = 0; i < len; i++) { 24 | x |= a[i] ^ b[i]; 25 | } 26 | 27 | return x; 28 | } 29 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | [advisories] 2 | version = 2 3 | 4 | [licenses] 5 | version = 2 6 | allow = [ 7 | "Apache-2.0", 8 | "ISC", 9 | "MIT", 10 | ] 11 | confidence-threshold = 1.0 12 | 13 | [bans] 14 | # We don't maintain a fixed Cargo.lock so enforcing 15 | # `multiple-versions = "deny"` is impractical. 16 | multiple-versions = "allow" 17 | wildcards = "deny" 18 | 19 | [sources] 20 | unknown-registry = "deny" 21 | unknown-git = "deny" 22 | -------------------------------------------------------------------------------- /doc/ecdh.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/doc/ecdh.pdf -------------------------------------------------------------------------------- /doc/ecdsa.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/doc/ecdsa.pdf -------------------------------------------------------------------------------- /include/ring-core/aes.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/include/ring-core/aes.h -------------------------------------------------------------------------------- /include/ring-core/base.h: -------------------------------------------------------------------------------- 1 | // Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef OPENSSL_HEADER_BASE_H 16 | #define OPENSSL_HEADER_BASE_H 17 | 18 | 19 | // This file should be the first included by all BoringSSL headers. 20 | 21 | #if defined(_MSC_VER) && !defined(__clang__) 22 | #pragma warning(push, 3) 23 | #endif 24 | 25 | #include 26 | #include 27 | 28 | #if defined(_MSC_VER) && !defined(__clang__) 29 | #pragma warning(pop) 30 | #endif 31 | 32 | #if defined(__APPLE__) 33 | #include 34 | #endif 35 | 36 | #include // IWYU pragma: export 37 | 38 | #include 39 | 40 | #include 41 | 42 | #if defined(__APPLE__) 43 | // Note |TARGET_OS_MAC| is set for all Apple OS variants. |TARGET_OS_OSX| 44 | // targets macOS specifically. 45 | #if defined(TARGET_OS_OSX) && TARGET_OS_OSX 46 | #define OPENSSL_MACOS 47 | #endif 48 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE 49 | #define OPENSSL_IOS 50 | #endif 51 | #endif 52 | 53 | // *ring* doesn't support the `BORINGSSL_SHARED_LIBRARY` configuration, so 54 | // the default (usually "hidden") visibility is always used, even for exported 55 | // items. 56 | #define OPENSSL_EXPORT 57 | 58 | // `ring::c` would need to be customized on any platform where these assertions 59 | // fail. Keep in sync with `ring::c`. 60 | OPENSSL_STATIC_ASSERT(sizeof(int32_t) == sizeof(int), "int isn't 32 bits."); 61 | OPENSSL_STATIC_ASSERT(sizeof(uint32_t) == sizeof(unsigned int), "unsigned int isn't 32 bits."); 62 | OPENSSL_STATIC_ASSERT(sizeof(size_t) == sizeof(uintptr_t), "uintptr_t and size_t differ."); 63 | OPENSSL_STATIC_ASSERT(sizeof(size_t) <= sizeof(uint64_t), "size_t is larger than uint64_t."); 64 | OPENSSL_STATIC_ASSERT(sizeof(size_t) >= sizeof(uint32_t), "size_t is smaller than uint32_t."); 65 | 66 | #endif // OPENSSL_HEADER_BASE_H 67 | -------------------------------------------------------------------------------- /include/ring-core/check.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #ifndef RING_CHECK_H 16 | #define RING_CHECK_H 17 | 18 | // |debug_assert_nonsecret| is like |assert| and should be used (only) when the 19 | // assertion does not have any potential to leak a secret. |NDEBUG| controls this 20 | // exactly like |assert|. It is emulated when there is no assert.h to make 21 | // cross-building easier. 22 | // 23 | // When reviewing uses of |debug_assert_nonsecret|, verify that the check 24 | // really does not have potential to leak a secret. 25 | 26 | #if !defined(RING_CORE_NOSTDLIBINC) 27 | # include 28 | # define debug_assert_nonsecret(x) assert(x) 29 | #else 30 | # if !defined(NDEBUG) 31 | # define debug_assert_nonsecret(x) ((x) ? ((void)0) : __builtin_trap()) 32 | # else 33 | # define debug_assert_nonsecret(x) ((void)0) 34 | # endif 35 | #endif 36 | 37 | // |dev_assert_secret| is like |assert| and should be used (only) when the 38 | // assertion operates on secret data in a way that has the potential to leak 39 | // the secret. |dev_assert_secret| can only be enabled by changing the |#if 0| 40 | // here to |#if 1| (or equivalent) when |NDEBUG| is not defined. This is not 41 | // controlled only through |NDEBUG| so that such checks do not leak into debug 42 | // builds that may make it into production use. 43 | // 44 | // When reviewing uses of |dev_assert_secret|, verify that the check really 45 | // does have the potential to leak a secret. 46 | #if 0 // DO NOT COMMIT CHANGES TO THIS LINE. 47 | # define dev_assert_secret debug_assert_nonsecret 48 | #else 49 | # define dev_assert_secret(x) ((void)0) 50 | #endif 51 | 52 | #endif // RING_CHECK_H 53 | -------------------------------------------------------------------------------- /include/ring-core/mem.h: -------------------------------------------------------------------------------- 1 | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef OPENSSL_HEADER_MEM_H 16 | #define OPENSSL_HEADER_MEM_H 17 | 18 | #include 19 | 20 | // CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It 21 | // takes an amount of time dependent on |len|, but independent of the contents 22 | // of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a 23 | // defined order as the return value when a != b is undefined, other than to be 24 | // non-zero. 25 | OPENSSL_EXPORT int CRYPTO_memcmp(const void *a, const void *b, size_t len); 26 | 27 | #endif // OPENSSL_HEADER_MEM_H 28 | -------------------------------------------------------------------------------- /include/ring-core/prefix_symbols.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/include/ring-core/prefix_symbols.h -------------------------------------------------------------------------------- /include/ring-core/type_check.h: -------------------------------------------------------------------------------- 1 | // Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // https://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef OPENSSL_HEADER_TYPE_CHECK_H 16 | #define OPENSSL_HEADER_TYPE_CHECK_H 17 | 18 | #include 19 | 20 | 21 | #if defined(__cplusplus) || (defined(_MSC_VER) && !defined(__clang__)) 22 | // In C++ and non-clang MSVC, |static_assert| is a keyword. 23 | #define OPENSSL_STATIC_ASSERT(cond, msg) static_assert(cond, msg) 24 | #else 25 | // C11 defines the |_Static_assert| keyword and the |static_assert| macro in 26 | // assert.h. While the former is available at all versions in Clang and GCC, the 27 | // later depends on libc and, in glibc, depends on being built in C11 mode. We 28 | // do not require this, for now, so use |_Static_assert| directly. 29 | #define OPENSSL_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg) 30 | #endif 31 | 32 | #endif // OPENSSL_HEADER_TYPE_CHECK_H 33 | -------------------------------------------------------------------------------- /mk/check-symbol-prefixes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2021 Brian Smith. 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -eux -o pipefail 18 | IFS=$'\n\t' 19 | 20 | for arg in $*; do 21 | case $arg in 22 | --target=*) 23 | target=${arg#*=} 24 | ;; 25 | +*) 26 | toolchain=${arg#*+} 27 | ;; 28 | *) 29 | ;; 30 | esac 31 | done 32 | 33 | # Keep in sync with cargo.sh. 34 | # Use the host target-libdir, not the target target-libdir. 35 | llvm_root="$(rustc +${toolchain} --print target-libdir)/../bin" 36 | 37 | nm_exe="${llvm_root}/llvm-nm" 38 | 39 | # TODO: This should only look in one target directory. 40 | # TODO: This isn't as strict as it should be. 41 | # 42 | # This assumes that if the prefix starts with "ring_core_" then it is correct. 43 | # It would be better to get the prefix exactly correct. 44 | # 45 | # This is very liberal in filtering out symbols that "look like" 46 | # Rust-compiler-generated symbols. 47 | find target/$target -type f -name libring-*.rlib | while read -r infile; do 48 | bad=$($nm_exe --defined-only --extern-only --print-file-name "$infile" \ 49 | | ( grep -v -E " . _?(__imp__ZN4ring|ring_core_|__rustc|_ZN|DW.ref.rust_eh_personality)" || [[ $? == 1 ]] )) 50 | if [ ! -z "${bad-}" ]; then 51 | echo "$bad" 52 | exit 1 53 | fi 54 | done 55 | -------------------------------------------------------------------------------- /mk/clippy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2021 Brian Smith. 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -eux -o pipefail 18 | IFS=$'\n\t' 19 | 20 | export NULL="" 21 | cargo clippy \ 22 | --all-features --all-targets \ 23 | -- \ 24 | --deny missing_docs \ 25 | --deny unused_qualifications \ 26 | --deny warnings \ 27 | $NULL 28 | -------------------------------------------------------------------------------- /mk/install-build-tools.ps1: -------------------------------------------------------------------------------- 1 | # TODO: Lock this down to a specific commit instead of always using the latest. 2 | git clone ` 3 | --branch windows ` 4 | --depth 1 ` 5 | https://github.com/briansmith/ring-toolchain ` 6 | target/tools/windows 7 | -------------------------------------------------------------------------------- /mk/package.sh: -------------------------------------------------------------------------------- 1 | # This only works on Windows, using MinGW. 2 | set -eux -o pipefail 3 | IFS=$'\n\t' 4 | 5 | # Make sure the current tree isn't dirty. 6 | # https://stackoverflow.com/a/5737794 7 | if [[ -n "$(git status --porcelain)" ]]; then 8 | echo Repository is dirty. 9 | exit 1 10 | fi 11 | 12 | msrv=1.66.0 13 | cargo clean --target-dir=target/pregenerate_asm 14 | RING_PREGENERATE_ASM=1 CC_AARCH64_PC_WINDOWS_MSVC=clang \ 15 | cargo +${msrv} build -p ring --target-dir=target/pregenerate_asm 16 | if [[ -n "$(git status --porcelain -- ':(exclude)pregenerated/')" ]]; then 17 | echo Repository is dirty. 18 | exit 1 19 | fi 20 | cargo +${msrv} package -p ring --allow-dirty 21 | -------------------------------------------------------------------------------- /mk/publish.sh: -------------------------------------------------------------------------------- 1 | set -eux -o pipefail 2 | IFS=$'\n\t' 3 | 4 | # Make sure the current tree isn't dirty other than what's in pregenerated/. 5 | if [[ -n "$(git status --porcelain -- ':(exclude)pregenerated/')" ]]; then 6 | echo Repository is dirty. 7 | exit 1 8 | fi 9 | cargo publish -p ring --allow-dirty 10 | -------------------------------------------------------------------------------- /mk/runner: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eux -o pipefail 3 | IFS=$'\n\t' 4 | 5 | for arg in $*; do 6 | # There can be some arguments prefixed in front of the executable, e.g. 7 | # when qemu-user is used. There can be arguments after the executable, 8 | # e.g. `cargo test` arguments like `TESTNAME`. 9 | if [[ $arg = */deps/* ]]; then 10 | executable=$arg 11 | break 12 | fi 13 | done 14 | 15 | export LLVM_PROFILE_FILE=$(dirname "$RING_BUILD_EXECUTABLE_LIST")/$(basename "$executable").profraw 16 | 17 | if [ -n "$RING_BUILD_EXECUTABLE_LIST" ]; then 18 | echo "$executable" >> "$RING_BUILD_EXECUTABLE_LIST" 19 | fi 20 | 21 | $* 22 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2018" 2 | max_width = 100 3 | newline_style = "Unix" 4 | reorder_imports = true 5 | use_field_init_shorthand = true 6 | -------------------------------------------------------------------------------- /src/aead/aes/bs.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg(all(target_arch = "arm", target_endian = "little"))] 16 | 17 | use super::{Counter, Overlapping, AES_KEY}; 18 | 19 | /// SAFETY: 20 | /// * The caller must ensure that if blocks > 0 then either `input` and 21 | /// `output` do not overlap at all, or input == output.add(n) for some 22 | /// (nonnegative) n. 23 | /// * if blocks > 0, The caller must ensure `input` points to `blocks` blocks 24 | /// and that `output` points to writable space for `blocks` blocks. 25 | /// * The caller must ensure that `vpaes_key` was initialized with 26 | /// `vpaes_set_encrypt_key`. 27 | /// * Upon returning, `blocks` blocks will have been read from `input` and 28 | /// written to `output`. 29 | pub(super) unsafe fn ctr32_encrypt_blocks_with_vpaes_key( 30 | in_out: Overlapping<'_>, 31 | vpaes_key: &AES_KEY, 32 | ctr: &mut Counter, 33 | ) { 34 | prefixed_extern! { 35 | // bsaes_ctr32_encrypt_blocks requires transformation of an existing 36 | // VPAES key; there is no `bsaes_set_encrypt_key`. 37 | fn vpaes_encrypt_key_to_bsaes(bsaes_key: *mut AES_KEY, vpaes_key: &AES_KEY); 38 | } 39 | 40 | // SAFETY: 41 | // * The caller ensures `vpaes_key` was initialized by 42 | // `vpaes_set_encrypt_key`. 43 | // * `bsaes_key was zeroed above, and `vpaes_encrypt_key_to_bsaes` 44 | // is assumed to initialize `bsaes_key`. 45 | let bsaes_key = unsafe { AES_KEY::derive(vpaes_encrypt_key_to_bsaes, vpaes_key) }; 46 | 47 | // The code for `vpaes_encrypt_key_to_bsaes` notes "vpaes stores one 48 | // fewer round count than bsaes, but the number of keys is the same," 49 | // so use this as a sanity check. 50 | debug_assert_eq!(bsaes_key.rounds(), vpaes_key.rounds() + 1); 51 | 52 | // SAFETY: 53 | // * `bsaes_key` is in bsaes format after calling 54 | // `vpaes_encrypt_key_to_bsaes`. 55 | // * `bsaes_ctr32_encrypt_blocks` satisfies the contract for 56 | // `ctr32_encrypt_blocks`. 57 | unsafe { 58 | ctr32_encrypt_blocks!(bsaes_ctr32_encrypt_blocks, in_out, &bsaes_key, ctr); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/aead/aes_tests.txt: -------------------------------------------------------------------------------- 1 | Key = 000102030405060708090a0b0c0d0e0f 2 | Input = 00112233445566778899aabbccddeeff 3 | Output = 69c4e0d86a7b0430d8cdb78070b4c55a 4 | 5 | Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 6 | Input = 00112233445566778899aabbccddeeff 7 | Output = 8ea2b7ca516745bfeafc49904b496089 8 | -------------------------------------------------------------------------------- /src/aead/chacha/ffi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::{super::overlapping::Overlapping, Counter, Key}; 16 | 17 | // `unsafe { (N, C, InOut) => f }` means that the function `f` is safe to call 18 | // iff the in/out length is at least `N`, the CPU features `C` are available, 19 | // and the input type is `InOut`. If `f` supports overlapping input/output then 20 | // `InOut` should be `Overlapping<'_, u8>`; otherwise it should be `&mut [u8]`. 21 | macro_rules! chacha20_ctr32_ffi { 22 | ( unsafe { ($MIN_LEN:expr, $Cpu:ty, $InOut:ty) => $f:ident }, 23 | $key:expr, $counter:expr, $in_out:expr, $cpu:expr ) => {{ 24 | prefixed_extern! { 25 | fn $f( 26 | out: *mut u8, 27 | in_: *const u8, 28 | in_len: crate::c::size_t, 29 | key: &[u32; 8], 30 | counter: &crate::aead::chacha::Counter, 31 | ); 32 | } 33 | // SAFETY: The user asserts that $f has the signature above and is safe 34 | // to call if additionally we have a value of type `$Cpu` and an in/out 35 | // value of the indicated type, which we do. 36 | unsafe { 37 | crate::aead::chacha::ffi::chacha20_ctr32_ffi::<$InOut, $Cpu, $MIN_LEN>( 38 | $key, $counter, $in_out, $cpu, $f, 39 | ) 40 | } 41 | }}; 42 | } 43 | 44 | // Panics if `in_out.len() < MIN_LEN`. The caller should have guarded against 45 | // that so that the assertion gets optimized away. 46 | pub(super) unsafe fn chacha20_ctr32_ffi< 47 | 'o, 48 | InOut: 'o + Into>, 49 | Cpu, 50 | const MIN_LEN: usize, 51 | >( 52 | key: &Key, 53 | counter: Counter, 54 | in_out: InOut, 55 | cpu: Cpu, 56 | f: unsafe extern "C" fn(*mut u8, *const u8, crate::c::size_t, &[u32; 8], &Counter), 57 | ) { 58 | assert!(MIN_LEN > 0); 59 | let in_out: Overlapping<'_, u8> = in_out.into(); 60 | in_out.with_input_output_len(|input, output, len| { 61 | assert!(len >= MIN_LEN); 62 | let key = key.words_less_safe(); 63 | let _: Cpu = cpu; 64 | unsafe { f(output, input, len, key, &counter) } 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /src/aead/gcm/clmulavxmovbe.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg(target_arch = "x86_64")] 16 | 17 | use super::{ffi, HTable, KeyValue, UpdateBlock, UpdateBlocks, Xi, BLOCK_LEN}; 18 | use crate::{c, cpu::intel, polyfill::slice::AsChunks}; 19 | 20 | #[derive(Clone)] 21 | pub struct Key { 22 | h_table: HTable, 23 | } 24 | 25 | impl Key { 26 | #[inline(never)] 27 | pub(in super::super) fn new( 28 | value: KeyValue, 29 | _required_cpu_features: (intel::ClMul, intel::Avx, intel::Movbe), 30 | ) -> Self { 31 | prefixed_extern! { 32 | fn gcm_init_avx(HTable: *mut HTable, h: &KeyValue); 33 | } 34 | Self { 35 | h_table: HTable::new(|table| unsafe { gcm_init_avx(table, &value) }), 36 | } 37 | } 38 | 39 | pub(super) fn inner(&self) -> &HTable { 40 | &self.h_table 41 | } 42 | } 43 | 44 | impl UpdateBlock for Key { 45 | fn update_block(&self, xi: &mut Xi, a: [u8; BLOCK_LEN]) { 46 | self.update_blocks(xi, (&a).into()) 47 | } 48 | } 49 | 50 | impl UpdateBlocks for Key { 51 | fn update_blocks(&self, xi: &mut Xi, input: AsChunks) { 52 | prefixed_extern! { 53 | fn gcm_ghash_avx( 54 | xi: &mut Xi, 55 | Htable: &HTable, 56 | inp: *const u8, 57 | len: c::NonZero_size_t, 58 | ); 59 | } 60 | let htable = self.inner(); 61 | ffi::with_non_dangling_ptr(input, |input, len| unsafe { 62 | gcm_ghash_avx(xi, htable, input, len) 63 | }) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/aead/gcm/neon.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg(any( 16 | all(target_arch = "aarch64", target_endian = "little"), 17 | all(target_arch = "arm", target_endian = "little") 18 | ))] 19 | 20 | use super::{ffi, HTable, KeyValue, UpdateBlock, UpdateBlocks, Xi, BLOCK_LEN}; 21 | use crate::{c, cpu, polyfill::slice::AsChunks}; 22 | 23 | #[derive(Clone)] 24 | pub struct Key { 25 | h_table: HTable, 26 | } 27 | 28 | impl Key { 29 | #[cfg(all(target_arch = "aarch64", target_endian = "little"))] 30 | pub(in super::super) fn new(value: KeyValue, _cpu: cpu::aarch64::Neon) -> Self { 31 | prefixed_extern! { 32 | fn gcm_init_neon(HTable: *mut HTable, h: &KeyValue); 33 | } 34 | Self { 35 | h_table: HTable::new(|table| unsafe { gcm_init_neon(table, &value) }), 36 | } 37 | } 38 | 39 | #[cfg(all(target_arch = "arm", target_endian = "little"))] 40 | pub(in super::super) fn new(value: KeyValue, _cpu: cpu::arm::Neon) -> Self { 41 | prefixed_extern! { 42 | fn gcm_init_neon(HTable: *mut HTable, h: &KeyValue); 43 | } 44 | Self { 45 | h_table: HTable::new(|table| unsafe { gcm_init_neon(table, &value) }), 46 | } 47 | } 48 | } 49 | 50 | impl UpdateBlock for Key { 51 | fn update_block(&self, xi: &mut Xi, a: [u8; BLOCK_LEN]) { 52 | prefixed_extern! { 53 | fn gcm_gmult_neon(xi: &mut Xi, Htable: &HTable); 54 | } 55 | xi.bitxor_assign(a); 56 | unsafe { self.h_table.gmult(gcm_gmult_neon, xi) }; 57 | } 58 | } 59 | 60 | impl UpdateBlocks for Key { 61 | fn update_blocks(&self, xi: &mut Xi, input: AsChunks) { 62 | prefixed_extern! { 63 | fn gcm_ghash_neon( 64 | xi: &mut Xi, 65 | Htable: &HTable, 66 | inp: *const u8, 67 | len: c::NonZero_size_t, 68 | ); 69 | } 70 | let htable = &self.h_table; 71 | ffi::with_non_dangling_ptr(input, |input, len| unsafe { 72 | gcm_ghash_neon(xi, htable, input, len) 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/aead/gcm/vclmulavx2.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg(target_arch = "x86_64")] 16 | 17 | use super::{ 18 | ffi::{self, KeyValue}, 19 | HTable, UpdateBlock, Xi, 20 | }; 21 | use crate::{ 22 | aead::gcm::ffi::BLOCK_LEN, 23 | c, 24 | cpu::intel::{Avx2, VAesClmul}, 25 | polyfill::slice::AsChunks, 26 | }; 27 | 28 | #[derive(Clone)] 29 | pub struct Key { 30 | h_table: HTable, 31 | } 32 | 33 | impl Key { 34 | pub(in super::super) fn new(value: KeyValue, _cpu: (Avx2, VAesClmul)) -> Self { 35 | prefixed_extern! { 36 | fn gcm_init_vpclmulqdq_avx2(HTable: *mut HTable, h: &KeyValue); 37 | } 38 | Self { 39 | h_table: HTable::new(|table| unsafe { gcm_init_vpclmulqdq_avx2(table, &value) }), 40 | } 41 | } 42 | 43 | pub(super) fn inner(&self) -> &HTable { 44 | &self.h_table 45 | } 46 | } 47 | 48 | impl UpdateBlock for Key { 49 | fn update_block(&self, xi: &mut Xi, a: [u8; BLOCK_LEN]) { 50 | prefixed_extern! { 51 | fn gcm_ghash_vpclmulqdq_avx2_16( 52 | xi: &mut Xi, 53 | Htable: &HTable, 54 | inp: *const u8, 55 | len: c::NonZero_size_t, 56 | ); 57 | } 58 | let input: AsChunks = (&a).into(); 59 | let htable = self.inner(); 60 | ffi::with_non_dangling_ptr(input, |input, len| unsafe { 61 | gcm_ghash_vpclmulqdq_avx2_16(xi, htable, input, len) 62 | }) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/aead/nonce.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::error; 16 | 17 | /// A nonce for a single AEAD opening or sealing operation. 18 | /// 19 | /// The user must ensure, for a particular key, that each nonce is unique. 20 | /// 21 | /// `Nonce` intentionally doesn't implement `Clone` to ensure that each one is 22 | /// consumed at most once. 23 | pub struct Nonce([u8; NONCE_LEN]); 24 | 25 | impl Nonce { 26 | /// Constructs a `Nonce` with the given value, assuming that the value is 27 | /// unique for the lifetime of the key it is being used with. 28 | /// 29 | /// Fails if `value` isn't `NONCE_LEN` bytes long. 30 | #[inline] 31 | pub fn try_assume_unique_for_key(value: &[u8]) -> Result { 32 | let value: &[u8; NONCE_LEN] = value.try_into()?; 33 | Ok(Self::assume_unique_for_key(*value)) 34 | } 35 | 36 | /// Constructs a `Nonce` with the given value, assuming that the value is 37 | /// unique for the lifetime of the key it is being used with. 38 | #[inline] 39 | pub fn assume_unique_for_key(value: [u8; NONCE_LEN]) -> Self { 40 | Self(value) 41 | } 42 | } 43 | 44 | impl AsRef<[u8; NONCE_LEN]> for Nonce { 45 | fn as_ref(&self) -> &[u8; NONCE_LEN] { 46 | &self.0 47 | } 48 | } 49 | 50 | /// All the AEADs we support use 96-bit nonces. 51 | pub const NONCE_LEN: usize = 96 / 8; 52 | -------------------------------------------------------------------------------- /src/aead/overlapping/array.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg_attr(not(test), allow(dead_code))] 16 | 17 | use super::Overlapping; 18 | use crate::error::LenMismatchError; 19 | use core::array::TryFromSliceError; 20 | 21 | pub struct Array<'o, T, const N: usize> { 22 | // Invariant: N != 0. 23 | // Invariant: `self.in_out.len() == N`. 24 | in_out: Overlapping<'o, T>, 25 | } 26 | 27 | impl<'o, T, const N: usize> Array<'o, T, N> { 28 | pub(super) fn new(in_out: Overlapping<'o, T>) -> Result { 29 | if N == 0 || in_out.len() != N { 30 | return Err(LenMismatchError::new(N)); 31 | } 32 | Ok(Self { in_out }) 33 | } 34 | 35 | pub fn into_unwritten_output(self) -> &'o mut [T; N] 36 | where 37 | &'o mut [T]: TryInto<&'o mut [T; N], Error = TryFromSliceError>, 38 | { 39 | self.in_out 40 | .into_unwritten_output() 41 | .try_into() 42 | .unwrap_or_else(|TryFromSliceError { .. }| { 43 | unreachable!() // Due to invariant 44 | }) 45 | } 46 | } 47 | 48 | impl Array<'_, T, N> { 49 | pub fn input<'s>(&'s self) -> &'s [T; N] 50 | where 51 | &'s [T]: TryInto<&'s [T; N], Error = TryFromSliceError>, 52 | { 53 | self.in_out 54 | .input() 55 | .try_into() 56 | .unwrap_or_else(|TryFromSliceError { .. }| { 57 | unreachable!() // Due to invariant 58 | }) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/aead/overlapping/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | pub use self::{ 16 | array::Array, 17 | base::{IndexError, Overlapping}, 18 | partial_block::PartialBlock, 19 | }; 20 | 21 | mod array; 22 | mod base; 23 | mod partial_block; 24 | -------------------------------------------------------------------------------- /src/aead/overlapping/partial_block.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::Overlapping; 16 | use crate::error::InputTooLongError; 17 | 18 | pub struct PartialBlock<'i, T, const BLOCK_LEN: usize> { 19 | // invariant: `self.in_out.len() < BLOCK_LEN`. 20 | in_out: Overlapping<'i, T>, 21 | } 22 | 23 | impl<'i, T, const BLOCK_LEN: usize> PartialBlock<'i, T, BLOCK_LEN> { 24 | pub fn new(in_out: Overlapping<'i, T>) -> Result { 25 | let len = in_out.len(); 26 | if len >= BLOCK_LEN { 27 | return Err(InputTooLongError::new(len)); 28 | } 29 | Ok(Self { in_out }) 30 | } 31 | 32 | pub fn overwrite_at_start(self, padded: [T; BLOCK_LEN]) 33 | where 34 | T: Copy, 35 | { 36 | let len = self.len(); 37 | let output = self.in_out.into_unwritten_output(); 38 | assert!(output.len() <= padded.len()); 39 | output.copy_from_slice(&padded[..len]); 40 | } 41 | } 42 | 43 | impl PartialBlock<'_, T, BLOCK_LEN> { 44 | #[inline(always)] 45 | pub fn input(&self) -> &[T] { 46 | let r = self.in_out.input(); 47 | // Help the optimizer optimize the caller using the invariant. 48 | // TODO: Does this actually help? 49 | if r.len() >= BLOCK_LEN { 50 | unreachable!() 51 | } 52 | r 53 | } 54 | 55 | #[inline(always)] 56 | pub fn len(&self) -> usize { 57 | self.input().len() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/aead/unbound_key.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2021 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! Authenticated Encryption with Associated Data (AEAD). 16 | //! 17 | //! See [Authenticated encryption: relations among notions and analysis of the 18 | //! generic composition paradigm][AEAD] for an introduction to the concept of 19 | //! AEADs. 20 | //! 21 | //! [AEAD]: https://eprint.iacr.org/2000/025.pdf 22 | //! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD 23 | 24 | use super::{Algorithm, LessSafeKey, MAX_KEY_LEN}; 25 | use crate::{cpu, error, hkdf}; 26 | 27 | /// An AEAD key without a designated role or nonce sequence. 28 | pub struct UnboundKey { 29 | inner: LessSafeKey, 30 | } 31 | 32 | impl UnboundKey { 33 | /// Constructs a `UnboundKey`. 34 | /// 35 | /// Fails if `key_bytes.len() != algorithm.key_len()`. 36 | #[inline] 37 | pub fn new( 38 | algorithm: &'static Algorithm, 39 | key_bytes: &[u8], 40 | ) -> Result { 41 | Ok(Self { 42 | inner: LessSafeKey::new_(algorithm, key_bytes, cpu::features())?, 43 | }) 44 | } 45 | 46 | /// The key's AEAD algorithm. 47 | #[inline] 48 | pub fn algorithm(&self) -> &'static Algorithm { 49 | self.inner.algorithm() 50 | } 51 | 52 | #[inline] 53 | pub(super) fn into_inner(self) -> LessSafeKey { 54 | self.inner 55 | } 56 | } 57 | 58 | impl core::fmt::Debug for UnboundKey { 59 | fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { 60 | self.inner.fmt_debug("UnboundKey", f) 61 | } 62 | } 63 | 64 | impl From> for UnboundKey { 65 | fn from(okm: hkdf::Okm<&'static Algorithm>) -> Self { 66 | let mut key_bytes = [0; MAX_KEY_LEN]; 67 | let key_bytes = &mut key_bytes[..okm.len().key_len()]; 68 | let algorithm = *okm.len(); 69 | okm.fill(key_bytes).unwrap(); 70 | Self { 71 | inner: LessSafeKey::new_(algorithm, key_bytes, cpu::features()).unwrap(), 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | pub(crate) use self::{constant::limbs_from_hex, limb_slice_error::LimbSliceError}; 16 | use crate::{error::LenMismatchError, limb::LIMB_BITS}; 17 | 18 | #[macro_use] 19 | mod ffi; 20 | 21 | mod constant; 22 | 23 | #[cfg(feature = "alloc")] 24 | pub mod bigint; 25 | 26 | pub(crate) mod inout; 27 | mod limbs; 28 | mod limbs512; 29 | pub mod montgomery; 30 | 31 | mod n0; 32 | 33 | // The minimum number of limbs allowed for any `&[Limb]` operation. 34 | // 35 | // TODO: Use `256 / LIMB_BITS` so that the limit is independent of limb size. 36 | pub const MIN_LIMBS: usize = 4; 37 | 38 | // The maximum number of limbs allowed for any `&[Limb]` operation. 39 | pub const MAX_LIMBS: usize = 8192 / LIMB_BITS; 40 | 41 | cold_exhaustive_error! { 42 | enum limb_slice_error::LimbSliceError { 43 | len_mismatch => LenMismatch(LenMismatchError), 44 | too_short => TooShort(usize), 45 | too_long => TooLong(usize), 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/arithmetic/bigint/boxed_limbs.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::Modulus; 16 | use crate::{ 17 | error, 18 | limb::{self, Limb}, 19 | }; 20 | use alloc::{boxed::Box, vec}; 21 | use core::{ 22 | marker::PhantomData, 23 | ops::{Deref, DerefMut}, 24 | }; 25 | 26 | /// All `BoxedLimbs` are stored in the same number of limbs. 27 | pub(super) struct BoxedLimbs { 28 | limbs: Box<[Limb]>, 29 | 30 | /// The modulus *m* that determines the size of `limbx`. 31 | m: PhantomData, 32 | } 33 | 34 | impl Deref for BoxedLimbs { 35 | type Target = [Limb]; 36 | #[inline] 37 | fn deref(&self) -> &Self::Target { 38 | &self.limbs 39 | } 40 | } 41 | 42 | impl DerefMut for BoxedLimbs { 43 | #[inline] 44 | fn deref_mut(&mut self) -> &mut Self::Target { 45 | &mut self.limbs 46 | } 47 | } 48 | 49 | // TODO: `derive(Clone)` after https://github.com/rust-lang/rust/issues/26925 50 | // is resolved or restrict `M: Clone`. 51 | impl Clone for BoxedLimbs { 52 | fn clone(&self) -> Self { 53 | Self { 54 | limbs: self.limbs.clone(), 55 | m: self.m, 56 | } 57 | } 58 | } 59 | 60 | impl BoxedLimbs { 61 | pub(super) fn from_be_bytes_padded_less_than( 62 | input: untrusted::Input, 63 | m: &Modulus, 64 | ) -> Result { 65 | let mut r = Self::zero(m.limbs().len()); 66 | limb::parse_big_endian_and_pad_consttime(input, &mut r)?; 67 | limb::verify_limbs_less_than_limbs_leak_bit(&r, m.limbs())?; 68 | Ok(r) 69 | } 70 | 71 | pub(super) fn zero(len: usize) -> Self { 72 | Self { 73 | limbs: vec![0; len].into_boxed_slice(), 74 | m: PhantomData, 75 | } 76 | } 77 | 78 | pub(super) fn into_limbs(self) -> Box<[Limb]> { 79 | self.limbs 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/arithmetic/bigint/private_exponent.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::{limb, BoxedLimbs, Limb, Modulus}; 16 | use crate::error; 17 | use alloc::boxed::Box; 18 | 19 | pub struct PrivateExponent { 20 | // Unlike most `[Limb]` we deal with, these are stored most significant 21 | // word first. 22 | limbs: Box<[Limb]>, 23 | } 24 | 25 | impl PrivateExponent { 26 | // `p` is the modulus for which the exponent is in the interval [1, `p` - 1). 27 | pub fn from_be_bytes_padded( 28 | input: untrusted::Input, 29 | p: &Modulus, 30 | ) -> Result { 31 | let mut dP = BoxedLimbs::from_be_bytes_padded_less_than(input, p)?; 32 | 33 | // Proof that `dP < p - 1`: 34 | // 35 | // If `dP < p` then either `dP == p - 1` or `dP < p - 1`. Since `p` is 36 | // odd, `p - 1` is even. `d` is odd, and an odd number modulo an even 37 | // number is odd. Therefore `dP` must be odd. But then it cannot be 38 | // `p - 1` and so we know `dP < p - 1`. 39 | // 40 | // Further we know `dP != 0` because `dP` is not even. 41 | limb::limbs_reject_even_leak_bit(&dP)?; 42 | dP.reverse(); 43 | 44 | Ok(Self { 45 | limbs: dP.into_limbs(), 46 | }) 47 | } 48 | 49 | // Create a `PrivateExponent` with a value that we do not support in 50 | // production use, to allow testing with additional test vectors. 51 | #[cfg(test)] 52 | pub fn from_be_bytes_for_test_only( 53 | input: untrusted::Input, 54 | p: &Modulus, 55 | ) -> Result { 56 | use crate::limb::LIMB_BYTES; 57 | 58 | // Do exactly what `from_be_bytes_padded` does for any inputs it accepts. 59 | if let r @ Ok(_) = Self::from_be_bytes_padded(input, p) { 60 | return r; 61 | } 62 | 63 | let num_limbs = (input.len() + LIMB_BYTES - 1) / LIMB_BYTES; 64 | let mut limbs = BoxedLimbs::::zero(num_limbs); 65 | limb::parse_big_endian_and_pad_consttime(input, &mut limbs) 66 | .map_err(|error::Unspecified| error::KeyRejected::unexpected_error())?; 67 | limbs.reverse(); 68 | Ok(Self { 69 | limbs: limbs.into_limbs(), 70 | }) 71 | } 72 | 73 | #[inline] 74 | pub(super) fn limbs(&self) -> &[Limb] { 75 | &self.limbs 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/arithmetic/bigint_elem_exp_vartime_tests.txt: -------------------------------------------------------------------------------- 1 | # ModExp tests. 2 | # 3 | # These test vectors satisfy A ^ E = ModExp (mod M) and 0 <= ModExp < M. 4 | # Additionally, These test vectors satisfy the following constraints: 5 | # 6 | # * 0 <= A < M. 7 | # * E is odd, and the number of bits in E is in [2, 33]. 8 | # * M requires at least 4 (64-bit) words to represent. 9 | # 10 | # XXX: Unfortunately, the above criteria exclude all BoringSSL test vectors; 11 | # i.e. none of the BoringSSL test vectors were suitable for testing the 12 | # variable-time exponentiation used in RSA verification in *ring*. TODO: Make 13 | # new test vectors. 14 | -------------------------------------------------------------------------------- /src/arithmetic/constant.rs: -------------------------------------------------------------------------------- 1 | use crate::limb::LeakyLimb; 2 | use core::mem::size_of; 3 | 4 | const fn parse_digit(d: u8) -> u8 { 5 | match d.to_ascii_lowercase() { 6 | b'0'..=b'9' => d - b'0', 7 | b'a'..=b'f' => d - b'a' + 10, 8 | _ => panic!(), 9 | } 10 | } 11 | 12 | // TODO: this would be nicer as a trait, but currently traits don't support const functions 13 | pub const fn limbs_from_hex(hex: &str) -> [LeakyLimb; LIMBS] { 14 | let hex = hex.as_bytes(); 15 | let mut limbs = [0; LIMBS]; 16 | let limb_nibbles = size_of::() * 2; 17 | let mut i = 0; 18 | 19 | while i < hex.len() { 20 | let char = hex[hex.len() - 1 - i]; 21 | let val = parse_digit(char); 22 | limbs[i / limb_nibbles] |= (val as LeakyLimb) << ((i % limb_nibbles) * 4); 23 | i += 1; 24 | } 25 | 26 | limbs 27 | } 28 | -------------------------------------------------------------------------------- /src/arithmetic/limbs/aarch64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg(all(target_arch = "aarch64", target_endian = "little"))] 16 | 17 | pub(in super::super) use self::mont::{mul_mont, sqr_mont5}; 18 | 19 | mod mont; 20 | -------------------------------------------------------------------------------- /src/arithmetic/limbs/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | pub(super) mod aarch64; 16 | pub(super) mod x86_64; 17 | -------------------------------------------------------------------------------- /src/arithmetic/limbs/x86_64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![cfg(target_arch = "x86_64")] 16 | 17 | pub(in super::super::super) mod mont; 18 | -------------------------------------------------------------------------------- /src/arithmetic/limbs512/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | mod storage; 16 | 17 | pub(super) use self::storage::{AlignedStorage, LIMBS_PER_CHUNK}; 18 | -------------------------------------------------------------------------------- /src/arithmetic/limbs512/storage.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::{ 16 | error::LenMismatchError, 17 | limb::{Limb, LIMB_BITS}, 18 | polyfill::slice::{self, AsChunksMut}, 19 | }; 20 | use core::mem::{align_of, size_of}; 21 | 22 | // Some x86_64 assembly is written under the assumption that some of its 23 | // input data and/or temporary storage is aligned to `MOD_EXP_CTIME_ALIGN` 24 | // bytes, which was/is 64 in OpenSSL. 25 | // 26 | // We use this in the non-X86-64 implementation of exponentiation as well, 27 | // with the hope of converging th two implementations into one. 28 | 29 | #[repr(C, align(64))] 30 | pub struct AlignedStorage([Limb; N]); 31 | 32 | const _LIMB_SIZE_DIVIDES_ALIGNMENT: () = 33 | assert!(align_of::>() % size_of::() == 0); 34 | 35 | pub const LIMBS_PER_CHUNK: usize = 512 / LIMB_BITS; 36 | 37 | impl AlignedStorage { 38 | pub fn zeroed() -> Self { 39 | assert_eq!(N % LIMBS_PER_CHUNK, 0); // TODO: const. 40 | Self([0; N]) 41 | } 42 | 43 | // The result will have every chunk aligned on a 64 byte boundary. 44 | pub fn aligned_chunks_mut( 45 | &mut self, 46 | num_entries: usize, 47 | chunks_per_entry: usize, 48 | ) -> Result, LenMismatchError> { 49 | let total_limbs = num_entries * chunks_per_entry * LIMBS_PER_CHUNK; 50 | let len = self.0.len(); 51 | let flattened = self 52 | .0 53 | .get_mut(..total_limbs) 54 | .ok_or_else(|| LenMismatchError::new(len))?; 55 | match slice::as_chunks_mut(flattened) { 56 | (chunks, []) => Ok(chunks), 57 | (_, r) => Err(LenMismatchError::new(r.len())), 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/arithmetic/n0.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2022 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::limb::Limb; 16 | 17 | #[derive(Clone, Copy)] 18 | #[repr(transparent)] 19 | pub struct N0([Limb; 2]); 20 | 21 | impl N0 { 22 | #[cfg(feature = "alloc")] 23 | pub(super) const LIMBS_USED: usize = 64 / crate::limb::LIMB_BITS; 24 | 25 | #[inline] 26 | pub const fn precalculated(n0: u64) -> Self { 27 | #[cfg(target_pointer_width = "64")] 28 | { 29 | Self([n0, 0]) 30 | } 31 | 32 | #[cfg(target_pointer_width = "32")] 33 | { 34 | Self([n0 as Limb, (n0 >> crate::limb::LIMB_BITS) as Limb]) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/bb/boolmask.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::Word; 16 | use core::ops; 17 | 18 | // BoolMask is either `BoolMask::TRUE` or `BoolMask::FALSE`. 19 | #[repr(transparent)] 20 | pub struct BoolMask(Word); 21 | 22 | impl BoolMask { 23 | #[cfg(test)] 24 | pub(super) const TRUE: Self = Self(Word::MAX); 25 | #[cfg(test)] 26 | pub(super) const FALSE: Self = Self(0); 27 | 28 | /// Returns true if `self` is `BoolMask::TRUE`; otherwise, returns false 29 | /// (`self` is `BoolMask::FALSE`). 30 | pub(crate) fn leak(self) -> bool { 31 | self.0 != 0 32 | } 33 | } 34 | 35 | impl ops::BitAnd for BoolMask { 36 | type Output = Self; 37 | 38 | fn bitand(self, rhs: Self) -> Self { 39 | Self(self.0 & rhs.0) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/bb/leaky.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #[cfg(target_pointer_width = "64")] 16 | type CompilerWord = u64; 17 | 18 | #[cfg(target_pointer_width = "32")] 19 | type CompilerWord = u32; 20 | 21 | /// A native word that isn't secret. 22 | /// 23 | /// `LeakyWord` supports `as` conversions to/from native types. 24 | /// 25 | /// XXX: This isn't the native word size on targets where a pointer isn't the 26 | /// same size as a native word. TODO: Fix this. 27 | pub(crate) type LeakyWord = CompilerWord; 28 | -------------------------------------------------------------------------------- /src/bb/word.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::LeakyWord; 16 | 17 | /// A native word that may hold a secret. 18 | /// 19 | /// XXX: Currently this is a type alias of `LeakyWord` so it doesn't enforce, 20 | /// except by convention, the prevention of leaks. This is a temporary state to 21 | /// support the refactorings that will 22 | /// 23 | /// XXX: This isn't the native word size on targets where a pointer isn't the 24 | /// same size as a native word. TODO: Fix this. 25 | /// 26 | /// XXX: Over time, we'll evolve Word into a newtype with an API that minimizes 27 | /// leaks and makes all leaks explicit, like so: 28 | pub(crate) type Word = LeakyWord; 29 | 30 | /* TODO: 31 | #[repr(transparent)] 32 | pub(crate) struct Word(LeakyWord); 33 | 34 | impl Word { 35 | pub fn leak_word(self) -> LeakyWord { self.0 } 36 | } 37 | 38 | impl From for Word { 39 | fn from(w: LeakyWord) -> Self { 40 | // TODO: Use a stronger `black_box`. 41 | Self(core::hint::black_box(w)) 42 | } 43 | } 44 | */ 45 | -------------------------------------------------------------------------------- /src/bssl.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::error; 16 | use core::ffi::c_int; 17 | 18 | /// An `int` returned from a foreign function containing **1** if the function 19 | /// was successful or **0** if an error occurred. This is the convention used by 20 | /// C code in `ring`. 21 | #[must_use] 22 | #[repr(transparent)] 23 | pub struct Result(c_int); 24 | 25 | impl From for core::result::Result<(), error::Unspecified> { 26 | fn from(ret: Result) -> Self { 27 | match ret.0 { 28 | 1 => Ok(()), 29 | c => { 30 | debug_assert_eq!(c, 0, "`bssl::Result` value must be 0 or 1"); 31 | Err(error::Unspecified) 32 | } 33 | } 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | mod result { 40 | use crate::bssl; 41 | use core::{ 42 | ffi::c_int, 43 | mem::{align_of, size_of}, 44 | }; 45 | 46 | #[test] 47 | fn size_and_alignment() { 48 | type Underlying = c_int; 49 | assert_eq!(size_of::(), size_of::()); 50 | assert_eq!(align_of::(), align_of::()); 51 | } 52 | 53 | #[test] 54 | fn semantics() { 55 | assert!(Result::from(bssl::Result(0)).is_err()); 56 | assert!(Result::from(bssl::Result(1)).is_ok()); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/c.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! C types. 16 | //! 17 | //! Avoid using the `libc` crate to get C types since `libc` doesn't support 18 | //! all the targets we need to support. It turns out that the few types we need 19 | //! are all uniformly defined on the platforms we care about. This will 20 | //! probably change if/when we support 16-bit platforms or platforms where 21 | //! `usize` and `uintptr_t` are different sizes. 22 | //! 23 | //! TODO(MSRV, feature(c_size_t)): Use `core::{ffi::c_size_t}`. 24 | //! TODO(MSRV-1.79): Use `NonZero`. 25 | 26 | // Keep in sync with the checks in base.h that verify these assumptions. 27 | 28 | #![allow(dead_code)] 29 | 30 | use core::num::NonZeroUsize; 31 | 32 | pub(crate) type size_t = usize; 33 | pub(crate) type NonZero_size_t = NonZeroUsize; 34 | -------------------------------------------------------------------------------- /src/cpu/aarch64/fuchsia.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::{Aes, Neon, PMull, Sha256, Sha512, CAPS_STATIC}; 16 | 17 | pub const FORCE_DYNAMIC_DETECTION: u32 = 0; 18 | 19 | pub fn detect_features() -> u32 { 20 | type zx_status_t = i32; 21 | 22 | #[link(name = "zircon")] 23 | extern "C" { 24 | fn zx_system_get_features(kind: u32, features: *mut u32) -> zx_status_t; 25 | } 26 | 27 | const ZX_OK: i32 = 0; 28 | const ZX_FEATURE_KIND_CPU: u32 = 0; 29 | const ZX_ARM64_FEATURE_ISA_AES: u32 = 1 << 3; 30 | const ZX_ARM64_FEATURE_ISA_PMULL: u32 = 1 << 4; 31 | const ZX_ARM64_FEATURE_ISA_SHA256: u32 = 1 << 6; 32 | const ZX_ARM64_FEATURE_ISA_SHA512: u32 = 1 << 18; 33 | 34 | let mut caps = 0; 35 | let rc = unsafe { zx_system_get_features(ZX_FEATURE_KIND_CPU, &mut caps) }; 36 | 37 | let mut features = 0; 38 | 39 | // We do not need to check for the presence of NEON, as Armv8-A always has it 40 | const _ASSERT_NEON_DETECTED: () = assert!((CAPS_STATIC & Neon::mask()) == Neon::mask()); 41 | 42 | if rc == ZX_OK { 43 | if caps & ZX_ARM64_FEATURE_ISA_AES == ZX_ARM64_FEATURE_ISA_AES { 44 | features |= Aes::mask(); 45 | } 46 | if caps & ZX_ARM64_FEATURE_ISA_PMULL == ZX_ARM64_FEATURE_ISA_PMULL { 47 | features |= PMull::mask(); 48 | } 49 | if caps & ZX_ARM64_FEATURE_ISA_SHA256 == ZX_ARM64_FEATURE_ISA_SHA256 { 50 | features |= Sha256::mask(); 51 | } 52 | if caps & ZX_ARM64_FEATURE_ISA_SHA512 == ZX_ARM64_FEATURE_ISA_SHA512 { 53 | features |= Sha512::mask(); 54 | } 55 | } 56 | 57 | features 58 | } 59 | -------------------------------------------------------------------------------- /src/cpu/aarch64/linux.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::Neon; 16 | 17 | // Work around a bug in LLVM/rustc where `-C target_cpu=cortex-a72`-- 18 | // and `-C target_cpu=native` on Cortex-A72 Raspberry PI devices in 19 | // particular--enables crypto features even though not all Cortex-A72 20 | // CPUs have crypto features: 21 | // 22 | // ``` 23 | // $ rustc --print cfg --target=aarch64-unknown-linux-gnu | grep feature 24 | // target_feature="neon" 25 | // $ rustc --print cfg --target=aarch64-unknown-linux-gnu -C target_cpu=cortex-a72 | grep feature 26 | // target_feature="aes" 27 | // target_feature="crc" 28 | // target_feature="neon" 29 | // target_feature="pmuv3" 30 | // target_feature="sha2" 31 | // ``` 32 | // 33 | // XXX/TODO(MSRV https://github.com/llvm/llvm-project/issues/90365): This 34 | // workaround is heavy-handed since it forces extra branches for devices that 35 | // have correctly-modeled feature sets, so it should be removed. 36 | pub const FORCE_DYNAMIC_DETECTION: u32 = !Neon::mask(); 37 | 38 | pub fn detect_features() -> u32 { 39 | use super::{Aes, PMull, Sha256, Sha512, CAPS_STATIC}; 40 | use libc::{getauxval, AT_HWCAP, HWCAP_AES, HWCAP_PMULL, HWCAP_SHA2, HWCAP_SHA512}; 41 | 42 | let mut features = 0; 43 | 44 | // We do not need to check for the presence of NEON, as Armv8-A always has it 45 | const _ASSERT_NEON_DETECTED: () = assert!((CAPS_STATIC & Neon::mask()) == Neon::mask()); 46 | 47 | let caps = unsafe { getauxval(AT_HWCAP) }; 48 | 49 | if caps & HWCAP_AES == HWCAP_AES { 50 | features |= Aes::mask(); 51 | } 52 | if caps & HWCAP_PMULL == HWCAP_PMULL { 53 | features |= PMull::mask(); 54 | } 55 | if caps & HWCAP_SHA2 == HWCAP_SHA2 { 56 | features |= Sha256::mask(); 57 | } 58 | if caps & HWCAP_SHA512 == HWCAP_SHA512 { 59 | features |= Sha512::mask(); 60 | } 61 | 62 | features 63 | } 64 | -------------------------------------------------------------------------------- /src/cpu/aarch64/windows.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::{Aes, Neon, PMull, Sha256, CAPS_STATIC}; 16 | use windows_sys::Win32::System::Threading::{ 17 | IsProcessorFeaturePresent, PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE, 18 | }; 19 | 20 | pub const FORCE_DYNAMIC_DETECTION: u32 = 0; 21 | 22 | pub fn detect_features() -> u32 { 23 | // We do not need to check for the presence of NEON, as Armv8-A always has it 24 | const _ASSERT_NEON_DETECTED: () = assert!((CAPS_STATIC & Neon::mask()) == Neon::mask()); 25 | 26 | let mut features = 0; 27 | 28 | let result = unsafe { IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) }; 29 | 30 | if result != 0 { 31 | // These are all covered by one call in Windows 32 | features |= Aes::mask(); 33 | features |= PMull::mask(); 34 | features |= Sha256::mask(); 35 | } 36 | 37 | features 38 | } 39 | -------------------------------------------------------------------------------- /src/cpu/arm/linux.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::Neon; 16 | 17 | // Work around a bug in LLVM/rustc where `-C target_cpu=cortex-a72`-- 18 | // and `-C target_cpu=native` on Cortex-A72 Raspberry PI devices in 19 | // particular--enables crypto features even though not all Cortex-A72 20 | // CPUs have crypto features: 21 | // 22 | // ``` 23 | // $ rustc --print cfg --target=aarch64-unknown-linux-gnu | grep feature 24 | // target_feature="neon" 25 | // $ rustc --print cfg --target=aarch64-unknown-linux-gnu -C target_cpu=cortex-a72 | grep feature 26 | // target_feature="aes" 27 | // target_feature="crc" 28 | // target_feature="neon" 29 | // target_feature="pmuv3" 30 | // target_feature="sha2" 31 | // ``` 32 | // 33 | // XXX/TODO(MSRV https://github.com/llvm/llvm-project/issues/90365): This 34 | // workaround is heavy-handed since it forces extra branches for devices that 35 | // have correctly-modeled feature sets, so it should be removed. 36 | pub const FORCE_DYNAMIC_DETECTION: u32 = !Neon::mask(); 37 | 38 | pub fn detect_features() -> u32 { 39 | let mut features = 0; 40 | 41 | // When linked statically, uclibc doesn't provide getauxval. When linked 42 | // dynamically, recent versions do provide it, but we want to support older 43 | // versions too. Assume that if uclibc is being used, this is an embedded 44 | // target where the user cares a lot about minimizing code size and also 45 | // that they know in advance exactly what target features are supported, so 46 | // rely only on static feature detection. 47 | #[cfg(not(target_env = "uclibc"))] 48 | { 49 | use super::CAPS_STATIC; 50 | use libc::{c_ulong, getauxval, AT_HWCAP}; 51 | 52 | const HWCAP_NEON: c_ulong = 1 << 12; 53 | 54 | if CAPS_STATIC & Neon::mask() != Neon::mask() { 55 | let caps = unsafe { getauxval(AT_HWCAP) }; 56 | 57 | // OpenSSL and BoringSSL don't enable any other features if NEON isn't 58 | // available. We don't enable any hardware implementations for 32-bit ARM. 59 | if caps & HWCAP_NEON == HWCAP_NEON { 60 | features |= Neon::mask(); 61 | } 62 | } 63 | } 64 | 65 | features 66 | } 67 | -------------------------------------------------------------------------------- /src/data/alg-rsa-encryption.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/src/data/alg-rsa-encryption.der -------------------------------------------------------------------------------- /src/deprecated_constant_time.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::{bb, error}; 16 | 17 | #[deprecated( 18 | note = "To be removed. Internal function not intended for external use with no promises regarding side channels." 19 | )] 20 | pub fn verify_slices_are_equal(a: &[u8], b: &[u8]) -> Result<(), error::Unspecified> { 21 | bb::verify_slices_are_equal(a, b) 22 | } 23 | -------------------------------------------------------------------------------- /src/deprecated_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![doc(hidden)] 16 | 17 | /// References a test input file. 18 | #[macro_export] 19 | macro_rules! test_file { 20 | ($file_name:expr) => { 21 | $crate::test::File { 22 | file_name: $file_name, 23 | contents: include_str!($file_name), 24 | } 25 | }; 26 | } 27 | 28 | pub use crate::testutil::{ 29 | compile_time_assert_clone, compile_time_assert_copy, compile_time_assert_eq, 30 | compile_time_assert_send, compile_time_assert_sync, from_hex, run, File, TestCase, 31 | }; 32 | 33 | #[cfg(feature = "std")] 34 | pub use crate::testutil::compile_time_assert_std_error_error; 35 | 36 | #[deprecated(note = "internal API that will be removed")] 37 | #[doc(hidden)] 38 | pub mod rand { 39 | #[deprecated(note = "internal API that will be removed")] 40 | pub type FixedByteRandom = crate::testutil::rand::FixedByteRandom; 41 | #[deprecated(note = "internal API that will be removed")] 42 | pub type FixedSliceRandom<'a> = crate::testutil::rand::FixedSliceRandom<'a>; 43 | #[deprecated(note = "internal API that will be removed")] 44 | pub type FixedSliceSequenceRandom<'a> = crate::testutil::rand::FixedSliceSequenceRandom<'a>; 45 | } 46 | -------------------------------------------------------------------------------- /src/digest/sha2/ffi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::CHAINING_WORDS; 16 | use crate::polyfill::slice::AsChunks; 17 | use core::num::{NonZeroUsize, Wrapping}; 18 | 19 | /// `unsafe { T => f }` means it is safe to call `f` iff we can construct 20 | /// a value of type `T`. 21 | macro_rules! sha2_ffi { 22 | ( $U:ty, $BLOCK_LEN:expr, unsafe { $Cpu:ty => $f:ident }, 23 | $state:expr, $data:expr, $cpu:expr $(,)? ) => {{ 24 | prefixed_extern! { 25 | fn $f( 26 | state: *mut [core::num::Wrapping<$U>; crate::digest::sha2::CHAINING_WORDS], 27 | data: *const [u8; $BLOCK_LEN], 28 | num: crate::c::NonZero_size_t); 29 | } 30 | // SAFETY: The user asserts that $f has the signature above and is safe 31 | // to call if additionally we have a value of type `$Cpu`, which we do. 32 | unsafe { 33 | crate::digest::sha2::ffi::sha2_ffi::<$U, $Cpu, { $BLOCK_LEN }>($state, $data, $cpu, $f) 34 | } 35 | }}; 36 | } 37 | 38 | macro_rules! sha2_32_ffi { 39 | ( unsafe { $Cpu:ty => $f:ident }, $state:expr, $data:expr, $cpu:expr $(,)? ) => { 40 | sha2_ffi!(u32, crate::digest::sha2::SHA256_BLOCK_LEN.into(), 41 | unsafe { $Cpu => $f }, $state, $data, $cpu) 42 | } 43 | } 44 | 45 | macro_rules! sha2_64_ffi { 46 | ( unsafe { $Cpu:ty => $f:ident }, $state:expr, $data:expr, $cpu:expr $(,)? ) => { 47 | sha2_ffi!(u64, SHA512_BLOCK_LEN.into(), unsafe { $Cpu => $f }, $state, $data, $cpu) 48 | } 49 | } 50 | 51 | pub(super) unsafe fn sha2_ffi( 52 | state: &mut [Wrapping; CHAINING_WORDS], 53 | data: AsChunks, 54 | cpu: Cpu, 55 | f: unsafe extern "C" fn( 56 | *mut [Wrapping; CHAINING_WORDS], 57 | *const [u8; BLOCK_LEN], 58 | crate::c::NonZero_size_t, 59 | ), 60 | ) { 61 | if let Some(blocks) = NonZeroUsize::new(data.len()) { 62 | let data = data.as_ptr(); 63 | let _: Cpu = cpu; 64 | // SAFETY: 65 | // * `blocks` is non-zero. 66 | // * `data` is non-NULL and points to `blocks` blocks. 67 | // * The caller asserted that `f` meets this contract if we have 68 | // an instance of `Cpu`. 69 | unsafe { f(state, data, blocks) } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/digest/sha2/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::BlockLen; 16 | 17 | pub(super) use self::{ 18 | sha2_32::{block_data_order_32, State32, SHA256_BLOCK_LEN}, 19 | sha2_64::{block_data_order_64, State64, SHA512_BLOCK_LEN}, 20 | }; 21 | 22 | pub(super) const CHAINING_WORDS: usize = 8; 23 | 24 | #[cfg(any( 25 | all(target_arch = "aarch64", target_endian = "little"), 26 | all(target_arch = "arm", target_endian = "little"), 27 | target_arch = "x86_64" 28 | ))] 29 | #[macro_use] 30 | mod ffi; 31 | 32 | pub(super) mod fallback; 33 | mod sha2_32; 34 | mod sha2_64; 35 | -------------------------------------------------------------------------------- /src/digest/sha2/sha2_64.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::{BlockLen, CHAINING_WORDS}; 16 | use crate::{cpu, polyfill::slice::AsChunks}; 17 | use cfg_if::cfg_if; 18 | use core::num::Wrapping; 19 | 20 | pub(in super::super) const SHA512_BLOCK_LEN: BlockLen = BlockLen::_1024; 21 | 22 | pub type State64 = [Wrapping; CHAINING_WORDS]; 23 | 24 | pub(crate) fn block_data_order_64( 25 | state: &mut State64, 26 | data: AsChunks, 27 | cpu: cpu::Features, 28 | ) { 29 | cfg_if! { 30 | if #[cfg(all(target_arch = "aarch64", target_endian = "little"))] { 31 | use cpu::{GetFeature as _, aarch64::Sha512}; 32 | if let Some(cpu) = cpu.get_feature() { 33 | sha2_64_ffi!(unsafe { Sha512 => sha512_block_data_order_hw }, state, data, cpu) 34 | } else { 35 | sha2_64_ffi!(unsafe { () => sha512_block_data_order_nohw }, state, data, ()) 36 | } 37 | } else if #[cfg(all(target_arch = "arm", target_endian = "little"))] { 38 | use cpu::{GetFeature as _, arm::Neon}; 39 | if let Some(cpu) = cpu.get_feature() { 40 | sha2_64_ffi!(unsafe { Neon => sha512_block_data_order_neon }, state, data, cpu) 41 | } else { 42 | sha2_64_ffi!(unsafe { () => sha512_block_data_order_nohw }, state, data, ()) 43 | } 44 | } else if #[cfg(target_arch = "x86_64")] { 45 | use cpu::{GetFeature as _, intel::{Avx, IntelCpu}}; 46 | if let Some(cpu) = cpu.get_feature() { 47 | // Pre-Zen AMD CPUs had microcoded SHLD/SHRD which makes the 48 | // AVX version slow. We're also unsure of the side channel 49 | // ramifications of those microcoded instructions. 50 | sha2_64_ffi!(unsafe { (Avx, IntelCpu) => sha512_block_data_order_avx }, 51 | state, data, cpu); 52 | } else { 53 | sha2_64_ffi!(unsafe { () => sha512_block_data_order_nohw }, state, data, ()) 54 | } 55 | } else { 56 | let _ = cpu; // Unneeded. 57 | *state = super::fallback::block_data_order(*state, data) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ec.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::{cpu, error, rand}; 16 | 17 | pub use self::keys::{KeyPair, PublicKey, Seed}; 18 | 19 | pub struct Curve { 20 | pub public_key_len: usize, 21 | pub elem_scalar_seed_len: usize, 22 | 23 | pub id: CurveID, 24 | 25 | // Precondition: `bytes` is the correct length. 26 | check_private_key_bytes: fn(bytes: &[u8], cpu: cpu::Features) -> Result<(), error::Unspecified>, 27 | 28 | generate_private_key: fn( 29 | rng: &dyn rand::SecureRandom, 30 | &mut [u8], 31 | cpu: cpu::Features, 32 | ) -> Result<(), error::Unspecified>, 33 | 34 | public_from_private: fn( 35 | public_out: &mut [u8], 36 | private_key: &Seed, 37 | cpu: cpu::Features, 38 | ) -> Result<(), error::Unspecified>, 39 | } 40 | 41 | derive_debug_via_id!(Curve); 42 | 43 | #[derive(Clone, Copy, Debug, PartialEq)] 44 | pub enum CurveID { 45 | Curve25519, 46 | P256, 47 | P384, 48 | } 49 | 50 | const ELEM_MAX_BITS: usize = 384; 51 | pub const ELEM_MAX_BYTES: usize = (ELEM_MAX_BITS + 7) / 8; 52 | 53 | pub const SCALAR_MAX_BYTES: usize = ELEM_MAX_BYTES; 54 | const SEED_MAX_BYTES: usize = ELEM_MAX_BYTES; 55 | 56 | /// The maximum length of a PKCS#8 documents generated by *ring* for ECC keys. 57 | /// 58 | /// This is NOT the maximum length of a PKCS#8 document that can be consumed by 59 | /// `pkcs8::unwrap_key()`. 60 | /// 61 | /// `40` is the length of the P-384 template. It is actually one byte shorter 62 | /// than the P-256 template, but the private key and the public key are much 63 | /// longer. 64 | pub const PKCS8_DOCUMENT_MAX_LEN: usize = 40 + SCALAR_MAX_BYTES + keys::PUBLIC_KEY_MAX_LEN; 65 | 66 | pub mod curve25519; 67 | mod keys; 68 | pub mod suite_b; 69 | -------------------------------------------------------------------------------- /src/ec/curve25519.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! Elliptic curve operations and schemes using Curve25519. 16 | 17 | pub mod ed25519; 18 | 19 | pub mod x25519; 20 | 21 | mod ops; 22 | mod scalar; 23 | -------------------------------------------------------------------------------- /src/ec/curve25519/ed25519.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! EdDSA Signatures. 16 | 17 | use super::ops::ELEM_LEN; 18 | use crate::digest; 19 | 20 | pub mod signing; 21 | pub mod verification; 22 | 23 | /// The length of an Ed25519 public key. 24 | pub const ED25519_PUBLIC_KEY_LEN: usize = ELEM_LEN; 25 | 26 | pub fn eddsa_digest(signature_r: &[u8], public_key: &[u8], msg: &[u8]) -> digest::Digest { 27 | let mut ctx = digest::Context::new(&digest::SHA512); 28 | ctx.update(signature_r); 29 | ctx.update(public_key); 30 | ctx.update(msg); 31 | ctx.finish() 32 | } 33 | -------------------------------------------------------------------------------- /src/ec/curve25519/ed25519/ed25519_pkcs8_v2_template.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/src/ec/curve25519/ed25519/ed25519_pkcs8_v2_template.der -------------------------------------------------------------------------------- /src/ec/curve25519/scalar.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::{ 16 | arithmetic::limbs_from_hex, 17 | digest, error, limb, 18 | polyfill::slice::{self, AsChunks}, 19 | }; 20 | use core::array; 21 | 22 | #[repr(transparent)] 23 | pub struct Scalar([u8; SCALAR_LEN]); 24 | 25 | pub const SCALAR_LEN: usize = 32; 26 | 27 | impl Scalar { 28 | // Constructs a `Scalar` from `bytes`, failing if `bytes` encodes a scalar 29 | // that is not in the range [0, n). 30 | pub fn from_bytes_checked(bytes: [u8; SCALAR_LEN]) -> Result { 31 | const ORDER: [limb::Limb; SCALAR_LEN / limb::LIMB_BYTES] = 32 | limbs_from_hex("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"); 33 | let order = ORDER.map(limb::Limb::from); 34 | 35 | let (limbs_as_bytes, _empty): (AsChunks, _) = 36 | slice::as_chunks(&bytes); 37 | debug_assert!(_empty.is_empty()); 38 | let limbs: [limb::Limb; SCALAR_LEN / limb::LIMB_BYTES] = 39 | array::from_fn(|i| limb::Limb::from_le_bytes(limbs_as_bytes[i])); 40 | limb::verify_limbs_less_than_limbs_leak_bit(&limbs, &order)?; 41 | 42 | Ok(Self(bytes)) 43 | } 44 | 45 | // Constructs a `Scalar` from `digest` reduced modulo n. 46 | pub fn from_sha512_digest_reduced(digest: digest::Digest) -> Self { 47 | prefixed_extern! { 48 | fn x25519_sc_reduce(s: &mut UnreducedScalar); 49 | } 50 | let mut unreduced = [0u8; digest::SHA512_OUTPUT_LEN]; 51 | unreduced.copy_from_slice(digest.as_ref()); 52 | unsafe { x25519_sc_reduce(&mut unreduced) }; 53 | Self((&unreduced[..SCALAR_LEN]).try_into().unwrap()) 54 | } 55 | } 56 | 57 | #[repr(transparent)] 58 | pub struct MaskedScalar([u8; SCALAR_LEN]); 59 | 60 | impl MaskedScalar { 61 | pub fn from_bytes_masked(bytes: [u8; SCALAR_LEN]) -> Self { 62 | prefixed_extern! { 63 | fn x25519_sc_mask(a: &mut [u8; SCALAR_LEN]); 64 | } 65 | let mut r = Self(bytes); 66 | unsafe { x25519_sc_mask(&mut r.0) }; 67 | r 68 | } 69 | } 70 | 71 | impl From for Scalar { 72 | fn from(MaskedScalar(scalar): MaskedScalar) -> Self { 73 | Self(scalar) 74 | } 75 | } 76 | 77 | type UnreducedScalar = [u8; UNREDUCED_SCALAR_LEN]; 78 | const UNREDUCED_SCALAR_LEN: usize = SCALAR_LEN * 2; 79 | -------------------------------------------------------------------------------- /src/ec/keys.rs: -------------------------------------------------------------------------------- 1 | use super::{Curve, ELEM_MAX_BYTES, SEED_MAX_BYTES}; 2 | use crate::{cpu, error, rand}; 3 | 4 | pub struct KeyPair { 5 | seed: Seed, 6 | public_key: PublicKey, 7 | } 8 | 9 | impl KeyPair { 10 | pub(super) fn derive( 11 | seed: Seed, 12 | cpu_features: cpu::Features, 13 | ) -> Result { 14 | let public_key = seed.compute_public_key(cpu_features)?; 15 | Ok(Self { seed, public_key }) 16 | } 17 | 18 | pub fn public_key(&self) -> &PublicKey { 19 | &self.public_key 20 | } 21 | pub fn split(self) -> (Seed, PublicKey) { 22 | (self.seed, self.public_key) 23 | } 24 | } 25 | 26 | pub struct Seed { 27 | bytes: [u8; SEED_MAX_BYTES], 28 | curve: &'static Curve, 29 | } 30 | 31 | impl Seed { 32 | pub(crate) fn generate( 33 | curve: &'static Curve, 34 | rng: &dyn rand::SecureRandom, 35 | cpu: cpu::Features, 36 | ) -> Result { 37 | let mut r = Self { 38 | bytes: [0u8; SEED_MAX_BYTES], 39 | curve, 40 | }; 41 | (curve.generate_private_key)(rng, &mut r.bytes[..curve.elem_scalar_seed_len], cpu)?; 42 | Ok(r) 43 | } 44 | 45 | pub(crate) fn from_bytes( 46 | curve: &'static Curve, 47 | bytes: untrusted::Input, 48 | cpu: cpu::Features, 49 | ) -> Result { 50 | let bytes = bytes.as_slice_less_safe(); 51 | if curve.elem_scalar_seed_len != bytes.len() { 52 | return Err(error::Unspecified); 53 | } 54 | (curve.check_private_key_bytes)(bytes, cpu)?; 55 | let mut r = Self { 56 | bytes: [0; SEED_MAX_BYTES], 57 | curve, 58 | }; 59 | r.bytes[..curve.elem_scalar_seed_len].copy_from_slice(bytes); 60 | Ok(r) 61 | } 62 | 63 | pub fn bytes_less_safe(&self) -> &[u8] { 64 | &self.bytes[..self.curve.elem_scalar_seed_len] 65 | } 66 | 67 | pub(crate) fn compute_public_key( 68 | &self, 69 | cpu_features: cpu::Features, 70 | ) -> Result { 71 | let mut public_key = PublicKey { 72 | bytes: [0u8; PUBLIC_KEY_MAX_LEN], 73 | len: self.curve.public_key_len, 74 | }; 75 | (self.curve.public_from_private)( 76 | &mut public_key.bytes[..public_key.len], 77 | self, 78 | cpu_features, 79 | )?; 80 | Ok(public_key) 81 | } 82 | } 83 | 84 | #[derive(Copy, Clone)] 85 | pub struct PublicKey { 86 | bytes: [u8; PUBLIC_KEY_MAX_LEN], 87 | len: usize, 88 | } 89 | 90 | impl AsRef<[u8]> for PublicKey { 91 | fn as_ref(&self) -> &[u8] { 92 | &self.bytes[..self.len] 93 | } 94 | } 95 | 96 | /// The maximum length, in bytes, of an encoded public key. 97 | pub const PUBLIC_KEY_MAX_LEN: usize = 1 + (2 * ELEM_MAX_BYTES); 98 | -------------------------------------------------------------------------------- /src/ec/suite_b/ecdsa.rs: -------------------------------------------------------------------------------- 1 | mod digest_scalar; 2 | pub mod signing; 3 | pub mod verification; 4 | -------------------------------------------------------------------------------- /src/ec/suite_b/ecdsa/ecPublicKey_p256_pkcs8_v1_template.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/src/ec/suite_b/ecdsa/ecPublicKey_p256_pkcs8_v1_template.der -------------------------------------------------------------------------------- /src/ec/suite_b/ecdsa/ecPublicKey_p384_pkcs8_v1_template.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/src/ec/suite_b/ecdsa/ecPublicKey_p384_pkcs8_v1_template.der -------------------------------------------------------------------------------- /src/ec/suite_b/ecdsa/ecdsa_sign_asn1_tests.txt: -------------------------------------------------------------------------------- 1 | # Tests from NIST CAVP 186-4 ECDSA2VS Test Vectors, Signature Generation Test 2 | # http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip 3 | # 4 | # CAVS 11.2 5 | # "SigVer" information for "ecdsa_values" 6 | # Curves/SHAs selected: P-224,SHA-224 P-224,SHA-256 P-224,SHA-384 P-224,SHA-512 P-256,SHA-224 P-256,SHA-256 P-256,SHA-384 P-256,SHA-512 P-384,SHA-224 P-384,SHA-256 P-384,SHA-384 P-384,SHA-512 P-521,SHA-224 P-521,SHA-256 P-521,SHA-384 P-521,SHA-512 K-233,SHA-224 K-233,SHA-256 K-233,SHA-384 K-233,SHA-512 K-283,SHA-224 K-283,SHA-256 K-283,SHA-384 K-283,SHA-512 K-409,SHA-224 K-409,SHA-256 K-409,SHA-384 K-409,SHA-512 K-571,SHA-224 K-571,SHA-256 K-571,SHA-384 K-571,SHA-512 B-233,SHA-224 B-233,SHA-256 B-233,SHA-384 B-233,SHA-512 B-283,SHA-224 B-283,SHA-256 B-283,SHA-384 B-283,SHA-512 B-409,SHA-224 B-409,SHA-256 B-409,SHA-384 B-409,SHA-512 BB-571,SHA-224 B-571,SHA-256 B-571,SHA-384 B-571,SHA-512 7 | # Generated on Tue Aug 16 15:27:42 2011 8 | 9 | # [P-256,SHA-256] 10 | 11 | Curve = P-256 12 | Digest = SHA256 13 | Msg = 5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17cc934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8 14 | d = 519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464 15 | Q = 041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9 16 | k = 94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de 17 | Sig = 3046022100f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac0221008bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903 18 | 19 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p256_elem_mul_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | b = 00 4 | r = 00 5 | 6 | a = 00 7 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe 8 | r = 00 9 | 10 | a = 01 11 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe 12 | r = fffffffd00000002fffffffdffffffff00000001fffffffcffffffff 13 | 14 | a = 02 15 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe 16 | r = 01fffffffa00000005fffffffbfffffffe00000003fffffff9fffffffe 17 | 18 | a = 03 19 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe 20 | r = 02fffffff700000008fffffff9fffffffd00000005fffffff6fffffffd 21 | 22 | a = 7fffffff800000008000000000000000000000007fffffffffffffffffffffff 23 | b = 02 24 | r = fffffffd00000002fffffffdffffffff00000001fffffffcffffffff 25 | 26 | a = 7fffffff80000000800000000000000000000000800000000000000000000000 27 | b = 02 28 | r = fffffffe00000003fffffffd0000000200000001fffffffe0000000300000000 29 | 30 | a = 8000000000000000000000000000000000000000000000000000000000000000 31 | b = 02 32 | r = 01 33 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p256_elem_neg_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | b = 00 4 | 5 | a = 01 6 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe 7 | 8 | a = 02 9 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffd 10 | 11 | a = 03 12 | b = ffffffff00000001000000000000000000000000fffffffffffffffffffffffc 13 | 14 | a = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe 15 | b = 01 16 | 17 | a = 7fffffff800000008000000000000000000000007fffffffffffffffffffffff 18 | b = 7fffffff80000000800000000000000000000000800000000000000000000000 19 | 20 | a = 7fffffff80000000800000000000000000000000800000000000000000000000 21 | b = 7fffffff800000008000000000000000000000007fffffffffffffffffffffff 22 | 23 | a = 8000000000000000000000000000000000000000000000000000000000000000 24 | b = 7fffffff00000001000000000000000000000000ffffffffffffffffffffffff 25 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p256_point_double_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | # G doubled once. 3 | a = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c, 8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a, 00000000fffffffeffffffffffffffffffffffff000000000000000000000001 4 | r = f6bb32e43dcf3a3b732205038d1490d9aa6ae3c1a433827d850046d410ddd64d, 78c577510a5b8a3b19a8fb0e92042dbe152cd7cbeb236ff82f3648d361bee1a5 5 | 6 | # Point at infinity doubled. This uses the (0, 0, 0) representation of 7 | # the point at infinity instead of the classic (1, 1, 0) 8 | # representation. 9 | a = 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 10 | r = inf 11 | 12 | # Point at infinity doubled. This form is the result of multiplying 13 | # n * G (affine), which is more interesting than the above case 14 | # because only the Z coordinate is zero. 15 | a = 2b11cb945c8cf152ffa4c9c2b1c965b019b35d0b7626919ef0ae6cb9d232f8af, 6d333da42e30f7011245b6281015ded14e0f100968e758a1b6c3c083afc14ea0, 0000000000000000000000000000000000000000000000000000000000000000 16 | r = inf 17 | 18 | # (n - 1) * G doubled. 19 | a = 2b11cb945c8cf152ffa4c9c2b1c965b019b35d0b7626919ef0ae6cb9d232f8af, 6d333da42e30f7011245b6281015ded14e0f100968e758a1b6c3c083afc14ea0, 3c396f06c1dc69e4f4b2dce51cd660f761064a4ab098ef61ba3868961f0ef178 20 | r = f6bb32e43dcf3a3b732205038d1490d9aa6ae3c1a433827d850046d410ddd64d, 873a88adf5a475c5e65704f16dfbd241ead3283514dc9007d0c9b72c9e411e5a 21 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p256_point_mul_serialized_tests.txt: -------------------------------------------------------------------------------- 1 | # Regression Test from https://github.com/golang/go/issues/20040 2 | 3 | p_scalar = 2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737 4 | p = 04023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882eaf93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad 5 | r = 044d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0 6 | 7 | p_scalar = 313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd 8 | p = 04cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031 9 | r = 04831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f1799193f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684 10 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p256_scalar_square_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | r = 00 4 | 5 | a = 00 6 | r = 00 7 | 8 | a = 01 9 | r = 60d066334905c1e907f8b6041e607725badef3e243566fafce1bc8f79c197c79 10 | 11 | a = 02 12 | r = 834198ce241707a31fe2d8107981dc972e94d4db6642203a44b5591b7402cc93 13 | 14 | a = ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550 15 | r = 60d066334905c1e907f8b6041e607725badef3e243566fafce1bc8f79c197c79 16 | 17 | a = ffffffff80000000600000002fffffff 18 | r = 965f4779ac1ddbac28a14bd1e0c28dcb091d48820b4116d22afbc3f00f90f476 19 | 20 | a = ffffffff800000006000000030000000 21 | r = 9e07cb5cdf45939f41541805d2c24625e1cb1719e37a89efc755b5e58e585515 22 | 23 | a = 8000000000000000000000000000000000000000000000000000000000000000 24 | r = 4000000000000000000000000000000000000000000000000000000000000000 25 | 26 | # From BoringSSL 27 | 28 | a = 0000000000000000000000000000000000000000000000000000000000000000 29 | r = 0000000000000000000000000000000000000000000000000000000000000000 30 | 31 | a = 00000000ffffffff00000000000000004319055258e8617b0c46353d039cdaaf 32 | r = 00000000ffffffff00000000000000004319055258e8617b0c46353d039cdaaf 33 | 34 | a = ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550 35 | r = 60d066334905c1e907f8b6041e607725badef3e243566fafce1bc8f79c197c79 36 | 37 | a = da43b8dd7fe8830a4fe8980ec585ccbe903a2965a695cdff398200b74b2ede41 38 | r = 5ec68604412205b380e26ee4e4081eccc10ac7d1417b09cd534f8517b0de81ec 39 | 40 | a = a82a2b8bdbf8a37dc7cb5799691494a8c9fbf649686a4d250dc30697feb0fa47 41 | r = 552c094a8841621d6cc26b3b54ce5da5664283888445196a6433d3cfdcad3aee 42 | 43 | a = d785006e250410d9dcc6d7740795a7374c25b00b9c9a37b8285694a07307eacd 44 | r = 971aaa9e70ad082cf43725f2e65bc73f4bf762459cee13167545072ec7bdcaf8 45 | 46 | a = 69d6d9f5417e87d603a3fb6acafa0d1f974abf94ca57ce58d718a0ad5d02a496 47 | r = eb3284e5799fbe93171f08e6de9f792cd17f036b3a17671b0310e49b48e589b3 48 | 49 | a = 1c28f742c3e26e74901d0425f2eb4d5272524668d2405875b32cf6433f212900 50 | r = 74f70a95399b7ad061a2200fa50528d68eee4654341c8158101e1e3f8f16e642 51 | 52 | a = 026b2f69f0259d221920b2f358b378a79826f0332ee36afa257765043e3d6732 53 | r = e1e9cfa4724995bb50971ca22f3c028cd31cb51fbef8a37c31f10fd1d468f13b 54 | 55 | a = 376ed4fadcc1c6c4160a0c9c2ab7c62260367968b08d304d47c65f25625d7d60 56 | r = b9ccb67f377e1278f1d2eeda26e5eed76f32406c9deed9764fc0aa346d91e02b 57 | 58 | a = 50f66867d0a4ef389678d760d2a4db886583b4c068d0e240f7ddf3472c871304 59 | r = 82c3467bc5f7ca8b45f4ee61546745e2f53755a02e87f65f572418d60e471c8b 60 | 61 | a = 5b8bd82b37206d2b727f19ad2d02f63773470074dde7d43d2a77c448ddf2f978 62 | r = dbf3c2fc67a0688c3b5ff12cab1739d50b6093c5d98943d388652b1207e4a0f2 63 | 64 | a = bed7b3a4dada0e16984eb59ee239005ab212e5b1772cdd5d240c8ee268f65c81 65 | r = 9232aa2759ca9c5efbaefb0cf45cc6bc9c89def8c25e5c169fe623f30787df36 66 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p384_elem_div_by_2_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | r = 00 4 | 5 | a = 00 6 | r = 00 7 | 8 | a = 01 9 | r = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff800000000000000080000000 10 | 11 | a = 02 12 | r = 01 13 | 14 | a = 03 15 | r = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff800000000000000080000001 16 | 17 | a = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 18 | r = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff80000000000000007fffffff 19 | 20 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff80000000000000007fffffff 21 | r = bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3fffffff4000000000000000bfffffff 22 | 23 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff800000000000000080000000 24 | r = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 25 | 26 | a = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 27 | r = 400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 28 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p384_elem_mul_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | b = 00 4 | r = 00 5 | 6 | a = 00 7 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 8 | r = 00 9 | 10 | a = 01 11 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 12 | r = ffffffebffffffebfffffff3fffffffd0000000300000005000000040000000100000013000000270000001ffffffff9 13 | 14 | a = 02 15 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 16 | r = ffffffd7ffffffd7ffffffe7fffffffa000000060000000a0000000800000003000000270000004e0000003efffffff3 17 | 18 | a = 03 19 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 20 | r = ffffffc3ffffffc3ffffffdbfffffff7000000090000000f0000000c000000050000003b000000750000005dffffffed 21 | 22 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff80000000000000007fffffff 23 | b = 02 24 | r = ffffffebffffffebfffffff3fffffffd0000000300000005000000040000000100000013000000270000001ffffffff9 25 | 26 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff800000000000000080000000 27 | b = 02 28 | r = 14000000140000000c00000002fffffffcfffffffafffffffbfffffffdffffffebffffffd8ffffffe100000006 29 | 30 | a = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 31 | b = 02 32 | r = 01 33 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p384_elem_neg_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | b = 00 4 | 5 | a = 01 6 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 7 | 8 | a = 02 9 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd 10 | 11 | a = 03 12 | b = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc 13 | 14 | a = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe 15 | b = 01 16 | 17 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff80000000000000007fffffff 18 | b = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff800000000000000080000000 19 | 20 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff800000000000000080000000 21 | b = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffff80000000000000007fffffff 22 | 23 | a = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 24 | b = 7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff 25 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p384_point_double_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | # G doubled once. 3 | a = 4d3aadc2299e1513812ff723614ede2b6454868459a30eff879c3afc541b4d6e20e378e2a0d6ce383dd0756649c0b528, 2b78abc25a15c5e9dd8002263969a840c6c3521968f4ffd98bade7562e83b050a1bfa8bf7bb4a9ac23043dad4b03a4fe, 000000000000000000000000000000000000000000000000000000000000000100000000ffffffffffffffff00000001 4 | r = db93b776427460c39c90a4fd2de4b506da821495f0687f503504e6f0ff9d48a18e6c8f2e022b53f0c8229e55783dde91, e34947f7123df0c2070d430900b0e68409f1fe415172bad915e4f18bdc588258e8e8e4a8c2aaccd842ea84633140bfda 5 | 6 | # Point at infinity doubled. This uses the (0, 0, 0) representation of 7 | # the point at infinity instead of the classic (1, 1, 0) 8 | # representation. 9 | a = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 10 | r = inf 11 | 12 | # Point at infinity doubled. This form is the result of multiplying 13 | # n * G (affine), which is more interesting than the above case 14 | # because only the Z coordinate is zero. 15 | a = 4a0fd63f894499928e4b2b72aced45cfc589976f4ff86f78c904d59da9379a62b702d968c1184834c11db28c7356ceb6, be113b04484cd4bc215a9f2a33a674c3764c38ca4de135dd50ce8dcf3c85d55a5aad0e171860bdb6c58201e6212d9ac5, 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 16 | r = inf 17 | 18 | # (n - 1) * G doubled. 19 | a = f3ee335326d22614d01b5d7cd0be73f1bfdd75982c9c273f72d0abfeecbca0431601a1bcafcdeb07e21ecf4d91c7b520, 57b82ca1527c5a01b78bc8ccb9febe74178b04b7c6fde1c1c4ef9a220c4320bb560cb078542256a3900df61c107de6c5, 53b3adc887551c0e17c07ecb42d1a5ec105aeec6b0f040a936ed4f756e83939226232b4e11191b3eb1d841c650682ca0 20 | r = db93b776427460c39c90a4fd2de4b506da821495f0687f503504e6f0ff9d48a18e6c8f2e022b53f0c8229e55783dde91, 1cb6b808edc20f3df8f2bcf6ff4f197bf60e01beae8d4526ea1b0e7423a77da617171b563d553327bd157b9dcebf4025 21 | -------------------------------------------------------------------------------- /src/ec/suite_b/ops/p384_scalar_mul_tests.txt: -------------------------------------------------------------------------------- 1 | 2 | a = 00 3 | b = 00 4 | r = 00 5 | 6 | a = 00 7 | b = ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972 8 | r = 00 9 | 10 | a = 01 11 | b = ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972 12 | r = caa357821c6244e05eafdf931b0e6b53872b45a79929e877e4c3adcae9998bc585acc2c6a24bb9ca8be13114da045062 13 | 14 | a = 02 15 | b = ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972 16 | r = 9546af0438c489c0bd5fbf26361cd6a70e568b4f3253d0f002240e13defbe9abb33f77dafbe6cc1a2ad648bee7437751 17 | 18 | a = 03 19 | b = ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972 20 | r = 5fea06865526cea11c0f9eb9512b41fa9581d0f6cb7db9681f846e5cd45e4791e0d22cef5581de69c9cb6068f4829e40 21 | 22 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb5666294b9 23 | b = 02 24 | r = caa357821c6244e05eafdf931b0e6b53872b45a79929e877e4c3adcae9998bc585acc2c6a24bb9ca8be13114da045062 25 | 26 | a = 7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb5666294ba 27 | b = 02 28 | r = 355ca87de39dbb1fa150206ce4f194ac78d4ba5866d61787e29f9fb70a9da219d26d4aeba664edb0610ae855f2c0d911 29 | 30 | a = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 31 | b = 02 32 | r = 01 33 | -------------------------------------------------------------------------------- /src/error/input_too_long.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | pub struct InputTooLongError { 16 | /// Note that this might not actually be the (exact) length of the input, 17 | /// and its units might be lost. For example, it could be any of the 18 | /// following: 19 | /// 20 | /// * The length in bytes of the entire input. 21 | /// * The length in bytes of some *part* of the input. 22 | /// * A bit length. 23 | /// * A length in terms of "blocks" or other grouping of input values. 24 | /// * Some intermediate quantity that was used when checking the input 25 | /// length. 26 | /// * Some arbitrary value. 27 | #[allow(dead_code)] 28 | imprecise_input_length: T, 29 | } 30 | 31 | impl InputTooLongError { 32 | #[cold] 33 | #[inline(never)] 34 | pub(crate) fn new(imprecise_input_length: T) -> Self { 35 | Self { 36 | imprecise_input_length, 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/error/into_unspecified.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::error::{KeyRejected, Unspecified}; 16 | 17 | impl From for Unspecified { 18 | fn from(source: untrusted::EndOfInput) -> Self { 19 | super::erase(source) 20 | } 21 | } 22 | 23 | impl From for Unspecified { 24 | fn from(source: core::array::TryFromSliceError) -> Self { 25 | super::erase(source) 26 | } 27 | } 28 | 29 | impl From for Unspecified { 30 | fn from(source: KeyRejected) -> Self { 31 | super::erase(source) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/error/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! Error reporting. 16 | 17 | pub use self::{key_rejected::KeyRejected, unspecified::Unspecified}; 18 | 19 | pub(crate) use self::{ 20 | input_too_long::InputTooLongError, len_mismatch_error::LenMismatchError, 21 | too_much_output_requested::TooMuchOutputRequestedError, 22 | }; 23 | 24 | mod input_too_long; 25 | mod into_unspecified; 26 | mod key_rejected; 27 | mod unspecified; 28 | 29 | #[cold] 30 | #[inline(never)] 31 | pub(crate) fn erase(_: T) -> Unspecified { 32 | Unspecified 33 | } 34 | 35 | cold_exhaustive_error! { 36 | struct too_much_output_requested::TooMuchOutputRequestedError 37 | with pub(crate) constructor { 38 | // Note that this might not actually be the (exact) output length 39 | // requested, and its units might be lost. For example, it could be any of 40 | // the following: 41 | // 42 | // * The length in bytes of the entire output. 43 | // * The length in bytes of some *part* of the output. 44 | // * A bit length. 45 | // * A length in terms of "blocks" or other grouping of output values. 46 | // * Some intermediate quantity that was used when checking the output 47 | // length. 48 | // * Some arbitrary value. 49 | imprecise_output_length: usize 50 | } 51 | } 52 | 53 | cold_exhaustive_error! { 54 | struct len_mismatch_error::LenMismatchError 55 | with pub(crate) constructor { 56 | len: usize 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/hmac_generate_serializable_tests.txt: -------------------------------------------------------------------------------- 1 | HMAC = SHA1 2 | Key = 000102030405060708090a0b0c0d0e0f10111213 3 | 4 | HMAC = SHA256 5 | Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 6 | 7 | HMAC = SHA384 8 | Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f 9 | 10 | HMAC = SHA512 11 | Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f 12 | -------------------------------------------------------------------------------- /src/io.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! Serialization and deserialization. 16 | 17 | #[doc(hidden)] 18 | pub mod der; 19 | 20 | #[cfg(feature = "alloc")] 21 | mod writer; 22 | 23 | #[cfg(feature = "alloc")] 24 | pub(crate) mod der_writer; 25 | 26 | pub(crate) mod positive; 27 | 28 | pub use self::positive::Positive; 29 | 30 | #[cfg(feature = "alloc")] 31 | pub(crate) use self::writer::TooLongError; 32 | -------------------------------------------------------------------------------- /src/io/der_writer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::{der::*, writer::*, *}; 16 | use alloc::boxed::Box; 17 | 18 | pub(crate) fn write_positive_integer( 19 | output: &mut dyn Accumulator, 20 | value: &Positive, 21 | ) -> Result<(), TooLongError> { 22 | let first_byte = value.first_byte(); 23 | let value = value.big_endian_without_leading_zero_as_input(); 24 | write_tlv(output, Tag::Integer, |output| { 25 | if (first_byte & 0x80) != 0 { 26 | output.write_byte(0)?; // Disambiguate negative number. 27 | } 28 | write_copy(output, value) 29 | }) 30 | } 31 | 32 | pub(crate) fn write_all( 33 | tag: Tag, 34 | write_value: &dyn Fn(&mut dyn Accumulator) -> Result<(), TooLongError>, 35 | ) -> Result, TooLongError> { 36 | let length = { 37 | let mut length = LengthMeasurement::zero(); 38 | write_tlv(&mut length, tag, write_value)?; 39 | length 40 | }; 41 | 42 | let mut output = Writer::with_capacity(length); 43 | write_tlv(&mut output, tag, write_value)?; 44 | 45 | Ok(output.into()) 46 | } 47 | 48 | fn write_tlv(output: &mut dyn Accumulator, tag: Tag, write_value: F) -> Result<(), TooLongError> 49 | where 50 | F: Fn(&mut dyn Accumulator) -> Result<(), TooLongError>, 51 | { 52 | let length: usize = { 53 | let mut length = LengthMeasurement::zero(); 54 | write_value(&mut length)?; 55 | length.into() 56 | }; 57 | let length: u16 = length.try_into().map_err(|_| TooLongError::new())?; 58 | 59 | output.write_byte(tag.into())?; 60 | 61 | let [lo, hi] = length.to_le_bytes(); 62 | if length >= 0x1_00 { 63 | output.write_byte(0x82)?; 64 | output.write_byte(hi)?; 65 | } else if length >= 0x80 { 66 | output.write_byte(0x81)?; 67 | } 68 | output.write_byte(lo)?; 69 | 70 | write_value(output) 71 | } 72 | -------------------------------------------------------------------------------- /src/io/writer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use alloc::{boxed::Box, vec::Vec}; 16 | 17 | pub trait Accumulator { 18 | fn write_byte(&mut self, value: u8) -> Result<(), TooLongError>; 19 | fn write_bytes(&mut self, value: &[u8]) -> Result<(), TooLongError>; 20 | } 21 | 22 | pub(super) struct LengthMeasurement { 23 | len: usize, 24 | } 25 | 26 | impl From for usize { 27 | fn from(len: LengthMeasurement) -> usize { 28 | len.len 29 | } 30 | } 31 | 32 | impl LengthMeasurement { 33 | pub fn zero() -> Self { 34 | Self { len: 0 } 35 | } 36 | } 37 | 38 | impl Accumulator for LengthMeasurement { 39 | fn write_byte(&mut self, _value: u8) -> Result<(), TooLongError> { 40 | self.len = self.len.checked_add(1).ok_or_else(TooLongError::new)?; 41 | Ok(()) 42 | } 43 | fn write_bytes(&mut self, value: &[u8]) -> Result<(), TooLongError> { 44 | self.len = self 45 | .len 46 | .checked_add(value.len()) 47 | .ok_or_else(TooLongError::new)?; 48 | Ok(()) 49 | } 50 | } 51 | 52 | pub(super) struct Writer { 53 | bytes: Vec, 54 | requested_capacity: usize, 55 | } 56 | 57 | impl Writer { 58 | pub(super) fn with_capacity(capacity: LengthMeasurement) -> Self { 59 | Self { 60 | bytes: Vec::with_capacity(capacity.len), 61 | requested_capacity: capacity.len, 62 | } 63 | } 64 | } 65 | 66 | impl From for Box<[u8]> { 67 | fn from(writer: Writer) -> Self { 68 | assert_eq!(writer.requested_capacity, writer.bytes.len()); 69 | writer.bytes.into_boxed_slice() 70 | } 71 | } 72 | 73 | impl Accumulator for Writer { 74 | fn write_byte(&mut self, value: u8) -> Result<(), TooLongError> { 75 | self.bytes.push(value); 76 | Ok(()) 77 | } 78 | fn write_bytes(&mut self, value: &[u8]) -> Result<(), TooLongError> { 79 | self.bytes.extend(value); 80 | Ok(()) 81 | } 82 | } 83 | 84 | pub fn write_copy( 85 | accumulator: &mut dyn Accumulator, 86 | to_copy: untrusted::Input, 87 | ) -> Result<(), TooLongError> { 88 | accumulator.write_bytes(to_copy.as_slice_less_safe()) 89 | } 90 | 91 | pub struct TooLongError(()); 92 | 93 | impl TooLongError { 94 | pub fn new() -> Self { 95 | Self(()) 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/polyfill/array_split_map.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | pub trait ArraySplitMap { 16 | fn array_split_map(self, f: impl Fn([I; CN]) -> O) -> [O; ON]; 17 | } 18 | 19 | impl ArraySplitMap for [I; 12] { 20 | #[inline] 21 | fn array_split_map(self, f: impl Fn([I; 4]) -> O) -> [O; 3] { 22 | let [a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3] = self; 23 | [ 24 | f([a0, a1, a2, a3]), 25 | f([b0, b1, b2, b3]), 26 | f([c0, c1, c2, c3]), 27 | ] 28 | } 29 | } 30 | 31 | impl ArraySplitMap for [I; 16] { 32 | #[inline] 33 | fn array_split_map(self, f: impl Fn([I; 4]) -> O) -> [O; 4] { 34 | let [a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3] = self; 35 | [ 36 | f([a0, a1, a2, a3]), 37 | f([b0, b1, b2, b3]), 38 | f([c0, c1, c2, c3]), 39 | f([d0, d1, d2, d3]), 40 | ] 41 | } 42 | } 43 | 44 | impl ArraySplitMap for [I; 32] { 45 | #[inline] 46 | fn array_split_map(self, f: impl Fn([I; 4]) -> O) -> [O; 8] { 47 | let [a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3, f0, f1, f2, f3, g0, g1, g2, g3, h0, h1, h2, h3] = 48 | self; 49 | [ 50 | f([a0, a1, a2, a3]), 51 | f([b0, b1, b2, b3]), 52 | f([c0, c1, c2, c3]), 53 | f([d0, d1, d2, d3]), 54 | f([e0, e1, e2, e3]), 55 | f([f0, f1, f2, f3]), 56 | f([g0, g1, g2, g3]), 57 | f([h0, h1, h2, h3]), 58 | ] 59 | } 60 | } 61 | 62 | impl ArraySplitMap for [I; 16] { 63 | #[inline] 64 | fn array_split_map(self, f: impl Fn([I; 8]) -> O) -> [O; 2] { 65 | let [a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7] = self; 66 | [ 67 | f([a0, a1, a2, a3, a4, a5, a6, a7]), 68 | f([b0, b1, b2, b3, b4, b5, b6, b7]), 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/polyfill/leading_zeros_skipped.rs: -------------------------------------------------------------------------------- 1 | use core::iter::Peekable; 2 | 3 | /// An iterator that skips all leading zeros. 4 | /// 5 | /// When the wrapped iterator is all zeros, then the last item is retained. 6 | pub struct LeadingZerosStripped 7 | where 8 | I: Iterator, 9 | { 10 | inner: Peekable, 11 | } 12 | 13 | impl Clone for LeadingZerosStripped 14 | where 15 | I: Iterator, 16 | Peekable: Clone, 17 | { 18 | fn clone(&self) -> Self { 19 | Self { 20 | inner: self.inner.clone(), 21 | } 22 | } 23 | } 24 | 25 | impl LeadingZerosStripped 26 | where 27 | I: ExactSizeIterator, 28 | { 29 | pub fn new(inner: I) -> Self { 30 | let mut len = inner.len(); 31 | let mut inner = inner.peekable(); 32 | // Strip all leading zeroes, but don't strip the last byte if all bytes 33 | // were zero. 34 | while len > 1 && inner.next_if_eq(&0).is_some() { 35 | len -= 1; 36 | } 37 | Self { inner } 38 | } 39 | } 40 | 41 | impl Iterator for LeadingZerosStripped 42 | where 43 | I: Iterator, 44 | { 45 | type Item = I::Item; 46 | 47 | fn next(&mut self) -> Option { 48 | self.inner.next() 49 | } 50 | 51 | fn size_hint(&self) -> (usize, Option) { 52 | self.inner.size_hint() 53 | } 54 | } 55 | 56 | impl ExactSizeIterator for LeadingZerosStripped where I: ExactSizeIterator {} 57 | 58 | #[cfg(test)] 59 | mod tests { 60 | use super::*; 61 | 62 | #[test] 63 | fn test_leading_zeroes_stripped() { 64 | static TEST_CASES: &[(&[u8], &[u8])] = &[ 65 | (&[], &[]), 66 | (&[0], &[0]), 67 | (&[0, 1], &[1]), 68 | (&[0, 0, 1], &[1]), 69 | (&[0, 0, 0, 1], &[1]), 70 | (&[1, 0], &[1, 0]), 71 | (&[0, 1, 0], &[1, 0]), 72 | ]; 73 | TEST_CASES.iter().copied().for_each(|(input, expected)| { 74 | let stripped = LeadingZerosStripped::new(input.iter().copied()); 75 | super::super::test::assert_iterator(stripped, expected); 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/polyfill/notsend.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::testutil; 16 | use core::{marker::PhantomData, mem::size_of}; 17 | 18 | /// A ZST that can be added to any type to make the type `!Send`. 19 | #[derive(Clone, Copy)] 20 | pub struct NotSend(PhantomData<*mut ()>); 21 | 22 | impl NotSend { 23 | pub const VALUE: Self = Self(PhantomData); 24 | } 25 | 26 | #[allow(deprecated)] 27 | const _: () = testutil::compile_time_assert_clone::(); 28 | #[allow(deprecated)] 29 | const _: () = testutil::compile_time_assert_copy::(); 30 | const _: () = assert!(size_of::() == 0); 31 | -------------------------------------------------------------------------------- /src/polyfill/once_cell/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHOR OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/polyfill/once_cell/README.txt: -------------------------------------------------------------------------------- 1 | Vendored from matklad/once_cell d119eeade59cd7e47b7abf979488b0be1d5b2d79. 2 | Originally unmodified except for deleting everything after `OnceNonZeroUsize`. 3 | -------------------------------------------------------------------------------- /src/polyfill/ptr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // TODO(MSRV 1.76): Replace with `core::ptr::from_mut`. 16 | #[allow(dead_code)] 17 | #[inline(always)] 18 | pub fn from_mut(r: &mut T) -> *mut T { 19 | r 20 | } 21 | 22 | // TODO(MSRV 1.76): Replace with `core::ptr::from_ref`. 23 | #[allow(dead_code)] 24 | #[inline(always)] 25 | pub const fn from_ref(r: &T) -> *const T { 26 | r 27 | } 28 | -------------------------------------------------------------------------------- /src/polyfill/slice.rs: -------------------------------------------------------------------------------- 1 | // Permission is hereby granted, free of charge, to any 2 | // person obtaining a copy of this software and associated 3 | // documentation files (the "Software"), to deal in the 4 | // Software without restriction, including without 5 | // limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of 7 | // the Software, and to permit persons to whom the Software 8 | // is furnished to do so, subject to the following 9 | // conditions: 10 | // 11 | // The above copyright notice and this permission notice 12 | // shall be included in all copies or substantial portions 13 | // of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | // SHALL THE AUTHOR OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | // DEALINGS IN THE SOFTWARE. 24 | 25 | mod as_chunks; 26 | mod as_chunks_mut; 27 | 28 | pub use as_chunks::{as_chunks, AsChunks}; 29 | pub use as_chunks_mut::{as_chunks_mut, AsChunksMut}; 30 | 31 | // TODO(MSRV-1.80): Use `slice::split_at_checked`. 32 | // 33 | // Note that the libcore version is implemented in terms of 34 | // `slice::split_at_unchecked()`, and `slice::split_at()` was changed to be 35 | // implemented in terms of `split_at_checked`. For now, we implement this in 36 | // terms of `split_at` and rely on the optimizer to eliminate the panic. 37 | #[inline] 38 | pub fn split_at_checked(slice: &[T], mid: usize) -> Option<(&[T], &[T])> { 39 | if slice.len() >= mid { 40 | Some(slice.split_at(mid)) 41 | } else { 42 | None 43 | } 44 | } 45 | 46 | // TODO(MSRV-1.80): Use `slice::split_at_checked`. 47 | #[inline] 48 | pub fn split_at_mut_checked(slice: &mut [T], mid: usize) -> Option<(&mut [T], &mut [T])> { 49 | if slice.len() >= mid { 50 | Some(slice.split_at_mut(mid)) 51 | } else { 52 | None 53 | } 54 | } 55 | 56 | // TODO(MSRV-1.77): Use `slice::split_first_chunk_mut`. 57 | #[inline] 58 | pub fn split_first_chunk_mut( 59 | slice: &mut [T], 60 | ) -> Option<(&mut [T; N], &mut [T])> { 61 | let (head, tail) = split_at_mut_checked(slice, N)?; 62 | head.try_into().ok().map(|head| (head, tail)) 63 | } 64 | -------------------------------------------------------------------------------- /src/polyfill/sliceutil.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! Utilities to make dealing with slices less tediuous. 16 | 17 | /// Replaces the first N elements of `a` with the first N elements of `b`, where 18 | /// N is `core::cmp::min(a.len(), b.len())`, leaving the rest unchanged. 19 | pub fn overwrite_at_start(a: &mut [T], b: &[T]) { 20 | a.iter_mut().zip(b).for_each(|(a, b)| { 21 | *a = *b; 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /src/polyfill/test.rs: -------------------------------------------------------------------------------- 1 | pub fn assert_iterator(it: impl ExactSizeIterator + Clone, expected: &[T]) 2 | where 3 | T: Copy + core::fmt::Debug + PartialEq, 4 | { 5 | // Assert that the cloned iterator is correct. 6 | assert_exact_size_iterator(it.clone(), expected); 7 | // Assert that the original iterator is correct. 8 | assert_exact_size_iterator(it, expected); 9 | } 10 | 11 | /// Asserts that `it` adheres to the `ExactSizeIterator` contract. 12 | fn assert_exact_size_iterator(mut it: impl ExactSizeIterator, expected: &[T]) 13 | where 14 | T: Copy + core::fmt::Debug + PartialEq, 15 | { 16 | assert_eq!(it.len(), expected.len()); 17 | assert_eq!(it.size_hint(), expected.iter().size_hint()); 18 | 19 | for i in 0..expected.len() { 20 | let len = it.len(); 21 | assert_eq!(len, expected.len() - i); 22 | assert_eq!(it.size_hint(), (len, Some(len))); 23 | assert_eq!(it.next(), Some(expected[i])); 24 | } 25 | 26 | assert_eq!(it.len(), 0); 27 | assert_eq!(it.size_hint(), (0, Some(0))); 28 | assert_eq!(it.next(), None); 29 | } 30 | -------------------------------------------------------------------------------- /src/polyfill/unwrap_const.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | /// Polyfill for `Option::unwrap()` as a const fn; feature `const_option`. 16 | /// https://github.com/rust-lang/rust/issues/67441. 17 | /// TODO(MSRV): Replace this with `x.unwrap()`. 18 | /// 19 | /// `T: Copy` avoids "constant functions cannot evaluate destructors." 20 | pub const fn unwrap_const(x: Option) -> T 21 | where 22 | T: Copy, 23 | { 24 | if let Some(x) = x { 25 | x 26 | } else { 27 | panic!("unwrap_const on `None`"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/rsa.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // *R* and *r* in Montgomery math refer to different things, so we always use 16 | // `R` to refer to *R* to avoid confusion, even when that's against the normal 17 | // naming conventions. Also the standard camelCase names are used for `KeyPair` 18 | // components. 19 | 20 | //! RSA. 21 | 22 | use crate::{ 23 | arithmetic::bigint, 24 | bits, error, 25 | io::{self, der}, 26 | }; 27 | 28 | pub(crate) mod padding; 29 | 30 | // Maximum RSA modulus size supported for signature verification (in bytes). 31 | const PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN: usize = 32 | bits::BitLength::from_bits(8192).as_usize_bytes_rounded_up(); 33 | 34 | // Keep in sync with the documentation comment for `KeyPair`. 35 | const PRIVATE_KEY_PUBLIC_MODULUS_MAX_BITS: bits::BitLength = bits::BitLength::from_bits(4096); 36 | 37 | /// Parameters for RSA verification. 38 | #[derive(Debug)] 39 | pub struct RsaParameters { 40 | padding_alg: &'static dyn padding::Verification, 41 | min_bits: bits::BitLength, 42 | } 43 | 44 | fn parse_public_key( 45 | input: untrusted::Input, 46 | ) -> Result<(io::Positive, io::Positive), error::Unspecified> { 47 | input.read_all(error::Unspecified, |input| { 48 | der::nested(input, der::Tag::Sequence, error::Unspecified, |input| { 49 | let n = der::positive_integer(input)?; 50 | let e = der::positive_integer(input)?; 51 | Ok((n, e)) 52 | }) 53 | }) 54 | } 55 | 56 | // Type-level representation of an RSA public modulus *n*. See 57 | // `super::bigint`'s modulue-level documentation. 58 | enum N {} 59 | 60 | impl bigint::PublicModulus for N {} 61 | 62 | mod keypair; 63 | mod keypair_components; 64 | mod public_exponent; 65 | mod public_key; 66 | mod public_key_components; 67 | mod public_modulus; 68 | 69 | pub(crate) mod verification; 70 | 71 | use self::{public_exponent::PublicExponent, public_modulus::PublicModulus}; 72 | 73 | pub use self::{ 74 | keypair::KeyPair, keypair_components::KeyPairComponents, public_key::PublicKey, 75 | public_key_components::PublicKeyComponents, 76 | }; 77 | -------------------------------------------------------------------------------- /src/rsa/keypair_components.rs: -------------------------------------------------------------------------------- 1 | use super::PublicKeyComponents; 2 | 3 | /// RSA key pair components. 4 | #[derive(Clone, Copy)] 5 | pub struct KeyPairComponents { 6 | /// The public key components. 7 | pub public_key: PublicKeyComponents, 8 | 9 | /// The private exponent. 10 | pub d: Private, 11 | 12 | /// The first prime factor of `d`. 13 | pub p: Private, 14 | 15 | /// The second prime factor of `d`. 16 | pub q: Private, 17 | 18 | /// `p`'s public Chinese Remainder Theorem exponent. 19 | pub dP: Private, 20 | 21 | /// `q`'s public Chinese Remainder Theorem exponent. 22 | pub dQ: Private, 23 | 24 | /// `q**-1 mod p`. 25 | pub qInv: Private, 26 | } 27 | 28 | impl core::fmt::Debug for KeyPairComponents 29 | where 30 | PublicKeyComponents: core::fmt::Debug, 31 | { 32 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { 33 | // Non-public components are intentionally skipped 34 | f.debug_struct("KeyPairComponents") 35 | .field("public_key", &self.public_key) 36 | .finish() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/rsa/public_key_components.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2021 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use super::PublicKey; 16 | use core::iter::FromIterator; 17 | 18 | /// RSA public key components. 19 | /// 20 | /// `B` must implement `AsRef<[u8]>` like `&[u8]` or `Vec`. 21 | #[derive(Clone, Copy)] 22 | pub struct PublicKeyComponents { 23 | /// The public modulus, encoded in big-endian bytes without leading zeros. 24 | pub n: B, 25 | 26 | /// The public exponent, encoded in big-endian bytes without leading zeros. 27 | pub e: B, 28 | } 29 | 30 | impl core::fmt::Debug for PublicKeyComponents 31 | where 32 | B: core::fmt::Debug, 33 | { 34 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { 35 | f.debug_struct("PublicKeyComponents") 36 | .field("n", &self.n) 37 | .field("e", &self.e) 38 | .finish() 39 | } 40 | } 41 | 42 | impl From<&PublicKey> for PublicKeyComponents 43 | where 44 | B: FromIterator, 45 | { 46 | fn from(public_key: &PublicKey) -> Self { 47 | Self { 48 | n: public_key.inner().n().be_bytes().collect(), 49 | e: public_key.inner().e().be_bytes().collect(), 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/rsa/signature_rsa_example_private_key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/src/rsa/signature_rsa_example_private_key.der -------------------------------------------------------------------------------- /src/rsa/signature_rsa_example_public_key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/src/rsa/signature_rsa_example_public_key.der -------------------------------------------------------------------------------- /src/test_1_syntax_error_tests.txt: -------------------------------------------------------------------------------- 1 | Key: 0 2 | -------------------------------------------------------------------------------- /src/test_1_tests.txt: -------------------------------------------------------------------------------- 1 | Key = Value 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/test_3_tests.txt: -------------------------------------------------------------------------------- 1 | Key = 0 2 | 3 | Key = 1 4 | 5 | Key = 2 6 | -------------------------------------------------------------------------------- /src/tests/bits_tests.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use crate::{ 16 | bits::{BitLength, FromByteLen as _}, 17 | polyfill::u64_from_usize, 18 | }; 19 | 20 | #[test] 21 | fn test_from_byte_len_overflow() { 22 | const USIZE_MAX_VALID_BYTES: usize = usize::MAX / 8; 23 | 24 | // Maximum valid input for BitLength. 25 | match BitLength::::from_byte_len(USIZE_MAX_VALID_BYTES) { 26 | Ok(bits) => { 27 | assert_eq!(bits.as_usize_bytes_rounded_up(), USIZE_MAX_VALID_BYTES); 28 | assert_eq!(bits.as_bits(), usize::MAX & !0b111); 29 | } 30 | Err(_) => unreachable!(), 31 | } 32 | 33 | // Minimum invalid usize input for BitLength. 34 | assert!(BitLength::::from_byte_len(USIZE_MAX_VALID_BYTES + 1).is_err()); 35 | 36 | // Minimum invalid usize input for BitLength on 64-bit targets. 37 | { 38 | let r = BitLength::::from_byte_len(USIZE_MAX_VALID_BYTES + 1); 39 | if cfg!(target_pointer_width = "64") { 40 | assert!(r.is_err()); 41 | } else { 42 | match r { 43 | Ok(bits) => { 44 | assert_eq!( 45 | bits.as_bits(), 46 | (u64_from_usize(USIZE_MAX_VALID_BYTES) + 1) * 8 47 | ); 48 | } 49 | Err(_) => unreachable!(), 50 | } 51 | } 52 | } 53 | 54 | const U64_MAX_VALID_BYTES: u64 = u64::MAX / 8; 55 | 56 | // Maximum valid u64 input for BitLength. 57 | match BitLength::::from_byte_len(U64_MAX_VALID_BYTES) { 58 | Ok(bits) => assert_eq!(bits.as_bits(), u64::MAX & !0b111), 59 | Err(_) => unreachable!(), 60 | }; 61 | 62 | // Minimum invalid usize input for BitLength on 64-bit targets. 63 | assert!(BitLength::::from_byte_len(U64_MAX_VALID_BYTES + 1).is_err()); 64 | } 65 | -------------------------------------------------------------------------------- /src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | //! Integration tests for non-public APIs. 16 | 17 | mod bits_tests; 18 | -------------------------------------------------------------------------------- /tests/ecdsa_test_private_key_p256.p8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/ecdsa_test_private_key_p256.p8 -------------------------------------------------------------------------------- /tests/ecdsa_test_public_key_p256.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/ecdsa_test_public_key_p256.der -------------------------------------------------------------------------------- /tests/ecdsa_test_public_key_p256_debug.txt: -------------------------------------------------------------------------------- 1 | PublicKey("04fc116698a3e3236550c4c9efa9bd4d0619602a65d2930e9150ab33e84dbc83f8a6a6b9933f35ab59245e5b5a7af5dca76b33cbe7aeee5981b3ca350bebf52ecd") -------------------------------------------------------------------------------- /tests/ed25519_test_private_key.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/ed25519_test_private_key.bin -------------------------------------------------------------------------------- /tests/ed25519_test_private_key.p8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/ed25519_test_private_key.p8 -------------------------------------------------------------------------------- /tests/ed25519_test_public_key.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/ed25519_test_public_key.bin -------------------------------------------------------------------------------- /tests/ed25519_test_public_key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/ed25519_test_public_key.der -------------------------------------------------------------------------------- /tests/ed25519_verify_tests.txt: -------------------------------------------------------------------------------- 1 | # BoringSSL TEST(Ed25519Test Malleability) 2 | 3 | # Control; S is in range. 4 | MESSAGE = 54657374 5 | SIG = 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d 6 | PUB = 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 7 | Result = P 8 | 9 | # Same as above, but with the order L added to S so it is out of range. 10 | # BoringSSL commit 472ba2c2dd52d06a657a63b7fbf02732a6649d21 11 | MESSAGE = 54657374 12 | SIG = 7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab067654bce3832c2d76f8f6f5dafc08d9339d4eef676573336a5c51eb6f946b31d 13 | PUB = 7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa 14 | Result = F 15 | 16 | 17 | # BoringSSL commit 3094902fcdc2db2cc832fa854b9a6a8be383926c 18 | MESSAGE = 124e583f8b8eca58bb29c271b41d36986bbc45541f8e51f9cb0133eca447601e 19 | SIG = dac119d6ca87fc59ae611c157048f4d4fc932a149dbe20ec6effd1436abf83ea05c7df0fef06147241259113909bc71bd3c53ba4464ffcad3c0968f2ffffff0f 20 | PUB = 100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86 21 | Result = P 22 | 23 | # Control. Same key as above; same message and signature as below, except S is in range. 24 | PUB = 100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86 25 | MESSAGE = 6a0bc2b0057cedfc0fa2e3f7f7d39279b30f454a69dfd1117c758d86b19d85e0 26 | SIG = 0971f86d2c9c78582524a103cb9cf949522ae528f8054dc20107d999be673ff4f58ac9d20ec563133cabc6230b1db8625f8446639ede46ad4df4053000000000 27 | Result = P 28 | 29 | # Same key as above, but S is out of range. 30 | # BoringSSL commit 472ba2c2dd52d06a657a63b7fbf02732a6649d21 31 | PUB = 100fdf47fb94f1536a4f7c3fda27383fa03375a8f527c537e6f1703c47f94f86 32 | MESSAGE = 6a0bc2b0057cedfc0fa2e3f7f7d39279b30f454a69dfd1117c758d86b19d85e0 33 | SIG = 0971f86d2c9c78582524a103cb9cf949522ae528f8054dc20107d999be673ff4e25ebf2f2928766b1248bec6e91697775f8446639ede46ad4df4053000000010 34 | Result = F 35 | -------------------------------------------------------------------------------- /tests/error_tests.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | #[cfg(feature = "std")] 4 | #[test] 5 | fn error_impl_std_error_error_test() { 6 | use ring::error; 7 | #[allow(deprecated)] 8 | use ring::test; 9 | 10 | test::compile_time_assert_std_error_error::(); 11 | test::compile_time_assert_std_error_error::(); 12 | } 13 | -------------------------------------------------------------------------------- /tests/hkdf_tests.txt: -------------------------------------------------------------------------------- 1 | # Test Cases from RFC 5869. Note that the parameter L is implied by the length 2 | # of |OKM| and so it was omitted. 3 | 4 | # A.1. Test Case 1 = Basic test case with SHA-256 5 | Hash = SHA256 6 | IKM = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 7 | salt = 000102030405060708090a0b0c 8 | info = f0f1f2f3f4f5f6f7f8f9 9 | PRK = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5 10 | OKM = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865 11 | 12 | # A.2. Test Case 2 = Test with SHA-256 and longer inputs/outputs 13 | Hash = SHA256 14 | IKM = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f 15 | salt = 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf 16 | info = b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff 17 | PRK = 06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244 18 | OKM = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87 19 | 20 | # A.3. Test Case 3 = Test with SHA-256 and zero-length salt/info 21 | Hash = SHA256 22 | IKM = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 23 | salt = "" 24 | info = "" 25 | PRK = 19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04 26 | OKM = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8 27 | 28 | # Variants of the above tests. 29 | 30 | # Variant of A.1. with zero-length output 31 | Hash = SHA256 32 | IKM = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 33 | salt = 000102030405060708090a0b0c 34 | info = f0f1f2f3f4f5f6f7f8f9 35 | PRK = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5 36 | OKM = "" 37 | 38 | # Variant of A.1. with hash-length output 39 | Hash = SHA256 40 | IKM = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 41 | salt = 000102030405060708090a0b0c 42 | info = f0f1f2f3f4f5f6f7f8f9 43 | PRK = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5 44 | OKM = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf 45 | -------------------------------------------------------------------------------- /tests/quic_aes_128_tests.txt: -------------------------------------------------------------------------------- 1 | KEY = e8904ecc2e37a6e4cc02271e319c804b 2 | SAMPLE = 13484ec85dc4d36349697c7d4ea1a159 3 | MASK = 67387ebf3a 4 | 5 | KEY = e8904ecc2e37a6e4cc02271e319c804b 6 | SAMPLE = 00000000000000000000000fffffffff 7 | MASK = feb191f8af 8 | 9 | KEY = e8904ecc2e37a6e4cc02271e319c804b 10 | SAMPLE = 000000000000000fffffffffffffffff 11 | MASK = 6f23441ee8 12 | -------------------------------------------------------------------------------- /tests/quic_aes_256_tests.txt: -------------------------------------------------------------------------------- 1 | KEY = 85af7213814aec7b92ace6284a906643912ec8853d00d158a927b8697c7ff585 2 | SAMPLE = 82a0db90f4cee12fa4afeddb74396cf6 3 | MASK = 670897adf5 4 | 5 | KEY = 85af7213814aec7b92ace6284a906643912ec8853d00d158a927b8697c7ff585 6 | SAMPLE = 000000000000000000000000ffffffff 7 | MASK = b77a18bb3f 8 | 9 | KEY = 85af7213814aec7b92ace6284a906643912ec8853d00d158a927b8697c7ff585 10 | SAMPLE = 000000000000000fffffffffffffffff 11 | MASK = 4aadd3cbef 12 | -------------------------------------------------------------------------------- /tests/quic_chacha20_tests.txt: -------------------------------------------------------------------------------- 1 | KEY = 59bdff7a5bcdaacf319d99646c6273ad96687d2c74ace678f15a1c710675bb23 2 | SAMPLE = 215a7c1688b4ab7d830dcd052aef9f3c 3 | MASK = 6409a6196d 4 | -------------------------------------------------------------------------------- /tests/rand_tests.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2019 Brian Smith. 2 | // 3 | // Permission to use, copy, modify, and/or distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | #![allow(missing_docs)] 16 | 17 | use ring::rand::{self, SecureRandom as _}; 18 | #[allow(deprecated)] 19 | use ring::test; 20 | 21 | #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] 22 | use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure}; 23 | 24 | #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] 25 | wasm_bindgen_test_configure!(run_in_browser); 26 | 27 | #[test] 28 | fn test_system_random_lengths() { 29 | const LINUX_LIMIT: usize = 256; 30 | const WEB_LIMIT: usize = 65536; 31 | 32 | // Test that `fill` succeeds for various interesting lengths. `256` and 33 | // multiples thereof are interesting because that's an edge case for 34 | // `getrandom` on Linux. 35 | let lengths = [ 36 | 0, 37 | 1, 38 | 2, 39 | 3, 40 | 96, 41 | LINUX_LIMIT - 1, 42 | LINUX_LIMIT, 43 | LINUX_LIMIT + 1, 44 | LINUX_LIMIT * 2, 45 | 511, 46 | 512, 47 | 513, 48 | 4096, 49 | WEB_LIMIT - 1, 50 | WEB_LIMIT, 51 | WEB_LIMIT + 1, 52 | WEB_LIMIT * 2, 53 | ]; 54 | 55 | for len in lengths.iter() { 56 | let mut buf = vec![0; *len]; 57 | 58 | let rng = rand::SystemRandom::new(); 59 | assert!(rng.fill(&mut buf).is_ok()); 60 | 61 | // If `len` < 96 then there's a big chance of false positives, but 62 | // otherwise the likelihood of a false positive is so too low to 63 | // worry about. 64 | if *len >= 96 { 65 | assert!(buf.iter().any(|x| *x != 0)); 66 | } 67 | } 68 | } 69 | 70 | #[test] 71 | fn test_system_random_traits() { 72 | test::compile_time_assert_clone::(); 73 | test::compile_time_assert_send::(); 74 | 75 | assert_eq!( 76 | "SystemRandom(())", 77 | format!("{:?}", rand::SystemRandom::new()) 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /tests/rsa_test_private_key_2048.p8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/rsa_test_private_key_2048.p8 -------------------------------------------------------------------------------- /tests/rsa_test_public_key_2048.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/rsa_test_public_key_2048.der -------------------------------------------------------------------------------- /tests/rsa_test_public_key_2048_debug.txt: -------------------------------------------------------------------------------- 1 | PublicKey("3082010a0282010100c8a78500a5a250db8ed36c85b8dcf83c4be1953114faaac7616e0ea24922fa6b7ab01f85582c815cc3bdeb5ed46762bc536accaa8b72705b00cef316b2ec508fb9697241b9e34238419cccf7339eeb8b062147af4f5932f613d9bc0ae70bf6d56d4432e83e13767587531bfa9dd56531741244be75e8bc9226b9fa44b4b8a101358d7e8bb75d0c724a4f11ece77776263faefe79612eb1d71646e77e8982866be1400eafc3580d3139b41aaa7380187372f22e35bd55b288496165c881ed154d5811245c52d56cc09d4916d4f2a50bcf5ae0a2637f4cfa6bf9daafc113dba8383b6dd7da6dd8db22d8510a8d3115983308909a1a0332517aa55e896e154249b30203010001") -------------------------------------------------------------------------------- /tests/rsa_test_public_modulus.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/briansmith/ring/624969f9b2e3fb23e36a19741d726ec2433f55c3/tests/rsa_test_public_modulus.bin -------------------------------------------------------------------------------- /tests/signature_tests.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | use ring::signature; 4 | #[allow(deprecated)] 5 | use ring::test; 6 | 7 | #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] 8 | use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure}; 9 | 10 | #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] 11 | wasm_bindgen_test_configure!(run_in_browser); 12 | 13 | #[test] 14 | fn signature_impl_test() { 15 | test::compile_time_assert_clone::(); 16 | test::compile_time_assert_copy::(); 17 | test::compile_time_assert_send::(); 18 | test::compile_time_assert_sync::(); 19 | 20 | let unparsed_public_key = 21 | signature::UnparsedPublicKey::new(&signature::ED25519, &[0x01, 0x02, 0x03]); 22 | 23 | assert_eq!( 24 | format!("{:?}", unparsed_public_key), 25 | r#"UnparsedPublicKey { algorithm: ring::signature::ED25519, bytes: "010203" }"# 26 | ); 27 | 28 | // Test `AsRef<[u8]>` 29 | assert_eq!(unparsed_public_key.as_ref(), &[0x01, 0x02, 0x03]); 30 | } 31 | -------------------------------------------------------------------------------- /third_party/fiat/.gitattributes: -------------------------------------------------------------------------------- 1 | curve25519_32.h linguist-generated=true 2 | curve25519_64.h linguist-generated=true 3 | -------------------------------------------------------------------------------- /third_party/fiat/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of fiat-crypto authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as one of 6 | # Organization's name 7 | # Individual's name 8 | # Individual's name 9 | # See CONTRIBUTORS for the meaning of multiple email addresses. 10 | 11 | # Please keep the list sorted. 12 | 13 | Andres Erbsen 14 | Google Inc. 15 | Jade Philipoom 16 | Massachusetts Institute of Technology 17 | Zoe Paraskevopoulou -------------------------------------------------------------------------------- /third_party/fiat/LICENSE: -------------------------------------------------------------------------------- 1 | The Apache License, Version 2.0 (Apache-2.0) 2 | 3 | Copyright 2015-2020 the fiat-crypto authors (see the AUTHORS file) 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /third_party/fiat/METADATA: -------------------------------------------------------------------------------- 1 | name: "fiat" 2 | description: "Fiat-Crypto: Synthesizing Correct-by-Construction Code for Cryptographic Primitives." 3 | 4 | third_party { 5 | url { 6 | type: GIT 7 | value: "https://github.com/mit-plv/fiat-crypto" 8 | } 9 | version: "6ccc6638716d4632304baf1adbb5c47c3a12ea6f" 10 | last_upgrade_date { year: 2022 month: 3 day: 22 } 11 | 12 | local_modifications: "Files renamed to .h for BoringSSL integration. LICENSE file is LICENSE-MIT from upstream." 13 | } 14 | -------------------------------------------------------------------------------- /third_party/fiat/README.md: -------------------------------------------------------------------------------- 1 | # Fiat Cryptography 2 | 3 | The files in this directory are generated using [Fiat 4 | Cryptography](https://github.com/mit-plv/fiat-crypto) from the associated 5 | library of arithmetic-implementation templates. These files are included under 6 | the Apache 2.0 license. (See LICENSE file.) 7 | 8 | Some files are included directly from the `fiat-c/src` directory of the Fiat 9 | Cryptography repository. Their contents are `#include`d into source files, so 10 | we rename them to `.h`. Implementations that use saturated arithmetic on 64-bit 11 | words are further manually edited to use platform-appropriate incantations for 12 | operations such as addition with carry; these changes are marked with "`NOTE: 13 | edited after generation`". 14 | 15 | # CryptOpt 16 | 17 | Files in the `asm` directory are compiled from Fiat-Cryptography templates 18 | using [CryptOpt](https://github.com/0xADE1A1DE/CryptOpt). These generated 19 | assembly files have been edited to support call-stack unwinding. The modified 20 | files have been checked for functional correctness using the CryptOpt 21 | translation validator that is included in the Fiat-Cryptography repository. 22 | Correct unwinding and manual assembler-directive changes related to object-file 23 | conventions are validated using unit tests. 24 | --------------------------------------------------------------------------------