mirror of https://github.com/thesofproject/sof.git
hash: New hash functions
Prepared a new set of functions for computing digest with error handling. The hash context has been placed into a separate structure. This allows to conveniently pass the calculated digest along with its length and used algorithm. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
This commit is contained in:
parent
93c5e8b51f
commit
2bd8be35d2
163
src/hash.c
163
src/hash.c
|
@ -1,9 +1,11 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
//
|
||||
// Copyright(c) 2017 Intel Corporation. All rights reserved.
|
||||
//
|
||||
// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
// Keyon Jie <yang.jie@linux.intel.com>
|
||||
/*
|
||||
* Copyright(c) 2017 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
|
||||
* Keyon Jie <yang.jie@linux.intel.com>
|
||||
* Adrian Warecki <adrian.warecki@intel.com>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -11,8 +13,6 @@
|
|||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/evp.h>
|
||||
|
@ -20,6 +20,9 @@
|
|||
|
||||
#include <rimage/rimage.h>
|
||||
#include <rimage/manifest.h>
|
||||
#include <rimage/hash.h>
|
||||
|
||||
#define DEBUG_HASH 0
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
|
||||
|
@ -46,7 +49,151 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define DEBUG_HASH 0
|
||||
static int hash_error(struct hash_context *context, int errcode, const char *msg)
|
||||
{
|
||||
EVP_MD_CTX_free(context->context);
|
||||
context->context = NULL;
|
||||
context->state = HS_ERROR;
|
||||
context->error = -errcode;
|
||||
fprintf(stderr, "hash: %s\n", msg);
|
||||
return context->error;
|
||||
}
|
||||
|
||||
int hash_init(struct hash_context *context, const EVP_MD *algo)
|
||||
{
|
||||
assert(context);
|
||||
assert(algo);
|
||||
|
||||
context->error = 0;
|
||||
context->digest_length = 0;
|
||||
context->algo = algo;
|
||||
|
||||
context->context = EVP_MD_CTX_new();
|
||||
if (!context->context)
|
||||
return hash_error(context, ENOMEM, "Unable to allocate hash context.");
|
||||
|
||||
if (!EVP_DigestInit_ex(context->context, context->algo, NULL)) {
|
||||
EVP_MD_CTX_free(context->context);
|
||||
return hash_error(context, ENOTRECOVERABLE, "Unable to initialize hash context.");
|
||||
}
|
||||
|
||||
context->state = HS_UPDATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_sha256_init(struct hash_context *context)
|
||||
{
|
||||
return hash_init(context, EVP_sha256());
|
||||
}
|
||||
|
||||
int hash_sha384_init(struct hash_context *context)
|
||||
{
|
||||
return hash_init(context, EVP_sha384());
|
||||
}
|
||||
|
||||
int hash_update(struct hash_context *context, const void *data, size_t size)
|
||||
{
|
||||
assert(context);
|
||||
assert(data);
|
||||
|
||||
if (context->error)
|
||||
return context->error;
|
||||
|
||||
assert(context->state == HS_UPDATE);
|
||||
|
||||
if (!EVP_DigestUpdate(context->context, data, size))
|
||||
return hash_error(context, EINVAL, "Unable to update hash context.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_finalize(struct hash_context *context)
|
||||
{
|
||||
assert(context);
|
||||
|
||||
if (context->error)
|
||||
return context->error;
|
||||
|
||||
assert(context->state == HS_UPDATE);
|
||||
|
||||
if (!EVP_DigestFinal_ex(context->context, context->digest, &context->digest_length))
|
||||
return hash_error(context, EINVAL, "Unable to finalize hash context.");
|
||||
|
||||
context->state = HS_DONE;
|
||||
|
||||
#if DEBUG_HASH
|
||||
fprintf(stdout, "Hash result is: ");
|
||||
hash_print(context);
|
||||
#endif
|
||||
|
||||
EVP_MD_CTX_free(context->context);
|
||||
context->context = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_get_digest(struct hash_context *context, void *output, size_t output_len)
|
||||
{
|
||||
assert(context);
|
||||
assert(output);
|
||||
|
||||
if (context->error)
|
||||
return context->error;
|
||||
|
||||
assert(context->state == HS_DONE);
|
||||
|
||||
if (context->digest_length > output_len)
|
||||
return -ENOBUFS;
|
||||
|
||||
memcpy(output, context->digest, context->digest_length);
|
||||
return context->digest_length;
|
||||
}
|
||||
|
||||
void hash_print(struct hash_context *context)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
assert(context);
|
||||
assert(context->state == HS_DONE);
|
||||
assert(context->digest_length);
|
||||
|
||||
for (i = 0; i < context->digest_length; i++)
|
||||
fprintf(stdout, "%02x", context->digest[i]);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
int hash_single(const void *data, size_t size, const EVP_MD *algo, void *output, size_t output_len)
|
||||
{
|
||||
int algo_out_size;
|
||||
|
||||
assert(algo);
|
||||
assert(data);
|
||||
assert(output);
|
||||
|
||||
//algo_out_size = EVP_MD_get_size(algo);
|
||||
algo_out_size = EVP_MD_size(algo);
|
||||
if (algo_out_size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (output_len > algo_out_size)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (!EVP_Digest(data, size, output, NULL, algo, NULL)) {
|
||||
fprintf(stderr, "Unable to compute hash.");
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_sha256(const void *data, size_t size, void *output, size_t output_len)
|
||||
{
|
||||
return hash_single(data, size, EVP_sha256(), output, output_len);
|
||||
}
|
||||
|
||||
int hash_sha384(const void *data, size_t size, void *output, size_t output_len)
|
||||
{
|
||||
return hash_single(data, size, EVP_sha384(), output, output_len);
|
||||
}
|
||||
|
||||
void module_sha256_create(struct image *image)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright(c) 2023 Intel Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __HASH_H__
|
||||
#define __HASH_H__
|
||||
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Hash context state used to detect invalid use of hash functions */
|
||||
enum hash_state { HS_INIT, HS_UPDATE, HS_DONE, HS_ERROR };
|
||||
|
||||
struct hash_context {
|
||||
enum hash_state state;
|
||||
EVP_MD_CTX *context;
|
||||
const EVP_MD *algo;
|
||||
uint8_t digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int digest_length;
|
||||
int error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize hash context with given algorithm
|
||||
* @param [out]context structure storing the hash context
|
||||
* @param [in]algo hash algorithm
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_init(struct hash_context *context, const EVP_MD *algo);
|
||||
|
||||
/**
|
||||
* Initialize sha256 hash context
|
||||
* @param [out]context structure storing the hash context
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_sha256_init(struct hash_context *context);
|
||||
|
||||
/**
|
||||
* Initialize sha384 hash context
|
||||
* @param [out]context structure storing the hash context
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_sha384_init(struct hash_context *context);
|
||||
|
||||
/**
|
||||
* Add data to hash
|
||||
* @param [in]context structure storing the hash context
|
||||
* @param [in]data data to be added
|
||||
* @param [in]size length of data in bytes
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_update(struct hash_context *context, const void *data, size_t size);
|
||||
|
||||
/**
|
||||
* Completes the hash calculation. No more data can be added!
|
||||
* @param [in]context structure storing the hash context
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_finalize(struct hash_context *context);
|
||||
|
||||
/**
|
||||
* Read out computed digest. Must finalize first.
|
||||
* @param [in]context structure storing the hash context
|
||||
* @param [out]output pointer to array where place hash value
|
||||
* @param [in]output_len size of the output buffer
|
||||
* @return copied digest length, < 0 if error
|
||||
*/
|
||||
int hash_get_digest(struct hash_context *context, void *output, size_t output_len);
|
||||
|
||||
/**
|
||||
* Print digest value
|
||||
* @param [in]context structure storing the hash context
|
||||
*/
|
||||
void hash_print(struct hash_context *context);
|
||||
|
||||
/**
|
||||
* Calculates hash of a single memory buffer
|
||||
* @param [in]data pointer to the data to be processed
|
||||
* @param [in]size length of the data to be processed
|
||||
* @param [in]algo hash algorithm
|
||||
* @param [out]output pointer to array where place hash value
|
||||
* @param [in]output_len size of the output buffer
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_single(const void* data, size_t size, const EVP_MD *algo, void *output, size_t output_len);
|
||||
|
||||
/**
|
||||
* Calculates sha256 hash of a memory buffer
|
||||
* @param [in]data pointer to the data to be processed
|
||||
* @param [in]size length of the data to be processed
|
||||
* @param [out]output pointer to array where place hash value
|
||||
* @param [in]output_len size of the output buffer
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_sha256(const void* data, size_t size, void *output, size_t output_len);
|
||||
|
||||
/**
|
||||
* Calculates sha384 hash of a memory buffer
|
||||
* @param [in]data pointer to the data to be processed
|
||||
* @param [in]size length of the data to be processed
|
||||
* @param [out]output pointer to array where place hash value
|
||||
* @param [in]output_len size of the output buffer
|
||||
* @return error code, 0 when success
|
||||
*/
|
||||
int hash_sha384(const void* data, size_t size, void *output, size_t output_len);
|
||||
|
||||
#endif /* __HASH_H__ */
|
Loading…
Reference in New Issue