1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use crate::crypto::{rc, sha256};
use crate::result::*;
use core::ptr;
use core::mem;
pub struct Context {
sha_ctx: sha256::Context,
key: [u32; sha256::BLOCK_SIZE_32],
mac: [u32; sha256::HASH_SIZE_32],
finalized: bool
}
impl Context {
pub fn new(key: &[u8]) -> Result<Self> {
let mut ctx = Self {
sha_ctx: sha256::Context::new(),
key: [0; sha256::BLOCK_SIZE_32],
mac: [0; sha256::HASH_SIZE_32],
finalized: false
};
if key.len() <= sha256::BLOCK_SIZE {
unsafe {
ptr::copy(key.as_ptr(), ctx.key.as_mut_ptr() as *mut u8, key.len());
}
}
else {
ctx.sha_ctx.update(key);
ctx.sha_ctx.get_hash(&mut ctx.key)?;
}
for i in 0..ctx.key.len() {
ctx.key[i] ^= super::IPAD_VAL;
}
ctx.sha_ctx.reset();
ctx.sha_ctx.update(&ctx.key);
Ok(ctx)
}
pub fn update<T>(&mut self, data: &[T]) {
self.sha_ctx.update(data);
}
pub fn get_mac<T>(&mut self, out_mac: &mut [T]) -> Result<()> {
result_return_unless!(out_mac.len() * mem::size_of::<T>() == sha256::HASH_SIZE, rc::ResultInvalidSize);
if !self.finalized {
self.sha_ctx.get_hash(&mut self.mac)?;
for i in 0..self.key.len() {
self.key[i] ^= super::IPAD_XOR_OPAD_VAL;
}
self.sha_ctx.reset();
self.sha_ctx.update(&self.key);
self.sha_ctx.update(&self.mac);
self.sha_ctx.get_hash(&mut self.mac)?;
self.finalized = true;
}
unsafe {
ptr::copy(self.mac.as_ptr() as *const u8, out_mac.as_mut_ptr() as *mut u8, sha256::HASH_SIZE);
}
Ok(())
}
}