capsules_extra/
sha256.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Software implementation of SHA-256.
6//!
7//! Implementation is based on the Wikipedia description of the
8//! algorithm. It performs the hash using 32-bit native values,
9//! translating the input data into the endianness of the processor
10//! and translating the output into big endian format.
11
12use core::cell::Cell;
13use kernel::deferred_call::{DeferredCall, DeferredCallClient};
14
15use kernel::hil::digest::Sha256;
16use kernel::hil::digest::{Client, ClientData, ClientHash, ClientVerify};
17use kernel::hil::digest::{ClientDataHash, ClientDataVerify, DigestDataHash, DigestDataVerify};
18use kernel::hil::digest::{Digest, DigestData, DigestHash, DigestVerify};
19use kernel::utilities::cells::{MapCell, OptionalCell};
20use kernel::utilities::leasable_buffer::SubSlice;
21use kernel::utilities::leasable_buffer::SubSliceMut;
22use kernel::utilities::leasable_buffer::SubSliceMutImmut;
23use kernel::ErrorCode;
24
25#[derive(Clone, Copy, PartialEq)]
26pub enum State {
27    Idle,
28    Data,
29    Hash,
30    Verify,
31    CancelData,
32    CancelHash,
33    CancelVerify,
34}
35
36const SHA_BLOCK_LEN_BYTES: usize = 64;
37const SHA_256_OUTPUT_LEN_BYTES: usize = 32;
38const NUM_ROUND_CONSTANTS: usize = 64;
39
40const ROUND_CONSTANTS: [u32; NUM_ROUND_CONSTANTS] = [
41    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
42    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
43    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
44    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
45    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
46    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
47    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
48    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
49];
50
51pub struct Sha256Software<'a> {
52    state: Cell<State>,
53
54    client: OptionalCell<&'a dyn Client<SHA_256_OUTPUT_LEN_BYTES>>,
55    input_data: OptionalCell<SubSliceMutImmut<'static, u8>>,
56    data_buffer: MapCell<[u8; SHA_BLOCK_LEN_BYTES]>,
57    buffered_length: Cell<usize>,
58    total_length: Cell<usize>,
59
60    // Used to store the hash or the hash to compare against with verify
61    output_data: Cell<Option<&'static mut [u8; SHA_256_OUTPUT_LEN_BYTES]>>,
62
63    hash_values: Cell<[u32; 8]>,
64    deferred_call: DeferredCall,
65}
66
67impl Sha256Software<'_> {
68    pub fn new() -> Self {
69        let s = Self {
70            state: Cell::new(State::Idle),
71            client: OptionalCell::empty(),
72            input_data: OptionalCell::empty(),
73            data_buffer: MapCell::new([0; SHA_BLOCK_LEN_BYTES]),
74            buffered_length: Cell::new(0),
75            total_length: Cell::new(0),
76
77            output_data: Cell::new(None),
78            hash_values: Cell::new([0; 8]),
79
80            deferred_call: DeferredCall::new(),
81        };
82        s.initialize();
83        s
84    }
85
86    pub fn busy(&self) -> bool {
87        match self.state.get() {
88            State::Idle => false,
89            _ => true,
90        }
91    }
92
93    fn initialize(&self) {
94        let new_state = match self.state.get() {
95            State::Idle => State::Idle,
96            State::Data | State::CancelData => State::CancelData,
97            State::Hash | State::CancelHash => State::CancelHash,
98            State::Verify | State::CancelVerify => State::CancelVerify,
99        };
100        self.state.set(new_state);
101
102        self.buffered_length.set(0);
103        self.total_length.set(0);
104        self.data_buffer.map(|b| {
105            for i in 0..SHA_BLOCK_LEN_BYTES {
106                b[i] = 0;
107            }
108        });
109        self.hash_values.set([
110            0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
111            0x5be0cd19,
112        ]);
113    }
114
115    // Complete the hash and produce a final hash result.
116    fn complete_sha256(&self) {
117        let mut buffered_length = self.buffered_length.get();
118        // This shouldn't be necessary, as temp buffer should never be
119        // full. But if it is full, appending the 1 will be an
120        // out-of-bounds access and panic, so check and clear
121        // the buffered block just in case.
122        if buffered_length == 64 {
123            self.data_buffer.map(|b| {
124                self.compute_block(b);
125                for i in 0..SHA_BLOCK_LEN_BYTES {
126                    b[i] = 0;
127                }
128            });
129            buffered_length -= 64;
130        }
131        if buffered_length < 64 {
132            self.data_buffer.map(|b| {
133                for i in buffered_length..SHA_BLOCK_LEN_BYTES {
134                    b[i] = 0;
135                }
136            });
137        }
138
139        self.data_buffer.map(|b| {
140            // Append the 1
141            b.get_mut(buffered_length).map(|d| *d = 0x80);
142            //b[buffered_length] = 0x80;
143            buffered_length += 1;
144            // The length is 56 because of the 8 bytes appended.
145            // Since a block is 64 bytes, this means the last block
146            // must have at most 56 bytes including the appended 1, or
147            // it will bleed into the next block.
148            if buffered_length > 56 {
149                for i in buffered_length..SHA_BLOCK_LEN_BYTES {
150                    b[i] = 0;
151                }
152                self.compute_block(b);
153                for i in 0..SHA_BLOCK_LEN_BYTES {
154                    b[i] = 0;
155                }
156                buffered_length = 0;
157            }
158            let total_length = self.total_length.get();
159            let length64 = (total_length * 8) as u64;
160            let len_high: u32 = (length64 >> 32) as u32;
161            let len_low: u32 = (length64 & 0xffffffff) as u32;
162            b[56] = (len_high >> 24 & 0xff) as u8;
163            b[57] = (len_high >> 16 & 0xff) as u8;
164            b[58] = (len_high >> 8 & 0xff) as u8;
165            b[59] = (len_high >> 0 & 0xff) as u8;
166            b[60] = (len_low >> 24 & 0xff) as u8;
167            b[61] = (len_low >> 16 & 0xff) as u8;
168            b[62] = (len_low >> 8 & 0xff) as u8;
169            b[63] = (len_low >> 0 & 0xff) as u8;
170            self.compute_block(b);
171        });
172    }
173
174    // This method computes SHA256 on data in input_data,
175    // updating the internal hash state. `data_buffer`
176    // contains input data that did or does not fill a block:
177    // the implementation first fills temp_buffer and computes
178    // on it, then operates on input_data. If the end of
179    // input_data does not complete a block then the remainder
180    // is stored in data_buffer.
181    fn compute_sha256(&self) {
182        if let Some(mut data) = self.input_data.take() {
183            let data_length = data.len();
184            self.total_length.set(self.total_length.get() + data_length);
185            let mut buffered_length = self.buffered_length.get();
186            if buffered_length != 0 {
187                // Copy bytes into the front of the temp buffer and
188                // compute if it fills.
189                self.data_buffer.map(|b| {
190                    let copy_len = if data_length + buffered_length >= SHA_BLOCK_LEN_BYTES {
191                        SHA_BLOCK_LEN_BYTES - buffered_length
192                    } else {
193                        data_length
194                    };
195
196                    for i in 0..copy_len {
197                        b[i + buffered_length] = data[i];
198                    }
199                    data.slice(copy_len..data.len());
200                    buffered_length += copy_len;
201
202                    if buffered_length == SHA_BLOCK_LEN_BYTES {
203                        self.compute_block(b);
204                        buffered_length = 0;
205                    }
206                });
207            }
208            // Process blocks
209            while data.len() >= 64 {
210                self.compute_buffer(&data[0..64]);
211                data.slice(64..data.len());
212            }
213            // Process tail end of block
214            if data.len() != 0 {
215                self.data_buffer.map(|b| {
216                    for i in 0..data.len() {
217                        b[i] = data[i];
218                    }
219                    buffered_length = data.len();
220                    // Go to end of data.
221                    data.slice(data.len()..data.len());
222                });
223            }
224            self.input_data.set(data);
225            self.buffered_length.set(buffered_length);
226        } else { /* do nothing, no data */
227        }
228    }
229
230    fn right_rotate(&self, x: u32, rotate: u32) -> u32 {
231        (x >> rotate) | (x << (32 - rotate))
232    }
233
234    // Note: slice MUST be >= 64 bytes long
235    fn compute_buffer(&self, buffer: &[u8]) {
236        // This is clearly inefficient (copy a u8 array into a u32
237        // array), but it's better than using unsafe.  This
238        // implementation is not intended to be high performance.
239        let mut message_schedule: [u32; 64] = [0; 64];
240        for i in 0..16 {
241            let val: u32 = (buffer[i * 4 + 0] as u32) << 24
242                | (buffer[i * 4 + 1] as u32) << 16
243                | (buffer[i * 4 + 2] as u32) << 8
244                | (buffer[i * 4 + 3] as u32);
245            message_schedule[i] = val;
246        }
247        self.perform_sha(&mut message_schedule);
248    }
249
250    fn compute_block(&self, data: &[u8; 64]) {
251        self.compute_buffer(data);
252    }
253
254    fn perform_sha(&self, message_schedule: &mut [u32; 64]) {
255        // Message schedule
256        for i in 16..64 {
257            let mut s0 = self.right_rotate(message_schedule[i - 15], 7);
258            s0 ^= self.right_rotate(message_schedule[i - 15], 18);
259            s0 ^= message_schedule[i - 15] >> 3;
260            let mut s1 = self.right_rotate(message_schedule[i - 2], 17);
261            s1 ^= self.right_rotate(message_schedule[i - 2], 19);
262            s1 ^= message_schedule[i - 2] >> 10;
263            message_schedule[i] = message_schedule[i - 16] + s0 + message_schedule[i - 7] + s1;
264        }
265
266        // Compression
267        let mut hashes = self.hash_values.get();
268        for i in 0..64 {
269            let s1 = self.right_rotate(hashes[4], 6)
270                ^ self.right_rotate(hashes[4], 11)
271                ^ self.right_rotate(hashes[4], 25);
272            let ch = (hashes[4] & hashes[5]) ^ ((!hashes[4]) & hashes[6]);
273            let constant = ROUND_CONSTANTS[i];
274            let temp1 = hashes[7] + s1 + ch + constant + message_schedule[i];
275            let s0 = self.right_rotate(hashes[0], 2)
276                ^ self.right_rotate(hashes[0], 13)
277                ^ self.right_rotate(hashes[0], 22);
278            let maj = (hashes[0] & hashes[1]) ^ (hashes[0] & hashes[2]) ^ (hashes[1] & hashes[2]);
279            let temp2 = s0 + maj;
280
281            hashes[7] = hashes[6];
282            hashes[6] = hashes[5];
283            hashes[5] = hashes[4];
284            hashes[4] = hashes[3].wrapping_add(temp1);
285            hashes[3] = hashes[2];
286            hashes[2] = hashes[1];
287            hashes[1] = hashes[0];
288            hashes[0] = temp1.wrapping_add(temp2);
289        }
290
291        let mut new_hashes = self.hash_values.get();
292        for i in 0..8 {
293            new_hashes[i] = new_hashes[i].wrapping_add(hashes[i]);
294        }
295        self.hash_values.set(new_hashes);
296    }
297}
298
299impl<'a> DigestData<'a, 32> for Sha256Software<'a> {
300    fn add_data(
301        &self,
302        data: SubSlice<'static, u8>,
303    ) -> Result<(), (ErrorCode, SubSlice<'static, u8>)> {
304        if self.busy() {
305            Err((ErrorCode::BUSY, data))
306        } else {
307            self.state.set(State::Data);
308            self.deferred_call.set();
309            self.input_data.set(SubSliceMutImmut::Immutable(data));
310            self.compute_sha256();
311            Ok(())
312        }
313    }
314
315    fn add_mut_data(
316        &self,
317        data: SubSliceMut<'static, u8>,
318    ) -> Result<(), (ErrorCode, SubSliceMut<'static, u8>)> {
319        if self.busy() {
320            Err((ErrorCode::BUSY, data))
321        } else {
322            self.state.set(State::Data);
323            self.deferred_call.set();
324            self.input_data.set(SubSliceMutImmut::Mutable(data));
325            self.compute_sha256();
326            Ok(())
327        }
328    }
329
330    fn clear_data(&self) {
331        self.initialize();
332    }
333
334    fn set_data_client(&'a self, _client: &'a (dyn ClientData<32> + 'a)) {
335        unimplemented!()
336    }
337}
338
339impl<'a> DigestHash<'a, 32> for Sha256Software<'a> {
340    fn run(
341        &'a self,
342        digest: &'static mut [u8; 32],
343    ) -> Result<(), (ErrorCode, &'static mut [u8; 32])> {
344        if self.busy() {
345            Err((ErrorCode::BUSY, digest))
346        } else {
347            self.state.set(State::Hash);
348            self.complete_sha256();
349            for i in 0..8 {
350                let val = self.hash_values.get()[i];
351                digest[4 * i + 3] = (val >> 0 & 0xff) as u8;
352                digest[4 * i + 2] = (val >> 8 & 0xff) as u8;
353                digest[4 * i + 1] = (val >> 16 & 0xff) as u8;
354                digest[4 * i + 0] = (val >> 24 & 0xff) as u8;
355            }
356            self.output_data.set(Some(digest));
357            self.deferred_call.set();
358            Ok(())
359        }
360    }
361
362    fn set_hash_client(&'a self, _client: &'a (dyn ClientHash<32> + 'a)) {
363        unimplemented!()
364    }
365}
366
367impl<'a> DigestVerify<'a, 32> for Sha256Software<'a> {
368    fn verify(
369        &'a self,
370        compare: &'static mut [u8; 32],
371    ) -> Result<(), (ErrorCode, &'static mut [u8; 32])> {
372        if self.busy() {
373            Err((ErrorCode::BUSY, compare))
374        } else {
375            self.state.set(State::Verify);
376            self.complete_sha256();
377            self.output_data.set(Some(compare));
378            self.deferred_call.set();
379            Ok(())
380        }
381    }
382
383    fn set_verify_client(&'a self, _client: &'a (dyn ClientVerify<32> + 'a)) {
384        unimplemented!()
385    }
386}
387
388impl<'a> Digest<'a, 32> for Sha256Software<'a> {
389    fn set_client(&'a self, client: &'a dyn Client<32>) {
390        self.client.set(client);
391    }
392}
393
394impl DeferredCallClient for Sha256Software<'_> {
395    fn handle_deferred_call(&self) {
396        let prior = self.state.get();
397        self.state.set(State::Idle);
398        match prior {
399            State::Idle => {}
400            State::Verify => {
401                // Do the verification here so we don't have to store
402                // the result across the callback.
403                let output = self.output_data.replace(None).unwrap();
404                let mut pass = true;
405                for i in 0..8 {
406                    let hashval = self.hash_values.get()[i];
407                    if output[4 * i + 3] != (hashval >> 0 & 0xff) as u8
408                        || output[4 * i + 2] != (hashval >> 8 & 0xff) as u8
409                        || output[4 * i + 1] != (hashval >> 16 & 0xff) as u8
410                        || output[4 * i + 0] != (hashval >> 24 & 0xff) as u8
411                    {
412                        pass = false;
413                        break;
414                    }
415                }
416                self.state.set(State::Idle);
417                self.clear_data();
418                self.client.map(|c| {
419                    c.verification_done(Ok(pass), output);
420                });
421            }
422            State::Data => {
423                // Data already computed in method call
424                let data = self.input_data.take().unwrap();
425                self.state.set(State::Idle);
426                match data {
427                    SubSliceMutImmut::Mutable(buffer) => {
428                        self.client.map(|client| {
429                            client.add_mut_data_done(Ok(()), buffer);
430                        });
431                    }
432                    SubSliceMutImmut::Immutable(buffer) => {
433                        self.client.map(|client| {
434                            client.add_data_done(Ok(()), buffer);
435                        });
436                    }
437                }
438            }
439            State::Hash => {
440                // Hash already copied in method call.
441                let output = self.output_data.replace(None).unwrap();
442                self.state.set(State::Idle);
443                self.clear_data();
444                self.client.map(|c| {
445                    c.hash_done(Ok(()), output);
446                });
447            }
448            State::CancelData => {
449                self.state.set(State::Idle);
450                self.clear_data();
451                let data = self.input_data.take().unwrap();
452                match data {
453                    SubSliceMutImmut::Mutable(buffer) => {
454                        self.client.map(|client| {
455                            client.add_mut_data_done(Err(ErrorCode::CANCEL), buffer);
456                        });
457                    }
458                    SubSliceMutImmut::Immutable(buffer) => {
459                        self.client.map(|client| {
460                            client.add_data_done(Err(ErrorCode::CANCEL), buffer);
461                        });
462                    }
463                }
464            }
465            State::CancelVerify => {
466                self.state.set(State::Idle);
467                self.clear_data();
468                let output = self.output_data.replace(None).unwrap();
469                self.client.map(|client| {
470                    client.verification_done(Err(ErrorCode::CANCEL), output);
471                });
472            }
473            State::CancelHash => {
474                self.state.set(State::Idle);
475                self.clear_data();
476                let output = self.output_data.replace(None).unwrap();
477                self.client.map(|client| {
478                    client.hash_done(Err(ErrorCode::CANCEL), output);
479                });
480            }
481        }
482    }
483
484    fn register(&'static self) {
485        self.deferred_call.register(self);
486    }
487}
488
489impl Sha256 for Sha256Software<'_> {
490    /// Call before adding data to perform Sha256
491    fn set_mode_sha256(&self) -> Result<(), ErrorCode> {
492        Ok(())
493    }
494}
495
496impl<'a> DigestDataHash<'a, 32> for Sha256Software<'a> {
497    fn set_client(&'a self, _client: &'a dyn ClientDataHash<32>) {
498        unimplemented!()
499    }
500}
501
502impl<'a> DigestDataVerify<'a, 32> for Sha256Software<'a> {
503    fn set_client(&'a self, _client: &'a dyn ClientDataVerify<32>) {
504        unimplemented!()
505    }
506}