blob: 402326bfc9395687fbc2d178182ee4c28a787579 [file] [log] [blame]
// 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;
}