diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2022-01-10 16:35:54 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2022-02-17 16:11:38 +0100 |
commit | 984f4c6b8040fc969f54ddf1f8b726f94ffd2383 (patch) | |
tree | 020a0333d46625cbfccb4b9576b279d44a95c332 | |
parent | 442f766d6f294399b8986656e942fa1740e22438 (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.rs | 2 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng.rs | 7 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng/aead.rs | 7 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle.rs | 2 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/aead.rs | 24 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust.rs | 7 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/aead.rs | 6 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 3 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 5 | ||||
-rw-r--r-- | openpgp/src/types/mod.rs | 6 |
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) => |