]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/opencrypto/cryptodev.py
Squash deprecation warning related to array.array(..).tostring()
[FreeBSD/FreeBSD.git] / tests / sys / opencrypto / cryptodev.py
1 #!/usr/local/bin/python2
2 #
3 # Copyright (c) 2014 The FreeBSD Foundation
4 # Copyright 2014 John-Mark Gurney
5 # All rights reserved.
6 #
7 # This software was developed by John-Mark Gurney under
8 # the sponsorship from the FreeBSD Foundation.
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions
11 # are met:
12 # 1.  Redistributions of source code must retain the above copyright
13 #     notice, this list of conditions and the following disclaimer.
14 # 2.  Redistributions in binary form must reproduce the above copyright
15 #     notice, this list of conditions and the following disclaimer in the
16 #     documentation and/or other materials provided with the distribution.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 # SUCH DAMAGE.
29 #
30 # $FreeBSD$
31 #
32
33 from __future__ import print_function
34 import array
35 import binascii
36 from fcntl import ioctl
37 import os
38 import random
39 import signal
40 from struct import pack as _pack
41 import sys
42 import time
43
44 import dpkt
45
46 from cryptodevh import *
47
48 __all__ = [ 'Crypto', 'MismatchError', ]
49
50 class FindOp(dpkt.Packet):
51     __byte_order__ = '@'
52     __hdr__ = (
53         ('crid', 'i',   0),
54         ('name', '32s', 0),
55     )
56
57 class SessionOp(dpkt.Packet):
58     __byte_order__ = '@'
59     __hdr__ = (
60         ('cipher',    'I', 0),
61         ('mac',       'I', 0),
62         ('keylen',    'I', 0),
63         ('key',       'P', 0),
64         ('mackeylen', 'i', 0),
65         ('mackey',    'P', 0),
66         ('ses',       'I', 0),
67     )
68
69 class SessionOp2(dpkt.Packet):
70     __byte_order__ = '@'
71     __hdr__ = (
72         ('cipher',    'I', 0),
73         ('mac',       'I', 0),
74         ('keylen',    'I', 0),
75         ('key',       'P', 0),
76         ('mackeylen', 'i', 0),
77         ('mackey',    'P', 0),
78         ('ses',       'I', 0),
79         ('crid',      'i', 0),
80         ('pad0',      'i', 0),
81         ('pad1',      'i', 0),
82         ('pad2',      'i', 0),
83         ('pad3',      'i', 0),
84     )
85
86 class CryptOp(dpkt.Packet):
87     __byte_order__ = '@'
88     __hdr__ = (
89         ('ses',   'I', 0),
90         ('op',    'H', 0),
91         ('flags', 'H', 0),
92         ('len',   'I', 0),
93         ('src',   'P', 0),
94         ('dst',   'P', 0),
95         ('mac',   'P', 0),
96         ('iv',    'P', 0),
97     )
98
99 class CryptAEAD(dpkt.Packet):
100     __byte_order__ = '@'
101     __hdr__ = (
102         ('ses',    'I', 0),
103         ('op',     'H', 0),
104         ('flags',  'H', 0),
105         ('len',    'I', 0),
106         ('aadlen', 'I', 0),
107         ('ivlen',  'I', 0),
108         ('src',    'P', 0),
109         ('dst',    'P', 0),
110         ('aad',    'P', 0),
111         ('tag',    'P', 0),
112         ('iv',     'P', 0),
113     )
114
115 # h2py.py can't handle multiarg macros
116 CRIOGET = 3221513060
117 CIOCGSESSION = 3224396645
118 CIOCGSESSION2 = 3225445226
119 CIOCFSESSION = 2147771238
120 CIOCCRYPT = 3224396647
121 CIOCKEY = 3230688104
122 CIOCASYMFEAT = 1074029417
123 CIOCKEY2 = 3230688107
124 CIOCFINDDEV = 3223610220
125 CIOCCRYPTAEAD = 3225445229
126
127 def _getdev():
128     buf = array.array('I', [0])
129     fd = os.open('/dev/crypto', os.O_RDWR)
130     try:
131         ioctl(fd, CRIOGET, buf, 1)
132     finally:
133         os.close(fd)
134
135     return buf[0]
136
137 _cryptodev = _getdev()
138
139 def _findop(crid, name):
140     fop = FindOp()
141     fop.crid = crid
142     fop.name = name
143     s = array.array('B', fop.pack_hdr())
144     ioctl(_cryptodev, CIOCFINDDEV, s, 1)
145     fop.unpack(s)
146
147     try:
148         idx = fop.name.index('\x00')
149         name = fop.name[:idx]
150     except ValueError:
151         name = fop.name
152
153     return fop.crid, name
154
155 def array_tobytes(array_obj):
156     if sys.version_info[:2] >= (3, 2):
157         return array_obj.tobytes()
158     return array_obj.tostring()
159
160 class Crypto:
161     @staticmethod
162     def findcrid(name):
163         return _findop(-1, name)[0]
164
165     @staticmethod
166     def getcridname(crid):
167         return _findop(crid, '')[1]
168
169     def __init__(self, cipher=0, key=None, mac=0, mackey=None,
170         crid=CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE, maclen=None):
171         self._ses = None
172         self._maclen = maclen
173         ses = SessionOp2()
174         ses.cipher = cipher
175         ses.mac = mac
176
177         if key is not None:
178             ses.keylen = len(key)
179             k = array.array('B', key)
180             ses.key = k.buffer_info()[0]
181         else:
182             self.key = None
183
184         if mackey is not None:
185             ses.mackeylen = len(mackey)
186             mk = array.array('B', mackey)
187             ses.mackey = mk.buffer_info()[0]
188
189         if not cipher and not mac:
190             raise ValueError('one of cipher or mac MUST be specified.')
191         ses.crid = crid
192         #print(ses)
193         s = array.array('B', ses.pack_hdr())
194         #print(s)
195         ioctl(_cryptodev, CIOCGSESSION2, s, 1)
196         ses.unpack(s)
197
198         self._ses = ses.ses
199
200     def __del__(self):
201         if self._ses is None:
202             return
203
204         try:
205             ioctl(_cryptodev, CIOCFSESSION, _pack('I', self._ses))
206         except TypeError:
207             pass
208         self._ses = None
209
210     def _doop(self, op, src, iv):
211         cop = CryptOp()
212         cop.ses = self._ses
213         cop.op = op
214         cop.flags = 0
215         cop.len = len(src)
216         s = array.array('B', src)
217         cop.src = cop.dst = s.buffer_info()[0]
218         if self._maclen is not None:
219             m = array.array('B', [0] * self._maclen)
220             cop.mac = m.buffer_info()[0]
221         ivbuf = array.array('B', iv)
222         cop.iv = ivbuf.buffer_info()[0]
223
224         #print('cop:', cop)
225         ioctl(_cryptodev, CIOCCRYPT, str(cop))
226
227         s = array_tobytes(s)
228         if self._maclen is not None:
229             return s, array_tobytes(m)
230
231         return s
232
233     def _doaead(self, op, src, aad, iv, tag=None):
234         caead = CryptAEAD()
235         caead.ses = self._ses
236         caead.op = op
237         caead.flags = CRD_F_IV_EXPLICIT
238         caead.flags = 0
239         caead.len = len(src)
240         s = array.array('B', src)
241         caead.src = caead.dst = s.buffer_info()[0]
242         caead.aadlen = len(aad)
243         saad = array.array('B', aad)
244         caead.aad = saad.buffer_info()[0]
245
246         if self._maclen is None:
247             raise ValueError('must have a tag length')
248
249         if tag is None:
250             tag = array.array('B', [0] * self._maclen)
251         else:
252             assert len(tag) == self._maclen, \
253                 '%d != %d' % (len(tag), self._maclen)
254             tag = array.array('B', tag)
255
256         caead.tag = tag.buffer_info()[0]
257
258         ivbuf = array.array('B', iv)
259         caead.ivlen = len(iv)
260         caead.iv = ivbuf.buffer_info()[0]
261
262         ioctl(_cryptodev, CIOCCRYPTAEAD, str(caead))
263
264         s = array_tobytes(s)
265
266         return s, array_tobytes(tag)
267
268     def perftest(self, op, size, timeo=3):
269         inp = array.array('B', (random.randint(0, 255) for x in range(size)))
270         out = array.array('B', inp)
271
272         # prep ioctl
273         cop = CryptOp()
274         cop.ses = self._ses
275         cop.op = op
276         cop.flags = 0
277         cop.len = len(inp)
278         s = array.array('B', inp)
279         cop.src = s.buffer_info()[0]
280         cop.dst = out.buffer_info()[0]
281         if self._maclen is not None:
282             m = array.array('B', [0] * self._maclen)
283             cop.mac = m.buffer_info()[0]
284         ivbuf = array.array('B', (random.randint(0, 255) for x in range(16)))
285         cop.iv = ivbuf.buffer_info()[0]
286
287         exit = [ False ]
288         def alarmhandle(a, b, exit=exit):
289             exit[0] = True
290
291         oldalarm = signal.signal(signal.SIGALRM, alarmhandle)
292         signal.alarm(timeo)
293
294         start = time.time()
295         reps = 0
296         while not exit[0]:
297             ioctl(_cryptodev, CIOCCRYPT, str(cop))
298             reps += 1
299
300         end = time.time()
301
302         signal.signal(signal.SIGALRM, oldalarm)
303
304         print('time:', end - start)
305         print('perf MB/sec:', (reps * size) / (end - start) / 1024 / 1024)
306
307     def encrypt(self, data, iv, aad=None):
308         if aad is None:
309             return self._doop(COP_ENCRYPT, data, iv)
310         else:
311             return self._doaead(COP_ENCRYPT, data, aad,
312                 iv)
313
314     def decrypt(self, data, iv, aad=None, tag=None):
315         if aad is None:
316             return self._doop(COP_DECRYPT, data, iv)
317         else:
318             return self._doaead(COP_DECRYPT, data, aad,
319                 iv, tag=tag)
320
321 class MismatchError(Exception):
322     pass
323
324 class KATParser:
325     def __init__(self, fname, fields):
326         self.fp = open(fname)
327         self.fields = set(fields)
328         self._pending = None
329
330     def __iter__(self):
331         while True:
332             didread = False
333             if self._pending is not None:
334                 i = self._pending
335                 self._pending = None
336             else:
337                 i = self.fp.readline()
338                 didread = True
339
340             if didread and not i:
341                 return
342
343             if (i and i[0] == '#') or not i.strip():
344                 continue
345             if i[0] == '[':
346                 yield i[1:].split(']', 1)[0], self.fielditer()
347             else:
348                 raise ValueError('unknown line: %r' % repr(i))
349
350     def eatblanks(self):
351         while True:
352             line = self.fp.readline()
353             if line == '':
354                 break
355
356             line = line.strip()
357             if line:
358                 break
359
360         return line
361
362     def fielditer(self):
363         while True:
364             values = {}
365
366             line = self.eatblanks()
367             if not line or line[0] == '[':
368                 self._pending = line
369                 return
370
371             while True:
372                 try:
373                     f, v = line.split(' =')
374                 except:
375                     if line == 'FAIL':
376                         f, v = 'FAIL', ''
377                     else:
378                         print('line:', repr(line))
379                         raise
380                 v = v.strip()
381
382                 if f in values:
383                     raise ValueError('already present: %r' % repr(f))
384                 values[f] = v
385                 line = self.fp.readline().strip()
386                 if not line:
387                     break
388
389             # we should have everything
390             remain = self.fields.copy() - set(values.keys())
391             # XXX - special case GCM decrypt
392             if remain and not ('FAIL' in values and 'PT' in remain):
393                 raise ValueError('not all fields found: %r' % repr(remain))
394
395             yield values
396
397 # The CCM files use a bit of a different syntax that doesn't quite fit
398 # the generic KATParser.  In particular, some keys are set globally at
399 # the start of the file, and some are set globally at the start of a
400 # section.
401 class KATCCMParser:
402     def __init__(self, fname):
403         self.fp = open(fname)
404         self._pending = None
405         self.read_globals()
406
407     def read_globals(self):
408         self.global_values = {}
409         while True:
410             line = self.fp.readline()
411             if not line:
412                 return
413             if line[0] == '#' or not line.strip():
414                 continue
415             if line[0] == '[':
416                 self._pending = line
417                 return
418
419             try:
420                 f, v = line.split(' =')
421             except:
422                 print('line:', repr(line))
423                 raise
424
425             v = v.strip()
426
427             if f in self.global_values:
428                 raise ValueError('already present: %r' % repr(f))
429             self.global_values[f] = v
430
431     def read_section_values(self, kwpairs):
432         self.section_values = self.global_values.copy()
433         for pair in kwpairs.split(', '):
434             f, v = pair.split(' = ')
435             if f in self.section_values:
436                 raise ValueError('already present: %r' % repr(f))
437             self.section_values[f] = v
438
439         while True:
440             line = self.fp.readline()
441             if not line:
442                 return
443             if line[0] == '#' or not line.strip():
444                 continue
445             if line[0] == '[':
446                 self._pending = line
447                 return
448
449             try:
450                 f, v = line.split(' =')
451             except:
452                 print('line:', repr(line))
453                 raise
454
455             if f == 'Count':
456                 self._pending = line
457                 return
458
459             v = v.strip()
460
461             if f in self.section_values:
462                 raise ValueError('already present: %r' % repr(f))
463             self.section_values[f] = v
464
465     def __iter__(self):
466         while True:
467             if self._pending:
468                 line = self._pending
469                 self._pending = None
470             else:
471                 line = self.fp.readline()
472                 if not line:
473                     return
474
475             if (line and line[0] == '#') or not line.strip():
476                 continue
477
478             if line[0] == '[':
479                 section = line[1:].split(']', 1)[0]
480                 self.read_section_values(section)
481                 continue
482
483             values = self.section_values.copy()
484
485             while True:
486                 try:
487                     f, v = line.split(' =')
488                 except:
489                     print('line:', repr(line))
490                     raise
491                 v = v.strip()
492
493                 if f in values:
494                     raise ValueError('already present: %r' % repr(f))
495                 values[f] = v
496                 line = self.fp.readline().strip()
497                 if not line:
498                     break
499
500             yield values
501
502
503 def _spdechex(s):
504     return binascii.hexlify(''.join(s.split()))
505
506 if __name__ == '__main__':
507     if True:
508         try:
509             crid = Crypto.findcrid('aesni0')
510             print('aesni:', crid)
511         except IOError:
512             print('aesni0 not found')
513
514         for i in range(10):
515             try:
516                 name = Crypto.getcridname(i)
517                 print('%2d: %r' % (i, repr(name)))
518             except IOError:
519                 pass
520     elif False:
521         kp = KATParser('/usr/home/jmg/aesni.testing/format tweak value input - data unit seq no/XTSGenAES128.rsp', [ 'COUNT', 'DataUnitLen', 'Key', 'DataUnitSeqNumber', 'PT', 'CT' ])
522         for mode, ni in kp:
523             print(i, ni)
524             for j in ni:
525                 print(j)
526     elif False:
527         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
528         iv = _spdechex('00000000000000000000000000000001')
529         pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e')
530         #pt = _spdechex('00000000000000000000000000000000')
531         ct = _spdechex('f42c33853ecc5ce2949865fdb83de3bff1089e9360c94f830baebfaff72836ab5236f77212f1e7396c8c54ac73d81986375a6e9e299cfeca5ba051ed25e8d1affa5beaf6c1d2b45e90802408f2ced21663497e906de5f29341e5e52ddfea5363d628b3eb7806835e17bae051b3a6da3f8e2941fe44384eac17a9d298d2c331ca8320c775b5d53263a5e905059d891b21dede2d8110fd427c7bd5a9a274ddb47b1945ee79522203b6e297d0e399ef')
532
533         c = Crypto(CRYPTO_AES_ICM, key)
534         enc = c.encrypt(pt, iv)
535
536         print('enc:', binascii.hexlify(enc))
537         print(' ct:', binascii.hexlify(ct))
538
539         assert ct == enc
540
541         dec = c.decrypt(ct, iv)
542
543         print('dec:', binascii.hexlify(dec))
544         print(' pt:', binascii.hexlify(pt))
545
546         assert pt == dec
547     elif False:
548         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
549         iv = _spdechex('00000000000000000000000000000001')
550         pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e0a3f')
551         #pt = _spdechex('00000000000000000000000000000000')
552         ct = _spdechex('f42c33853ecc5ce2949865fdb83de3bff1089e9360c94f830baebfaff72836ab5236f77212f1e7396c8c54ac73d81986375a6e9e299cfeca5ba051ed25e8d1affa5beaf6c1d2b45e90802408f2ced21663497e906de5f29341e5e52ddfea5363d628b3eb7806835e17bae051b3a6da3f8e2941fe44384eac17a9d298d2c331ca8320c775b5d53263a5e905059d891b21dede2d8110fd427c7bd5a9a274ddb47b1945ee79522203b6e297d0e399ef3768')
553
554         c = Crypto(CRYPTO_AES_ICM, key)
555         enc = c.encrypt(pt, iv)
556
557         print('enc:', binascii.hexlify(enc))
558         print(' ct:', binascii.hexlify(ct))
559
560         assert ct == enc
561
562         dec = c.decrypt(ct, iv)
563
564         print('dec:', binascii.hexlify(dec))
565         print(' pt:', binascii.hexlify(pt))
566
567         assert pt == dec
568     elif False:
569         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
570         iv = _spdechex('6eba2716ec0bd6fa5cdef5e6d3a795bc')
571         pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e0a3f')
572         ct = _spdechex('f1f81f12e72e992dbdc304032705dc75dc3e4180eff8ee4819906af6aee876d5b00b7c36d282a445ce3620327be481e8e53a8e5a8e5ca9abfeb2281be88d12ffa8f46d958d8224738c1f7eea48bda03edbf9adeb900985f4fa25648b406d13a886c25e70cfdecdde0ad0f2991420eb48a61c64fd797237cf2798c2675b9bb744360b0a3f329ac53bbceb4e3e7456e6514f1a9d2f06c236c31d0f080b79c15dce1096357416602520daa098b17d1af427')
573         c = Crypto(CRYPTO_AES_CBC, key)
574
575         enc = c.encrypt(pt, iv)
576
577         print('enc:', binascii.hexlify(enc))
578         print(' ct:', binascii.hexlify(ct))
579
580         assert ct == enc
581
582         dec = c.decrypt(ct, iv)
583
584         print('dec:', binascii.hexlify(dec))
585         print(' pt:', binascii.hexlify(pt))
586
587         assert pt == dec
588     elif False:
589         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
590         iv = _spdechex('b3d8cc017cbb89b39e0f67e2')
591         pt = _spdechex('c3b3c41f113a31b73d9a5cd4321030')
592         aad = _spdechex('24825602bd12a984e0092d3e448eda5f')
593         ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa7354')
594         ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa73')
595         tag = _spdechex('0032a1dc85f1c9786925a2e71d8272dd')
596         tag = _spdechex('8d11a0929cb3fbe1fef01a4a38d5f8ea')
597
598         c = Crypto(CRYPTO_AES_NIST_GCM_16, key,
599             mac=CRYPTO_AES_128_NIST_GMAC, mackey=key)
600
601         enc, enctag = c.encrypt(pt, iv, aad=aad)
602
603         print('enc:', binascii.hexlify(enc))
604         print(' ct:', binascii.hexlify(ct))
605
606         assert enc == ct
607
608         print('etg:', binascii.hexlify(enctag))
609         print('tag:', binascii.hexlify(tag))
610         assert enctag == tag
611
612         # Make sure we get EBADMSG
613         #enctag = enctag[:-1] + 'a'
614         dec, dectag = c.decrypt(ct, iv, aad=aad, tag=enctag)
615
616         print('dec:', binascii.hexlify(dec))
617         print(' pt:', binascii.hexlify(pt))
618
619         assert dec == pt
620
621         print('dtg:', binascii.hexlify(dectag))
622         print('tag:', binascii.hexlify(tag))
623
624         assert dectag == tag
625     elif False:
626         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
627         iv = _spdechex('b3d8cc017cbb89b39e0f67e2')
628         key = key + iv[:4]
629         iv = iv[4:]
630         pt = _spdechex('c3b3c41f113a31b73d9a5cd432103069')
631         aad = _spdechex('24825602bd12a984e0092d3e448eda5f')
632         ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa7354')
633         tag = _spdechex('0032a1dc85f1c9786925a2e71d8272dd')
634
635         c = Crypto(CRYPTO_AES_GCM_16, key, mac=CRYPTO_AES_128_GMAC, mackey=key)
636
637         enc, enctag = c.encrypt(pt, iv, aad=aad)
638
639         print('enc:', binascii.hexlify(enc))
640         print(' ct:', binascii.hexlify(ct))
641
642         assert enc == ct
643
644         print('etg:', binascii.hexlify(enctag))
645         print('tag:', binascii.hexlify(tag))
646         assert enctag == tag
647     elif False:
648         for i in range(100000):
649             c = Crypto(CRYPTO_AES_XTS, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'))
650             data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec')
651             ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240')
652             iv = _pack('QQ', 71, 0)
653
654             enc = c.encrypt(data, iv)
655             assert enc == ct
656     elif True:
657         c = Crypto(CRYPTO_AES_XTS, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'))
658         data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec')
659         ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240')
660         iv = _pack('QQ', 71, 0)
661
662         enc = c.encrypt(data, iv)
663         assert enc == ct
664
665         dec = c.decrypt(enc, iv)
666         assert dec == data
667
668         #c.perftest(COP_ENCRYPT, 192*1024, reps=30000)
669
670     else:
671         key = binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382')
672         print('XTS %d testing:' % (len(key) * 8))
673         c = Crypto(CRYPTO_AES_XTS, key)
674         for i in [ 8192, 192*1024]:
675             print('block size: %d' % i)
676             c.perftest(COP_ENCRYPT, i)
677             c.perftest(COP_DECRYPT, i)