]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/opencrypto/cryptotest.py
MFV r315791: ntp 4.2.8p10.
[FreeBSD/FreeBSD.git] / tests / sys / opencrypto / cryptotest.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2014 The FreeBSD Foundation
4 # All rights reserved.
5 #
6 # This software was developed by John-Mark Gurney under
7 # the sponsorship from the FreeBSD Foundation.
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 # 1.  Redistributions of source code must retain the above copyright
12 #     notice, this list of conditions and the following disclaimer.
13 # 2.  Redistributions in binary form must reproduce the above copyright
14 #     notice, this list of conditions and the following disclaimer in the
15 #     documentation and/or other materials provided with the distribution.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 # SUCH DAMAGE.
28 #
29 # $FreeBSD$
30 #
31
32 import cryptodev
33 import itertools
34 import os
35 import struct
36 import unittest
37 from cryptodev import *
38 from glob import iglob
39
40 katdir = '/usr/local/share/nist-kat'
41
42 def katg(base, glob):
43         return iglob(os.path.join(katdir, base, glob))
44
45 aesmodules = [ 'cryptosoft0', 'aesni0', ]
46 desmodules = [ 'cryptosoft0', ]
47 shamodules = [ 'cryptosoft0', ]
48
49 def GenTestCase(cname):
50         try:
51                 crid = cryptodev.Crypto.findcrid(cname)
52         except IOError:
53                 return None
54
55         class GendCryptoTestCase(unittest.TestCase):
56                 ###############
57                 ##### AES #####
58                 ###############
59                 @unittest.skipIf(cname not in aesmodules, 'skipping AES on %s' % `cname`)
60                 def test_xts(self):
61                         for i in katg('XTSTestVectors/format tweak value input - data unit seq no', '*.rsp'):
62                                 self.runXTS(i, cryptodev.CRYPTO_AES_XTS)
63
64                 def test_cbc(self):
65                         for i in katg('KAT_AES', 'CBC[GKV]*.rsp'):
66                                 self.runCBC(i)
67
68                 def test_gcm(self):
69                         for i in katg('gcmtestvectors', 'gcmEncrypt*'):
70                                 self.runGCM(i, 'ENCRYPT')
71
72                         for i in katg('gcmtestvectors', 'gcmDecrypt*'):
73                                 self.runGCM(i, 'DECRYPT')
74
75                 _gmacsizes = { 32: cryptodev.CRYPTO_AES_256_NIST_GMAC,
76                         24: cryptodev.CRYPTO_AES_192_NIST_GMAC,
77                         16: cryptodev.CRYPTO_AES_128_NIST_GMAC,
78                 }
79                 def runGCM(self, fname, mode):
80                         curfun = None
81                         if mode == 'ENCRYPT':
82                                 swapptct = False
83                                 curfun = Crypto.encrypt
84                         elif mode == 'DECRYPT':
85                                 swapptct = True
86                                 curfun = Crypto.decrypt
87                         else:
88                                 raise RuntimeError('unknown mode: %s' % `mode`)
89
90                         for bogusmode, lines in cryptodev.KATParser(fname,
91                             [ 'Count', 'Key', 'IV', 'CT', 'AAD', 'Tag', 'PT', ]):
92                                 for data in lines:
93                                         curcnt = int(data['Count'])
94                                         cipherkey = data['Key'].decode('hex')
95                                         iv = data['IV'].decode('hex')
96                                         aad = data['AAD'].decode('hex')
97                                         tag = data['Tag'].decode('hex')
98                                         if 'FAIL' not in data:
99                                                 pt = data['PT'].decode('hex')
100                                         ct = data['CT'].decode('hex')
101
102                                         if len(iv) != 12:
103                                                 # XXX - isn't supported
104                                                 continue
105
106                                         c = Crypto(cryptodev.CRYPTO_AES_NIST_GCM_16,
107                                             cipherkey,
108                                             mac=self._gmacsizes[len(cipherkey)],
109                                             mackey=cipherkey, crid=crid)
110
111                                         if mode == 'ENCRYPT':
112                                                 rct, rtag = c.encrypt(pt, iv, aad)
113                                                 rtag = rtag[:len(tag)]
114                                                 data['rct'] = rct.encode('hex')
115                                                 data['rtag'] = rtag.encode('hex')
116                                                 self.assertEqual(rct, ct, `data`)
117                                                 self.assertEqual(rtag, tag, `data`)
118                                         else:
119                                                 if len(tag) != 16:
120                                                         continue
121                                                 args = (ct, iv, aad, tag)
122                                                 if 'FAIL' in data:
123                                                         self.assertRaises(IOError,
124                                                                 c.decrypt, *args)
125                                                 else:
126                                                         rpt, rtag = c.decrypt(*args)
127                                                         data['rpt'] = rpt.encode('hex')
128                                                         data['rtag'] = rtag.encode('hex')
129                                                         self.assertEqual(rpt, pt,
130                                                             `data`)
131
132                 def runCBC(self, fname):
133                         curfun = None
134                         for mode, lines in cryptodev.KATParser(fname,
135                             [ 'COUNT', 'KEY', 'IV', 'PLAINTEXT', 'CIPHERTEXT', ]):
136                                 if mode == 'ENCRYPT':
137                                         swapptct = False
138                                         curfun = Crypto.encrypt
139                                 elif mode == 'DECRYPT':
140                                         swapptct = True
141                                         curfun = Crypto.decrypt
142                                 else:
143                                         raise RuntimeError('unknown mode: %s' % `mode`)
144
145                                 for data in lines:
146                                         curcnt = int(data['COUNT'])
147                                         cipherkey = data['KEY'].decode('hex')
148                                         iv = data['IV'].decode('hex')
149                                         pt = data['PLAINTEXT'].decode('hex')
150                                         ct = data['CIPHERTEXT'].decode('hex')
151
152                                         if swapptct:
153                                                 pt, ct = ct, pt
154                                         # run the fun
155                                         c = Crypto(cryptodev.CRYPTO_AES_CBC, cipherkey, crid=crid)
156                                         r = curfun(c, pt, iv)
157                                         self.assertEqual(r, ct)
158
159                 def runXTS(self, fname, meth):
160                         curfun = None
161                         for mode, lines in cryptodev.KATParser(fname,
162                             [ 'COUNT', 'DataUnitLen', 'Key', 'DataUnitSeqNumber', 'PT',
163                             'CT' ]):
164                                 if mode == 'ENCRYPT':
165                                         swapptct = False
166                                         curfun = Crypto.encrypt
167                                 elif mode == 'DECRYPT':
168                                         swapptct = True
169                                         curfun = Crypto.decrypt
170                                 else:
171                                         raise RuntimeError('unknown mode: %s' % `mode`)
172
173                                 for data in lines:
174                                         curcnt = int(data['COUNT'])
175                                         nbits = int(data['DataUnitLen'])
176                                         cipherkey = data['Key'].decode('hex')
177                                         iv = struct.pack('QQ', int(data['DataUnitSeqNumber']), 0)
178                                         pt = data['PT'].decode('hex')
179                                         ct = data['CT'].decode('hex')
180
181                                         if nbits % 128 != 0:
182                                                 # XXX - mark as skipped
183                                                 continue
184                                         if swapptct:
185                                                 pt, ct = ct, pt
186                                         # run the fun
187                                         c = Crypto(meth, cipherkey, crid=crid)
188                                         r = curfun(c, pt, iv)
189                                         self.assertEqual(r, ct)
190
191                 ###############
192                 ##### DES #####
193                 ###############
194                 @unittest.skipIf(cname not in desmodules, 'skipping DES on %s' % `cname`)
195                 def test_tdes(self):
196                         for i in katg('KAT_TDES', 'TCBC[a-z]*.rsp'):
197                                 self.runTDES(i)
198
199                 def runTDES(self, fname):
200                         curfun = None
201                         for mode, lines in cryptodev.KATParser(fname,
202                             [ 'COUNT', 'KEYs', 'IV', 'PLAINTEXT', 'CIPHERTEXT', ]):
203                                 if mode == 'ENCRYPT':
204                                         swapptct = False
205                                         curfun = Crypto.encrypt
206                                 elif mode == 'DECRYPT':
207                                         swapptct = True
208                                         curfun = Crypto.decrypt
209                                 else:
210                                         raise RuntimeError('unknown mode: %s' % `mode`)
211
212                                 for data in lines:
213                                         curcnt = int(data['COUNT'])
214                                         key = data['KEYs'] * 3
215                                         cipherkey = key.decode('hex')
216                                         iv = data['IV'].decode('hex')
217                                         pt = data['PLAINTEXT'].decode('hex')
218                                         ct = data['CIPHERTEXT'].decode('hex')
219
220                                         if swapptct:
221                                                 pt, ct = ct, pt
222                                         # run the fun
223                                         c = Crypto(cryptodev.CRYPTO_3DES_CBC, cipherkey, crid=crid)
224                                         r = curfun(c, pt, iv)
225                                         self.assertEqual(r, ct)
226
227                 ###############
228                 ##### SHA #####
229                 ###############
230                 @unittest.skipIf(cname not in shamodules, 'skipping SHA on %s' % `cname`)
231                 def test_sha(self):
232                         # SHA not available in software
233                         pass
234                         #for i in iglob('SHA1*'):
235                         #       self.runSHA(i)
236
237                 def test_sha1hmac(self):
238                         for i in katg('hmactestvectors', 'HMAC.rsp'):
239                                 self.runSHA1HMAC(i)
240
241                 def runSHA1HMAC(self, fname):
242                         for bogusmode, lines in cryptodev.KATParser(fname,
243                             [ 'Count', 'Klen', 'Tlen', 'Key', 'Msg', 'Mac' ]):
244                                 for data in lines:
245                                         key = data['Key'].decode('hex')
246                                         msg = data['Msg'].decode('hex')
247                                         mac = data['Mac'].decode('hex')
248
249                                         if len(key) != 20:
250                                                 # XXX - implementation bug
251                                                 continue
252
253                                         c = Crypto(mac=cryptodev.CRYPTO_SHA1_HMAC,
254                                             mackey=key, crid=crid)
255
256                                         r = c.encrypt(msg)
257                                         self.assertEqual(r, mac, `data`)
258
259         return GendCryptoTestCase
260
261 cryptosoft = GenTestCase('cryptosoft0')
262 aesni = GenTestCase('aesni0')
263
264 if __name__ == '__main__':
265         unittest.main()