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 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 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(not(target_arch = "wasm32"), feature = "wasm32_c"))]
16
17 #[cfg(target_arch = "wasm32")]
18 use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
19
20 #[cfg(target_arch = "wasm32")]
21 wasm_bindgen_test_configure!(run_in_browser);
22
23 use core::{convert::TryInto, ops::RangeFrom};
24 use ring::{aead, error, test, test_file};
25
26 /// Generate the known answer test functions for the given algorithm and test
27 /// case input file, where each test is implemented by a test in `$test`.
28 ///
29 /// All of these tests can be run in parallel.
30 macro_rules! test_known_answer {
31 ( $alg:ident, $test_file:expr, [ $( $test:ident ),+, ] ) => {
32 $(
33 #[test]
34 fn $test() {
35 test_aead(
36 &aead::$alg,
37 super::super::$test,
38 test_file!($test_file));
39 }
40 )+
41 }
42 }
43
44 /// Generate the tests for a given algorithm.
45 ///
46 /// All of these tests can be run in parallel.
47 macro_rules! test_aead {
48 { $( { $alg:ident, $test_file:expr } ),+, } => {
49 mod aead_test { // Make `cargo test aead` include these files.
50 $(
51 #[allow(non_snake_case)]
52 mod $alg { // Provide a separate namespace for each algorithm's test.
53 #[cfg(not(target_arch = "wasm32"))]
54 use super::super::*;
55
56 #[cfg(target_arch = "wasm32")]
57 use super::super::{*, test};
58
59 test_known_answer!(
60 $alg,
61 $test_file,
62 [
63 less_safe_key_open_in_place,
64 less_safe_key_open_within,
65 less_safe_key_seal_in_place_append_tag,
66 less_safe_key_seal_in_place_separate_tag,
67 opening_key_open_in_place,
68 opening_key_open_within,
69 sealing_key_seal_in_place_append_tag,
70 sealing_key_seal_in_place_separate_tag,
71 ]);
72
73 #[test]
74 fn key_sizes() {
75 super::super::key_sizes(&aead::$alg);
76 }
77 }
78 )+
79 }
80 }
81 }
82
83 test_aead! {
84 { AES_128_GCM, "aead_aes_128_gcm_tests.txt" },
85 { AES_256_GCM, "aead_aes_256_gcm_tests.txt" },
86 { CHACHA20_POLY1305, "aead_chacha20_poly1305_tests.txt" },
87 }
88
89 struct KnownAnswerTestCase<'a> {
90 key: &'a [u8],
91 nonce: [u8; aead::NONCE_LEN],
92 plaintext: &'a [u8],
93 aad: aead::Aad<&'a [u8]>,
94 ciphertext: &'a [u8],
95 tag: &'a [u8],
96 }
97
test_aead( aead_alg: &'static aead::Algorithm, f: impl Fn(&'static aead::Algorithm, KnownAnswerTestCase) -> Result<(), error::Unspecified>, test_file: test::File, )98 fn test_aead(
99 aead_alg: &'static aead::Algorithm,
100 f: impl Fn(&'static aead::Algorithm, KnownAnswerTestCase) -> Result<(), error::Unspecified>,
101 test_file: test::File,
102 ) {
103 test::run(test_file, |section, test_case| {
104 assert_eq!(section, "");
105 let key = test_case.consume_bytes("KEY");
106 let nonce = test_case.consume_bytes("NONCE");
107 let plaintext = test_case.consume_bytes("IN");
108 let aad = test_case.consume_bytes("AD");
109 let ct = test_case.consume_bytes("CT");
110 let tag = test_case.consume_bytes("TAG");
111 let error = test_case.consume_optional_string("FAILS");
112
113 match error.as_deref() {
114 Some("WRONG_NONCE_LENGTH") => {
115 assert!(matches!(
116 aead::Nonce::try_assume_unique_for_key(&nonce),
117 Err(error::Unspecified)
118 ));
119 return Ok(());
120 }
121 Some(unexpected) => {
122 unreachable!("unexpected error in test data: {}", unexpected);
123 }
124 None => {}
125 };
126
127 let test_case = KnownAnswerTestCase {
128 key: &key,
129 nonce: nonce.as_slice().try_into().unwrap(),
130 plaintext: &plaintext,
131 aad: aead::Aad::from(&aad),
132 ciphertext: &ct,
133 tag: &tag,
134 };
135
136 f(aead_alg, test_case)
137 })
138 }
139
test_seal_append_tag<Seal>( tc: &KnownAnswerTestCase, seal: Seal, ) -> Result<(), error::Unspecified> where Seal: FnOnce(aead::Nonce, &mut Vec<u8>) -> Result<(), error::Unspecified>,140 fn test_seal_append_tag<Seal>(
141 tc: &KnownAnswerTestCase,
142 seal: Seal,
143 ) -> Result<(), error::Unspecified>
144 where
145 Seal: FnOnce(aead::Nonce, &mut Vec<u8>) -> Result<(), error::Unspecified>,
146 {
147 let mut in_out = Vec::from(tc.plaintext);
148 seal(aead::Nonce::assume_unique_for_key(tc.nonce), &mut in_out)?;
149
150 let mut expected_ciphertext_and_tag = Vec::from(tc.ciphertext);
151 expected_ciphertext_and_tag.extend_from_slice(tc.tag);
152
153 assert_eq!(in_out, expected_ciphertext_and_tag);
154
155 Ok(())
156 }
157
test_seal_separate_tag<Seal>( tc: &KnownAnswerTestCase, seal: Seal, ) -> Result<(), error::Unspecified> where Seal: Fn(aead::Nonce, &mut [u8]) -> Result<aead::Tag, error::Unspecified>,158 fn test_seal_separate_tag<Seal>(
159 tc: &KnownAnswerTestCase,
160 seal: Seal,
161 ) -> Result<(), error::Unspecified>
162 where
163 Seal: Fn(aead::Nonce, &mut [u8]) -> Result<aead::Tag, error::Unspecified>,
164 {
165 let mut in_out = Vec::from(tc.plaintext);
166 let actual_tag = seal(aead::Nonce::assume_unique_for_key(tc.nonce), &mut in_out)?;
167 assert_eq!(actual_tag.as_ref(), tc.tag);
168 assert_eq!(in_out, tc.ciphertext);
169
170 Ok(())
171 }
172
test_open_in_place<OpenInPlace>( tc: &KnownAnswerTestCase<'_>, open_in_place: OpenInPlace, ) -> Result<(), error::Unspecified> where OpenInPlace: for<'a> FnOnce(aead::Nonce, &'a mut [u8]) -> Result<&'a mut [u8], error::Unspecified>,173 fn test_open_in_place<OpenInPlace>(
174 tc: &KnownAnswerTestCase<'_>,
175 open_in_place: OpenInPlace,
176 ) -> Result<(), error::Unspecified>
177 where
178 OpenInPlace:
179 for<'a> FnOnce(aead::Nonce, &'a mut [u8]) -> Result<&'a mut [u8], error::Unspecified>,
180 {
181 let nonce = aead::Nonce::assume_unique_for_key(tc.nonce);
182
183 let mut in_out = Vec::from(tc.ciphertext);
184 in_out.extend_from_slice(tc.tag);
185
186 let actual_plaintext = open_in_place(nonce, &mut in_out)?;
187
188 assert_eq!(actual_plaintext, tc.plaintext);
189 assert_eq!(&in_out[..tc.plaintext.len()], tc.plaintext);
190 Ok(())
191 }
192
test_open_within<OpenWithin>( tc: &KnownAnswerTestCase<'_>, open_within: OpenWithin, ) -> Result<(), error::Unspecified> where OpenWithin: for<'a> Fn( aead::Nonce, &'a mut [u8], RangeFrom<usize>, ) -> Result<&'a mut [u8], error::Unspecified>,193 fn test_open_within<OpenWithin>(
194 tc: &KnownAnswerTestCase<'_>,
195 open_within: OpenWithin,
196 ) -> Result<(), error::Unspecified>
197 where
198 OpenWithin: for<'a> Fn(
199 aead::Nonce,
200 &'a mut [u8],
201 RangeFrom<usize>,
202 ) -> Result<&'a mut [u8], error::Unspecified>,
203 {
204 // In release builds, test all prefix lengths from 0 to 4096 bytes.
205 // Debug builds are too slow for this, so for those builds, only
206 // test a smaller subset.
207
208 // TLS record headers are 5 bytes long.
209 // TLS explicit nonces for AES-GCM are 8 bytes long.
210 static MINIMAL_IN_PREFIX_LENS: [usize; 36] = [
211 // No input prefix to overwrite; i.e. the opening is exactly
212 // "in place."
213 0,
214 1,
215 2,
216 // Proposed TLS 1.3 header (no explicit nonce).
217 5,
218 8,
219 // Probably the most common use of a non-zero `in_prefix_len`
220 // would be to write a decrypted TLS record over the top of the
221 // TLS header and nonce.
222 5 /* record header */ + 8, /* explicit nonce */
223 // The stitched AES-GCM x86-64 code works on 6-block (96 byte)
224 // units. Some of the ChaCha20 code is even weirder.
225 15, // The maximum partial AES block.
226 16, // One AES block.
227 17, // One byte more than a full AES block.
228 31, // 2 AES blocks or 1 ChaCha20 block, minus 1.
229 32, // Two AES blocks, one ChaCha20 block.
230 33, // 2 AES blocks or 1 ChaCha20 block, plus 1.
231 47, // Three AES blocks - 1.
232 48, // Three AES blocks.
233 49, // Three AES blocks + 1.
234 63, // Four AES blocks or two ChaCha20 blocks, minus 1.
235 64, // Four AES blocks or two ChaCha20 blocks.
236 65, // Four AES blocks or two ChaCha20 blocks, plus 1.
237 79, // Five AES blocks, minus 1.
238 80, // Five AES blocks.
239 81, // Five AES blocks, plus 1.
240 95, // Six AES blocks or three ChaCha20 blocks, minus 1.
241 96, // Six AES blocks or three ChaCha20 blocks.
242 97, // Six AES blocks or three ChaCha20 blocks, plus 1.
243 111, // Seven AES blocks, minus 1.
244 112, // Seven AES blocks.
245 113, // Seven AES blocks, plus 1.
246 127, // Eight AES blocks or four ChaCha20 blocks, minus 1.
247 128, // Eight AES blocks or four ChaCha20 blocks.
248 129, // Eight AES blocks or four ChaCha20 blocks, plus 1.
249 143, // Nine AES blocks, minus 1.
250 144, // Nine AES blocks.
251 145, // Nine AES blocks, plus 1.
252 255, // 16 AES blocks or 8 ChaCha20 blocks, minus 1.
253 256, // 16 AES blocks or 8 ChaCha20 blocks.
254 257, // 16 AES blocks or 8 ChaCha20 blocks, plus 1.
255 ];
256
257 let mut more_comprehensive_in_prefix_lengths = [0; 4096];
258 let in_prefix_lengths = if cfg!(debug_assertions) {
259 &MINIMAL_IN_PREFIX_LENS[..]
260 } else {
261 #[allow(clippy::needless_range_loop)]
262 for b in 0..more_comprehensive_in_prefix_lengths.len() {
263 more_comprehensive_in_prefix_lengths[b] = b;
264 }
265 &more_comprehensive_in_prefix_lengths[..]
266 };
267 let mut in_out = vec![123u8; 4096];
268
269 for &in_prefix_len in in_prefix_lengths.iter() {
270 in_out.truncate(0);
271 in_out.resize(in_prefix_len, 123);
272 in_out.extend_from_slice(tc.ciphertext);
273 in_out.extend_from_slice(tc.tag);
274
275 let actual_plaintext = open_within(
276 aead::Nonce::assume_unique_for_key(tc.nonce),
277 &mut in_out,
278 in_prefix_len..,
279 )?;
280 assert_eq!(actual_plaintext, tc.plaintext);
281 assert_eq!(&in_out[..tc.plaintext.len()], tc.plaintext);
282 }
283
284 Ok(())
285 }
286
sealing_key_seal_in_place_append_tag( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>287 fn sealing_key_seal_in_place_append_tag(
288 alg: &'static aead::Algorithm,
289 tc: KnownAnswerTestCase,
290 ) -> Result<(), error::Unspecified> {
291 test_seal_append_tag(&tc, |nonce, in_out| {
292 let mut key: aead::SealingKey<OneNonceSequence> = make_key(alg, tc.key, nonce);
293 key.seal_in_place_append_tag(tc.aad, in_out)
294 })
295 }
296
sealing_key_seal_in_place_separate_tag( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>297 fn sealing_key_seal_in_place_separate_tag(
298 alg: &'static aead::Algorithm,
299 tc: KnownAnswerTestCase,
300 ) -> Result<(), error::Unspecified> {
301 test_seal_separate_tag(&tc, |nonce, in_out| {
302 let mut key: aead::SealingKey<_> = make_key(alg, tc.key, nonce);
303 key.seal_in_place_separate_tag(tc.aad, in_out)
304 })
305 }
306
opening_key_open_in_place( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>307 fn opening_key_open_in_place(
308 alg: &'static aead::Algorithm,
309 tc: KnownAnswerTestCase,
310 ) -> Result<(), error::Unspecified> {
311 test_open_in_place(&tc, |nonce, in_out| {
312 let mut key: aead::OpeningKey<_> = make_key(alg, tc.key, nonce);
313 key.open_in_place(tc.aad, in_out)
314 })
315 }
316
opening_key_open_within( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>317 fn opening_key_open_within(
318 alg: &'static aead::Algorithm,
319 tc: KnownAnswerTestCase,
320 ) -> Result<(), error::Unspecified> {
321 test_open_within(&tc, |nonce, in_out, ciphertext_and_tag| {
322 let mut key: aead::OpeningKey<OneNonceSequence> = make_key(alg, tc.key, nonce);
323 key.open_within(tc.aad, in_out, ciphertext_and_tag)
324 })
325 }
326
less_safe_key_seal_in_place_append_tag( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>327 fn less_safe_key_seal_in_place_append_tag(
328 alg: &'static aead::Algorithm,
329 tc: KnownAnswerTestCase,
330 ) -> Result<(), error::Unspecified> {
331 test_seal_append_tag(&tc, |nonce, in_out| {
332 let key = make_less_safe_key(alg, tc.key);
333 key.seal_in_place_append_tag(nonce, tc.aad, in_out)
334 })
335 }
336
less_safe_key_open_in_place( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>337 fn less_safe_key_open_in_place(
338 alg: &'static aead::Algorithm,
339 tc: KnownAnswerTestCase,
340 ) -> Result<(), error::Unspecified> {
341 test_open_in_place(&tc, |nonce, in_out| {
342 let key = make_less_safe_key(alg, tc.key);
343 key.open_in_place(nonce, tc.aad, in_out)
344 })
345 }
346
less_safe_key_seal_in_place_separate_tag( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>347 fn less_safe_key_seal_in_place_separate_tag(
348 alg: &'static aead::Algorithm,
349 tc: KnownAnswerTestCase,
350 ) -> Result<(), error::Unspecified> {
351 test_seal_separate_tag(&tc, |nonce, in_out| {
352 let key = make_less_safe_key(alg, tc.key);
353 key.seal_in_place_separate_tag(nonce, tc.aad, in_out)
354 })
355 }
356
less_safe_key_open_within( alg: &'static aead::Algorithm, tc: KnownAnswerTestCase, ) -> Result<(), error::Unspecified>357 fn less_safe_key_open_within(
358 alg: &'static aead::Algorithm,
359 tc: KnownAnswerTestCase,
360 ) -> Result<(), error::Unspecified> {
361 test_open_within(&tc, |nonce, in_out, ciphertext_and_tag| {
362 let key = make_less_safe_key(alg, tc.key);
363 key.open_within(nonce, tc.aad, in_out, ciphertext_and_tag)
364 })
365 }
366
367 #[allow(clippy::range_plus_one)]
key_sizes(aead_alg: &'static aead::Algorithm)368 fn key_sizes(aead_alg: &'static aead::Algorithm) {
369 let key_len = aead_alg.key_len();
370 let key_data = vec![0u8; key_len * 2];
371
372 // Key is the right size.
373 assert!(aead::UnboundKey::new(aead_alg, &key_data[..key_len]).is_ok());
374
375 // Key is one byte too small.
376 assert!(aead::UnboundKey::new(aead_alg, &key_data[..(key_len - 1)]).is_err());
377
378 // Key is one byte too large.
379 assert!(aead::UnboundKey::new(aead_alg, &key_data[..(key_len + 1)]).is_err());
380
381 // Key is half the required size.
382 assert!(aead::UnboundKey::new(aead_alg, &key_data[..(key_len / 2)]).is_err());
383
384 // Key is twice the required size.
385 assert!(aead::UnboundKey::new(aead_alg, &key_data[..(key_len * 2)]).is_err());
386
387 // Key is empty.
388 assert!(aead::UnboundKey::new(aead_alg, &[]).is_err());
389
390 // Key is one byte.
391 assert!(aead::UnboundKey::new(aead_alg, &[0]).is_err());
392 }
393
394 // Test that we reject non-standard nonce sizes.
395 #[allow(clippy::range_plus_one)]
396 #[test]
test_aead_nonce_sizes()397 fn test_aead_nonce_sizes() {
398 let nonce_len = aead::NONCE_LEN;
399 let nonce = vec![0u8; nonce_len * 2];
400
401 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..nonce_len]).is_ok());
402 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..(nonce_len - 1)]).is_err());
403 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..(nonce_len + 1)]).is_err());
404 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..(nonce_len / 2)]).is_err());
405 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..(nonce_len * 2)]).is_err());
406 assert!(aead::Nonce::try_assume_unique_for_key(&[]).is_err());
407 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..1]).is_err());
408 assert!(aead::Nonce::try_assume_unique_for_key(&nonce[..16]).is_err()); // 128 bits.
409 }
410
411 #[allow(clippy::range_plus_one)]
412 #[test]
aead_chacha20_poly1305_openssh()413 fn aead_chacha20_poly1305_openssh() {
414 // TODO: test_aead_key_sizes(...);
415
416 test::run(
417 test_file!("aead_chacha20_poly1305_openssh_tests.txt"),
418 |section, test_case| {
419 assert_eq!(section, "");
420
421 // XXX: `polyfill::convert` isn't available here.
422 let key_bytes = {
423 let as_vec = test_case.consume_bytes("KEY");
424 let mut as_array = [0u8; aead::chacha20_poly1305_openssh::KEY_LEN];
425 as_array.copy_from_slice(&as_vec);
426 as_array
427 };
428
429 let sequence_number = test_case.consume_usize("SEQUENCE_NUMBER");
430 assert_eq!(sequence_number as u32 as usize, sequence_number);
431 let sequence_num = sequence_number as u32;
432 let plaintext = test_case.consume_bytes("IN");
433 let ct = test_case.consume_bytes("CT");
434 let expected_tag = test_case.consume_bytes("TAG");
435
436 // TODO: Add some tests for when things fail.
437 //let error = test_case.consume_optional_string("FAILS");
438
439 let mut tag = [0u8; aead::chacha20_poly1305_openssh::TAG_LEN];
440 let mut s_in_out = plaintext.clone();
441 let s_key = aead::chacha20_poly1305_openssh::SealingKey::new(&key_bytes);
442 s_key.seal_in_place(sequence_num, &mut s_in_out[..], &mut tag);
443 assert_eq!(&ct, &s_in_out);
444 assert_eq!(&expected_tag, &tag);
445 let o_key = aead::chacha20_poly1305_openssh::OpeningKey::new(&key_bytes);
446
447 {
448 let o_result = o_key.open_in_place(sequence_num, &mut s_in_out[..], &tag);
449 assert_eq!(o_result, Ok(&plaintext[4..]));
450 }
451 assert_eq!(&s_in_out[..4], &ct[..4]);
452 assert_eq!(&s_in_out[4..], &plaintext[4..]);
453
454 Ok(())
455 },
456 );
457 }
458
459 #[test]
aead_test_aad_traits()460 fn aead_test_aad_traits() {
461 test::compile_time_assert_copy::<aead::Aad<&'_ [u8]>>();
462 test::compile_time_assert_eq::<aead::Aad<Vec<u8>>>(); // `!Copy`
463
464 let aad_123 = aead::Aad::from(vec![1, 2, 3]); // `!Copy`
465 assert_eq!(aad_123, aad_123.clone()); // Cover `Clone` and `PartialEq`
466 assert_eq!(
467 format!("{:?}", aead::Aad::from(&[1, 2, 3])),
468 "Aad([1, 2, 3])"
469 );
470 }
471
472 #[test]
test_tag_traits()473 fn test_tag_traits() {
474 test::compile_time_assert_send::<aead::Tag>();
475 test::compile_time_assert_sync::<aead::Tag>();
476 }
477
478 #[test]
test_aead_key_debug()479 fn test_aead_key_debug() {
480 let key_bytes = [0; 32];
481 let nonce = [0; aead::NONCE_LEN];
482
483 let key = aead::UnboundKey::new(&aead::AES_256_GCM, &key_bytes).unwrap();
484 assert_eq!(
485 "UnboundKey { algorithm: AES_256_GCM }",
486 format!("{:?}", key)
487 );
488
489 let sealing_key: aead::SealingKey<OneNonceSequence> = make_key(
490 &aead::AES_256_GCM,
491 &key_bytes,
492 aead::Nonce::try_assume_unique_for_key(&nonce).unwrap(),
493 );
494 assert_eq!(
495 "SealingKey { algorithm: AES_256_GCM }",
496 format!("{:?}", sealing_key)
497 );
498
499 let opening_key: aead::OpeningKey<OneNonceSequence> = make_key(
500 &aead::AES_256_GCM,
501 &key_bytes,
502 aead::Nonce::try_assume_unique_for_key(&nonce).unwrap(),
503 );
504 assert_eq!(
505 "OpeningKey { algorithm: AES_256_GCM }",
506 format!("{:?}", opening_key)
507 );
508
509 let key: aead::LessSafeKey = make_less_safe_key(&aead::AES_256_GCM, &key_bytes);
510 assert_eq!(
511 "LessSafeKey { algorithm: AES_256_GCM }",
512 format!("{:?}", key)
513 );
514 }
515
make_key<K: aead::BoundKey<OneNonceSequence>>( algorithm: &'static aead::Algorithm, key: &[u8], nonce: aead::Nonce, ) -> K516 fn make_key<K: aead::BoundKey<OneNonceSequence>>(
517 algorithm: &'static aead::Algorithm,
518 key: &[u8],
519 nonce: aead::Nonce,
520 ) -> K {
521 let key = aead::UnboundKey::new(algorithm, key).unwrap();
522 let nonce_sequence = OneNonceSequence::new(nonce);
523 K::new(key, nonce_sequence)
524 }
525
make_less_safe_key(algorithm: &'static aead::Algorithm, key: &[u8]) -> aead::LessSafeKey526 fn make_less_safe_key(algorithm: &'static aead::Algorithm, key: &[u8]) -> aead::LessSafeKey {
527 let key = aead::UnboundKey::new(algorithm, key).unwrap();
528 aead::LessSafeKey::new(key)
529 }
530
531 struct OneNonceSequence(Option<aead::Nonce>);
532
533 impl OneNonceSequence {
534 /// Constructs the sequence allowing `advance()` to be called
535 /// `allowed_invocations` times.
new(nonce: aead::Nonce) -> Self536 fn new(nonce: aead::Nonce) -> Self {
537 Self(Some(nonce))
538 }
539 }
540
541 impl aead::NonceSequence for OneNonceSequence {
advance(&mut self) -> Result<aead::Nonce, error::Unspecified>542 fn advance(&mut self) -> Result<aead::Nonce, error::Unspecified> {
543 self.0.take().ok_or(error::Unspecified)
544 }
545 }
546