capsules_extra/test/
sha512.rs1use core::cell::Cell;
11use core::cmp;
12
13use capsules_core::test::capsule_test::{CapsuleTest, CapsuleTestClient};
14use kernel::ErrorCode;
15use kernel::debug;
16use kernel::hil::digest;
17use kernel::utilities::cells::{OptionalCell, TakeCell};
18use kernel::utilities::leasable_buffer::SubSlice;
19use kernel::utilities::leasable_buffer::SubSliceMut;
20
21const SHA512_DIGEST_LEN: usize = 64;
22
23pub struct TestSha512<'a, H: digest::Digest<'a, SHA512_DIGEST_LEN>> {
24 sha: &'a H,
25 data: TakeCell<'static, [u8]>, hash: TakeCell<'static, [u8; SHA512_DIGEST_LEN]>, position: Cell<usize>, correct: Cell<bool>, client: OptionalCell<&'static dyn CapsuleTestClient>,
30}
31
32const CHUNK_SIZE: usize = 12;
36
37impl<'a, H: digest::Digest<'a, SHA512_DIGEST_LEN> + digest::Sha512> TestSha512<'a, H> {
38 pub fn new(
39 sha: &'a H,
40 data: &'static mut [u8],
41 hash: &'static mut [u8; SHA512_DIGEST_LEN],
42 correct: bool,
43 ) -> Self {
44 TestSha512 {
45 sha,
46 data: TakeCell::new(data),
47 hash: TakeCell::new(hash),
48 position: Cell::new(0),
49 correct: Cell::new(correct),
50 client: OptionalCell::empty(),
51 }
52 }
53
54 pub fn run(&'a self) {
55 let r = self.sha.set_mode_sha512();
56 if r.is_err() {
57 panic!("Sha512Test: failed to set mode: {:?}", r)
58 }
59 self.sha.set_client(self);
60 let data = self.data.take().unwrap();
61 let chunk_size = cmp::min(CHUNK_SIZE, data.len());
62 self.position.set(chunk_size);
63 let mut buffer = SubSliceMut::new(data);
64 buffer.slice(0..chunk_size);
65 let r = self.sha.add_mut_data(buffer);
66 if r.is_err() {
67 panic!("Sha512Test: failed to add data: {:?}", r);
68 }
69 }
70}
71
72impl<'a, H: digest::Digest<'a, SHA512_DIGEST_LEN>> digest::ClientData<SHA512_DIGEST_LEN>
73 for TestSha512<'a, H>
74{
75 fn add_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSlice<'static, u8>) {
76 unimplemented!()
77 }
78
79 fn add_mut_data_done(&self, result: Result<(), ErrorCode>, mut data: SubSliceMut<'static, u8>) {
80 if data.len() != 0 {
81 let r = self.sha.add_mut_data(data);
82 if r.is_err() {
83 panic!("Sha512Test: failed to add data: {:?}", r);
84 }
85 } else {
86 data.reset();
87 if self.position.get() < data.len() {
88 let new_position = cmp::min(data.len(), self.position.get() + CHUNK_SIZE);
89 data.slice(self.position.get()..new_position);
90 debug!(
91 "Sha512Test: Setting slice to {}..{}",
92 self.position.get(),
93 new_position
94 );
95 let r = self.sha.add_mut_data(data);
96 if r.is_err() {
97 panic!("Sha512Test: failed to add data: {:?}", r);
98 }
99 self.position.set(new_position);
100 } else {
101 data.reset();
102 self.data.put(Some(data.take()));
103 match result {
104 Ok(()) => {
105 let v = self.sha.verify(self.hash.take().unwrap());
106 if v.is_err() {
107 panic!("Sha512Test: failed to verify: {:?}", v);
108 }
109 }
110 Err(e) => {
111 panic!("Sha512Test: adding data failed: {:?}", e);
112 }
113 }
114 }
115 }
116 }
117}
118
119impl<'a, H: digest::Digest<'a, SHA512_DIGEST_LEN>> digest::ClientVerify<SHA512_DIGEST_LEN>
120 for TestSha512<'a, H>
121{
122 fn verification_done(
123 &self,
124 result: Result<bool, ErrorCode>,
125 compare: &'static mut [u8; SHA512_DIGEST_LEN],
126 ) {
127 self.hash.put(Some(compare));
128 debug!("Sha512Test: Verification result: {:?}", result);
129 match result {
130 Ok(success) => {
131 if success != self.correct.get() {
132 panic!(
133 "Sha512Test: Verification should have been {}, was {}",
134 self.correct.get(),
135 success
136 );
137 } else {
138 self.client.map(|client| {
139 client.done(Ok(()));
140 });
141 }
142 }
143 Err(e) => {
144 panic!("Sha512Test: Error in verification: {:?}", e);
145 }
146 }
147 }
148}
149
150impl<'a, H: digest::Digest<'a, SHA512_DIGEST_LEN>> digest::ClientHash<SHA512_DIGEST_LEN>
151 for TestSha512<'a, H>
152{
153 fn hash_done(
154 &self,
155 _result: Result<(), ErrorCode>,
156 _digest: &'static mut [u8; SHA512_DIGEST_LEN],
157 ) {
158 }
159}
160
161impl<'a, H: digest::Digest<'a, SHA512_DIGEST_LEN>> CapsuleTest for TestSha512<'a, H> {
162 fn set_client(&self, client: &'static dyn CapsuleTestClient) {
163 self.client.set(client);
164 }
165}