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