diff --git a/sw/device/lib/crypto/drivers/kmac.c b/sw/device/lib/crypto/drivers/kmac.c index 3f96b2705038e..46a38f5183875 100644 --- a/sw/device/lib/crypto/drivers/kmac.c +++ b/sw/device/lib/crypto/drivers/kmac.c @@ -733,7 +733,7 @@ status_t kmac_sha3_224(const uint8_t *message, size_t message_len, HARDENED_TRY(kmac_init(kKmacOperationSHA3, kKmacSecurityStrength224, /*hw_backed=*/kHardenedBoolFalse)); - size_t digest_len_words = 224 / 32; + size_t digest_len_words = kSha3_224DigestWords; return kmac_process_msg_blocks(kKmacOperationSHA3, message, message_len, digest, digest_len_words); } @@ -743,7 +743,7 @@ status_t kmac_sha3_256(const uint8_t *message, size_t message_len, HARDENED_TRY(kmac_init(kKmacOperationSHA3, kKmacSecurityStrength256, /*hw_backed=*/kHardenedBoolFalse)); - size_t digest_len_words = 256 / 32; + size_t digest_len_words = kSha3_256DigestWords; return kmac_process_msg_blocks(kKmacOperationSHA3, message, message_len, digest, digest_len_words); } @@ -753,7 +753,7 @@ status_t kmac_sha3_384(const uint8_t *message, size_t message_len, HARDENED_TRY(kmac_init(kKmacOperationSHA3, kKmacSecurityStrength384, /*hw_backed=*/kHardenedBoolFalse)); - size_t digest_len_words = 384 / 32; + size_t digest_len_words = kSha3_384DigestWords; return kmac_process_msg_blocks(kKmacOperationSHA3, message, message_len, digest, digest_len_words); } @@ -763,7 +763,7 @@ status_t kmac_sha3_512(const uint8_t *message, size_t message_len, HARDENED_TRY(kmac_init(kKmacOperationSHA3, kKmacSecurityStrength512, /*hw_backed=*/kHardenedBoolFalse)); - size_t digest_len_words = 512 / 32; + size_t digest_len_words = kSha3_512DigestWords; return kmac_process_msg_blocks(kKmacOperationSHA3, message, message_len, digest, digest_len_words); } diff --git a/sw/device/lib/crypto/drivers/kmac.h b/sw/device/lib/crypto/drivers/kmac.h index 70cbd1c03d06c..ac3ed26815f96 100644 --- a/sw/device/lib/crypto/drivers/kmac.h +++ b/sw/device/lib/crypto/drivers/kmac.h @@ -26,6 +26,22 @@ enum { // The size of the sideload key. This parameter is not exposed by KMAC or // Keymgr hjson files from HW, so we need to hardcode it for the moment. kKmacSideloadKeyLength = 256, + // Length of a SHA3-224 digest in bytes. + kSha3_224DigestBytes = 224 / 8, + // Length of a SHA3-224 digest in 32-bit words. + kSha3_224DigestWords = kSha3_224DigestBytes / sizeof(uint32_t), + // Length of a SHA3_256 digest in bytes. + kSha3_256DigestBytes = 256 / 8, + // Length of a SHA3_256 digest in 32-bit words. + kSha3_256DigestWords = kSha3_256DigestBytes / sizeof(uint32_t), + // Length of a SHA3_384 digest in bytes. + kSha3_384DigestBytes = 384 / 8, + // Length of a SHA3_384 digest in 32-bit words. + kSha3_384DigestWords = kSha3_384DigestBytes / sizeof(uint32_t), + // Length of a SHA3_512 digest in bytes. + kSha3_512DigestBytes = 512 / 8, + // Length of a SHA3_512 digest in 32-bit words. + kSha3_512DigestWords = kSha3_512DigestBytes / sizeof(uint32_t), }; /** diff --git a/sw/device/lib/crypto/impl/rsa/BUILD b/sw/device/lib/crypto/impl/rsa/BUILD index 0661010d6b495..4db9c56ee0f10 100644 --- a/sw/device/lib/crypto/impl/rsa/BUILD +++ b/sw/device/lib/crypto/impl/rsa/BUILD @@ -64,6 +64,7 @@ cc_library( "//sw/device/lib/base:hardened_memory", "//sw/device/lib/base:memory", "//sw/device/lib/crypto/drivers:entropy", + "//sw/device/lib/crypto/drivers:kmac", "//sw/device/lib/crypto/impl:hash", "//sw/device/lib/crypto/impl:status", "//sw/device/lib/crypto/impl/sha2:sha256", diff --git a/sw/device/lib/crypto/impl/rsa/rsa_padding.c b/sw/device/lib/crypto/impl/rsa/rsa_padding.c index 9c34ae2acd1d7..62210e0f82f9f 100644 --- a/sw/device/lib/crypto/impl/rsa/rsa_padding.c +++ b/sw/device/lib/crypto/impl/rsa/rsa_padding.c @@ -8,6 +8,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/base/math.h" #include "sw/device/lib/crypto/drivers/entropy.h" +#include "sw/device/lib/crypto/drivers/kmac.h" #include "sw/device/lib/crypto/impl/sha2/sha256.h" #include "sw/device/lib/crypto/impl/sha2/sha512.h" #include "sw/device/lib/crypto/include/hash.h" @@ -32,6 +33,27 @@ static const uint8_t kSha512DigestIdentifier[] = { 0x40, 0x04, 0x00, 0x05, 0x03, 0x02, 0x04, 0x03, 0x65, 0x01, 0x48, 0x86, 0x60, 0x09, 0x06, 0x0d, 0x30, 0x51, 0x30, }; +/* + * SHA-3 digest identifiers adapted from the SHA-2 identifers based on the + * algorithm identifiers on + * https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration + */ +static const uint8_t kSha3_224DigestIdentifier[] = { + 0x1c, 0x04, 0x00, 0x05, 0x07, 0x02, 0x04, 0x03, 0x65, 0x01, + 0x48, 0x86, 0x60, 0x09, 0x06, 0x0d, 0x30, 0x2d, 0x30, +}; +static const uint8_t kSha3_256DigestIdentifier[] = { + 0x20, 0x04, 0x00, 0x05, 0x08, 0x02, 0x04, 0x03, 0x65, 0x01, + 0x48, 0x86, 0x60, 0x09, 0x06, 0x0d, 0x30, 0x31, 0x30, +}; +static const uint8_t kSha3_384DigestIdentifier[] = { + 0x30, 0x04, 0x00, 0x05, 0x09, 0x02, 0x04, 0x03, 0x65, 0x01, + 0x48, 0x86, 0x60, 0x09, 0x06, 0x0d, 0x30, 0x41, 0x30, +}; +static const uint8_t kSha3_512DigestIdentifier[] = { + 0x40, 0x04, 0x00, 0x05, 0x0a, 0x02, 0x04, 0x03, 0x65, 0x01, + 0x48, 0x86, 0x60, 0x09, 0x06, 0x0d, 0x30, 0x51, 0x30, +}; /** * Get the length of the DER encoding for the given hash function's digests. @@ -56,6 +78,18 @@ static status_t digest_info_length_get(const otcrypto_hash_mode_t hash_mode, case kOtcryptoHashModeSha512: *len = sizeof(kSha512DigestIdentifier) + kSha512DigestBytes; return OTCRYPTO_OK; + case kOtcryptoHashModeSha3_224: + *len = sizeof(kSha3_224DigestIdentifier) + kSha3_224DigestBytes; + return OTCRYPTO_OK; + case kOtcryptoHashModeSha3_256: + *len = sizeof(kSha3_256DigestIdentifier) + kSha3_256DigestBytes; + return OTCRYPTO_OK; + case kOtcryptoHashModeSha3_384: + *len = sizeof(kSha3_384DigestIdentifier) + kSha3_384DigestBytes; + return OTCRYPTO_OK; + case kOtcryptoHashModeSha3_512: + *len = sizeof(kSha512DigestIdentifier) + kSha3_512DigestBytes; + return OTCRYPTO_OK; default: // Unsupported or unrecognized hash function. return OTCRYPTO_BAD_ARGS; @@ -106,17 +140,45 @@ static status_t digest_info_write(const otcrypto_hash_digest_t message_digest, memcpy(encoding + kSha512DigestWords, &kSha512DigestIdentifier, sizeof(kSha512DigestIdentifier)); break; + case kOtcryptoHashModeSha3_224: + if (message_digest.len != kSha3_224DigestWords) { + return OTCRYPTO_BAD_ARGS; + } + memcpy(encoding + kSha3_224DigestWords, &kSha3_224DigestIdentifier, + sizeof(kSha3_224DigestIdentifier)); + break; + case kOtcryptoHashModeSha3_256: + if (message_digest.len != kSha3_256DigestWords) { + return OTCRYPTO_BAD_ARGS; + } + memcpy(encoding + kSha3_256DigestWords, &kSha3_256DigestIdentifier, + sizeof(kSha3_256DigestIdentifier)); + break; + case kOtcryptoHashModeSha3_384: + if (message_digest.len != kSha3_384DigestWords) { + return OTCRYPTO_BAD_ARGS; + } + memcpy(encoding + kSha3_384DigestWords, &kSha3_384DigestIdentifier, + sizeof(kSha3_384DigestIdentifier)); + break; + case kOtcryptoHashModeSha3_512: + if (message_digest.len != kSha3_512DigestWords) { + return OTCRYPTO_BAD_ARGS; + } + memcpy(encoding + kSha3_512DigestWords, &kSha3_512DigestIdentifier, + sizeof(kSha3_512DigestIdentifier)); + break; default: // Unsupported or unrecognized hash function. return OTCRYPTO_BAD_ARGS; }; // Copy the digest into the encoding, reversing the order of bytes. - for (size_t i = 0; i < message_digest.len / 2; i++) { - uint32_t tmp = __builtin_bswap32(message_digest.data[i]); + for (size_t i = 0; i < ceil_div(message_digest.len, 2); i++) { encoding[i] = __builtin_bswap32(message_digest.data[message_digest.len - 1 - i]); - encoding[message_digest.len - 1 - i] = tmp; + encoding[message_digest.len - 1 - i] = + __builtin_bswap32(message_digest.data[i]); } return OTCRYPTO_OK; @@ -145,7 +207,6 @@ status_t rsa_padding_pkcs1v15_encode( // specifies that the 0xff padding must be at least 8 octets. return OTCRYPTO_BAD_ARGS; } - // Write the digest info to the start of the buffer. HARDENED_TRY(digest_info_write(message_digest, encoded_message)); @@ -163,7 +224,6 @@ status_t rsa_padding_pkcs1v15_verify( uint32_t expected_encoded_message[encoded_message_len]; HARDENED_TRY(rsa_padding_pkcs1v15_encode(message_digest, encoded_message_len, expected_encoded_message)); - // Compare with the expected value. *result = hardened_memeq(encoded_message, expected_encoded_message, ARRAYSIZE(expected_encoded_message));