svn commit: r366073 - stable/12/tests/sys/opencrypto

Li-Wen Hsu lwhsu at FreeBSD.org
Wed Sep 23 12:11:15 UTC 2020


Author: lwhsu
Date: Wed Sep 23 12:11:14 2020
New Revision: 366073
URL: https://svnweb.freebsd.org/changeset/base/366073

Log:
  MFC r347996, r348024, r348031, r348042 (by ngie)
  
  r347996:
  Replace uses of `foo.(de|en)code('hex')` with `binascii.(un)?hexlify(foo)`
  
  Python 3 no longer doesn't support encoding/decoding hexadecimal numbers using
  the `str.format` method. The backwards compatible new method (using the
  binascii module/methods) is a comparable means of converting to/from
  hexadecimal format.
  
  In short, the functional change is the following:
  * `foo.decode('hex')` -> `binascii.unhexlify(foo)`
  * `foo.encode('hex')` -> `binascii.hexlify(foo)`
  
  While here, move the dpkt import in `cryptodev.py` down per PEP8, so it comes
  after the standard library provided imports.
  
  PR:		237403
  
  r348024:
  Followup to r347996
  
  Replace uses of `foo.encode("hex")` with `binascii.hexlify(foo)` for forwards
  compatibility between python 2.x and python 3.
  
  PR:		237403
  
  r348031:
  Squash deprecation warning related to array.array(..).tostring()
  
  In version 3.2+, `array.array(..).tostring()` was renamed to
  `array.array(..).tobytes()`. Conditionally call `array.array(..).tobytes()` if
  the python version is 3.2+.
  
  PR:		237403
  
  r348042:
  Fix encoding issues with python 3
  
  In python 3, the default encoding was switched from ascii character sets to
  unicode character sets in order to support internationalization by default.
  Some interfaces, like ioctls and packets, however, specify data in terms of
  non-unicode encodings formats, either in host endian (`fcntl.ioctl`) or
  network endian (`dpkt`) byte order/format.
  
  This change alters assumptions made by previous code where it was all
  data objects were assumed to be basestrings, when they should have been
  treated as byte arrays. In order to achieve this the following are done:
  * str objects with encodings needing to be encoded as ascii byte arrays are
    done so via `.encode("ascii")`. In order for this to work on python 3 in a
    type agnostic way (as it anecdotally varied depending on the caller), call
    `.encode("ascii")` only on str objects with python 3 to cast them to ascii
    byte arrays in a helper function name `str_to_ascii(..)`.
  * `dpkt.Packet` objects needing to be passed in to `fcntl.ioctl(..)` are done
    so by casting them to byte arrays via `bytes()`, which calls
    `dpkt.Packet__str__` under the covers and does the necessary str to byte array
    conversion needed for the `dpkt` APIs and `struct` module.
  
  In order to accomodate this change, apply the necessary typecasting for the
  byte array literal in order to search `fop.name` for nul bytes.
  
  This resolves all remaining python 2.x and python 3.x compatibility issues on
  amd64. More work needs to be done for the tests to function with i386, in
  general (this is a legacy issue).
  
  PR:		237403
  Tested with:	python 2.7.16 (amd64), python 3.6.8 (amd64)

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	Wed Sep 23 11:02:23 2020	(r366072)
+++ stable/12/tests/sys/opencrypto/cryptodev.py	Wed Sep 23 12:11:14 2020	(r366073)
@@ -32,13 +32,16 @@
 
 
 import array
-import dpkt
+import binascii
 from fcntl import ioctl
 import os
 import platform
 import signal
 from struct import pack as _pack
+import sys
 
+import dpkt
+
 from cryptodevh import *
 
 __all__ = [ 'Crypto', 'MismatchError', ]
@@ -131,22 +134,33 @@ def _getdev():
 
 _cryptodev = _getdev()
 
+def str_to_ascii(val):
+	if sys.version_info[0] >= 3:
+		if isinstance(val, str):
+			return val.encode("ascii")
+	return val;
+
 def _findop(crid, name):
 	fop = FindOp()
 	fop.crid = crid
-	fop.name = name
+	fop.name = str_to_ascii(name)
 	s = array.array('B', fop.pack_hdr())
 	ioctl(_cryptodev, CIOCFINDDEV, s, 1)
 	fop.unpack(s)
 
 	try:
-		idx = fop.name.index('\x00')
+		idx = fop.name.index(b'\x00')
 		name = fop.name[:idx]
 	except ValueError:
 		name = fop.name
 
 	return fop.crid, name
 
+def array_tobytes(array_obj):
+	if sys.version_info[:2] >= (3, 2):
+		return array_obj.tobytes()
+	return array_obj.tostring()
+
 class Crypto:
 	@staticmethod
 	def findcrid(name):
@@ -208,15 +222,15 @@ class Crypto:
 		if self._maclen is not None:
 			m = array.array('B', [0] * self._maclen)
 			cop.mac = m.buffer_info()[0]
-		ivbuf = array.array('B', iv)
+		ivbuf = array.array('B', str_to_ascii(iv))
 		cop.iv = ivbuf.buffer_info()[0]
 
 		#print('cop:', cop)
-		ioctl(_cryptodev, CIOCCRYPT, str(cop))
+		ioctl(_cryptodev, CIOCCRYPT, bytes(cop))
 
-		s = s.tostring()
+		s = array_tobytes(s)
 		if self._maclen is not None:
-			return s, m.tostring()
+			return s, array_tobytes(m)
 
 		return s
 
@@ -226,6 +240,7 @@ class Crypto:
 		caead.op = op
 		caead.flags = CRD_F_IV_EXPLICIT
 		caead.flags = 0
+		src = str_to_ascii(src)
 		caead.len = len(src)
 		s = array.array('B', src)
 		caead.src = caead.dst = s.buffer_info()[0]
@@ -236,6 +251,7 @@ class Crypto:
 		if self._maclen is None:
 			raise ValueError('must have a tag length')
 
+		tag = str_to_ascii(tag)
 		if tag is None:
 			tag = array.array('B', [0] * self._maclen)
 		else:
@@ -249,17 +265,18 @@ class Crypto:
 		caead.ivlen = len(iv)
 		caead.iv = ivbuf.buffer_info()[0]
 
-		ioctl(_cryptodev, CIOCCRYPTAEAD, str(caead))
+		ioctl(_cryptodev, CIOCCRYPTAEAD, bytes(caead))
 
-		s = s.tostring()
+		s = array_tobytes(s)
 
-		return s, tag.tostring()
+		return s, array_tobytes(tag)
 
 	def perftest(self, op, size, timeo=3):
 		import random
 		import time
 
 		inp = array.array('B', (random.randint(0, 255) for x in xrange(size)))
+		inp = str_to_ascii(inp)
 		out = array.array('B', inp)
 
 		# prep ioctl
@@ -286,8 +303,9 @@ class Crypto:
 
 		start = time.time()
 		reps = 0
+		cop = bytes(cop)
 		while not exit[0]:
-			ioctl(_cryptodev, CIOCCRYPT, str(cop))
+			ioctl(_cryptodev, CIOCCRYPT, cop)
 			reps += 1
 
 		end = time.time()
@@ -494,7 +512,7 @@ class KATCCMParser:
 
 
 def _spdechex(s):
-	return ''.join(s.split()).decode('hex')
+	return binascii.hexlify(''.join(s.split()))
 
 if __name__ == '__main__':
 	if True:
@@ -526,15 +544,15 @@ if __name__ == '__main__':
 		c = Crypto(CRYPTO_AES_ICM, key)
 		enc = c.encrypt(pt, iv)
 
-		print('enc:', enc.encode('hex'))
-		print(' ct:', ct.encode('hex'))
+		print('enc:', binascii.hexlify(enc))
+		print(' ct:', binascii.hexlify(ct))
 
 		assert ct == enc
 
 		dec = c.decrypt(ct, iv)
 
-		print('dec:', dec.encode('hex'))
-		print(' pt:', pt.encode('hex'))
+		print('dec:', binascii.hexlify(dec))
+		print(' pt:', binascii.hexlify(pt))
 
 		assert pt == dec
 	elif False:
@@ -547,15 +565,15 @@ if __name__ == '__main__':
 		c = Crypto(CRYPTO_AES_ICM, key)
 		enc = c.encrypt(pt, iv)
 
-		print('enc:', enc.encode('hex'))
-		print(' ct:', ct.encode('hex'))
+		print('enc:', binascii.hexlify(enc))
+		print(' ct:', binascii.hexlify(ct))
 
 		assert ct == enc
 
 		dec = c.decrypt(ct, iv)
 
-		print('dec:', dec.encode('hex'))
-		print(' pt:', pt.encode('hex'))
+		print('dec:', binascii.hexlify(dec))
+		print(' pt:', binascii.hexlify(pt))
 
 		assert pt == dec
 	elif False:
@@ -567,15 +585,15 @@ if __name__ == '__main__':
 
 		enc = c.encrypt(pt, iv)
 
-		print('enc:', enc.encode('hex'))
-		print(' ct:', ct.encode('hex'))
+		print('enc:', binascii.hexlify(enc))
+		print(' ct:', binascii.hexlify(ct))
 
 		assert ct == enc
 
 		dec = c.decrypt(ct, iv)
 
-		print('dec:', dec.encode('hex'))
-		print(' pt:', pt.encode('hex'))
+		print('dec:', binascii.hexlify(dec))
+		print(' pt:', binascii.hexlify(pt))
 
 		assert pt == dec
 	elif False:
@@ -593,26 +611,26 @@ if __name__ == '__main__':
 
 		enc, enctag = c.encrypt(pt, iv, aad=aad)
 
-		print('enc:', enc.encode('hex'))
-		print(' ct:', ct.encode('hex'))
+		print('enc:', binascii.hexlify(enc))
+		print(' ct:', binascii.hexlify(ct))
 
 		assert enc == ct
 
-		print('etg:', enctag.encode('hex'))
-		print('tag:', tag.encode('hex'))
+		print('etg:', binascii.hexlify(enctag))
+		print('tag:', binascii.hexlify(tag))
 		assert enctag == tag
 
 		# Make sure we get EBADMSG
 		#enctag = enctag[:-1] + 'a'
 		dec, dectag = c.decrypt(ct, iv, aad=aad, tag=enctag)
 
-		print('dec:', dec.encode('hex'))
-		print(' pt:', pt.encode('hex'))
+		print('dec:', binascii.hexlify(dec))
+		print(' pt:', binascii.hexlify(pt))
 
 		assert dec == pt
 
-		print('dtg:', dectag.encode('hex'))
-		print('tag:', tag.encode('hex'))
+		print('dtg:', binascii.hexlify(dectag))
+		print('tag:', binascii.hexlify(tag))
 
 		assert dectag == tag
 	elif False:
@@ -629,27 +647,27 @@ if __name__ == '__main__':
 
 		enc, enctag = c.encrypt(pt, iv, aad=aad)
 
-		print('enc:', enc.encode('hex'))
-		print(' ct:', ct.encode('hex'))
+		print('enc:', binascii.hexlify(enc))
+		print(' ct:', binascii.hexlify(ct))
 
 		assert enc == ct
 
-		print('etg:', enctag.encode('hex'))
-		print('tag:', tag.encode('hex'))
+		print('etg:', binascii.hexlify(enctag))
+		print('tag:', binascii.hexlify(tag))
 		assert enctag == tag
 	elif False:
 		for i in xrange(100000):
-			c = Crypto(CRYPTO_AES_XTS, '1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'.decode('hex'))
-			data = '52a42bca4e9425a25bbc8c8bf6129dec'.decode('hex')
-			ct = '517e602becd066b65fa4f4f56ddfe240'.decode('hex')
+			c = Crypto(CRYPTO_AES_XTS, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'))
+			data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec')
+			ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240')
 			iv = _pack('QQ', 71, 0)
 
 			enc = c.encrypt(data, iv)
 			assert enc == ct
 	elif True:
-		c = Crypto(CRYPTO_AES_XTS, '1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'.decode('hex'))
-		data = '52a42bca4e9425a25bbc8c8bf6129dec'.decode('hex')
-		ct = '517e602becd066b65fa4f4f56ddfe240'.decode('hex')
+		c = Crypto(CRYPTO_AES_XTS, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'))
+		data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec')
+		ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240')
 		iv = _pack('QQ', 71, 0)
 
 		enc = c.encrypt(data, iv)
@@ -661,7 +679,7 @@ if __name__ == '__main__':
 		#c.perftest(COP_ENCRYPT, 192*1024, reps=30000)
 
 	else:
-		key = '1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382'.decode('hex')
+		key = binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382')
 		print('XTS %d testing:' % (len(key) * 8))
 		c = Crypto(CRYPTO_AES_XTS, key)
 		for i in [ 8192, 192*1024]:

Modified: stable/12/tests/sys/opencrypto/cryptotest.py
==============================================================================
--- stable/12/tests/sys/opencrypto/cryptotest.py	Wed Sep 23 11:02:23 2020	(r366072)
+++ stable/12/tests/sys/opencrypto/cryptotest.py	Wed Sep 23 12:11:14 2020	(r366073)
@@ -108,13 +108,13 @@ def GenTestCase(cname):
 			    [ 'Count', 'Key', 'IV', 'CT', 'AAD', 'Tag', 'PT', ]):
 				for data in lines:
 					curcnt = int(data['Count'])
-					cipherkey = data['Key'].decode('hex')
-					iv = data['IV'].decode('hex')
-					aad = data['AAD'].decode('hex')
-					tag = data['Tag'].decode('hex')
+					cipherkey = binascii.unhexlify(data['Key'])
+					iv = binascii.unhexlify(data['IV'])
+					aad = binascii.unhexlify(data['AAD'])
+					tag = binascii.unhexlify(data['Tag'])
 					if 'FAIL' not in data:
-						pt = data['PT'].decode('hex')
-					ct = data['CT'].decode('hex')
+						pt = binascii.unhexlify(data['PT'])
+					ct = binascii.unhexlify(data['CT'])
 
 					if len(iv) != 12:
 						# XXX - isn't supported
@@ -141,8 +141,8 @@ def GenTestCase(cname):
 								raise
 							continue
 						rtag = rtag[:len(tag)]
-						data['rct'] = rct.encode('hex')
-						data['rtag'] = rtag.encode('hex')
+						data['rct'] = binascii.hexlify(rct)
+						data['rtag'] = binascii.hexlify(rtag)
 						self.assertEqual(rct, ct, repr(data))
 						self.assertEqual(rtag, tag, repr(data))
 					else:
@@ -160,8 +160,8 @@ def GenTestCase(cname):
 								if e.errno != errno.EINVAL:
 									raise
 								continue
-							data['rpt'] = rpt.encode('hex')
-							data['rtag'] = rtag.encode('hex')
+							data['rpt'] = binascii.hexlify(rpt)
+							data['rtag'] = binascii.hexlify(rtag)
 							self.assertEqual(rpt, pt,
 							    repr(data))
 
@@ -180,10 +180,10 @@ def GenTestCase(cname):
 
 				for data in lines:
 					curcnt = int(data['COUNT'])
-					cipherkey = data['KEY'].decode('hex')
-					iv = data['IV'].decode('hex')
-					pt = data['PLAINTEXT'].decode('hex')
-					ct = data['CIPHERTEXT'].decode('hex')
+					cipherkey = binascii.unhexlify(data['KEY'])
+					iv = binascii.unhexlify(data['IV'])
+					pt = binascii.unhexlify(data['PLAINTEXT'])
+					ct = binascii.unhexlify(data['CIPHERTEXT'])
 
 					if swapptct:
 						pt, ct = ct, pt
@@ -209,10 +209,10 @@ def GenTestCase(cname):
 				for data in lines:
 					curcnt = int(data['COUNT'])
 					nbits = int(data['DataUnitLen'])
-					cipherkey = data['Key'].decode('hex')
+					cipherkey = binascii.unhexlify(data['Key'])
 					iv = struct.pack('QQ', int(data['DataUnitSeqNumber']), 0)
-					pt = data['PT'].decode('hex')
-					ct = data['CT'].decode('hex')
+					pt = binascii.unhexlify(data['PT'])
+					ct = binascii.unhexlify(data['CT'])
 
 					if nbits % 128 != 0:
 						# XXX - mark as skipped
@@ -236,15 +236,15 @@ def GenTestCase(cname):
 				if Nlen != 12:
 					# OCF only supports 12 byte IVs
 					continue
-				key = data['Key'].decode('hex')
-				nonce = data['Nonce'].decode('hex')
+				key = binascii.unhexlify(data['Key'])
+				nonce = binascii.unhexlify(data['Nonce'])
 				Alen = int(data['Alen'])
 				if Alen != 0:
-					aad = data['Adata'].decode('hex')
+					aad = binascii.unhexlify(data['Adata'])
 				else:
 					aad = None
-				payload = data['Payload'].decode('hex')
-				ct = data['CT'].decode('hex')
+				payload = binascii.unhexlify(data['Payload'])
+				ct = binascii.unhexlify(data['CT'])
 
 				try:
 					c = Crypto(crid=crid,
@@ -262,7 +262,7 @@ def GenTestCase(cname):
 				out = r + tag
 				self.assertEqual(out, ct,
 				    "Count " + data['Count'] + " Actual: " + \
-				    repr(out.encode("hex")) + " Expected: " + \
+				    repr(binascii.hexlify(out)) + " Expected: " + \
 				    repr(data) + " on " + cname)
 
 		def runCCMDecrypt(self, fname):
@@ -279,14 +279,14 @@ def GenTestCase(cname):
 				if Tlen != 16:
 					# OCF only supports 16 byte tags
 					continue
-				key = data['Key'].decode('hex')
-				nonce = data['Nonce'].decode('hex')
+				key = binascii.unhexlify(data['Key'])
+				nonce = binascii.unhexlify(data['Nonce'])
 				Alen = int(data['Alen'])
 				if Alen != 0:
-					aad = data['Adata'].decode('hex')
+					aad = binascii.unhexlify(data['Adata'])
 				else:
 					aad = None
-				ct = data['CT'].decode('hex')
+				ct = binascii.unhexlify(data['CT'])
 				tag = ct[-16:]
 				ct = ct[:-16]
 
@@ -308,12 +308,12 @@ def GenTestCase(cname):
 					r = Crypto.decrypt(c, payload, nonce,
 					    aad, tag)
 
-					payload = data['Payload'].decode('hex')
+					payload = binascii.unhexlify(data['Payload'])
 					Plen = int(data('Plen'))
 					payload = payload[:plen]
 					self.assertEqual(r, payload,
 					    "Count " + data['Count'] + \
-					    " Actual: " + repr(r.encode("hex")) + \
+					    " Actual: " + repr(binascii.hexlify(r)) + \
 					    " Expected: " + repr(data) + \
 					    " on " + cname)
 
@@ -341,10 +341,10 @@ def GenTestCase(cname):
 				for data in lines:
 					curcnt = int(data['COUNT'])
 					key = data['KEYs'] * 3
-					cipherkey = key.decode('hex')
-					iv = data['IV'].decode('hex')
-					pt = data['PLAINTEXT'].decode('hex')
-					ct = data['CIPHERTEXT'].decode('hex')
+					cipherkey = binascii.unhexlify(key)
+					iv = binascii.unhexlify(data['IV'])
+					pt = binascii.unhexlify(data['PLAINTEXT'])
+					ct = binascii.unhexlify(data['CIPHERTEXT'])
 
 					if swapptct:
 						pt, ct = ct, pt
@@ -389,9 +389,9 @@ def GenTestCase(cname):
 					continue
 
 				for data in lines:
-					msg = data['Msg'].decode('hex')
+					msg = binascii.unhexlify(data['Msg'])
 					msg = msg[:int(data['Len'])]
-					md = data['MD'].decode('hex')
+					md = binascii.unhexlify(data['MD'])
 
 					try:
 						c = Crypto(mac=alg, crid=crid,
@@ -405,7 +405,7 @@ def GenTestCase(cname):
 					_, r = c.encrypt(msg, iv="")
 
 					self.assertEqual(r, md, "Actual: " + \
-					    repr(r.encode("hex")) + " Expected: " + repr(data) + " on " + cname)
+					    repr(binascii.hexlify(r)) + " Expected: " + repr(data) + " on " + cname)
 
 		@unittest.skipIf(cname not in shamodules, 'skipping SHA-HMAC on %s' % str(cname))
 		def test_sha1hmac(self):
@@ -442,9 +442,9 @@ def GenTestCase(cname):
 					continue
 
 				for data in lines:
-					key = data['Key'].decode('hex')
-					msg = data['Msg'].decode('hex')
-					mac = data['Mac'].decode('hex')
+					key = binascii.unhexlify(data['Key'])
+					msg = binascii.unhexlify(data['Msg'])
+					mac = binascii.unhexlify(data['Mac'])
 					tlen = int(data['Tlen'])
 
 					if len(key) > blocksize:
@@ -462,7 +462,7 @@ def GenTestCase(cname):
 					_, r = c.encrypt(msg, iv="")
 
 					self.assertEqual(r[:tlen], mac, "Actual: " + \
-					    repr(r.encode("hex")) + " Expected: " + repr(data))
+					    repr(binascii.hexlify(r)) + " Expected: " + repr(data))
 
 	return GendCryptoTestCase
 


More information about the svn-src-all mailing list