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