2
2
//!
3
3
//! [RFC 8018 Section 6.2]: https://tools.ietf.org/html/rfc8018#section-6.2
4
4
5
+ mod kdf;
6
+
5
7
#[ cfg( feature = "pbes2" ) ]
6
8
mod encryption;
7
9
10
+ pub use self :: kdf:: * ;
11
+
8
12
use crate :: { AlgorithmIdentifier , CryptoError , ObjectIdentifier } ;
9
13
use core:: convert:: { TryFrom , TryInto } ;
10
14
use der:: { Any , Decodable , Encodable , Encoder , Error , ErrorKind , Length , Message , OctetString } ;
11
15
12
16
#[ cfg( all( feature = "alloc" , feature = "pbes2" ) ) ]
13
17
use alloc:: vec:: Vec ;
14
18
15
- /// Password-Based Encryption Scheme 2 (PBES2) OID.
16
- ///
17
- /// <https://tools.ietf.org/html/rfc8018#section-6.2>
18
- pub const PBES2_OID : ObjectIdentifier = ObjectIdentifier :: new ( "1.2.840.113549.1.5.13" ) ;
19
-
20
- /// Password-Based Key Derivation Function (PBKDF2) OID.
21
- pub const PBKDF2_OID : ObjectIdentifier = ObjectIdentifier :: new ( "1.2.840.113549.1.5.12" ) ;
22
-
23
- /// HMAC-SHA1 (for use with PBKDF2)
24
- pub const HMAC_WITH_SHA1_OID : ObjectIdentifier = ObjectIdentifier :: new ( "1.2.840.113549.2.7" ) ;
25
-
26
- /// HMAC-SHA-256 (for use with PBKDF2)
27
- pub const HMAC_WITH_SHA256_OID : ObjectIdentifier = ObjectIdentifier :: new ( "1.2.840.113549.2.9" ) ;
28
-
29
19
/// 128-bit Advanced Encryption Standard (AES) algorithm with Cipher-Block
30
20
/// Chaining (CBC) mode of operation.
31
21
pub const AES_128_CBC_OID : ObjectIdentifier = ObjectIdentifier :: new ( "2.16.840.1.101.3.4.1.2" ) ;
@@ -34,6 +24,11 @@ pub const AES_128_CBC_OID: ObjectIdentifier = ObjectIdentifier::new("2.16.840.1.
34
24
/// Chaining (CBC) mode of operation.
35
25
pub const AES_256_CBC_OID : ObjectIdentifier = ObjectIdentifier :: new ( "2.16.840.1.101.3.4.1.42" ) ;
36
26
27
+ /// Password-Based Encryption Scheme 2 (PBES2) OID.
28
+ ///
29
+ /// <https://tools.ietf.org/html/rfc8018#section-6.2>
30
+ pub const PBES2_OID : ObjectIdentifier = ObjectIdentifier :: new ( "1.2.840.113549.1.5.13" ) ;
31
+
37
32
/// AES cipher block size
38
33
const AES_BLOCK_SIZE : usize = 16 ;
39
34
@@ -175,253 +170,6 @@ impl<'a> Message<'a> for Parameters<'a> {
175
170
}
176
171
}
177
172
178
- /// Password-based key derivation function.
179
- #[ derive( Clone , Debug , Eq , PartialEq ) ]
180
- #[ non_exhaustive]
181
- pub enum Kdf < ' a > {
182
- /// Password-Based Key Derivation Function 2 (PBKDF2).
183
- Pbkdf2 ( Pbkdf2Params < ' a > ) ,
184
- }
185
-
186
- impl < ' a > Kdf < ' a > {
187
- /// Get the [`ObjectIdentifier`] (a.k.a OID) for this algorithm.
188
- pub fn oid ( & self ) -> ObjectIdentifier {
189
- match self {
190
- Self :: Pbkdf2 ( _) => PBKDF2_OID ,
191
- }
192
- }
193
-
194
- /// Get [`Pbkdf2Params`] if it is the selected algorithm.
195
- pub fn pbkdf2 ( & self ) -> Option < & Pbkdf2Params < ' a > > {
196
- match self {
197
- Self :: Pbkdf2 ( params) => Some ( params) ,
198
- }
199
- }
200
-
201
- /// Is the selected KDF PBKDF2?
202
- pub fn is_pbkdf2 ( & self ) -> bool {
203
- self . pbkdf2 ( ) . is_some ( )
204
- }
205
- }
206
-
207
- impl < ' a > From < Pbkdf2Params < ' a > > for Kdf < ' a > {
208
- fn from ( params : Pbkdf2Params < ' a > ) -> Self {
209
- Kdf :: Pbkdf2 ( params)
210
- }
211
- }
212
-
213
- impl < ' a > TryFrom < Any < ' a > > for Kdf < ' a > {
214
- type Error = Error ;
215
-
216
- fn try_from ( any : Any < ' a > ) -> der:: Result < Self > {
217
- AlgorithmIdentifier :: try_from ( any) . and_then ( TryInto :: try_into)
218
- }
219
- }
220
-
221
- impl < ' a > TryFrom < AlgorithmIdentifier < ' a > > for Kdf < ' a > {
222
- type Error = Error ;
223
-
224
- fn try_from ( alg : AlgorithmIdentifier < ' a > ) -> der:: Result < Self > {
225
- match alg. oid {
226
- PBKDF2_OID => alg
227
- . parameters_any ( )
228
- . and_then ( TryFrom :: try_from)
229
- . map ( Self :: Pbkdf2 ) ,
230
- oid => Err ( ErrorKind :: UnknownOid { oid } . into ( ) ) ,
231
- }
232
- }
233
- }
234
-
235
- impl < ' a > Message < ' a > for Kdf < ' a > {
236
- fn fields < F , T > ( & self , f : F ) -> der:: Result < T >
237
- where
238
- F : FnOnce ( & [ & dyn Encodable ] ) -> der:: Result < T > ,
239
- {
240
- match self {
241
- Self :: Pbkdf2 ( params) => f ( & [ & self . oid ( ) , params] ) ,
242
- }
243
- }
244
- }
245
-
246
- /// Password-Based Key Derivation Scheme 2 parameters as defined in
247
- /// [RFC 8018 Appendix A.2].
248
- ///
249
- /// ```text
250
- /// PBKDF2-params ::= SEQUENCE {
251
- /// salt CHOICE {
252
- /// specified OCTET STRING,
253
- /// otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
254
- /// },
255
- /// iterationCount INTEGER (1..MAX),
256
- /// keyLength INTEGER (1..MAX) OPTIONAL,
257
- /// prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT
258
- /// algid-hmacWithSHA1 }
259
- /// ```
260
- ///
261
- /// [RFC 8018 Appendix A.2]: https://tools.ietf.org/html/rfc8018#appendix-A.2
262
- #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
263
- pub struct Pbkdf2Params < ' a > {
264
- /// PBKDF2 salt
265
- // TODO(tarcieri): support `CHOICE` with `otherSource`
266
- pub salt : & ' a [ u8 ] ,
267
-
268
- /// PBKDF2 iteration count
269
- pub iteration_count : u16 ,
270
-
271
- /// PBKDF2 output length
272
- // TODO(tarcieri): support this OPTIONAL field
273
- // Blocked on: https://github.com/RustCrypto/utils/issues/271
274
- pub key_length : Option < u16 > ,
275
-
276
- /// Pseudo-random function to use with PBKDF2
277
- pub prf : Pbkdf2Prf ,
278
- }
279
-
280
- impl < ' a > Pbkdf2Params < ' a > {
281
- /// Initialize PBKDF2-SHA256 with the given iteration count and salt
282
- pub fn hmac_with_sha256 ( iteration_count : u16 , salt : & ' a [ u8 ] ) -> Result < Self , CryptoError > {
283
- Ok ( Self {
284
- salt,
285
- iteration_count,
286
- key_length : None ,
287
- prf : Pbkdf2Prf :: HmacWithSha256 ,
288
- } )
289
- }
290
- }
291
-
292
- impl < ' a > TryFrom < Any < ' a > > for Pbkdf2Params < ' a > {
293
- type Error = Error ;
294
-
295
- fn try_from ( any : Any < ' a > ) -> der:: Result < Self > {
296
- any. sequence ( |params| {
297
- // TODO(tarcieri): support salt `CHOICE` w\ `AlgorithmIdentifier`
298
- let salt = params. octet_string ( ) ?;
299
- let iteration_count = params. decode ( ) ?;
300
-
301
- // TODO(tarcieri): support OPTIONAL key length field
302
- // Blocked on: https://github.com/RustCrypto/utils/issues/271
303
- let key_length = None ;
304
- let prf: Option < AlgorithmIdentifier < ' _ > > = params. optional ( ) ?;
305
-
306
- Ok ( Self {
307
- salt : salt. as_bytes ( ) ,
308
- iteration_count,
309
- key_length,
310
- prf : prf. map ( TryInto :: try_into) . transpose ( ) ?. unwrap_or_default ( ) ,
311
- } )
312
- } )
313
- }
314
- }
315
-
316
- impl < ' a > Message < ' a > for Pbkdf2Params < ' a > {
317
- fn fields < F , T > ( & self , f : F ) -> der:: Result < T >
318
- where
319
- F : FnOnce ( & [ & dyn Encodable ] ) -> der:: Result < T > ,
320
- {
321
- if self . prf == Pbkdf2Prf :: default ( ) {
322
- f ( & [
323
- & OctetString :: new ( self . salt ) ?,
324
- & self . iteration_count ,
325
- & self . key_length ,
326
- ] )
327
- } else {
328
- f ( & [
329
- & OctetString :: new ( self . salt ) ?,
330
- & self . iteration_count ,
331
- & self . key_length ,
332
- & self . prf ,
333
- ] )
334
- }
335
- }
336
- }
337
-
338
- /// Pseudo-random function used by PBKDF2.
339
- #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
340
- #[ non_exhaustive]
341
- pub enum Pbkdf2Prf {
342
- /// HMAC with SHA1
343
- HmacWithSha1 ,
344
-
345
- /// HMAC with SHA-256
346
- HmacWithSha256 ,
347
- }
348
-
349
- impl Pbkdf2Prf {
350
- /// Get the [`ObjectIdentifier`] (a.k.a OID) for this algorithm.
351
- pub fn oid ( self ) -> ObjectIdentifier {
352
- match self {
353
- Self :: HmacWithSha1 => HMAC_WITH_SHA1_OID ,
354
- Self :: HmacWithSha256 => HMAC_WITH_SHA256_OID ,
355
- }
356
- }
357
- }
358
-
359
- /// Default PRF as specified in RFC 8018 Appendix A.2:
360
- ///
361
- /// ```text
362
- /// prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
363
- /// ```
364
- ///
365
- /// Note that modern usage should avoid the use of SHA-1, despite it being
366
- /// the "default" here.
367
- impl Default for Pbkdf2Prf {
368
- fn default ( ) -> Self {
369
- Self :: HmacWithSha1
370
- }
371
- }
372
-
373
- impl < ' a > TryFrom < Any < ' a > > for Pbkdf2Prf {
374
- type Error = Error ;
375
-
376
- fn try_from ( any : Any < ' a > ) -> der:: Result < Self > {
377
- AlgorithmIdentifier :: try_from ( any) . and_then ( TryInto :: try_into)
378
- }
379
- }
380
-
381
- impl < ' a > TryFrom < AlgorithmIdentifier < ' a > > for Pbkdf2Prf {
382
- type Error = Error ;
383
-
384
- fn try_from ( alg : AlgorithmIdentifier < ' a > ) -> der:: Result < Self > {
385
- if let Some ( params) = alg. parameters {
386
- // TODO(tarcieri): support non-NULL parameters?
387
- if !params. is_null ( ) {
388
- return Err ( ErrorKind :: Value { tag : params. tag ( ) } . into ( ) ) ;
389
- }
390
- } else {
391
- // TODO(tarcieri): support OPTIONAL parameters?
392
- return Err ( ErrorKind :: Truncated . into ( ) ) ;
393
- }
394
-
395
- match alg. oid {
396
- HMAC_WITH_SHA1_OID => Ok ( Self :: HmacWithSha1 ) ,
397
- HMAC_WITH_SHA256_OID => Ok ( Self :: HmacWithSha256 ) ,
398
- oid => Err ( ErrorKind :: UnknownOid { oid } . into ( ) ) ,
399
- }
400
- }
401
- }
402
-
403
- impl < ' a > From < Pbkdf2Prf > for AlgorithmIdentifier < ' a > {
404
- fn from ( prf : Pbkdf2Prf ) -> Self {
405
- // TODO(tarcieri): support non-NULL parameters?
406
- let parameters = der:: Null ;
407
-
408
- AlgorithmIdentifier {
409
- oid : prf. oid ( ) ,
410
- parameters : Some ( parameters. into ( ) ) ,
411
- }
412
- }
413
- }
414
-
415
- impl Encodable for Pbkdf2Prf {
416
- fn encoded_len ( & self ) -> der:: Result < Length > {
417
- AlgorithmIdentifier :: try_from ( * self ) ?. encoded_len ( )
418
- }
419
-
420
- fn encode ( & self , encoder : & mut Encoder < ' _ > ) -> der:: Result < ( ) > {
421
- AlgorithmIdentifier :: try_from ( * self ) ?. encode ( encoder)
422
- }
423
- }
424
-
425
173
/// Symmetric encryption scheme used by PBES2.
426
174
#[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
427
175
#[ non_exhaustive]
0 commit comments