xref: /freebsd/tests/sys/opencrypto/cryptodev.py (revision ffbc8cc0f2f20c4169faa2acd553e5ab7bbefbf8)
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
33from __future__ import print_function
34import array
35import binascii
36from fcntl import ioctl
37import os
38import random
39import signal
40from struct import pack as _pack
41import sys
42import time
43
44import dpkt
45
46from cryptodevh import *
47
48__all__ = [ 'Crypto', 'MismatchError', ]
49
50class FindOp(dpkt.Packet):
51    __byte_order__ = '@'
52    __hdr__ = (
53        ('crid', 'i',   0),
54        ('name', '32s', 0),
55    )
56
57class 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
69class 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
86class 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
99class 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
116CRIOGET = 3221513060
117CIOCGSESSION = 3224396645
118CIOCGSESSION2 = 3225445226
119CIOCFSESSION = 2147771238
120CIOCCRYPT = 3224396647
121CIOCKEY = 3230688104
122CIOCASYMFEAT = 1074029417
123CIOCKEY2 = 3230688107
124CIOCFINDDEV = 3223610220
125CIOCCRYPTAEAD = 3225445229
126
127def _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
139def 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
145def _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
161def array_tobytes(array_obj):
162    if sys.version_info[:2] >= (3, 2):
163        return array_obj.tobytes()
164    return array_obj.tostring()
165
166class 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
331class MismatchError(Exception):
332    pass
333
334class 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.
424class 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
537def _spdechex(s):
538    return binascii.hexlify(''.join(s.split()))
539
540if sys.version_info[0] < 3:
541    KATCCMParser.next = KATCCMParser.__next__
542    KATParser.next = KATParser.__next__
543
544if __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)
718