cryptoxide/mac.rs
1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7/*!
8 * The mac module defines the Message Authentication Code (`Mac`) trait.
9 */
10
11use crate::constant_time::CtEqual;
12use alloc::vec::Vec;
13
14/**
15 * The `Mac` trait defines methods for a Message Authentication function.
16 */
17pub trait Mac {
18 /**
19 * Process input data.
20 *
21 * # Arguments
22 * * data - The input data to process.
23 *
24 */
25 fn input(&mut self, data: &[u8]);
26
27 /**
28 * Reset the Mac state to begin processing another input stream.
29 */
30 fn reset(&mut self);
31
32 /**
33 * Obtain the result of a Mac computation as a `MacResult`.
34 */
35 fn result(&mut self) -> MacResult;
36
37 /**
38 * Obtain the result of a Mac computation as [u8]. This method should be used very carefully
39 * since incorrect use of the Mac code could result in permitting a timing attack which defeats
40 * the security provided by a Mac function.
41 */
42 fn raw_result(&mut self, output: &mut [u8]);
43
44 /**
45 * Get the size of the Mac code, in bytes.
46 */
47 fn output_bytes(&self) -> usize;
48}
49
50/**
51 * A `MacResult` wraps a Mac code and provides a safe Eq implementation that runs in fixed time.
52 */
53pub struct MacResult {
54 code: Vec<u8>,
55}
56
57impl MacResult {
58 /**
59 * Create a new `MacResult`.
60 */
61 pub fn new(code: &[u8]) -> MacResult {
62 MacResult {
63 code: code.to_vec(),
64 }
65 }
66
67 /**
68 * Create a new `MacResult` taking ownership of the specified code value.
69 */
70 pub fn new_from_owned(code: Vec<u8>) -> MacResult {
71 MacResult { code: code }
72 }
73
74 /**
75 * Get the code value. Be very careful using this method, since incorrect use of the code value
76 * may permit timing attacks which defeat the security provided by the Mac function.
77 */
78 pub fn code(&self) -> &[u8] {
79 &self.code[..]
80 }
81}
82
83impl PartialEq for MacResult {
84 fn eq(&self, x: &MacResult) -> bool {
85 let lhs = self.code();
86 let rhs = x.code();
87 // it's a user error to compare two mac results from two different mac
88 if lhs.len() == rhs.len() {
89 CtEqual::ct_eq(lhs, rhs).into()
90 } else {
91 false
92 }
93 }
94}
95
96impl Eq for MacResult {}