ring-native 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +3 -0
- data/README.md +22 -0
- data/Rakefile +1 -0
- data/ext/ring/extconf.rb +29 -0
- data/lib/ring/native.rb +8 -0
- data/lib/ring/native/version.rb +5 -0
- data/ring-native.gemspec +25 -0
- data/vendor/ring/BUILDING.md +40 -0
- data/vendor/ring/Cargo.toml +43 -0
- data/vendor/ring/LICENSE +185 -0
- data/vendor/ring/Makefile +35 -0
- data/vendor/ring/PORTING.md +163 -0
- data/vendor/ring/README.md +113 -0
- data/vendor/ring/STYLE.md +197 -0
- data/vendor/ring/appveyor.yml +27 -0
- data/vendor/ring/build.rs +108 -0
- data/vendor/ring/crypto/aes/aes.c +1142 -0
- data/vendor/ring/crypto/aes/aes_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/aes/aes_test.cc +93 -0
- data/vendor/ring/crypto/aes/asm/aes-586.pl +2368 -0
- data/vendor/ring/crypto/aes/asm/aes-armv4.pl +1249 -0
- data/vendor/ring/crypto/aes/asm/aes-x86_64.pl +2246 -0
- data/vendor/ring/crypto/aes/asm/aesni-x86.pl +1318 -0
- data/vendor/ring/crypto/aes/asm/aesni-x86_64.pl +2084 -0
- data/vendor/ring/crypto/aes/asm/aesv8-armx.pl +675 -0
- data/vendor/ring/crypto/aes/asm/bsaes-armv7.pl +1364 -0
- data/vendor/ring/crypto/aes/asm/bsaes-x86_64.pl +1565 -0
- data/vendor/ring/crypto/aes/asm/vpaes-x86.pl +841 -0
- data/vendor/ring/crypto/aes/asm/vpaes-x86_64.pl +1116 -0
- data/vendor/ring/crypto/aes/internal.h +87 -0
- data/vendor/ring/crypto/aes/mode_wrappers.c +61 -0
- data/vendor/ring/crypto/bn/add.c +394 -0
- data/vendor/ring/crypto/bn/asm/armv4-mont.pl +694 -0
- data/vendor/ring/crypto/bn/asm/armv8-mont.pl +1503 -0
- data/vendor/ring/crypto/bn/asm/bn-586.pl +774 -0
- data/vendor/ring/crypto/bn/asm/co-586.pl +287 -0
- data/vendor/ring/crypto/bn/asm/rsaz-avx2.pl +1882 -0
- data/vendor/ring/crypto/bn/asm/x86-mont.pl +592 -0
- data/vendor/ring/crypto/bn/asm/x86_64-gcc.c +599 -0
- data/vendor/ring/crypto/bn/asm/x86_64-mont.pl +1393 -0
- data/vendor/ring/crypto/bn/asm/x86_64-mont5.pl +3507 -0
- data/vendor/ring/crypto/bn/bn.c +352 -0
- data/vendor/ring/crypto/bn/bn_asn1.c +74 -0
- data/vendor/ring/crypto/bn/bn_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/bn/bn_test.cc +1696 -0
- data/vendor/ring/crypto/bn/cmp.c +200 -0
- data/vendor/ring/crypto/bn/convert.c +433 -0
- data/vendor/ring/crypto/bn/ctx.c +311 -0
- data/vendor/ring/crypto/bn/div.c +594 -0
- data/vendor/ring/crypto/bn/exponentiation.c +1335 -0
- data/vendor/ring/crypto/bn/gcd.c +711 -0
- data/vendor/ring/crypto/bn/generic.c +1019 -0
- data/vendor/ring/crypto/bn/internal.h +316 -0
- data/vendor/ring/crypto/bn/montgomery.c +516 -0
- data/vendor/ring/crypto/bn/mul.c +888 -0
- data/vendor/ring/crypto/bn/prime.c +829 -0
- data/vendor/ring/crypto/bn/random.c +334 -0
- data/vendor/ring/crypto/bn/rsaz_exp.c +262 -0
- data/vendor/ring/crypto/bn/rsaz_exp.h +53 -0
- data/vendor/ring/crypto/bn/shift.c +276 -0
- data/vendor/ring/crypto/bytestring/bytestring_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/bytestring/bytestring_test.cc +421 -0
- data/vendor/ring/crypto/bytestring/cbb.c +399 -0
- data/vendor/ring/crypto/bytestring/cbs.c +227 -0
- data/vendor/ring/crypto/bytestring/internal.h +46 -0
- data/vendor/ring/crypto/chacha/chacha_generic.c +140 -0
- data/vendor/ring/crypto/chacha/chacha_vec.c +323 -0
- data/vendor/ring/crypto/chacha/chacha_vec_arm.S +1447 -0
- data/vendor/ring/crypto/chacha/chacha_vec_arm_generate.go +153 -0
- data/vendor/ring/crypto/cipher/cipher_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/cipher/e_aes.c +390 -0
- data/vendor/ring/crypto/cipher/e_chacha20poly1305.c +208 -0
- data/vendor/ring/crypto/cipher/internal.h +173 -0
- data/vendor/ring/crypto/cipher/test/aes_128_gcm_tests.txt +543 -0
- data/vendor/ring/crypto/cipher/test/aes_128_key_wrap_tests.txt +9 -0
- data/vendor/ring/crypto/cipher/test/aes_256_gcm_tests.txt +475 -0
- data/vendor/ring/crypto/cipher/test/aes_256_key_wrap_tests.txt +23 -0
- data/vendor/ring/crypto/cipher/test/chacha20_poly1305_old_tests.txt +422 -0
- data/vendor/ring/crypto/cipher/test/chacha20_poly1305_tests.txt +484 -0
- data/vendor/ring/crypto/cipher/test/cipher_test.txt +100 -0
- data/vendor/ring/crypto/constant_time_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/constant_time_test.c +304 -0
- data/vendor/ring/crypto/cpu-arm-asm.S +32 -0
- data/vendor/ring/crypto/cpu-arm.c +199 -0
- data/vendor/ring/crypto/cpu-intel.c +261 -0
- data/vendor/ring/crypto/crypto.c +151 -0
- data/vendor/ring/crypto/curve25519/asm/x25519-arm.S +2118 -0
- data/vendor/ring/crypto/curve25519/curve25519.c +4888 -0
- data/vendor/ring/crypto/curve25519/x25519_test.cc +128 -0
- data/vendor/ring/crypto/digest/md32_common.h +181 -0
- data/vendor/ring/crypto/ec/asm/p256-x86_64-asm.pl +2725 -0
- data/vendor/ring/crypto/ec/ec.c +193 -0
- data/vendor/ring/crypto/ec/ec_curves.c +61 -0
- data/vendor/ring/crypto/ec/ec_key.c +228 -0
- data/vendor/ring/crypto/ec/ec_montgomery.c +114 -0
- data/vendor/ring/crypto/ec/example_mul.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/ec/internal.h +243 -0
- data/vendor/ring/crypto/ec/oct.c +253 -0
- data/vendor/ring/crypto/ec/p256-64.c +1794 -0
- data/vendor/ring/crypto/ec/p256-x86_64-table.h +9548 -0
- data/vendor/ring/crypto/ec/p256-x86_64.c +509 -0
- data/vendor/ring/crypto/ec/simple.c +1007 -0
- data/vendor/ring/crypto/ec/util-64.c +183 -0
- data/vendor/ring/crypto/ec/wnaf.c +508 -0
- data/vendor/ring/crypto/ecdh/ecdh.c +155 -0
- data/vendor/ring/crypto/ecdsa/ecdsa.c +304 -0
- data/vendor/ring/crypto/ecdsa/ecdsa_asn1.c +193 -0
- data/vendor/ring/crypto/ecdsa/ecdsa_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/ecdsa/ecdsa_test.cc +327 -0
- data/vendor/ring/crypto/header_removed.h +17 -0
- data/vendor/ring/crypto/internal.h +495 -0
- data/vendor/ring/crypto/libring.Windows.vcxproj +101 -0
- data/vendor/ring/crypto/mem.c +98 -0
- data/vendor/ring/crypto/modes/asm/aesni-gcm-x86_64.pl +1045 -0
- data/vendor/ring/crypto/modes/asm/ghash-armv4.pl +517 -0
- data/vendor/ring/crypto/modes/asm/ghash-x86.pl +1393 -0
- data/vendor/ring/crypto/modes/asm/ghash-x86_64.pl +1741 -0
- data/vendor/ring/crypto/modes/asm/ghashv8-armx.pl +422 -0
- data/vendor/ring/crypto/modes/ctr.c +226 -0
- data/vendor/ring/crypto/modes/gcm.c +1206 -0
- data/vendor/ring/crypto/modes/gcm_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/modes/gcm_test.c +348 -0
- data/vendor/ring/crypto/modes/internal.h +299 -0
- data/vendor/ring/crypto/perlasm/arm-xlate.pl +170 -0
- data/vendor/ring/crypto/perlasm/readme +100 -0
- data/vendor/ring/crypto/perlasm/x86_64-xlate.pl +1164 -0
- data/vendor/ring/crypto/perlasm/x86asm.pl +292 -0
- data/vendor/ring/crypto/perlasm/x86gas.pl +263 -0
- data/vendor/ring/crypto/perlasm/x86masm.pl +200 -0
- data/vendor/ring/crypto/perlasm/x86nasm.pl +187 -0
- data/vendor/ring/crypto/poly1305/poly1305.c +331 -0
- data/vendor/ring/crypto/poly1305/poly1305_arm.c +301 -0
- data/vendor/ring/crypto/poly1305/poly1305_arm_asm.S +2015 -0
- data/vendor/ring/crypto/poly1305/poly1305_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/poly1305/poly1305_test.cc +80 -0
- data/vendor/ring/crypto/poly1305/poly1305_test.txt +52 -0
- data/vendor/ring/crypto/poly1305/poly1305_vec.c +892 -0
- data/vendor/ring/crypto/rand/asm/rdrand-x86_64.pl +75 -0
- data/vendor/ring/crypto/rand/internal.h +32 -0
- data/vendor/ring/crypto/rand/rand.c +189 -0
- data/vendor/ring/crypto/rand/urandom.c +219 -0
- data/vendor/ring/crypto/rand/windows.c +56 -0
- data/vendor/ring/crypto/refcount_c11.c +66 -0
- data/vendor/ring/crypto/refcount_lock.c +53 -0
- data/vendor/ring/crypto/refcount_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/refcount_test.c +58 -0
- data/vendor/ring/crypto/rsa/blinding.c +462 -0
- data/vendor/ring/crypto/rsa/internal.h +108 -0
- data/vendor/ring/crypto/rsa/padding.c +300 -0
- data/vendor/ring/crypto/rsa/rsa.c +450 -0
- data/vendor/ring/crypto/rsa/rsa_asn1.c +261 -0
- data/vendor/ring/crypto/rsa/rsa_impl.c +944 -0
- data/vendor/ring/crypto/rsa/rsa_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/rsa/rsa_test.cc +437 -0
- data/vendor/ring/crypto/sha/asm/sha-armv8.pl +436 -0
- data/vendor/ring/crypto/sha/asm/sha-x86_64.pl +2390 -0
- data/vendor/ring/crypto/sha/asm/sha256-586.pl +1275 -0
- data/vendor/ring/crypto/sha/asm/sha256-armv4.pl +735 -0
- data/vendor/ring/crypto/sha/asm/sha256-armv8.pl +14 -0
- data/vendor/ring/crypto/sha/asm/sha256-x86_64.pl +14 -0
- data/vendor/ring/crypto/sha/asm/sha512-586.pl +911 -0
- data/vendor/ring/crypto/sha/asm/sha512-armv4.pl +666 -0
- data/vendor/ring/crypto/sha/asm/sha512-armv8.pl +14 -0
- data/vendor/ring/crypto/sha/asm/sha512-x86_64.pl +14 -0
- data/vendor/ring/crypto/sha/sha1.c +271 -0
- data/vendor/ring/crypto/sha/sha256.c +204 -0
- data/vendor/ring/crypto/sha/sha512.c +355 -0
- data/vendor/ring/crypto/test/file_test.cc +326 -0
- data/vendor/ring/crypto/test/file_test.h +181 -0
- data/vendor/ring/crypto/test/malloc.cc +150 -0
- data/vendor/ring/crypto/test/scoped_types.h +95 -0
- data/vendor/ring/crypto/test/test.Windows.vcxproj +35 -0
- data/vendor/ring/crypto/test/test_util.cc +46 -0
- data/vendor/ring/crypto/test/test_util.h +41 -0
- data/vendor/ring/crypto/thread_none.c +55 -0
- data/vendor/ring/crypto/thread_pthread.c +165 -0
- data/vendor/ring/crypto/thread_test.Windows.vcxproj +25 -0
- data/vendor/ring/crypto/thread_test.c +200 -0
- data/vendor/ring/crypto/thread_win.c +282 -0
- data/vendor/ring/examples/checkdigest.rs +103 -0
- data/vendor/ring/include/openssl/aes.h +121 -0
- data/vendor/ring/include/openssl/arm_arch.h +129 -0
- data/vendor/ring/include/openssl/base.h +156 -0
- data/vendor/ring/include/openssl/bn.h +794 -0
- data/vendor/ring/include/openssl/buffer.h +18 -0
- data/vendor/ring/include/openssl/bytestring.h +235 -0
- data/vendor/ring/include/openssl/chacha.h +37 -0
- data/vendor/ring/include/openssl/cmac.h +76 -0
- data/vendor/ring/include/openssl/cpu.h +184 -0
- data/vendor/ring/include/openssl/crypto.h +43 -0
- data/vendor/ring/include/openssl/curve25519.h +88 -0
- data/vendor/ring/include/openssl/ec.h +225 -0
- data/vendor/ring/include/openssl/ec_key.h +129 -0
- data/vendor/ring/include/openssl/ecdh.h +110 -0
- data/vendor/ring/include/openssl/ecdsa.h +156 -0
- data/vendor/ring/include/openssl/err.h +201 -0
- data/vendor/ring/include/openssl/mem.h +101 -0
- data/vendor/ring/include/openssl/obj_mac.h +71 -0
- data/vendor/ring/include/openssl/opensslfeatures.h +68 -0
- data/vendor/ring/include/openssl/opensslv.h +18 -0
- data/vendor/ring/include/openssl/ossl_typ.h +18 -0
- data/vendor/ring/include/openssl/poly1305.h +51 -0
- data/vendor/ring/include/openssl/rand.h +70 -0
- data/vendor/ring/include/openssl/rsa.h +399 -0
- data/vendor/ring/include/openssl/thread.h +133 -0
- data/vendor/ring/include/openssl/type_check.h +71 -0
- data/vendor/ring/mk/Common.props +63 -0
- data/vendor/ring/mk/Windows.props +42 -0
- data/vendor/ring/mk/WindowsTest.props +18 -0
- data/vendor/ring/mk/appveyor.bat +62 -0
- data/vendor/ring/mk/bottom_of_makefile.mk +54 -0
- data/vendor/ring/mk/ring.mk +266 -0
- data/vendor/ring/mk/top_of_makefile.mk +214 -0
- data/vendor/ring/mk/travis.sh +40 -0
- data/vendor/ring/mk/update-travis-yml.py +229 -0
- data/vendor/ring/ring.sln +153 -0
- data/vendor/ring/src/aead.rs +682 -0
- data/vendor/ring/src/agreement.rs +248 -0
- data/vendor/ring/src/c.rs +129 -0
- data/vendor/ring/src/constant_time.rs +37 -0
- data/vendor/ring/src/der.rs +96 -0
- data/vendor/ring/src/digest.rs +690 -0
- data/vendor/ring/src/digest_tests.txt +57 -0
- data/vendor/ring/src/ecc.rs +28 -0
- data/vendor/ring/src/ecc_build.rs +279 -0
- data/vendor/ring/src/ecc_curves.rs +117 -0
- data/vendor/ring/src/ed25519_tests.txt +2579 -0
- data/vendor/ring/src/exe_tests.rs +46 -0
- data/vendor/ring/src/ffi.rs +29 -0
- data/vendor/ring/src/file_test.rs +187 -0
- data/vendor/ring/src/hkdf.rs +153 -0
- data/vendor/ring/src/hkdf_tests.txt +59 -0
- data/vendor/ring/src/hmac.rs +414 -0
- data/vendor/ring/src/hmac_tests.txt +97 -0
- data/vendor/ring/src/input.rs +312 -0
- data/vendor/ring/src/lib.rs +41 -0
- data/vendor/ring/src/pbkdf2.rs +265 -0
- data/vendor/ring/src/pbkdf2_tests.txt +113 -0
- data/vendor/ring/src/polyfill.rs +57 -0
- data/vendor/ring/src/rand.rs +28 -0
- data/vendor/ring/src/signature.rs +314 -0
- data/vendor/ring/third-party/NIST/README.md +9 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA1LongMsg.rsp +263 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA1Monte.rsp +309 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA1ShortMsg.rsp +267 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA224LongMsg.rsp +263 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA224Monte.rsp +309 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA224ShortMsg.rsp +267 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA256LongMsg.rsp +263 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA256Monte.rsp +309 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA256ShortMsg.rsp +267 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA384LongMsg.rsp +519 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA384Monte.rsp +309 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA384ShortMsg.rsp +523 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA512LongMsg.rsp +519 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA512Monte.rsp +309 -0
- data/vendor/ring/third-party/NIST/SHAVS/SHA512ShortMsg.rsp +523 -0
- data/vendor/ring/third-party/NIST/sha256sums.txt +1 -0
- metadata +333 -0
|
@@ -0,0 +1,312 @@
|
|
|
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 AUTHORS DISCLAIM ALL WARRANTIES
|
|
8
|
+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
|
10
|
+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
|
|
15
|
+
//! The Input/Reader framework for safe, fast, zero-heap-usage protocol parsing.
|
|
16
|
+
//!
|
|
17
|
+
//! The Input/Reader framework goes beyond Rust's normal safety guarantees by
|
|
18
|
+
//! also guaranteeing that parsing will be panic-free, as long as
|
|
19
|
+
//! `Input::as_slice_less_safe` is not used. It avoids copying data and heap
|
|
20
|
+
//! allocation and strives to prevent common pitfalls such as accidentally
|
|
21
|
+
//! parsing input bytes multiple times. In order to meet these goals, the
|
|
22
|
+
//! Input/Reader framework is limited in functionality such that it works best
|
|
23
|
+
//! for input languages with a small fixed amount of lookahead such as ASN.1,
|
|
24
|
+
//! TLS, TCP/IP, and many other networking, IPC, and related protocols.
|
|
25
|
+
//! Input languages that require more lookahead and/or backtracking require
|
|
26
|
+
//! some significant contortions to parse using this framework. It would not be
|
|
27
|
+
//! realistic to use it for parsing programming language code or natural
|
|
28
|
+
//! language text, for example.
|
|
29
|
+
//!
|
|
30
|
+
//! The overall pattern for using the Input/Reader framework is:
|
|
31
|
+
//!
|
|
32
|
+
//! 1. Write a recursive-descent-style parser for the input language, where the
|
|
33
|
+
//! input data is given as a `&mut Reader` parameter to each function. Each
|
|
34
|
+
//! function should have a return type of `Result<V, E>` for some value type
|
|
35
|
+
//! `V` and some error type `E`, either or both of which may be `()`.
|
|
36
|
+
//! Functions for parsing the lowest-level language constructs should be
|
|
37
|
+
//! defined. Those lowest-level functions will parse their inputs using
|
|
38
|
+
//! `Reader::read_byte`, `Reader::peek`, and similar functions. Higher-level
|
|
39
|
+
//! language constructs are then parsed by calling the lower-level functions
|
|
40
|
+
//! in sequence.
|
|
41
|
+
//!
|
|
42
|
+
//! 2. Wrap the top-most functions of your recursive-descent parser in
|
|
43
|
+
//! functions that take their input data as an `Input`. The wrapper
|
|
44
|
+
//! functions should pass the `Input` to `read_all` or one of the variants.
|
|
45
|
+
//! The wrapper functions are the only ones that should be exposed outside
|
|
46
|
+
//! the parser's module.
|
|
47
|
+
//!
|
|
48
|
+
//! 3. After receiving the input data to parse, wrap it in an `Input` using
|
|
49
|
+
//! `Input::new` as early as possible. Pass the `Input` to the wrapper
|
|
50
|
+
//! functions when they need to be parsed.
|
|
51
|
+
//!
|
|
52
|
+
//! In general parsers built using `Reader` do not need to explicitly check
|
|
53
|
+
//! for end-of-input unless they are parsing optional constructs, because
|
|
54
|
+
//! `Reader::read_byte()` will return `Err(())` on end-of-input. Similarly,
|
|
55
|
+
//! parsers using `Reader` generally don't need to check for extra junk at the
|
|
56
|
+
//! end of the input as long as the parser's API uses the pattern described
|
|
57
|
+
//! above, as `read_all` and its variants automatically check for trailing
|
|
58
|
+
//! junk. `Reader::skip_to_end` should be used when the end of the input should
|
|
59
|
+
//! be ignored without triggering an error.
|
|
60
|
+
//!
|
|
61
|
+
//! The Input/Reader framework works best when all processing of the input data
|
|
62
|
+
//! is done through the `Input` and `Reader` types. In particular, avoid trying
|
|
63
|
+
//! to parse input data using functions that take slices. However, when you
|
|
64
|
+
//! need to access a part of the input data as a slice,
|
|
65
|
+
//! `Input::as_slice_less_safe` can be used. *ring* is in the process of
|
|
66
|
+
//! migrating fully to using `Input` for all inputs to the crypto functions,
|
|
67
|
+
//! which means that `Input::as_slice_less_safe` currently needs to be used
|
|
68
|
+
//! frequently to use *ring*'s crypto functionality. This will change soon.
|
|
69
|
+
//!
|
|
70
|
+
//! [libwebpki](https://github.com/briansmith/webpki)'s X.509 certificate
|
|
71
|
+
//! parser is a good example of a real-world use of the Input/Reader framework
|
|
72
|
+
//! to parse complex data.
|
|
73
|
+
|
|
74
|
+
use std;
|
|
75
|
+
|
|
76
|
+
/// Calls `read` with the given input as a `Reader`, ensuring that `read`
|
|
77
|
+
/// consumed the entire input. If `read` does not consume the entire input,
|
|
78
|
+
/// `incomplete_read` is returned.
|
|
79
|
+
pub fn read_all<'a, F, R, E>(input: Input<'a>, incomplete_read: E, read: F)
|
|
80
|
+
-> Result<R, E>
|
|
81
|
+
where F: FnOnce(&mut Reader<'a>) -> Result<R, E> {
|
|
82
|
+
let mut input = Reader::new(input);
|
|
83
|
+
let result = try!(read(&mut input));
|
|
84
|
+
if input.at_end() {
|
|
85
|
+
Ok(result)
|
|
86
|
+
} else {
|
|
87
|
+
Err(incomplete_read)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Like `read_all`, except taking an `FnMut`.
|
|
92
|
+
pub fn read_all_mut<'a, F, R, E>(input: Input<'a>, incomplete_read: E, mut read: F)
|
|
93
|
+
-> Result<R, E>
|
|
94
|
+
where F: FnMut(&mut Reader<'a>)
|
|
95
|
+
-> Result<R, E> {
|
|
96
|
+
let mut input = Reader::new(input);
|
|
97
|
+
let result = try!(read(&mut input));
|
|
98
|
+
if input.at_end() {
|
|
99
|
+
Ok(result)
|
|
100
|
+
} else {
|
|
101
|
+
Err(incomplete_read)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// Calls `read` with the given input as a `Reader`, ensuring that `read`
|
|
106
|
+
/// consumed the entire input. When `input` is `None`, `read` will be called
|
|
107
|
+
/// with `None`.
|
|
108
|
+
pub fn read_all_optional<'a, F, R, E>(input: Option<Input<'a>>,
|
|
109
|
+
incomplete_read: E, read: F)
|
|
110
|
+
-> Result<R, E>
|
|
111
|
+
where F: FnOnce(Option<&mut Reader>)
|
|
112
|
+
-> Result<R, E> {
|
|
113
|
+
match input {
|
|
114
|
+
Some(input) => {
|
|
115
|
+
let mut input = Reader::new(input);
|
|
116
|
+
let result = try!(read(Option::Some(&mut input)));
|
|
117
|
+
if input.at_end() {
|
|
118
|
+
Ok(result)
|
|
119
|
+
} else {
|
|
120
|
+
Err(incomplete_read)
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
None => read(Option::None)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/// A wrapper around `&'a [u8]` that helps in writing panic-free code.
|
|
128
|
+
///
|
|
129
|
+
/// No methods of `Input` will ever panic.
|
|
130
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
131
|
+
pub struct Input<'a> {
|
|
132
|
+
value: no_panic::NoPanicSlice<'a>
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
impl<'a> Input<'a> {
|
|
136
|
+
/// Construct a new `Input` for the given input `bytes`.
|
|
137
|
+
pub fn new(bytes: &'a [u8]) -> Result<Input<'a>, ()> {
|
|
138
|
+
// This limit is important for avoiding integer overflow. In particular,
|
|
139
|
+
// `Reader` assumes that an `i + 1 > i` if `input.value.get(i)` does
|
|
140
|
+
// not return `None`.
|
|
141
|
+
if bytes.len() > std::usize::MAX - 1 {
|
|
142
|
+
return Err(())
|
|
143
|
+
}
|
|
144
|
+
Ok(Input { value: no_panic::NoPanicSlice::new(bytes) })
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/// Returns `true` if the input is empty and false otherwise.
|
|
148
|
+
#[inline]
|
|
149
|
+
pub fn is_empty(&self) -> bool { self.value.len() == 0 }
|
|
150
|
+
|
|
151
|
+
/// Returns the length of the `Input`.
|
|
152
|
+
#[inline]
|
|
153
|
+
pub fn len(&self) -> usize { self.value.len() }
|
|
154
|
+
|
|
155
|
+
/// Access the input as a slice so it can be processed by functions that
|
|
156
|
+
/// are not written using the Input/Reader framework.
|
|
157
|
+
#[inline]
|
|
158
|
+
pub fn as_slice_less_safe(&self) -> &'a [u8] {
|
|
159
|
+
self.value.as_slice_less_safe()
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/// Returns `true` if the contents of `Input` `a` are equal to the contents of
|
|
164
|
+
/// slice `b`, and `false` otherwise.
|
|
165
|
+
#[inline]
|
|
166
|
+
pub fn input_equals(a: Input, b: &[u8]) -> bool {
|
|
167
|
+
a.value.as_slice_less_safe() == b
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// A read-only, forward-only* cursor into the data in an `Input`.
|
|
171
|
+
///
|
|
172
|
+
/// Using `Reader` to parse input helps to ensure that no byte of the input
|
|
173
|
+
/// will be accidentally processed more than once. Using `Reader` in
|
|
174
|
+
/// conjunction with `read_all`, `read_all_mut`, and `read_all_optional`
|
|
175
|
+
/// helps ensure that no byte of the input is accidentally left unprocessed.
|
|
176
|
+
/// The methods of `Reader` never panic, so `Reader` also assists the writing
|
|
177
|
+
/// of panic-free code.
|
|
178
|
+
///
|
|
179
|
+
/// \* `Reader` is not strictly forward-only because of the method
|
|
180
|
+
/// `get_input_between_marks`, which is provided mainly to support calculating
|
|
181
|
+
/// digests over parsed data.
|
|
182
|
+
#[derive(Debug)]
|
|
183
|
+
pub struct Reader<'a> {
|
|
184
|
+
input: no_panic::NoPanicSlice<'a>,
|
|
185
|
+
i: usize
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/// An index into the already-parsed input of a `Reader`.
|
|
189
|
+
pub struct Mark {
|
|
190
|
+
i: usize
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
impl<'a> Reader<'a> {
|
|
194
|
+
/// Construct a new Reader for the given input. Use `read_all`,
|
|
195
|
+
/// `read_all_mut`, or `read_all_optional` instead of `Reader::new`
|
|
196
|
+
/// whenever possible.
|
|
197
|
+
#[inline]
|
|
198
|
+
pub fn new(input: Input<'a>) -> Reader<'a> {
|
|
199
|
+
Reader { input: input.value, i: 0 }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// Returns `true` if the reader is at the end of the input, and `false`
|
|
203
|
+
/// otherwise.
|
|
204
|
+
#[inline]
|
|
205
|
+
pub fn at_end(&self) -> bool { self.i == self.input.len() }
|
|
206
|
+
|
|
207
|
+
/// Returns an `Input` for already-parsed input that has had its boundaries
|
|
208
|
+
/// marked using `mark`.
|
|
209
|
+
#[inline]
|
|
210
|
+
pub fn get_input_between_marks(&self, mark1: Mark, mark2: Mark)
|
|
211
|
+
-> Result<Input<'a>, ()> {
|
|
212
|
+
self.input.subslice(mark1.i, mark2.i)
|
|
213
|
+
.map(|subslice| Input { value: subslice })
|
|
214
|
+
.ok_or(())
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/// Return the current position of the `Reader` for future use in a call
|
|
218
|
+
/// to `get_input_between_marks`.
|
|
219
|
+
#[inline]
|
|
220
|
+
pub fn mark(&self) -> Mark { Mark { i: self.i } }
|
|
221
|
+
|
|
222
|
+
/// Returns `true` if there is at least one more byte in the input and that
|
|
223
|
+
/// byte is equal to `b`, and false otherwise.
|
|
224
|
+
pub fn peek(&self, b: u8) -> bool {
|
|
225
|
+
match self.input.get(self.i) {
|
|
226
|
+
Some(actual_b) => return b == *actual_b,
|
|
227
|
+
None => false
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// Reads the next input byte.
|
|
232
|
+
///
|
|
233
|
+
/// Returns `Ok(b)` where `b` is the next input byte, or `Err(())` if the
|
|
234
|
+
/// `Reader` is at the end of the input.
|
|
235
|
+
pub fn read_byte(&mut self) -> Result<u8, ()> {
|
|
236
|
+
match self.input.get(self.i) {
|
|
237
|
+
Some(b) => {
|
|
238
|
+
self.i += 1; // safe from overflow; see Input::new.
|
|
239
|
+
Ok(*b)
|
|
240
|
+
}
|
|
241
|
+
None => Err(())
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// Skips `num_bytes` of the input.
|
|
246
|
+
///
|
|
247
|
+
/// Returns `Ok(())` if there are at least `num_bytes` of input remaining,
|
|
248
|
+
/// and `Err(())` otherwise.
|
|
249
|
+
pub fn skip(&mut self, num_bytes: usize) -> Result<(), ()> {
|
|
250
|
+
self.skip_and_get_input(num_bytes).map(|_| ())
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// Skips `num_bytes` of the input, returning the skipped input as an `Input`.
|
|
254
|
+
///
|
|
255
|
+
/// Returns `Ok(i)` where `i` is an `Input` if there are at least
|
|
256
|
+
/// `num_bytes` of input remaining, and `Err(())` otherwise.
|
|
257
|
+
pub fn skip_and_get_input(&mut self, num_bytes: usize)
|
|
258
|
+
-> Result<Input<'a>, ()> {
|
|
259
|
+
match self.i.checked_add(num_bytes) {
|
|
260
|
+
Some(new_i) => {
|
|
261
|
+
let ret = self.input.subslice(self.i, new_i)
|
|
262
|
+
.map(|subslice| Input { value: subslice })
|
|
263
|
+
.ok_or(());
|
|
264
|
+
self.i = new_i;
|
|
265
|
+
ret
|
|
266
|
+
},
|
|
267
|
+
_ => Err(())
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// Skips the reader to the end of the input, returning the skipped input
|
|
272
|
+
/// as an `Input`.
|
|
273
|
+
pub fn skip_to_end(&mut self) -> Input<'a> {
|
|
274
|
+
let to_skip = self.input.len() - self.i;
|
|
275
|
+
self.skip_and_get_input(to_skip).unwrap()
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
mod no_panic {
|
|
280
|
+
|
|
281
|
+
/// A wrapper around a slice that exposes no functions that can panic.
|
|
282
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
283
|
+
pub struct NoPanicSlice<'a> {
|
|
284
|
+
bytes: &'a [u8]
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
impl<'a> NoPanicSlice<'a> {
|
|
288
|
+
#[inline]
|
|
289
|
+
pub fn new(bytes: &'a [u8]) -> NoPanicSlice<'a> {
|
|
290
|
+
NoPanicSlice { bytes: bytes }
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
#[inline]
|
|
294
|
+
pub fn get(&self, i: usize) -> Option<&u8> { self.bytes.get(i) }
|
|
295
|
+
|
|
296
|
+
#[inline]
|
|
297
|
+
pub fn len(&self) -> usize { self.bytes.len() }
|
|
298
|
+
|
|
299
|
+
#[inline]
|
|
300
|
+
pub fn subslice(&self, start: usize, end: usize) -> Option<NoPanicSlice<'a>> {
|
|
301
|
+
if start <= end && end <= self.bytes.len() {
|
|
302
|
+
Some(NoPanicSlice::new(&self.bytes[start..end]))
|
|
303
|
+
} else {
|
|
304
|
+
None
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
#[inline]
|
|
309
|
+
pub fn as_slice_less_safe(&self) -> &'a [u8] { self.bytes }
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
} // mod no_panic
|
|
@@ -0,0 +1,41 @@
|
|
|
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 AUTHORS DISCLAIM ALL WARRANTIES
|
|
8
|
+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
|
10
|
+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
|
|
15
|
+
#[cfg(test)]
|
|
16
|
+
extern crate rustc_serialize;
|
|
17
|
+
|
|
18
|
+
pub mod aead;
|
|
19
|
+
pub mod agreement;
|
|
20
|
+
mod c;
|
|
21
|
+
pub mod constant_time;
|
|
22
|
+
|
|
23
|
+
#[doc(hidden)]
|
|
24
|
+
pub mod der;
|
|
25
|
+
|
|
26
|
+
pub mod digest;
|
|
27
|
+
mod ecc;
|
|
28
|
+
mod ffi;
|
|
29
|
+
pub mod hkdf;
|
|
30
|
+
pub mod hmac;
|
|
31
|
+
pub mod input;
|
|
32
|
+
pub mod pbkdf2;
|
|
33
|
+
mod polyfill;
|
|
34
|
+
pub mod rand;
|
|
35
|
+
pub mod signature;
|
|
36
|
+
|
|
37
|
+
#[cfg(test)]
|
|
38
|
+
mod exe_tests;
|
|
39
|
+
|
|
40
|
+
#[cfg(test)]
|
|
41
|
+
mod file_test;
|
|
@@ -0,0 +1,265 @@
|
|
|
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 AUTHORS DISCLAIM ALL WARRANTIES
|
|
8
|
+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
|
10
|
+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
|
|
15
|
+
//! PBKDF2 derivation and verification.
|
|
16
|
+
//!
|
|
17
|
+
//! Use `derive` to derive PBKDF2 outputs. Use `verify` to verify secret
|
|
18
|
+
//! against previously-derived outputs.
|
|
19
|
+
//!
|
|
20
|
+
//! PBKDF2 is specified in
|
|
21
|
+
//! [RFC 2898 Section 5.2](https://tools.ietf.org/html/rfc2898#section-5.2)
|
|
22
|
+
//! with test vectors given in [RFC 6070](https://tools.ietf.org/html/rfc6070).
|
|
23
|
+
//! See also [NIST Special Publication
|
|
24
|
+
//! 800-132](http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf).
|
|
25
|
+
//!
|
|
26
|
+
//! # Examples
|
|
27
|
+
//!
|
|
28
|
+
//! ## Password Database Example
|
|
29
|
+
//!
|
|
30
|
+
//! ```
|
|
31
|
+
//! use ring::pbkdf2;
|
|
32
|
+
//! use std::collections::HashMap;
|
|
33
|
+
//!
|
|
34
|
+
//! static PBKDF2_PRF: &'static pbkdf2::PRF = &pbkdf2::HMAC_SHA256;
|
|
35
|
+
//! const CREDENTIAL_LEN: usize = 32; // digest::SHA256.output_len()
|
|
36
|
+
//! pub type Credential = [u8; CREDENTIAL_LEN];
|
|
37
|
+
//!
|
|
38
|
+
//! struct PasswordDatabase {
|
|
39
|
+
//! pbkdf2_iterations: usize,
|
|
40
|
+
//! db_salt_component: [u8; 16],
|
|
41
|
+
//!
|
|
42
|
+
//! // Normally this would be a persistent database.
|
|
43
|
+
//! storage: HashMap<String, Credential>,
|
|
44
|
+
//! }
|
|
45
|
+
//!
|
|
46
|
+
//! impl PasswordDatabase {
|
|
47
|
+
//! pub fn store_password(&mut self, username: &str, password: &str) {
|
|
48
|
+
//! let salt = self.salt(username);
|
|
49
|
+
//! let mut to_store: Credential = [0u8; CREDENTIAL_LEN];
|
|
50
|
+
//! pbkdf2::derive(PBKDF2_PRF, self.pbkdf2_iterations, &salt,
|
|
51
|
+
//! password.as_bytes(), &mut to_store);
|
|
52
|
+
//! self.storage.insert(String::from(username), to_store);
|
|
53
|
+
//! }
|
|
54
|
+
//!
|
|
55
|
+
//! pub fn verify_password(&self, username: &str, attempted_password: &str)
|
|
56
|
+
//! -> Result<(), ()> {
|
|
57
|
+
//! match self.storage.get(username) {
|
|
58
|
+
//! Some(actual_password) => {
|
|
59
|
+
//! let salt = self.salt(username);
|
|
60
|
+
//! pbkdf2::verify(PBKDF2_PRF, self.pbkdf2_iterations, &salt,
|
|
61
|
+
//! attempted_password.as_bytes(),
|
|
62
|
+
//! actual_password)
|
|
63
|
+
//! },
|
|
64
|
+
//!
|
|
65
|
+
//! None => Err(())
|
|
66
|
+
//! }
|
|
67
|
+
//! }
|
|
68
|
+
//!
|
|
69
|
+
//! // The salt should have a user-specific component so that an attacker
|
|
70
|
+
//! // cannot crack one password for multiple users in the database. It
|
|
71
|
+
//! // should have a database-unique component so that an attacker cannot
|
|
72
|
+
//! // crack the same user's password across databases in the unfortunate
|
|
73
|
+
//! // but common case that the user has used the same password for
|
|
74
|
+
//! // multiple systems.
|
|
75
|
+
//! fn salt(&self, username: &str) -> Vec<u8> {
|
|
76
|
+
//! let mut salt = Vec::with_capacity(self.db_salt_component.len() +
|
|
77
|
+
//! username.as_bytes().len());
|
|
78
|
+
//! salt.extend(self.db_salt_component.as_ref());
|
|
79
|
+
//! salt.extend(username.as_bytes());
|
|
80
|
+
//! salt
|
|
81
|
+
//! }
|
|
82
|
+
//! }
|
|
83
|
+
//!
|
|
84
|
+
//! fn main() {
|
|
85
|
+
//! // Normally these parameters would be loaded from a configuration file.
|
|
86
|
+
//! let mut db = PasswordDatabase {
|
|
87
|
+
//! pbkdf2_iterations: 100_000,
|
|
88
|
+
//! db_salt_component: [
|
|
89
|
+
//! // This value was generated from a secure PRNG.
|
|
90
|
+
//! 0xd6, 0x26, 0x98, 0xda, 0xf4, 0xdc, 0x50, 0x52,
|
|
91
|
+
//! 0x24, 0xf2, 0x27, 0xd1, 0xfe, 0x39, 0x01, 0x8a
|
|
92
|
+
//! ],
|
|
93
|
+
//! storage: HashMap::new(),
|
|
94
|
+
//! };
|
|
95
|
+
//!
|
|
96
|
+
//! db.store_password("alice", "@74d7]404j|W}6u");
|
|
97
|
+
//!
|
|
98
|
+
//! // An attempt to log in with the wrong password fails.
|
|
99
|
+
//! assert!(db.verify_password("alice", "wrong password").is_err());
|
|
100
|
+
//!
|
|
101
|
+
//! // Normally there should be an expoentially-increasing delay between
|
|
102
|
+
//! // attempts to further protect against online attacks.
|
|
103
|
+
//!
|
|
104
|
+
//! // An attempt to log in with the right password succeeds.
|
|
105
|
+
//! assert!(db.verify_password("alice", "@74d7]404j|W}6u").is_ok());
|
|
106
|
+
//! }
|
|
107
|
+
|
|
108
|
+
use super::{constant_time, digest, hmac};
|
|
109
|
+
|
|
110
|
+
/// Fills `out` with the key derived using PBKDF2 with the given inputs.
|
|
111
|
+
///
|
|
112
|
+
/// Do not use `derive` as part of verifying a secret; use `verify` instead, to
|
|
113
|
+
/// minimize the effectiveness of timing attacks.
|
|
114
|
+
///
|
|
115
|
+
/// `out.len()` must be no larger than the output length of the digest function
|
|
116
|
+
/// used in the PRF algorithm. This limit is more strict than what the
|
|
117
|
+
/// specification requires. As noted at https://github.com/ctz/fastpbkdf2,
|
|
118
|
+
/// "PBKDF2 is mis-designed and you should avoid asking for more than your hash
|
|
119
|
+
/// function's output length."
|
|
120
|
+
///
|
|
121
|
+
/// | Parameter | RFC 2898 Section 5.2 Term
|
|
122
|
+
/// |-------------|---------------------------------------
|
|
123
|
+
/// | prf | PRF
|
|
124
|
+
/// | iterations | c (iteration count)
|
|
125
|
+
/// | salt | S (salt)
|
|
126
|
+
/// | secret | P (password)
|
|
127
|
+
/// | out | dk (derived key)
|
|
128
|
+
/// | out.len() | dkLen (derived key length)
|
|
129
|
+
///
|
|
130
|
+
/// C analog: `PKCS5_PBKDF2_HMAC`
|
|
131
|
+
///
|
|
132
|
+
/// # Panics
|
|
133
|
+
///
|
|
134
|
+
/// `derive` panics if `iterations < 1`.
|
|
135
|
+
///
|
|
136
|
+
/// `derive` panics if `out.len()` is larger than the output length of the
|
|
137
|
+
/// digest function used by the PRF algorithm.
|
|
138
|
+
pub fn derive(prf: &'static PRF, iterations: usize, salt: &[u8], secret: &[u8],
|
|
139
|
+
out: &mut [u8]) {
|
|
140
|
+
assert!(iterations >= 1);
|
|
141
|
+
assert!(out.len() <= prf.digest_alg.output_len);
|
|
142
|
+
|
|
143
|
+
// This implementation's performance is asymptotically optimal as described
|
|
144
|
+
// in https://jbp.io/2015/08/11/pbkdf2-performance-matters/. However, it
|
|
145
|
+
// hasn't been optimized to the same extent as fastpbkdf2. In particular,
|
|
146
|
+
// this implementation is probably doing a lot of unnecessary copying.
|
|
147
|
+
|
|
148
|
+
let secret = hmac::SigningKey::new(prf.digest_alg, secret);
|
|
149
|
+
|
|
150
|
+
// Clear |out|.
|
|
151
|
+
for i in 0..out.len() {
|
|
152
|
+
out[i] = 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let mut ctx = hmac::SigningContext::with_key(&secret);
|
|
156
|
+
ctx.update(salt);
|
|
157
|
+
ctx.update(&[0, 0, 0, 1]);
|
|
158
|
+
let mut u = ctx.sign();
|
|
159
|
+
|
|
160
|
+
let mut remaining = iterations;
|
|
161
|
+
loop {
|
|
162
|
+
for i in 0..out.len() {
|
|
163
|
+
out[i] ^= u.as_ref()[i];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if remaining == 1 {
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
remaining -= 1;
|
|
170
|
+
|
|
171
|
+
u = hmac::sign(&secret, u.as_ref());
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Verifies that a previously-derived (e.g., using `derive`) PBKDF2 value
|
|
176
|
+
/// matches the PBKDF2 value derived from the other inputs.
|
|
177
|
+
///
|
|
178
|
+
/// The comparison is done in constant time to prevent timing attacks.
|
|
179
|
+
///
|
|
180
|
+
/// | Parameter | RFC 2898 Section 5.2 Term
|
|
181
|
+
/// |--------------------------|---------------------------------------
|
|
182
|
+
/// | prf | PRF
|
|
183
|
+
/// | iterations | c (iteration count)
|
|
184
|
+
/// | salt | S (salt)
|
|
185
|
+
/// | secret | P (password)
|
|
186
|
+
/// | previously_derived | dk (derived key)
|
|
187
|
+
/// | previously_derived.len() | dkLen (derived key length)
|
|
188
|
+
///
|
|
189
|
+
/// C analog: `PKCS5_PBKDF2_HMAC` + `CRYPTO_memcmp`
|
|
190
|
+
///
|
|
191
|
+
/// # Panics
|
|
192
|
+
///
|
|
193
|
+
/// `verify` panics if `iterations < 1`.
|
|
194
|
+
///
|
|
195
|
+
/// `verify` panics if `out.len()` is larger than the output length of the
|
|
196
|
+
/// digest function used by the PRF algorithm.
|
|
197
|
+
pub fn verify(prf: &'static PRF, iterations: usize, salt: &[u8], secret: &[u8],
|
|
198
|
+
previously_derived: &[u8]) -> Result<(), ()> {
|
|
199
|
+
let mut derived_buf = [0u8; digest::MAX_OUTPUT_LEN];
|
|
200
|
+
if previously_derived.len() > derived_buf.len() {
|
|
201
|
+
return Err(());
|
|
202
|
+
}
|
|
203
|
+
let derived = &mut derived_buf[0..previously_derived.len()];
|
|
204
|
+
derive(prf, iterations, salt, secret, derived);
|
|
205
|
+
constant_time::verify_slices_are_equal(derived, previously_derived)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// A PRF algorithm for use with `derive` and `verify`.
|
|
209
|
+
pub struct PRF {
|
|
210
|
+
digest_alg: &'static digest::Algorithm,
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/// HMAC-SHA256.
|
|
214
|
+
pub static HMAC_SHA256: PRF = PRF {
|
|
215
|
+
digest_alg: &digest::SHA256,
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/// HMAC-SHA512.
|
|
219
|
+
pub static HMAC_SHA512: PRF = PRF {
|
|
220
|
+
digest_alg: &digest::SHA512,
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/// HMAC-SHA1. *Deprecated*.
|
|
224
|
+
///
|
|
225
|
+
/// SHA-1 is deprecated in *ring* and its implementation in *ring* will be more
|
|
226
|
+
/// optimized more for size than for speed on some platforms. Since PBKDF2
|
|
227
|
+
/// requires an implementation highly optimized for speed, the size-for-speed
|
|
228
|
+
/// trade-off does not work well for PBKDF2.
|
|
229
|
+
///
|
|
230
|
+
pub static HMAC_SHA1: PRF = PRF {
|
|
231
|
+
digest_alg: &digest::SHA1,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
#[cfg(test)]
|
|
235
|
+
mod tests {
|
|
236
|
+
use super::super::{digest, file_test, pbkdf2};
|
|
237
|
+
|
|
238
|
+
#[test]
|
|
239
|
+
pub fn pkbdf2_tests() {
|
|
240
|
+
file_test::run("src/pbkdf2_tests.txt", |section, test_case| {
|
|
241
|
+
assert_eq!(section, "");
|
|
242
|
+
let digest_alg = test_case.consume_digest_alg("Hash").unwrap();
|
|
243
|
+
let iterations = test_case.consume_usize("c");
|
|
244
|
+
let secret = test_case.consume_bytes("P");
|
|
245
|
+
let salt = test_case.consume_bytes("S");
|
|
246
|
+
let dk = test_case.consume_bytes("DK");
|
|
247
|
+
|
|
248
|
+
let prf = if digest_alg.nid == digest::SHA1.nid {
|
|
249
|
+
&pbkdf2::HMAC_SHA1
|
|
250
|
+
} else if digest_alg.nid == digest::SHA256.nid {
|
|
251
|
+
&pbkdf2::HMAC_SHA256
|
|
252
|
+
} else if digest_alg.nid == digest::SHA512.nid {
|
|
253
|
+
&pbkdf2::HMAC_SHA512
|
|
254
|
+
} else {
|
|
255
|
+
unimplemented!();
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
let mut out = vec![0u8; dk.len()];
|
|
259
|
+
pbkdf2::derive(prf, iterations, &salt, &secret, &mut out);
|
|
260
|
+
assert_eq!(dk, out);
|
|
261
|
+
assert!(pbkdf2::verify(prf, iterations, &salt, &secret, &out)
|
|
262
|
+
.is_ok());
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|