Version 0.5.0 of tinydtls
Dependents: tinydtls_test_cellular tinydtls_test_ethernet tiny-dtls
Diff: hmac.c
- Revision:
- 0:ff9ebe0cf0e9
diff -r 000000000000 -r ff9ebe0cf0e9 hmac.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hmac.c Fri Oct 18 13:18:30 2013 +0000 @@ -0,0 +1,168 @@ +/* dtls -- a very basic DTLS implementation + * + * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org> + * + * 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> +#ifdef HAVE_ASSERT_H +#include <assert.h> +#endif + +#include "debug.h" +#include "hmac.h" + +/* use malloc()/free() on platforms other than Contiki */ +#ifndef WITH_CONTIKI +#include <stdlib.h> + +static inline dtls_hmac_context_t * +dtls_hmac_context_new() { + return (dtls_hmac_context_t *)malloc(sizeof(dtls_hmac_context_t)); +} + +static inline void +dtls_hmac_context_free(dtls_hmac_context_t *ctx) { + free(ctx); +} + +#else /* WITH_CONTIKI */ +#include "memb.h" +MEMB(hmac_context_storage, dtls_hmac_context_t, DTLS_HASH_MAX); + +static inline dtls_hmac_context_t * +dtls_hmac_context_new() { + return (dtls_hmac_context_t *)memb_alloc(&hmac_context_storage); +} + +static inline void +dtls_hmac_context_free(dtls_hmac_context_t *ctx) { + memb_free(&hmac_context_storage, ctx); +} + +void +dtls_hmac_storage_init() { + memb_init(&hmac_context_storage); +} +#endif /* WITH_CONTIKI */ + +void +dtls_hmac_update(dtls_hmac_context_t *ctx, + const unsigned char *input, size_t ilen) { + assert(ctx); + dtls_hash_update(&ctx->data, input, ilen); +} + +dtls_hmac_context_t * +dtls_hmac_new(const unsigned char *key, size_t klen) { + dtls_hmac_context_t *ctx; + + ctx = dtls_hmac_context_new(); + if (ctx) + dtls_hmac_init(ctx, key, klen); + + return ctx; +} + +void +dtls_hmac_init(dtls_hmac_context_t *ctx, const unsigned char *key, size_t klen) { + int i; + + assert(ctx); + + memset(ctx, 0, sizeof(dtls_hmac_context_t)); + + if (klen > DTLS_HMAC_BLOCKSIZE) { + dtls_hash_init(&ctx->data); + dtls_hash_update(&ctx->data, key, klen); + dtls_hash_finalize(ctx->pad, &ctx->data); + } else + memcpy(ctx->pad, key, klen); + + /* create ipad: */ + for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i) + ctx->pad[i] ^= 0x36; + + dtls_hash_init(&ctx->data); + dtls_hmac_update(ctx, ctx->pad, DTLS_HMAC_BLOCKSIZE); + + /* create opad by xor-ing pad[i] with 0x36 ^ 0x5C: */ + for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i) + ctx->pad[i] ^= 0x6A; +} + +void +dtls_hmac_free(dtls_hmac_context_t *ctx) { + if (ctx) + dtls_hmac_context_free(ctx); +} + +int +dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result) { + unsigned char buf[DTLS_HMAC_DIGEST_SIZE]; + size_t len; + + assert(ctx); + assert(result); + + len = dtls_hash_finalize(buf, &ctx->data); + + dtls_hash_init(&ctx->data); + dtls_hash_update(&ctx->data, ctx->pad, DTLS_HMAC_BLOCKSIZE); + dtls_hash_update(&ctx->data, buf, len); + + len = dtls_hash_finalize(result, &ctx->data); + + return len; +} + +#ifdef HMAC_TEST +#include <stdio.h> + +int main(int argc, char **argv) { + static unsigned char buf[DTLS_HMAC_DIGEST_SIZE]; + size_t len, i; + dtls_hmac_context_t *ctx; + + if (argc < 3) { + fprintf(stderr, "usage: %s key text", argv[0]); + return -1; + } + + dtls_hmac_storage_init(); + ctx = dtls_hmac_new(argv[1], strlen(argv[1])); + assert(ctx); + dtls_hmac_update(ctx, argv[2], strlen(argv[2])); + + len = dtls_hmac_finalize(ctx, buf); + + for(i = 0; i < len; i++) + printf("%02x", buf[i]); + printf("\n"); + + dtls_hmac_free(ctx); + + return 0; +} +#endif