Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sha: remove 64 byte alignment on input & split up SHA_Finalize and SHA_Calculate #186

Merged
merged 3 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 59 additions & 5 deletions gc/ogc/sha.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,68 @@ typedef struct
u32 lower_length;
} sha_context;

/*!
* \fn s32 SHA_Init(void)
* \brief Initializes the SHA1 subsystem. This call could be done in the early stages of your main()
*
* \return 0 or higher on success, otherwise the returned error code
*/
s32 SHA_Init(void);
s32 SHA_Close(void);
s32 SHA_InitializeContext(sha_context* context);

//calculate hash or add data manually - input data should *always* be 64bit aligned!
s32 SHA_Calculate(sha_context* context, const void* data, const u32 data_size, void* message_digest);
s32 SHA_Input(sha_context* context, const void* data, const u32 data_size);
/*!
* \fn s32 SHA_Close(void)
* \brief Closes the SHA1 subsystem handlers. This call could be done when exiting your application or before reloading IOS
*
* \return 0 or higher on success, otherwise the returned error code
*/
s32 SHA_Close(void);

/*!
* \fn s32 SHA_Calculate(const void* data, const u32 data_size, void* message_digest)
* \brief Calculates the SHA1 hash of the given data, and puts it in message_digest
*
* \param[in] data pointer to the data to hash. if it is not 64-byte aligned an internal buffer will be used
* \param[in] data_size size of the data to hash
* \param[out] message_digest pointer to where to write the hash to
*
* \return 0 or higher on success, otherwise the returned error code
*/
s32 SHA_Calculate(const void* data, const u32 data_size, void* message_digest);

/*!
* \fn s32 SHA_InitializeContext(sha_context* context)
* \brief Initializes the given sha context
*
* \param[in] context pointer to the sha_context to initialize
*
* \return 0 or higher on success, otherwise the returned error code
*/
s32 SHA_InitializeContext(const sha_context* context);

/*!
* \fn s32 SHA_Input(const sha_context* context, const void* data, const u32 data_size)
* \brief Adds data to the given sha_context and hashes it
*
* \param[in] context pointer to the sha_context to use
* \param[in] data pointer to the data to hash. if it is not 64-byte aligned an internal buffer will be used
* \param[in] data_size size of the data to hash
*
* \return 0 or higher on success, otherwise the returned error code
*/
s32 SHA_Input(const sha_context* context, const void* data, const u32 data_size);

/*!
* \fn s32 SHA_Finalize(const sha_context* context, const void* data, const u32 data_size, void* message_digest)
* \brief Calculates the final SHA1 hash of the given context and last data, and puts it in message_digest
*
* \param[in] context pointer to the sha_context to use
* \param[in] data pointer to the data to hash. if it is not 64-byte aligned an internal buffer will be used
* \param[in] data_size size of the data to hash
* \param[out] message_digest pointer to where to write the final SHA1 hash to
*
* \return 0 or higher on success, otherwise the returned error code
*/
s32 SHA_Finalize(const sha_context* context, const void* data, const u32 data_size, void* message_digest);

#ifdef __cplusplus
}
Expand Down
76 changes: 50 additions & 26 deletions libogc/sha.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ distribution.
-------------------------------------------------------------*/
#if defined(HW_RVL)

#include <malloc.h>
#include <string.h>
#include "gctypes.h"
#include "gcutil.h"
Expand All @@ -43,36 +44,50 @@ typedef enum
AddData = 0x01,
FinalizeHash = 0x02,
} ShaCommand;
static u8 input_buffer[0x1000] ATTRIBUTE_ALIGN(64);

static s32 SHA_ExecuteCommand(const ShaCommand command, sha_context* context, const void* in_data, const u32 data_size, void* out_data)
static s32 SHA_ExecuteCommand(const ShaCommand command, const sha_context* context, const void* in_data, const u32 data_size, void* out_data)
{
ioctlv* params = (ioctlv*)iosAlloc(__sha_hid, sizeof(ioctlv) * 3);
s32 ret = -1;

if(params == NULL)
return -4;
return -5;

for (u32 i = 0; i < data_size; i += SHA_MSGBLOCK_SIZE) {
u32 size = SHA_MSGBLOCK_SIZE;
params[1].data = (void*) context;
params[1].len = sizeof(sha_context);
params[2].data = out_data;
params[2].len = 0x14;

//if data is not 64-byte aligned we use the internal input_buffer to contain the data
bool isAlignedInput = ((u32)in_data & 0x3F) == 0;
s32 ret = -1;

for (u32 i = 0; i < data_size;)
{
const void* input = in_data + i;
u32 size = isAlignedInput ? SHA_MSGBLOCK_SIZE : sizeof(input_buffer);
ShaCommand block_cmd = command;

//if it's the final block, set size correctly.
//if it's not the final block, and we got a finalize, we will first send the add command
if(i+SHA_MSGBLOCK_SIZE >= data_size)
if(i+size >= data_size)
size = data_size - i;
else if(command == FinalizeHash)
block_cmd = AddData;

params[0].data = (void*)((u32)in_data + i);
params[0].len = size;
params[1].data = (void*) context;
params[1].len = sizeof(sha_context);
params[2].data = (void*)((u32)out_data);
params[2].len = 0x14;
if(!isAlignedInput)
{
input = input_buffer;
memcpy(input_buffer, in_data + i, size);
}

params[0].data = (void*)input;
params[0].len = size;

ret = IOS_Ioctlv(__sha_fd, block_cmd, 1, 2, params);
if (ret < 0)
break;

i += size;
}

iosFree(__sha_hid, params);
Expand Down Expand Up @@ -112,7 +127,7 @@ s32 SHA_Close(void)
return 0;
}

s32 SHA_InitializeContext(sha_context* context)
s32 SHA_InitializeContext(const sha_context* context)
{
if(context == NULL)
return -1;
Expand All @@ -132,29 +147,38 @@ s32 SHA_InitializeContext(sha_context* context)
iosFree(__sha_hid, params);
return ret;
}
s32 SHA_Calculate(sha_context* context, const void* data, const u32 data_size, void* message_digest)

s32 SHA_Input(const sha_context* context, const void* data, const u32 data_size)
{
if(context == NULL || message_digest == NULL || data_size == 0 || data == NULL)
//when adding data, it should be in 64-byte blocks.
if(context == NULL || data == NULL || data_size == 0)
return -1;

if(((u32)context & 0x1F) != 0 || ((u32)message_digest & 0x1F) != 0)
return -4;

if( data != NULL && ((u32)data & 0x3F) != 0)
if(((u32)context) & 0x1F || data_size & 0x3F)
return -4;

return SHA_ExecuteCommand(FinalizeHash, context, data, data_size, message_digest);
return SHA_ExecuteCommand(AddData, context, data, data_size, NULL);
}

s32 SHA_Input(sha_context* context, const void* data, const u32 data_size)
s32 SHA_Finalize(const sha_context* context, const void* data, const u32 data_size, void* message_digest)
{
if(context == NULL || data == NULL || data_size == 0)
if(context == NULL || message_digest == NULL || data_size == 0 || data == NULL)
return -1;

if((((u32)context) & 0x1F) || (((u32)data) & 0x3F))
if(((u32)context & 0x1F) != 0 || ((u32)message_digest & 0x1F) != 0)
return -4;

return SHA_ExecuteCommand(AddData, context, data, data_size, NULL);
return SHA_ExecuteCommand(FinalizeHash, context, data, data_size, message_digest);
}

s32 SHA_Calculate(const void* data, const u32 data_size, void* message_digest)
{
sha_context context ATTRIBUTE_ALIGN(32) = {0};
s32 ret = SHA_InitializeContext(&context);
if(ret < 0)
return ret;

return SHA_Finalize(&context, data, data_size, message_digest);
}

#endif
Loading