summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2022-01-10 16:35:54 +0100
committerJustus Winter <justus@sequoia-pgp.org>2022-02-17 16:11:38 +0100
commit984f4c6b8040fc969f54ddf1f8b726f94ffd2383 (patch)
tree020a0333d46625cbfccb4b9576b279d44a95c332
parent442f766d6f294399b8986656e942fa1740e22438 (diff)
openpgp: Implement GCM mode.justus/openpgp-next-gcm
- The Galois/Counter mode for block ciphers is a FIPS-approved AEAD mode. It will be added to the upcoming OpenPGP standard so that we have a FIPS-compliant subset of OpenPGP. - Currently, this is only implemented by the Nettle backend.
-rw-r--r--openpgp/src/crypto/aead.rs2
-rw-r--r--openpgp/src/crypto/backend/cng.rs7
-rw-r--r--openpgp/src/crypto/backend/cng/aead.rs7
-rw-r--r--openpgp/src/crypto/backend/nettle.rs2
-rw-r--r--openpgp/src/crypto/backend/nettle/aead.rs24
-rw-r--r--openpgp/src/crypto/backend/rust.rs7
-rw-r--r--openpgp/src/crypto/backend/rust/aead.rs6
-rw-r--r--openpgp/src/policy.rs3
-rw-r--r--openpgp/src/serialize/stream.rs5
-rw-r--r--openpgp/src/types/mod.rs6
10 files changed, 60 insertions, 9 deletions
diff --git a/openpgp/src/crypto/aead.rs b/openpgp/src/crypto/aead.rs
index e602c3a1..5c933fda 100644
--- a/openpgp/src/crypto/aead.rs
+++ b/openpgp/src/crypto/aead.rs
@@ -89,6 +89,7 @@ impl AEADAlgorithm {
EAX => Ok(16),
// According to RFC4880bis, Section 5.16.2.
OCB => Ok(16),
+ GCM => Ok(16),
_ => Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
@@ -103,6 +104,7 @@ impl AEADAlgorithm {
// least 15 octets long". GnuPG hardcodes 15 in
// openpgp_aead_algo_info.
OCB => Ok(15),
+ GCM => Ok(12),
_ => Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
diff --git a/openpgp/src/crypto/backend/cng.rs b/openpgp/src/crypto/backend/cng.rs
index 8bf01b02..15c418a2 100644
--- a/openpgp/src/crypto/backend/cng.rs
+++ b/openpgp/src/crypto/backend/cng.rs
@@ -46,9 +46,10 @@ impl AEADAlgorithm {
pub(crate) fn is_supported_by_backend(&self) -> bool {
use self::AEADAlgorithm::*;
match &self {
- EAX
- => true,
- OCB | Private(_) | Unknown(_)
+ EAX => true,
+ OCB => false,
+ GCM => false,
+ Private(_) | Unknown(_)
=> false,
}
}
diff --git a/openpgp/src/crypto/backend/cng/aead.rs b/openpgp/src/crypto/backend/cng/aead.rs
index a7b87613..9bf4fcb9 100644
--- a/openpgp/src/crypto/backend/cng/aead.rs
+++ b/openpgp/src/crypto/backend/cng/aead.rs
@@ -72,7 +72,12 @@ impl AEADAlgorithm {
}
_ => Err(Error::UnsupportedSymmetricAlgorithm(sym_algo).into()),
},
- _ => Err(Error::UnsupportedAEADAlgorithm(self.clone()).into()),
+ AEADAlgorithm::OCB =>
+ Err(Error::UnsupportedAEADAlgorithm(*self).into()),
+ AEADAlgorithm::GCM =>
+ Err(Error::UnsupportedAEADAlgorithm(*self).into()),
+ AEADAlgorithm::Private(_) | AEADAlgorithm::Unknown(_) =>
+ Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
}
diff --git a/openpgp/src/crypto/backend/nettle.rs b/openpgp/src/crypto/backend/nettle.rs
index 9bf737c0..b8a112be 100644
--- a/openpgp/src/crypto/backend/nettle.rs
+++ b/openpgp/src/crypto/backend/nettle.rs
@@ -54,6 +54,8 @@ impl AEADAlgorithm {
match &self {
EAX
=> true,
+ GCM
+ => true,
OCB | Private(_) | Unknown(_)
=> false,
}
diff --git a/openpgp/src/crypto/backend/nettle/aead.rs b/openpgp/src/crypto/backend/nettle/aead.rs
index e7ae9d85..3b950941 100644
--- a/openpgp/src/crypto/backend/nettle/aead.rs
+++ b/openpgp/src/crypto/backend/nettle/aead.rs
@@ -59,6 +59,30 @@ impl AEADAlgorithm {
)),
_ => Err(Error::UnsupportedSymmetricAlgorithm(sym_algo).into()),
},
+ AEADAlgorithm::GCM => match sym_algo {
+ SymmetricAlgorithm::AES128 => Ok(Box::new(
+ aead::Gcm::<cipher::Aes128>::with_key_and_nonce(key, nonce)?,
+ )),
+ SymmetricAlgorithm::AES192 => Ok(Box::new(
+ aead::Gcm::<cipher::Aes192>::with_key_and_nonce(key, nonce)?,
+ )),
+ SymmetricAlgorithm::AES256 => Ok(Box::new(
+ aead::Gcm::<cipher::Aes256>::with_key_and_nonce(key, nonce)?,
+ )),
+ SymmetricAlgorithm::Twofish => Ok(Box::new(
+ aead::Gcm::<cipher::Twofish>::with_key_and_nonce(key, nonce)?,
+ )),
+ SymmetricAlgorithm::Camellia128 => Ok(Box::new(
+ aead::Gcm::<cipher::Camellia128>::with_key_and_nonce(key, nonce)?,
+ )),
+ SymmetricAlgorithm::Camellia192 => Ok(Box::new(
+ aead::Gcm::<cipher::Camellia192>::with_key_and_nonce(key, nonce)?,
+ )),
+ SymmetricAlgorithm::Camellia256 => Ok(Box::new(
+ aead::Gcm::<cipher::Camellia256>::with_key_and_nonce(key, nonce)?,
+ )),
+ _ => Err(Error::UnsupportedSymmetricAlgorithm(sym_algo).into()),
+ },
_ => Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
diff --git a/openpgp/src/crypto/backend/rust.rs b/openpgp/src/crypto/backend/rust.rs
index 1bc6bf05..b46ee345 100644
--- a/openpgp/src/crypto/backend/rust.rs
+++ b/openpgp/src/crypto/backend/rust.rs
@@ -57,9 +57,10 @@ impl AEADAlgorithm {
pub(crate) fn is_supported_by_backend(&self) -> bool {
use self::AEADAlgorithm::*;
match &self {
- EAX
- => true,
- OCB | Private(_) | Unknown(_)
+ EAX => true,
+ OCB => false,
+ GCM => false,
+ Private(_) | Unknown(_)
=> false,
}
}
diff --git a/openpgp/src/crypto/backend/rust/aead.rs b/openpgp/src/crypto/backend/rust/aead.rs
index e5fcdb0b..4a51b427 100644
--- a/openpgp/src/crypto/backend/rust/aead.rs
+++ b/openpgp/src/crypto/backend/rust/aead.rs
@@ -150,7 +150,11 @@ impl AEADAlgorithm {
| SymmetricAlgorithm::Unencrypted =>
Err(Error::UnsupportedSymmetricAlgorithm(sym_algo).into()),
},
- AEADAlgorithm::OCB | AEADAlgorithm::Private(_) | AEADAlgorithm::Unknown(_) =>
+ AEADAlgorithm::OCB =>
+ Err(Error::UnsupportedAEADAlgorithm(*self).into()),
+ AEADAlgorithm::GCM =>
+ Err(Error::UnsupportedAEADAlgorithm(*self).into()),
+ AEADAlgorithm::Private(_) | AEADAlgorithm::Unknown(_) =>
Err(Error::UnsupportedAEADAlgorithm(*self).into()),
}
}
diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs
index 889326c2..c3e9c32b 100644
--- a/openpgp/src/policy.rs
+++ b/openpgp/src/policy.rs
@@ -720,11 +720,12 @@ a_cutoff_list!(SymmetricAlgorithmCutoffList, SymmetricAlgorithm, 14,
ACCEPT, // 13. Camellia256.
]);
-a_cutoff_list!(AEADAlgorithmCutoffList, AEADAlgorithm, 3,
+a_cutoff_list!(AEADAlgorithmCutoffList, AEADAlgorithm, 4,
[
REJECT, // 0. Reserved.
ACCEPT, // 1. EAX.
ACCEPT, // 2. OCB.
+ ACCEPT, // 3. GCM.
]);
a_cutoff_list!(PacketTagCutoffList, Tag, 21,
diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs
index 61fe94e3..62ce3806 100644
--- a/openpgp/src/serialize/stream.rs
+++ b/openpgp/src/serialize/stream.rs
@@ -3399,6 +3399,11 @@ mod test {
test_aead_messages(AEADAlgorithm::EAX)
}
+ #[test]
+ fn aead_gcm() -> Result<()> {
+ test_aead_messages(AEADAlgorithm::GCM)
+ }
+
fn test_aead_messages(algo: AEADAlgorithm) -> Result<()> {
if ! algo.is_supported() {
eprintln!("Skipping because {} is not supported.", algo);
diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs
index bdadccf7..de6c395a 100644
--- a/openpgp/src/types/mod.rs
+++ b/openpgp/src/types/mod.rs
@@ -696,6 +696,8 @@ pub enum AEADAlgorithm {
EAX,
/// OCB mode.
OCB,
+ /// Galois/Counter mode.
+ GCM,
/// Private algorithm identifier.
Private(u8),
/// Unknown algorithm identifier.
@@ -724,6 +726,7 @@ impl From<u8> for AEADAlgorithm {
match u {
1 => AEADAlgorithm::EAX,
2 => AEADAlgorithm::OCB,
+ 3 => AEADAlgorithm::GCM,
100..=110 => AEADAlgorithm::Private(u),
u => AEADAlgorithm::Unknown(u),
}
@@ -735,6 +738,7 @@ impl From<AEADAlgorithm> for u8 {
match s {
AEADAlgorithm::EAX => 1,
AEADAlgorithm::OCB => 2,
+ AEADAlgorithm::GCM => 3,
AEADAlgorithm::Private(u) => u,
AEADAlgorithm::Unknown(u) => u,
}
@@ -748,6 +752,8 @@ impl fmt::Display for AEADAlgorithm {
f.write_str("EAX mode"),
AEADAlgorithm::OCB =>
f.write_str("OCB mode"),
+ AEADAlgorithm::GCM =>
+ f.write_str("GCM mode"),
AEADAlgorithm::Private(u) =>
f.write_fmt(format_args!("Private/Experimental AEAD algorithm {}", u)),
AEADAlgorithm::Unknown(u) =>