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