1 # =============================================================================
2 # Copyright (c) 2008 Christophe Oosterlynck (christophe.oosterlynck@gmail.com)
3 # Philippe Teuwen (philippe.teuwen@nxp.com)
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # =============================================================================
23 from ..Util
import util
24 from array
import array
26 from ..Util
.padding
import Padding
28 from exceptions
import Exception
38 class Error(Exception):
39 """Base class for exceptions in this module."""
42 class InputError(Error
):
43 """Exception raised for errors in the input.
46 expression -- input expression in which the error occurred
47 message -- explanation of the error
50 def __init__(self
, expression
, message
):
51 self
.expression
= expression
52 self
.message
= message
55 """ Base class for all blockciphers
58 key_error_message
= "Wrong key size" #should be overwritten in child classes
60 def __init__(self
,key
,mode
,IV
,counter
,cipher_module
,args
={}):
61 # Cipher classes inheriting from this one take care of:
69 if 'keylen_valid' in dir(self
): #wrappers for pycrypto functions don't have this function
70 if not self
.keylen_valid(key
) and type(key
) is not tuple:
71 raise ValueError(self
.key_error_message
)
74 self
.cipher
= cipher_module(self
.key
,**args
)
76 self
.chain
= ECB(self
.cipher
, self
.blocksize
)
77 elif mode
== MODE_CBC
:
79 raise Exception,"Provide an IV!"
80 if len(IV
) <> self
.blocksize
:
81 raise Exception,"the IV length should be %i bytes"%self
.blocksize
82 self
.chain
= CBC(self
.cipher
, self
.blocksize
,IV
)
83 elif mode
== MODE_CFB
:
85 raise Exception,"Provide an IV!"
86 if len(IV
) <> self
.blocksize
:
87 raise Exception,"the IV length should be %i bytes"%self
.blocksize
88 self
.chain
= CFB(self
.cipher
, self
.blocksize
,IV
)
89 elif mode
== MODE_OFB
:
91 raise Exception,"Provide an IV!"
92 if len(IV
) <> self
.blocksize
:
93 raise ValueError("the IV length should be %i bytes"%self
.blocksize
)
94 self
.chain
= OFB(self
.cipher
, self
.blocksize
,IV
)
95 elif mode
== MODE_CTR
:
96 if (counter
== None) or not callable(counter
):
97 raise Exception,"Supply a valid counter object for the CTR mode"
98 self
.chain
= CTR(self
.cipher
,self
.blocksize
,counter
)
99 elif mode
== MODE_XTS
:
100 if self
.blocksize
<> 16:
101 raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
102 if not(type(key
) == tuple and len(key
) == 2):
103 raise Exception,'Supply two keys as a tuple when using XTS'
104 if 'keylen_valid' in dir(self
): #wrappers for pycrypto functions don't have this function
105 if not self
.keylen_valid(key
[0]) or not self
.keylen_valid(key
[1]):
106 raise ValueError(self
.key_error_message
)
107 self
.cipher
= cipher_module(self
.key
[0],**args
)
108 self
.cipher2
= cipher_module(self
.key
[1],**args
)
109 self
.chain
= XTS(self
.cipher
, self
.cipher2
)
110 elif mode
== MODE_CMAC
:
111 if self
.blocksize
not in (8,16):
112 raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
113 self
.chain
= CMAC(self
.cipher
,self
.blocksize
)
115 raise Exception,"Unknown chaining mode!"
117 def encrypt(self
,plaintext
,n
=''):
118 """Encrypt some plaintext
120 plaintext = a string of binary data
121 n = the 'tweak' value when the chaining mode is XTS
123 The encrypt function will encrypt the supplied plaintext.
124 The behavior varies slightly depending on the chaining mode.
128 When the supplied plaintext is not a multiple of the blocksize
129 of the cipher, then the remaining plaintext will be cached.
130 The next time the encrypt function is called with some plaintext,
131 the new plaintext will be concatenated to the cache and then
132 cache+plaintext will be encrypted.
136 When the chaining mode allows the cipher to act as a stream cipher,
137 the encrypt function will always encrypt all of the supplied
138 plaintext immediately. No cache will be kept.
142 Because the handling of the last two blocks is linked,
143 it needs the whole block of plaintext to be supplied at once.
144 Every encrypt function called on a XTS cipher will output
145 an encrypted block based on the current supplied plaintext block.
149 Everytime the function is called, the hash from the input data is calculated.
150 No finalizing needed.
151 The hashlength is equal to block size of the used block cipher.
153 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
154 # None if nothing happened with the chain yet
155 #assert self.ed in ('e',None)
156 # makes sure you don't encrypt with a cipher that has started decrypting
158 if self
.mode
== MODE_XTS
:
159 # data sequence number (or 'tweak') has to be provided when in XTS mode
160 return self
.chain
.update(plaintext
,'e',n
)
162 return self
.chain
.update(plaintext
,'e')
164 def decrypt(self
,ciphertext
,n
=''):
165 """Decrypt some ciphertext
167 ciphertext = a string of binary data
168 n = the 'tweak' value when the chaining mode is XTS
170 The decrypt function will decrypt the supplied ciphertext.
171 The behavior varies slightly depending on the chaining mode.
175 When the supplied ciphertext is not a multiple of the blocksize
176 of the cipher, then the remaining ciphertext will be cached.
177 The next time the decrypt function is called with some ciphertext,
178 the new ciphertext will be concatenated to the cache and then
179 cache+ciphertext will be decrypted.
183 When the chaining mode allows the cipher to act as a stream cipher,
184 the decrypt function will always decrypt all of the supplied
185 ciphertext immediately. No cache will be kept.
189 Because the handling of the last two blocks is linked,
190 it needs the whole block of ciphertext to be supplied at once.
191 Every decrypt function called on a XTS cipher will output
192 a decrypted block based on the current supplied ciphertext block.
196 Mode not supported for decryption as this does not make sense.
198 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
199 # None if nothing happened with the chain yet
200 #assert self.ed in ('d',None)
201 # makes sure you don't decrypt with a cipher that has started encrypting
203 if self
.mode
== MODE_XTS
:
204 # data sequence number (or 'tweak') has to be provided when in XTS mode
205 return self
.chain
.update(ciphertext
,'d',n
)
207 return self
.chain
.update(ciphertext
,'d')
209 def final(self
,padding
='PKCS7'):
210 # TODO: after calling final, reset the IV? so the cipher is as good as new?
211 """Finalizes the encryption by padding the cache
213 padding = padding function provided as an argument. Possible padding functions:
220 While a cipher object is in encryption mode, the final function will pad the remaining cache and encrypt it.
221 If the cipher has been used for decryption, the final function won't do antyhing. You have to manually unpad if necessary or
222 construct a Padder yourself en use its unpad function.
224 After finalization, the chain can still be used but the IV, counter etc aren't reset but just continu as they were after the last step (finalization step).
226 assert self
.mode
not in (MODE_XTS
, MODE_CMAC
) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
228 # when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
229 padder
= Padding(self
.blocksize
)
230 if self
.mode
in (MODE_OFB
,MODE_CFB
,MODE_CTR
):
231 dummy
= '0'*(self
.blocksize
- self
.chain
.keystream
.buffer_info()[1]) # a dummy string that will be used to get a valid padding
233 dummy
= self
.chain
.cache
234 return self
.chain
.update(padder
.pad(dummy
,padding
)[len(dummy
):],'e') # pad the cache and then only supply the padding to the update function
236 # final function doesn't make sense when decrypting => padding should be removed manually
242 def __init__(self
, codebook
, blocksize
):
244 self
.codebook
= codebook
245 self
.blocksize
= blocksize
247 def update(self
, data
, ed
):
248 """Processes the given ciphertext/plaintext
251 data: raw string of any length
252 ed: 'e' for encryption, 'd' for decryption
254 processed raw string block(s), if any
256 When the supplied data is not a multiple of the blocksize
257 of the cipher, then the remaining input data will be cached.
258 The next time the update function is called with some data,
259 the new data will be concatenated to the cache and then
260 cache+data will be processed and full blocks will be outputted.
264 if len(self
.cache
) < self
.blocksize
:
266 for i
in xrange(0, len(self
.cache
)-self
.blocksize
+1, self
.blocksize
):
267 #the only difference between encryption/decryption in the chain is the cipher block
269 output_blocks
.append(self
.codebook
.encrypt( self
.cache
[i
:i
+ self
.blocksize
] ))
271 output_blocks
.append(self
.codebook
.decrypt( self
.cache
[i
:i
+ self
.blocksize
] ))
272 self
.cache
= self
.cache
[i
+self
.blocksize
:]
273 return ''.join(output_blocks
)
278 def __init__(self
, codebook
, blocksize
, IV
):
281 self
.codebook
= codebook
282 self
.blocksize
= blocksize
284 def update(self
, data
, ed
):
285 """Processes the given ciphertext/plaintext
288 data: raw string of any length
289 ed: 'e' for encryption, 'd' for decryption
291 processed raw string block(s), if any
293 When the supplied data is not a multiple of the blocksize
294 of the cipher, then the remaining input data will be cached.
295 The next time the update function is called with some data,
296 the new data will be concatenated to the cache and then
297 cache+data will be processed and full blocks will be outputted.
300 encrypted_blocks
= ''
302 if len(self
.cache
) < self
.blocksize
:
304 for i
in xrange(0, len(self
.cache
)-self
.blocksize
+1, self
.blocksize
):
305 self
.IV
= self
.codebook
.encrypt(util
.xorstring(self
.cache
[i
:i
+self
.blocksize
],self
.IV
))
306 encrypted_blocks
+= self
.IV
307 self
.cache
= self
.cache
[i
+self
.blocksize
:]
308 return encrypted_blocks
310 decrypted_blocks
= ''
312 if len(self
.cache
) < self
.blocksize
:
314 for i
in xrange(0, len(self
.cache
)-self
.blocksize
+1, self
.blocksize
):
315 plaintext
= util
.xorstring(self
.IV
,self
.codebook
.decrypt(self
.cache
[i
:i
+ self
.blocksize
]))
316 self
.IV
= self
.cache
[i
:i
+ self
.blocksize
]
317 decrypted_blocks
+=plaintext
318 self
.cache
= self
.cache
[i
+self
.blocksize
:]
319 return decrypted_blocks
324 Can be accessed as a stream cipher.
327 def __init__(self
, codebook
, blocksize
, IV
):
328 self
.codebook
= codebook
330 self
.blocksize
= blocksize
332 def update(self
, data
, ed
):
333 """Processes the given ciphertext/plaintext
336 data: raw string of any multiple of bytes
337 ed: 'e' for encryption, 'd' for decryption
341 The encrypt/decrypt functions will always process all of the supplied
342 input data immediately. No cache will be kept.
346 for i
in xrange(len(data
)):
348 if len(self
.keystream
) == 0:
349 block
= self
.codebook
.encrypt(self
.IV
)
350 self
.keystream
= list(block
)
352 output
[i
] = chr(ord(output
[i
]) ^
ord(self
.keystream
.pop(0)))
353 self
.IV
+= output
[i
] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
355 if len(self
.keystream
) == 0:
356 block
= self
.codebook
.encrypt(self
.IV
)
357 self
.keystream
= list(block
)
360 output
[i
] = chr(ord(output
[i
]) ^
ord(self
.keystream
.pop(0)))
361 return ''.join(output
)
366 Can be accessed as a stream cipher.
368 def __init__(self
, codebook
, blocksize
, IV
):
369 self
.codebook
= codebook
371 self
.blocksize
= blocksize
372 self
.keystream
=array('B', '')
373 def update(self
, data
, ed
):
374 """Processes the given ciphertext/plaintext
377 data: raw string of any multiple of bytes
378 ed: 'e' for encryption, 'd' for decryption
382 The encrypt/decrypt functions will always process all of the supplied
383 input data immediately. No cache will be kept.
385 #no difference between encryption and decryption mode
387 blocksize
= self
.blocksize
388 output
= array('B', data
)
391 if self
.keystream
.buffer_info()[1] == 0: #encrypt a new counter block when the current keystream is fully used
392 self
.IV
= self
.codebook
.encrypt(self
.IV
)
393 self
.keystream
= array('B', self
.IV
)
394 output
[i
] ^
= self
.keystream
.pop(0) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
395 return output
.tostring()
400 Can be accessed as a stream cipher.
402 # initial counter value can be choosen, decryption always starts from beginning
403 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
404 def __init__(self
, codebook
, blocksize
, counter
):
405 self
.codebook
= codebook
406 self
.counter
= counter
407 self
.blocksize
= blocksize
408 self
.keystream
=array('B', '') #holds the output of the current encrypted counter value
410 def update(self
, data
, ed
):
411 """Processes the given ciphertext/plaintext
414 data: raw string of any multiple of bytes
415 ed: 'e' for encryption, 'd' for decryption
419 The encrypt/decrypt functions will always process all of the supplied
420 input data immediately. No cache will be kept.
422 # no need for the encryption/decryption distinction: both are the same
424 blocksize
= self
.blocksize
426 output
= array('B', data
)
428 if self
.keystream
.buffer_info()[1] == 0: #encrypt a new counter block when the current keystream is fully used
429 block
= self
.codebook
.encrypt(self
.counter())
430 self
.keystream
= array('B', block
)
431 output
[i
] ^
= self
.keystream
.pop(0) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
432 return output
.tostring()
437 # TODO: allow other blocksizes besides 16bytes?
438 def __init__(self
,codebook1
, codebook2
):
440 self
.codebook1
= codebook1
441 self
.codebook2
= codebook2
443 def update(self
, data
, ed
,tweak
=''):
444 # supply n as a raw string
445 # tweak = data sequence number
446 """Perform a XTS encrypt/decrypt operation.
448 Because the handling of the last two blocks is linked,
449 it needs the whole block of ciphertext to be supplied at once.
450 Every decrypt function called on a XTS cipher will output
451 a decrypted block based on the current supplied ciphertext block.
454 assert len(data
) > 15, "At least one block of 128 bits needs to be supplied"
455 assert len(data
) < 128*pow(2,20)
458 # e_k2_n = E_K2(tweak)
459 e_k2_n
= self
.codebook2
.encrypt(tweak
+ '\x00' * (16-len(tweak
)))[::-1]
460 self
.T
= util
.string2number(e_k2_n
)
463 while i
< ((len(data
) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
464 # C = E_K1(P xor T) xor T
465 output
+= self
.__xts
_step
(ed
,data
[i
*16:(i
+1)*16],self
.T
)
466 # T = E_K2(n) mul (a pow i)
470 # Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
471 if len(data
[i
*16:]) == 16:
472 # C = E_K1(P xor T) xor T
473 output
+= self
.__xts
_step
(ed
,data
[i
*16:(i
+1)*16],self
.T
)
474 # T = E_K2(n) mul (a pow i)
479 T_temp
.append(self
.T
)
481 # Permutation of the last two indexes
483 # Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
484 Cm1
= data
[i
*16:(i
+1)*16]
486 PP
= self
.__xts
_step
(ed
,Cm1
,T_temp
[0])
490 Pm1
= self
.__xts
_step
(ed
,CC
,T_temp
[1])
494 def __xts_step(self
,ed
,tocrypt
,T
):
495 T_string
= util
.number2string_N(T
,16)[::-1]
496 # C = E_K1(P xor T) xor T
498 return util
.xorstring(T_string
, self
.codebook1
.decrypt(util
.xorstring(T_string
, tocrypt
)))
500 return util
.xorstring(T_string
, self
.codebook1
.encrypt(util
.xorstring(T_string
, tocrypt
)))
502 def __T_update(self
):
503 # Used for calculating T for a certain step using the T value from the previous step
507 #T[0] ^= GF_128_FDBK;
508 self
.T
= self
.T ^
0x100000000000000000000000000000087L
512 """CMAC chaining mode
514 Supports every cipher with a blocksize available
515 in the list CMAC.supported_blocksizes.
516 The hashlength is equal to block size of the used block cipher.
518 # TODO: move to hash module?
519 # TODO: change update behaviour to .update() and .digest() as for all hash modules?
520 # -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
521 __Rb_dictionary
= {64:0x000000000000001b,128:0x00000000000000000000000000000087}
522 supported_blocksizes
= __Rb_dictionary
.keys()
523 def __init__(self
,codebook
,blocksize
):
524 # Purpose of init: calculate Lu & Lu2
525 #blocksize (in bytes): to select the Rb constant in the dictionary
526 #Rb as a dictionary: adding support for other blocksizes is easy
528 self
.blocksize
= blocksize
529 self
.codebook
= codebook
531 #Rb_dictionary: holds values for Rb for different blocksizes
532 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
533 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
534 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
535 # the lexicographically first among all such polynomials with the minimum possible number of
536 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
537 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
539 self
.Rb
= self
.__Rb
_dictionary
[blocksize
*8]
541 mask1
= int(('\xff'*blocksize
).encode('hex'),16)
542 mask2
= int(('\x80' + '\x00'*(blocksize
-1) ).encode('hex'),16)
544 L
= int(self
.codebook
.encrypt('\x00'*blocksize
).encode('hex'),16)
547 Lu
= ((L
<< 1) & mask1
) ^ self
.Rb
553 Lu2
= ((Lu
<< 1) & mask1
)^ self
.Rb
558 self
.Lu
=util
.number2string_N(Lu
,self
.blocksize
)
559 self
.Lu2
=util
.number2string_N(Lu2
,self
.blocksize
)
561 def update(self
, data
, ed
):
562 """Processes the given ciphertext/plaintext
565 data: raw string of any length
566 ed: 'e' for encryption, 'd' for decryption
568 hashed data as raw string
570 This is not really an update function:
571 Everytime the function is called, the hash from the input data is calculated.
572 No finalizing needed.
575 blocksize
= self
.blocksize
577 m
= (len(data
)+blocksize
-1)/blocksize
#m = amount of datablocks
581 y
= self
.codebook
.encrypt( util
.xorstring(data
[(i
-1)*blocksize
:(i
)*blocksize
],y
) )
583 if len(data
[(i
)*blocksize
:])==blocksize
:
584 X
= util
.xorstring(util
.xorstring(data
[(i
)*blocksize
:],y
),self
.Lu
)
586 tmp
= data
[(i
)*blocksize
:] + '\x80' + '\x00'*(blocksize
- len(data
[(i
)*blocksize
:])-1)
587 X
= util
.xorstring(util
.xorstring(tmp
,y
),self
.Lu2
)
589 T
= self
.codebook
.encrypt(X
)