xref: /freebsd/tests/sys/opencrypto/cryptotest.py (revision a60d9a98927226deb5b7a716892db27dfa3181da)
1369ee090SLi-Wen Hsu#!/usr/local/bin/python2
208fca7a5SJohn-Mark Gurney#
308fca7a5SJohn-Mark Gurney# Copyright (c) 2014 The FreeBSD Foundation
408fca7a5SJohn-Mark Gurney# All rights reserved.
508fca7a5SJohn-Mark Gurney#
608fca7a5SJohn-Mark Gurney# This software was developed by John-Mark Gurney under
708fca7a5SJohn-Mark Gurney# the sponsorship from the FreeBSD Foundation.
808fca7a5SJohn-Mark Gurney# Redistribution and use in source and binary forms, with or without
908fca7a5SJohn-Mark Gurney# modification, are permitted provided that the following conditions
1008fca7a5SJohn-Mark Gurney# are met:
1108fca7a5SJohn-Mark Gurney# 1.  Redistributions of source code must retain the above copyright
1208fca7a5SJohn-Mark Gurney#     notice, this list of conditions and the following disclaimer.
1308fca7a5SJohn-Mark Gurney# 2.  Redistributions in binary form must reproduce the above copyright
1408fca7a5SJohn-Mark Gurney#     notice, this list of conditions and the following disclaimer in the
1508fca7a5SJohn-Mark Gurney#     documentation and/or other materials provided with the distribution.
1608fca7a5SJohn-Mark Gurney#
1708fca7a5SJohn-Mark Gurney# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1808fca7a5SJohn-Mark Gurney# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1908fca7a5SJohn-Mark Gurney# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2008fca7a5SJohn-Mark Gurney# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2108fca7a5SJohn-Mark Gurney# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2208fca7a5SJohn-Mark Gurney# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2308fca7a5SJohn-Mark Gurney# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2408fca7a5SJohn-Mark Gurney# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2508fca7a5SJohn-Mark Gurney# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2608fca7a5SJohn-Mark Gurney# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2708fca7a5SJohn-Mark Gurney# SUCH DAMAGE.
2808fca7a5SJohn-Mark Gurney#
2908fca7a5SJohn-Mark Gurney# $FreeBSD$
3008fca7a5SJohn-Mark Gurney#
3108fca7a5SJohn-Mark Gurney
32d86680b0SEnji Cooperfrom __future__ import print_function
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
52844d9543SConrad Meyeraesmodules = [ 'cryptosoft0', 'aesni0', 'ccr0', 'ccp0' ]
5308fca7a5SJohn-Mark Gurneydesmodules = [ 'cryptosoft0', ]
54844d9543SConrad Meyershamodules = [ 'cryptosoft0', 'aesni0', 'ccr0', 'ccp0' ]
5508fca7a5SJohn-Mark Gurney
5608fca7a5SJohn-Mark Gurneydef GenTestCase(cname):
5708fca7a5SJohn-Mark Gurney    try:
5808fca7a5SJohn-Mark Gurney        crid = cryptodev.Crypto.findcrid(cname)
5908fca7a5SJohn-Mark Gurney    except IOError:
6008fca7a5SJohn-Mark Gurney        return None
6108fca7a5SJohn-Mark Gurney
6208fca7a5SJohn-Mark Gurney    class GendCryptoTestCase(unittest.TestCase):
6308fca7a5SJohn-Mark Gurney        ###############
6408fca7a5SJohn-Mark Gurney        ##### AES #####
6508fca7a5SJohn-Mark Gurney        ###############
66c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-XTS on %s' % (cname))
6708fca7a5SJohn-Mark Gurney        def test_xts(self):
6808fca7a5SJohn-Mark Gurney            for i in katg('XTSTestVectors/format tweak value input - data unit seq no', '*.rsp'):
6908fca7a5SJohn-Mark Gurney                self.runXTS(i, cryptodev.CRYPTO_AES_XTS)
7008fca7a5SJohn-Mark Gurney
71c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-CBC on %s' % (cname))
7208fca7a5SJohn-Mark Gurney        def test_cbc(self):
7308fca7a5SJohn-Mark Gurney            for i in katg('KAT_AES', 'CBC[GKV]*.rsp'):
7408fca7a5SJohn-Mark Gurney                self.runCBC(i)
7508fca7a5SJohn-Mark Gurney
76151f0ca8SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-CCM on %s' % (cname))
77151f0ca8SJohn Baldwin        def test_ccm(self):
78151f0ca8SJohn Baldwin            for i in katg('ccmtestvectors', 'V*.rsp'):
79151f0ca8SJohn Baldwin                self.runCCMEncrypt(i)
80151f0ca8SJohn Baldwin
81151f0ca8SJohn Baldwin            for i in katg('ccmtestvectors', 'D*.rsp'):
82151f0ca8SJohn Baldwin                self.runCCMDecrypt(i)
83151f0ca8SJohn Baldwin
84c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in aesmodules, 'skipping AES-GCM on %s' % (cname))
8508fca7a5SJohn-Mark Gurney        def test_gcm(self):
8608fca7a5SJohn-Mark Gurney            for i in katg('gcmtestvectors', 'gcmEncrypt*'):
8708fca7a5SJohn-Mark Gurney                self.runGCM(i, 'ENCRYPT')
8808fca7a5SJohn-Mark Gurney
8908fca7a5SJohn-Mark Gurney            for i in katg('gcmtestvectors', 'gcmDecrypt*'):
9008fca7a5SJohn-Mark Gurney                self.runGCM(i, 'DECRYPT')
9108fca7a5SJohn-Mark Gurney
9208fca7a5SJohn-Mark Gurney        _gmacsizes = { 32: cryptodev.CRYPTO_AES_256_NIST_GMAC,
9308fca7a5SJohn-Mark Gurney            24: cryptodev.CRYPTO_AES_192_NIST_GMAC,
9408fca7a5SJohn-Mark Gurney            16: cryptodev.CRYPTO_AES_128_NIST_GMAC,
9508fca7a5SJohn-Mark Gurney        }
9608fca7a5SJohn-Mark Gurney        def runGCM(self, fname, mode):
9708fca7a5SJohn-Mark Gurney            curfun = None
9808fca7a5SJohn-Mark Gurney            if mode == 'ENCRYPT':
9908fca7a5SJohn-Mark Gurney                swapptct = False
10008fca7a5SJohn-Mark Gurney                curfun = Crypto.encrypt
10108fca7a5SJohn-Mark Gurney            elif mode == 'DECRYPT':
10208fca7a5SJohn-Mark Gurney                swapptct = True
10308fca7a5SJohn-Mark Gurney                curfun = Crypto.decrypt
10408fca7a5SJohn-Mark Gurney            else:
105d86680b0SEnji Cooper                raise RuntimeError('unknown mode: %r' % repr(mode))
10608fca7a5SJohn-Mark Gurney
107*a60d9a98SEnji Cooper            columns = [ 'Count', 'Key', 'IV', 'CT', 'AAD', 'Tag', 'PT', ]
108*a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
109*a60d9a98SEnji Cooper                self.runGCMWithParser(parser, mode)
110*a60d9a98SEnji Cooper
111*a60d9a98SEnji Cooper        def runGCMWithParser(self, parser, mode):
112*a60d9a98SEnji Cooper            for _, lines in next(parser):
11308fca7a5SJohn-Mark Gurney                for data in lines:
11408fca7a5SJohn-Mark Gurney                    curcnt = int(data['Count'])
115d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(data['Key'])
116d99c2cecSEnji Cooper                    iv = binascii.unhexlify(data['IV'])
117d99c2cecSEnji Cooper                    aad = binascii.unhexlify(data['AAD'])
118d99c2cecSEnji Cooper                    tag = binascii.unhexlify(data['Tag'])
11908fca7a5SJohn-Mark Gurney                    if 'FAIL' not in data:
120d99c2cecSEnji Cooper                        pt = binascii.unhexlify(data['PT'])
121d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CT'])
12208fca7a5SJohn-Mark Gurney
12308fca7a5SJohn-Mark Gurney                    if len(iv) != 12:
12408fca7a5SJohn-Mark Gurney                        # XXX - isn't supported
12508fca7a5SJohn-Mark Gurney                        continue
12608fca7a5SJohn-Mark Gurney
127844d9543SConrad Meyer                    try:
12808fca7a5SJohn-Mark Gurney                        c = Crypto(cryptodev.CRYPTO_AES_NIST_GCM_16,
12908fca7a5SJohn-Mark Gurney                            cipherkey,
13008fca7a5SJohn-Mark Gurney                            mac=self._gmacsizes[len(cipherkey)],
131de0f7dcaSJohn Baldwin                            mackey=cipherkey, crid=crid,
132de0f7dcaSJohn Baldwin                            maclen=16)
133b106e0fcSEnji Cooper                    except EnvironmentError as e:
134844d9543SConrad Meyer                        # Can't test algorithms the driver does not support.
135844d9543SConrad Meyer                        if e.errno != errno.EOPNOTSUPP:
136844d9543SConrad Meyer                            raise
137844d9543SConrad Meyer                        continue
13808fca7a5SJohn-Mark Gurney
13908fca7a5SJohn-Mark Gurney                    if mode == 'ENCRYPT':
140844d9543SConrad Meyer                        try:
14108fca7a5SJohn-Mark Gurney                            rct, rtag = c.encrypt(pt, iv, aad)
142b106e0fcSEnji Cooper                        except EnvironmentError as e:
143844d9543SConrad Meyer                            # Can't test inputs the driver does not support.
144844d9543SConrad Meyer                            if e.errno != errno.EINVAL:
145844d9543SConrad Meyer                                raise
146844d9543SConrad Meyer                            continue
14708fca7a5SJohn-Mark Gurney                        rtag = rtag[:len(tag)]
148d99c2cecSEnji Cooper                        data['rct'] = binascii.hexlify(rct)
149d99c2cecSEnji Cooper                        data['rtag'] = binascii.hexlify(rtag)
150d86680b0SEnji Cooper                        self.assertEqual(rct, ct, repr(data))
151d86680b0SEnji Cooper                        self.assertEqual(rtag, tag, repr(data))
15208fca7a5SJohn-Mark Gurney                    else:
15308fca7a5SJohn-Mark Gurney                        if len(tag) != 16:
15408fca7a5SJohn-Mark Gurney                            continue
15508fca7a5SJohn-Mark Gurney                        args = (ct, iv, aad, tag)
15608fca7a5SJohn-Mark Gurney                        if 'FAIL' in data:
15708fca7a5SJohn-Mark Gurney                            self.assertRaises(IOError,
15808fca7a5SJohn-Mark Gurney                                c.decrypt, *args)
15908fca7a5SJohn-Mark Gurney                        else:
160844d9543SConrad Meyer                            try:
16108fca7a5SJohn-Mark Gurney                                rpt, rtag = c.decrypt(*args)
162b106e0fcSEnji Cooper                            except EnvironmentError as e:
163844d9543SConrad Meyer                                # Can't test inputs the driver does not support.
164844d9543SConrad Meyer                                if e.errno != errno.EINVAL:
165844d9543SConrad Meyer                                    raise
166844d9543SConrad Meyer                                continue
167d99c2cecSEnji Cooper                            data['rpt'] = binascii.hexlify(rpt)
168d99c2cecSEnji Cooper                            data['rtag'] = binascii.hexlify(rtag)
16908fca7a5SJohn-Mark Gurney                            self.assertEqual(rpt, pt,
170d86680b0SEnji Cooper                                repr(data))
17108fca7a5SJohn-Mark Gurney
17208fca7a5SJohn-Mark Gurney        def runCBC(self, fname):
173*a60d9a98SEnji Cooper            columns = [ 'COUNT', 'KEY', 'IV', 'PLAINTEXT', 'CIPHERTEXT', ]
174*a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
175*a60d9a98SEnji Cooper                self.runCBCWithParser(parser)
176*a60d9a98SEnji Cooper
177*a60d9a98SEnji Cooper        def runCBCWithParser(self, parser):
17808fca7a5SJohn-Mark Gurney            curfun = None
179*a60d9a98SEnji Cooper            for mode, lines in next(parser):
18008fca7a5SJohn-Mark Gurney                if mode == 'ENCRYPT':
18108fca7a5SJohn-Mark Gurney                    swapptct = False
18208fca7a5SJohn-Mark Gurney                    curfun = Crypto.encrypt
18308fca7a5SJohn-Mark Gurney                elif mode == 'DECRYPT':
18408fca7a5SJohn-Mark Gurney                    swapptct = True
18508fca7a5SJohn-Mark Gurney                    curfun = Crypto.decrypt
18608fca7a5SJohn-Mark Gurney                else:
187d86680b0SEnji Cooper                    raise RuntimeError('unknown mode: %r' % repr(mode))
18808fca7a5SJohn-Mark Gurney
18908fca7a5SJohn-Mark Gurney                for data in lines:
19008fca7a5SJohn-Mark Gurney                    curcnt = int(data['COUNT'])
191d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(data['KEY'])
192d99c2cecSEnji Cooper                    iv = binascii.unhexlify(data['IV'])
193d99c2cecSEnji Cooper                    pt = binascii.unhexlify(data['PLAINTEXT'])
194d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CIPHERTEXT'])
19508fca7a5SJohn-Mark Gurney
19608fca7a5SJohn-Mark Gurney                    if swapptct:
19708fca7a5SJohn-Mark Gurney                        pt, ct = ct, pt
19808fca7a5SJohn-Mark Gurney                    # run the fun
19908fca7a5SJohn-Mark Gurney                    c = Crypto(cryptodev.CRYPTO_AES_CBC, cipherkey, crid=crid)
20008fca7a5SJohn-Mark Gurney                    r = curfun(c, pt, iv)
20108fca7a5SJohn-Mark Gurney                    self.assertEqual(r, ct)
20208fca7a5SJohn-Mark Gurney
20308fca7a5SJohn-Mark Gurney        def runXTS(self, fname, meth):
204*a60d9a98SEnji Cooper            columns = [ 'COUNT', 'DataUnitLen', 'Key', 'DataUnitSeqNumber', 'PT',
205*a60d9a98SEnji Cooper                        'CT']
206*a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
207*a60d9a98SEnji Cooper                self.runXTSWithParser(parser, meth)
208*a60d9a98SEnji Cooper
209*a60d9a98SEnji Cooper        def runXTSWithParser(self, parser, meth):
21008fca7a5SJohn-Mark Gurney            curfun = None
211*a60d9a98SEnji Cooper            for mode, lines in next(parser):
21208fca7a5SJohn-Mark Gurney                if mode == 'ENCRYPT':
21308fca7a5SJohn-Mark Gurney                    swapptct = False
21408fca7a5SJohn-Mark Gurney                    curfun = Crypto.encrypt
21508fca7a5SJohn-Mark Gurney                elif mode == 'DECRYPT':
21608fca7a5SJohn-Mark Gurney                    swapptct = True
21708fca7a5SJohn-Mark Gurney                    curfun = Crypto.decrypt
21808fca7a5SJohn-Mark Gurney                else:
219d86680b0SEnji Cooper                    raise RuntimeError('unknown mode: %r' % repr(mode))
22008fca7a5SJohn-Mark Gurney
22108fca7a5SJohn-Mark Gurney                for data in lines:
22208fca7a5SJohn-Mark Gurney                    curcnt = int(data['COUNT'])
22308fca7a5SJohn-Mark Gurney                    nbits = int(data['DataUnitLen'])
224d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(data['Key'])
22508fca7a5SJohn-Mark Gurney                    iv = struct.pack('QQ', int(data['DataUnitSeqNumber']), 0)
226d99c2cecSEnji Cooper                    pt = binascii.unhexlify(data['PT'])
227d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CT'])
22808fca7a5SJohn-Mark Gurney
22908fca7a5SJohn-Mark Gurney                    if nbits % 128 != 0:
23008fca7a5SJohn-Mark Gurney                        # XXX - mark as skipped
23108fca7a5SJohn-Mark Gurney                        continue
23208fca7a5SJohn-Mark Gurney                    if swapptct:
23308fca7a5SJohn-Mark Gurney                        pt, ct = ct, pt
23408fca7a5SJohn-Mark Gurney                    # run the fun
235844d9543SConrad Meyer                    try:
23608fca7a5SJohn-Mark Gurney                        c = Crypto(meth, cipherkey, crid=crid)
23708fca7a5SJohn-Mark Gurney                        r = curfun(c, pt, iv)
238b106e0fcSEnji Cooper                    except EnvironmentError as e:
239844d9543SConrad Meyer                        # Can't test hashes the driver does not support.
240844d9543SConrad Meyer                        if e.errno != errno.EOPNOTSUPP:
241844d9543SConrad Meyer                            raise
242844d9543SConrad Meyer                        continue
24308fca7a5SJohn-Mark Gurney                    self.assertEqual(r, ct)
24408fca7a5SJohn-Mark Gurney
245151f0ca8SJohn Baldwin        def runCCMEncrypt(self, fname):
246*a60d9a98SEnji Cooper            with cryptodev.KATCCMParser(fname) as parser:
247*a60d9a98SEnji Cooper                self.runCCMEncryptWithParser(parser)
248*a60d9a98SEnji Cooper
249*a60d9a98SEnji Cooper        def runCCMEncryptWithParser(self, parser):
250*a60d9a98SEnji Cooper            for data in next(parser):
251151f0ca8SJohn Baldwin                Nlen = int(data['Nlen'])
252151f0ca8SJohn Baldwin                if Nlen != 12:
253151f0ca8SJohn Baldwin                    # OCF only supports 12 byte IVs
254151f0ca8SJohn Baldwin                    continue
255d99c2cecSEnji Cooper                key = binascii.unhexlify(data['Key'])
256d99c2cecSEnji Cooper                nonce = binascii.unhexlify(data['Nonce'])
257151f0ca8SJohn Baldwin                Alen = int(data['Alen'])
258151f0ca8SJohn Baldwin                if Alen != 0:
259d99c2cecSEnji Cooper                    aad = binascii.unhexlify(data['Adata'])
260151f0ca8SJohn Baldwin                else:
261151f0ca8SJohn Baldwin                    aad = None
262d99c2cecSEnji Cooper                payload = binascii.unhexlify(data['Payload'])
263d99c2cecSEnji Cooper                ct = binascii.unhexlify(data['CT'])
264151f0ca8SJohn Baldwin
265151f0ca8SJohn Baldwin                try:
266151f0ca8SJohn Baldwin                    c = Crypto(crid=crid,
267151f0ca8SJohn Baldwin                        cipher=cryptodev.CRYPTO_AES_CCM_16,
268151f0ca8SJohn Baldwin                        key=key,
269151f0ca8SJohn Baldwin                        mac=cryptodev.CRYPTO_AES_CCM_CBC_MAC,
270151f0ca8SJohn Baldwin                        mackey=key, maclen=16)
271151f0ca8SJohn Baldwin                    r, tag = Crypto.encrypt(c, payload,
272151f0ca8SJohn Baldwin                        nonce, aad)
273b106e0fcSEnji Cooper                except EnvironmentError as e:
274151f0ca8SJohn Baldwin                    if e.errno != errno.EOPNOTSUPP:
275151f0ca8SJohn Baldwin                        raise
276151f0ca8SJohn Baldwin                    continue
277151f0ca8SJohn Baldwin
278151f0ca8SJohn Baldwin                out = r + tag
279151f0ca8SJohn Baldwin                self.assertEqual(out, ct,
280151f0ca8SJohn Baldwin                    "Count " + data['Count'] + " Actual: " + \
281e8b4bbdfSEnji Cooper                    repr(binascii.hexlify(out)) + " Expected: " + \
282151f0ca8SJohn Baldwin                    repr(data) + " on " + cname)
283151f0ca8SJohn Baldwin
284151f0ca8SJohn Baldwin        def runCCMDecrypt(self, fname):
285*a60d9a98SEnji Cooper            with cryptodev.KATCCMParser(fname) as parser:
286*a60d9a98SEnji Cooper                self.runCCMDecryptWithParser(parser)
287*a60d9a98SEnji Cooper
288*a60d9a98SEnji Cooper        def runCCMDecryptWithParser(self, parser):
289151f0ca8SJohn Baldwin            # XXX: Note that all of the current CCM
290151f0ca8SJohn Baldwin            # decryption test vectors use IV and tag sizes
291151f0ca8SJohn Baldwin            # that aren't supported by OCF none of the
292151f0ca8SJohn Baldwin            # tests are actually ran.
293*a60d9a98SEnji Cooper            for data in next(parser):
294151f0ca8SJohn Baldwin                Nlen = int(data['Nlen'])
295151f0ca8SJohn Baldwin                if Nlen != 12:
296151f0ca8SJohn Baldwin                    # OCF only supports 12 byte IVs
297151f0ca8SJohn Baldwin                    continue
298151f0ca8SJohn Baldwin                Tlen = int(data['Tlen'])
299151f0ca8SJohn Baldwin                if Tlen != 16:
300151f0ca8SJohn Baldwin                    # OCF only supports 16 byte tags
301151f0ca8SJohn Baldwin                    continue
302d99c2cecSEnji Cooper                key = binascii.unhexlify(data['Key'])
303d99c2cecSEnji Cooper                nonce = binascii.unhexlify(data['Nonce'])
304151f0ca8SJohn Baldwin                Alen = int(data['Alen'])
305151f0ca8SJohn Baldwin                if Alen != 0:
306d99c2cecSEnji Cooper                    aad = binascii.unhexlify(data['Adata'])
307151f0ca8SJohn Baldwin                else:
308151f0ca8SJohn Baldwin                    aad = None
309d99c2cecSEnji Cooper                ct = binascii.unhexlify(data['CT'])
310151f0ca8SJohn Baldwin                tag = ct[-16:]
311151f0ca8SJohn Baldwin                ct = ct[:-16]
312151f0ca8SJohn Baldwin
313151f0ca8SJohn Baldwin                try:
314151f0ca8SJohn Baldwin                    c = Crypto(crid=crid,
315151f0ca8SJohn Baldwin                        cipher=cryptodev.CRYPTO_AES_CCM_16,
316151f0ca8SJohn Baldwin                        key=key,
317151f0ca8SJohn Baldwin                        mac=cryptodev.CRYPTO_AES_CCM_CBC_MAC,
318151f0ca8SJohn Baldwin                        mackey=key, maclen=16)
319b106e0fcSEnji Cooper                except EnvironmentError as e:
320151f0ca8SJohn Baldwin                    if e.errno != errno.EOPNOTSUPP:
321151f0ca8SJohn Baldwin                        raise
322151f0ca8SJohn Baldwin                    continue
323151f0ca8SJohn Baldwin
324151f0ca8SJohn Baldwin                if data['Result'] == 'Fail':
325151f0ca8SJohn Baldwin                    self.assertRaises(IOError,
326151f0ca8SJohn Baldwin                        c.decrypt, payload, nonce, aad, tag)
327151f0ca8SJohn Baldwin                else:
328151f0ca8SJohn Baldwin                    r = Crypto.decrypt(c, payload, nonce,
329151f0ca8SJohn Baldwin                        aad, tag)
330151f0ca8SJohn Baldwin
331d99c2cecSEnji Cooper                    payload = binascii.unhexlify(data['Payload'])
3322a96ae15SEnji Cooper                    plen = int(data('Plen'))
333151f0ca8SJohn Baldwin                    payload = payload[:plen]
334151f0ca8SJohn Baldwin                    self.assertEqual(r, payload,
335151f0ca8SJohn Baldwin                        "Count " + data['Count'] + \
336e8b4bbdfSEnji Cooper                        " Actual: " + repr(binascii.hexlify(r)) + \
337151f0ca8SJohn Baldwin                        " Expected: " + repr(data) + \
338151f0ca8SJohn Baldwin                        " on " + cname)
339151f0ca8SJohn Baldwin
34008fca7a5SJohn-Mark Gurney        ###############
34108fca7a5SJohn-Mark Gurney        ##### DES #####
34208fca7a5SJohn-Mark Gurney        ###############
343d86680b0SEnji Cooper        @unittest.skipIf(cname not in desmodules, 'skipping DES on %s' % (cname))
34408fca7a5SJohn-Mark Gurney        def test_tdes(self):
34508fca7a5SJohn-Mark Gurney            for i in katg('KAT_TDES', 'TCBC[a-z]*.rsp'):
34608fca7a5SJohn-Mark Gurney                self.runTDES(i)
34708fca7a5SJohn-Mark Gurney
34808fca7a5SJohn-Mark Gurney        def runTDES(self, fname):
349*a60d9a98SEnji Cooper            columns = [ 'COUNT', 'KEYs', 'IV', 'PLAINTEXT', 'CIPHERTEXT', ]
350*a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
351*a60d9a98SEnji Cooper                self.runTDESWithParser(parser)
352*a60d9a98SEnji Cooper
353*a60d9a98SEnji Cooper        def runTDESWithParser(self, parser):
35408fca7a5SJohn-Mark Gurney            curfun = None
355*a60d9a98SEnji Cooper            for mode, lines in next(parser):
35608fca7a5SJohn-Mark Gurney                if mode == 'ENCRYPT':
35708fca7a5SJohn-Mark Gurney                    swapptct = False
35808fca7a5SJohn-Mark Gurney                    curfun = Crypto.encrypt
35908fca7a5SJohn-Mark Gurney                elif mode == 'DECRYPT':
36008fca7a5SJohn-Mark Gurney                    swapptct = True
36108fca7a5SJohn-Mark Gurney                    curfun = Crypto.decrypt
36208fca7a5SJohn-Mark Gurney                else:
363d86680b0SEnji Cooper                    raise RuntimeError('unknown mode: %r' % repr(mode))
36408fca7a5SJohn-Mark Gurney
36508fca7a5SJohn-Mark Gurney                for data in lines:
36608fca7a5SJohn-Mark Gurney                    curcnt = int(data['COUNT'])
36708fca7a5SJohn-Mark Gurney                    key = data['KEYs'] * 3
368d99c2cecSEnji Cooper                    cipherkey = binascii.unhexlify(key)
369d99c2cecSEnji Cooper                    iv = binascii.unhexlify(data['IV'])
370d99c2cecSEnji Cooper                    pt = binascii.unhexlify(data['PLAINTEXT'])
371d99c2cecSEnji Cooper                    ct = binascii.unhexlify(data['CIPHERTEXT'])
37208fca7a5SJohn-Mark Gurney
37308fca7a5SJohn-Mark Gurney                    if swapptct:
37408fca7a5SJohn-Mark Gurney                        pt, ct = ct, pt
37508fca7a5SJohn-Mark Gurney                    # run the fun
37608fca7a5SJohn-Mark Gurney                    c = Crypto(cryptodev.CRYPTO_3DES_CBC, cipherkey, crid=crid)
37708fca7a5SJohn-Mark Gurney                    r = curfun(c, pt, iv)
37808fca7a5SJohn-Mark Gurney                    self.assertEqual(r, ct)
37908fca7a5SJohn-Mark Gurney
38008fca7a5SJohn-Mark Gurney        ###############
38108fca7a5SJohn-Mark Gurney        ##### SHA #####
38208fca7a5SJohn-Mark Gurney        ###############
383d86680b0SEnji Cooper        @unittest.skipIf(cname not in shamodules, 'skipping SHA on %s' % str(cname))
38408fca7a5SJohn-Mark Gurney        def test_sha(self):
385de0f7dcaSJohn Baldwin            for i in katg('shabytetestvectors', 'SHA*Msg.rsp'):
386de0f7dcaSJohn Baldwin                self.runSHA(i)
387de0f7dcaSJohn Baldwin
388de0f7dcaSJohn Baldwin        def runSHA(self, fname):
389de0f7dcaSJohn Baldwin            # Skip SHA512_(224|256) tests
390de0f7dcaSJohn Baldwin            if fname.find('SHA512_') != -1:
391de0f7dcaSJohn Baldwin                return
392*a60d9a98SEnji Cooper            columns = [ 'Len', 'Msg', 'MD' ]
393*a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
394*a60d9a98SEnji Cooper                self.runSHAWithParser(parser)
395de0f7dcaSJohn Baldwin
396*a60d9a98SEnji Cooper        def runSHAWithParser(self, parser):
397*a60d9a98SEnji Cooper            for hashlength, lines in next(parser):
398de0f7dcaSJohn Baldwin                # E.g., hashlength will be "L=20" (bytes)
399de0f7dcaSJohn Baldwin                hashlen = int(hashlength.split("=")[1])
400de0f7dcaSJohn Baldwin
401de0f7dcaSJohn Baldwin                if hashlen == 20:
402de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA1
403de0f7dcaSJohn Baldwin                elif hashlen == 28:
404de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_224
405de0f7dcaSJohn Baldwin                elif hashlen == 32:
406de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_256
407de0f7dcaSJohn Baldwin                elif hashlen == 48:
408de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_384
409de0f7dcaSJohn Baldwin                elif hashlen == 64:
410de0f7dcaSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_512
411de0f7dcaSJohn Baldwin                else:
412de0f7dcaSJohn Baldwin                    # Skip unsupported hashes
413de0f7dcaSJohn Baldwin                    # Slurp remaining input in section
414de0f7dcaSJohn Baldwin                    for data in lines:
415de0f7dcaSJohn Baldwin                        continue
416de0f7dcaSJohn Baldwin                    continue
417de0f7dcaSJohn Baldwin
418de0f7dcaSJohn Baldwin                for data in lines:
419d99c2cecSEnji Cooper                    msg = binascii.unhexlify(data['Msg'])
420de0f7dcaSJohn Baldwin                    msg = msg[:int(data['Len'])]
421d99c2cecSEnji Cooper                    md = binascii.unhexlify(data['MD'])
422de0f7dcaSJohn Baldwin
423de0f7dcaSJohn Baldwin                    try:
424de0f7dcaSJohn Baldwin                        c = Crypto(mac=alg, crid=crid,
425de0f7dcaSJohn Baldwin                            maclen=hashlen)
426b106e0fcSEnji Cooper                    except EnvironmentError as e:
427de0f7dcaSJohn Baldwin                        # Can't test hashes the driver does not support.
428de0f7dcaSJohn Baldwin                        if e.errno != errno.EOPNOTSUPP:
429de0f7dcaSJohn Baldwin                            raise
430de0f7dcaSJohn Baldwin                        continue
431de0f7dcaSJohn Baldwin
432de0f7dcaSJohn Baldwin                    _, r = c.encrypt(msg, iv="")
433de0f7dcaSJohn Baldwin
434de0f7dcaSJohn Baldwin                    self.assertEqual(r, md, "Actual: " + \
435e8b4bbdfSEnji Cooper                        repr(binascii.hexlify(r)) + " Expected: " + repr(data) + " on " + cname)
43608fca7a5SJohn-Mark Gurney
437c091d0d9SJohn Baldwin        @unittest.skipIf(cname not in shamodules, 'skipping SHA-HMAC on %s' % str(cname))
43808fca7a5SJohn-Mark Gurney        def test_sha1hmac(self):
43908fca7a5SJohn-Mark Gurney            for i in katg('hmactestvectors', 'HMAC.rsp'):
44008fca7a5SJohn-Mark Gurney                self.runSHA1HMAC(i)
44108fca7a5SJohn-Mark Gurney
44208fca7a5SJohn-Mark Gurney        def runSHA1HMAC(self, fname):
443*a60d9a98SEnji Cooper            columns = [ 'Count', 'Klen', 'Tlen', 'Key', 'Msg', 'Mac' ]
444*a60d9a98SEnji Cooper            with cryptodev.KATParser(fname, columns) as parser:
445*a60d9a98SEnji Cooper                self.runSHA1HMACWithParser(parser)
446*a60d9a98SEnji Cooper
447*a60d9a98SEnji Cooper        def runSHA1HMACWithParser(self, parser):
448*a60d9a98SEnji Cooper            for hashlength, lines in next(parser):
449005fdbbcSConrad Meyer                # E.g., hashlength will be "L=20" (bytes)
450005fdbbcSConrad Meyer                hashlen = int(hashlength.split("=")[1])
451005fdbbcSConrad Meyer
452005fdbbcSConrad Meyer                blocksize = None
453005fdbbcSConrad Meyer                if hashlen == 20:
454005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA1_HMAC
455005fdbbcSConrad Meyer                    blocksize = 64
456005fdbbcSConrad Meyer                elif hashlen == 28:
457c87ada6aSJohn Baldwin                    alg = cryptodev.CRYPTO_SHA2_224_HMAC
458c87ada6aSJohn Baldwin                    blocksize = 64
459005fdbbcSConrad Meyer                elif hashlen == 32:
460005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA2_256_HMAC
461005fdbbcSConrad Meyer                    blocksize = 64
462005fdbbcSConrad Meyer                elif hashlen == 48:
463005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA2_384_HMAC
464005fdbbcSConrad Meyer                    blocksize = 128
465005fdbbcSConrad Meyer                elif hashlen == 64:
466005fdbbcSConrad Meyer                    alg = cryptodev.CRYPTO_SHA2_512_HMAC
467005fdbbcSConrad Meyer                    blocksize = 128
468005fdbbcSConrad Meyer                else:
469005fdbbcSConrad Meyer                    # Skip unsupported hashes
470005fdbbcSConrad Meyer                    # Slurp remaining input in section
471005fdbbcSConrad Meyer                    for data in lines:
472005fdbbcSConrad Meyer                        continue
473005fdbbcSConrad Meyer                    continue
474005fdbbcSConrad Meyer
47508fca7a5SJohn-Mark Gurney                for data in lines:
476d99c2cecSEnji Cooper                    key = binascii.unhexlify(data['Key'])
477d99c2cecSEnji Cooper                    msg = binascii.unhexlify(data['Msg'])
478d99c2cecSEnji Cooper                    mac = binascii.unhexlify(data['Mac'])
479005fdbbcSConrad Meyer                    tlen = int(data['Tlen'])
48008fca7a5SJohn-Mark Gurney
481005fdbbcSConrad Meyer                    if len(key) > blocksize:
48208fca7a5SJohn-Mark Gurney                        continue
48308fca7a5SJohn-Mark Gurney
484a317fb03SConrad Meyer                    try:
485005fdbbcSConrad Meyer                        c = Crypto(mac=alg, mackey=key,
486de0f7dcaSJohn Baldwin                            crid=crid, maclen=hashlen)
487b106e0fcSEnji Cooper                    except EnvironmentError as e:
488a317fb03SConrad Meyer                        # Can't test hashes the driver does not support.
489a317fb03SConrad Meyer                        if e.errno != errno.EOPNOTSUPP:
490a317fb03SConrad Meyer                            raise
491a317fb03SConrad Meyer                        continue
49208fca7a5SJohn-Mark Gurney
493005fdbbcSConrad Meyer                    _, r = c.encrypt(msg, iv="")
494005fdbbcSConrad Meyer
495de0f7dcaSJohn Baldwin                    self.assertEqual(r[:tlen], mac, "Actual: " + \
496e8b4bbdfSEnji Cooper                        repr(binascii.hexlify(r)) + " Expected: " + repr(data))
49708fca7a5SJohn-Mark Gurney
49808fca7a5SJohn-Mark Gurney    return GendCryptoTestCase
49908fca7a5SJohn-Mark Gurney
50008fca7a5SJohn-Mark Gurneycryptosoft = GenTestCase('cryptosoft0')
50108fca7a5SJohn-Mark Gurneyaesni = GenTestCase('aesni0')
5026720b890SJohn Baldwinccr = GenTestCase('ccr0')
503844d9543SConrad Meyerccp = GenTestCase('ccp0')
50408fca7a5SJohn-Mark Gurney
50508fca7a5SJohn-Mark Gurneyif __name__ == '__main__':
50608fca7a5SJohn-Mark Gurney    unittest.main()
507