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