1use crate::BlockCipher;
37use crate::cipher::aes::Aes;
38use crate::drbg::Error;
39use crate::drbg::util::ct_increment;
40
41const RESEED_INTERVAL: u64 = 1 << 48;
43const MAX_REQUEST_OCTETS: usize = 1 << 16;
45
46const BLOCKLEN: usize = 16;
48const MAX_KEYLEN: usize = 32;
50const MAX_SEEDLEN: usize = MAX_KEYLEN + BLOCKLEN;
52const DF_MAX_S: usize = 512;
59
60pub struct CtrDrbg {
67 key: [u8; MAX_KEYLEN],
68 v: [u8; BLOCKLEN],
69 keylen: usize,
70 reseed_counter: u64,
71 use_df: bool,
72}
73
74const fn security_strength(keylen: usize) -> usize {
77 keylen * 8
78}
79
80impl CtrDrbg {
81 #[inline]
82 fn seedlen(&self) -> usize {
83 self.keylen + BLOCKLEN
84 }
85
86 fn block_encrypt(key: &[u8], input: &[u8; BLOCKLEN], out: &mut [u8; BLOCKLEN]) {
90 let cipher = Aes::new(key);
91 out.copy_from_slice(input);
92 cipher.encrypt_block(out);
93 }
94
95 fn ctr_drbg_update(&mut self, provided_data: &[u8]) {
111 let seedlen = self.seedlen();
112 debug_assert_eq!(provided_data.len(), seedlen);
113 let mut temp = [0u8; MAX_SEEDLEN];
114 let mut off = 0;
115 let mut block = [0u8; BLOCKLEN];
116 while off < seedlen {
117 ct_increment(&mut self.v);
118 Self::block_encrypt(&self.key[..self.keylen], &self.v, &mut block);
119 let take = core::cmp::min(BLOCKLEN, seedlen - off);
120 temp[off..off + take].copy_from_slice(&block[..take]);
121 off += take;
122 }
123 for i in 0..seedlen {
125 temp[i] ^= provided_data[i];
126 }
127 self.key[..self.keylen].copy_from_slice(&temp[..self.keylen]);
129 self.v.copy_from_slice(&temp[self.keylen..seedlen]);
130 }
131
132 fn block_cipher_df(keylen: usize, input_parts: &[&[u8]], out: &mut [u8]) -> Result<(), Error> {
140 let seedlen = keylen + BLOCKLEN;
141 let outlen = out.len();
142 debug_assert!(outlen <= seedlen);
143
144 let l: u32 = input_parts.iter().map(|p| p.len() as u32).sum();
146 let n: u32 = outlen as u32;
147 if 8 + l as usize + 1 + BLOCKLEN > DF_MAX_S {
151 return Err(Error::InvalidLength);
152 }
153
154 let mut sbuf = [0u8; DF_MAX_S];
160 let mut slen = 0;
161 sbuf[slen..slen + 4].copy_from_slice(&l.to_be_bytes());
162 slen += 4;
163 sbuf[slen..slen + 4].copy_from_slice(&n.to_be_bytes());
164 slen += 4;
165 for p in input_parts {
166 sbuf[slen..slen + p.len()].copy_from_slice(p);
167 slen += p.len();
168 }
169 sbuf[slen] = 0x80;
170 slen += 1;
171 while slen % BLOCKLEN != 0 {
172 sbuf[slen] = 0x00;
173 slen += 1;
174 }
175 let s = &sbuf[..slen];
176
177 let mut df_key = [0u8; MAX_KEYLEN];
179 for (i, b) in df_key.iter_mut().enumerate().take(keylen) {
180 *b = i as u8;
181 }
182 let df_key = &df_key[..keylen];
183
184 let mut temp = [0u8; MAX_SEEDLEN];
189 let mut i: u32 = 0;
190 let mut off = 0;
191 while off < seedlen {
192 let mut iv = [0u8; BLOCKLEN];
193 iv[..4].copy_from_slice(&i.to_be_bytes());
194 let mut chain = [0u8; BLOCKLEN];
195 Self::bcc(df_key, &iv, s, &mut chain);
196 let take = core::cmp::min(BLOCKLEN, seedlen - off);
197 temp[off..off + take].copy_from_slice(&chain[..take]);
198 off += take;
199 i += 1;
200 }
201
202 let k = {
207 let mut kk = [0u8; MAX_KEYLEN];
208 kk[..keylen].copy_from_slice(&temp[..keylen]);
209 kk
210 };
211 let mut x = [0u8; BLOCKLEN];
212 x.copy_from_slice(&temp[keylen..keylen + BLOCKLEN]);
213
214 let mut off = 0;
215 let mut blk = [0u8; BLOCKLEN];
216 while off < outlen {
217 Self::block_encrypt(&k[..keylen], &x, &mut blk);
218 x.copy_from_slice(&blk);
219 let take = core::cmp::min(BLOCKLEN, outlen - off);
220 out[off..off + take].copy_from_slice(&x[..take]);
221 off += take;
222 }
223 Ok(())
224 }
225
226 fn bcc(key: &[u8], iv: &[u8; BLOCKLEN], data: &[u8], out: &mut [u8; BLOCKLEN]) {
228 let mut chaining = [0u8; BLOCKLEN];
229 let mut input = [0u8; BLOCKLEN];
232 for j in 0..BLOCKLEN {
234 input[j] = chaining[j] ^ iv[j];
235 }
236 Self::block_encrypt(key, &input, &mut chaining);
237 let mut off = 0;
239 while off < data.len() {
240 for j in 0..BLOCKLEN {
241 input[j] = chaining[j] ^ data[off + j];
242 }
243 Self::block_encrypt(key, &input, &mut chaining);
244 off += BLOCKLEN;
245 }
246 out.copy_from_slice(&chaining);
247 }
248
249 pub fn instantiate(
268 key_len: usize,
269 entropy_input: &[u8],
270 nonce: &[u8],
271 personalization: &[u8],
272 ) -> Result<Self, Error> {
273 if !matches!(key_len, 16 | 24 | 32) {
274 return Err(Error::InvalidLength);
275 }
276 if entropy_input.len() * 8 < security_strength(key_len) {
277 return Err(Error::InsufficientEntropy);
278 }
279 let seedlen = key_len + BLOCKLEN;
280 let mut s = CtrDrbg {
281 key: [0u8; MAX_KEYLEN],
282 v: [0u8; BLOCKLEN],
283 keylen: key_len,
284 reseed_counter: 1,
285 use_df: true,
286 };
287 let mut seed_material = [0u8; MAX_SEEDLEN];
288 Self::block_cipher_df(
289 key_len,
290 &[entropy_input, nonce, personalization],
291 &mut seed_material[..seedlen],
292 )?;
293 s.ctr_drbg_update(&seed_material[..seedlen]);
295 s.reseed_counter = 1;
296 Ok(s)
297 }
298
299 pub fn instantiate_no_df(key_len: usize, entropy_input: &[u8], personalization: &[u8]) -> Result<Self, Error> {
308 if !matches!(key_len, 16 | 24 | 32) {
309 return Err(Error::InvalidLength);
310 }
311 let seedlen = key_len + BLOCKLEN;
312 if entropy_input.len() != seedlen {
313 return Err(Error::InsufficientEntropy);
314 }
315 if !personalization.is_empty() && personalization.len() != seedlen {
316 return Err(Error::InvalidLength);
317 }
318 let mut s = CtrDrbg {
319 key: [0u8; MAX_KEYLEN],
320 v: [0u8; BLOCKLEN],
321 keylen: key_len,
322 reseed_counter: 1,
323 use_df: false,
324 };
325 let mut seed_material = [0u8; MAX_SEEDLEN];
327 seed_material[..seedlen].copy_from_slice(&entropy_input[..seedlen]);
328 for i in 0..personalization.len() {
329 seed_material[i] ^= personalization[i];
330 }
331 s.ctr_drbg_update(&seed_material[..seedlen]);
332 s.reseed_counter = 1;
333 Ok(s)
334 }
335
336 pub fn reseed(&mut self, entropy_input: &[u8], additional_input: &[u8]) -> Result<(), Error> {
343 let seedlen = self.seedlen();
344 let mut seed_material = [0u8; MAX_SEEDLEN];
345 if self.use_df {
346 if entropy_input.len() * 8 < security_strength(self.keylen) {
347 return Err(Error::InsufficientEntropy);
348 }
349 Self::block_cipher_df(
350 self.keylen,
351 &[entropy_input, additional_input],
352 &mut seed_material[..seedlen],
353 )?;
354 } else {
355 if entropy_input.len() != seedlen {
356 return Err(Error::InsufficientEntropy);
357 }
358 if !additional_input.is_empty() && additional_input.len() != seedlen {
359 return Err(Error::InvalidLength);
360 }
361 seed_material[..seedlen].copy_from_slice(&entropy_input[..seedlen]);
362 for i in 0..additional_input.len() {
363 seed_material[i] ^= additional_input[i];
364 }
365 }
366 self.ctr_drbg_update(&seed_material[..seedlen]);
367 self.reseed_counter = 1;
368 Ok(())
369 }
370
371 pub fn generate(&mut self, out: &mut [u8], additional_input: &[u8]) -> Result<(), Error> {
389 if out.len() > MAX_REQUEST_OCTETS {
390 return Err(Error::RequestTooLarge);
391 }
392 if self.reseed_counter > RESEED_INTERVAL {
393 return Err(Error::ReseedRequired);
394 }
395 let seedlen = self.seedlen();
396
397 let mut add = [0u8; MAX_SEEDLEN];
399 let have_add = !additional_input.is_empty();
400 if have_add {
401 if self.use_df {
402 Self::block_cipher_df(self.keylen, &[additional_input], &mut add[..seedlen])?;
403 } else {
404 if additional_input.len() != seedlen {
405 return Err(Error::InvalidLength);
406 }
407 add[..seedlen].copy_from_slice(&additional_input[..seedlen]);
408 }
409 self.ctr_drbg_update(&add[..seedlen]);
410 }
411 let mut off = 0;
415 let mut block = [0u8; BLOCKLEN];
416 while off < out.len() {
417 ct_increment(&mut self.v);
418 Self::block_encrypt(&self.key[..self.keylen], &self.v, &mut block);
419 let take = core::cmp::min(BLOCKLEN, out.len() - off);
420 out[off..off + take].copy_from_slice(&block[..take]);
421 off += take;
422 }
423
424 self.ctr_drbg_update(&add[..seedlen]);
426 self.reseed_counter += 1;
428 Ok(())
429 }
430}
431
432#[cfg(test)]
433mod tests {
434 use super::*;
435 use crate::drbg::test_util::hx;
436
437 #[test]
442 fn ctr_aes256_usedf_no_reseed_pers0_add0() {
443 let entropy = hx("36401940fa8b1fba91a1661f211d78a0b9389a74e5bccfece8d766af1a6d3b14");
444 let nonce = hx("496f25b0f1301b4f501be30380a137eb");
445 let mut drbg = CtrDrbg::instantiate(32, &entropy, &nonce, &[]).unwrap();
446 let mut out = [0u8; 64];
447 drbg.generate(&mut out, &[]).unwrap();
448 drbg.generate(&mut out, &[]).unwrap();
449 assert_eq!(
450 out[..],
451 hx("5862eb38bd558dd978a696e6df164782ddd887e7e9a6c9f3f1fbafb78941b535\
452 a64912dfd224c6dc7454e5250b3d97165e16260c2faf1cc7735cb75fb4f07e1d")[..]
453 );
454 }
455
456 #[test]
458 fn ctr_aes256_usedf_no_reseed_pers_add() {
459 let entropy = hx("87b56e964eba227154724bb9484b812d3e2c0c43b3d17f6098d9526e16e6d0ef");
460 let nonce = hx("9bea6a7ff2358df142e6c23e2157fb83");
461 let pers = hx("9860b432edd58d1ccbfeecbce99ffaee7d935a614860d4e965bd67041403096b");
462 let add0 = hx("99a5cc87924e8ea65a596f81fd17d63f5b4542fe6e8e1511b5d35c835dfadb0b");
463 let add1 = hx("9a8dec54734a34582a2332f3452e82313524c3e0dfb485faeac6ca5fc0ff504d");
464 let mut drbg = CtrDrbg::instantiate(32, &entropy, &nonce, &pers).unwrap();
465 let mut out = [0u8; 64];
466 drbg.generate(&mut out, &add0).unwrap();
467 drbg.generate(&mut out, &add1).unwrap();
468 assert_eq!(
469 out[..],
470 hx("dbc6a2330b19b5cddd8cd6392ec1fb508678c805e87d1aca07ac265007632503\
471 044a00610c79d98375afa7ab4cca1a90989cbfe7c674af5d823ced11c47e9af6")[..]
472 );
473 }
474
475 #[test]
479 fn ctr_aes256_nodf_no_reseed_pers0_add0() {
480 let entropy = hx("df5d73faa468649edda33b5cca79b0b05600419ccb7a879ddfec9db32ee494e5\
481 531b51de16a30f769262474c73bec010");
482 let mut drbg = CtrDrbg::instantiate_no_df(32, &entropy, &[]).unwrap();
483 let mut out = [0u8; 64];
484 drbg.generate(&mut out, &[]).unwrap();
485 drbg.generate(&mut out, &[]).unwrap();
486 assert_eq!(
487 out[..],
488 hx("d1c07cd95af8a7f11012c84ce48bb8cb87189e99d40fccb1771c619bdf82ab22\
489 80b1dc2f2581f39164f7ac0c510494b3a43c41b7db17514c87b107ae793e01c5")[..]
490 );
491 }
492
493 #[test]
495 fn ctr_aes256_nodf_no_reseed_pers_add() {
496 let entropy = hx("0dd4d80062ecc0f359efbe7723020be9b88b550fe74088094069e74428395856\
497 f63eed4f5b0e7d1e006f0eaff74f638c");
498 let pers = hx("d2aa2ccd4bc6537e51f6550ab6d6294547bef3e971a7f128e4436f957de9982c\
499 93ee22110b0e40ab33a7d3dfa22f599d");
500 let add0 = hx("0b081bab6c74d86b4a010e2ded99d14e0c9838f7c3d69afd64f1b66377d95cdc\
501 b7f6ec5358e3516034c3339ced7e1638");
502 let add1 = hx("ca818f938ae0c7f4f507e4cfec10e7baf51fe34b89a502f754d2d2be7395120f\
503 e1fb013c67ac2500b3d17b735da09a6e");
504 let mut drbg = CtrDrbg::instantiate_no_df(32, &entropy, &pers).unwrap();
505 let mut out = [0u8; 64];
506 drbg.generate(&mut out, &add0).unwrap();
507 drbg.generate(&mut out, &add1).unwrap();
508 assert_eq!(
509 out[..],
510 hx("6808268b13e236f642c06deba2494496e7003c937ebf6f7cb7c92104ea090f18\
511 484aa075560d7844a06eb559948c93b26ae40f2db98ecb53ad593eb4c78f82b1")[..]
512 );
513 }
514
515 #[test]
518 fn ctr_aes256_usedf_pr_false_reseed() {
519 let entropy = hx("2d4c9f46b981c6a0b2b5d8c69391e569ff13851437ebc0fc00d616340252fed5");
520 let nonce = hx("0bf814b411f65ec4866be1abb59d3c32");
521 let reseed_entropy = hx("93500fae4fa32b86033b7a7bac9d37e710dcc67ca266bc8607d665937766d207");
522 let mut drbg = CtrDrbg::instantiate(32, &entropy, &nonce, &[]).unwrap();
523 drbg.reseed(&reseed_entropy, &[]).unwrap();
524 let mut out = [0u8; 64];
525 drbg.generate(&mut out, &[]).unwrap();
526 drbg.generate(&mut out, &[]).unwrap();
527 assert_eq!(
528 out[..],
529 hx("322dd28670e75c0ea638f3cb68d6a9d6e50ddfd052b772a7b1d78263a7b8978b\
530 6740c2b65a9550c3a76325866fa97e16d74006bc96f26249b9f0a90d076f08e5")[..]
531 );
532 }
533
534 #[test]
541 fn ctr_aes128_usedf_no_reseed_pers0_add0() {
542 let entropy = hx("890eb067acf7382eff80b0c73bc872c6");
543 let nonce = hx("aad471ef3ef1d203");
544 let mut drbg = CtrDrbg::instantiate(16, &entropy, &nonce, &[]).unwrap();
545 let mut out = [0u8; 64];
546 drbg.generate(&mut out, &[]).unwrap();
547 drbg.generate(&mut out, &[]).unwrap();
548 assert_eq!(
549 out[..],
550 hx("a5514ed7095f64f3d0d3a5760394ab42062f373a25072a6ea6bcfd8489e94af6\
551 cf18659fea22ed1ca0a9e33f718b115ee536b12809c31b72b08ddd8be1910fa3")[..]
552 );
553 }
554
555 #[test]
557 fn ctr_aes128_usedf_no_reseed_pers_add() {
558 let entropy = hx("cae48dd80d298103ef1ec0bf1bb96270");
559 let nonce = hx("d827f91613e0b47f");
560 let pers = hx("cc928f3d2df31a29f4e444f3df08be21");
561 let add0 = hx("7eaa1bbec79393a7f4a8227b691ecb68");
562 let add1 = hx("6869c6c7b9e6653b3977f0789e94478a");
563 let mut drbg = CtrDrbg::instantiate(16, &entropy, &nonce, &pers).unwrap();
564 let mut out = [0u8; 64];
565 drbg.generate(&mut out, &add0).unwrap();
566 drbg.generate(&mut out, &add1).unwrap();
567 assert_eq!(
568 out[..],
569 hx("920132cd284695b868b5bc4b703afea4d996624a8f57e9fbf5e793b509cb15b4\
570 beaf702dac28712d249ae75090a91fd35775294bf24ddebfd24e45d13f4a1748")[..]
571 );
572 }
573
574 #[test]
576 fn ctr_aes192_usedf_no_reseed_pers0_add0() {
577 let entropy = hx("c35c2fa2a89d52a11fa32aa96c95b8f1c9a8f9cb245a8b40");
578 let nonce = hx("f3a6e5a7fbd9d3c68e277ba9ac9bbb00");
579 let mut drbg = CtrDrbg::instantiate(24, &entropy, &nonce, &[]).unwrap();
580 let mut out = [0u8; 64];
581 drbg.generate(&mut out, &[]).unwrap();
582 drbg.generate(&mut out, &[]).unwrap();
583 assert_eq!(
584 out[..],
585 hx("8c2e72abfd9bb8284db79e17a43a3146cd7694e35249fc3383914a7117f41368\
586 e6d4f148ff49bf29076b5015c59f457945662e3d3503843f4aa5a3df9a9df10d")[..]
587 );
588 }
589
590 #[test]
592 fn ctr_aes192_usedf_no_reseed_pers_add() {
593 let entropy = hx("d5973b5c9105cbf67e978f419924790d83023e86a8b5dd6b");
594 let nonce = hx("358af1ae9a842c6e03f88dfa2a311161");
595 let pers = hx("294d7d35f53a5d7ddef5ca4100f3547112c93e41251257dc0a19b6dfaa4a60a4");
596 let add0 = hx("0805f31446c51d5d9d27b7cbb16e840b9e8b0dfe6fb4b69792bc8de9e3bd6d92");
597 let add1 = hx("934d7fd5e716376342607123ea113d6b20170ccda53fc86541407a156cd94904");
598 let mut drbg = CtrDrbg::instantiate(24, &entropy, &nonce, &pers).unwrap();
599 let mut out = [0u8; 64];
600 drbg.generate(&mut out, &add0).unwrap();
601 drbg.generate(&mut out, &add1).unwrap();
602 assert_eq!(
603 out[..],
604 hx("cb95459d1735cb9bce8a75bf097a099c9f7c70bad43e3e431f2d3829d7ca9d06\
605 17b9a99337af5248d4741cb5a60dff6f8c5221e23f3cb524a94ffdd2190bfb3b")[..]
606 );
607 }
608
609 #[test]
611 fn ctr_aes128_nodf_no_reseed_pers0_add0() {
612 let entropy = hx("ce50f33da5d4c1d3d4004eb35244b7f2cd7f2e5076fbf6780a7ff634b249a5fc");
613 let mut drbg = CtrDrbg::instantiate_no_df(16, &entropy, &[]).unwrap();
614 let mut out = [0u8; 64];
615 drbg.generate(&mut out, &[]).unwrap();
616 drbg.generate(&mut out, &[]).unwrap();
617 assert_eq!(
618 out[..],
619 hx("6545c0529d372443b392ceb3ae3a99a30f963eaf313280f1d1a1e87f9db373d3\
620 61e75d18018266499cccd64d9bbb8de0185f213383080faddec46bae1f784e5a")[..]
621 );
622 }
623
624 #[test]
626 fn ctr_aes128_nodf_no_reseed_pers_add() {
627 let entropy = hx("50b96542a1f2b8b05074051fe8fb0e45adbbd5560e3594e12d485fe1bfcb741f");
628 let pers = hx("820c3030f97b3ead81a93b88b871937278fd3d711d2085d9280cba394673b17e");
629 let add0 = hx("1f1632058806d6d8e231288f3b15a3c324e90ccef4891bd595f09c3e80e27469");
630 let add1 = hx("5cadc8bfd86d2a5d44f921f64c7d153001b9bdd7caa6618639b948ebfad5cb8a");
631 let mut drbg = CtrDrbg::instantiate_no_df(16, &entropy, &pers).unwrap();
632 let mut out = [0u8; 64];
633 drbg.generate(&mut out, &add0).unwrap();
634 drbg.generate(&mut out, &add1).unwrap();
635 assert_eq!(
636 out[..],
637 hx("02b76a66f103e98d450e25e09c35337747d987471d2b3d81e03be24c7e985417\
638 a32acd72bc0a6eddd9871410dacb921c659249b4e2b368c4ac8580fb5db559bc")[..]
639 );
640 }
641
642 #[test]
644 fn ctr_aes192_nodf_no_reseed_pers0_add0() {
645 let entropy = hx("f1ef7eb311c850e189be229df7e6d68f1795aa8e21d93504e75abe78f04139587\
646 3540386812a9a2a");
647 let mut drbg = CtrDrbg::instantiate_no_df(24, &entropy, &[]).unwrap();
648 let mut out = [0u8; 64];
649 drbg.generate(&mut out, &[]).unwrap();
650 drbg.generate(&mut out, &[]).unwrap();
651 assert_eq!(
652 out[..],
653 hx("6bb0aa5b4b97ee83765736ad0e9068dfef0ccfc93b71c1d3425302ef7ba4635f\
654 fc09981d262177e208a7ec90a557b6d76112d56c40893892c3034835036d7a69")[..]
655 );
656 }
657
658 #[test]
660 fn ctr_aes192_nodf_no_reseed_pers_add() {
661 let entropy = hx("8db47ca284294daeb303e6459422e32577ca539c00fead8839d42946bad8eb30\
662 e489c6d858763a28");
663 let pers = hx("c2491a6ce1ef9bd13eb66a86c0f5be3d2f3239bf7f713e830e8ae8907a2084f8\
664 73ed3f5eddf5b569");
665 let add0 = hx("e9a3f24180345a0c0680aacdb89ce7cf841c7ad547ef92dad54f8262445e2f0c\
666 54c8f8e42350f79c");
667 let add1 = hx("e2427b93738424c0fce14cb6c5f1d6b6a0532787157b6d907bc55d1c9a670494\
668 776212a643a9fb2c");
669 let mut drbg = CtrDrbg::instantiate_no_df(24, &entropy, &pers).unwrap();
670 let mut out = [0u8; 64];
671 drbg.generate(&mut out, &add0).unwrap();
672 drbg.generate(&mut out, &add1).unwrap();
673 assert_eq!(
674 out[..],
675 hx("494b1957ab382b382054f54bb62f0b5b464afb3b18492c60809c26e86e45b6b9\
676 fa44524dd89ecdca99c60e68ed107ff336be1591cadd6fd7e35f742611809f2e")[..]
677 );
678 }
679
680 #[test]
683 fn ctr_aes128_usedf_pr_false_reseed() {
684 let entropy = hx("0f65da13dca407999d4773c2b4a11d85");
685 let nonce = hx("5209e5b4ed82a234");
686 let reseed_entropy = hx("1dea0a12c52bf64339dd291c80d8ca89");
687 let mut drbg = CtrDrbg::instantiate(16, &entropy, &nonce, &[]).unwrap();
688 drbg.reseed(&reseed_entropy, &[]).unwrap();
689 let mut out = [0u8; 64];
690 drbg.generate(&mut out, &[]).unwrap();
691 drbg.generate(&mut out, &[]).unwrap();
692 assert_eq!(
693 out[..],
694 hx("2859cc468a76b08661ffd23b28547ffd0997ad526a0f51261b99ed3a37bd407b\
695 f418dbe6c6c3e26ed0ddefcb7474d899bd99f3655427519fc5b4057bcaf306d4")[..]
696 );
697 }
698
699 #[test]
700 fn ctr_aes256_nodf_rejects_wrong_entropy_len() {
701 let bad = [0u8; 32];
703 assert_eq!(
704 CtrDrbg::instantiate_no_df(32, &bad, &[]).err(),
705 Some(Error::InsufficientEntropy)
706 );
707 }
708
709 #[test]
710 fn ctr_rejects_bad_key_len() {
711 assert_eq!(
712 CtrDrbg::instantiate(20, &[0u8; 32], &[0u8; 16], &[]).err(),
713 Some(Error::InvalidLength)
714 );
715 }
716}