]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/opencrypto/cryptodev.py
Merge llvm-project release/17.x llvmorg-17.0.1-25-g098e653a5bed
[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 #
32
33
34 import array
35 import binascii
36 from fcntl import ioctl
37 import os
38 import platform
39 import random
40 import re
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:
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:
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         self.field_re = re.compile(r"\[(?P<field>[^]]+)\]")
362
363     def __enter__(self):
364         self.fp = open(self.fname)
365         return self
366
367     def __exit__(self, exc_type, exc_value, exc_tb):
368         if self.fp is not None:
369             self.fp.close()
370
371     def __iter__(self):
372         return self
373
374     def __next__(self):
375         while True:
376             while True:
377                 if self._pending is not None:
378                     i = self._pending
379                     self._pending = None
380                 else:
381                     i = self.fp.readline()
382                     if not i:
383                         return
384
385                 if not i.startswith('#') and i.strip():
386                     break
387
388             matches = self.field_re.match(i)
389             if matches is None:
390                 raise ValueError("Unknown line: %r" % (i))
391             yield matches.group("field"), self.fielditer()
392
393     def eatblanks(self):
394         while True:
395             line = self.fp.readline()
396             if line == '':
397                 break
398
399             line = line.strip()
400             if line:
401                 break
402
403         return line
404
405     def fielditer(self):
406         while True:
407             values = {}
408
409             line = self.eatblanks()
410             if not line or line[0] == '[':
411                 self._pending = line
412                 return
413
414             while True:
415                 try:
416                     f, v = line.split(' =')
417                 except:
418                     if line == 'FAIL':
419                         f, v = 'FAIL', ''
420                     else:
421                         print('line:', repr(line))
422                         raise
423                 v = v.strip()
424
425                 if f in values:
426                     raise ValueError('already present: %r' % repr(f))
427                 values[f] = v
428                 line = self.fp.readline().strip()
429                 if not line:
430                     break
431
432             # we should have everything
433             remain = self.fields.copy() - set(values.keys())
434             # XXX - special case GCM decrypt
435             if remain and not ('FAIL' in values and 'PT' in remain):
436                 raise ValueError('not all fields found: %r' % repr(remain))
437
438             yield values
439
440 # The CCM files use a bit of a different syntax that doesn't quite fit
441 # the generic KATParser.  In particular, some keys are set globally at
442 # the start of the file, and some are set globally at the start of a
443 # section.
444 class KATCCMParser:
445     def __init__(self, fname):
446         self._pending = None
447         self.fname = fname
448         self.fp = None
449
450     def __enter__(self):
451         self.fp = open(self.fname)
452         self.read_globals()
453         return self
454
455     def __exit__(self, exc_type, exc_value, exc_tb):
456         if self.fp is not None:
457             self.fp.close()
458
459     def read_globals(self):
460         self.global_values = {}
461         while True:
462             line = self.fp.readline()
463             if not line:
464                 return
465             if line[0] == '#' or not line.strip():
466                 continue
467             if line[0] == '[':
468                 self._pending = line
469                 return
470
471             try:
472                 f, v = line.split(' =')
473             except:
474                 print('line:', repr(line))
475                 raise
476
477             v = v.strip()
478
479             if f in self.global_values:
480                 raise ValueError('already present: %r' % repr(f))
481             self.global_values[f] = v
482
483     def read_section_values(self, kwpairs):
484         self.section_values = self.global_values.copy()
485         for pair in kwpairs.split(', '):
486             f, v = pair.split(' = ')
487             if f in self.section_values:
488                 raise ValueError('already present: %r' % repr(f))
489             self.section_values[f] = v
490
491         while True:
492             line = self.fp.readline()
493             if not line:
494                 return
495             if line[0] == '#' or not line.strip():
496                 continue
497             if line[0] == '[':
498                 self._pending = line
499                 return
500
501             try:
502                 f, v = line.split(' =')
503             except:
504                 print('line:', repr(line))
505                 raise
506
507             if f == 'Count':
508                 self._pending = line
509                 return
510
511             v = v.strip()
512
513             if f in self.section_values:
514                 raise ValueError('already present: %r' % repr(f))
515             self.section_values[f] = v
516
517     def __iter__(self):
518         return self
519
520     def __next__(self):
521         while True:
522             if self._pending:
523                 line = self._pending
524                 self._pending = None
525             else:
526                 line = self.fp.readline()
527                 if not line:
528                     return
529
530             if (line and line[0] == '#') or not line.strip():
531                 continue
532
533             if line[0] == '[':
534                 section = line[1:].split(']', 1)[0]
535                 self.read_section_values(section)
536                 continue
537
538             values = self.section_values.copy()
539
540             while True:
541                 try:
542                     f, v = line.split(' =')
543                 except:
544                     print('line:', repr(line))
545                     raise
546                 v = v.strip()
547
548                 if f in values:
549                     raise ValueError('already present: %r' % repr(f))
550                 values[f] = v
551                 line = self.fp.readline().strip()
552                 if not line:
553                     break
554
555             yield values
556
557 def _spdechex(s):
558     return binascii.hexlify(''.join(s.split()))
559
560 if sys.version_info[0] < 3:
561     KATCCMParser.next = KATCCMParser.__next__
562     KATParser.next = KATParser.__next__
563
564 if __name__ == '__main__':
565     if True:
566         try:
567             crid = Crypto.findcrid('aesni0')
568             print('aesni:', crid)
569         except IOError:
570             print('aesni0 not found')
571
572         for i in range(10):
573             try:
574                 name = Crypto.getcridname(i)
575                 print('%2d: %r' % (i, repr(name)))
576             except IOError:
577                 pass
578     elif False:
579         columns = [ 'COUNT', 'DataUnitLen', 'Key', 'DataUnitSeqNumber', 'PT', 'CT' ]
580         fname = '/usr/home/jmg/aesni.testing/format tweak value input - data unit seq no/XTSGenAES128.rsp'
581         with KATParser(fname, columns) as kp:
582             for mode, ni in kp:
583                 print(i, ni)
584                 for j in ni:
585                     print(j)
586     elif False:
587         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
588         iv = _spdechex('00000000000000000000000000000001')
589         pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e')
590         #pt = _spdechex('00000000000000000000000000000000')
591         ct = _spdechex('f42c33853ecc5ce2949865fdb83de3bff1089e9360c94f830baebfaff72836ab5236f77212f1e7396c8c54ac73d81986375a6e9e299cfeca5ba051ed25e8d1affa5beaf6c1d2b45e90802408f2ced21663497e906de5f29341e5e52ddfea5363d628b3eb7806835e17bae051b3a6da3f8e2941fe44384eac17a9d298d2c331ca8320c775b5d53263a5e905059d891b21dede2d8110fd427c7bd5a9a274ddb47b1945ee79522203b6e297d0e399ef')
592
593         c = Crypto(CRYPTO_AES_ICM, key)
594         enc = c.encrypt(pt, iv)
595
596         print('enc:', binascii.hexlify(enc))
597         print(' ct:', binascii.hexlify(ct))
598
599         assert ct == enc
600
601         dec = c.decrypt(ct, iv)
602
603         print('dec:', binascii.hexlify(dec))
604         print(' pt:', binascii.hexlify(pt))
605
606         assert pt == dec
607     elif False:
608         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
609         iv = _spdechex('00000000000000000000000000000001')
610         pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e0a3f')
611         #pt = _spdechex('00000000000000000000000000000000')
612         ct = _spdechex('f42c33853ecc5ce2949865fdb83de3bff1089e9360c94f830baebfaff72836ab5236f77212f1e7396c8c54ac73d81986375a6e9e299cfeca5ba051ed25e8d1affa5beaf6c1d2b45e90802408f2ced21663497e906de5f29341e5e52ddfea5363d628b3eb7806835e17bae051b3a6da3f8e2941fe44384eac17a9d298d2c331ca8320c775b5d53263a5e905059d891b21dede2d8110fd427c7bd5a9a274ddb47b1945ee79522203b6e297d0e399ef3768')
613
614         c = Crypto(CRYPTO_AES_ICM, key)
615         enc = c.encrypt(pt, iv)
616
617         print('enc:', binascii.hexlify(enc))
618         print(' ct:', binascii.hexlify(ct))
619
620         assert ct == enc
621
622         dec = c.decrypt(ct, iv)
623
624         print('dec:', binascii.hexlify(dec))
625         print(' pt:', binascii.hexlify(pt))
626
627         assert pt == dec
628     elif False:
629         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
630         iv = _spdechex('6eba2716ec0bd6fa5cdef5e6d3a795bc')
631         pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e0a3f')
632         ct = _spdechex('f1f81f12e72e992dbdc304032705dc75dc3e4180eff8ee4819906af6aee876d5b00b7c36d282a445ce3620327be481e8e53a8e5a8e5ca9abfeb2281be88d12ffa8f46d958d8224738c1f7eea48bda03edbf9adeb900985f4fa25648b406d13a886c25e70cfdecdde0ad0f2991420eb48a61c64fd797237cf2798c2675b9bb744360b0a3f329ac53bbceb4e3e7456e6514f1a9d2f06c236c31d0f080b79c15dce1096357416602520daa098b17d1af427')
633         c = Crypto(CRYPTO_AES_CBC, key)
634
635         enc = c.encrypt(pt, iv)
636
637         print('enc:', binascii.hexlify(enc))
638         print(' ct:', binascii.hexlify(ct))
639
640         assert ct == enc
641
642         dec = c.decrypt(ct, iv)
643
644         print('dec:', binascii.hexlify(dec))
645         print(' pt:', binascii.hexlify(pt))
646
647         assert pt == dec
648     elif False:
649         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
650         iv = _spdechex('b3d8cc017cbb89b39e0f67e2')
651         pt = _spdechex('c3b3c41f113a31b73d9a5cd4321030')
652         aad = _spdechex('24825602bd12a984e0092d3e448eda5f')
653         ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa7354')
654         ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa73')
655         tag = _spdechex('0032a1dc85f1c9786925a2e71d8272dd')
656         tag = _spdechex('8d11a0929cb3fbe1fef01a4a38d5f8ea')
657
658         c = Crypto(CRYPTO_AES_NIST_GCM_16, key)
659
660         enc, enctag = c.encrypt(pt, iv, aad=aad)
661
662         print('enc:', binascii.hexlify(enc))
663         print(' ct:', binascii.hexlify(ct))
664
665         assert enc == ct
666
667         print('etg:', binascii.hexlify(enctag))
668         print('tag:', binascii.hexlify(tag))
669         assert enctag == tag
670
671         # Make sure we get EBADMSG
672         #enctag = enctag[:-1] + 'a'
673         dec, dectag = c.decrypt(ct, iv, aad=aad, tag=enctag)
674
675         print('dec:', binascii.hexlify(dec))
676         print(' pt:', binascii.hexlify(pt))
677
678         assert dec == pt
679
680         print('dtg:', binascii.hexlify(dectag))
681         print('tag:', binascii.hexlify(tag))
682
683         assert dectag == tag
684     elif False:
685         key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c')
686         iv = _spdechex('b3d8cc017cbb89b39e0f67e2')
687         key = key + iv[:4]
688         iv = iv[4:]
689         pt = _spdechex('c3b3c41f113a31b73d9a5cd432103069')
690         aad = _spdechex('24825602bd12a984e0092d3e448eda5f')
691         ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa7354')
692         tag = _spdechex('0032a1dc85f1c9786925a2e71d8272dd')
693
694         c = Crypto(CRYPTO_AES_GCM_16, key)
695
696         enc, enctag = c.encrypt(pt, iv, aad=aad)
697
698         print('enc:', binascii.hexlify(enc))
699         print(' ct:', binascii.hexlify(ct))
700
701         assert enc == ct
702
703         print('etg:', binascii.hexlify(enctag))
704         print('tag:', binascii.hexlify(tag))
705         assert enctag == tag
706     elif False:
707         for i in range(100000):
708             c = Crypto(CRYPTO_AES_XTS, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'))
709             data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec')
710             ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240')
711             iv = _pack('QQ', 71, 0)
712
713             enc = c.encrypt(data, iv)
714             assert enc == ct
715     elif True:
716         c = Crypto(CRYPTO_AES_XTS, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'))
717         data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec')
718         ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240')
719         iv = _pack('QQ', 71, 0)
720
721         enc = c.encrypt(data, iv)
722         assert enc == ct
723
724         dec = c.decrypt(enc, iv)
725         assert dec == data
726
727         #c.perftest(COP_ENCRYPT, 192*1024, reps=30000)
728
729     else:
730         key = binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382')
731         print('XTS %d testing:' % (len(key) * 8))
732         c = Crypto(CRYPTO_AES_XTS, key)
733         for i in [ 8192, 192*1024]:
734             print('block size: %d' % i)
735             c.perftest(COP_ENCRYPT, i)
736             c.perftest(COP_DECRYPT, i)