@@ -183,7 +183,7 @@ class CryptAlgo(object):
183
183
"""
184
184
185
185
def __init__ (self , name , cipher , mode , block_size = None , iv_size = None ,
186
- key_size = None , icv_size = None , salt_size = None ):
186
+ key_size = None , icv_size = None , salt_size = None , format_mode_iv = None ):
187
187
"""
188
188
@param name: the name of this encryption algorithm
189
189
@param cipher: a Cipher module
@@ -199,6 +199,9 @@ def __init__(self, name, cipher, mode, block_size=None, iv_size=None,
199
199
Used by Combined Mode Algorithms e.g. GCM
200
200
@param salt_size: the length of the salt to use as the IV prefix.
201
201
Usually used by Counter modes e.g. CTR
202
+ @param format_mode_iv: function to format the Initialization Vector
203
+ e.g. handle the salt value
204
+ Default is the random buffer from `generate_iv`
202
205
"""
203
206
self .name = name
204
207
self .cipher = cipher
@@ -235,6 +238,11 @@ def __init__(self, name, cipher, mode, block_size=None, iv_size=None,
235
238
else :
236
239
self .salt_size = salt_size
237
240
241
+ if format_mode_iv is None :
242
+ self ._format_mode_iv = lambda iv , ** kw : iv
243
+ else :
244
+ self ._format_mode_iv = format_mode_iv
245
+
238
246
def check_key (self , key ):
239
247
"""
240
248
Check that the key length is valid.
@@ -251,31 +259,31 @@ def generate_iv(self):
251
259
"""
252
260
# XXX: Handle counter modes with real counters? RFCs allow the use of
253
261
# XXX: random bytes for counters, so it is not wrong to do it that way
254
- return os .urandom (self .iv_size - self . salt_size )
262
+ return os .urandom (self .iv_size )
255
263
256
264
@crypto_validator
257
- def new_cipher (self , key , iv , digest = None ):
265
+ def new_cipher (self , key , mode_iv , digest = None ):
258
266
"""
259
- @param key: the secret key, a byte string
260
- @param iv: the initialization vector, a byte string. Used as the
261
- initial nonce in counter mode
262
- @param digest: also known as tag or icv. A byte string containing the
263
- digest of the encrypted data. Only use this during
264
- decryption!
267
+ @param key: the secret key, a byte string
268
+ @param mode_iv: the initialization vector or nonce , a byte string.
269
+ Formatted by `format_mode_iv`.
270
+ @param digest: also known as tag or icv. A byte string containing the
271
+ digest of the encrypted data. Only use this during
272
+ decryption!
265
273
266
274
@return: an initialized cipher object for this algo
267
275
"""
268
276
if self .is_aead and digest is not None :
269
277
# With AEAD, the mode needs the digest during decryption.
270
278
return Cipher (
271
279
self .cipher (key ),
272
- self .mode (iv , digest , len (digest )),
280
+ self .mode (mode_iv , digest , len (digest )),
273
281
default_backend (),
274
282
)
275
283
else :
276
284
return Cipher (
277
285
self .cipher (key ),
278
- self .mode (iv ),
286
+ self .mode (mode_iv ),
279
287
default_backend (),
280
288
)
281
289
@@ -314,10 +322,11 @@ def pad(self, esp):
314
322
315
323
return esp
316
324
317
- def encrypt (self , esp , key ):
325
+ def encrypt (self , sa , esp , key ):
318
326
"""
319
327
Encrypt an ESP packet
320
328
329
+ @param sa: the SecurityAssociation associated with the ESP packet.
321
330
@param esp: an unencrypted _ESPPlain packet with valid padding
322
331
@param key: the secret key used for encryption
323
332
@@ -326,7 +335,8 @@ def encrypt(self, esp, key):
326
335
data = esp .data_for_encryption ()
327
336
328
337
if self .cipher :
329
- cipher = self .new_cipher (key , esp .iv )
338
+ mode_iv = self ._format_mode_iv (algo = self , sa = sa , iv = esp .iv )
339
+ cipher = self .new_cipher (key , mode_iv )
330
340
encryptor = cipher .encryptor ()
331
341
332
342
if self .is_aead :
@@ -339,10 +349,11 @@ def encrypt(self, esp, key):
339
349
340
350
return ESP (spi = esp .spi , seq = esp .seq , data = esp .iv + data )
341
351
342
- def decrypt (self , esp , key , icv_size = None ):
352
+ def decrypt (self , sa , esp , key , icv_size = None ):
343
353
"""
344
354
Decrypt an ESP packet
345
355
356
+ @param sa: the SecurityAssociation associated with the ESP packet.
346
357
@param esp: an encrypted ESP packet
347
358
@param key: the secret key used for encryption
348
359
@param icv_size: the length of the icv used for integrity check
@@ -359,7 +370,8 @@ def decrypt(self, esp, key, icv_size=None):
359
370
icv = esp .data [len (esp .data ) - icv_size :]
360
371
361
372
if self .cipher :
362
- cipher = self .new_cipher (key , iv , icv )
373
+ mode_iv = self ._format_mode_iv (sa = sa , iv = iv )
374
+ cipher = self .new_cipher (key , mode_iv , icv )
363
375
decryptor = cipher .decryptor ()
364
376
365
377
if self .is_aead :
@@ -402,20 +414,29 @@ def decrypt(self, esp, key, icv_size=None):
402
414
CRYPT_ALGOS ['AES-CBC' ] = CryptAlgo ('AES-CBC' ,
403
415
cipher = algorithms .AES ,
404
416
mode = modes .CBC )
417
+ _aes_ctr_format_mode_iv = lambda sa , iv , ** kw : sa .crypt_salt + iv + b'\x00 \x00 \x00 \x01 '
405
418
CRYPT_ALGOS ['AES-CTR' ] = CryptAlgo ('AES-CTR' ,
406
419
cipher = algorithms .AES ,
407
420
mode = modes .CTR ,
408
- salt_size = 4 )
421
+ iv_size = 8 ,
422
+ salt_size = 4 ,
423
+ format_mode_iv = _aes_ctr_format_mode_iv )
424
+ _salt_format_mode_iv = lambda sa , iv , ** kw : sa .crypt_salt + iv
409
425
CRYPT_ALGOS ['AES-GCM' ] = CryptAlgo ('AES-GCM' ,
410
426
cipher = algorithms .AES ,
411
427
mode = modes .GCM ,
412
428
salt_size = 4 ,
413
- icv_size = 16 )
429
+ iv_size = 8 ,
430
+ icv_size = 16 ,
431
+ format_mode_iv = _salt_format_mode_iv )
414
432
if hasattr (modes , 'CCM' ):
415
433
CRYPT_ALGOS ['AES-CCM' ] = CryptAlgo ('AES-CCM' ,
416
434
cipher = algorithms .AES ,
417
435
mode = modes .CCM ,
418
- icv_size = 16 )
436
+ iv_size = 8 ,
437
+ salt_size = 3 ,
438
+ icv_size = 16 ,
439
+ format_mode_iv = _salt_format_mode_iv )
419
440
# XXX: Flagged as weak by 'cryptography'. Kept for backward compatibility
420
441
CRYPT_ALGOS ['Blowfish' ] = CryptAlgo ('Blowfish' ,
421
442
cipher = algorithms .Blowfish ,
@@ -806,8 +827,6 @@ def _encrypt_esp(self, pkt, seq_num=None, iv=None):
806
827
807
828
if iv is None :
808
829
iv = self .crypt_algo .generate_iv ()
809
- if self .crypt_salt :
810
- iv = self .crypt_salt + iv
811
830
else :
812
831
if len (iv ) != self .crypt_algo .iv_size :
813
832
raise TypeError ('iv length must be %s' % self .crypt_algo .iv_size )
@@ -832,7 +851,7 @@ def _encrypt_esp(self, pkt, seq_num=None, iv=None):
832
851
esp .nh = nh
833
852
834
853
esp = self .crypt_algo .pad (esp )
835
- esp = self .crypt_algo .encrypt (esp , self .crypt_key )
854
+ esp = self .crypt_algo .encrypt (self , esp , self .crypt_key )
836
855
837
856
self .auth_algo .sign (esp , self .auth_key )
838
857
@@ -938,7 +957,7 @@ def _decrypt_esp(self, pkt, verify=True):
938
957
self .check_spi (pkt )
939
958
self .auth_algo .verify (encrypted , self .auth_key )
940
959
941
- esp = self .crypt_algo .decrypt (encrypted , self .crypt_key ,
960
+ esp = self .crypt_algo .decrypt (self , encrypted , self .crypt_key ,
942
961
self .crypt_algo .icv_size or
943
962
self .auth_algo .icv_size )
944
963
0 commit comments