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