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
|
//! Elliptic Curve Diffie-Hellman.
use crate::vec_truncate;
use crate::{Error, Result};
use crate::crypto::mem::Protected;
use crate::types::HashAlgorithm;
pub use crate::crypto::backend::ecdh::{encrypt, decrypt};
pub use crate::crypto::backend::ecdh::{encrypt_shared, decrypt_shared};
pub use crate::crypto::backend::ecdh::{aes_key_wrap, aes_key_unwrap};
/// Derives a secret key for session key wrapping.
///
/// See [Section 7 of RFC 6637].
///
/// [Section 7 of RFC 6637]: https://tools.ietf.org/html/rfc6637#section-7
pub fn kdf(x: &Protected, obits: usize, hash: HashAlgorithm, param: &[u8])
-> Result<Protected> {
let mut hash = hash.context()?;
if obits > hash.digest_size() {
return Err(
Error::InvalidArgument("Hash digest too short".into()).into());
}
hash.update(&[0, 0, 0, 1]);
hash.update(x);
hash.update(param);
// Providing a smaller buffer will truncate the digest.
let mut key: Protected = vec![0; obits].into();
hash.digest(&mut key);
Ok(key)
}
/// Pads a session key using PKCS5.
///
/// See [Section 8 of RFC 6637].
///
/// [Section 8 of RFC 6637]: https://tools.ietf.org/html/rfc6637#section-8
pub fn pkcs5_pad(sk: Protected, target_len: usize) -> Protected {
let mut buf: Vec<u8> = unsafe {
sk.into_vec()
};
let missing = target_len - buf.len();
assert!(missing <= 0xff);
for _ in 0..missing {
buf.push(missing as u8);
}
assert_eq!(buf.len(), target_len);
buf.into()
}
/// Removes PKCS5 padding from a session key.
///
/// See [Section 8 of RFC 6637].
///
/// [Section 8 of RFC 6637]: https://tools.ietf.org/html/rfc6637#section-8
pub fn pkcs5_unpad(sk: Protected, target_len: usize) -> Result<Protected> {
if sk.len() > 0xff {
return Err(Error::InvalidArgument("message too large".into()).into());
}
if sk.len() < target_len {
return Err(Error::InvalidArgument("message too small".into()).into());
}
let mut buf: Vec<u8> = unsafe {
sk.into_vec()
};
let mut good = true;
let missing = (buf.len() - target_len) as u8;
for &b in &buf[target_len..] {
good = b == missing && good;
}
if good {
vec_truncate(&mut buf, target_len);
Ok(buf.into())
} else {
let sk: Protected = buf.into();
drop(sk);
Err(Error::InvalidArgument("bad padding".into()).into())
}
}
|