mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-07-26 04:02:50 +02:00
Implement AES-GMAC-SIV in terms of OpenSSL too.
This commit is contained in:
parent
8681f61de3
commit
4ca8b30044
5 changed files with 303 additions and 8 deletions
61
aes-gmac-siv/Cargo.lock
generated
61
aes-gmac-siv/Cargo.lock
generated
|
@ -7,9 +7,16 @@ name = "aes-gmac-siv"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gcrypt",
|
||||
"openssl",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -71,6 +78,21 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "gcrypt"
|
||||
version = "0.7.0"
|
||||
|
@ -150,6 +172,39 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.5"
|
||||
|
@ -169,6 +224,12 @@ version = "1.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
|
|
|
@ -3,18 +3,15 @@ name = "aes-gmac-siv"
|
|||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[profile.test]
|
||||
opt-level = 3
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = 'abort'
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = 'abort'
|
||||
|
||||
[dependencies]
|
||||
openssl = "^0"
|
||||
|
||||
[target."cfg(not(any(target_os = \"macos\", target_os = \"ios\")))".dependencies]
|
||||
gcrypt = "^0"
|
||||
|
||||
|
|
168
aes-gmac-siv/src/impl_openssl.rs
Normal file
168
aes-gmac-siv/src/impl_openssl.rs
Normal file
|
@ -0,0 +1,168 @@
|
|||
// AES-GMAC-SIV implemented using OpenSSL.
|
||||
|
||||
use std::convert::TryInto;
|
||||
use openssl::symm::{Crypter, Cipher, Mode};
|
||||
|
||||
/// AES-GMAC-SIV encryptor/decryptor.
|
||||
#[repr(align(8))] // allow tag and tmp to be accessed as u64 arrays as well
|
||||
pub struct AesGmacSiv {
|
||||
tag: [u8; 16],
|
||||
tmp: [u8; 16],
|
||||
k0: [u8; 32],
|
||||
k1: [u8; 32],
|
||||
ctr: Option<Crypter>,
|
||||
gmac: Option<Crypter>,
|
||||
}
|
||||
|
||||
impl AesGmacSiv {
|
||||
/// Create a new keyed instance of AES-GMAC-SIV
|
||||
/// The key may be of size 16, 24, or 32 bytes (128, 192, or 256 bits). Any other size will panic.
|
||||
#[inline(always)]
|
||||
pub fn new(k0: &[u8], k1: &[u8]) -> Self {
|
||||
if k0.len() != 32 && k0.len() != 24 && k0.len() != 16 {
|
||||
panic!("AES supports 128, 192, or 256 bits keys");
|
||||
}
|
||||
if k1.len() != k0.len() {
|
||||
panic!("k0 and k1 must be of the same size");
|
||||
}
|
||||
AesGmacSiv {
|
||||
tag: [0_u8; 16],
|
||||
tmp: [0_u8; 16],
|
||||
k0: k0.try_into().unwrap(),
|
||||
k1: k1.try_into().unwrap(),
|
||||
ctr: None,
|
||||
gmac: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset to prepare for another encrypt or decrypt operation.
|
||||
#[inline(always)]
|
||||
pub fn reset(&mut self) {
|
||||
let _ = self.ctr.take();
|
||||
let _ = self.gmac.take();
|
||||
}
|
||||
|
||||
/// Initialize for encryption.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_init(&mut self, iv: &[u8]) {
|
||||
self.tag[0..8].copy_from_slice(iv);
|
||||
self.tag[8..16].fill(0);
|
||||
let _ = self.gmac.replace(Crypter::new(Cipher::aes_256_gcm(), Mode::Encrypt, &self.k0, Some(&self.tag)).unwrap());
|
||||
}
|
||||
|
||||
/// Set additional authenticated data (data to be authenticated but not encrypted).
|
||||
/// This can currently only be called once. Multiple calls will result in corrupt data.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_set_aad(&mut self, data: &[u8]) {
|
||||
let _ = self.gmac.as_mut().unwrap().aad_update(data);
|
||||
let pad = data.len() & 0xf;
|
||||
if pad != 0 {
|
||||
let _ = self.gmac.as_mut().unwrap().aad_update(&crate::ZEROES[0..(16 - pad)]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Feed plaintext in for the first encryption pass.
|
||||
/// This may be called more than once.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_first_pass(&mut self, plaintext: &[u8]) {
|
||||
let _ = self.gmac.as_mut().unwrap().aad_update(plaintext);
|
||||
}
|
||||
|
||||
/// Finish first pass and begin second pass.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_first_pass_finish(&mut self) {
|
||||
let gmac = self.gmac.as_mut().unwrap();
|
||||
let _ = gmac.finalize(&mut self.tmp);
|
||||
let _ = gmac.get_tag(&mut self.tmp);
|
||||
unsafe { // tag[8..16] = tmp[0..8] ^ tmp[8..16]
|
||||
let tmp = self.tmp.as_mut_ptr().cast::<u64>();
|
||||
*self.tag.as_mut_ptr().cast::<u64>().offset(1) = *tmp ^ *tmp.offset(1);
|
||||
}
|
||||
let mut tag_tmp = [0_u8; 32];
|
||||
let _ = Crypter::new(Cipher::aes_256_ecb(), Mode::Encrypt, &self.k1, None).unwrap().update(&self.tag, &mut tag_tmp);
|
||||
self.tag.copy_from_slice(&tag_tmp[0..16]);
|
||||
self.tmp.copy_from_slice(&self.tag);
|
||||
self.tmp[12] &= 0x7f;
|
||||
let _ = self.ctr.replace(Crypter::new(Cipher::aes_256_ctr(), Mode::Encrypt, &self.k1, Some(&self.tmp)).unwrap());
|
||||
}
|
||||
|
||||
/// Feed plaintext for second pass and write ciphertext to supplied buffer.
|
||||
/// This may be called more than once.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_second_pass(&mut self, plaintext: &[u8], ciphertext: &mut [u8]) {
|
||||
let _ = self.ctr.as_mut().unwrap().update(plaintext, ciphertext);
|
||||
}
|
||||
|
||||
/// Encrypt plaintext in place.
|
||||
/// This may be called more than once.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_second_pass_in_place(&mut self, plaintext_to_ciphertext: &mut [u8]) {
|
||||
let _ = self.ctr.as_mut().unwrap().update(unsafe { std::slice::from_raw_parts(plaintext_to_ciphertext.as_ptr(), plaintext_to_ciphertext.len()) }, plaintext_to_ciphertext);
|
||||
}
|
||||
|
||||
/// Finish second pass and return a reference to the tag for this message.
|
||||
/// The tag returned remains valid until reset() is called.
|
||||
#[inline(always)]
|
||||
pub fn encrypt_second_pass_finish(&mut self) -> &[u8; 16] {
|
||||
return &self.tag;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn decrypt_init_internal(&mut self) {
|
||||
self.tmp[12] &= 0x7f;
|
||||
let _ = self.ctr.replace(Crypter::new(Cipher::aes_256_ctr(), Mode::Decrypt, &self.k1, Some(&self.tmp)).unwrap());
|
||||
let mut tag_tmp = [0_u8; 32];
|
||||
let _ = Crypter::new(Cipher::aes_256_ecb(), Mode::Decrypt, &self.k1, None).unwrap().update(&self.tag, &mut tag_tmp);
|
||||
self.tag.copy_from_slice(&tag_tmp[0..16]);
|
||||
unsafe { // tmp[0..8] = tag[0..8], tmp[8..16] = 0
|
||||
let tmp = self.tmp.as_mut_ptr().cast::<u64>();
|
||||
*tmp = *self.tag.as_mut_ptr().cast::<u64>();
|
||||
*tmp.offset(1) = 0;
|
||||
}
|
||||
let _ = self.gmac.replace(Crypter::new(Cipher::aes_256_gcm(), Mode::Encrypt, &self.k0, Some(&self.tmp)).unwrap());
|
||||
}
|
||||
|
||||
/// Initialize this cipher for decryption.
|
||||
/// The supplied tag must be 16 bytes in length. Any other length will panic.
|
||||
#[inline(always)]
|
||||
pub fn decrypt_init(&mut self, tag: &[u8]) {
|
||||
self.tmp.copy_from_slice(tag);
|
||||
self.tag.copy_from_slice(tag);
|
||||
self.decrypt_init_internal();
|
||||
}
|
||||
|
||||
/// Set additional authenticated data to be checked.
|
||||
#[inline(always)]
|
||||
pub fn decrypt_set_aad(&mut self, data: &[u8]) {
|
||||
self.encrypt_set_aad(data);
|
||||
}
|
||||
|
||||
/// Decrypt ciphertext and write to plaintext.
|
||||
/// This may be called more than once.
|
||||
#[inline(always)]
|
||||
pub fn decrypt(&mut self, ciphertext: &[u8], plaintext: &mut [u8]) {
|
||||
let _ = self.ctr.as_mut().unwrap().update(ciphertext, plaintext);
|
||||
let _ = self.gmac.as_mut().unwrap().aad_update(plaintext);
|
||||
}
|
||||
|
||||
/// Decrypt ciphertext in place.
|
||||
/// This may be called more than once.
|
||||
#[inline(always)]
|
||||
pub fn decrypt_in_place(&mut self, ciphertext_to_plaintext: &mut [u8]) {
|
||||
let _ = self.ctr.as_mut().unwrap().update(unsafe { std::slice::from_raw_parts(ciphertext_to_plaintext.as_ptr(), ciphertext_to_plaintext.len()) }, ciphertext_to_plaintext);
|
||||
let _ = self.gmac.as_mut().unwrap().aad_update(ciphertext_to_plaintext);
|
||||
}
|
||||
|
||||
/// Finish decryption and return true if authentication appears valid.
|
||||
/// If this returns false the message should be dropped.
|
||||
#[inline(always)]
|
||||
pub fn decrypt_finish(&mut self) -> bool {
|
||||
let gmac = self.gmac.as_mut().unwrap();
|
||||
let _ = gmac.finalize(&mut self.tmp);
|
||||
let _ = gmac.get_tag(&mut self.tmp);
|
||||
unsafe { // tag[8..16] == tmp[0..8] ^ tmp[8..16]
|
||||
let tmp = self.tmp.as_mut_ptr().cast::<u64>();
|
||||
*self.tag.as_mut_ptr().cast::<u64>().offset(1) == *tmp ^ *tmp.offset(1)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,21 @@
|
|||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
mod impl_macos;
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios", target_arch = "s390x")))]
|
||||
mod impl_gcrypt;
|
||||
|
||||
#[cfg(all(not(any(target_os = "macos", target_os = "ios")), target_arch = "s390x"))]
|
||||
mod impl_openssl;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
pub use impl_macos::AesGmacSiv;
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios", target_arch = "s390x")))]
|
||||
pub use impl_gcrypt::AesGmacSiv;
|
||||
|
||||
#[cfg(all(not(any(target_os = "macos", target_os = "ios")), target_arch = "s390x"))]
|
||||
pub use impl_openssl::AesGmacSiv;
|
||||
|
||||
pub(crate) const ZEROES: [u8; 16] = [0_u8; 16];
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
61
network-hypervisor/Cargo.lock
generated
61
network-hypervisor/Cargo.lock
generated
|
@ -7,8 +7,15 @@ name = "aes-gmac-siv"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gcrypt",
|
||||
"openssl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
|
@ -128,6 +135,21 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "gcrypt"
|
||||
version = "0.7.0"
|
||||
|
@ -264,6 +286,33 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
|
@ -289,6 +338,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
|
@ -463,6 +518,12 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
|
|
Loading…
Add table
Reference in a new issue