/* dtls -- a very basic DTLS implementation * * Copyright (C) 2011--2012 Olaf Bergmann * * 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 #include #include #include "dtls_config.h" #ifdef HAVE_ASSERT_H #include #else #define assert(x) #endif #include "debug.h" #include "hmac.h" /* use malloc()/free() on platforms other than Contiki */ #ifndef WITH_CONTIKI #include 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 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