Skip to content

Commit

Permalink
[crypto] Support SHA-3 hashes in RSA PKCS#1 v1.5 padding mode
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Torok <[email protected]>
  • Loading branch information
RyanTorok authored and milesdai committed Feb 23, 2024
1 parent baed49a commit 92403e6
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 9 deletions.
8 changes: 4 additions & 4 deletions sw/device/lib/crypto/drivers/kmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down
16 changes: 16 additions & 0 deletions sw/device/lib/crypto/drivers/kmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};

/**
Expand Down
1 change: 1 addition & 0 deletions sw/device/lib/crypto/impl/rsa/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
70 changes: 65 additions & 5 deletions sw/device/lib/crypto/impl/rsa/rsa_padding.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));

Expand All @@ -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));
Expand Down

0 comments on commit 92403e6

Please sign in to comment.