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