1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/*
* Dibbler - a portable DHCPv6
*
* author: Michal Kowalczuk <michal@kowalczuk.eu>
*
* released under GNU GPL v2 licence
*
* $Id: hmac-sha-md5.c,v 1.1 2006-11-30 03:28:35 thomson Exp $
*
* $Log: hmac-sha-md5.c,v $
* Revision 1.1 2006-11-30 03:28:35 thomson
* Auth related changes by Sammael.
*
*
*
*/
#include <string.h>
#include <stdlib.h>
#include "hmac.h"
#include "md5.h"
#include "sha1.h"
#include "sha256.h"
#include "sha512.h"
/* "Feeding The Void With Emptiness..." ;) */
#define SHA_CASE(x,y) \
case x: \
ctx = malloc(sizeof(struct sha##y##_ctx)); \
init_ctx = (void(*)(void *)) &sha##x##_init_ctx; \
process_bytes = (void(*)(void *, size_t, void *))&sha##y##_process_bytes; \
finish_ctx = (void* (*)(void *, void *)) &sha##x##_finish_ctx; \
blocksize = SHA##x##_BLOCKSIZE; \
digestsize = SHA##x##_DIGESTSIZE; \
break;
/* Take buffer and key (and their lengths), generate HMAC-SHA (or HMAC-MD5) */
/* and write the result to RESBUF */
/* type is one of the following: 1, 224, 256, 384, 512 (for SHA) or 5 (for MD5) */
static void *
hmac_sha_md5 (const char *buffer, size_t len, char *key, size_t key_len, char *resbuf, int type) {
/* SHA512_BLOCKSIZE and SHA512_DIGESTSIZE are the biggest, so we can use it with other algorithms */
char Ki[SHA512_BLOCKSIZE];
char Ko[SHA512_BLOCKSIZE];
char tmpbuf[SHA512_DIGESTSIZE];
int i;
int blocksize;
int digestsize;
void *ctx;
void (*init_ctx)(void *);
void (*process_bytes)(void *, size_t, void *);
void *(*finish_ctx)(void *, void *);
void *result;
switch (type) {
case 5: /* Oh, it's MD5! */
ctx = malloc(sizeof(struct md5_ctx));
init_ctx = (void(*)(void *)) &md5_init_ctx;
process_bytes = (void(*)(void *, size_t, void *)) &md5_process_bytes;
finish_ctx = (void* (*)(void *, void *)) &md5_finish_ctx;
blocksize = MD5_BLOCKSIZE;
digestsize = MD5_DIGESTSIZE;
break;
/* .--------< SHA variant
|
v */
SHA_CASE( 1, 1)
SHA_CASE(224, 256)
SHA_CASE(256, 256)
SHA_CASE(384, 512)
SHA_CASE(512, 512)
default:
return NULL;
}
/* if given key is longer that algorithm's block, we must change it to
hash of the original key (of size of algorithm's digest) */
if (key_len > blocksize) {
init_ctx (&ctx);
process_bytes (key, key_len, &ctx);
finish_ctx (&ctx, Ki);
key_len = digestsize;
memcpy(Ko, Ki, key_len);
} else {
memcpy(Ki, key, key_len);
memcpy(Ko, key, key_len);
}
/* prepare input and output key */
for (i = 0; i < key_len; i++) {
Ki[i] ^= 0x36;
Ko[i] ^= 0x5c;
}
for (; i < blocksize; i++) {
Ki[i] = 0x36;
Ko[i] = 0x5c;
}
init_ctx (ctx);
process_bytes (Ki, blocksize, ctx);
process_bytes ((void *)buffer, len, ctx);
finish_ctx (ctx, tmpbuf);
init_ctx (ctx);
process_bytes (Ko, blocksize, ctx);
process_bytes (tmpbuf, digestsize, ctx);
result = finish_ctx (ctx, resbuf);
free(ctx);
return result;
}
/* HMAC-SHA function wrapper */
void *hmac_sha (const char *buffer, size_t len, char *key, size_t key_len, char *resbuf, int type) {
return hmac_sha_md5(buffer, len, key, key_len, resbuf, type);
}
/* HMAC-MD5 function wrapper */
void *hmac_md5 (const char *buffer, size_t len, char *key, size_t key_len, char *resbuf) {
return hmac_sha_md5(buffer, len, key, key_len, resbuf, 5);
}
|