Index: head/tests/sys/opencrypto/blake2_test.c =================================================================== --- head/tests/sys/opencrypto/blake2_test.c (revision 368007) +++ head/tests/sys/opencrypto/blake2_test.c (revision 368008) @@ -1,226 +1,219 @@ /*- * Copyright (c) 2018 Conrad Meyer * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Derived from blake2b-test.c and blake2s-test.c: * * BLAKE2 reference source code package - optimized C implementations * * Written in 2012 by Samuel Neves * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain * worldwide. This software is distributed without any warranty. * * You should have received a copy of the CC0 Public Domain Dedication along with * this software. If not, see . */ #include #include #include #include #include /* Be sure to include tree copy rather than system copy. */ #include "cryptodev.h" #include "freebsd_test_suite/macros.h" #include #include "blake2-kat.h" static uint8_t key2b[BLAKE2B_KEYBYTES]; static uint8_t key2s[BLAKE2S_KEYBYTES]; static uint8_t katbuf[KAT_LENGTH]; static void initialize_constant_buffers(void) { size_t i; for (i = 0; i < sizeof(key2b); i++) key2b[i] = (uint8_t)i; for (i = 0; i < sizeof(key2s); i++) key2s[i] = (uint8_t)i; for (i = 0; i < sizeof(katbuf); i++) katbuf[i] = (uint8_t)i; } static int lookup_crid(int fd, const char *devname) { struct crypt_find_op find; find.crid = -1; strlcpy(find.name, devname, sizeof(find.name)); ATF_REQUIRE(ioctl(fd, CIOCFINDDEV, &find) != -1); return (find.crid); } static int get_handle_fd(void) { - int dc_fd, fd; + int fd; - dc_fd = open("/dev/crypto", O_RDWR); - - /* - * Why do we do this dance instead of just operating on /dev/crypto - * directly? I have no idea. - */ - ATF_REQUIRE(dc_fd >= 0); - ATF_REQUIRE(ioctl(dc_fd, CRIOGET, &fd) != -1); - close(dc_fd); + fd = open("/dev/crypto", O_RDWR); + ATF_REQUIRE(fd >= 0); return (fd); } static int create_session(int fd, int alg, int crid, const void *key, size_t klen) { struct session2_op sop; memset(&sop, 0, sizeof(sop)); sop.mac = alg; sop.mackey = key; sop.mackeylen = klen; sop.crid = crid; ATF_REQUIRE_MSG(ioctl(fd, CIOCGSESSION2, &sop) >= 0, "alg %d keylen %zu, errno=%d (%s)", alg, klen, errno, strerror(errno)); return (sop.ses); } static void do_cryptop(int fd, int ses, size_t inlen, void *out) { struct crypt_op cop; memset(&cop, 0, sizeof(cop)); cop.ses = ses; cop.len = inlen; cop.src = katbuf; cop.mac = out; ATF_CHECK_MSG(ioctl(fd, CIOCCRYPT, &cop) >= 0, "ioctl(CIOCCRYPT)"); } static void test_blake2b_vectors(const char *devname, const char *modname) { uint8_t hash[BLAKE2B_OUTBYTES]; int crid, fd, ses; size_t i; ATF_REQUIRE_KERNEL_MODULE(modname); ATF_REQUIRE_KERNEL_MODULE("cryptodev"); initialize_constant_buffers(); fd = get_handle_fd(); crid = lookup_crid(fd, devname); ses = create_session(fd, CRYPTO_BLAKE2B, crid, key2b, sizeof(key2b)); for (i = 0; i < sizeof(katbuf); i++) { do_cryptop(fd, ses, i, hash); ATF_CHECK_EQ_MSG( memcmp(hash, blake2b_keyed_kat[i], sizeof(hash)), 0, "different at %zu", i); } } static void test_blake2s_vectors(const char *devname, const char *modname) { uint8_t hash[BLAKE2S_OUTBYTES]; int crid, fd, ses; size_t i; ATF_REQUIRE_KERNEL_MODULE(modname); ATF_REQUIRE_KERNEL_MODULE("cryptodev"); initialize_constant_buffers(); fd = get_handle_fd(); crid = lookup_crid(fd, devname); ses = create_session(fd, CRYPTO_BLAKE2S, crid, key2s, sizeof(key2s)); for (i = 0; i < sizeof(katbuf); i++) { do_cryptop(fd, ses, i, hash); ATF_CHECK_EQ_MSG( memcmp(hash, blake2s_keyed_kat[i], sizeof(hash)), 0, "different at %zu", i); } } ATF_TC_WITHOUT_HEAD(blake2b_vectors); ATF_TC_BODY(blake2b_vectors, tc) { ATF_REQUIRE_SYSCTL_INT("kern.crypto.allow_soft", 1); test_blake2b_vectors("cryptosoft0", "nexus/cryptosoft"); } ATF_TC_WITHOUT_HEAD(blake2s_vectors); ATF_TC_BODY(blake2s_vectors, tc) { ATF_REQUIRE_SYSCTL_INT("kern.crypto.allow_soft", 1); test_blake2s_vectors("cryptosoft0", "nexus/cryptosoft"); } #if defined(__i386__) || defined(__amd64__) ATF_TC_WITHOUT_HEAD(blake2b_vectors_x86); ATF_TC_BODY(blake2b_vectors_x86, tc) { ATF_REQUIRE_SYSCTL_INT("kern.crypto.allow_soft", 1); test_blake2b_vectors("blaketwo0", "nexus/blake2"); } ATF_TC_WITHOUT_HEAD(blake2s_vectors_x86); ATF_TC_BODY(blake2s_vectors_x86, tc) { ATF_REQUIRE_SYSCTL_INT("kern.crypto.allow_soft", 1); test_blake2s_vectors("blaketwo0", "nexus/blake2"); } #endif ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, blake2b_vectors); ATF_TP_ADD_TC(tp, blake2s_vectors); #if defined(__i386__) || defined(__amd64__) ATF_TP_ADD_TC(tp, blake2b_vectors_x86); ATF_TP_ADD_TC(tp, blake2s_vectors_x86); #endif return (atf_no_error()); } Index: head/tests/sys/opencrypto/cryptodev.py =================================================================== --- head/tests/sys/opencrypto/cryptodev.py (revision 368007) +++ head/tests/sys/opencrypto/cryptodev.py (revision 368008) @@ -1,724 +1,713 @@ #!/usr/local/bin/python3 # # Copyright (c) 2014 The FreeBSD Foundation # Copyright 2014 John-Mark Gurney # All rights reserved. # Copyright 2019 Enji Cooper # # This software was developed by John-Mark Gurney under # the sponsorship from the FreeBSD Foundation. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # import array import binascii from fcntl import ioctl import os import platform import random import signal from struct import pack as _pack import sys import time import dpkt from cryptodevh import * __all__ = [ 'Crypto', 'MismatchError', ] class FindOp(dpkt.Packet): __byte_order__ = '@' __hdr__ = ( ('crid', 'i', 0), ('name', '32s', 0), ) class SessionOp(dpkt.Packet): __byte_order__ = '@' __hdr__ = ( ('cipher', 'I', 0), ('mac', 'I', 0), ('keylen', 'I', 0), ('key', 'P', 0), ('mackeylen', 'i', 0), ('mackey', 'P', 0), ('ses', 'I', 0), ) class SessionOp2(dpkt.Packet): __byte_order__ = '@' __hdr__ = ( ('cipher', 'I', 0), ('mac', 'I', 0), ('keylen', 'I', 0), ('key', 'P', 0), ('mackeylen', 'i', 0), ('mackey', 'P', 0), ('ses', 'I', 0), ('crid', 'i', 0), ('pad0', 'i', 0), ('pad1', 'i', 0), ('pad2', 'i', 0), ('pad3', 'i', 0), ) class CryptOp(dpkt.Packet): __byte_order__ = '@' __hdr__ = ( ('ses', 'I', 0), ('op', 'H', 0), ('flags', 'H', 0), ('len', 'I', 0), ('src', 'P', 0), ('dst', 'P', 0), ('mac', 'P', 0), ('iv', 'P', 0), ) class CryptAEAD(dpkt.Packet): __byte_order__ = '@' __hdr__ = ( ('ses', 'I', 0), ('op', 'H', 0), ('flags', 'H', 0), ('len', 'I', 0), ('aadlen', 'I', 0), ('ivlen', 'I', 0), ('src', 'P', 0), ('dst', 'P', 0), ('aad', 'P', 0), ('tag', 'P', 0), ('iv', 'P', 0), ) # h2py.py can't handle multiarg macros -CRIOGET = 3221513060 CIOCGSESSION = 3224396645 CIOCFSESSION = 2147771238 CIOCKEY = 3230688104 CIOCASYMFEAT = 1074029417 CIOCKEY2 = 3230688107 CIOCFINDDEV = 3223610220 if platform.architecture()[0] == '64bit': CIOCGSESSION2 = 3225445226 CIOCCRYPT = 3224396647 CIOCCRYPTAEAD = 3225445229 else: CIOCGSESSION2 = 3224396650 CIOCCRYPT = 3223085927 CIOCCRYPTAEAD = 3223872365 -def _getdev(): - buf = array.array('I', [0]) - fd = os.open('/dev/crypto', os.O_RDWR) - try: - ioctl(fd, CRIOGET, buf, 1) - finally: - os.close(fd) - - return buf[0] - -_cryptodev = _getdev() +_cryptodev = os.open('/dev/crypto', os.O_RDWR) 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 = str_to_ascii(name) s = array.array('B', fop.pack_hdr()) ioctl(_cryptodev, CIOCFINDDEV, s, 1) fop.unpack(s) try: 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): return _findop(-1, name)[0] @staticmethod def getcridname(crid): return _findop(crid, '')[1] def __init__(self, cipher=0, key=None, mac=0, mackey=None, crid=CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE, maclen=None): self._ses = None self._maclen = maclen ses = SessionOp2() ses.cipher = cipher ses.mac = mac if key is not None: ses.keylen = len(key) k = array.array('B', key) ses.key = k.buffer_info()[0] else: self.key = None if mackey is not None: ses.mackeylen = len(mackey) mk = array.array('B', mackey) ses.mackey = mk.buffer_info()[0] if not cipher and not mac: raise ValueError('one of cipher or mac MUST be specified.') ses.crid = crid #print(ses) s = array.array('B', ses.pack_hdr()) #print(s) ioctl(_cryptodev, CIOCGSESSION2, s, 1) ses.unpack(s) self._ses = ses.ses def __del__(self): if self._ses is None: return try: ioctl(_cryptodev, CIOCFSESSION, _pack('I', self._ses)) except TypeError: pass self._ses = None def _doop(self, op, src, iv): cop = CryptOp() cop.ses = self._ses cop.op = op cop.flags = 0 cop.len = len(src) s = array.array('B', src) cop.src = cop.dst = s.buffer_info()[0] if self._maclen is not None: m = array.array('B', [0] * self._maclen) cop.mac = m.buffer_info()[0] ivbuf = array.array('B', str_to_ascii(iv)) cop.iv = ivbuf.buffer_info()[0] #print('cop:', cop) ioctl(_cryptodev, CIOCCRYPT, bytes(cop)) s = array_tobytes(s) if self._maclen is not None: return s, array_tobytes(m) return s def _doaead(self, op, src, aad, iv, tag=None): caead = CryptAEAD() caead.ses = self._ses 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] aad = str_to_ascii(aad) caead.aadlen = len(aad) saad = array.array('B', aad) caead.aad = saad.buffer_info()[0] 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: assert len(tag) == self._maclen, \ '%d != %d' % (len(tag), self._maclen) tag = array.array('B', tag) caead.tag = tag.buffer_info()[0] ivbuf = array.array('B', iv) caead.ivlen = len(iv) caead.iv = ivbuf.buffer_info()[0] ioctl(_cryptodev, CIOCCRYPTAEAD, bytes(caead)) s = array_tobytes(s) return s, array_tobytes(tag) def perftest(self, op, size, timeo=3): inp = array.array('B', (random.randint(0, 255) for x in range(size))) inp = str_to_ascii(inp) out = array.array('B', inp) # prep ioctl cop = CryptOp() cop.ses = self._ses cop.op = op cop.flags = 0 cop.len = len(inp) s = array.array('B', inp) cop.src = s.buffer_info()[0] cop.dst = out.buffer_info()[0] if self._maclen is not None: m = array.array('B', [0] * self._maclen) cop.mac = m.buffer_info()[0] ivbuf = array.array('B', (random.randint(0, 255) for x in range(16))) cop.iv = ivbuf.buffer_info()[0] exit = [ False ] def alarmhandle(a, b, exit=exit): exit[0] = True oldalarm = signal.signal(signal.SIGALRM, alarmhandle) signal.alarm(timeo) start = time.time() reps = 0 cop = bytes(cop) while not exit[0]: ioctl(_cryptodev, CIOCCRYPT, cop) reps += 1 end = time.time() signal.signal(signal.SIGALRM, oldalarm) print('time:', end - start) print('perf MB/sec:', (reps * size) / (end - start) / 1024 / 1024) def encrypt(self, data, iv, aad=None): if aad is None: return self._doop(COP_ENCRYPT, data, iv) else: return self._doaead(COP_ENCRYPT, data, aad, iv) def decrypt(self, data, iv, aad=None, tag=None): if aad is None: return self._doop(COP_DECRYPT, data, iv) else: return self._doaead(COP_DECRYPT, data, aad, iv, tag=tag) class MismatchError(Exception): pass class KATParser: def __init__(self, fname, fields): self.fields = set(fields) self._pending = None self.fname = fname self.fp = None def __enter__(self): self.fp = open(self.fname) return self def __exit__(self, exc_type, exc_value, exc_tb): if self.fp is not None: self.fp.close() def __iter__(self): return self def __next__(self): while True: didread = False if self._pending is not None: i = self._pending self._pending = None else: i = self.fp.readline() didread = True if didread and not i: return if not i.startswith('#') and i.strip(): break if i[0] == '[': yield i[1:].split(']', 1)[0], self.fielditer() else: raise ValueError('unknown line: %r' % repr(i)) def eatblanks(self): while True: line = self.fp.readline() if line == '': break line = line.strip() if line: break return line def fielditer(self): while True: values = {} line = self.eatblanks() if not line or line[0] == '[': self._pending = line return while True: try: f, v = line.split(' =') except: if line == 'FAIL': f, v = 'FAIL', '' else: 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 # we should have everything remain = self.fields.copy() - set(values.keys()) # XXX - special case GCM decrypt if remain and not ('FAIL' in values and 'PT' in remain): raise ValueError('not all fields found: %r' % repr(remain)) 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._pending = None self.fname = fname self.fp = None def __enter__(self): self.fp = open(self.fname) self.read_globals() return self def __exit__(self, exc_type, exc_value, exc_tb): if self.fp is not None: self.fp.close() 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): return self def __next__(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 binascii.hexlify(''.join(s.split())) if sys.version_info[0] < 3: KATCCMParser.next = KATCCMParser.__next__ KATParser.next = KATParser.__next__ if __name__ == '__main__': if True: try: crid = Crypto.findcrid('aesni0') print('aesni:', crid) except IOError: print('aesni0 not found') for i in range(10): try: name = Crypto.getcridname(i) print('%2d: %r' % (i, repr(name))) except IOError: pass elif False: columns = [ 'COUNT', 'DataUnitLen', 'Key', 'DataUnitSeqNumber', 'PT', 'CT' ] fname = '/usr/home/jmg/aesni.testing/format tweak value input - data unit seq no/XTSGenAES128.rsp' with KATParser(fname, columns) as kp: for mode, ni in kp: print(i, ni) for j in ni: print(j) elif False: key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c') iv = _spdechex('00000000000000000000000000000001') pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e') #pt = _spdechex('00000000000000000000000000000000') ct = _spdechex('f42c33853ecc5ce2949865fdb83de3bff1089e9360c94f830baebfaff72836ab5236f77212f1e7396c8c54ac73d81986375a6e9e299cfeca5ba051ed25e8d1affa5beaf6c1d2b45e90802408f2ced21663497e906de5f29341e5e52ddfea5363d628b3eb7806835e17bae051b3a6da3f8e2941fe44384eac17a9d298d2c331ca8320c775b5d53263a5e905059d891b21dede2d8110fd427c7bd5a9a274ddb47b1945ee79522203b6e297d0e399ef') c = Crypto(CRYPTO_AES_ICM, key) enc = c.encrypt(pt, iv) print('enc:', binascii.hexlify(enc)) print(' ct:', binascii.hexlify(ct)) assert ct == enc dec = c.decrypt(ct, iv) print('dec:', binascii.hexlify(dec)) print(' pt:', binascii.hexlify(pt)) assert pt == dec elif False: key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c') iv = _spdechex('00000000000000000000000000000001') pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e0a3f') #pt = _spdechex('00000000000000000000000000000000') ct = _spdechex('f42c33853ecc5ce2949865fdb83de3bff1089e9360c94f830baebfaff72836ab5236f77212f1e7396c8c54ac73d81986375a6e9e299cfeca5ba051ed25e8d1affa5beaf6c1d2b45e90802408f2ced21663497e906de5f29341e5e52ddfea5363d628b3eb7806835e17bae051b3a6da3f8e2941fe44384eac17a9d298d2c331ca8320c775b5d53263a5e905059d891b21dede2d8110fd427c7bd5a9a274ddb47b1945ee79522203b6e297d0e399ef3768') c = Crypto(CRYPTO_AES_ICM, key) enc = c.encrypt(pt, iv) print('enc:', binascii.hexlify(enc)) print(' ct:', binascii.hexlify(ct)) assert ct == enc dec = c.decrypt(ct, iv) print('dec:', binascii.hexlify(dec)) print(' pt:', binascii.hexlify(pt)) assert pt == dec elif False: key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c') iv = _spdechex('6eba2716ec0bd6fa5cdef5e6d3a795bc') pt = _spdechex('ab3cabed693a32946055524052afe3c9cb49664f09fc8b7da824d924006b7496353b8c1657c5dec564d8f38d7432e1de35aae9d95590e66278d4acce883e51abaf94977fcd3679660109a92bf7b2973ccd547f065ec6cee4cb4a72a5e9f45e615d920d76cb34cba482467b3e21422a7242e7d931330c0fbf465c3a3a46fae943029fd899626dda542750a1eee253df323c6ef1573f1c8c156613e2ea0a6cdbf2ae9701020be2d6a83ecb7f3f9d8e0a3f') ct = _spdechex('f1f81f12e72e992dbdc304032705dc75dc3e4180eff8ee4819906af6aee876d5b00b7c36d282a445ce3620327be481e8e53a8e5a8e5ca9abfeb2281be88d12ffa8f46d958d8224738c1f7eea48bda03edbf9adeb900985f4fa25648b406d13a886c25e70cfdecdde0ad0f2991420eb48a61c64fd797237cf2798c2675b9bb744360b0a3f329ac53bbceb4e3e7456e6514f1a9d2f06c236c31d0f080b79c15dce1096357416602520daa098b17d1af427') c = Crypto(CRYPTO_AES_CBC, key) enc = c.encrypt(pt, iv) print('enc:', binascii.hexlify(enc)) print(' ct:', binascii.hexlify(ct)) assert ct == enc dec = c.decrypt(ct, iv) print('dec:', binascii.hexlify(dec)) print(' pt:', binascii.hexlify(pt)) assert pt == dec elif False: key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c') iv = _spdechex('b3d8cc017cbb89b39e0f67e2') pt = _spdechex('c3b3c41f113a31b73d9a5cd4321030') aad = _spdechex('24825602bd12a984e0092d3e448eda5f') ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa7354') ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa73') tag = _spdechex('0032a1dc85f1c9786925a2e71d8272dd') tag = _spdechex('8d11a0929cb3fbe1fef01a4a38d5f8ea') c = Crypto(CRYPTO_AES_NIST_GCM_16, key) enc, enctag = c.encrypt(pt, iv, aad=aad) print('enc:', binascii.hexlify(enc)) print(' ct:', binascii.hexlify(ct)) assert enc == ct 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:', binascii.hexlify(dec)) print(' pt:', binascii.hexlify(pt)) assert dec == pt print('dtg:', binascii.hexlify(dectag)) print('tag:', binascii.hexlify(tag)) assert dectag == tag elif False: key = _spdechex('c939cc13397c1d37de6ae0e1cb7c423c') iv = _spdechex('b3d8cc017cbb89b39e0f67e2') key = key + iv[:4] iv = iv[4:] pt = _spdechex('c3b3c41f113a31b73d9a5cd432103069') aad = _spdechex('24825602bd12a984e0092d3e448eda5f') ct = _spdechex('93fe7d9e9bfd10348a5606e5cafa7354') tag = _spdechex('0032a1dc85f1c9786925a2e71d8272dd') c = Crypto(CRYPTO_AES_GCM_16, key) enc, enctag = c.encrypt(pt, iv, aad=aad) print('enc:', binascii.hexlify(enc)) print(' ct:', binascii.hexlify(ct)) assert enc == ct print('etg:', binascii.hexlify(enctag)) print('tag:', binascii.hexlify(tag)) assert enctag == tag elif False: for i in range(100000): 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, binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382')) data = binascii.unhexlify('52a42bca4e9425a25bbc8c8bf6129dec') ct = binascii.unhexlify('517e602becd066b65fa4f4f56ddfe240') iv = _pack('QQ', 71, 0) enc = c.encrypt(data, iv) assert enc == ct dec = c.decrypt(enc, iv) assert dec == data #c.perftest(COP_ENCRYPT, 192*1024, reps=30000) else: key = binascii.unhexlify('1bbfeadf539daedcae33ced497343f3ca1f2474ad932b903997d44707db41382') print('XTS %d testing:' % (len(key) * 8)) c = Crypto(CRYPTO_AES_XTS, key) for i in [ 8192, 192*1024]: print('block size: %d' % i) c.perftest(COP_ENCRYPT, i) c.perftest(COP_DECRYPT, i) Index: head/tests/sys/opencrypto/poly1305_test.c =================================================================== --- head/tests/sys/opencrypto/poly1305_test.c (revision 368007) +++ head/tests/sys/opencrypto/poly1305_test.c (revision 368008) @@ -1,403 +1,396 @@ /*- * Copyright (c) 2018 Conrad Meyer * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include /* Be sure to include tree copy rather than system copy. */ #include "cryptodev.h" #include "freebsd_test_suite/macros.h" struct poly1305_kat { const char *vector_name; const char *test_key_hex; const char *test_msg_hex; const size_t test_msg_len; const char *expected_tag_hex; }; static const struct poly1305_kat rfc7539_kats[] = { { .vector_name = "RFC 7539 \xc2\xa7 2.5.2", .test_key_hex = "85:d6:be:78:57:55:6d:33:7f:44:52:fe:42:d5:06:a8" ":01:03:80:8a:fb:0d:b2:fd:4a:bf:f6:af:41:49:f5:1b", .test_msg_hex = "43 72 79 70 74 6f 67 72 61 70 68 69 63 20 46 6f " "72 75 6d 20 52 65 73 65 61 72 63 68 20 47 72 6f " "75 70", .test_msg_len = 34, .expected_tag_hex = "a8:06:1d:c1:30:51:36:c6:c2:2b:8b:af:0c:01:27:a9", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #1", .test_key_hex = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_len = 64, .expected_tag_hex = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #2", .test_key_hex = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "36 e5 f6 b5 c5 e0 60 70 f0 ef ca 96 22 7a 86 3e ", .test_msg_hex = "41 6e 79 20 73 75 62 6d 69 73 73 69 6f 6e 20 74 " "6f 20 74 68 65 20 49 45 54 46 20 69 6e 74 65 6e " "64 65 64 20 62 79 20 74 68 65 20 43 6f 6e 74 72 " "69 62 75 74 6f 72 20 66 6f 72 20 70 75 62 6c 69 " "63 61 74 69 6f 6e 20 61 73 20 61 6c 6c 20 6f 72 " "20 70 61 72 74 20 6f 66 20 61 6e 20 49 45 54 46 " "20 49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 20 " "6f 72 20 52 46 43 20 61 6e 64 20 61 6e 79 20 73 " "74 61 74 65 6d 65 6e 74 20 6d 61 64 65 20 77 69 " "74 68 69 6e 20 74 68 65 20 63 6f 6e 74 65 78 74 " "20 6f 66 20 61 6e 20 49 45 54 46 20 61 63 74 69 " "76 69 74 79 20 69 73 20 63 6f 6e 73 69 64 65 72 " "65 64 20 61 6e 20 22 49 45 54 46 20 43 6f 6e 74 " "72 69 62 75 74 69 6f 6e 22 2e 20 53 75 63 68 20 " "73 74 61 74 65 6d 65 6e 74 73 20 69 6e 63 6c 75 " "64 65 20 6f 72 61 6c 20 73 74 61 74 65 6d 65 6e " "74 73 20 69 6e 20 49 45 54 46 20 73 65 73 73 69 " "6f 6e 73 2c 20 61 73 20 77 65 6c 6c 20 61 73 20 " "77 72 69 74 74 65 6e 20 61 6e 64 20 65 6c 65 63 " "74 72 6f 6e 69 63 20 63 6f 6d 6d 75 6e 69 63 61 " "74 69 6f 6e 73 20 6d 61 64 65 20 61 74 20 61 6e " "79 20 74 69 6d 65 20 6f 72 20 70 6c 61 63 65 2c " "20 77 68 69 63 68 20 61 72 65 20 61 64 64 72 65 " "73 73 65 64 20 74 6f", .test_msg_len = 375, .expected_tag_hex = "36 e5 f6 b5 c5 e0 60 70 f0 ef ca 96 22 7a 86 3e", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #3", .test_key_hex = "36 e5 f6 b5 c5 e0 60 70 f0 ef ca 96 22 7a 86 3e " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "41 6e 79 20 73 75 62 6d 69 73 73 69 6f 6e 20 74 " "6f 20 74 68 65 20 49 45 54 46 20 69 6e 74 65 6e " "64 65 64 20 62 79 20 74 68 65 20 43 6f 6e 74 72 " "69 62 75 74 6f 72 20 66 6f 72 20 70 75 62 6c 69 " "63 61 74 69 6f 6e 20 61 73 20 61 6c 6c 20 6f 72 " "20 70 61 72 74 20 6f 66 20 61 6e 20 49 45 54 46 " "20 49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 20 " "6f 72 20 52 46 43 20 61 6e 64 20 61 6e 79 20 73 " "74 61 74 65 6d 65 6e 74 20 6d 61 64 65 20 77 69 " "74 68 69 6e 20 74 68 65 20 63 6f 6e 74 65 78 74 " "20 6f 66 20 61 6e 20 49 45 54 46 20 61 63 74 69 " "76 69 74 79 20 69 73 20 63 6f 6e 73 69 64 65 72 " "65 64 20 61 6e 20 22 49 45 54 46 20 43 6f 6e 74 " "72 69 62 75 74 69 6f 6e 22 2e 20 53 75 63 68 20 " "73 74 61 74 65 6d 65 6e 74 73 20 69 6e 63 6c 75 " "64 65 20 6f 72 61 6c 20 73 74 61 74 65 6d 65 6e " "74 73 20 69 6e 20 49 45 54 46 20 73 65 73 73 69 " "6f 6e 73 2c 20 61 73 20 77 65 6c 6c 20 61 73 20 " "77 72 69 74 74 65 6e 20 61 6e 64 20 65 6c 65 63 " "74 72 6f 6e 69 63 20 63 6f 6d 6d 75 6e 69 63 61 " "74 69 6f 6e 73 20 6d 61 64 65 20 61 74 20 61 6e " "79 20 74 69 6d 65 20 6f 72 20 70 6c 61 63 65 2c " "20 77 68 69 63 68 20 61 72 65 20 61 64 64 72 65 " "73 73 65 64 20 74 6f", .test_msg_len = 375, .expected_tag_hex = "f3 47 7e 7c d9 54 17 af 89 a6 b8 79 4c 31 0c f0", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #4", .test_key_hex = "1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0 " "47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0 ", .test_msg_hex = "27 54 77 61 73 20 62 72 69 6c 6c 69 67 2c 20 61 " "6e 64 20 74 68 65 20 73 6c 69 74 68 79 20 74 6f " "76 65 73 0a 44 69 64 20 67 79 72 65 20 61 6e 64 " "20 67 69 6d 62 6c 65 20 69 6e 20 74 68 65 20 77 " "61 62 65 3a 0a 41 6c 6c 20 6d 69 6d 73 79 20 77 " "65 72 65 20 74 68 65 20 62 6f 72 6f 67 6f 76 65 " "73 2c 0a 41 6e 64 20 74 68 65 20 6d 6f 6d 65 20 " "72 61 74 68 73 20 6f 75 74 67 72 61 62 65 2e", .test_msg_len = 127, .expected_tag_hex = "45 41 66 9a 7e aa ee 61 e7 08 dc 7c bc c5 eb 62", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #5", .test_key_hex = "02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF", .test_msg_len = 16, .expected_tag_hex = "03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #6", .test_key_hex = "02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ", .test_msg_hex = "02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .test_msg_len = 16, .expected_tag_hex = "03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #7", .test_key_hex = "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF " "F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF " "11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .test_msg_len = 48, .expected_tag_hex = "05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #8", .test_key_hex = "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF " "FB FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE " "01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01", .test_msg_len = 48, .expected_tag_hex = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #9", .test_key_hex = "02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "FD FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF", .test_msg_len = 16, .expected_tag_hex = "FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #10", .test_key_hex = "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00 " "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .test_msg_len = 64, .expected_tag_hex = "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00", }, { .vector_name = "RFC 7539 \xc2\xa7 A.3 #11", .test_key_hex = "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", .test_msg_hex = "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00 " "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00 " "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", .test_msg_len = 48, .expected_tag_hex = "13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", }, }; static void parse_hex(const struct poly1305_kat *kat, const char *hexstr, void *voutput, size_t explen) { /* Space or colon delimited; may contain a single trailing space; * length should match exactly. */ const char *sep, *it; size_t sym_len, count; char hbyte[3], *out; int res; out = voutput; memset(hbyte, 0, sizeof(hbyte)); it = hexstr; count = 0; while (true) { sep = strpbrk(it, " :"); if (sep == NULL) sym_len = strlen(it); else sym_len = sep - it; ATF_REQUIRE_EQ_MSG(sym_len, 2, "invalid hex byte '%.*s' in vector %s", (int)sym_len, it, kat->vector_name); memcpy(hbyte, it, 2); res = sscanf(hbyte, "%hhx", &out[count]); ATF_REQUIRE_EQ_MSG(res, 1, "invalid hex byte '%s' in vector %s", hbyte, kat->vector_name); count++; ATF_REQUIRE_MSG(count <= explen, "got longer than expected value at %s", kat->vector_name); if (sep == NULL) break; it = sep; while (*it == ' ' || *it == ':') it++; if (*it == 0) break; } ATF_REQUIRE_EQ_MSG(count, explen, "got short value at %s", kat->vector_name); } static void parse_vector(const struct poly1305_kat *kat, uint8_t key[__min_size(POLY1305_KEY_LEN)], char *msg, uint8_t exptag[__min_size(POLY1305_HASH_LEN)]) { parse_hex(kat, kat->test_key_hex, key, POLY1305_KEY_LEN); parse_hex(kat, kat->test_msg_hex, msg, kat->test_msg_len); parse_hex(kat, kat->expected_tag_hex, exptag, POLY1305_HASH_LEN); } static int get_handle_fd(void) { - int dc_fd, fd; + int fd; - dc_fd = open("/dev/crypto", O_RDWR); - - /* - * Why do we do this dance instead of just operating on /dev/crypto - * directly? I have no idea. - */ - ATF_REQUIRE(dc_fd >= 0); - ATF_REQUIRE(ioctl(dc_fd, CRIOGET, &fd) != -1); - close(dc_fd); + fd = open("/dev/crypto", O_RDWR); + ATF_REQUIRE(fd >= 0); return (fd); } static int create_session(int fd, int alg, int crid, const void *key, size_t klen) { struct session2_op sop; memset(&sop, 0, sizeof(sop)); sop.mac = alg; sop.mackey = key; sop.mackeylen = klen; sop.crid = crid; ATF_REQUIRE_MSG(ioctl(fd, CIOCGSESSION2, &sop) >= 0, "alg %d keylen %zu, errno=%d (%s)", alg, klen, errno, strerror(errno)); return (sop.ses); } static void destroy_session(int fd, int _ses) { uint32_t ses; ses = _ses; ATF_REQUIRE_MSG(ioctl(fd, CIOCFSESSION, &ses) >= 0, "destroy session failed, errno=%d (%s)", errno, strerror(errno)); } static void do_cryptop(int fd, int ses, const void *inp, size_t inlen, void *out) { struct crypt_op cop; memset(&cop, 0, sizeof(cop)); cop.ses = ses; cop.len = inlen; cop.src = inp; cop.mac = out; ATF_CHECK_MSG(ioctl(fd, CIOCCRYPT, &cop) >= 0, "ioctl(CIOCCRYPT)"); } static void test_rfc7539_poly1305_vectors(int crid, const char *modname) { uint8_t comptag[POLY1305_HASH_LEN], exptag[POLY1305_HASH_LEN], key[POLY1305_KEY_LEN], msg[512]; int fd, ses; size_t i; ATF_REQUIRE_KERNEL_MODULE(modname); ATF_REQUIRE_KERNEL_MODULE("cryptodev"); fd = get_handle_fd(); for (i = 0; i < nitems(rfc7539_kats); i++) { const struct poly1305_kat *kat; kat = &rfc7539_kats[i]; parse_vector(kat, key, msg, exptag); ses = create_session(fd, CRYPTO_POLY1305, crid, key, sizeof(key)); do_cryptop(fd, ses, msg, kat->test_msg_len, comptag); ATF_CHECK_EQ_MSG(memcmp(comptag, exptag, sizeof(exptag)), 0, "KAT %s failed:", kat->vector_name); destroy_session(fd, ses); } } ATF_TC_WITHOUT_HEAD(poly1305_vectors); ATF_TC_BODY(poly1305_vectors, tc) { ATF_REQUIRE_SYSCTL_INT("kern.crypto.allow_soft", 1); test_rfc7539_poly1305_vectors(CRYPTO_FLAG_SOFTWARE, "nexus/cryptosoft"); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, poly1305_vectors); return (atf_no_error()); } Index: head/tools/tools/crypto/cryptokeytest.c =================================================================== --- head/tools/tools/crypto/cryptokeytest.c (revision 368007) +++ head/tools/tools/crypto/cryptokeytest.c (revision 368008) @@ -1,273 +1,270 @@ /* $FreeBSD$ */ /* * The big num stuff is a bit broken at the moment and I've not yet fixed it. * The symtom is that odd size big nums will fail. Test code below (it only * uses modexp currently). * * --Jason L. Wright */ #include #include #include #include #include #include #include #include #include #include #include #include #include int crid = CRYPTO_FLAG_HARDWARE; int verbose = 0; static int devcrypto(void) { static int fd = -1; if (fd < 0) { fd = open(_PATH_DEV "crypto", O_RDWR, 0); if (fd < 0) err(1, _PATH_DEV "crypto"); if (fcntl(fd, F_SETFD, 1) == -1) err(1, "fcntl(F_SETFD) (devcrypto)"); } return fd; } static int crlookup(const char *devname) { struct crypt_find_op find; find.crid = -1; strlcpy(find.name, devname, sizeof(find.name)); if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) err(1, "ioctl(CIOCFINDDEV)"); return find.crid; } static const char * crfind(int crid) { static struct crypt_find_op find; bzero(&find, sizeof(find)); find.crid = crid; if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) err(1, "ioctl(CIOCFINDDEV)"); return find.name; } /* * Convert a little endian byte string in 'p' that is 'plen' bytes long to a * BIGNUM. A new BIGNUM is allocated. Returns NULL on failure. */ static BIGNUM * le_to_bignum(BIGNUM *res, const void *p, int plen) { res = BN_lebin2bn(p, plen, res); if (res == NULL) ERR_print_errors_fp(stderr); return (res); } /* * Convert a BIGNUM to a little endian byte string. Space for BN_num_bytes(n) * is allocated. * Returns NULL on failure. */ static void * bignum_to_le(const BIGNUM *n) { int blen, error; void *rd; blen = BN_num_bytes(n); if (blen == 0) return (NULL); rd = malloc(blen); if (rd == NULL) return (NULL); error = BN_bn2lebinpad(n, rd, blen); if (error < 0) { ERR_print_errors_fp(stderr); free(rd); return (NULL); } return (rd); } static int UB_mod_exp(BIGNUM *res, const BIGNUM *a, const BIGNUM *b, const BIGNUM *c) { struct crypt_kop kop; void *ale, *ble, *cle; - static int crypto_fd = -1; - - if (crypto_fd == -1 && ioctl(devcrypto(), CRIOGET, &crypto_fd) == -1) - err(1, "CRIOGET"); + int crypto_fd = devcrypto(); if ((ale = bignum_to_le(a)) == NULL) err(1, "bignum_to_le, a"); if ((ble = bignum_to_le(b)) == NULL) err(1, "bignum_to_le, b"); if ((cle = bignum_to_le(c)) == NULL) err(1, "bignum_to_le, c"); bzero(&kop, sizeof(kop)); kop.crk_op = CRK_MOD_EXP; kop.crk_iparams = 3; kop.crk_oparams = 1; kop.crk_crid = crid; kop.crk_param[0].crp_p = ale; kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8; kop.crk_param[1].crp_p = ble; kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8; kop.crk_param[2].crp_p = cle; kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8; kop.crk_param[3].crp_p = cle; kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8; if (ioctl(crypto_fd, CIOCKEY2, &kop) == -1) err(1, "CIOCKEY2"); if (verbose) printf("device = %s\n", crfind(kop.crk_crid)); explicit_bzero(ale, BN_num_bytes(a)); free(ale); explicit_bzero(ble, BN_num_bytes(b)); free(ble); if (kop.crk_status != 0) { printf("error %d\n", kop.crk_status); explicit_bzero(cle, BN_num_bytes(c)); free(cle); return (-1); } else { res = le_to_bignum(res, cle, BN_num_bytes(c)); explicit_bzero(cle, BN_num_bytes(c)); free(cle); if (res == NULL) err(1, "le_to_bignum"); return (0); } return (0); } static void show_result(const BIGNUM *a, const BIGNUM *b, const BIGNUM *c, const BIGNUM *sw, const BIGNUM *hw) { printf("\n"); printf("A = "); BN_print_fp(stdout, a); printf("\n"); printf("B = "); BN_print_fp(stdout, b); printf("\n"); printf("C = "); BN_print_fp(stdout, c); printf("\n"); printf("sw= "); BN_print_fp(stdout, sw); printf("\n"); printf("hw= "); BN_print_fp(stdout, hw); printf("\n"); printf("\n"); } static void testit(void) { BIGNUM *a, *b, *c, *r1, *r2; BN_CTX *ctx; ctx = BN_CTX_new(); a = BN_new(); b = BN_new(); c = BN_new(); r1 = BN_new(); r2 = BN_new(); BN_pseudo_rand(a, 1023, 0, 0); BN_pseudo_rand(b, 1023, 0, 0); BN_pseudo_rand(c, 1024, 0, 0); if (BN_cmp(a, c) > 0) { BIGNUM *rem = BN_new(); BN_mod(rem, a, c, ctx); UB_mod_exp(r2, rem, b, c); BN_free(rem); } else { UB_mod_exp(r2, a, b, c); } BN_mod_exp(r1, a, b, c, ctx); if (BN_cmp(r1, r2) != 0) { show_result(a, b, c, r1, r2); } BN_free(r2); BN_free(r1); BN_free(c); BN_free(b); BN_free(a); BN_CTX_free(ctx); } static void usage(const char* cmd) { printf("usage: %s [-d dev] [-v] [count]\n", cmd); printf("count is the number of bignum ops to do\n"); printf("\n"); printf("-d use specific device\n"); printf("-v be verbose\n"); exit(-1); } int main(int argc, char *argv[]) { int c, i; while ((c = getopt(argc, argv, "d:v")) != -1) { switch (c) { case 'd': crid = crlookup(optarg); break; case 'v': verbose = 1; break; default: usage(argv[0]); } } argc -= optind, argv += optind; for (i = 0; i < 1000; i++) { fprintf(stderr, "test %d\n", i); testit(); } return (0); } Index: head/tools/tools/crypto/cryptotest.c =================================================================== --- head/tools/tools/crypto/cryptotest.c (revision 368007) +++ head/tools/tools/crypto/cryptotest.c (revision 368008) @@ -1,672 +1,660 @@ /*- * Copyright (c) 2004 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. * * $FreeBSD$ */ /* * Simple tool for testing hardware/system crypto support. * * cryptotest [-czsbv] [-a algorithm] [count] [size ...] * * Run count iterations of a crypt+decrypt or mac operation on a buffer of * size bytes. A random key and iv are used. Options: * -c check the results * -d dev pin work on device dev * -z run all available algorithms on a variety of buffer sizes * -v be verbose * -b mark operations for batching * -p profile kernel crypto operations (must be root) * -t n fork n threads and run tests concurrently * Known algorithms are: * null null cbc * des des cbc * 3des 3des cbc * blf blowfish cbc * cast cast cbc * skj skipjack cbc * aes rijndael/aes 128-bit cbc * aes192 rijndael/aes 192-bit cbc * aes256 rijndael/aes 256-bit cbc * chacha20 Chacha20 stream cipher * blake2b Blake2b * blake2s Blake2s * md5 md5 hmac * sha1 sha1 hmac * sha256 256-bit sha2 hmac * sha384 384-bit sha2 hmac * sha512 512--bit sha2 hmac * * For a test of how fast a crypto card is, use something like: * cryptotest -z 1024 * This will run a series of tests using the available crypto/cipher * algorithms over a variety of buffer sizes. The 1024 says to do 1024 * iterations. Extra arguments can be used to specify one or more buffer * sizes to use in doing tests. * * To fork multiple processes all doing the same work, specify -t X on the * command line to get X "threads" running simultaneously. No effort is made * to synchronize the threads or otherwise maximize load. * * If the kernel crypto code is built with CRYPTO_TIMING and you run as root, * then you can specify the -p option to get a "profile" of the time spent * processing crypto operations. At present this data is only meaningful for * symmetric operations. To get meaningful numbers you must run on an idle * machine. * * Expect ~400 Mb/s for a Broadcom 582x for 8K buffers on a reasonable CPU * (64-bit PCI helps). Hifn 7811 parts top out at ~110 Mb/s. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CHUNK 64 /* how much to display */ #define streq(a,b) (strcasecmp(a,b) == 0) void hexdump(char *, int); int verbose = 0; int opflags = 0; int verify = 0; int crid = CRYPTO_FLAG_HARDWARE; struct alg { const char* name; int ishash; int blocksize; int minkeylen; int maxkeylen; int code; } algorithms[] = { #ifdef CRYPTO_NULL_CBC { "null", 0, 8, 1, 256, CRYPTO_NULL_CBC }, #endif { "des", 0, 8, 8, 8, CRYPTO_DES_CBC }, { "3des", 0, 8, 24, 24, CRYPTO_3DES_CBC }, { "blf", 0, 8, 5, 56, CRYPTO_BLF_CBC }, { "cast", 0, 8, 5, 16, CRYPTO_CAST_CBC }, { "skj", 0, 8, 10, 10, CRYPTO_SKIPJACK_CBC }, { "rij", 0, 16, 16, 16, CRYPTO_RIJNDAEL128_CBC}, { "aes", 0, 16, 16, 16, CRYPTO_AES_CBC}, { "aes192", 0, 16, 24, 24, CRYPTO_AES_CBC}, { "aes256", 0, 16, 32, 32, CRYPTO_AES_CBC}, { "chacha20", 0, 1, 32, 32, CRYPTO_CHACHA20}, { "blake2b", 1, 128, 64, 64, CRYPTO_BLAKE2B }, { "blake2s", 1, 64, 32, 32, CRYPTO_BLAKE2S }, { "md5", 1, 8, 16, 16, CRYPTO_MD5_HMAC }, { "sha1", 1, 8, 20, 20, CRYPTO_SHA1_HMAC }, { "sha256", 1, 8, 32, 32, CRYPTO_SHA2_256_HMAC }, { "sha384", 1, 8, 48, 48, CRYPTO_SHA2_384_HMAC }, { "sha512", 1, 8, 64, 64, CRYPTO_SHA2_512_HMAC }, }; void usage(const char* cmd) { printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n", cmd); printf("where algorithm is one of:\n"); printf(" null des 3des (default) blowfish cast skipjack rij\n"); printf(" aes aes192 aes256 chacha20 md5 sha1 sha256 sha384 sha512\n"); printf(" blake2b blake2s\n"); printf(" or an encryption algorithm concatented with authentication\n"); printf(" algorithm with '+' in the middle, e.g., aes+sha1.\n"); printf("count is the number of encrypt/decrypt ops to do\n"); printf("size is the number of bytes of text to encrypt+decrypt\n"); printf("\n"); printf("-c check the results (slows timing)\n"); printf("-d use specific device, specify 'soft' for testing software implementations\n"); printf("\tNOTE: to use software you must set:\n\t sysctl kern.cryptodevallowsoft=1\n"); printf("-z run all available algorithms on a variety of sizes\n"); printf("-v be verbose\n"); printf("-b mark operations for batching\n"); printf("-p profile kernel crypto operation (must be root)\n"); printf("-t n for n threads and run tests concurrently\n"); exit(-1); } struct alg* getalgbycode(int cipher) { int i; for (i = 0; i < nitems(algorithms); i++) if (cipher == algorithms[i].code) return &algorithms[i]; return NULL; } struct alg* getalgbyname(const char* name) { int i; for (i = 0; i < nitems(algorithms); i++) if (streq(name, algorithms[i].name)) return &algorithms[i]; return NULL; } int devcrypto(void) { int fd = -1; if (fd < 0) { fd = open(_PATH_DEV "crypto", O_RDWR, 0); if (fd < 0) err(1, _PATH_DEV "crypto"); if (fcntl(fd, F_SETFD, 1) == -1) err(1, "fcntl(F_SETFD) (devcrypto)"); } return fd; } int crlookup(const char *devname) { struct crypt_find_op find; if (strncmp(devname, "soft", 4) == 0) return CRYPTO_FLAG_SOFTWARE; find.crid = -1; strlcpy(find.name, devname, sizeof(find.name)); if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) err(1, "ioctl(CIOCFINDDEV)"); return find.crid; } const char * crfind(int crid) { static struct crypt_find_op find; bzero(&find, sizeof(find)); find.crid = crid; - if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1) + if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) err(1, "ioctl(CIOCFINDDEV): crid %d", crid); return find.name; } -int -crget(void) -{ - int fd; - - if (ioctl(devcrypto(), CRIOGET, &fd) == -1) - err(1, "ioctl(CRIOGET)"); - if (fcntl(fd, F_SETFD, 1) == -1) - err(1, "fcntl(F_SETFD) (crget)"); - return fd; -} - char rdigit(void) { const char a[] = { 0x10,0x54,0x11,0x48,0x45,0x12,0x4f,0x13,0x49,0x53,0x14,0x41, 0x15,0x16,0x4e,0x55,0x54,0x17,0x18,0x4a,0x4f,0x42,0x19,0x01 }; return 0x20+a[random()%nitems(a)]; } void runtest(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, struct timeval *tv) { - int i, fd = crget(); + int i, fd = devcrypto(); struct timeval start, stop, dt; char *cleartext, *ciphertext, *originaltext, *key; struct session2_op sop; struct crypt_op cop; char iv[EALG_MAX_BLOCK_LEN]; char digest[512/8]; /* Canonicalize 'ealg' to crypt alg and 'alg' to authentication alg. */ if (ealg == NULL && !alg->ishash) { ealg = alg; alg = NULL; } bzero(&sop, sizeof(sop)); if (ealg != NULL) { sop.keylen = (ealg->minkeylen + ealg->maxkeylen)/2; key = (char *) malloc(sop.keylen); if (key == NULL) err(1, "malloc (key)"); for (i = 0; i < sop.keylen; i++) key[i] = rdigit(); sop.key = key; sop.cipher = ealg->code; } if (alg != NULL) { sop.mackeylen = (alg->minkeylen + alg->maxkeylen)/2; key = (char *) malloc(sop.mackeylen); if (key == NULL) err(1, "malloc (mac)"); for (i = 0; i < sop.mackeylen; i++) key[i] = rdigit(); sop.mackey = key; sop.mac = alg->code; } sop.crid = crid; if (ioctl(fd, cmd, &sop) < 0) { if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) { close(fd); if (verbose) { printf("cipher %s%s%s", ealg? ealg->name : "", (ealg && alg) ? "+" : "", alg? alg->name : ""); if (alg->ishash) printf(" mackeylen %u\n", sop.mackeylen); else printf(" keylen %u\n", sop.keylen); perror("CIOCGSESSION"); } /* hardware doesn't support algorithm; skip it */ return; } printf("cipher %s%s%s keylen %u mackeylen %u\n", ealg? ealg->name : "", (ealg && alg) ? "+" : "", alg? alg->name : "", sop.keylen, sop.mackeylen); err(1, "CIOCGSESSION"); } originaltext = malloc(3*size); if (originaltext == NULL) err(1, "malloc (text)"); cleartext = originaltext+size; ciphertext = cleartext+size; for (i = 0; i < size; i++) cleartext[i] = rdigit(); memcpy(originaltext, cleartext, size); for (i = 0; i < nitems(iv); i++) iv[i] = rdigit(); if (verbose) { printf("session = 0x%x\n", sop.ses); printf("device = %s\n", crfind(sop.crid)); printf("count = %d, size = %d\n", count, size); if (ealg) { printf("iv:"); hexdump(iv, sizeof iv); } printf("cleartext:"); hexdump(cleartext, MIN(size, CHUNK)); } gettimeofday(&start, NULL); if (ealg) { for (i = 0; i < count; i++) { cop.ses = sop.ses; cop.op = COP_ENCRYPT; cop.flags = opflags | COP_F_CIPHER_FIRST; cop.len = size; cop.src = cleartext; cop.dst = ciphertext; if (alg) cop.mac = digest; else cop.mac = 0; cop.iv = iv; if (ioctl(fd, CIOCCRYPT, &cop) < 0) err(1, "ioctl(CIOCCRYPT)"); if (verify && bcmp(ciphertext, cleartext, size) == 0) { printf("cipher text unchanged:"); hexdump(ciphertext, size); } memset(cleartext, 'x', MIN(size, CHUNK)); cop.ses = sop.ses; cop.op = COP_DECRYPT; cop.flags = opflags; cop.len = size; cop.src = ciphertext; cop.dst = cleartext; if (alg) cop.mac = digest; else cop.mac = 0; cop.iv = iv; if (ioctl(fd, CIOCCRYPT, &cop) < 0) err(1, "ioctl(CIOCCRYPT)"); if (verify && bcmp(cleartext, originaltext, size) != 0) { printf("decrypt mismatch:\n"); printf("original:"); hexdump(originaltext, size); printf("cleartext:"); hexdump(cleartext, size); } } } else { for (i = 0; i < count; i++) { cop.ses = sop.ses; cop.op = 0; cop.flags = opflags; cop.len = size; cop.src = cleartext; cop.dst = 0; cop.mac = ciphertext; cop.iv = 0; if (ioctl(fd, CIOCCRYPT, &cop) < 0) err(1, "ioctl(CIOCCRYPT)"); } } gettimeofday(&stop, NULL); if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0) perror("ioctl(CIOCFSESSION)"); if (verbose) { printf("cleartext:"); hexdump(cleartext, MIN(size, CHUNK)); } timersub(&stop, &start, tv); free(originaltext); close(fd); } #ifdef __FreeBSD__ void resetstats() { struct cryptostats stats; size_t slen; slen = sizeof (stats); if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) { perror("kern.crypto_stats"); return; } bzero(&stats.cs_invoke, sizeof (stats.cs_invoke)); bzero(&stats.cs_done, sizeof (stats.cs_done)); bzero(&stats.cs_cb, sizeof (stats.cs_cb)); bzero(&stats.cs_finis, sizeof (stats.cs_finis)); stats.cs_invoke.min.tv_sec = 10000; stats.cs_done.min.tv_sec = 10000; stats.cs_cb.min.tv_sec = 10000; stats.cs_finis.min.tv_sec = 10000; if (sysctlbyname("kern.crypto_stats", NULL, NULL, &stats, sizeof (stats)) < 0) perror("kern.cryptostats"); } void printt(const char* tag, struct cryptotstat *ts) { uint64_t avg, min, max; if (ts->count == 0) return; avg = (1000000000LL*ts->acc.tv_sec + ts->acc.tv_nsec) / ts->count; min = 1000000000LL*ts->min.tv_sec + ts->min.tv_nsec; max = 1000000000LL*ts->max.tv_sec + ts->max.tv_nsec; printf("%16.16s: avg %6llu ns : min %6llu ns : max %7llu ns [%u samps]\n", tag, avg, min, max, ts->count); } #endif void runtests(struct alg *ealg, struct alg *alg, int count, int size, u_long cmd, int threads, int profile) { int i, status; double t; void *region; struct timeval *tvp; struct timeval total; int otiming; if (size % alg->blocksize || (ealg && size % ealg->blocksize)) { if (verbose) printf("skipping blocksize %u 'cuz not a multiple of " "%s blocksize %u (or %s blocksize %u)\n", size, alg->name, alg->blocksize, ealg ? ealg->name : "n/a", ealg ? ealg->blocksize : 0); return; } region = mmap(NULL, threads * sizeof (struct timeval), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); if (region == MAP_FAILED) { perror("mmap"); return; } tvp = (struct timeval *) region; #ifdef __FreeBSD__ if (profile) { size_t tlen = sizeof (otiming); int timing = 1; resetstats(); if (sysctlbyname("debug.crypto_timing", &otiming, &tlen, &timing, sizeof (timing)) < 0) perror("debug.crypto_timing"); } #endif if (threads > 1) { for (i = 0; i < threads; i++) if (fork() == 0) { cpuset_t mask; CPU_ZERO(&mask); CPU_SET(i, &mask); cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask), &mask); runtest(ealg, alg, count, size, cmd, &tvp[i]); exit(0); } while (waitpid(WAIT_MYPGRP, &status, 0) != -1) ; } else runtest(ealg, alg, count, size, cmd, tvp); t = 0; for (i = 0; i < threads; i++) t += (((double)tvp[i].tv_sec * 1000000 + tvp[i].tv_usec) / 1000000); if (t) { int nops = alg->ishash ? count : 2*count; nops *= threads; printf("%8.3lf sec, %7d %6s%s%6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n", t, nops, alg->name, ealg? "+" : "", ealg? ealg->name : "", size, (double)nops*size / t, (double)nops*size / t * 8 / 1024 / 1024); } #ifdef __FreeBSD__ if (profile) { struct cryptostats stats; size_t slen = sizeof (stats); if (sysctlbyname("debug.crypto_timing", NULL, NULL, &otiming, sizeof (otiming)) < 0) perror("debug.crypto_timing"); if (sysctlbyname("kern.crypto_stats", &stats, &slen, NULL, 0) < 0) perror("kern.cryptostats"); if (stats.cs_invoke.count) { printt("dispatch->invoke", &stats.cs_invoke); printt("invoke->done", &stats.cs_done); printt("done->cb", &stats.cs_cb); printt("cb->finis", &stats.cs_finis); } } #endif fflush(stdout); } int main(int argc, char **argv) { struct alg *alg = NULL, *ealg = NULL; char *tmp; int count = 1; int sizes[128], nsizes = 0; u_long cmd = CIOCGSESSION2; int testall = 0; int maxthreads = 1; int profile = 0; int i, ch; while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) { switch (ch) { #ifdef CIOCGSSESSION case 's': cmd = CIOCGSSESSION; break; #endif case 'v': verbose++; break; case 'a': tmp = strchr(optarg, '+'); if (tmp != NULL) { *tmp = '\0'; ealg = getalgbyname(optarg); if (ealg == NULL || ealg->ishash) usage(argv[0]); optarg = tmp + 1; } alg = getalgbyname(optarg); if (alg == NULL) { if (streq(optarg, "rijndael")) alg = getalgbyname("aes"); else usage(argv[0]); } else if (ealg != NULL && !alg->ishash) usage(argv[0]); break; case 'd': crid = crlookup(optarg); break; case 't': maxthreads = atoi(optarg); break; case 'z': testall = 1; break; case 'p': profile = 1; break; case 'b': opflags |= COP_F_BATCH; break; case 'c': verify = 1; break; default: usage(argv[0]); } } argc -= optind, argv += optind; if (argc > 0) count = atoi(argv[0]); while (argc > 1) { int s = atoi(argv[1]); if (nsizes < nitems(sizes)) { sizes[nsizes++] = s; } else { printf("Too many sizes, ignoring %u\n", s); } argc--, argv++; } if (maxthreads > CPU_SETSIZE) errx(EX_USAGE, "Too many threads, %d, choose fewer.", maxthreads); if (nsizes == 0) { if (alg) sizes[nsizes++] = alg->blocksize; else sizes[nsizes++] = 8; if (testall) { while (sizes[nsizes-1] < 8*1024) { sizes[nsizes] = sizes[nsizes-1]<<1; nsizes++; } } } if (testall) { for (i = 0; i < nitems(algorithms); i++) { int j; alg = &algorithms[i]; for (j = 0; j < nsizes; j++) runtests(ealg, alg, count, sizes[j], cmd, maxthreads, profile); } } else { if (alg == NULL) alg = getalgbycode(CRYPTO_3DES_CBC); for (i = 0; i < nsizes; i++) runtests(ealg, alg, count, sizes[i], cmd, maxthreads, profile); } return (0); } void hexdump(char *p, int n) { int i, off; for (off = 0; n > 0; off += 16, n -= 16) { printf("%s%04x:", off == 0 ? "\n" : "", off); i = (n >= 16 ? 16 : n); do { printf(" %02x", *p++ & 0xff); } while (--i); printf("\n"); } }