-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added HMAC with SHA256 implementation from Aaron D. Gifford (http://w…
- Loading branch information
Showing
47 changed files
with
3,060 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
/* dtls -- a very basic DTLS implementation | ||
* | ||
* Copyright (C) 2011 Olaf Bergmann <[email protected]> | ||
* | ||
* Permission is hereby granted, free of charge, to any person | ||
* obtaining a copy of this software and associated documentation | ||
* files (the "Software"), to deal in the Software without | ||
* restriction, including without limitation the rights to use, copy, | ||
* modify, merge, publish, distribute, sublicense, and/or sell copies | ||
* of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be | ||
* included in all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
* SOFTWARE. | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <assert.h> | ||
|
||
#define DTLS_HMAC_BLOCKSIZE 64 | ||
#define DTLS_HMAC_MAX 64 | ||
|
||
/* Aaron D. Gifford's implementation of SHA256 | ||
* see http://www.aarongifford.com/ */ | ||
#include "sha2/sha2.h" | ||
#include "debug.h" | ||
|
||
#include "hmac.h" | ||
|
||
void | ||
h_sha256_init(void *ctx) { | ||
SHA256_Init((SHA256_CTX *)ctx); | ||
} | ||
|
||
void | ||
h_sha256_update(void *ctx, const unsigned char *input, size_t len) { | ||
SHA256_Update((SHA256_CTX *)ctx, input, len); | ||
} | ||
|
||
size_t | ||
h_sha256_finalize(unsigned char *buf, void *ctx) { | ||
SHA256_Final(buf, (SHA256_CTX *)ctx); | ||
return SHA256_DIGEST_LENGTH; | ||
} | ||
|
||
void | ||
dtls_hmac_update(dtls_hmac_context_t *ctx, | ||
const unsigned char *input, size_t ilen) { | ||
assert(ctx); | ||
assert(ctx->H); | ||
|
||
ctx->H->update(ctx->H->data, input, ilen); | ||
} | ||
|
||
dtls_hash_t * | ||
dtls_new_hash(dtls_hashfunc_t h) { | ||
dtls_hash_t *H; | ||
|
||
switch(h) { | ||
case SHA256: | ||
H = (dtls_hash_t *)malloc(sizeof(dtls_hash_t) + sizeof(SHA256_CTX)); | ||
if (H) { | ||
H->data = ((char *)H) + sizeof(dtls_hash_t); | ||
H->init = h_sha256_init; | ||
H->update = h_sha256_update; | ||
H->finalize = h_sha256_finalize; | ||
} | ||
break; | ||
default: | ||
dsrv_log(LOG_CRIT, "unknown hash function %d\n", h); | ||
} | ||
|
||
if (!H) | ||
dsrv_log(LOG_CRIT, "cannot create hash function %d\n", h); | ||
|
||
return H; | ||
} | ||
|
||
int | ||
dtls_hmac_init(dtls_hmac_context_t *ctx, | ||
unsigned char *key, size_t klen, | ||
dtls_hashfunc_t h) { | ||
int i; | ||
assert(ctx); | ||
|
||
ctx->H = dtls_new_hash(h);; | ||
if (!ctx->H) | ||
return -1; | ||
|
||
memset(ctx->ipad, 0, DTLS_HMAC_BLOCKSIZE); | ||
|
||
if (klen > DTLS_HMAC_BLOCKSIZE) { | ||
ctx->H->init(ctx->H->data); | ||
ctx->H->update(ctx->H->data, key, klen); | ||
ctx->H->finalize(ctx->ipad, ctx->H->data); | ||
} else | ||
memcpy(ctx->ipad, key, klen); | ||
|
||
memcpy(ctx->opad, ctx->ipad, DTLS_HMAC_BLOCKSIZE); | ||
|
||
for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i) { | ||
ctx->ipad[i] ^= 0x36; | ||
ctx->opad[i] ^= 0x5C; | ||
} | ||
|
||
ctx->H->init(ctx->H->data); | ||
dtls_hmac_update(ctx, ctx->ipad, DTLS_HMAC_BLOCKSIZE); | ||
return 1; | ||
} | ||
|
||
int | ||
dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result) { | ||
unsigned char buf[DTLS_HMAC_MAX]; | ||
size_t len; | ||
|
||
assert(ctx); | ||
assert(result); | ||
|
||
memset(result, 0, DTLS_HMAC_MAX); | ||
|
||
len = ctx->H->finalize(buf, ctx->H->data); | ||
|
||
ctx->H->init(ctx->H->data); | ||
ctx->H->update(ctx->H->data, ctx->opad, DTLS_HMAC_BLOCKSIZE); | ||
ctx->H->update(ctx->H->data, buf, len); | ||
|
||
len = ctx->H->finalize(result, ctx->H->data); | ||
|
||
free(ctx->H); | ||
return len; | ||
} | ||
|
||
#ifdef WITH_OPENSSL | ||
#define DIGEST EVP_sha256() | ||
|
||
#include <openssl/evp.h> | ||
#include <openssl/md5.h> | ||
#include <openssl/hmac.h> | ||
#include <openssl/err.h> | ||
#include <openssl/rand.h> | ||
#endif | ||
|
||
void | ||
reference(unsigned char *secret, int keylen, | ||
unsigned char *text, int textlen) { | ||
#ifdef WITH_OPENSSL | ||
HMAC_CTX hmac_context; | ||
|
||
static unsigned char buf[EVP_MAX_MD_SIZE]; | ||
unsigned int len, i; | ||
|
||
OpenSSL_add_all_digests(); | ||
|
||
HMAC_Init(&hmac_context, secret, keylen, DIGEST); | ||
HMAC_Update(&hmac_context, text, textlen); | ||
|
||
HMAC_Final(&hmac_context, buf, &len); | ||
|
||
for(i = 0; i < len; i++) | ||
printf("%02x", buf[i]); | ||
printf("\n"); | ||
#else | ||
fprintf(stderr,"Error: no OpenSSL\n"); | ||
#endif | ||
} | ||
|
||
#ifdef HMAC_TEST | ||
int main(int argc, char **argv) { | ||
static unsigned char key[] = { 0x0b, 0x0b, 0x0b, 0x0b, | ||
0x0b, 0x0b, 0x0b, 0x0b, | ||
0x0b, 0x0b, 0x0b, 0x0b, | ||
0x0b, 0x0b, 0x0b, 0x0b }; | ||
static unsigned char text[] = { 'H', 'i', ' ', 'T', 'h', 'e', 'r', 'e' }; | ||
static unsigned char buf[DTLS_HMAC_MAX]; | ||
size_t len, i; | ||
dtls_hmac_context_t hmac_ctx; | ||
|
||
dtls_hmac_init(&hmac_ctx, key, sizeof(key), SHA256); | ||
dtls_hmac_update(&hmac_ctx, text, sizeof(text)); | ||
|
||
len = dtls_hmac_finalize(&hmac_ctx, buf); | ||
|
||
for(i = 0; i < len; i++) | ||
printf("%02x", buf[i]); | ||
printf("\n"); | ||
|
||
reference(key, sizeof(key), text, sizeof(text)); | ||
|
||
return 0; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* dtls -- a very basic DTLS implementation | ||
* | ||
* Copyright (C) 2011 Olaf Bergmann <[email protected]> | ||
* | ||
* Permission is hereby granted, free of charge, to any person | ||
* obtaining a copy of this software and associated documentation | ||
* files (the "Software"), to deal in the Software without | ||
* restriction, including without limitation the rights to use, copy, | ||
* modify, merge, publish, distribute, sublicense, and/or sell copies | ||
* of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be | ||
* included in all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
* SOFTWARE. | ||
*/ | ||
|
||
#ifndef _HMAC_H_ | ||
#define _HMAC_H_ | ||
|
||
#define DTLS_HMAC_BLOCKSIZE 64 /**< size of hmac blocks */ | ||
#define DTLS_HMAC_MAX 64 /**< max number of bytes in digest */ | ||
|
||
/** | ||
* Description of hash function. The context object is carried in \c | ||
* data, \c init, \c update, and \c finalize reflect the typical | ||
* multi-stage API of hash operations, see e.g. RFC 1321. */ | ||
typedef struct { | ||
void *data; | ||
void (*init)(void *); | ||
void (*update)(void *, const unsigned char *, size_t); | ||
size_t (*finalize)(unsigned char *, void *); | ||
} dtls_hash_t; | ||
|
||
/** List of known hash functions for use in dtls_hmac_init(). */ | ||
typedef enum { SHA256=1 } dtls_hashfunc_t; | ||
|
||
/** | ||
* Context for HMAC generation. This object is initialized with | ||
* dtls_hmac_init() and must be passed to dtls_hmac_update() and | ||
* dtls_hmac_finalize(). Once, finalized, the component \c H is | ||
* invalid and must be initialized again with dtls_hmac_init() before | ||
* the structure can be used again. | ||
*/ | ||
typedef struct { | ||
unsigned char ipad[DTLS_HMAC_BLOCKSIZE]; | ||
unsigned char opad[DTLS_HMAC_BLOCKSIZE]; | ||
|
||
dtls_hash_t *H; | ||
} dtls_hmac_context_t; | ||
|
||
/** | ||
* Initializes the HMAC context \p ctx with the given secret key and | ||
* the specified hash function. This function returns \c 1 if \c ctx | ||
* has been set correctly, or \c 0 or \c -1 otherwise. Note that this | ||
* function allocates new storage for the hash context which is | ||
* released by dtls_hmac_finalize(). | ||
* | ||
* \param ctx The HMAC context to initialize. | ||
* \param key The secret key. | ||
* \param klen The length of \p key. | ||
* \param h The actual hash function to use. | ||
* \return 1 on success, <= 0 otherwise. | ||
*/ | ||
int dtls_hmac_init(dtls_hmac_context_t *ctx, | ||
unsigned char *key, size_t klen, | ||
dtls_hashfunc_t h); | ||
|
||
/** | ||
* Updates the HMAC context with data from \p input. | ||
* | ||
* \param ctx The HMAC context. | ||
* \param input The input data. | ||
* \param ilen Size of \p input. | ||
*/ | ||
void dtls_hmac_update(dtls_hmac_context_t *ctx, | ||
const unsigned char *input, size_t ilen); | ||
|
||
/** | ||
* Completes the HMAC generation and writes the result to the given | ||
* output parameter \c result. The buffer must be large enough to hold | ||
* the message digest created by the actual hash function. If in | ||
* doubt, use \c DTLS_HMAC_MAX. The function returns the number of | ||
* bytes written to \c result. As this function releases internal | ||
* storage that was allocated for the hash function, it must be called | ||
* exactly once whenever dtls_hmac_init() has been called. | ||
* | ||
* | ||
* \param ctx The HMAC context. | ||
* \param result Output parameter where the MAC is written to. | ||
* \return Length of the MAC written to \p result. | ||
*/ | ||
int dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result); | ||
|
||
#endif /* _HMAC_H_ */ |
Oops, something went wrong.