| // 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; |
| } |