diff options
-rwxr-xr-x | src/sw/hash_tester.py | 204 |
1 files changed, 168 insertions, 36 deletions
diff --git a/src/sw/hash_tester.py b/src/sw/hash_tester.py index 1d8d5b0..2ca0aab 100755 --- a/src/sw/hash_tester.py +++ b/src/sw/hash_tester.py @@ -5,9 +5,9 @@ # hash_tester.py # -------------- # This program sends several commands to the coretest_hashed subsystem -# in order to verify the SHA-1 and SHA-256 hash function cores. -# The program uses the built in hash implementations in Python -# to do functional comparison and validation. +# in order to verify the SHA-1, SHA-256 and SHA-512/x hash function +# cores. The program will use the built in hash implementations in +# Python to do functional comparison and validation. # # Note: This program requires the PySerial module. # http://pyserial.sourceforge.net/ @@ -18,7 +18,7 @@ # # # Author: Joachim Strömbergson -# Copyright (c) 2014, SUNET +# Copyright (c) 2014, Secworks Sweden AB # # Redistribution and use in source and binary forms, with or # without modification, are permitted provided that the following @@ -72,8 +72,9 @@ STOP_BITS = 1 # Verbose operation on/off VERBOSE = False -# Delay time we wait -DELAY_TIME = 0.05 +# Delay times we wait +PROC_DELAY_TIME = 0.05 +COMM_DELAY_TIME = 0.05 # Memory map. SOC = '\x55' @@ -279,22 +280,22 @@ NIST_512_SINGLE = ['\x61', '\x62', '\x63', '\x80', '\x00', '\x00', '\x00', '\x00 '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x18'] NIST_512_DOUBLE0 = ['\x61', '\x62', '\x63', '\x64', '\x62', '\x63', '\x64', '\x65', - '\x63', '\x64', '\x65', '\x66', '\x64', '\x65', '\x66', '\x67', - '\x65', '\x66', '\x67', '\x68', '\x66', '\x67', '\x68', '\x69', - '\x67', '\x68', '\x69', '\x6A', '\x68', '\x69', '\x6A', '\x6B', - '\x69', '\x6A', '\x6B', '\x6C', '\x6A', '\x6B', '\x6C', '\x6D', - '\x6B', '\x6C', '\x6D', '\x6E', '\x6C', '\x6D', '\x6E', '\x6F', - '\x6D', '\x6E', '\x6F', '\x70', '\x6E', '\x6F', '\x70', '\x71', - '\x80', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'] + '\x63', '\x64', '\x65', '\x66', '\x64', '\x65', '\x66', '\x67', + '\x65', '\x66', '\x67', '\x68', '\x66', '\x67', '\x68', '\x69', + '\x67', '\x68', '\x69', '\x6A', '\x68', '\x69', '\x6A', '\x6B', + '\x69', '\x6A', '\x6B', '\x6C', '\x6A', '\x6B', '\x6C', '\x6D', + '\x6B', '\x6C', '\x6D', '\x6E', '\x6C', '\x6D', '\x6E', '\x6F', + '\x6D', '\x6E', '\x6F', '\x70', '\x6E', '\x6F', '\x70', '\x71', + '\x80', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'] NIST_512_DOUBLE1 = ['\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x01', '\xC0'] + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x01', '\xC0'] NIST_1024_SINGLE = ['\x61', '\x62', '\x63', '\x80', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', @@ -313,6 +314,40 @@ NIST_1024_SINGLE = ['\x61', '\x62', '\x63', '\x80', '\x00', '\x00', '\x00', '\x0 '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x18'] +NIST_1024_DOUBLE0 = ['\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', + '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', '\x69', + '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', '\x69', '\x6a', + '\x64', '\x65', '\x66', '\x67', '\x68', '\x69', '\x6a', '\x6b', + '\x65', '\x66', '\x67', '\x68', '\x69', '\x6a', '\x6b', '\x6c', + '\x66', '\x67', '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', + '\x67', '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', + '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', + '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', '\x70', + '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', '\x70', '\x71', + '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', '\x70', '\x71', '\x72', + '\x6c', '\x6d', '\x6e', '\x6f', '\x70', '\x71', '\x72', '\x73', + '\x6d', '\x6e', '\x6f', '\x70', '\x71', '\x72', '\x73', '\x74', + '\x6e', '\x6f', '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', + '\x80', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'] + +NIST_1024_DOUBLE1 = ['\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x03', '\x80'] + #------------------------------------------------------------------- # print_response() @@ -373,7 +408,7 @@ def read_serial_thread(serialport): buffer = [] else: print "No open device yet." - time.sleep(DELAY_TIME) + time.sleep(COMM_DELAY_TIME) #------------------------------------------------------------------- @@ -389,7 +424,7 @@ def write_serial_bytes(tx_cmd, serialport): serialport.write(tx_byte) # Allow the device to complete the transaction. - time.sleep(DELAY_TIME) + time.sleep(COMM_DELAY_TIME) #------------------------------------------------------------------- @@ -409,9 +444,58 @@ def single_block_test_sha512x(block, mode, ser): mode_cmd = chr(ord(SHA512_CTRL_INIT_CMD) + (ord(mode) << SHA512_CTRL_MODE_LOW)) write_serial_bytes([SOC, WRITE_CMD, SHA512_ADDR_PREFIX, SHA512_ADDR_CTRL, '\x00', '\x00', '\x00', mode_cmd, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) + write_serial_bytes([SOC, READ_CMD, SHA512_ADDR_PREFIX, SHA512_ADDR_STATUS, EOC], ser) + + # Select the correct number of digest addresses to read. + if (mode == MODE_SHA_512_224): + mode_digest_addr = sha512_digest_addr[0 : 7] + elif (mode == MODE_SHA_512_256): + mode_digest_addr = sha512_digest_addr[0 : 8] + elif (mode == MODE_SHA_384): + mode_digest_addr = sha512_digest_addr[0 : 12] + elif (mode == MODE_SHA_512): + mode_digest_addr = sha512_digest_addr + + # Extract the digest. + for digest_addr in mode_digest_addr: + message = [SOC, READ_CMD, SHA512_ADDR_PREFIX] + [digest_addr] + [EOC] + write_serial_bytes(message, ser) + print"" + + +#------------------------------------------------------------------- +# dual_block_test_sha512x() +# +# Write a given block to SHA-512/x and perform single block +# processing for the given mode. +#------------------------------------------------------------------- +def dual_block_test_sha512x(block0, block1, mode, ser): + # Write block0 to SHA-512. + for i in range(len(block0) / 4): + message = [SOC, WRITE_CMD, SHA512_ADDR_PREFIX,] + [sha512_block_addr[i]] +\ + block0[(i * 4) : ((i * 4 ) + 4)] + [EOC] + write_serial_bytes(message, ser) + + # Start initial block hashing, wait and check status. + mode_cmd = chr(ord(SHA512_CTRL_INIT_CMD) + (ord(mode) << SHA512_CTRL_MODE_LOW)) + write_serial_bytes([SOC, WRITE_CMD, SHA512_ADDR_PREFIX, SHA512_ADDR_CTRL, + '\x00', '\x00', '\x00', mode_cmd, EOC], ser) + time.sleep(PROC_DELAY_TIME) + write_serial_bytes([SOC, READ_CMD, SHA512_ADDR_PREFIX, SHA512_ADDR_STATUS, EOC], ser) + + # Write block1 to SHA-512. + for i in range(len(block1) / 4): + message = [SOC, WRITE_CMD, SHA512_ADDR_PREFIX,] + [sha512_block_addr[i]] +\ + block1[(i * 4) : ((i * 4 ) + 4)] + [EOC] + write_serial_bytes(message, ser) + + # Start next block hashing, wait and check status. + mode_cmd = chr(ord(SHA512_CTRL_NEXT_CMD) + (ord(mode) << SHA512_CTRL_MODE_LOW)) + write_serial_bytes([SOC, WRITE_CMD, SHA512_ADDR_PREFIX, SHA512_ADDR_CTRL, + '\x00', '\x00', '\x00', mode_cmd, EOC], ser) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA512_ADDR_PREFIX, SHA512_ADDR_STATUS, EOC], ser) - time.sleep(DELAY_TIME) # Select the correct number of digest addresses to read. if (mode == MODE_SHA_512_224): @@ -446,7 +530,7 @@ def single_block_test_sha256(block, ser): # Start initial block hashing, wait and check status. write_serial_bytes([SOC, WRITE_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_CTRL, '\x00', '\x00', '\x00', SHA256_CTRL_INIT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_STATUS, EOC], ser) # Extract the digest. @@ -471,7 +555,7 @@ def double_block_test_sha256(block1, block2, ser): # Start initial block hashing, wait and check status. write_serial_bytes([SOC, WRITE_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_CTRL, '\x00', '\x00', '\x00', SHA256_CTRL_INIT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_STATUS, EOC], ser) # Extract the first digest. @@ -489,7 +573,7 @@ def double_block_test_sha256(block1, block2, ser): # Start next block hashing, wait and check status. write_serial_bytes([SOC, WRITE_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_CTRL, '\x00', '\x00', '\x00', SHA256_CTRL_NEXT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_STATUS, EOC], ser) # Extract the second digest. @@ -514,7 +598,7 @@ def huge_message_test_sha256(block, n, ser): # Start initial block hashing, wait. write_serial_bytes([SOC, WRITE_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_CTRL, '\x00', '\x00', '\x00', SHA256_CTRL_INIT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) print "Block 0 done." # First block done. @@ -531,14 +615,14 @@ def huge_message_test_sha256(block, n, ser): write_serial_bytes([SOC, WRITE_CMD, SHA256_ADDR_PREFIX, SHA256_ADDR_CTRL, '\x00', '\x00', '\x00', SHA256_CTRL_NEXT_CMD, EOC], ser) print "Block %d done." % (i + 1) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) # Extract the digest for the current block. for digest_addr in sha256_digest_addr: message = [SOC, READ_CMD, SHA256_ADDR_PREFIX] + [digest_addr] + [EOC] write_serial_bytes(message, ser) print"" - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) #------------------------------------------------------------------- @@ -557,7 +641,7 @@ def single_block_test_sha1(block, ser): # Start initial block hashing, wait and check status. write_serial_bytes([SOC, WRITE_CMD, SHA1_ADDR_PREFIX, SHA1_ADDR_CTRL, '\x00', '\x00', '\x00', SHA1_CTRL_INIT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA1_ADDR_PREFIX, SHA1_ADDR_STATUS, EOC], ser) # Extract the digest. @@ -582,7 +666,7 @@ def double_block_test_sha1(block1, block2, ser): # Start initial block hashing, wait and check status. write_serial_bytes([SOC, WRITE_CMD, SHA1_ADDR_PREFIX, SHA1_ADDR_CTRL, '\x00', '\x00', '\x00', SHA1_CTRL_INIT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA1_ADDR_PREFIX, SHA1_ADDR_STATUS, EOC], ser) # Extract the first digest. @@ -600,7 +684,7 @@ def double_block_test_sha1(block1, block2, ser): # Start next block hashing, wait and check status. write_serial_bytes([SOC, WRITE_CMD, SHA1_ADDR_PREFIX, SHA1_ADDR_CTRL, '\x00', '\x00', '\x00', SHA1_CTRL_NEXT_CMD, EOC], ser) - time.sleep(DELAY_TIME) + time.sleep(PROC_DELAY_TIME) write_serial_bytes([SOC, READ_CMD, SHA1_ADDR_PREFIX, SHA1_ADDR_STATUS, EOC], ser) # Extract the second digest. @@ -753,7 +837,7 @@ def tc8(ser): #------------------------------------------------------------------- -# TC9: Single block test of SHA-512 +# TC9: Single block tests of SHA-512/x # # We do this for all modes. #------------------------------------------------------------------- @@ -801,6 +885,54 @@ def tc9(ser): #------------------------------------------------------------------- +# TC10: Dual block tests of SHA-512/x +# +# We do this for all modes. +#------------------------------------------------------------------- +def tc10(ser): + print "TC9: Single block message test for SHA-512/x." + + tc10_224_expected = [0x23fec5bb, 0x94d60b23, 0x30819264, 0x0b0c4533, + 0x35d66473, 0x4fe40e72, 0x68674af9] + + tc10_256_expected = [0x3928e184, 0xfb8690f8, 0x40da3988, 0x121d31be, + 0x65cb9d3e, 0xf83ee614, 0x6feac861, 0xe19b563a] + + tc10_384_expected = [0xcb00753f, 0x45a35e8b, 0xb5a03d69, 0x9ac65007, + 0x272c32ab, 0x0eded163, 0x1a8b605a, 0x43ff5bed, + 0x8086072b, 0xa1e7cc23, 0x58baeca1, 0x34c825a7] + + tc10_512_expected = [0x8e959b75, 0xdae313da, 0x8cf4f728, 0x14fc143f, + 0x8f7779c6, 0xeb9f7fa1, 0x7299aead, 0xb6889018, + 0x501d289e, 0x4900f7e4, 0x331b99de, 0xc4b5433a, + 0xc7d329ee, 0xb6dd2654, 0x5e96e55b, 0x874be909] + + print "TC10-1: Expected digest values for SHA-512/224 as specified by NIST:" + for i in tc10_224_expected: + print("0x%08x " % i) + dual_block_test_sha512x(NIST_1024_DOUBLE0, NIST_1024_DOUBLE1, MODE_SHA_512_224, ser) + print("") + + print "TC10-2: Expected digest values for SHA-512/256 as specified by NIST:" + for i in tc10_256_expected: + print("0x%08x " % i) + dual_block_test_sha512x(NIST_1024_DOUBLE0, NIST_1024_DOUBLE1, MODE_SHA_512_256, ser) + print("") + + print "TC10-3: Expected digest values for SHA-384 as specified by NIST:" + for i in tc10_384_expected: + print("0x%08x " % i) + dual_block_test_sha512x(NIST_1024_DOUBLE0, NIST_1024_DOUBLE1, MODE_SHA_384, ser) + print("") + + print "TC10-4: Expected digest values for SHA-512 as specified by NIST:" + for i in tc10_512_expected: + print("0x%08x " % i) + dual_block_test_sha512x(NIST_1024_DOUBLE0, NIST_1024_DOUBLE1, MODE_SHA_512, ser) + print("") + + +#------------------------------------------------------------------- # main() # # Parse any arguments and run the tests. @@ -836,8 +968,8 @@ def main(): # Run the enabled test cases. tc_list = [(tc1, False), (tc2, False), (tc3, False), (tc4, False), - (tc5, False), (tc6, False), (tc7, False), (tc8, True), - (tc9, True)] + (tc5, False), (tc6, False), (tc7, False), (tc8, False), + (tc9, False), (tc10, True)] for (test_case, action) in tc_list: if action: test_case(ser) |