Implement HMAC-MD5, HMAC-SHA1, and HMAC-SHA256.

This commit is contained in:
Stephen Heumann 2023-11-29 19:43:03 -06:00
parent 4f7c6c0eb8
commit c1e1caa766
10 changed files with 261 additions and 11 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2017 Stephen Heumann
Copyright (c) 2017,2023 Stephen Heumann
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@ -4,7 +4,7 @@ CFLAGS = -O255 -w255
LIBRARIES = lib65816crypto lib65816hash
PROGRAMS = aescbctest aesctrtest aestest aescrypt sha1sum sha1test \
sha256sum sha256test md5sum md5test
sha256sum sha256test md5sum md5test hmactest
.PHONY: default
default: $(LIBRARIES) $(PROGRAMS)
@ -21,15 +21,15 @@ aes.a: aes.asm aes.macros
mv aes.A aes.a
# Hash algorithms
sha1.a: sha1.cc sha1.h sha1.asm sha1.macros
sha1.a: sha1.cc sha1.h sha1.asm sha1.macros hmacimpl.h
$(CC) $(CFLAGS) -c $<
sha1.B: sha1.a
sha256.a: sha256.cc sha1.h sha256.asm sha1.macros
sha256.a: sha256.cc sha256.h sha256.asm sha256.macros hmacimpl.h
$(CC) $(CFLAGS) -c $<
sha256.B: sha256.a
md5.a: md5.cc md5.h md5.asm md5.macros
md5.a: md5.cc md5.h md5.asm md5.macros hmacimpl.h
$(CC) $(CFLAGS) -c $<
md5.B: md5.a
@ -66,6 +66,9 @@ md5sum.a: md5sum.c md5.h cksumcommon.h
md5test.a: md5test.c md5.h
$(CC) $(CFLAGS) -c $<
hmactest.a: hmactest.c sha256.h sha1.h md5.h
$(CC) $(CFLAGS) -c $<
aescbctest: aescbctest.a pagealign.root lib65816crypto
$(CC) $(CFLAGS) pagealign.root $< -L. -llib65816crypto -o $@
aesctrtest: aesctrtest.a pagealign.root lib65816crypto
@ -90,6 +93,8 @@ md5sum: md5sum.a pagealign.root lib65816hash
md5test: md5test.a pagealign.root lib65816hash
$(CC) $(CFLAGS) pagealign.root $< -L. -llib65816hash -o $@
hmactest: hmactest.a lib65816hash
$(CC) $(CFLAGS) pagealign.root $< -L. -llib65816hash -o $@
.PHONY: clean
clean:

87
hmacimpl.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file is a template for computing HMACs using the hash functions
* from lib65816hash. It is #included from the files implementing the
* hash functions, with HASH_ALG defined to the name of the hash function.
*/
#define join(a,b) a##b
#define concat(a,b) join(a,b)
#define join3(a,b,c) a##b##c
#define concat3(a,b,c) join3(a,b,c)
#define hash_init concat(HASH_ALG,_init)
#define hash_update concat(HASH_ALG,_update)
#define hash_finalize concat(HASH_ALG,_finalize)
#define hmac_init concat3(hmac_,HASH_ALG,_init)
#define hmac_compute concat3(hmac_,HASH_ALG,_compute)
#define hmac_context concat3(hmac_,HASH_ALG,_context)
void hmac_init(struct hmac_context *context,
const unsigned char *key,
unsigned long key_length)
{
#define BLOCK_SIZE sizeof(context->u[0].ctx.block)
#define HASH_SIZE sizeof(context->u[0].ctx.hash)
unsigned i;
// Compute adjusted key (hashed from original key if necessary)
memset(context->u[0].k, 0, BLOCK_SIZE);
if (key_length <= BLOCK_SIZE) {
memcpy(context->u[0].k, key, key_length);
} else {
hash_init(&context->u[1].ctx);
hash_update(&context->u[1].ctx, key, key_length);
hash_finalize(&context->u[1].ctx);
memcpy(context->u[0].k, context->u[1].ctx.hash, HASH_SIZE);
}
// Set context->u[0].k to K XOR opad, context->u[1].k to K XOR ipad
for (i = 0; i < BLOCK_SIZE; i++) {
context->u[1].k[i] = context->u[0].k[i] ^ 0x36;
context->u[0].k[i] ^= 0x5C;
}
// Save inner hash context following initial block as context->u[2].ctx
hash_init(&context->u[2].ctx);
hash_update(&context->u[2].ctx, context->u[1].k, BLOCK_SIZE);
// Save outer hash context following initial block as context->u[1].ctx
hash_init(&context->u[1].ctx);
hash_update(&context->u[1].ctx, context->u[0].k, BLOCK_SIZE);
}
void hmac_compute(struct hmac_context *context,
const unsigned char *message,
unsigned long message_length)
{
// Compute inner hash
context->u[0].ctx = context->u[2].ctx;
hash_update(&context->u[0].ctx, message, message_length);
hash_finalize(&context->u[0].ctx);
memcpy(context->inner_hash, context->u[0].ctx.hash, HASH_SIZE);
// Compute outer hash
context->u[0].ctx = context->u[1].ctx;
hash_update(&context->u[0].ctx, context->inner_hash, HASH_SIZE);
hash_finalize(&context->u[0].ctx);
}

71
hmactest.c Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <orca.h>
#include <memory.h>
#include "sha256.h"
#include "sha1.h"
#include "md5.h"
int main(void) {
Handle context_hndl;
struct hmac_sha256_context *hmac_sha256_context;
struct hmac_sha1_context *hmac_sha1_context;
struct hmac_md5_context *hmac_md5_context;
char key[] = "key";
char msg[] = "The quick brown fox jumps over the lazy dog";
context_hndl = NewHandle(sizeof(struct hmac_sha256_context),
userid(), attrFixed|attrPage|attrBank|attrNoCross, 0x000000);
if (toolerror())
return 0;
hmac_sha256_context = (struct hmac_sha256_context *)*context_hndl;
hmac_sha256_init(hmac_sha256_context, key, sizeof(key)-1);
hmac_sha256_compute(hmac_sha256_context, msg, sizeof(msg)-1);
printf("HMAC-SHA256: ");
for (int i = 0; i < sizeof(hmac_sha256_context->u[0].ctx.hash); i++) {
printf("%02x", hmac_sha256_context->u[0].ctx.hash[i]);
}
printf("\n");
hmac_sha1_context = (struct hmac_sha1_context *)*context_hndl;
hmac_sha1_init(hmac_sha1_context, key, sizeof(key)-1);
hmac_sha1_compute(hmac_sha1_context, msg, sizeof(msg)-1);
printf("HMAC-SHA1: ");
for (int i = 0; i < sizeof(hmac_sha1_context->u[0].ctx.hash); i++) {
printf("%02x", hmac_sha1_context->u[0].ctx.hash[i]);
}
printf("\n");
hmac_md5_context = (struct hmac_md5_context *)*context_hndl;
hmac_md5_init(hmac_md5_context, key, sizeof(key)-1);
hmac_md5_compute(hmac_md5_context, msg, sizeof(msg)-1);
printf("HMAC-MD5: ");
for (int i = 0; i < sizeof(hmac_md5_context->u[0].ctx.hash); i++) {
printf("%02x", hmac_md5_context->u[0].ctx.hash[i]);
}
printf("\n");
}

5
md5.cc
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Stephen Heumann
* Copyright (c) 2017,2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -135,4 +135,7 @@ void md5_finalize(struct md5_context *context)
}
}
#define HASH_ALG md5
#include "hmacimpl.h"
#append "md5.asm"

28
md5.h
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Stephen Heumann
* Copyright (c) 2017,2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -24,6 +24,14 @@ struct md5_context {
unsigned char block[64];
};
struct hmac_md5_context {
union {
struct md5_context ctx;
unsigned char k[64];
} u[3];
unsigned char inner_hash[16];
};
/*
* The context structure must be in bank 0, preferably page-aligned.
*/
@ -49,3 +57,21 @@ void md5_finalize(struct md5_context *context);
* This is a low-level function; users should normally not call this directly.
*/
void md5_processblock(struct md5_context *context);
/*
* Initialize a context for HMAC-MD5 computation with a specified key.
* This must be called before any calls to hmac_md5_compute. After
* initialization, the context can be used to compute the HMAC for any
* number of messages.
*/
void hmac_md5_init(struct hmac_md5_context *context,
const unsigned char *key,
unsigned long key_length);
/*
* Compute the HMAC-MD5 of a message, using an already-initialized context.
* The result will be in context->u[0].ctx.hash.
*/
void hmac_md5_compute(struct hmac_md5_context *context,
const unsigned char *message,
unsigned long message_length);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Stephen Heumann
* Copyright (c) 2017,2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -180,4 +180,7 @@ void sha1_finalize(struct sha1_context *context)
}
}
#define HASH_ALG sha1
#include "hmacimpl.h"
#append "sha1.asm"

28
sha1.h
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Stephen Heumann
* Copyright (c) 2017,2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -24,6 +24,14 @@ struct sha1_context {
unsigned char reserved2[16];
};
struct hmac_sha1_context {
union {
struct sha1_context ctx;
unsigned char k[64];
} u[3];
unsigned char inner_hash[20];
};
/*
* The context structure must be in bank 0, preferably page-aligned.
*/
@ -49,3 +57,21 @@ void sha1_finalize(struct sha1_context *context);
* This is a low-level function; users should normally not call this directly.
*/
void sha1_processblock(struct sha1_context *context);
/*
* Initialize a context for HMAC-SHA1 computation with a specified key.
* This must be called before any calls to hmac_sha1_compute. After
* initialization, the context can be used to compute the HMAC for any
* number of messages.
*/
void hmac_sha1_init(struct hmac_sha1_context *context,
const unsigned char *key,
unsigned long key_length);
/*
* Compute the HMAC-SHA1 of a message, using an already-initialized context.
* The result will be in context->u[0].ctx.hash.
*/
void hmac_sha1_compute(struct hmac_sha1_context *context,
const unsigned char *message,
unsigned long message_length);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Stephen Heumann
* Copyright (c) 2017,2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -204,4 +204,7 @@ void sha256_finalize(struct sha256_context *context)
}
}
#define HASH_ALG sha256
#include "hmacimpl.h"
#append "sha256.asm"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Stephen Heumann
* Copyright (c) 2017,2023 Stephen Heumann
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -24,6 +24,14 @@ struct sha256_context {
unsigned char reserved2[60];
};
struct hmac_sha256_context {
union {
struct sha256_context ctx;
unsigned char k[64];
} u[3];
unsigned char inner_hash[32];
};
/*
* The context structure must be in bank 0, preferably page-aligned.
*/
@ -57,3 +65,21 @@ void sha256_finalize(struct sha256_context *context);
* This is a low-level function; users should normally not call this directly.
*/
void sha256_processblock(struct sha256_context *context);
/*
* Initialize a context for HMAC-SHA256 computation with a specified key.
* This must be called before any calls to hmac_sha256_compute. After
* initialization, the context can be used to compute the HMAC for any
* number of messages.
*/
void hmac_sha256_init(struct hmac_sha256_context *context,
const unsigned char *key,
unsigned long key_length);
/*
* Compute the HMAC-SHA256 of a message, using an already-initialized context.
* The result will be in context->u[0].ctx.hash.
*/
void hmac_sha256_compute(struct hmac_sha256_context *context,
const unsigned char *message,
unsigned long message_length);