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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::result::Result;
use openssl::{hash, pkey, sign};
use opcua_types::status_code::StatusCode;
use crate::{SHA1_SIZE, SHA256_SIZE};
pub fn p_sha(
message_digest: hash::MessageDigest,
secret: &[u8],
seed: &[u8],
length: usize,
) -> Vec<u8> {
let mut result = Vec::with_capacity(length);
let mut hmac = Vec::with_capacity(seed.len() * 2);
let mut a_last = Vec::with_capacity(seed.len());
a_last.extend_from_slice(seed);
while result.len() < length {
let a_next = hmac_vec(message_digest, secret, &a_last);
let bytes = {
hmac.clear();
hmac.extend(&a_next);
hmac.extend_from_slice(seed);
hmac_vec(message_digest, secret, &hmac)
};
result.extend(&bytes);
a_last.clear();
a_last.extend(&a_next);
}
result.truncate(length);
result
}
fn hmac_vec(digest: hash::MessageDigest, key: &[u8], data: &[u8]) -> Vec<u8> {
let pkey = pkey::PKey::hmac(key).unwrap();
let mut signer = sign::Signer::new(digest, &pkey).unwrap();
signer.update(data).unwrap();
signer.sign_to_vec().unwrap()
}
fn hmac(
digest: hash::MessageDigest,
key: &[u8],
data: &[u8],
signature: &mut [u8],
) -> Result<(), StatusCode> {
let hmac = hmac_vec(digest, key, data);
trace!("hmac length = {}", hmac.len());
signature.copy_from_slice(&hmac);
Ok(())
}
pub fn hmac_sha1(key: &[u8], data: &[u8], signature: &mut [u8]) -> Result<(), StatusCode> {
if signature.len() == SHA1_SIZE {
hmac(hash::MessageDigest::sha1(), key, data, signature)
} else {
error!(
"Signature buffer length must be exactly {} bytes to receive hmac_sha1 signature",
SHA1_SIZE
);
Err(StatusCode::BadInvalidArgument)
}
}
pub fn verify_hmac_sha1(key: &[u8], data: &[u8], signature: &[u8]) -> bool {
if signature.len() != SHA1_SIZE {
false
} else {
let mut tmp_signature = [0u8; SHA1_SIZE];
if hmac_sha1(key, data, &mut tmp_signature).is_err() {
false
} else {
trace!("Original signature = {:?}", signature);
trace!("Calculated signature = {:?}", tmp_signature);
openssl::memcmp::eq(signature, &tmp_signature[..])
}
}
}
pub fn hmac_sha256(key: &[u8], data: &[u8], signature: &mut [u8]) -> Result<(), StatusCode> {
if signature.len() == SHA256_SIZE {
hmac(hash::MessageDigest::sha256(), key, data, signature)
} else {
error!(
"Signature buffer length must be exactly {} bytes to receive hmac_sha256 signature",
SHA256_SIZE
);
Err(StatusCode::BadInvalidArgument)
}
}
pub fn verify_hmac_sha256(key: &[u8], data: &[u8], signature: &[u8]) -> bool {
if signature.len() != SHA256_SIZE {
false
} else {
let mut tmp_signature = [0u8; SHA256_SIZE];
if hmac_sha256(key, data, &mut tmp_signature).is_err() {
false
} else {
openssl::memcmp::eq(signature, &tmp_signature[..])
}
}
}