From f691cd1936b5f46ec89fc8bcd6af238b687f9628 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 27 Sep 2026 13:34:11 -0400 Subject: [PATCH] Change `--protect` to use SHA512 per IEEE 1735. --- Changes | 1 + src/V3EmitCBase.cpp | 4 +- src/V3EmitCImp.cpp | 2 +- src/V3File.cpp | 8 +- src/V3HierBlock.cpp | 4 +- src/V3Options.cpp | 2 +- src/V3Param.cpp | 6 +- src/V3String.cpp | 212 +++++++++++------- src/V3String.h | 39 ++-- src/Verilator.cpp | 2 +- .../t/t_constraint_unsat_protect_ids.out | 20 +- test_regress/t/t_inst_long_bad.out | 2 +- test_regress/t/t_protect_ids_key.out | 118 +++++----- test_regress/t/t_vpi_escape.cpp | 3 +- 14 files changed, 231 insertions(+), 192 deletions(-) diff --git a/Changes b/Changes index 4bb8d089a..684a0320f 100644 --- a/Changes +++ b/Changes @@ -22,6 +22,7 @@ Verilator 5.053 devel * Remove deprecated `--structs-packed`. * Change internal module inlining to after V3Scope (#1539) (#8453). [Geza Lore, Testorrent USA, Inc.] * Change JSON dumps to suppress empty strings, etc. +* Change `--protect` to use SHA512 per IEEE 1735. * Support multi-dimensional module instance arrays (#2675) (#8476). [Geza Lore, Testorrent USA, Inc.] * Support VPI interface references (#8081). [Todd Strader] * Support nested array and associative array element member access in constraint 1/4 - pre-cleanup (#8237). [Kamil Danecki, Antmicro Ltd.] diff --git a/src/V3EmitCBase.cpp b/src/V3EmitCBase.cpp index 300d770f5..cdd283a44 100644 --- a/src/V3EmitCBase.cpp +++ b/src/V3EmitCBase.cpp @@ -65,8 +65,8 @@ string EmitCUtil::prefixNameProtect(const AstNode* nodep) VL_MT_STABLE { } else if (it->second == prefix) { result = prefix; // Same capitialization as last time } else { - VHashSha256 hash{prefix}; - result = prefix + "__Vphsh" + hash.digestSymbol(); + VHashSha512 hash{prefix}; + result = prefix + "__Vphsh" + hash.digestSymbol24(); } } s_memoized.emplace(prefix, result); diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 7e2b3aca2..2435df499 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -284,7 +284,7 @@ class EmitCImp final : public EmitCFunc { // Place a computed checksum to ensure proper structure save/restore formatting // OK if this hash includes some things we won't dump, since // just looking for loading the wrong model - VHashSha256 hash; + VHashSha512 hash; for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (const AstVar* const varp = VN_CAST(nodep, Var)) { hash.insert(varp->name()); diff --git a/src/V3File.cpp b/src/V3File.cpp index 5ae649faa..6481360b3 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -73,7 +73,7 @@ class V3FileDependImp final { bool m_exists = true; // File exists const string m_filename; // Filename struct stat m_stat; // Stat information - VHashSha256 m_hash; // SHA hash of file contents + VHashSha512 m_hash; // SHA hash of file contents public: DependFile(const string& filename, bool target) : m_target{target} @@ -92,7 +92,7 @@ class V3FileDependImp final { time_t mstime() const { return m_stat.st_mtime; } // Seconds time_t mnstime() const { return VL_STAT_MTIME_NSEC(m_stat); } // Nanoseconds string hashDigestSymbol() { - static VHashSha256 s_emptyHash; + static VHashSha512 s_emptyHash; return m_hash.digestSymbol() != s_emptyHash.digestSymbol() ? m_hash.digestSymbol() : "unhashed"; } @@ -310,7 +310,7 @@ bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn // as unlikely to find a match and can be large if (chkHash == "unhashed") return false; - VHashSha256 curHash; + VHashSha512 curHash; curHash.insertFile(chkFilename); if (curHash.digestSymbol() != chkHash) { UINFO(2, " --check-times: hash differs " @@ -1077,7 +1077,7 @@ public: // missing a protect() out = "PS" + old; } else { - VHashSha256 digest{v3Global.opt.protectKeyDefaulted()}; + VHashSha512 digest{v3Global.opt.protectKeyDefaulted()}; digest.insert(old); // Add "PS" prefix (Protect Symbols) as cannot start symbol with number out = "PS" + digest.digestSymbol(); diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index d311de048..0bb96054c 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -281,8 +281,8 @@ string V3HierBlock::typeParametersFilename() const { void V3HierBlock::writeParametersFile() const { if (m_typeParams.empty()) return; - VHashSha256 hash{"type params"}; - const string moduleName = "Vhsh" + hash.digestSymbol(); + VHashSha512 hash{"type params"}; + const string moduleName = "Vhsh" + hash.digestSymbol24(); const std::unique_ptr of{V3File::new_ofstream(typeParametersFilename())}; *of << "module " << moduleName << ";\n"; for (AstParamTypeDType* const gparam : m_typeParams) { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index e23f1f2c7..45c8bec3e 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1110,7 +1110,7 @@ string V3Options::protectKeyDefaulted() VL_MT_SAFE { if (m_protectKey.empty()) { // Create a key with a human-readable symbol-like name. // This conversion drops ~2 bits of entropy out of 256, shouldn't matter. - VHashSha256 digest{V3Os::trueRandom(32)}; + VHashSha512 digest{V3Os::trueRandom(64)}; m_protectKey = "VL-KEY-" + digest.digestSymbol(); } return m_protectKey; diff --git a/src/V3Param.cpp b/src/V3Param.cpp index af9781dff..5ac176f92 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -684,13 +684,13 @@ class ParamProcessor final { const auto iter = m_longMap.find(longname); if (iter != m_longMap.end()) return iter->second; // Already calculated - VHashSha256 hash; + VHashSha512 hash; // Calculate hash using longname // The hash is used as the module suffix to find a module name that is unique in the design hash.insert(longname); while (true) { - // Copy VHashSha256 just in case of hash collision - VHashSha256 hashStrGen = hash; + // Copy VHashSha512 just in case of hash collision + VHashSha512 hashStrGen = hash; // Hex string must be a safe suffix for any symbol const string hashStr = hashStrGen.digestHex(); for (string::size_type i = 1; i < hashStr.size(); ++i) { diff --git a/src/V3String.cpp b/src/V3String.cpp index bb2625b7f..983b502ca 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -398,53 +398,63 @@ uint64_t VString::hashMurmur(const string& str) VL_PURE { void VString::selfTest() { UASSERT_SELFTEST(VString::replaceSubstr("aa", "a", "ba"), "baba"); } //###################################################################### -// VHashSha256 +// VHashSha512 -static const uint32_t sha256K[] - = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, - 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, - 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, - 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, - 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, - 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, - 0xc67178f2}; +static const uint64_t sha512K[] + = {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL}; VL_ATTR_ALWINLINE -static uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) VL_PURE { - return lhs >> rhs | lhs << (32 - rhs); +static uint64_t shaRotr64(uint64_t lhs, uint64_t rhs) VL_PURE { + return lhs >> rhs | lhs << (64 - rhs); } VL_ATTR_ALWINLINE -static void sha256Block(uint32_t* h, const uint32_t* chunk) VL_PURE { - uint32_t ah[8]; - const uint32_t* p = chunk; +static void sha512Block(uint64_t* h, const uint64_t* chunk) VL_PURE { + uint64_t ah[8]; + const uint64_t* p = chunk; // Initialize working variables to current hash value for (unsigned i = 0; i < 8; i++) ah[i] = h[i]; // Compression function main loop - uint32_t w[16] = {}; - for (unsigned i = 0; i < 4; ++i) { + uint64_t w[16] = {}; + for (unsigned i = 0; i < 5; ++i) { for (unsigned j = 0; j < 16; ++j) { if (i == 0) { w[j] = *p++; } else { // Extend the first 16 words into the remaining - // 48 words w[16..63] of the message schedule array: - const uint32_t s0 = shaRotr32(w[(j + 1) & 0xf], 7) - ^ shaRotr32(w[(j + 1) & 0xf], 18) ^ (w[(j + 1) & 0xf] >> 3); - const uint32_t s1 = shaRotr32(w[(j + 14) & 0xf], 17) - ^ shaRotr32(w[(j + 14) & 0xf], 19) ^ (w[(j + 14) & 0xf] >> 10); + // 64 words w[16..79] of the message schedule array: + const uint64_t s0 = shaRotr64(w[(j + 1) & 0xf], 1) ^ shaRotr64(w[(j + 1) & 0xf], 8) + ^ (w[(j + 1) & 0xf] >> 7); + const uint64_t s1 = shaRotr64(w[(j + 14) & 0xf], 19) + ^ shaRotr64(w[(j + 14) & 0xf], 61) ^ (w[(j + 14) & 0xf] >> 6); w[j] = w[j] + s0 + w[(j + 9) & 0xf] + s1; } - const uint32_t s1 = shaRotr32(ah[4], 6) ^ shaRotr32(ah[4], 11) ^ shaRotr32(ah[4], 25); - const uint32_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]); - const uint32_t temp1 = ah[7] + s1 + ch + sha256K[i << 4 | j] + w[j]; - const uint32_t s0 = shaRotr32(ah[0], 2) ^ shaRotr32(ah[0], 13) ^ shaRotr32(ah[0], 22); - const uint32_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]); - const uint32_t temp2 = s0 + maj; + const uint64_t s1 = shaRotr64(ah[4], 14) ^ shaRotr64(ah[4], 18) ^ shaRotr64(ah[4], 41); + const uint64_t ch = (ah[4] & ah[5]) ^ (~ah[4] & ah[6]); + const uint64_t temp1 = ah[7] + s1 + ch + sha512K[i * 16 + j] + w[j]; + const uint64_t s0 = shaRotr64(ah[0], 28) ^ shaRotr64(ah[0], 34) ^ shaRotr64(ah[0], 39); + const uint64_t maj = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]); + const uint64_t temp2 = s0 + maj; ah[7] = ah[6]; ah[6] = ah[5]; @@ -459,8 +469,8 @@ static void sha256Block(uint32_t* h, const uint32_t* chunk) VL_PURE { for (unsigned i = 0; i < 8; ++i) h[i] += ah[i]; } -void VHashSha256::insert(const void* datap, size_t length) { - UASSERT(!m_final, "Called VHashSha256::insert after finalized the hash value"); +void VHashSha512::insert(const void* datap, size_t length) { + UASSERT(!m_final, "Called VHashSha512::insert after finalized the hash value"); m_totLength += length; string tempData; @@ -478,28 +488,32 @@ void VHashSha256::insert(const void* datap, size_t length) { chunkp = reinterpret_cast(tempData.data()); } - // See wikipedia SHA-1 algorithm summary - uint32_t w[64]; // Round buffer, [0..15] are input data, rest used by rounds + // See wikipedia SHA-2 algorithm summary + uint64_t w[80]; // Round buffer, [0..15] are input data, rest used by rounds int posBegin = 0; // Position in buffer for start of this block int posEnd = 0; // Position in buffer for end of this block - // Process complete 64-byte blocks - while (posBegin <= chunkLen - 64) { - posEnd = posBegin + 64; - // 64 byte round input data, being careful to swap on big, keep on little - for (int roundByte = 0; posBegin < posEnd; posBegin += 4) { - w[roundByte++] = (static_cast(chunkp[posBegin + 3]) - | (static_cast(chunkp[posBegin + 2]) << 8) - | (static_cast(chunkp[posBegin + 1]) << 16) - | (static_cast(chunkp[posBegin]) << 24)); + // Process complete 128-byte blocks + while (posBegin <= chunkLen - 128) { + posEnd = posBegin + 128; + // 128 byte round input data, being careful to swap on big, keep on little + for (int roundByte = 0; posBegin < posEnd; posBegin += 8) { + w[roundByte++] = (static_cast(chunkp[posBegin + 7]) + | (static_cast(chunkp[posBegin + 6]) << 8) + | (static_cast(chunkp[posBegin + 5]) << 16) + | (static_cast(chunkp[posBegin + 4]) << 24) + | (static_cast(chunkp[posBegin + 3]) << 32) + | (static_cast(chunkp[posBegin + 2]) << 40) + | (static_cast(chunkp[posBegin + 1]) << 48) + | (static_cast(chunkp[posBegin]) << 56)); } - sha256Block(m_inthash, w); + sha512Block(m_inthash, w); } m_remainder = std::string(reinterpret_cast(chunkp + posBegin), chunkLen - posEnd); } -void VHashSha256::insertFile(const string& filename) { +void VHashSha512::insertFile(const string& filename) { static const size_t BUFFER_SIZE = 64 * 1024; const int fd = ::open(filename.c_str(), O_RDONLY); @@ -513,43 +527,46 @@ void VHashSha256::insertFile(const string& filename) { ::close(fd); } -void VHashSha256::finalize() { +void VHashSha512::finalize() { if (!m_final) { - // Make sure no 64 byte blocks left + // Make sure no 128 byte blocks left insert(""); m_final = true; - // Process final possibly non-complete 64-byte block - uint32_t w[16]; // Round buffer, [0..15] are input data + // Process final possibly non-complete 128-byte block + uint64_t w[16]; // Round buffer, [0..15] are input data for (int i = 0; i < 16; ++i) w[i] = 0; size_t blockPos = 0; for (; blockPos < m_remainder.length(); ++blockPos) { - w[blockPos >> 2] - |= ((static_cast(m_remainder[blockPos])) << ((3 - (blockPos & 3)) << 3)); + w[blockPos >> 3] + |= ((static_cast(static_cast(m_remainder[blockPos]))) + << ((7 - (blockPos & 7)) << 3)); } - w[blockPos >> 2] |= 0x80 << ((3 - (blockPos & 3)) << 3); - if (m_remainder.length() >= 56) { - sha256Block(m_inthash, w); + w[blockPos >> 3] |= static_cast(0x80) << ((7 - (blockPos & 7)) << 3); + if (m_remainder.length() >= 112) { + sha512Block(m_inthash, w); for (int i = 0; i < 16; ++i) w[i] = 0; } + // Only supporting 2^61 bytes max + w[14] = 0; w[15] = m_totLength << 3; - sha256Block(m_inthash, w); + sha512Block(m_inthash, w); m_remainder.clear(); } } -string VHashSha256::digestBinary() { +string VHashSha512::digestBinary() { finalize(); string result; - result.reserve(32); - for (size_t i = 0; i < 32; ++i) { - result += (m_inthash[i >> 2] >> (((3 - i) & 0x3) << 3)) & 0xff; + result.reserve(64); + for (size_t i = 0; i < 64; ++i) { + result += static_cast((m_inthash[i >> 3] >> (((7 - i) & 0x7) << 3)) & 0xff); } return result; } -uint64_t VHashSha256::digestUInt64() { +uint64_t VHashSha512::digestUInt64() { const string& binhash = digestBinary(); uint64_t result = 0; for (size_t byte = 0; byte < sizeof(uint64_t); ++byte) { @@ -559,19 +576,19 @@ uint64_t VHashSha256::digestUInt64() { return result; } -string VHashSha256::digestHex() { +string VHashSha512::digestHex() { static const char* const digits = "0123456789abcdef"; const string& binhash = digestBinary(); string result; - result.reserve(70); - for (size_t byte = 0; byte < 32; ++byte) { + result.reserve(128); + for (size_t byte = 0; byte < 64; ++byte) { result += digits[(binhash[byte] >> 4) & 0xf]; result += digits[(binhash[byte] >> 0) & 0xf]; } return result; } -string VHashSha256::digestSymbol() { +string VHashSha512::digestSymbol() { // Make a symbol name from hash. Similar to base64, however base 64 // has + and / for last two digits, but need C symbol, and we also // avoid conflicts with use of _, so use "AB" at the end. @@ -580,9 +597,9 @@ string VHashSha256::digestSymbol() { = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"; const string& binhash = digestBinary(); string result; - result.reserve(28); + result.reserve(84); int pos = 0; - for (; pos < (256 / 8) - 2; pos += 3) { + for (; pos < (512 / 8) - 2; pos += 3) { result += digits[((binhash[pos] >> 2) & 0x3f)]; result += digits[((binhash[pos] & 0x3) << 4) | (static_cast(binhash[pos + 1] & 0xf0) >> 4)]; @@ -594,9 +611,11 @@ string VHashSha256::digestSymbol() { return result; } -void VHashSha256::selfTestOne(const string& data, const string& data2, const string& exp, +string VHashSha512::digestSymbol24() { return digestSymbol().substr(0, 24); } + +void VHashSha512::selfTestOne(const string& data, const string& data2, const string& exp, const string& exp64) { - VHashSha256 digest{data}; + VHashSha512 digest{data}; if (data2 != "") digest.insert(data2); if (VL_UNCOVERABLE(digest.digestHex() != exp)) { std::cerr << "%Error: When hashing '" << data + data2 << "'\n" // LCOV_EXCL_LINE @@ -610,23 +629,42 @@ void VHashSha256::selfTestOne(const string& data, const string& data2, const str } } -void VHashSha256::selfTest() { - selfTestOne("", "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "47DEQpj8HBSaABTImWA5JCeuQeRkm5NMpJWZG3hS"); - selfTestOne("a", "", "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", - "ypeBEsobvcr6wjGzmiPcTaeG7BgUfE5yuYB3haBu"); - selfTestOne("The quick brown fox jumps over the lazy dog", "", - "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", - "16j7swfXgJRpypq8sAguT41WUeRtPNt2LQLQvzfJ"); - selfTestOne("The quick brown fox jumps over the lazy", " dog", - "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", - "16j7swfXgJRpypq8sAguT41WUeRtPNt2LQLQvzfJ"); - selfTestOne("Test using larger than block-size key and larger than one block-size data", "", - "9dc35674a024b28e8440080b5331652e985f2d61d7a1fca80a648b7f9ffa0dd3", - "ncNWdKAkso6EQAgLUzFlLphfLWHXofyoCmSLf5B6"); - selfTestOne("Test using", " larger than block-size key and larger than one block-size data", - "9dc35674a024b28e8440080b5331652e985f2d61d7a1fca80a648b7f9ffa0dd3", - "ncNWdKAkso6EQAgLUzFlLphfLWHXofyoCmSLf5B6"); +void VHashSha512::selfTest() { + // Cross-checked with sha512sum + selfTestOne( + "", "", + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcgBSpIdNs6c5H0NE8XYXysPADGNKHfuwvY7kxvUdBeoGlODJ6ASfa"); + selfTestOne( + "a", "", + "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f53" + "02860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", + "H0D8ktokFpR1CXnubPWC8tXX0o4YM13gWrxU0FYOD1MChgxlKBCNVgJSql50IQVG82n7u86MEsBHlXsmUv6a"); + selfTestOne( + "The quick brown fox jumps over the lazy dog", "", + "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64" + "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", + "BAVH2VhvanP3P7rAQ17XaVEhj7fQyNeIownXhUNru2Quk6JSqVTyORJUfR6KO17W4bBXCXghIzAgU489uFTA"); + selfTestOne( + "The quick brown fox jumps over the lazy", " dog", + "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64" + "2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", + "BAVH2VhvanP3P7rAQ17XaVEhj7fQyNeIownXhUNru2Quk6JSqVTyORJUfR6KO17W4bBXCXghIzAgU489uFTA"); + selfTestOne( + "Test using larger than block-size key and larger than one block-size data." + " SHA512 has a 128 byte block size so this needs to be more than 128 characters long.", + "", + "6f51a6ddad3a86fccd8d1d6584712567ee60b00d6d31bfecb69b0e288f45fbbd" + "91b785c218f1e7c019088ad9f47680a93720bada029294dd7a7fb8119137dbf1", + "b1Gm3a06hvzNjR1lhHElZA5gsA1tMbBstpsOKI9FA72Rt4XCGPHnwBkIitn0doCpNyC62gKSlN16f7gRkTfb"); + selfTestOne( + "Test using", + " larger than block-size key and larger than one block-size data." + " SHA512 has a 128 byte block size so this needs to be more than 128 characters long.", + "6f51a6ddad3a86fccd8d1d6584712567ee60b00d6d31bfecb69b0e288f45fbbd" + "91b785c218f1e7c019088ad9f47680a93720bada029294dd7a7fb8119137dbf1", + "b1Gm3a06hvzNjR1lhHElZA5gsA1tMbBstpsOKI9FA72Rt4XCGPHnwBkIitn0doCpNyC62gKSlN16f7gRkTfb"); } //###################################################################### @@ -686,8 +724,8 @@ string VName::hashedName() { m_hashed = m_name; return m_hashed; } - VHashSha256 hash{m_name}; - const string suffix = "__Vhsh" + hash.digestSymbol(); + VHashSha512 hash{m_name}; + const string suffix = "__Vhsh" + hash.digestSymbol24(); if (s_minLength < s_maxLength) { // Keep a prefix from the original name // Backup over digits so adding __Vhash doesn't look like a encoded hex digit diff --git a/src/V3String.h b/src/V3String.h index 2945ef933..2e8ab74df 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -144,41 +144,42 @@ public: }; //###################################################################### -// VHashSha256 - Compute Sha256 hashes +// VHashSha512 - Compute Sha512 hashes -class VHashSha256 final { - // As blocks must be processed in 64 byte chunks, this does not at present - // support calling input() on multiple non-64B chunks and getting the correct +class VHashSha512 final { + // As blocks must be processed in 128 byte chunks, this does not at present + // support calling input() on multiple non-128B chunks and getting the correct // hash. To do that first combine the string before calling here. - // Or improve to store 0-63 bytes of data between calls to input(). + // Or improve to store 0-127 bytes of data between calls to input(). // MEMBERS - uint32_t m_inthash[8]; // Intermediate hash, in host order + uint64_t m_inthash[8]; // Intermediate hash, in host order string m_remainder; // Unhashed data size_t m_totLength = 0; // Total all-chunk length as needed by output digest bool m_final = false; // Finalized public: // CONSTRUCTORS - VHashSha256() { - m_inthash[0] = 0x6a09e667; - m_inthash[1] = 0xbb67ae85; - m_inthash[2] = 0x3c6ef372; - m_inthash[3] = 0xa54ff53a; - m_inthash[4] = 0x510e527f; - m_inthash[5] = 0x9b05688c; - m_inthash[6] = 0x1f83d9ab; - m_inthash[7] = 0x5be0cd19; + VHashSha512() { + m_inthash[0] = 0x6a09e667f3bcc908ULL; + m_inthash[1] = 0xbb67ae8584caa73bULL; + m_inthash[2] = 0x3c6ef372fe94f82bULL; + m_inthash[3] = 0xa54ff53a5f1d36f1ULL; + m_inthash[4] = 0x510e527fade682d1ULL; + m_inthash[5] = 0x9b05688c2b3e6c1fULL; + m_inthash[6] = 0x1f83d9abfb41bd6bULL; + m_inthash[7] = 0x5be0cd19137e2179ULL; } - explicit VHashSha256(const string& data) - : VHashSha256{} { + explicit VHashSha512(const string& data) + : VHashSha512{} { insert(data); } - ~VHashSha256() = default; + ~VHashSha512() = default; // METHODS - string digestBinary(); // Return digest as 32 character binary + string digestBinary(); // Return digest as 64 character binary string digestHex(); // Return digest formatted as a hex string string digestSymbol(); // Return digest formatted as C symbol/base64ish + string digestSymbol24(); // Return short formatted as C symbol/base64ish uint64_t digestUInt64(); // Return 64-bits of digest static void selfTest(); // Test this class diff --git a/src/Verilator.cpp b/src/Verilator.cpp index ee6f82889..4e572069e 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -725,7 +725,7 @@ static bool verilate(const string& argString) { V3Os::selfTest(); V3Number::selfTest(); VString::selfTest(); - VHashSha256::selfTest(); + VHashSha512::selfTest(); VSpellCheck::selfTest(); V3Graph::selfTest(); V3ExecGraph::selfTest(); diff --git a/test_regress/t/t_constraint_unsat_protect_ids.out b/test_regress/t/t_constraint_unsat_protect_ids.out index 0b458dbfd..4309333ec 100644 --- a/test_regress/t/t_constraint_unsat_protect_ids.out +++ b/test_regress/t/t_constraint_unsat_protect_ids.out @@ -2,27 +2,27 @@ === Test 1: Valid constraints === === Test 2: addr out of range === -%Warning-UNSATCONSTR: PSTByA:11: Unsatisfied constraint -%Warning-UNSATCONSTR: PSTByA:16: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:11: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:16: Unsatisfied constraint Randomization failed. === Test 3: data out of range (too small) === -%Warning-UNSATCONSTR: PSTByA:12: Unsatisfied constraint -%Warning-UNSATCONSTR: PSTByA:16: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:12: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:16: Unsatisfied constraint Randomization failed. === Test 4: data out of range (too large) === -%Warning-UNSATCONSTR: PSTByA:12: Unsatisfied constraint -%Warning-UNSATCONSTR: PSTByA:16: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:12: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:16: Unsatisfied constraint Randomization failed. === Test 5: Both constraints violated === -%Warning-UNSATCONSTR: PSTByA:11: Unsatisfied constraint -%Warning-UNSATCONSTR: PSTByA:16: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:11: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:16: Unsatisfied constraint Randomization failed. === Test 6: Conflicting constraints (x > 100 && x < 50) === -%Warning-UNSATCONSTR: PSTByA:26: Unsatisfied constraint -%Warning-UNSATCONSTR: PSTByA:27: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:26: Unsatisfied constraint +%Warning-UNSATCONSTR: PSkxop:27: Unsatisfied constraint Expected failure: conflicting constraints detected *-* All Finished *-* diff --git a/test_regress/t/t_inst_long_bad.out b/test_regress/t/t_inst_long_bad.out index c903f6b35..8691da49d 100644 --- a/test_regress/t/t_inst_long_bad.out +++ b/test_regress/t/t_inst_long_bad.out @@ -1,4 +1,4 @@ -%Error-MODMISSING: t/t_inst_long_bad.v:9:3: Cannot find file containing module: 'long_long_long_long_long_long___Vhsh1JZCXQVBM1QiASYlLmgTuAXYyUr7VAbJYwVHfiAD' +%Error-MODMISSING: t/t_inst_long_bad.v:9:3: Cannot find file containing module: 'long_long_long_long_long_long___VhshbdSViRR8S4x6XATcfr3tXZd7' 9 | long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_long_ inst (); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ... For error description see https://verilator.org/warn/MODMISSING?v=latest diff --git a/test_regress/t/t_protect_ids_key.out b/test_regress/t/t_protect_ids_key.out index fed5d3d6b..f46726ea2 100644 --- a/test_regress/t/t_protect_ids_key.out +++ b/test_regress/t/t_protect_ids_key.out @@ -2,66 +2,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/test_regress/t/t_vpi_escape.cpp b/test_regress/t/t_vpi_escape.cpp index bd40dfc5d..0b05a1a61 100644 --- a/test_regress/t/t_vpi_escape.cpp +++ b/test_regress/t/t_vpi_escape.cpp @@ -152,8 +152,7 @@ int _mon_check_iter() { TEST_CHECK_CSTR(p, "\\mod.with_dot "); if (TestSimulator::is_verilator()) { p = vpi_get_str(vpiDefName, vh2); - TEST_CHECK_CSTR( - p, "sub_with_very___05Fvery_____VhshsmH6BYHIAHq4mnPF8T3lXnhhONMT1I4ouBvkJk58"); + TEST_CHECK_CSTR(p, "sub_with_very___05Fvery_____Vhsh94SWWRp3oTE09HFOL6AM09dz"); } TestVpiHandle vh_null_name = my_vpi_handle("___0_");