ring-native 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|