]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/opencrypto/cryptodev.py
OpenSSL: Merge OpenSSL 1.1.1t
[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 re
42 import signal
43 from struct import pack as _pack
44 import sys
45 import time
46
47 import dpkt
48
49 from cryptodevh import *
50
51 __all__ = [ 'Crypto', 'MismatchError', ]
52
53 class FindOp(dpkt.Packet):
54     __byte_order__ = '@'
55     __hdr__ = (
56         ('crid', 'i',   0),
57         ('name', '32s', 0),
58     )
59
60 class SessionOp(dpkt.Packet):
61     __byte_order__ = '@'
62     __hdr__ = (
63         ('cipher',    'I', 0),
64         ('mac',       'I', 0),
65         ('keylen',    'I', 0),
66         ('key',       'P', 0),
67         ('mackeylen', 'i', 0),
68         ('mackey',    'P', 0),
69         ('ses',       'I', 0),
70     )
71
72 class SessionOp2(dpkt.Packet):
73     __byte_order__ = '@'
74     __hdr__ = (
75         ('cipher',    'I', 0),
76         ('mac',       'I', 0),
77         ('keylen',    'I', 0),
78         ('key',       'P', 0),
79         ('mackeylen', 'i', 0),
80         ('mackey',    'P', 0),
81         ('ses',       'I', 0),
82         ('crid',      'i', 0),
83         ('ivlen',     'i', 0),
84         ('maclen',    'i', 0),
85         ('pad0',      'i', 0),
86         ('pad1',      'i', 0),
87     )
88
89 class CryptOp(dpkt.Packet):
90     __byte_order__ = '@'
91     __hdr__ = (
92         ('ses',   'I', 0),
93         ('op',    'H', 0),
94         ('flags', 'H', 0),
95         ('len',   'I', 0),
96         ('src',   'P', 0),
97         ('dst',   'P', 0),
98         ('mac',   'P', 0),
99         ('iv',    'P', 0),
100     )
101
102 class CryptAEAD(dpkt.Packet):
103     __byte_order__ = '@'
104     __hdr__ = (
105         ('ses',    'I', 0),
106         ('op',     'H', 0),
107         ('flags',  'H', 0),
108         ('len',    'I', 0),
109         ('aadlen', 'I', 0),
110         ('ivlen',  'I', 0),
111         ('src',    'P', 0),
112         ('dst',    'P', 0),
113         ('aad',    'P', 0),
114         ('tag',    'P', 0),
115         ('iv',     'P', 0),
116     )
117
118 # h2py.py can't handle multiarg macros
119 CIOCGSESSION = 3224396645
120 CIOCFSESSION = 2147771238
121 CIOCKEY = 3230688104
122 CIOCASYMFEAT = 1074029417
123 CIOCKEY2 = 3230688107
124 CIOCFINDDEV = 3223610220
125 if platform.architecture()[0] == '64bit':
126     CIOCGSESSION2 = 3225445226
127     CIOCCRYPT = 3224396647
128     CIOCCRYPTAEAD = 3225445229
129 else:
130     CIOCGSESSION2 = 3224396650
131     CIOCCRYPT = 3223085927
132     CIOCCRYPTAEAD = 3223872365
133
134 _cryptodev = os.open('/dev/crypto', os.O_RDWR)
135
136 def str_to_ascii(val):
137     if sys.version_info[0] >= 3:
138         if isinstance(val, str):
139             return val.encode("ascii")
140     return val
141
142 def _findop(crid, name):
143     fop = FindOp()
144     fop.crid = crid
145     fop.name = str_to_ascii(name)
146     s = array.array('B', fop.pack_hdr())
147     ioctl(_cryptodev, CIOCFINDDEV, s, 1)
148     fop.unpack(s)
149
150     try:
151         idx = fop.name.index(b'\x00')
152         name = fop.name[:idx]
153     except ValueError:
154         name = fop.name
155
156     return fop.crid, name
157
158 def array_tobytes(array_obj):
159     if sys.version_info[:2] >= (3, 2):
160         return array_obj.tobytes()
161     return array_obj.tostring()
162
163 def empty_bytes():
164     if sys.version_info[0] >= 3:
165         return b''
166     return ""
167
168 class Crypto:
169     @staticmethod
170     def findcrid(name):
171         return _findop(-1, name)[0]
172
173     @staticmethod
174     def getcridname(crid):
175         return _findop(crid, '')[1]
176
177     def __init__(self, cipher=0, key=None, mac=0, mackey=None,
178         crid=CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE, maclen=None,
179         ivlen=None):
180         self._ses = None
181         self._maclen = maclen
182         ses = SessionOp2()
183         ses.cipher = cipher
184         ses.mac = mac
185
186         if key is not None:
187             ses.keylen = len(key)
188             k = array.array('B', key)
189             ses.key = k.buffer_info()[0]
190         else:
191             self.key = None
192
193         if mackey is not None:
194             ses.mackeylen = len(mackey)
195             mk = array.array('B', mackey)
196             ses.mackey = mk.buffer_info()[0]
197
198         if not cipher and not mac:
199             raise ValueError('one of cipher or mac MUST be specified.')
200         ses.crid = crid
201         if ivlen:
202             ses.ivlen = ivlen
203         if maclen:
204             ses.maclen = maclen
205         #print(ses)
206         s = array.array('B', ses.pack_hdr())
207         #print(s)
208         ioctl(_cryptodev, CIOCGSESSION2, s, 1)
209         ses.unpack(s)
210
211         self._ses = ses.ses
212
213     def __del__(self):
214         if self._ses is None:
215             return
216
217         try:
218             ioctl(_cryptodev, CIOCFSESSION, _pack('I', self._ses))
219         except TypeError:
220             pass
221         self._ses = None
222
223     def _doop(self, op, src, iv, mac=None):
224         cop = CryptOp()
225         cop.ses = self._ses
226         cop.op = op
227         cop.flags = 0
228         if src is not None:
229             cop.len = len(src)
230             s = array.array('B', src)
231             cop.src = cop.dst = s.buffer_info()[0]
232         if mac is not None:
233             assert len(mac) == self._maclen, \
234                 '%d != %d' % (len(tag), self._maclen)
235         if self._maclen is not None:
236             if mac is None:
237                 m = array.array('B', [0] * self._maclen)
238             else:
239                 m = array.array('B', mac)
240             cop.mac = m.buffer_info()[0]
241         ivbuf = array.array('B', str_to_ascii(iv))
242         cop.iv = ivbuf.buffer_info()[0]
243
244         #print('cop:', cop)
245         ioctl(_cryptodev, CIOCCRYPT, bytes(cop))
246
247         if src is not None:
248             s = array_tobytes(s)
249         else:
250             s = empty_bytes()
251         if self._maclen is not None:
252             return s, array_tobytes(m)
253
254         return s
255
256     def _doaead(self, op, src, aad, iv, tag=None):
257         caead = CryptAEAD()
258         caead.ses = self._ses
259         caead.op = op
260         caead.flags = CRD_F_IV_EXPLICIT
261         caead.flags = 0
262         if src:
263             src = str_to_ascii(src)
264             caead.len = len(src)
265             s = array.array('B', src)
266             caead.src = caead.dst = s.buffer_info()[0]
267         aad = str_to_ascii(aad)
268         caead.aadlen = len(aad)
269         saad = array.array('B', aad)
270         caead.aad = saad.buffer_info()[0]
271
272         if self._maclen is None:
273             raise ValueError('must have a tag length')
274
275         tag = str_to_ascii(tag)
276         if tag is None:
277             tag = array.array('B', [0] * self._maclen)
278         else:
279             assert len(tag) == self._maclen, \
280                 '%d != %d' % (len(tag), self._maclen)
281             tag = array.array('B', tag)
282
283         caead.tag = tag.buffer_info()[0]
284
285         ivbuf = array.array('B', iv)
286         caead.ivlen = len(iv)
287         caead.iv = ivbuf.buffer_info()[0]
288
289         ioctl(_cryptodev, CIOCCRYPTAEAD, bytes(caead))
290
291         if src:
292             s = array_tobytes(s)
293         else:
294             s = empty_bytes()
295
296         return s, array_tobytes(tag)
297
298     def perftest(self, op, size, timeo=3):
299         inp = array.array('B', (random.randint(0, 255) for x in range(size)))
300         inp = str_to_ascii(inp)
301         out = array.array('B', inp)
302
303         # prep ioctl
304         cop = CryptOp()
305         cop.ses = self._ses
306         cop.op = op
307         cop.flags = 0
308         cop.len = len(inp)
309         s = array.array('B', inp)
310         cop.src = s.buffer_info()[0]
311         cop.dst = out.buffer_info()[0]
312         if self._maclen is not None:
313             m = array.array('B', [0] * self._maclen)
314             cop.mac = m.buffer_info()[0]
315         ivbuf = array.array('B', (random.randint(0, 255) for x in range(16)))
316         cop.iv = ivbuf.buffer_info()[0]
317
318         exit = [ False ]
319         def alarmhandle(a, b, exit=exit):
320             exit[0] = True
321
322         oldalarm = signal.signal(signal.SIGALRM, alarmhandle)
323         signal.alarm(timeo)
324
325         start = time.time()
326         reps = 0
327         cop = bytes(cop)
328         while not exit[0]:
329             ioctl(_cryptodev, CIOCCRYPT, cop)
330             reps += 1
331
332         end = time.time()
333
334         signal.signal(signal.SIGALRM, oldalarm)
335
336         print('time:', end - start)
337         print('perf MB/sec:', (reps * size) / (end - start) / 1024 / 1024)
338
339     def encrypt(self, data, iv, aad=None):
340         if aad is None:
341             return self._doop(COP_ENCRYPT, data, iv)
342         else:
343             return self._doaead(COP_ENCRYPT, data, aad,
344                 iv)
345
346     def decrypt(self, data, iv, aad=None, tag=None):
347         if aad is None:
348             return self._doop(COP_DECRYPT, data, iv, mac=tag)
349         else:
350             return self._doaead(COP_DECRYPT, data, aad,
351                 iv, tag=tag)
352
353 class MismatchError(Exception):
354     pass
355
356 class KATParser:
357     def __init__(self, fname, fields):
358         self.fields = set(fields)
359         self._pending = None
360         self.fname = fname
361         self.fp = None
362         self.field_re = re.compile(r"\[(?P<field>[^]]+)\]")
363
364     def __enter__(self):
365         self.fp = open(self.fname)
366         return self
367
368     def __exit__(self, exc_type, exc_value, exc_tb):
369         if self.fp is not None:
370             self.fp.close()
371
372     def __iter__(self):
373         return self
374
375     def __next__(self):
376         while True:
377             while True:
378                 if self._pending is not None:
379                     i = self._pending
380                     self._pending = None
381                 else:
382                     i = self.fp.readline()
383                     if not i:
384                         return
385
386                 if not i.startswith('#') and i.strip():
387                     break
388
389             matches = self.field_re.match(i)
390             if matches is None:
391                 raise ValueError("Unknown line: %r" % (i))
392             yield matches.group("field"), self.fielditer()
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)