@@ -39,6 +39,14 @@ pub const AES_192_CBC_OID: ObjectIdentifier =
3939pub const AES_256_CBC_OID : ObjectIdentifier =
4040 ObjectIdentifier :: new_unwrap ( "2.16.840.1.101.3.4.1.42" ) ;
4141
42+ /// 128-bit Advanced Encryption Standard (AES) algorithm with Galois Counter Mode
43+ pub const AES_128_GCM_OID : ObjectIdentifier =
44+ ObjectIdentifier :: new_unwrap ( "2.16.840.1.101.3.4.1.6" ) ;
45+
46+ /// 256-bit Advanced Encryption Standard (AES) algorithm with Galois Counter Mode
47+ pub const AES_256_GCM_OID : ObjectIdentifier =
48+ ObjectIdentifier :: new_unwrap ( "2.16.840.1.101.3.4.1.46" ) ;
49+
4250/// DES operating in CBC mode
4351#[ cfg( feature = "des-insecure" ) ]
4452pub const DES_CBC_OID : ObjectIdentifier = ObjectIdentifier :: new_unwrap ( "1.3.14.3.2.7" ) ;
@@ -55,6 +63,12 @@ pub const PBES2_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.11
5563/// AES cipher block size
5664const AES_BLOCK_SIZE : usize = 16 ;
5765
66+ /// GCM nonce size
67+ ///
68+ /// We could use any value here but GCM is most efficient
69+ /// with 96 bit nonces
70+ const GCM_NONCE_SIZE : usize = 12 ;
71+
5872/// DES / Triple DES block size
5973#[ cfg( any( feature = "3des" , feature = "des-insecure" ) ) ]
6074const DES_BLOCK_SIZE : usize = 8 ;
@@ -255,6 +269,46 @@ impl Parameters {
255269 Ok ( Self { kdf, encryption } )
256270 }
257271
272+ /// Initialize PBES2 parameters using scrypt as the password-based
273+ /// key derivation function and AES-128-GCM as the symmetric cipher.
274+ ///
275+ /// For more information on scrypt parameters, see documentation for the
276+ /// [`scrypt::Params`] struct.
277+ ///
278+ /// # Errors
279+ /// Propagates errors from [`ScryptParams::from_params_and_salt`].
280+ // TODO(tarcieri): encapsulate `scrypt::Params`?
281+ #[ cfg( feature = "pbes2" ) ]
282+ pub fn scrypt_aes128gcm (
283+ params : scrypt:: Params ,
284+ salt : & [ u8 ] ,
285+ gcm_nonce : [ u8 ; GCM_NONCE_SIZE ] ,
286+ ) -> Result < Self > {
287+ let kdf = ScryptParams :: from_params_and_salt ( params, salt) ?. into ( ) ;
288+ let encryption = EncryptionScheme :: Aes128Gcm { nonce : gcm_nonce } ;
289+ Ok ( Self { kdf, encryption } )
290+ }
291+
292+ /// Initialize PBES2 parameters using scrypt as the password-based
293+ /// key derivation function and AES-256-GCM as the symmetric cipher.
294+ ///
295+ /// For more information on scrypt parameters, see documentation for the
296+ /// [`scrypt::Params`] struct.
297+ ///
298+ /// # Errors
299+ /// Propagates errors from [`ScryptParams::from_params_and_salt`].
300+ // TODO(tarcieri): encapsulate `scrypt::Params`?
301+ #[ cfg( feature = "pbes2" ) ]
302+ pub fn scrypt_aes256gcm (
303+ params : scrypt:: Params ,
304+ salt : & [ u8 ] ,
305+ gcm_nonce : [ u8 ; GCM_NONCE_SIZE ] ,
306+ ) -> Result < Self > {
307+ let kdf = ScryptParams :: from_params_and_salt ( params, salt) ?. into ( ) ;
308+ let encryption = EncryptionScheme :: Aes256Gcm { nonce : gcm_nonce } ;
309+ Ok ( Self { kdf, encryption } )
310+ }
311+
258312 /// Attempt to decrypt the given ciphertext, allocating and returning a
259313 /// byte vector containing the plaintext.
260314 ///
@@ -387,6 +441,18 @@ pub enum EncryptionScheme {
387441 iv : [ u8 ; AES_BLOCK_SIZE ] ,
388442 } ,
389443
444+ /// AES-128 in CBC mode
445+ Aes128Gcm {
446+ /// GCM nonce
447+ nonce : [ u8 ; GCM_NONCE_SIZE ] ,
448+ } ,
449+
450+ /// AES-256 in GCM mode
451+ Aes256Gcm {
452+ /// GCM nonce
453+ nonce : [ u8 ; GCM_NONCE_SIZE ] ,
454+ } ,
455+
390456 /// 3-Key Triple DES in CBC mode
391457 #[ cfg( feature = "3des" ) ]
392458 DesEde3Cbc {
@@ -410,6 +476,8 @@ impl EncryptionScheme {
410476 Self :: Aes128Cbc { .. } => 16 ,
411477 Self :: Aes192Cbc { .. } => 24 ,
412478 Self :: Aes256Cbc { .. } => 32 ,
479+ Self :: Aes128Gcm { .. } => 16 ,
480+ Self :: Aes256Gcm { .. } => 32 ,
413481 #[ cfg( feature = "des-insecure" ) ]
414482 Self :: DesCbc { .. } => 8 ,
415483 #[ cfg( feature = "3des" ) ]
@@ -424,6 +492,8 @@ impl EncryptionScheme {
424492 Self :: Aes128Cbc { .. } => AES_128_CBC_OID ,
425493 Self :: Aes192Cbc { .. } => AES_192_CBC_OID ,
426494 Self :: Aes256Cbc { .. } => AES_256_CBC_OID ,
495+ Self :: Aes128Gcm { .. } => AES_128_GCM_OID ,
496+ Self :: Aes256Gcm { .. } => AES_256_GCM_OID ,
427497 #[ cfg( feature = "des-insecure" ) ]
428498 Self :: DesCbc { .. } => DES_CBC_OID ,
429499 #[ cfg( feature = "3des" ) ]
@@ -468,6 +538,12 @@ impl TryFrom<AlgorithmIdentifierRef<'_>> for EncryptionScheme {
468538 AES_256_CBC_OID => Ok ( Self :: Aes256Cbc {
469539 iv : iv. try_into ( ) . map_err ( |_| Tag :: OctetString . value_error ( ) ) ?,
470540 } ) ,
541+ AES_128_GCM_OID => Ok ( Self :: Aes128Gcm {
542+ nonce : iv. try_into ( ) . map_err ( |_| Tag :: OctetString . value_error ( ) ) ?,
543+ } ) ,
544+ AES_256_GCM_OID => Ok ( Self :: Aes256Gcm {
545+ nonce : iv. try_into ( ) . map_err ( |_| Tag :: OctetString . value_error ( ) ) ?,
546+ } ) ,
471547 #[ cfg( feature = "des-insecure" ) ]
472548 DES_CBC_OID => Ok ( Self :: DesCbc {
473549 iv : iv[ 0 ..DES_BLOCK_SIZE ]
@@ -493,6 +569,8 @@ impl<'a> TryFrom<&'a EncryptionScheme> for AlgorithmIdentifierRef<'a> {
493569 EncryptionScheme :: Aes128Cbc { iv } => iv. as_slice ( ) ,
494570 EncryptionScheme :: Aes192Cbc { iv } => iv. as_slice ( ) ,
495571 EncryptionScheme :: Aes256Cbc { iv } => iv. as_slice ( ) ,
572+ EncryptionScheme :: Aes128Gcm { nonce } => nonce. as_slice ( ) ,
573+ EncryptionScheme :: Aes256Gcm { nonce } => nonce. as_slice ( ) ,
496574 #[ cfg( feature = "des-insecure" ) ]
497575 EncryptionScheme :: DesCbc { iv } => iv. as_slice ( ) ,
498576 #[ cfg( feature = "3des" ) ]
0 commit comments