Use IV for AES-CMAC mode
[python-cryptoplus.git] / src / CryptoPlus / Cipher / blockcipher.py
blob6d2ca01fd2b1ca52d5675f66564b44f7a7545d3c
1 # =============================================================================
2 # Copyright (c) 2008 Christophe Oosterlynck <christophe.oosterlynck_AT_gmail.com>
3 # & NXP ( Philippe Teuwen <philippe.teuwen_AT_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
21 # THE SOFTWARE.
22 # =============================================================================
23 from ..Util import util
24 from array import array
25 from ..Util import padding
27 MODE_ECB = 1
28 MODE_CBC = 2
29 MODE_CFB = 3
30 MODE_OFB = 5
31 MODE_CTR = 6
32 MODE_XTS = 7
33 MODE_CMAC = 8
35 class BlockCipher():
36 """ Base class for all blockciphers
37 """
39 key_error_message = "Wrong key size" #should be overwritten in child classes
41 def __init__(self,key,mode,IV,counter,cipher_module,segment_size,args={}):
42 # Cipher classes inheriting from this one take care of:
43 # self.blocksize
44 # self.cipher
45 self.key = key
46 self.mode = mode
47 self.cache = ''
48 self.ed = None
50 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
51 if not self.keylen_valid(key) and type(key) is not tuple:
52 raise ValueError(self.key_error_message)
54 if IV == None:
55 self.IV = '\x00'*self.blocksize
56 else:
57 self.IV = IV
59 if segment_size == None:
60 segment_size = 8
62 if mode <> MODE_XTS:
63 self.cipher = cipher_module(self.key,**args)
64 if mode == MODE_ECB:
65 self.chain = ECB(self.cipher, self.blocksize)
66 elif mode == MODE_CBC:
67 if len(self.IV) <> self.blocksize:
68 raise Exception,"the IV length should be %i bytes"%self.blocksize
69 self.chain = CBC(self.cipher, self.blocksize,self.IV)
70 elif mode == MODE_CFB:
71 if len(self.IV) <> self.blocksize:
72 raise Exception,"the IV length should be %i bytes"%self.blocksize
73 if segment_size > self.blocksize*8 or segment_size%8 <> 0:
74 # current CFB implementation doesn't support bit level acces => segment_size should be multiple of bytes
75 raise ValueError,"segment size should be a multiple of 8 bits between 8 and %i"%(self.blocksize*8)
76 self.chain = CFB(self.cipher, self.blocksize,self.IV,segment_size)
77 elif mode == MODE_OFB:
78 if len(self.IV) <> self.blocksize:
79 raise ValueError("the IV length should be %i bytes"%self.blocksize)
80 self.chain = OFB(self.cipher, self.blocksize,self.IV)
81 elif mode == MODE_CTR:
82 if (counter == None) or not callable(counter):
83 raise Exception,"Supply a valid counter object for the CTR mode"
84 self.chain = CTR(self.cipher,self.blocksize,counter)
85 elif mode == MODE_XTS:
86 if self.blocksize <> 16:
87 raise Exception,'XTS only works with blockcipher that have a 128-bit blocksize'
88 if not(type(key) == tuple and len(key) == 2):
89 raise Exception,'Supply two keys as a tuple when using XTS'
90 if 'keylen_valid' in dir(self): #wrappers for pycrypto functions don't have this function
91 if not self.keylen_valid(key[0]) or not self.keylen_valid(key[1]):
92 raise ValueError(self.key_error_message)
93 self.cipher = cipher_module(self.key[0],**args)
94 self.cipher2 = cipher_module(self.key[1],**args)
95 self.chain = XTS(self.cipher, self.cipher2)
96 elif mode == MODE_CMAC:
97 if self.blocksize not in (8,16):
98 raise Exception,'CMAC only works with blockcipher that have a 64 or 128-bit blocksize'
99 self.chain = CMAC(self.cipher,self.blocksize,self.IV)
100 else:
101 raise Exception,"Unknown chaining mode!"
103 def encrypt(self,plaintext,n=''):
104 """Encrypt some plaintext
106 plaintext = a string of binary data
107 n = the 'tweak' value when the chaining mode is XTS
109 The encrypt function will encrypt the supplied plaintext.
110 The behavior varies slightly depending on the chaining mode.
112 ECB, CBC:
113 ---------
114 When the supplied plaintext is not a multiple of the blocksize
115 of the cipher, then the remaining plaintext will be cached.
116 The next time the encrypt function is called with some plaintext,
117 the new plaintext will be concatenated to the cache and then
118 cache+plaintext will be encrypted.
120 CFB, OFB, CTR:
121 --------------
122 When the chaining mode allows the cipher to act as a stream cipher,
123 the encrypt function will always encrypt all of the supplied
124 plaintext immediately. No cache will be kept.
126 XTS:
127 ----
128 Because the handling of the last two blocks is linked,
129 it needs the whole block of plaintext to be supplied at once.
130 Every encrypt function called on a XTS cipher will output
131 an encrypted block based on the current supplied plaintext block.
133 CMAC:
134 -----
135 Everytime the function is called, the hash from the input data is calculated.
136 No finalizing needed.
137 The hashlength is equal to block size of the used block cipher.
139 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
140 # None if nothing happened with the chain yet
141 #assert self.ed in ('e',None)
142 # makes sure you don't encrypt with a cipher that has started decrypting
143 self.ed = 'e'
144 if self.mode == MODE_XTS:
145 # data sequence number (or 'tweak') has to be provided when in XTS mode
146 return self.chain.update(plaintext,'e',n)
147 else:
148 return self.chain.update(plaintext,'e')
150 def decrypt(self,ciphertext,n=''):
151 """Decrypt some ciphertext
153 ciphertext = a string of binary data
154 n = the 'tweak' value when the chaining mode is XTS
156 The decrypt function will decrypt the supplied ciphertext.
157 The behavior varies slightly depending on the chaining mode.
159 ECB, CBC:
160 ---------
161 When the supplied ciphertext is not a multiple of the blocksize
162 of the cipher, then the remaining ciphertext will be cached.
163 The next time the decrypt function is called with some ciphertext,
164 the new ciphertext will be concatenated to the cache and then
165 cache+ciphertext will be decrypted.
167 CFB, OFB, CTR:
168 --------------
169 When the chaining mode allows the cipher to act as a stream cipher,
170 the decrypt function will always decrypt all of the supplied
171 ciphertext immediately. No cache will be kept.
173 XTS:
174 ----
175 Because the handling of the last two blocks is linked,
176 it needs the whole block of ciphertext to be supplied at once.
177 Every decrypt function called on a XTS cipher will output
178 a decrypted block based on the current supplied ciphertext block.
180 CMAC:
181 -----
182 Mode not supported for decryption as this does not make sense.
184 #self.ed = 'e' if chain is encrypting, 'd' if decrypting,
185 # None if nothing happened with the chain yet
186 #assert self.ed in ('d',None)
187 # makes sure you don't decrypt with a cipher that has started encrypting
188 self.ed = 'd'
189 if self.mode == MODE_XTS:
190 # data sequence number (or 'tweak') has to be provided when in XTS mode
191 return self.chain.update(ciphertext,'d',n)
192 else:
193 return self.chain.update(ciphertext,'d')
195 def final(self,padfct=padding.PKCS7):
196 # TODO: after calling final, reset the IV? so the cipher is as good as new?
197 """Finalizes the encryption by padding the cache
199 padfct = padding function
200 import from CryptoPlus.Util.padding
202 For ECB, CBC: the remaining bytes in the cache will be padded and
203 encrypted.
204 For OFB,CFB, CTR: an encrypted padding will be returned, making the
205 total outputed bytes since construction of the cipher
206 a multiple of the blocksize of that cipher.
208 If the cipher has been used for decryption, the final function won't do
209 anything. You have to manually unpad if necessary.
211 After finalization, the chain can still be used but the IV, counter etc
212 aren't reset but just continue as they were after the last step (finalization step).
214 assert self.mode not in (MODE_XTS, MODE_CMAC) # finalizing (=padding) doesn't make sense when in XTS or CMAC mode
215 if self.ed == 'e':
216 # when the chain is in encryption mode, finalizing will pad the cache and encrypt this last block
217 if self.mode in (MODE_OFB,MODE_CFB,MODE_CTR):
218 dummy = '0'*(self.chain.totalbytes%self.blocksize) # a dummy string that will be used to get a valid padding
219 else: #ECB, CBC
220 dummy = self.chain.cache
221 pad = padfct(dummy,padding.PAD,self.blocksize)[len(dummy):] # construct the padding necessary
222 return self.chain.update(pad,'e') # supply the padding to the update function => chain cache will be "cache+padding"
223 else:
224 # final function doesn't make sense when decrypting => padding should be removed manually
225 pass
227 class ECB:
228 """ECB chaining mode
230 def __init__(self, codebook, blocksize):
231 self.cache = ''
232 self.codebook = codebook
233 self.blocksize = blocksize
235 def update(self, data, ed):
236 """Processes the given ciphertext/plaintext
238 Inputs:
239 data: raw string of any length
240 ed: 'e' for encryption, 'd' for decryption
241 Output:
242 processed raw string block(s), if any
244 When the supplied data is not a multiple of the blocksize
245 of the cipher, then the remaining input data will be cached.
246 The next time the update function is called with some data,
247 the new data will be concatenated to the cache and then
248 cache+data will be processed and full blocks will be outputted.
250 output_blocks = []
251 self.cache += data
252 if len(self.cache) < self.blocksize:
253 return ''
254 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
255 #the only difference between encryption/decryption in the chain is the cipher block
256 if ed == 'e':
257 output_blocks.append(self.codebook.encrypt( self.cache[i:i + self.blocksize] ))
258 else:
259 output_blocks.append(self.codebook.decrypt( self.cache[i:i + self.blocksize] ))
260 self.cache = self.cache[i+self.blocksize:]
261 return ''.join(output_blocks)
263 class CBC:
264 """CBC chaining mode
266 def __init__(self, codebook, blocksize, IV):
267 self.IV = IV
268 self.cache = ''
269 self.codebook = codebook
270 self.blocksize = blocksize
272 def update(self, data, ed):
273 """Processes the given ciphertext/plaintext
275 Inputs:
276 data: raw string of any length
277 ed: 'e' for encryption, 'd' for decryption
278 Output:
279 processed raw string block(s), if any
281 When the supplied data is not a multiple of the blocksize
282 of the cipher, then the remaining input data will be cached.
283 The next time the update function is called with some data,
284 the new data will be concatenated to the cache and then
285 cache+data will be processed and full blocks will be outputted.
287 if ed == 'e':
288 encrypted_blocks = ''
289 self.cache += data
290 if len(self.cache) < self.blocksize:
291 return ''
292 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
293 self.IV = self.codebook.encrypt(util.xorstring(self.cache[i:i+self.blocksize],self.IV))
294 encrypted_blocks += self.IV
295 self.cache = self.cache[i+self.blocksize:]
296 return encrypted_blocks
297 else:
298 decrypted_blocks = ''
299 self.cache += data
300 if len(self.cache) < self.blocksize:
301 return ''
302 for i in xrange(0, len(self.cache)-self.blocksize+1, self.blocksize):
303 plaintext = util.xorstring(self.IV,self.codebook.decrypt(self.cache[i:i + self.blocksize]))
304 self.IV = self.cache[i:i + self.blocksize]
305 decrypted_blocks+=plaintext
306 self.cache = self.cache[i+self.blocksize:]
307 return decrypted_blocks
309 class CFB:
310 # TODO: bit access instead of only byte level access
311 """CFB Chaining Mode
313 Can be accessed as a stream cipher.
316 def __init__(self, codebook, blocksize, IV,segment_size):
317 self.codebook = codebook
318 self.IV = IV
319 self.blocksize = blocksize
320 self.segment_size = segment_size/8
321 self.keystream = []
322 self.totalbytes = 0
324 def update(self, data, ed):
325 """Processes the given ciphertext/plaintext
327 Inputs:
328 data: raw string of any multiple of bytes
329 ed: 'e' for encryption, 'd' for decryption
330 Output:
331 processed raw string
333 The encrypt/decrypt functions will always process all of the supplied
334 input data immediately. No cache will be kept.
336 output = list(data)
338 for i in xrange(len(data)):
339 if ed =='e':
340 if len(self.keystream) == 0:
341 block = self.codebook.encrypt(self.IV)
342 self.keystream = list(block)[:self.segment_size] # keystream consists of the s MSB's
343 self.IV = self.IV[self.segment_size:] # keeping (b-s) LSB's
344 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
345 self.IV += output[i] # the IV for the next block in the chain is being built byte per byte as the ciphertext flows in
346 else:
347 if len(self.keystream) == 0:
348 block = self.codebook.encrypt(self.IV)
349 self.keystream = list(block)[:self.segment_size]
350 self.IV = self.IV[self.segment_size:]
351 self.IV += output[i]
352 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0)))
353 self.totalbytes += len(output)
354 return ''.join(output)
356 class OFB:
357 """OFB Chaining Mode
359 Can be accessed as a stream cipher.
361 def __init__(self, codebook, blocksize, IV):
362 self.codebook = codebook
363 self.IV = IV
364 self.blocksize = blocksize
365 self.keystream = []
366 self.totalbytes = 0
368 def update(self, data, ed):
369 """Processes the given ciphertext/plaintext
371 Inputs:
372 data: raw string of any multiple of bytes
373 ed: 'e' for encryption, 'd' for decryption
374 Output:
375 processed raw string
377 The encrypt/decrypt functions will always process all of the supplied
378 input data immediately. No cache will be kept.
380 #no difference between encryption and decryption mode
381 n = len(data)
382 blocksize = self.blocksize
383 output = list(data)
385 for i in xrange(n):
386 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
387 self.IV = self.codebook.encrypt(self.IV)
388 self.keystream = list(self.IV)
389 output[i] = chr(ord(output[i]) ^ ord(self.keystream.pop(0))) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
391 self.totalbytes += len(output)
392 return ''.join(output)
394 class CTR:
395 """CTR Chaining Mode
397 Can be accessed as a stream cipher.
399 # initial counter value can be choosen, decryption always starts from beginning
400 # -> you can start from anywhere yourself: just feed the cipher encoded blocks and feed a counter with the corresponding value
401 def __init__(self, codebook, blocksize, counter):
402 self.codebook = codebook
403 self.counter = counter
404 self.blocksize = blocksize
405 self.keystream = [] #holds the output of the current encrypted counter value
406 self.totalbytes = 0
408 def update(self, data, ed):
409 """Processes the given ciphertext/plaintext
411 Inputs:
412 data: raw string of any multiple of bytes
413 ed: 'e' for encryption, 'd' for decryption
414 Output:
415 processed raw string
417 The encrypt/decrypt functions will always process all of the supplied
418 input data immediately. No cache will be kept.
420 # no need for the encryption/decryption distinction: both are the same
421 n = len(data)
422 blocksize = self.blocksize
424 output = list(data)
425 for i in xrange(n):
426 if len(self.keystream) == 0: #encrypt a new counter block when the current keystream is fully used
427 block = self.codebook.encrypt(self.counter())
428 self.keystream = list(block)
429 output[i] = chr(ord(output[i])^ord(self.keystream.pop(0))) #as long as an encrypted counter value is available, the output is just "input XOR keystream"
430 self.totalbytes += len(output)
431 return ''.join(output)
433 class XTS:
434 """XTS Chaining Mode
436 Usable with blockciphers with a 16-byte blocksize
438 # TODO: allow other blocksizes besides 16bytes?
439 def __init__(self,codebook1, codebook2):
440 self.cache = ''
441 self.codebook1 = codebook1
442 self.codebook2 = codebook2
444 def update(self, data, ed,tweak=''):
445 # supply n as a raw string
446 # tweak = data sequence number
447 """Perform a XTS encrypt/decrypt operation.
449 Because the handling of the last two blocks is linked,
450 it needs the whole block of ciphertext to be supplied at once.
451 Every decrypt function called on a XTS cipher will output
452 a decrypted block based on the current supplied ciphertext block.
454 output = ''
455 assert len(data) > 15, "At least one block of 128 bits needs to be supplied"
456 assert len(data) < 128*pow(2,20)
458 # initializing T
459 # e_k2_n = E_K2(tweak)
460 e_k2_n = self.codebook2.encrypt(tweak+ '\x00' * (16-len(tweak)))[::-1]
461 self.T = util.string2number(e_k2_n)
464 while i < ((len(data) // 16)-1): #Decrypt all the blocks but one last full block and opt one last partial block
465 # C = E_K1(P xor T) xor T
466 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
467 # T = E_K2(n) mul (a pow i)
468 self.__T_update()
469 i+=1
471 # Check if the data supplied is a multiple of 16 bytes -> one last full block and we're done
472 if len(data[i*16:]) == 16:
473 # C = E_K1(P xor T) xor T
474 output += self.__xts_step(ed,data[i*16:(i+1)*16],self.T)
475 # T = E_K2(n) mul (a pow i)
476 self.__T_update()
477 else:
478 T_temp = [self.T]
479 self.__T_update()
480 T_temp.append(self.T)
481 if ed=='d':
482 # Permutation of the last two indexes
483 T_temp.reverse()
484 # Decrypt/Encrypt the last two blocks when data is not a multiple of 16 bytes
485 Cm1 = data[i*16:(i+1)*16]
486 Cm = data[(i+1)*16:]
487 PP = self.__xts_step(ed,Cm1,T_temp[0])
488 Cp = PP[len(Cm):]
489 Pm = PP[:len(Cm)]
490 CC = Cm+Cp
491 Pm1 = self.__xts_step(ed,CC,T_temp[1])
492 output += Pm1 + Pm
493 return output
495 def __xts_step(self,ed,tocrypt,T):
496 T_string = util.number2string_N(T,16)[::-1]
497 # C = E_K1(P xor T) xor T
498 if ed == 'd':
499 return util.xorstring(T_string, self.codebook1.decrypt(util.xorstring(T_string, tocrypt)))
500 else:
501 return util.xorstring(T_string, self.codebook1.encrypt(util.xorstring(T_string, tocrypt)))
503 def __T_update(self):
504 # Used for calculating T for a certain step using the T value from the previous step
505 self.T = self.T << 1
506 # if (Cout)
507 if self.T >> (8*16):
508 #T[0] ^= GF_128_FDBK;
509 self.T = self.T ^ 0x100000000000000000000000000000087L
512 class CMAC:
513 """CMAC chaining mode
515 Supports every cipher with a blocksize available
516 in the list CMAC.supported_blocksizes.
517 The hashlength is equal to block size of the used block cipher.
519 Usable with blockciphers with a 8 or 16-byte blocksize
521 # TODO: move to hash module?
522 # TODO: change update behaviour to .update() and .digest() as for all hash modules?
523 # -> other hash functions in pycrypto: calling update, concatenates current input with previous input and hashes everything
524 __Rb_dictionary = {64:0x000000000000001b,128:0x00000000000000000000000000000087}
525 supported_blocksizes = __Rb_dictionary.keys()
526 def __init__(self,codebook,blocksize,IV):
527 # Purpose of init: calculate Lu & Lu2
528 #blocksize (in bytes): to select the Rb constant in the dictionary
529 #Rb as a dictionary: adding support for other blocksizes is easy
530 self.cache=''
531 self.blocksize = blocksize
532 self.codebook = codebook
533 self.IV = IV
535 #Rb_dictionary: holds values for Rb for different blocksizes
536 # values for 64 and 128 bits found here: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
537 # explanation from: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
538 # Rb is a representation of a certain irreducible binary polynomial of degree b, namely,
539 # the lexicographically first among all such polynomials with the minimum possible number of
540 # nonzero terms. If this polynomial is expressed as ub+cb-1ub-1+...+c2u2+c1u+c0, where the
541 # coefficients cb-1, cb-2, ..., c2, c1, c0 are either 0 or 1, then Rb is the bit string cb-1cb-2...c2c1c0.
543 self.Rb = self.__Rb_dictionary[blocksize*8]
545 mask1 = int(('\xff'*blocksize).encode('hex'),16)
546 mask2 = int(('\x80' + '\x00'*(blocksize-1) ).encode('hex'),16)
548 L = int(self.codebook.encrypt('\x00'*blocksize).encode('hex'),16)
550 if L & mask2:
551 Lu = ((L << 1) & mask1) ^ self.Rb
552 else:
553 Lu = L << 1
554 Lu = Lu & mask1
556 if Lu & mask2:
557 Lu2 = ((Lu << 1) & mask1)^ self.Rb
558 else:
559 Lu2 = Lu << 1
560 Lu2 = Lu2 & mask1
562 self.Lu =util.number2string_N(Lu,self.blocksize)
563 self.Lu2=util.number2string_N(Lu2,self.blocksize)
565 def update(self, data, ed):
566 """Processes the given ciphertext/plaintext
568 Inputs:
569 data: raw string of any length
570 ed: 'e' for encryption, 'd' for decryption
571 Output:
572 hashed data as raw string
574 This is not really an update function:
575 Everytime the function is called, the hash from the input data is calculated.
576 No finalizing needed.
578 assert ed == 'e'
579 blocksize = self.blocksize
581 m = (len(data)+blocksize-1)/blocksize #m = amount of datablocks
583 for i in range(1,m):
584 self.IV = self.codebook.encrypt( util.xorstring(data[(i-1)*blocksize:(i)*blocksize],self.IV) )
586 if len(data[(i)*blocksize:])==blocksize:
587 X = util.xorstring(util.xorstring(data[(i)*blocksize:],self.IV),self.Lu)
588 else:
589 tmp = data[(i)*blocksize:] + '\x80' + '\x00'*(blocksize - len(data[(i)*blocksize:])-1)
590 X = util.xorstring(util.xorstring(tmp,self.IV),self.Lu2)
592 T = self.codebook.encrypt(X)
593 return T