xref: /freebsd/tests/sys/opencrypto/cryptotest.py (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
12a7a4b19SAlan Somers#!/usr/local/bin/python3
208fca7a5SJohn-Mark Gurney#
308fca7a5SJohn-Mark Gurney# Copyright (c) 2014 The FreeBSD Foundation
408fca7a5SJohn-Mark Gurney# All rights reserved.
5f2a34445SEnji Cooper# Copyright 2019 Enji Cooper
608fca7a5SJohn-Mark Gurney#
708fca7a5SJohn-Mark Gurney# This software was developed by John-Mark Gurney under
808fca7a5SJohn-Mark Gurney# the sponsorship from the FreeBSD Foundation.
908fca7a5SJohn-Mark Gurney# Redistribution and use in source and binary forms, with or without
1008fca7a5SJohn-Mark Gurney# modification, are permitted provided that the following conditions
1108fca7a5SJohn-Mark Gurney# are met:
1208fca7a5SJohn-Mark Gurney# 1.  Redistributions of source code must retain the above copyright
1308fca7a5SJohn-Mark Gurney#     notice, this list of conditions and the following disclaimer.
1408fca7a5SJohn-Mark Gurney# 2.  Redistributions in binary form must reproduce the above copyright
1508fca7a5SJohn-Mark Gurney#     notice, this list of conditions and the following disclaimer in the
1608fca7a5SJohn-Mark Gurney#     documentation and/or other materials provided with the distribution.
1708fca7a5SJohn-Mark Gurney#
1808fca7a5SJohn-Mark Gurney# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1908fca7a5SJohn-Mark Gurney# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2008fca7a5SJohn-Mark Gurney# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2108fca7a5SJohn-Mark Gurney# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2208fca7a5SJohn-Mark Gurney# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2308fca7a5SJohn-Mark Gurney# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2408fca7a5SJohn-Mark Gurney# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2508fca7a5SJohn-Mark Gurney# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2608fca7a5SJohn-Mark Gurney# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2708fca7a5SJohn-Mark Gurney# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2808fca7a5SJohn-Mark Gurney# SUCH DAMAGE.
2908fca7a5SJohn-Mark Gurney#
3008fca7a5SJohn-Mark Gurney#
3108fca7a5SJohn-Mark Gurney
322a7a4b19SAlan Somers
33d99c2cecSEnji Cooper
34d99c2cecSEnji Cooperimport binascii
35a317fb03SConrad Meyerimport errno
3608fca7a5SJohn-Mark Gurneyimport cryptodev
3708fca7a5SJohn-Mark Gurneyimport itertools
3808fca7a5SJohn-Mark Gurneyimport os
3908fca7a5SJohn-Mark Gurneyimport struct
4008fca7a5SJohn-Mark Gurneyimport unittest
4108fca7a5SJohn-Mark Gurneyfrom cryptodev import *
4208fca7a5SJohn-Mark Gurneyfrom glob import iglob
4308fca7a5SJohn-Mark Gurney
4408fca7a5SJohn-Mark Gurneykatdir = '/usr/local/share/nist-kat'
4508fca7a5SJohn-Mark Gurney
4608fca7a5SJohn-Mark Gurneydef katg(base, glob):
47aeb5c8e6SJohn Baldwin    assert os.path.exists(katdir), "Please 'pkg install nist-kat'"
48aeb5c8e6SJohn Baldwin    if not os.path.exists(os.path.join(katdir, base)):
49aeb5c8e6SJohn Baldwin        raise unittest.SkipTest("Missing %s test vectors" % (base))
5008fca7a5SJohn-Mark Gurney    return iglob(os.path.join(katdir, base, glob))
5108fca7a5SJohn-Mark Gurney
52*197ff4c3SKornel Dulebaaesmodules = [ 'cryptosoft0', 'aesni0', 'armv8crypto0', 'ccr0', 'ccp0', 'ossl0', 'safexcel0', 'qat0' ]
53870d4ba3SMark Johnstonshamodules = [ 'cryptosoft0', 'aesni0', 'armv8crypto0', 'ccr0', 'ccp0', 'ossl0', 'safexcel0', 'qat0' ]
5408fca7a5SJohn-Mark Gurney
5508fca7a5SJohn-Mark Gurneydef GenTestCase(cname):
5608fca7a5SJohn-Mark Gurney    try:
5708fca7a5SJohn-Mark Gurney        crid = cryptodev.Crypto.findcrid(cname)
5808fca7a5SJohn-Mark Gurney    except IOError:
5908fca7a5SJohn-Mark Gurney        return None
6008fca7a5SJohn-Mark Gurney
6108fca7a5SJohn-Mark Gurney    class GendCryptoTestCase(unittest.TestCase):
6208fca7a5SJohn-Mark Gurney        ###############
6308fca7a5SJohn-Mark Gurney        ##### AES #####
6408fca7a5SJohn-Mark Gurney        ###############
65c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-XTS on %s' % (cname))
6608fca7a5SJohn-Mark Gurney        def test_xts(self):
6708fca7a5SJohn-Mark Gurney            for i in katg('XTSTestVectors/format tweak value input - data unit seq no', '*.rsp'):
6808fca7a5SJohn-Mark Gurney                self.runXTS(i, cryptodev.CRYPTO_AES_XTS)
6908fca7a5SJohn-Mark Gurney
70c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-CBC on %s' % (cname))
7108fca7a5SJohn-Mark Gurney        def test_cbc(self):
7208fca7a5SJohn-Mark Gurney            for i in katg('KAT_AES', 'CBC[GKV]*.rsp'):
7308fca7a5SJohn-Mark Gurney                self.runCBC(i)
7408fca7a5SJohn-Mark Gurney
75151f0ca8SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-CCM on %s' % (cname))
76151f0ca8SJohn Baldwin        def test_ccm(self):
77151f0ca8SJohn Baldwin            for i in katg('ccmtestvectors', 'V*.rsp'):
78151f0ca8SJohn Baldwin                self.runCCMEncrypt(i)
79151f0ca8SJohn Baldwin
80151f0ca8SJohn Baldwin            for i in katg('ccmtestvectors', 'D*.rsp'):
81151f0ca8SJohn Baldwin                self.runCCMDecrypt(i)
82151f0ca8SJohn Baldwin
83c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-GCM on %s' % (cname))
8408fca7a5SJohn-Mark Gurney        def test_gcm(self):
8508fca7a5SJohn-Mark Gurney            for i in katg('gcmtestvectors', 'gcmEncrypt*'):
8608fca7a5SJohn-Mark Gurney                self.runGCM(i, 'ENCRYPT')
8708fca7a5SJohn-Mark Gurney
8808fca7a5SJohn-Mark Gurney            for i in katg('gcmtestvectors', 'gcmDecrypt*'):
8908fca7a5SJohn-Mark Gurney                self.runGCM(i, 'DECRYPT')
9008fca7a5SJohn-Mark Gurney
9108fca7a5SJohn-Mark Gurney        def runGCM(self, fname, mode):
9208fca7a5SJohn-Mark Gurney            curfun = None
9308fca7a5SJohn-Mark Gurney            if mode == 'ENCRYPT':
9408fca7a5SJohn-Mark Gurney                swapptct = False
9508fca7a5SJohn-Mark Gurney                curfun = Crypto.encrypt
9608fca7a5SJohn-Mark Gurney            elif mode == 'DECRYPT':
9708fca7a5SJohn-Mark Gurney                swapptct = True
9808fca7a5SJohn-Mark Gurney                curfun = Crypto.decrypt
9908fca7a5SJohn-Mark Gurney            else:
100d86680b0SEnji Cooper                raise RuntimeError('unknown mode: %r' % repr(mode))
10108fca7a5SJohn-Mark Gurney
102a60d9a98SEnji Cooper            columns = [ 'Count', 'Key', 'IV', 'CT', 'AAD', 'Tag', 'PT', ]
103a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
104a60d9a98SEnji Cooper                self.runGCMWithParser(parser, mode)
105a60d9a98SEnji Cooper
106a60d9a98SEnji Cooper        def runGCMWithParser(self, parser, mode):
107a60d9a98SEnji Cooper            for _, lines in next(parser):
10808fca7a5SJohn-Mark Gurney                for data in lines:
10908fca7a5SJohn-Mark Gurney                    curcnt = int(data['Count'])
110d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(data['Key'])
111d99c2cecSEnji Cooper                    iv = binascii.unhexlify(data['IV'])
112d99c2cecSEnji Cooper                    aad = binascii.unhexlify(data['AAD'])
113d99c2cecSEnji Cooper                    tag = binascii.unhexlify(data['Tag'])
11408fca7a5SJohn-Mark Gurney                    if 'FAIL' not in data:
115d99c2cecSEnji Cooper                        pt = binascii.unhexlify(data['PT'])
116d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CT'])
11708fca7a5SJohn-Mark Gurney
11808fca7a5SJohn-Mark Gurney                    if len(iv) != 12:
11908fca7a5SJohn-Mark Gurney                        # XXX - isn't supported
12008fca7a5SJohn-Mark Gurney                        continue
12108fca7a5SJohn-Mark Gurney
122844d9543SConrad Meyer                    try:
12308fca7a5SJohn-Mark Gurney                        c = Crypto(cryptodev.CRYPTO_AES_NIST_GCM_16,
124c0341432SJohn Baldwin                            cipherkey, crid=crid,
125de0f7dcaSJohn Baldwin                            maclen=16)
126b106e0fcSEnji Cooper                    except EnvironmentError as e:
127844d9543SConrad Meyer                        # Can't test algorithms the driver does not support.
128844d9543SConrad Meyer                        if e.errno != errno.EOPNOTSUPP:
129844d9543SConrad Meyer                            raise
130844d9543SConrad Meyer                        continue
13108fca7a5SJohn-Mark Gurney
13208fca7a5SJohn-Mark Gurney                    if mode == 'ENCRYPT':
133844d9543SConrad Meyer                        try:
13408fca7a5SJohn-Mark Gurney                            rct, rtag = c.encrypt(pt, iv, aad)
135b106e0fcSEnji Cooper                        except EnvironmentError as e:
136844d9543SConrad Meyer                            # Can't test inputs the driver does not support.
137844d9543SConrad Meyer                            if e.errno != errno.EINVAL:
138844d9543SConrad Meyer                                raise
139844d9543SConrad Meyer                            continue
14008fca7a5SJohn-Mark Gurney                        rtag = rtag[:len(tag)]
141d99c2cecSEnji Cooper                        data['rct'] = binascii.hexlify(rct)
142d99c2cecSEnji Cooper                        data['rtag'] = binascii.hexlify(rtag)
143d86680b0SEnji Cooper                        self.assertEqual(rct, ct, repr(data))
144d86680b0SEnji Cooper                        self.assertEqual(rtag, tag, repr(data))
14508fca7a5SJohn-Mark Gurney                    else:
14608fca7a5SJohn-Mark Gurney                        if len(tag) != 16:
14708fca7a5SJohn-Mark Gurney                            continue
14808fca7a5SJohn-Mark Gurney                        args = (ct, iv, aad, tag)
14908fca7a5SJohn-Mark Gurney                        if 'FAIL' in data:
15008fca7a5SJohn-Mark Gurney                            self.assertRaises(IOError,
15108fca7a5SJohn-Mark Gurney                                c.decrypt, *args)
15208fca7a5SJohn-Mark Gurney                        else:
153844d9543SConrad Meyer                            try:
15408fca7a5SJohn-Mark Gurney                                rpt, rtag = c.decrypt(*args)
155b106e0fcSEnji Cooper                            except EnvironmentError as e:
156844d9543SConrad Meyer                                # Can't test inputs the driver does not support.
157844d9543SConrad Meyer                                if e.errno != errno.EINVAL:
158844d9543SConrad Meyer                                    raise
159844d9543SConrad Meyer                                continue
160d99c2cecSEnji Cooper                            data['rpt'] = binascii.hexlify(rpt)
161d99c2cecSEnji Cooper                            data['rtag'] = binascii.hexlify(rtag)
16208fca7a5SJohn-Mark Gurney                            self.assertEqual(rpt, pt,
163d86680b0SEnji Cooper                                repr(data))
16408fca7a5SJohn-Mark Gurney
16508fca7a5SJohn-Mark Gurney        def runCBC(self, fname):
166a60d9a98SEnji Cooper            columns = [ 'COUNT', 'KEY', 'IV', 'PLAINTEXT', 'CIPHERTEXT', ]
167a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
168a60d9a98SEnji Cooper                self.runCBCWithParser(parser)
169a60d9a98SEnji Cooper
170a60d9a98SEnji Cooper        def runCBCWithParser(self, parser):
17108fca7a5SJohn-Mark Gurney            curfun = None
172a60d9a98SEnji Cooper            for mode, lines in next(parser):
17308fca7a5SJohn-Mark Gurney                if mode == 'ENCRYPT':
17408fca7a5SJohn-Mark Gurney                    swapptct = False
17508fca7a5SJohn-Mark Gurney                    curfun = Crypto.encrypt
17608fca7a5SJohn-Mark Gurney                elif mode == 'DECRYPT':
17708fca7a5SJohn-Mark Gurney                    swapptct = True
17808fca7a5SJohn-Mark Gurney                    curfun = Crypto.decrypt
17908fca7a5SJohn-Mark Gurney                else:
180d86680b0SEnji Cooper                    raise RuntimeError('unknown mode: %r' % repr(mode))
18108fca7a5SJohn-Mark Gurney
18208fca7a5SJohn-Mark Gurney                for data in lines:
18308fca7a5SJohn-Mark Gurney                    curcnt = int(data['COUNT'])
184d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(data['KEY'])
185d99c2cecSEnji Cooper                    iv = binascii.unhexlify(data['IV'])
186d99c2cecSEnji Cooper                    pt = binascii.unhexlify(data['PLAINTEXT'])
187d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CIPHERTEXT'])
18808fca7a5SJohn-Mark Gurney
18908fca7a5SJohn-Mark Gurney                    if swapptct:
19008fca7a5SJohn-Mark Gurney                        pt, ct = ct, pt
19108fca7a5SJohn-Mark Gurney                    # run the fun
19208fca7a5SJohn-Mark Gurney                    c = Crypto(cryptodev.CRYPTO_AES_CBC, cipherkey, crid=crid)
19308fca7a5SJohn-Mark Gurney                    r = curfun(c, pt, iv)
19408fca7a5SJohn-Mark Gurney                    self.assertEqual(r, ct)
19508fca7a5SJohn-Mark Gurney
19608fca7a5SJohn-Mark Gurney        def runXTS(self, fname, meth):
197a60d9a98SEnji Cooper            columns = [ 'COUNT', 'DataUnitLen', 'Key', 'DataUnitSeqNumber', 'PT',
198a60d9a98SEnji Cooper                        'CT']
199a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
200a60d9a98SEnji Cooper                self.runXTSWithParser(parser, meth)
201a60d9a98SEnji Cooper
202a60d9a98SEnji Cooper        def runXTSWithParser(self, parser, meth):
20308fca7a5SJohn-Mark Gurney            curfun = None
204a60d9a98SEnji Cooper            for mode, lines in next(parser):
20508fca7a5SJohn-Mark Gurney                if mode == 'ENCRYPT':
20608fca7a5SJohn-Mark Gurney                    swapptct = False
20708fca7a5SJohn-Mark Gurney                    curfun = Crypto.encrypt
20808fca7a5SJohn-Mark Gurney                elif mode == 'DECRYPT':
20908fca7a5SJohn-Mark Gurney                    swapptct = True
21008fca7a5SJohn-Mark Gurney                    curfun = Crypto.decrypt
21108fca7a5SJohn-Mark Gurney                else:
212d86680b0SEnji Cooper                    raise RuntimeError('unknown mode: %r' % repr(mode))
21308fca7a5SJohn-Mark Gurney
21408fca7a5SJohn-Mark Gurney                for data in lines:
21508fca7a5SJohn-Mark Gurney                    curcnt = int(data['COUNT'])
21608fca7a5SJohn-Mark Gurney                    nbits = int(data['DataUnitLen'])
217d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(data['Key'])
21808fca7a5SJohn-Mark Gurney                    iv = struct.pack('QQ', int(data['DataUnitSeqNumber']), 0)
219d99c2cecSEnji Cooper                    pt = binascii.unhexlify(data['PT'])
220d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CT'])
22108fca7a5SJohn-Mark Gurney
22208fca7a5SJohn-Mark Gurney                    if nbits % 128 != 0:
22308fca7a5SJohn-Mark Gurney                        # XXX - mark as skipped
22408fca7a5SJohn-Mark Gurney                        continue
22508fca7a5SJohn-Mark Gurney                    if swapptct:
22608fca7a5SJohn-Mark Gurney                        pt, ct = ct, pt
22708fca7a5SJohn-Mark Gurney                    # run the fun
228844d9543SConrad Meyer                    try:
22908fca7a5SJohn-Mark Gurney                        c = Crypto(meth, cipherkey, crid=crid)
23008fca7a5SJohn-Mark Gurney                        r = curfun(c, pt, iv)
231b106e0fcSEnji Cooper                    except EnvironmentError as e:
232844d9543SConrad Meyer                        # Can't test hashes the driver does not support.
233844d9543SConrad Meyer                        if e.errno != errno.EOPNOTSUPP:
234844d9543SConrad Meyer                            raise
235844d9543SConrad Meyer                        continue
23608fca7a5SJohn-Mark Gurney                    self.assertEqual(r, ct)
23708fca7a5SJohn-Mark Gurney
238151f0ca8SJohn Baldwin        def runCCMEncrypt(self, fname):
239a60d9a98SEnji Cooper            with cryptodev.KATCCMParser(fname) as parser:
240a60d9a98SEnji Cooper                self.runCCMEncryptWithParser(parser)
241a60d9a98SEnji Cooper
242a60d9a98SEnji Cooper        def runCCMEncryptWithParser(self, parser):
243a60d9a98SEnji Cooper            for data in next(parser):
244151f0ca8SJohn Baldwin                Nlen = int(data['Nlen'])
245668770dcSJohn Baldwin                Tlen = int(data['Tlen'])
246d99c2cecSEnji Cooper                key = binascii.unhexlify(data['Key'])
247d99c2cecSEnji Cooper                nonce = binascii.unhexlify(data['Nonce'])
248151f0ca8SJohn Baldwin                Alen = int(data['Alen'])
249668770dcSJohn Baldwin                Plen = int(data['Plen'])
250151f0ca8SJohn Baldwin                if Alen != 0:
251d99c2cecSEnji Cooper                    aad = binascii.unhexlify(data['Adata'])
252151f0ca8SJohn Baldwin                else:
253151f0ca8SJohn Baldwin                    aad = None
254668770dcSJohn Baldwin                if Plen != 0:
255d99c2cecSEnji Cooper                    payload = binascii.unhexlify(data['Payload'])
256668770dcSJohn Baldwin                else:
257668770dcSJohn Baldwin                    payload = None
258d99c2cecSEnji Cooper                ct = binascii.unhexlify(data['CT'])
259151f0ca8SJohn Baldwin
260151f0ca8SJohn Baldwin                try:
261151f0ca8SJohn Baldwin                    c = Crypto(crid=crid,
262151f0ca8SJohn Baldwin                        cipher=cryptodev.CRYPTO_AES_CCM_16,
263151f0ca8SJohn Baldwin                        key=key,
264668770dcSJohn Baldwin                        mackey=key, maclen=Tlen, ivlen=Nlen)
265151f0ca8SJohn Baldwin                    r, tag = Crypto.encrypt(c, payload,
266151f0ca8SJohn Baldwin                        nonce, aad)
267b106e0fcSEnji Cooper                except EnvironmentError as e:
268151f0ca8SJohn Baldwin                    if e.errno != errno.EOPNOTSUPP:
269151f0ca8SJohn Baldwin                        raise
270151f0ca8SJohn Baldwin                    continue
271151f0ca8SJohn Baldwin
272151f0ca8SJohn Baldwin                out = r + tag
273151f0ca8SJohn Baldwin                self.assertEqual(out, ct,
274151f0ca8SJohn Baldwin                    "Count " + data['Count'] + " Actual: " + \
275e8b4bbdfSEnji Cooper                    repr(binascii.hexlify(out)) + " Expected: " + \
276151f0ca8SJohn Baldwin                    repr(data) + " on " + cname)
277151f0ca8SJohn Baldwin
278151f0ca8SJohn Baldwin        def runCCMDecrypt(self, fname):
279a60d9a98SEnji Cooper            with cryptodev.KATCCMParser(fname) as parser:
280a60d9a98SEnji Cooper                self.runCCMDecryptWithParser(parser)
281a60d9a98SEnji Cooper
282a60d9a98SEnji Cooper        def runCCMDecryptWithParser(self, parser):
283a60d9a98SEnji Cooper            for data in next(parser):
284151f0ca8SJohn Baldwin                Nlen = int(data['Nlen'])
285151f0ca8SJohn Baldwin                Tlen = int(data['Tlen'])
286d99c2cecSEnji Cooper                key = binascii.unhexlify(data['Key'])
287d99c2cecSEnji Cooper                nonce = binascii.unhexlify(data['Nonce'])
288151f0ca8SJohn Baldwin                Alen = int(data['Alen'])
289668770dcSJohn Baldwin                Plen = int(data['Plen'])
290151f0ca8SJohn Baldwin                if Alen != 0:
291d99c2cecSEnji Cooper                    aad = binascii.unhexlify(data['Adata'])
292151f0ca8SJohn Baldwin                else:
293151f0ca8SJohn Baldwin                    aad = None
294d99c2cecSEnji Cooper                ct = binascii.unhexlify(data['CT'])
295668770dcSJohn Baldwin                tag = ct[-Tlen:]
296668770dcSJohn Baldwin                if Plen != 0:
297668770dcSJohn Baldwin                    payload = ct[:-Tlen]
298668770dcSJohn Baldwin                else:
299668770dcSJohn Baldwin                    payload = None
300151f0ca8SJohn Baldwin
301151f0ca8SJohn Baldwin                try:
302151f0ca8SJohn Baldwin                    c = Crypto(crid=crid,
303151f0ca8SJohn Baldwin                        cipher=cryptodev.CRYPTO_AES_CCM_16,
304151f0ca8SJohn Baldwin                        key=key,
305668770dcSJohn Baldwin                        mackey=key, maclen=Tlen, ivlen=Nlen)
306b106e0fcSEnji Cooper                except EnvironmentError as e:
307151f0ca8SJohn Baldwin                    if e.errno != errno.EOPNOTSUPP:
308151f0ca8SJohn Baldwin                        raise
309151f0ca8SJohn Baldwin                    continue
310151f0ca8SJohn Baldwin
311151f0ca8SJohn Baldwin                if data['Result'] == 'Fail':
312151f0ca8SJohn Baldwin                    self.assertRaises(IOError,
313151f0ca8SJohn Baldwin                        c.decrypt, payload, nonce, aad, tag)
314151f0ca8SJohn Baldwin                else:
315668770dcSJohn Baldwin                    r, tag = Crypto.decrypt(c, payload, nonce,
316151f0ca8SJohn Baldwin                                            aad, tag)
317151f0ca8SJohn Baldwin
318d99c2cecSEnji Cooper                    payload = binascii.unhexlify(data['Payload'])
319668770dcSJohn Baldwin                    payload = payload[:Plen]
320151f0ca8SJohn Baldwin                    self.assertEqual(r, payload,
321151f0ca8SJohn Baldwin                        "Count " + data['Count'] + \
322e8b4bbdfSEnji Cooper                        " Actual: " + repr(binascii.hexlify(r)) + \
323151f0ca8SJohn Baldwin                        " Expected: " + repr(data) + \
324151f0ca8SJohn Baldwin                        " on " + cname)
325151f0ca8SJohn Baldwin
32608fca7a5SJohn-Mark Gurney        ###############
32708fca7a5SJohn-Mark Gurney        ##### SHA #####
32808fca7a5SJohn-Mark Gurney        ###############
329d86680b0SEnji Cooper        @unittest.skipIf(cname not in shamodules, 'skipping SHA on %s' % str(cname))
33008fca7a5SJohn-Mark Gurney        def test_sha(self):
331de0f7dcaSJohn Baldwin            for i in katg('shabytetestvectors', 'SHA*Msg.rsp'):
332de0f7dcaSJohn Baldwin                self.runSHA(i)
333de0f7dcaSJohn Baldwin
334de0f7dcaSJohn Baldwin        def runSHA(self, fname):
335de0f7dcaSJohn Baldwin            # Skip SHA512_(224|256) tests
336de0f7dcaSJohn Baldwin            if fname.find('SHA512_') != -1:
337de0f7dcaSJohn Baldwin                return
338a60d9a98SEnji Cooper            columns = [ 'Len', 'Msg', 'MD' ]
339a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
340a60d9a98SEnji Cooper                self.runSHAWithParser(parser)
341de0f7dcaSJohn Baldwin
342a60d9a98SEnji Cooper        def runSHAWithParser(self, parser):
343a60d9a98SEnji Cooper            for hashlength, lines in next(parser):
344de0f7dcaSJohn Baldwin                # E.g., hashlength will be "L=20" (bytes)
345de0f7dcaSJohn Baldwin                hashlen = int(hashlength.split("=")[1])
346de0f7dcaSJohn Baldwin
347de0f7dcaSJohn Baldwin                if hashlen == 20:
348de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA1
349de0f7dcaSJohn Baldwin                elif hashlen == 28:
350de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_224
351de0f7dcaSJohn Baldwin                elif hashlen == 32:
352de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_256
353de0f7dcaSJohn Baldwin                elif hashlen == 48:
354de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_384
355de0f7dcaSJohn Baldwin                elif hashlen == 64:
356de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_512
357de0f7dcaSJohn Baldwin                else:
358de0f7dcaSJohn Baldwin                    # Skip unsupported hashes
359de0f7dcaSJohn Baldwin                    # Slurp remaining input in section
360de0f7dcaSJohn Baldwin                    for data in lines:
361de0f7dcaSJohn Baldwin                        continue
362de0f7dcaSJohn Baldwin                    continue
363de0f7dcaSJohn Baldwin
364de0f7dcaSJohn Baldwin                for data in lines:
365d99c2cecSEnji Cooper                    msg = binascii.unhexlify(data['Msg'])
366de0f7dcaSJohn Baldwin                    msg = msg[:int(data['Len'])]
367d99c2cecSEnji Cooper                    md = binascii.unhexlify(data['MD'])
368de0f7dcaSJohn Baldwin
369de0f7dcaSJohn Baldwin                    try:
370de0f7dcaSJohn Baldwin                        c = Crypto(mac=alg, crid=crid,
371de0f7dcaSJohn Baldwin                            maclen=hashlen)
372b106e0fcSEnji Cooper                    except EnvironmentError as e:
373de0f7dcaSJohn Baldwin                        # Can't test hashes the driver does not support.
374de0f7dcaSJohn Baldwin                        if e.errno != errno.EOPNOTSUPP:
375de0f7dcaSJohn Baldwin                            raise
376de0f7dcaSJohn Baldwin                        continue
377de0f7dcaSJohn Baldwin
378de0f7dcaSJohn Baldwin                    _, r = c.encrypt(msg, iv="")
379de0f7dcaSJohn Baldwin
380de0f7dcaSJohn Baldwin                    self.assertEqual(r, md, "Actual: " + \
381e8b4bbdfSEnji Cooper                        repr(binascii.hexlify(r)) + " Expected: " + repr(data) + " on " + cname)
38208fca7a5SJohn-Mark Gurney
383c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in shamodules, 'skipping SHA-HMAC on %s' % str(cname))
38408fca7a5SJohn-Mark Gurney        def test_sha1hmac(self):
38508fca7a5SJohn-Mark Gurney            for i in katg('hmactestvectors', 'HMAC.rsp'):
38608fca7a5SJohn-Mark Gurney                self.runSHA1HMAC(i)
38708fca7a5SJohn-Mark Gurney
38808fca7a5SJohn-Mark Gurney        def runSHA1HMAC(self, fname):
389a60d9a98SEnji Cooper            columns = [ 'Count', 'Klen', 'Tlen', 'Key', 'Msg', 'Mac' ]
390a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
391a60d9a98SEnji Cooper                self.runSHA1HMACWithParser(parser)
392a60d9a98SEnji Cooper
393a60d9a98SEnji Cooper        def runSHA1HMACWithParser(self, parser):
394a60d9a98SEnji Cooper            for hashlength, lines in next(parser):
395005fdbbcSConrad Meyer                # E.g., hashlength will be "L=20" (bytes)
396005fdbbcSConrad Meyer                hashlen = int(hashlength.split("=")[1])
397005fdbbcSConrad Meyer
398005fdbbcSConrad Meyer                blocksize = None
399005fdbbcSConrad Meyer                if hashlen == 20:
400005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA1_HMAC
401005fdbbcSConrad Meyer                    blocksize = 64
402005fdbbcSConrad Meyer                elif hashlen == 28:
403c87ada6aSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_224_HMAC
404c87ada6aSJohn Baldwin                    blocksize = 64
405005fdbbcSConrad Meyer                elif hashlen == 32:
406005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA2_256_HMAC
407005fdbbcSConrad Meyer                    blocksize = 64
408005fdbbcSConrad Meyer                elif hashlen == 48:
409005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA2_384_HMAC
410005fdbbcSConrad Meyer                    blocksize = 128
411005fdbbcSConrad Meyer                elif hashlen == 64:
412005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA2_512_HMAC
413005fdbbcSConrad Meyer                    blocksize = 128
414005fdbbcSConrad Meyer                else:
415005fdbbcSConrad Meyer                    # Skip unsupported hashes
416005fdbbcSConrad Meyer                    # Slurp remaining input in section
417005fdbbcSConrad Meyer                    for data in lines:
418005fdbbcSConrad Meyer                        continue
419005fdbbcSConrad Meyer                    continue
420005fdbbcSConrad Meyer
42108fca7a5SJohn-Mark Gurney                for data in lines:
422d99c2cecSEnji Cooper                    key = binascii.unhexlify(data['Key'])
423d99c2cecSEnji Cooper                    msg = binascii.unhexlify(data['Msg'])
424d99c2cecSEnji Cooper                    mac = binascii.unhexlify(data['Mac'])
425005fdbbcSConrad Meyer                    tlen = int(data['Tlen'])
42608fca7a5SJohn-Mark Gurney
427005fdbbcSConrad Meyer                    if len(key) > blocksize:
42808fca7a5SJohn-Mark Gurney                        continue
42908fca7a5SJohn-Mark Gurney
430a317fb03SConrad Meyer                    try:
431005fdbbcSConrad Meyer                        c = Crypto(mac=alg, mackey=key,
432de0f7dcaSJohn Baldwin                            crid=crid, maclen=hashlen)
433b106e0fcSEnji Cooper                    except EnvironmentError as e:
434a317fb03SConrad Meyer                        # Can't test hashes the driver does not support.
435a317fb03SConrad Meyer                        if e.errno != errno.EOPNOTSUPP:
436a317fb03SConrad Meyer                            raise
437a317fb03SConrad Meyer                        continue
43808fca7a5SJohn-Mark Gurney
439005fdbbcSConrad Meyer                    _, r = c.encrypt(msg, iv="")
440005fdbbcSConrad Meyer
441de0f7dcaSJohn Baldwin                    self.assertEqual(r[:tlen], mac, "Actual: " + \
442e8b4bbdfSEnji Cooper                        repr(binascii.hexlify(r)) + " Expected: " + repr(data))
44308fca7a5SJohn-Mark Gurney
44408fca7a5SJohn-Mark Gurney    return GendCryptoTestCase
44508fca7a5SJohn-Mark Gurney
44608fca7a5SJohn-Mark Gurneycryptosoft = GenTestCase('cryptosoft0')
44708fca7a5SJohn-Mark Gurneyaesni = GenTestCase('aesni0')
44884a457c6SEnji Cooperarmv8crypto = GenTestCase('armv8crypto0')
4496720b890SJohn Baldwinccr = GenTestCase('ccr0')
450844d9543SConrad Meyerccp = GenTestCase('ccp0')
451ac619349SJung-uk Kimossl = GenTestCase('ossl0')
4529a1184deSMark Johnstonsafexcel = GenTestCase('safexcel0')
453870d4ba3SMark Johnstonqat = GenTestCase('qat0')
45408fca7a5SJohn-Mark Gurney
45508fca7a5SJohn-Mark Gurneyif __name__ == '__main__':
45608fca7a5SJohn-Mark Gurney    unittest.main()
457