From owner-svn-src-all@freebsd.org Thu May 23 21:58:00 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D060615B7109; Thu, 23 May 2019 21:57:59 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 6F2DD8A7C4; Thu, 23 May 2019 21:57:59 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 49EA2B36E; Thu, 23 May 2019 21:57:59 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x4NLvxEn078382; Thu, 23 May 2019 21:57:59 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x4NLvwEZ078381; Thu, 23 May 2019 21:57:58 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201905232157.x4NLvwEZ078381@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Thu, 23 May 2019 21:57:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r348203 - stable/12/tests/sys/opencrypto X-SVN-Group: stable-12 X-SVN-Commit-Author: jhb X-SVN-Commit-Paths: stable/12/tests/sys/opencrypto X-SVN-Commit-Revision: 348203 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 6F2DD8A7C4 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-0.99)[-0.995,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.96)[-0.964,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 May 2019 21:58:00 -0000 Author: jhb Date: Thu May 23 21:57:58 2019 New Revision: 348203 URL: https://svnweb.freebsd.org/changeset/base/348203 Log: MFC 346617: Test the AES-CCM test vectors from the NIST Known Answer Tests. The CCM test vectors use a slightly different file format in that there are global key-value pairs as well as section key-value pairs that need to be used in each test. In addition, the sections can set multiple key-value pairs in the section name. The CCM KAT parser class is an iterator that returns a dictionary once per test where the dictionary contains all of the relevant key-value pairs for a given test (global, section name, section, test-specific). Note that all of the CCM decrypt tests use nonce and tag lengths that are not supported by OCF (OCF only supports a 12 byte nonce and 16 byte tag), so none of the decryption vectors are actually tested. Modified: stable/12/tests/sys/opencrypto/cryptodev.py stable/12/tests/sys/opencrypto/cryptotest.py Directory Properties: stable/12/ (props changed) Modified: stable/12/tests/sys/opencrypto/cryptodev.py ============================================================================== --- stable/12/tests/sys/opencrypto/cryptodev.py Thu May 23 21:52:24 2019 (r348202) +++ stable/12/tests/sys/opencrypto/cryptodev.py Thu May 23 21:57:58 2019 (r348203) @@ -381,6 +381,112 @@ class KATParser: yield values +# The CCM files use a bit of a different syntax that doesn't quite fit +# the generic KATParser. In particular, some keys are set globally at +# the start of the file, and some are set globally at the start of a +# section. +class KATCCMParser: + def __init__(self, fname): + self.fp = open(fname) + self._pending = None + self.read_globals() + + def read_globals(self): + self.global_values = {} + while True: + line = self.fp.readline() + if not line: + return + if line[0] == '#' or not line.strip(): + continue + if line[0] == '[': + self._pending = line + return + + try: + f, v = line.split(' =') + except: + print('line:', repr(line)) + raise + + v = v.strip() + + if f in self.global_values: + raise ValueError('already present: %r' % repr(f)) + self.global_values[f] = v + + def read_section_values(self, kwpairs): + self.section_values = self.global_values.copy() + for pair in kwpairs.split(', '): + f, v = pair.split(' = ') + if f in self.section_values: + raise ValueError('already present: %r' % repr(f)) + self.section_values[f] = v + + while True: + line = self.fp.readline() + if not line: + return + if line[0] == '#' or not line.strip(): + continue + if line[0] == '[': + self._pending = line + return + + try: + f, v = line.split(' =') + except: + print('line:', repr(line)) + raise + + if f == 'Count': + self._pending = line + return + + v = v.strip() + + if f in self.section_values: + raise ValueError('already present: %r' % repr(f)) + self.section_values[f] = v + + def __iter__(self): + while True: + if self._pending: + line = self._pending + self._pending = None + else: + line = self.fp.readline() + if not line: + return + + if (line and line[0] == '#') or not line.strip(): + continue + + if line[0] == '[': + section = line[1:].split(']', 1)[0] + self.read_section_values(section) + continue + + values = self.section_values.copy() + + while True: + try: + f, v = line.split(' =') + except: + print('line:', repr(line)) + raise + v = v.strip() + + if f in values: + raise ValueError('already present: %r' % repr(f)) + values[f] = v + line = self.fp.readline().strip() + if not line: + break + + yield values + + def _spdechex(s): return ''.join(s.split()).decode('hex') Modified: stable/12/tests/sys/opencrypto/cryptotest.py ============================================================================== --- stable/12/tests/sys/opencrypto/cryptotest.py Thu May 23 21:52:24 2019 (r348202) +++ stable/12/tests/sys/opencrypto/cryptotest.py Thu May 23 21:57:58 2019 (r348203) @@ -71,6 +71,14 @@ def GenTestCase(cname): for i in katg('KAT_AES', 'CBC[GKV]*.rsp'): self.runCBC(i) + @unittest.skipIf(cname not in aesmodules, 'skipping AES-CCM on %s' % (cname)) + def test_ccm(self): + for i in katg('ccmtestvectors', 'V*.rsp'): + self.runCCMEncrypt(i) + + for i in katg('ccmtestvectors', 'D*.rsp'): + self.runCCMDecrypt(i) + @unittest.skipIf(cname not in aesmodules, 'skipping AES-GCM on %s' % (cname)) def test_gcm(self): for i in katg('gcmtestvectors', 'gcmEncrypt*'): @@ -219,6 +227,93 @@ def GenTestCase(cname): raise continue self.assertEqual(r, ct) + + def runCCMEncrypt(self, fname): + for data in cryptodev.KATCCMParser(fname): + Nlen = int(data['Nlen']) + if Nlen != 12: + # OCF only supports 12 byte IVs + continue + key = data['Key'].decode('hex') + nonce = data['Nonce'].decode('hex') + Alen = int(data['Alen']) + if Alen != 0: + aad = data['Adata'].decode('hex') + else: + aad = None + payload = data['Payload'].decode('hex') + ct = data['CT'].decode('hex') + + try: + c = Crypto(crid=crid, + cipher=cryptodev.CRYPTO_AES_CCM_16, + key=key, + mac=cryptodev.CRYPTO_AES_CCM_CBC_MAC, + mackey=key, maclen=16) + r, tag = Crypto.encrypt(c, payload, + nonce, aad) + except EnvironmentError, e: + if e.errno != errno.EOPNOTSUPP: + raise + continue + + out = r + tag + self.assertEqual(out, ct, + "Count " + data['Count'] + " Actual: " + \ + repr(out.encode("hex")) + " Expected: " + \ + repr(data) + " on " + cname) + + def runCCMDecrypt(self, fname): + # XXX: Note that all of the current CCM + # decryption test vectors use IV and tag sizes + # that aren't supported by OCF none of the + # tests are actually ran. + for data in cryptodev.KATCCMParser(fname): + Nlen = int(data['Nlen']) + if Nlen != 12: + # OCF only supports 12 byte IVs + continue + Tlen = int(data['Tlen']) + if Tlen != 16: + # OCF only supports 16 byte tags + continue + key = data['Key'].decode('hex') + nonce = data['Nonce'].decode('hex') + Alen = int(data['Alen']) + if Alen != 0: + aad = data['Adata'].decode('hex') + else: + aad = None + ct = data['CT'].decode('hex') + tag = ct[-16:] + ct = ct[:-16] + + try: + c = Crypto(crid=crid, + cipher=cryptodev.CRYPTO_AES_CCM_16, + key=key, + mac=cryptodev.CRYPTO_AES_CCM_CBC_MAC, + mackey=key, maclen=16) + except EnvironmentError, e: + if e.errno != errno.EOPNOTSUPP: + raise + continue + + if data['Result'] == 'Fail': + self.assertRaises(IOError, + c.decrypt, payload, nonce, aad, tag) + else: + r = Crypto.decrypt(c, payload, nonce, + aad, tag) + + payload = data['Payload'].decode('hex') + Plen = int(data('Plen')) + payload = payload[:plen] + self.assertEqual(r, payload, + "Count " + data['Count'] + \ + " Actual: " + repr(r.encode("hex")) + \ + " Expected: " + repr(data) + \ + " on " + cname) ############### ##### DES #####