| // Copyright lowRISC contributors. | |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| // SPDX-License-Identifier: Apache-2.0 | |
| #include "sw/device/lib/crypto/include/hash.h" | |
| #include <stdbool.h> | |
| #include "sw/device/lib/crypto/drivers/kmac.h" | |
| /** | |
| * Return the digest size (in bytes) for given hashing mode. | |
| * | |
| * @param hash_mode Hashing mode (e.g. kHashModeSha256). | |
| * @param digest_len Result digest size in bytes. | |
| * @return Error status. | |
| */ | |
| OT_WARN_UNUSED_RESULT | |
| static crypto_status_t get_digest_size(hash_mode_t hash_mode, | |
| size_t *digest_len) { | |
| if (digest_len == NULL) { | |
| return kCryptoStatusBadArgs; | |
| } | |
| // Below `digest_len` is in bytes, therefore magic values are obtained | |
| // after division by 8. | |
| switch (hash_mode) { | |
| case kHashModeSha3_224: | |
| *digest_len = 224 / 8; | |
| break; | |
| case kHashModeSha256: | |
| OT_FALLTHROUGH_INTENDED; | |
| case kHashModeSha3_256: | |
| *digest_len = 256 / 8; | |
| break; | |
| case kHashModeSha384: | |
| OT_FALLTHROUGH_INTENDED; | |
| case kHashModeSha3_384: | |
| *digest_len = 384 / 8; | |
| break; | |
| case kHashModeSha512: | |
| OT_FALLTHROUGH_INTENDED; | |
| case kHashModeSha3_512: | |
| *digest_len = 512 / 8; | |
| break; | |
| default: | |
| return kCryptoStatusBadArgs; | |
| } | |
| return kCryptoStatusOK; | |
| } | |
| OT_WARN_UNUSED_RESULT | |
| crypto_status_t otcrypto_hash(crypto_const_uint8_buf_t input_message, | |
| hash_mode_t hash_mode, | |
| crypto_uint8_buf_t *digest) { | |
| if (input_message.data == NULL && input_message.len != 0) { | |
| return kCryptoStatusBadArgs; | |
| } else if (digest->data == NULL) { | |
| return kCryptoStatusBadArgs; | |
| } | |
| // Check `digest->len` is consistent with `hash_mode` | |
| size_t expected_digest_len; | |
| crypto_status_t err_status = get_digest_size(hash_mode, &expected_digest_len); | |
| if (err_status != kCryptoStatusOK) { | |
| return err_status; | |
| } else if (expected_digest_len != digest->len) { | |
| return kCryptoStatusBadArgs; | |
| } | |
| kmac_error_t err = kKmacOk; | |
| switch (hash_mode) { | |
| case kHashModeSha3_224: | |
| err = kmac_sha3_224(input_message, digest); | |
| break; | |
| case kHashModeSha3_256: | |
| err = kmac_sha3_256(input_message, digest); | |
| break; | |
| case kHashModeSha3_384: | |
| err = kmac_sha3_384(input_message, digest); | |
| break; | |
| case kHashModeSha3_512: | |
| err = kmac_sha3_512(input_message, digest); | |
| break; | |
| default: | |
| // TODO: (#16410) Connect SHA-2 implementations | |
| return kCryptoStatusBadArgs; | |
| } | |
| // TODO: (#14549, #16410) Revisit KMAC error flow | |
| // Need to map KMAC driver error enum to cryptolib error enum | |
| if (err != kKmacOk) { | |
| return kCryptoStatusBadArgs; | |
| } | |
| // TODO: (#16410) SHA-2 error check to be added here | |
| return kCryptoStatusOK; | |
| } | |
| OT_WARN_UNUSED_RESULT | |
| crypto_status_t otcrypto_xof(crypto_const_uint8_buf_t input_message, | |
| xof_mode_t xof_mode, | |
| crypto_const_uint8_buf_t function_name_string, | |
| crypto_const_uint8_buf_t customization_string, | |
| size_t required_output_len, | |
| crypto_uint8_buf_t *digest) { | |
| // TODO: (#16410) Add error checks | |
| if (required_output_len != digest->len) { | |
| return kCryptoStatusBadArgs; | |
| } | |
| // According to NIST SP 800-185 Section 3.2, cSHAKE call should use SHAKE, if | |
| // both `customization_string` and `function_name_string` are empty string | |
| if (customization_string.len == 0 && function_name_string.len == 0) { | |
| if (xof_mode == kXofModeSha3Cshake128) { | |
| xof_mode = kXofModeSha3Shake128; | |
| } else if (xof_mode == kXofModeSha3Cshake256) { | |
| xof_mode = kXofModeSha3Shake256; | |
| } | |
| } | |
| kmac_error_t err; | |
| switch (xof_mode) { | |
| case kXofModeSha3Shake128: | |
| err = kmac_shake_128(input_message, digest); | |
| break; | |
| case kXofModeSha3Shake256: | |
| err = kmac_shake_256(input_message, digest); | |
| break; | |
| case kXofModeSha3Cshake128: | |
| err = kmac_cshake_128(input_message, function_name_string, | |
| customization_string, digest); | |
| break; | |
| case kXofModeSha3Cshake256: | |
| err = kmac_cshake_256(input_message, function_name_string, | |
| customization_string, digest); | |
| break; | |
| default: | |
| return kCryptoStatusBadArgs; | |
| } | |
| // TODO: (#14549, #16410) Revisit KMAC error flow | |
| if (err != kKmacOk) { | |
| return kCryptoStatusBadArgs; | |
| } | |
| return kCryptoStatusOK; | |
| } |