44#
55
66from __future__ import division
7- from tlslite .utils .cryptomath import numberToByteArray , divceil
8- from tlslite .utils .python_aes import Python_AES
9- import sys
10- import array
7+ from tlslite .utils .cryptomath import numberToByteArray
8+ from tlslite .utils import python_aes
119
1210
1311class AESCCM (object ):
@@ -18,6 +16,9 @@ def __init__(self, key, implementation, rawAesEncrypt, tag_length=16):
1816 self .isAEAD = True
1917 self .key = key
2018 self .tagLength = tag_length
19+ self .nonceLength = 12
20+ self .implementation = implementation
21+
2122 if len (self .key ) == 16 and self .tagLength == 8 :
2223 self .name = "aes128ccm_8"
2324 elif len (self .key ) == 16 and self .tagLength == 16 :
@@ -27,10 +28,10 @@ def __init__(self, key, implementation, rawAesEncrypt, tag_length=16):
2728 else :
2829 assert len (self .key ) == 32 and self .tagLength == 16
2930 self .name = "aes256ccm"
30- self . _rawAesEncrypt = rawAesEncrypt
31- self .implementation = implementation
32- self .nonceLength = 12
33- self . _cbc = Python_AES ( self . key , 2 , bytearray ( b' \x00 ' * 16 ))
31+
32+ self ._ctr = python_aes . new ( self . key , 6 , bytearray ( b' \x00 ' * 16 ))
33+ self ._cbc = python_aes . new ( self . key , 2 , bytearray ( b' \x00 ' * 16 ))
34+
3435
3536 def _cbcmac_calc (self , nonce , aad , msg ):
3637 L = 15 - len (nonce )
@@ -89,25 +90,19 @@ def seal(self, nonce, msg, aad):
8990 raise ValueError ("Bad nonce length" )
9091
9192 L = 15 - len (nonce )
92- auth_value = bytearray (self .tagLength )
9393
9494 # We construct the key stream blocks.
9595 # S_0 is not used for encrypting the message, it is only used
9696 # to compute the authentication value.
9797 # S_1..S_n are used to encrypt the message.
9898
9999 flags = L - 1
100- s_0 = self ._rawAesEncrypt (bytearray ([flags ]) +
101- nonce + numberToByteArray (0 , L ))
102-
103- s_n = self ._construct_s_n (msg , flags , nonce , L )
104-
105- enc_msg = self ._xor (msg , s_n )
100+ s_0 = bytearray ([flags ]) + nonce + numberToByteArray (0 , L )
106101
107102 mac = self ._cbcmac_calc (nonce , aad , msg )
108-
109- for i in range ( self .tagLength ):
110- auth_value [ i ] = mac [ i ] ^ s_0 [ i ]
103+ self . _ctr . counter = s_0
104+ auth_value = self ._ctr . encrypt ( mac )
105+ enc_msg = self . _ctr . encrypt ( msg )
111106
112107 ciphertext = enc_msg + auth_value
113108 return ciphertext
@@ -122,61 +117,29 @@ def open(self, nonce, ciphertext, aad):
122117 return None
123118
124119 L = 15 - len (nonce )
125- received_mac = bytearray (self .tagLength )
126120 flags = L - 1
127121
128122 # Same construction as in seal function
129123
130- s_0 = self ._rawAesEncrypt (bytearray ([flags ]) +
131- nonce + numberToByteArray (0 , L ))
124+ s_0 = bytearray ([flags ]) + nonce + numberToByteArray (0 , L )
132125
133- s_n = self ._construct_s_n ( ciphertext , flags , nonce , L )
126+ auth_value = ciphertext [ - self .tagLength :]
134127
135- msg = self ._xor (ciphertext , s_n )
128+ # We decrypt the auth value
129+ self ._ctr .counter = s_0
130+ received_mac = self ._ctr .decrypt (auth_value )
131+ msg = self ._ctr .decrypt (ciphertext )
136132 msg = msg [:- self .tagLength ]
137-
138- auth_value = ciphertext [- self .tagLength :]
139133 computed_mac = self ._cbcmac_calc (nonce , aad , msg )
140134
141- # We decrypt the auth value
142- for i in range (self .tagLength ):
143- received_mac [i ] = auth_value [i ] ^ s_0 [i ]
144135
145136 # Compare the mac vlaue is the same as the one we computed
146137 if received_mac != computed_mac :
147138 return None
148139 return msg
149140
150- def _construct_s_n (self , ciphertext , flags , nonce , L ):
151- s_n = bytearray ()
152- counter_lmt = divceil (len (ciphertext ), 16 )
153- for i in range (1 , int (counter_lmt ) + 1 ):
154- s_n += self ._rawAesEncrypt (bytearray ([flags ]) +
155- nonce + numberToByteArray (i , L ))
156- return s_n
157-
158- if sys .version_info [0 ] >= 3 :
159- def _xor (self , inp , s_n ):
160- inp_added = - ((8 - (len (inp ) % 8 )) % 8 ) or None
161- self ._pad_with_zeroes (inp , 8 )
162- msg = self ._use_memoryview (inp , s_n )[:inp_added ]
163- inp [:] = inp [:inp_added ]
164- return msg
165- else :
166- def _xor (self , inp , s_n ):
167- msg = bytearray (i ^ j for i , j in zip (inp , s_n ))
168- return msg
169-
170141 @staticmethod
171142 def _pad_with_zeroes (data , size ):
172143 if len (data ) % size != 0 :
173144 zeroes_to_add = size - (len (data ) % size )
174145 data += b'\x00 ' * zeroes_to_add
175-
176- @staticmethod
177- def _use_memoryview (msg , s_n ):
178- msg_mv = memoryview (msg ).cast ('Q' )
179- s_n_mv = memoryview (s_n ).cast ('Q' )
180- enc_arr = array .array ('Q' , (i ^ j for i , j in zip (msg_mv , s_n_mv )))
181- enc_msg = bytearray (enc_arr .tobytes ())
182- return enc_msg
0 commit comments