Skip to content

Commit e067249

Browse files
committed
Enabled the psa_mac_compute and psa_mac_verify functions.
Added new tests, fixed doc tests and formatted code. Signed-off-by: Mike Smoot <mes@aescon.com>
1 parent 7695a58 commit e067249

File tree

5 files changed

+250
-60
lines changed

5 files changed

+250
-60
lines changed

psa-crypto/src/operations/mac.rs

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,32 @@
44
//! # Message Authentication Code (MAC) operations
55
66
use crate::initialized;
7-
use crate::types::key::Id;
87
use crate::types::algorithm::Mac;
9-
use crate::types::status::{Result, Status, Error};
10-
8+
use crate::types::key::Id;
9+
use crate::types::status::{Result, Status};
1110

1211
/// Calculate the message authentication code (MAC) of a message
13-
/// The key must allow `sign_message`
12+
/// The key must allow `sign_hash`
1413
///
1514
/// # Example
1615
///
1716
/// ```
1817
/// use psa_crypto::operations::{mac::compute_mac, key_management::generate};
19-
/// use psa_crypto::types::algorithm::{Hash, Mac, FullLengthMac};
18+
/// use psa_crypto::types::algorithm::{Algorithm, Hash, Mac, FullLengthMac};
2019
/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
2120
/// # const MESSAGE: [u8; 32] = [
2221
/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
2322
/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
2423
/// # ];
24+
/// # let mut usage = UsageFlags::default();
25+
/// # let _ = usage.set_sign_hash().set_verify_hash();
2526
/// # let mut attributes = Attributes {
26-
/// # key_type: Type::RsaKeyPair,
27-
/// # bits: 1024,
27+
/// # key_type: Type::Hmac,
28+
/// # bits: 256,
2829
/// # lifetime: Lifetime::Volatile,
2930
/// # policy: Policy {
30-
/// # usage_flags: UsageFlags {
31-
/// # sign_message: true,
32-
/// # ..Default::default()
33-
/// # },
34-
/// # permitted_algorithms: FullLengthMac::Hmac{hash_alg: Hash::Sha256}.into(),
31+
/// # usage_flags: usage,
32+
/// # permitted_algorithms: Algorithm::Mac(Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256})),
3533
/// # },
3634
/// # };
3735
/// #
@@ -42,89 +40,92 @@ use crate::types::status::{Result, Status, Error};
4240
/// let mut mac = vec![0; buffer_size];
4341
///
4442
/// let size = compute_mac(my_key,
45-
/// mac_alg,
46-
/// &MESSAGE,
47-
/// &mut mac).unwrap();
43+
/// mac_alg,
44+
/// &MESSAGE,
45+
/// &mut mac).unwrap();
4846
/// mac.resize(size, 0);
4947
/// ```
50-
pub fn compute_mac(key_id: Id, mac_alg: Mac, input_message: &[u8], mac: &mut [u8]) -> Result<usize> {
48+
pub fn compute_mac(
49+
key_id: Id,
50+
mac_alg: Mac,
51+
input_message: &[u8],
52+
mac: &mut [u8],
53+
) -> Result<usize> {
5154
initialized()?;
5255

5356
let mut output_length = 0;
54-
let key_handle = key_id.handle()?;
5557

5658
let mac_compute_res = Status::from(unsafe {
5759
psa_crypto_sys::psa_mac_compute(
58-
key_handle,
60+
key_id.0,
5961
mac_alg.into(),
6062
input_message.as_ptr(),
6163
input_message.len(),
6264
mac.as_mut_ptr(),
6365
mac.len(),
6466
&mut output_length,
65-
)}
66-
).to_result();
67-
let close_handle_res = key_id.close_handle(key_handle);
67+
)
68+
})
69+
.to_result();
6870
mac_compute_res?;
69-
close_handle_res?;
7071
Ok(output_length)
7172
}
7273

7374
/// Calculate the message authentication code (MAC) of a message and compare it with a reference value
74-
/// The key must allow `sign_message`
75+
/// The key must allow `verify_hash`
7576
///
7677
/// # Example
7778
///
7879
/// ```
7980
/// use psa_crypto::operations::{mac::{compute_mac, verify_mac}, key_management::generate};
80-
/// use psa_crypto::types::algorithm::{Hash, Mac, FullLengthMac};
81+
/// use psa_crypto::types::algorithm::{Algorithm, Hash, Mac, FullLengthMac};
8182
/// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
82-
/// # const MESSAGE: [u8; 32] = [
83-
/// # 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
84-
/// # 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
85-
/// # ];
86-
/// # let mut attributes = Attributes {
87-
/// # key_type: Type::RsaKeyPair,
88-
/// # bits: 1024,
89-
/// # lifetime: Lifetime::Volatile,
90-
/// # policy: Policy {
91-
/// # usage_flags: UsageFlags {
92-
/// # sign_message: true,
93-
/// # ..Default::default()
94-
/// # },
95-
/// # permitted_algorithms: Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256}).into(),
96-
/// # },
97-
/// # };
98-
/// #
83+
/// const MESSAGE: [u8; 32] = [
84+
/// 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
85+
/// 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
86+
/// ];
87+
/// let mut usage = UsageFlags::default();
88+
/// let _ = usage.set_sign_hash().set_verify_hash();
89+
/// let mut attributes = Attributes {
90+
/// key_type: Type::Hmac,
91+
/// bits: 256,
92+
/// lifetime: Lifetime::Volatile,
93+
/// policy: Policy {
94+
/// usage_flags: usage,
95+
/// permitted_algorithms: Algorithm::Mac(Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256})),
96+
/// },
97+
/// };
98+
///
9999
/// psa_crypto::init().unwrap();
100100
/// let my_key = generate(attributes, None).unwrap();
101101
/// let mac_alg = Mac::FullLength(FullLengthMac::Hmac{hash_alg: Hash::Sha256});
102102
/// let buffer_size = attributes.mac_length(mac_alg).unwrap();
103103
/// let mut mac = vec![0; buffer_size];
104104
///
105105
/// let size = compute_mac(my_key,
106-
/// mac_alg,
107-
/// &MESSAGE,
108-
/// &mut mac).unwrap();
106+
/// mac_alg,
107+
/// &MESSAGE,
108+
/// &mut mac).unwrap();
109109
/// mac.resize(size, 0);
110-
/// assert!(verify_mac(my_key, mac_alg, &MESSAGE, &mac));
110+
/// verify_mac(my_key, mac_alg, &MESSAGE, &mac).unwrap();
111111
/// ```
112-
pub fn verify_mac(key_id: Id, mac_alg: Mac, input_message: &[u8], expected_mac: &[u8]) -> Result<()> {
112+
pub fn verify_mac(
113+
key_id: Id,
114+
mac_alg: Mac,
115+
input_message: &[u8],
116+
expected_mac: &[u8],
117+
) -> Result<()> {
113118
initialized()?;
114119

115-
let key_handle = key_id.handle()?;
116-
117-
let mac_verify_res = Status::from(unsafe {
120+
Status::from(unsafe {
118121
psa_crypto_sys::psa_mac_verify(
119-
key_handle,
122+
key_id.0,
120123
mac_alg.into(),
121124
input_message.as_ptr(),
122125
input_message.len(),
123126
expected_mac.as_ptr(),
124127
expected_mac.len(),
125-
)}
126-
).to_result();
127-
let close_handle_res = key_id.close_handle(key_handle);
128-
mac_verify_res?;
129-
close_handle_res
130-
}
128+
)
129+
})
130+
.to_result()
131+
}

psa-crypto/src/operations/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ pub mod aead;
77
pub mod asym_encryption;
88
pub mod asym_signature;
99
pub mod cipher;
10+
pub mod hash;
1011
pub mod key_agreement;
1112
pub mod key_derivation;
1213
pub mod key_management;
13-
//pub mod mac; Mbed Crypto does not support mac compute or verify yet (as of 16/07/20)
14-
pub mod hash;
14+
pub mod mac;
1515
pub mod message_digest;
1616
pub mod other;

psa-crypto/src/types/key.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,17 @@ impl Attributes {
431431
#[cfg(feature = "interface")]
432432
pub fn mac_length(self, mac_alg: Mac) -> Result<usize> {
433433
self.compatible_with_alg(mac_alg.into())?;
434-
Ok(unsafe {
434+
let size = unsafe {
435435
psa_crypto_sys::PSA_MAC_LENGTH(self.key_type.try_into()?, self.bits, mac_alg.into())
436-
})
436+
};
437+
// PSA_MAC_LENGTH will return 0 for incompatible algorithms
438+
// and other errors. Since we need > 0 mac_length to allocate
439+
// space for the mac itself, treat 0 as an error.
440+
if size > 0 {
441+
Ok(size)
442+
} else {
443+
Err(Error::DataInvalid)
444+
}
437445
}
438446

439447
/// Sufficient buffer size for an encrypted message using the given aead algorithm

psa-crypto/tests/mac.rs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
use psa_crypto::operations::key_management::import;
2+
use psa_crypto::operations::mac::{compute_mac, verify_mac};
3+
use psa_crypto::types::algorithm::{Algorithm, FullLengthMac, Hash, Mac};
4+
use psa_crypto::types::key::{Attributes, Lifetime, Policy, Type, UsageFlags};
5+
use psa_crypto::types::status::Result;
6+
7+
const KEY: [u8; 32] = [
8+
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
9+
0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
10+
];
11+
12+
// "hello mac"
13+
const MESSAGE: [u8; 9] = [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x6d, 0x61, 0x63];
14+
15+
const EXPECTED_HMAC_SHA256: [u8; 32] = [
16+
0x6d, 0x20, 0x70, 0xf, 0x9, 0x82, 0x70, 0xf8, 0x6c, 0x42, 0x13, 0xbe, 0xff, 0x13, 0x68, 0x3c,
17+
0x31, 0x79, 0xce, 0xf5, 0x68, 0x56, 0xde, 0xf9, 0xb9, 0x5f, 0x72, 0x9, 0x62, 0xf4, 0xd, 0x8a,
18+
];
19+
const EXPECTED_HMAC_RIPEMD160: [u8; 20] = [
20+
0x39, 0xcf, 0x6b, 0xbd, 0x4a, 0xd6, 0xfd, 0x2c, 0x23, 0xb5, 0xa4, 0x1d, 0x94, 0xe3, 0xde, 0x7f,
21+
0x1c, 0xa3, 0xf0, 0x73,
22+
];
23+
const EXPECTED_CMAC_AES: [u8; 16] = [
24+
0x2b, 0x93, 0xe2, 0xaa, 0x77, 0xb2, 0xb1, 0xe7, 0xa, 0x12, 0xb, 0xfc, 0xaf, 0x47, 0x12, 0xc4,
25+
];
26+
27+
const NOT_EXPECTED: [u8; 1] = [0x00];
28+
29+
fn get_attrs(alg: &Mac, key_type: Type) -> Attributes {
30+
let mut usage = UsageFlags::default();
31+
let _ = usage.set_sign_hash().set_verify_hash();
32+
Attributes {
33+
key_type: key_type.clone(),
34+
bits: 256,
35+
lifetime: Lifetime::Volatile,
36+
policy: Policy {
37+
usage_flags: usage,
38+
permitted_algorithms: Algorithm::Mac(alg.clone()),
39+
},
40+
}
41+
}
42+
43+
fn test_mac_compute(mac_alg: Mac, key_type: Type, expected: &[u8]) -> Result<()> {
44+
println!("{:?}", &mac_alg);
45+
let attributes = get_attrs(&mac_alg, key_type);
46+
psa_crypto::init()?;
47+
let my_key = import(attributes, None, &KEY)?;
48+
let buffer_size = attributes.mac_length(mac_alg)?;
49+
let mut mac = vec![0; buffer_size];
50+
let _size = compute_mac(my_key, mac_alg, &MESSAGE, &mut mac)?;
51+
assert_eq!(expected, mac);
52+
Ok(())
53+
}
54+
55+
fn test_mac_verify(mac_alg: Mac, key_type: Type, expected: &[u8]) -> Result<()> {
56+
println!("{:?}", &mac_alg);
57+
let attributes = get_attrs(&mac_alg, key_type);
58+
psa_crypto::init()?;
59+
let my_key = import(attributes, None, &KEY)?;
60+
let _size = verify_mac(my_key, mac_alg, &MESSAGE, &expected)?;
61+
Ok(())
62+
}
63+
64+
#[test]
65+
fn mac_compute_full_hmac_sha256() {
66+
let mac_alg = Mac::FullLength(FullLengthMac::Hmac {
67+
hash_alg: Hash::Sha256,
68+
});
69+
test_mac_compute(mac_alg, Type::Hmac, &EXPECTED_HMAC_SHA256).expect("successful mac");
70+
}
71+
72+
#[test]
73+
fn mac_compute_full_hmac_ripemd160() {
74+
let mac_alg = Mac::FullLength(FullLengthMac::Hmac {
75+
hash_alg: Hash::Ripemd160,
76+
});
77+
test_mac_compute(mac_alg, Type::Hmac, &EXPECTED_HMAC_RIPEMD160).expect("successful mac");
78+
}
79+
80+
#[test]
81+
fn mac_compute_full_cmac() {
82+
let mac_alg = Mac::FullLength(FullLengthMac::Cmac);
83+
test_mac_compute(mac_alg, Type::Aes, &EXPECTED_CMAC_AES).expect("successful mac");
84+
}
85+
86+
#[test]
87+
fn mac_compute_full_cbcmac() {
88+
let mac_alg = Mac::FullLength(FullLengthMac::CbcMac);
89+
test_mac_compute(mac_alg, Type::Aes, &NOT_EXPECTED).expect_err("CbcMac not supported");
90+
}
91+
92+
#[test]
93+
fn mac_compute_truncated_hmac_sha256() {
94+
let mac_alg = Mac::Truncated {
95+
mac_alg: FullLengthMac::Hmac {
96+
hash_alg: Hash::Sha256,
97+
},
98+
mac_length: 10,
99+
};
100+
test_mac_compute(mac_alg, Type::Hmac, &EXPECTED_HMAC_SHA256[0..10]).expect("successful mac");
101+
}
102+
103+
#[test]
104+
fn mac_compute_truncated_hmac_ripemd160() {
105+
let mac_alg = Mac::Truncated {
106+
mac_alg: FullLengthMac::Hmac {
107+
hash_alg: Hash::Ripemd160,
108+
},
109+
mac_length: 10,
110+
};
111+
test_mac_compute(mac_alg, Type::Hmac, &EXPECTED_HMAC_RIPEMD160[0..10]).expect("successful mac");
112+
}
113+
114+
#[test]
115+
fn mac_compute_truncated_cmac() {
116+
let mac_alg = Mac::Truncated {
117+
mac_alg: FullLengthMac::Cmac,
118+
mac_length: 10,
119+
};
120+
test_mac_compute(mac_alg, Type::Aes, &EXPECTED_CMAC_AES[0..10]).expect("successful mac");
121+
}
122+
123+
#[test]
124+
fn mac_verify_full_hmac_sha256() {
125+
let mac_alg = Mac::FullLength(FullLengthMac::Hmac {
126+
hash_alg: Hash::Sha256,
127+
});
128+
test_mac_verify(mac_alg, Type::Hmac, &EXPECTED_HMAC_SHA256).expect("successful mac");
129+
}
130+
131+
#[test]
132+
fn mac_verify_full_hmac_ripemd160() {
133+
let mac_alg = Mac::FullLength(FullLengthMac::Hmac {
134+
hash_alg: Hash::Ripemd160,
135+
});
136+
test_mac_verify(mac_alg, Type::Hmac, &EXPECTED_HMAC_RIPEMD160).expect("successful mac");
137+
}
138+
139+
#[test]
140+
fn mac_verify_full_cmac() {
141+
let mac_alg = Mac::FullLength(FullLengthMac::Cmac);
142+
test_mac_verify(mac_alg, Type::Aes, &EXPECTED_CMAC_AES).expect("successful mac");
143+
}
144+
145+
#[test]
146+
fn mac_verify_full_cbcmac() {
147+
let mac_alg = Mac::FullLength(FullLengthMac::CbcMac);
148+
test_mac_verify(mac_alg, Type::Aes, &NOT_EXPECTED).expect_err("CbcMac not supported");
149+
}
150+
151+
#[test]
152+
fn mac_verify_truncated_hmac_sha256() {
153+
let mac_alg = Mac::Truncated {
154+
mac_alg: FullLengthMac::Hmac {
155+
hash_alg: Hash::Sha256,
156+
},
157+
mac_length: 10,
158+
};
159+
test_mac_verify(mac_alg, Type::Hmac, &EXPECTED_HMAC_SHA256[0..10]).expect("successful mac");
160+
}
161+
162+
#[test]
163+
fn mac_verify_truncated_hmac_ripemd160() {
164+
let mac_alg = Mac::Truncated {
165+
mac_alg: FullLengthMac::Hmac {
166+
hash_alg: Hash::Ripemd160,
167+
},
168+
mac_length: 10,
169+
};
170+
test_mac_verify(mac_alg, Type::Hmac, &EXPECTED_HMAC_RIPEMD160[0..10]).expect("successful mac");
171+
}
172+
173+
#[test]
174+
fn mac_verify_truncated_cmac() {
175+
let mac_alg = Mac::Truncated {
176+
mac_alg: FullLengthMac::Cmac,
177+
mac_length: 10,
178+
};
179+
test_mac_verify(mac_alg, Type::Aes, &EXPECTED_CMAC_AES[0..10]).expect("successful mac");
180+
}

0 commit comments

Comments
 (0)