1#![allow(private_bounds)]
5
6use crate::Sp80090ADrbg;
7
8use bouncycastle_core::errors::{KeyMaterialError, RNGError};
9use bouncycastle_core::key_material::{
10 KeyMaterial512, KeyMaterialTrait, KeyType, do_hazardous_operations,
11};
12use bouncycastle_core::traits::{Hash, HashAlgParams, RNG, SecurityStrength};
13use bouncycastle_sha2::{SHA256, SHA512};
14use bouncycastle_utils::{min, secret::Secret};
15
16use std::fmt::{Display, Formatter};
17
18enum SupportedHash {
19 SHA256,
20 SHA512,
21}
22
23trait HashDRBG80090AParams {
26 const HASH: SupportedHash;
27 const MAX_SECURITY_STRENGTH: SecurityStrength;
29 const MAX_LENGTH: u64;
31 const MAX_PERSONALIZATION_STRING_LENGTH: u64;
32 const MAX_ADDITIONAL_INPUT_LENGTH: u64;
33 const MAX_NUMBER_OF_BITS_PER_REQUEST: u64;
34 const RESEED_INTERVAL: u64;
35}
36
37#[allow(non_camel_case_types)]
39pub struct HashDRBG80090AParams_SHA256 {}
40
41impl HashDRBG80090AParams for HashDRBG80090AParams_SHA256 {
42 const HASH: SupportedHash = SupportedHash::SHA256;
43 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_128bit;
44 const MAX_LENGTH: u64 = (1u64 << 35) / 8; const MAX_PERSONALIZATION_STRING_LENGTH: u64 = (1u64 << 35) / 8; const MAX_ADDITIONAL_INPUT_LENGTH: u64 = (1u64 << 35) / 8; const MAX_NUMBER_OF_BITS_PER_REQUEST: u64 = (1u64 << 19) / 8; const RESEED_INTERVAL: u64 = 1u64 << 48; }
50
51#[allow(non_camel_case_types)]
53pub struct HashDRBG80090AParams_SHA512 {}
54impl HashDRBG80090AParams for HashDRBG80090AParams_SHA512 {
55 const HASH: SupportedHash = SupportedHash::SHA512;
56 const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::_256bit;
57 const MAX_LENGTH: u64 = (1u64 << 35) / 8; const MAX_PERSONALIZATION_STRING_LENGTH: u64 = (1u64 << 35) / 8; const MAX_ADDITIONAL_INPUT_LENGTH: u64 = (1u64 << 35) / 8; const MAX_NUMBER_OF_BITS_PER_REQUEST: u64 = (1u64 << 19) / 8; const RESEED_INTERVAL: u64 = 1u64 << 48; }
63
64const LARGEST_HASHER_OUTPUT_LEN: usize = 64;
66
67#[allow(private_bounds)]
68pub struct HashDRBG80090A<H: HashDRBG80090AParams> {
70 _phantom: core::marker::PhantomData<H>,
71 state: WorkingState<LARGEST_HASHER_OUTPUT_LEN>,
74 admin_info: AdministrativeInfo,
75}
76
77struct WorkingState<const SEED_LEN: usize> {
78 v: Secret<[u8; SEED_LEN]>,
79 c: Secret<[u8; SEED_LEN]>,
80
81 reseed_counter: Secret<u64>,
83}
84
85struct AdministrativeInfo {
86 strength: SecurityStrength,
87 prediction_resistance: bool,
88 instantiated: bool,
89}
90
91impl<const SEED_LEN: usize> Display for WorkingState<SEED_LEN> {
93 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
94 write!(f, "HashDRBG80090A::WorkingState::<{}>", SEED_LEN)
95 }
96}
97
98#[test]
99fn test_working_state_display() {
101 let ws =
102 WorkingState::<32> { v: Secret::new(), c: Secret::new(), reseed_counter: Secret::new() };
103 assert_eq!(format!("{}", ws), "HashDRBG80090A::WorkingState::<32>");
104}
105
106impl<H: HashDRBG80090AParams> HashDRBG80090A<H> {
107 pub fn new() -> Self {
110 Self::new_from_os()
111 }
112
113 pub fn new_unititialized() -> Self {
118 Self {
119 _phantom: core::marker::PhantomData,
120 state: WorkingState::<LARGEST_HASHER_OUTPUT_LEN> {
121 v: Secret::<[u8; LARGEST_HASHER_OUTPUT_LEN]>::new(),
122 c: Secret::<[u8; LARGEST_HASHER_OUTPUT_LEN]>::new(),
123 reseed_counter: Secret::new(),
124 },
125 admin_info: AdministrativeInfo {
126 strength: H::MAX_SECURITY_STRENGTH,
127 prediction_resistance: false,
128 instantiated: false,
129 },
130 }
131 }
132
133 pub fn new_from_os() -> Self {
135 let mut seed = KeyMaterial512::new();
136 do_hazardous_operations(&mut seed, |seed| {
137 seed.set_key_type(KeyType::Seed).unwrap();
138 match H::HASH {
139 SupportedHash::SHA256 => {
140 getrandom::fill(&mut seed.ref_to_bytes_mut().unwrap()[..32]).unwrap();
141 seed.set_key_len(32).unwrap();
142 seed.set_security_strength(SecurityStrength::_128bit).unwrap();
143 }
144 SupportedHash::SHA512 => {
145 getrandom::fill(&mut seed.ref_to_bytes_mut().unwrap()).unwrap();
146 seed.set_key_len(64).unwrap();
147 seed.set_security_strength(SecurityStrength::_256bit).unwrap();
148 }
149 }
150 Ok(())
151 })
152 .unwrap();
153
154 let mut rng = Self::new_unititialized();
155 let ss = seed.security_strength().clone();
156 rng.instantiate(false, seed, &KeyMaterial512::new(), "new_from_os".as_bytes(), ss).unwrap();
157 rng
158 }
159}
160
161impl<H: HashDRBG80090AParams> Default for HashDRBG80090A<H> {
162 fn default() -> Self {
165 Self::new_from_os()
166 }
167}
168
169impl<H: HashDRBG80090AParams> Sp80090ADrbg for HashDRBG80090A<H> {
170 fn instantiate(
173 &mut self,
174 prediction_resistance: bool,
175 seed: impl KeyMaterialTrait,
176 nonce: &impl KeyMaterialTrait,
177 personalization_string: &[u8],
178 security_strength: SecurityStrength,
179 ) -> Result<(), RNGError> {
180 if self.admin_info.instantiated {
189 return Err(RNGError::GenericError(
190 "This DRBG instance has already been instantiated.",
191 ));
192 }
193
194 if prediction_resistance {
196 todo!("Prediction resistance is not yet supported by Hash_DRBG80090A.")
197 }
198
199 if personalization_string.len() as u64 > H::MAX_PERSONALIZATION_STRING_LENGTH {
200 return Err(RNGError::GenericError(
201 "Personalization string exceeds the maximum length allowed by the DRBG instance",
202 ));
203 }
204
205 if seed.key_type() != KeyType::Seed {
206 return Err(KeyMaterialError::InvalidKeyType("RNG seed must be KeyType::Seed"))?;
207 }
208
209 if (seed.key_len() as u32) < security_strength.as_int() / 8 {
210 return Err(KeyMaterialError::SecurityStrength(
211 "Provided seed must have a length that matches or exceeds the DRBG security strength.",
212 ))?;
213 }
214 if (seed.key_len() as u64) > H::MAX_LENGTH {
215 return Err(KeyMaterialError::SecurityStrength(
216 "Provided seed exceeds the maximum seed length.",
217 ))?;
218 }
219 if security_strength > H::MAX_SECURITY_STRENGTH {
222 return Err(KeyMaterialError::SecurityStrength(
223 "Requested security strength exceeds the maximum strength that this DRBG instance can provide.",
224 ))?;
225 }
226
227 match H::HASH {
231 SupportedHash::SHA256 => hash_df::<SHA256>(
232 seed.ref_to_bytes(),
233 nonce.ref_to_bytes(),
234 personalization_string,
235 &[0u8; 0],
236 &mut *self.state.v,
237 ),
238 SupportedHash::SHA512 => hash_df::<SHA512>(
239 seed.ref_to_bytes(),
240 nonce.ref_to_bytes(),
241 personalization_string,
242 &[0u8; 0],
243 &mut *self.state.v,
244 ),
245 }
246
247 match H::HASH {
249 SupportedHash::SHA256 => {
250 hash_df::<SHA256>(&[0u8], &*self.state.v, &[0u8; 0], &[0u8; 0], &mut *self.state.c)
251 }
252 SupportedHash::SHA512 => {
253 hash_df::<SHA512>(&[0u8], &*self.state.v, &[0u8; 0], &[0u8; 0], &mut *self.state.c)
254 }
255 }
256
257 *self.state.reseed_counter = 1;
259 self.admin_info.strength = min(&security_strength, &H::MAX_SECURITY_STRENGTH).clone();
260 self.admin_info.prediction_resistance = prediction_resistance;
261 self.admin_info.instantiated = true;
262
263 Ok(())
265 }
266
267 fn reseed<K: KeyMaterialTrait + ?Sized>(
268 &mut self,
269 seed: &K,
270 additional_input: &[u8],
271 ) -> Result<(), RNGError> {
272 if !self.admin_info.instantiated {
281 return Err(RNGError::Uninitialized);
282 }
283
284 if additional_input.len() as u64 > H::MAX_ADDITIONAL_INPUT_LENGTH {
285 return Err(RNGError::GenericError(
286 "Additional input exceeds the maximum length allowed by the DRBG instance",
287 ));
288 }
289
290 if seed.key_type() != KeyType::Seed {
291 return Err(KeyMaterialError::InvalidKeyType("RNG seed must be KeyType::Seed"))?;
292 }
293
294 if (seed.key_len() as u32) < self.admin_info.strength.as_int() / 8 {
297 return Err(KeyMaterialError::SecurityStrength(
298 "Provided seed must have a length that matches or exceeds the DRBG security strength.",
299 ))?;
300 }
301 if (seed.key_len() as u64) > H::MAX_LENGTH {
302 return Err(KeyMaterialError::SecurityStrength(
303 "Provided seed exceeds the maximum seed length.",
304 ))?;
305 }
306
307 match H::HASH {
311 SupportedHash::SHA256 => hash_df::<SHA256>(
312 &[0x01],
313 &*self.state.v.clone(),
314 seed.ref_to_bytes(),
315 additional_input,
316 &mut *self.state.v,
317 ),
318 SupportedHash::SHA512 => hash_df::<SHA512>(
319 &[0x01],
320 &*self.state.v.clone(),
321 seed.ref_to_bytes(),
322 additional_input,
323 &mut *self.state.v,
324 ),
325 }
326
327 match H::HASH {
329 SupportedHash::SHA256 => {
330 hash_df::<SHA256>(&[0u8], &*self.state.v, &[0u8; 0], &[0u8; 0], &mut *self.state.c)
331 }
332 SupportedHash::SHA512 => {
333 hash_df::<SHA512>(&[0u8], &*self.state.v, &[0u8; 0], &[0u8; 0], &mut *self.state.c)
334 }
335 }
336
337 *self.state.reseed_counter = 1;
339
340 Ok(())
342 }
343
344 fn generate(&mut self, additional_input: &[u8], len: usize) -> Result<Vec<u8>, RNGError> {
345 let mut out = vec![0u8; len];
346 self.generate_out(additional_input, &mut out)?;
347 Ok(out)
348 }
349
350 fn generate_out(&mut self, additional_input: &[u8], out: &mut [u8]) -> Result<usize, RNGError> {
351 if !self.admin_info.instantiated {
363 return Err(RNGError::Uninitialized);
364 }
365 if out.len() as u64 > H::MAX_NUMBER_OF_BITS_PER_REQUEST {
366 return Err(RNGError::GenericError(
367 "Requested number of bits exceeds the maximum number of bits per request allowed by the DRBG instance",
368 ));
369 }
370 if additional_input.len() as u64 > H::MAX_ADDITIONAL_INPUT_LENGTH {
371 return Err(RNGError::GenericError(
372 "Additional input exceeds the maximum length allowed by the DRBG instance",
373 ));
374 }
375
376 if *self.state.reseed_counter > H::RESEED_INTERVAL {
378 return Err(RNGError::ReseedRequired);
379 }
380
381 out.fill(0);
382
383 if additional_input.len() > 0 {
387 match H::HASH {
388 SupportedHash::SHA256 => {
389 let mut h = SHA256::new();
390 h.do_update(&[0x02]);
391 h.do_update(&*self.state.v);
392 h.do_update(additional_input);
393
394 let mut w = [0u8; SHA256::OUTPUT_LEN];
395 h.do_final_out(&mut w);
396 add_to_array(&mut *self.state.v, &w);
397 }
398 SupportedHash::SHA512 => {
399 let mut h = SHA512::new();
400 h.do_update(&[0x02]);
401 h.do_update(&*self.state.v);
402 h.do_update(additional_input);
403
404 let mut w = [0u8; SHA512::OUTPUT_LEN];
405 h.do_final_out(&mut w);
406 add_to_array(&mut *self.state.v, &w);
407 }
408 }
409 }
410
411 if out.len() > 0 {
413 match H::HASH {
417 SupportedHash::SHA256 => {
418 hashgen::<SHA256>(&*self.state.v, out);
419 }
420 SupportedHash::SHA512 => {
421 hashgen::<SHA512>(&*self.state.v, out);
422 }
423 }
424 }
425
426 let mut h = [0u8; 64];
429 match H::HASH {
430 SupportedHash::SHA256 => {
431 let mut sha = SHA256::default();
432 sha.do_update(&[0x03]);
433 sha.do_update(&*self.state.v);
434 sha.do_final_out(&mut h);
435 }
436 SupportedHash::SHA512 => {
437 let mut sha = SHA512::default();
438 sha.do_update(&[0x03]);
439 sha.do_update(&*self.state.v);
440 sha.do_final_out(&mut h);
441 }
442 };
443
444 add_to_array(&mut *self.state.v, &h);
446 add_to_array(&mut *self.state.v, &*self.state.c);
447 add_to_array(&mut *self.state.v, &self.state.reseed_counter.to_le_bytes());
448
449 *self.state.reseed_counter += 1;
451
452 Ok(out.len())
454 }
455
456 fn generate_keymaterial_out<K: KeyMaterialTrait + ?Sized>(
457 &mut self,
458 additional_input: &[u8],
459 out: &mut K,
460 ) -> Result<usize, RNGError> {
461 let mut ret: Result<usize, RNGError> = Ok(0);
462 do_hazardous_operations(out, |out| {
463 let out_ref = out.ref_to_bytes_mut()?;
464 ret = self.generate_out(additional_input, out_ref);
465 Ok(())
466 })?;
467
468 let bytes_written = match ret {
469 Err(e) => return Err(e),
470 Ok(bytes_written) => bytes_written,
471 };
472
473 do_hazardous_operations(out, |out| {
474 out.set_key_len(bytes_written)?;
475 out.set_key_type(KeyType::CryptographicRandom)?;
476 let new_security_strength =
477 min(&self.admin_info.strength, &SecurityStrength::from_bits(bytes_written * 8))
478 .clone();
479 out.set_security_strength(new_security_strength)?;
480 Ok(())
481 })?;
482 Ok(bytes_written)
483 }
484}
485
486impl<H: HashDRBG80090AParams> RNG for HashDRBG80090A<H> {
487 fn add_seed_keymaterial(
495 &mut self,
496 additional_seed: &dyn KeyMaterialTrait,
497 ) -> Result<(), RNGError> {
498 self.reseed(additional_seed, "add_seed_keymaterial".as_bytes())
499 }
500
501 fn next_int(&mut self) -> Result<u32, RNGError> {
502 let mut out = [0u8; 4];
503 self.generate_out("next_int".as_bytes(), &mut out)?;
504 Ok(u32::from_le_bytes(out))
505 }
506
507 fn next_bytes(&mut self, len: usize) -> Result<Vec<u8>, RNGError> {
508 self.generate("next_bytes".as_bytes(), len)
509 }
510
511 fn next_bytes_out(&mut self, out: &mut [u8]) -> Result<usize, RNGError> {
512 out.fill(0);
513
514 self.generate_out("next_bytes_out".as_bytes(), out)
515 }
516
517 fn fill_keymaterial_out(&mut self, out: &mut dyn KeyMaterialTrait) -> Result<usize, RNGError> {
518 self.generate_keymaterial_out("fill_keymaterial".as_bytes(), out)
519 }
520
521 fn security_strength(&self) -> SecurityStrength {
522 self.admin_info.strength.clone()
523 }
524}
525
526fn hash_df<H: Hash + HashAlgParams + Default>(
533 in1: &[u8],
534 in2: &[u8],
535 in3: &[u8],
536 in4: &[u8],
537 out: &mut [u8],
538) {
539 if out.len() > 255 * H::OUTPUT_LEN {
543 panic!("hash_df can't produce that much output!")
544 }
545
546 out.fill(0);
547
548 let no_of_bits_to_return: u32 = (out.len() * 8) as u32;
550 let len = u32::div_ceil(out.len() as u32, H::OUTPUT_LEN as u32);
551 let mut counter: u8 = 0x01;
552
553 for i in 1..len {
556 let mut h = H::default();
557 h.do_update(&counter.to_le_bytes());
558 h.do_update(&no_of_bits_to_return.to_le_bytes());
559 h.do_update(in1);
560 h.do_update(in2);
561 h.do_update(in3);
562 h.do_update(in4);
563 h.do_final_out(&mut out[((i - 1) as usize) * H::OUTPUT_LEN..(i as usize) * H::OUTPUT_LEN]);
564
565 counter += 1;
566 }
567
568 let bytes_written = (len - 1) as usize * H::OUTPUT_LEN;
572 let remainder = out.len() - bytes_written;
573 if remainder != 0 {
574 let mut h = H::default();
575 h.do_update(&counter.to_le_bytes());
576 h.do_update(&no_of_bits_to_return.to_le_bytes());
577 h.do_update(in1);
578 h.do_update(in2);
579 h.do_update(in3);
580 h.do_update(in4);
581
582 let mut temp = [0u8; 64];
584 h.do_final_out(&mut temp);
585
586 out[bytes_written..].copy_from_slice(&temp[..remainder]);
588 }
589}
590
591#[test]
592fn test_hash_df() {
593 let mut out = [0u8; 100];
595 hash_df::<SHA256>(&[0x01, 0x02, 0x03], &[0x04, 0x05], &[0x06, 0x07], &[0x08, 0x09], &mut out);
596 assert_ne!(out, [0u8; 100]);
597 assert_eq!(
600 out,
601 [
602 150u8, 177u8, 87u8, 145u8, 138u8, 4u8, 164u8, 14u8, 162u8, 43u8, 159u8, 152u8, 121u8,
603 117u8, 6u8, 18u8, 253u8, 84u8, 41u8, 64u8, 40u8, 209u8, 16u8, 176u8, 106u8, 115u8,
604 172u8, 193u8, 246u8, 228u8, 208u8, 79u8, 37u8, 31u8, 134u8, 141u8, 200u8, 7u8, 42u8,
605 199u8, 229u8, 236u8, 236u8, 186u8, 28u8, 87u8, 200u8, 14u8, 127u8, 36u8, 132u8, 23u8,
606 36u8, 150u8, 23u8, 215u8, 247u8, 121u8, 175u8, 82u8, 99u8, 187u8, 235u8, 25u8, 213u8,
607 18u8, 106u8, 22u8, 4u8, 99u8, 1u8, 184u8, 211u8, 160u8, 177u8, 67u8, 78u8, 181u8, 69u8,
608 51u8, 117u8, 2u8, 72u8, 36u8, 134u8, 72u8, 2u8, 9u8, 105u8, 149u8, 136u8, 35u8, 81u8,
609 114u8, 142u8, 80u8, 94u8, 42u8, 85u8, 155
610 ]
611 );
612
613 let mut out_max_sha256 = vec![0u8; 255 * 32];
615 hash_df::<SHA256>(&[0x01], &[0x02], &[0x03], &[0x04], &mut out_max_sha256);
616 assert_ne!(out_max_sha256, vec![0u8; 255 * 32]);
617
618 let mut out_too_large_sha256 = vec![0u8; 255 * 32 + 1];
620 let result_sha256 = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
621 hash_df::<SHA256>(&[0x01], &[0x02], &[0x03], &[0x04], &mut out_too_large_sha256);
622 }));
623 assert!(result_sha256.is_err());
624
625 let mut out_max_sha512 = vec![0u8; 255 * 64];
627 hash_df::<SHA512>(&[0x01], &[0x02], &[0x03], &[0x04], &mut out_max_sha512);
628 assert_ne!(out_max_sha512, vec![0u8; 255 * 64]);
629 assert_ne!(out_max_sha512[254 * 64..], [0u8; 64]);
631
632 let mut out_too_large_sha512 = vec![0u8; 255 * 64 + 1];
634 let result_sha512 = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
635 hash_df::<SHA512>(&[0x01], &[0x02], &[0x03], &[0x04], &mut out_too_large_sha512);
636 }));
637 assert!(result_sha512.is_err());
638}
639
640fn hashgen<H: Hash + HashAlgParams + Default>(v: &[u8], out: &mut [u8]) {
641 out.fill(0);
654
655 let m = u32::div_ceil(out.len() as u32, H::OUTPUT_LEN as u32);
656
657 let mut data = [0u8; 64];
660 data.copy_from_slice(v);
661 for i in 1..m {
668 H::default().hash_out(
669 &data,
670 &mut out[((i - 1) as usize) * H::OUTPUT_LEN..(i as usize) * H::OUTPUT_LEN],
671 );
672 add_to_array(&mut data, &[0x01]);
673 }
674
675 let bytes_written = (m - 1) as usize * H::OUTPUT_LEN;
679 let remainder = out.len() - bytes_written;
680 if remainder != 0 {
681 let mut temp = [0u8; 64];
683 H::default().hash_out(&data, &mut temp);
684
685 out[bytes_written..].copy_from_slice(&temp[..remainder as usize]);
687 }
688}
689
690fn add_to_array(longer: &mut [u8], shorter: &[u8]) {
696 if shorter.len() > longer.len() {
697 panic!("add_to_array: shorter array is longer than longer array!")
698 }
699
700 let mut carry: u8 = 0;
701
702 for i in 1..=shorter.len() {
704 let res = (longer[longer.len() - i] as u16)
705 + (shorter[shorter.len() - i] as u16)
706 + (carry as u16);
707 carry = if res > 0xFF { 1 } else { 0 };
708 longer[longer.len() - i] = res as u8;
709 }
710
711 for i in (shorter.len() + 1)..=longer.len() {
713 let res = (longer[longer.len() - i] as u16) + (carry as u16);
714 carry = if res > 0xFF { 1 } else { 0 };
715 longer[longer.len() - i] = res as u8;
716 }
717}
718
719#[test]
720fn test_add_to_array() {
721 let mut longer = [0x0F, 0xFF, 0xFF, 0xFF];
722 let shorter = [0x01];
723 add_to_array(&mut longer, &shorter);
724 assert_eq!(longer, [0x10, 0x00, 0x00, 0x00]);
725
726 let mut longer = [0x0F, 0xFF, 0xFE, 0xFE];
727 let shorter = [0x01];
728 add_to_array(&mut longer, &shorter);
729 assert_eq!(longer, [0x0F, 0xFF, 0xFE, 0xFF]);
730
731 let mut longer = [0x0F, 0xFF, 0xFE, 0xFF];
732 let shorter = [0x01];
733 add_to_array(&mut longer, &shorter);
734 assert_eq!(longer, [0x0F, 0xFF, 0xFF, 0x00]);
735
736 let mut longer = [0x1F, 0xFF, 0xFF, 0xFF];
737 let shorter = [0xE0, 0x00, 0x00, 0x02];
738 add_to_array(&mut longer, &shorter);
739 assert_eq!(longer, [0x00, 0x00, 0x00, 0x01]);
740
741 let mut longer = [0xFF];
742 let shorter = [0x01];
743 add_to_array(&mut longer, &shorter);
744 assert_eq!(longer, [0x00]);
745
746 let mut longer = [0x00, 0x01];
747 let shorter = [0xFF];
748 add_to_array(&mut longer, &shorter);
749 assert_eq!(longer, [0x01, 0x00]);
750
751 let mut longer = [0x00, 0x00, 0xFF];
752 let shorter = [0x00, 0x01];
753 add_to_array(&mut longer, &shorter);
754 assert_eq!(longer, [0x00, 0x01, 0x00]);
755
756 let mut longer = [0x00, 0x00, 0xFF];
757 let shorter = [0x0C, 0x01];
758 add_to_array(&mut longer, &shorter);
759 assert_eq!(longer, [0x00, 0x0D, 0x00]);
760
761 let mut longer = [0x00, 0xFF];
762 let shorter = [0x00, 0x01];
763 add_to_array(&mut longer, &shorter);
764 assert_eq!(longer, [0x01, 0x00]);
765
766 let mut longer = [0x00, 0x00, 0xFF];
767 let shorter = [0x00, 0x0C, 0x01];
768 add_to_array(&mut longer, &shorter);
769 assert_eq!(longer, [0x00, 0x0D, 0x00]);
770
771 let mut longer = [0x00, 0x00, 0xFF];
772 let shorter = [0x00, 0x0F, 0x01];
773 add_to_array(&mut longer, &shorter);
774 assert_eq!(longer, [0x00, 0x10, 0x00]);
775
776 let mut longer = [0x00, 0x00, 0xFC];
777 let shorter = [0x00, 0x0F, 0x01];
778 add_to_array(&mut longer, &shorter);
779 assert_eq!(longer, [0x00, 0x0F, 0xFD]);
780
781 let mut longer = [0x00, 0x0F, 0xFC];
782 let shorter = [0x00, 0x1F, 0x01];
783 add_to_array(&mut longer, &shorter);
784 assert_eq!(longer, [0x00, 0x2E, 0xFD]);
785}