mbed port of tinydtls

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac.c Source File

hmac.c

00001 /* dtls -- a very basic DTLS implementation
00002  *
00003  * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
00004  *
00005  * Permission is hereby granted, free of charge, to any person
00006  * obtaining a copy of this software and associated documentation
00007  * files (the "Software"), to deal in the Software without
00008  * restriction, including without limitation the rights to use, copy,
00009  * modify, merge, publish, distribute, sublicense, and/or sell copies
00010  * of the Software, and to permit persons to whom the Software is
00011  * furnished to do so, subject to the following conditions:
00012  *
00013  * The above copyright notice and this permission notice shall be
00014  * included in all copies or substantial portions of the Software.
00015  *
00016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
00020  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00021  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00023  * SOFTWARE.
00024  */
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #ifdef HAVE_ASSERT_H
00030 #include <assert.h>
00031 #endif
00032 
00033 #include "debug.h"
00034 #include "hmac.h"
00035 /* use malloc()/free() on platforms other than Contiki */
00036 #ifndef WITH_CONTIKI
00037 #include <stdlib.h>
00038 
00039 static inline dtls_hmac_context_t *
00040 dtls_hmac_context_new() {
00041   return (dtls_hmac_context_t *)malloc(sizeof(dtls_hmac_context_t));
00042 }
00043 
00044 static inline void
00045 dtls_hmac_context_free(dtls_hmac_context_t *ctx) {
00046   free(ctx);
00047 }
00048 
00049 #else /* WITH_CONTIKI */
00050 #include "memb.h"
00051 MEMB(hmac_context_storage, dtls_hmac_context_t, DTLS_HASH_MAX);
00052 
00053 static inline dtls_hmac_context_t *
00054 dtls_hmac_context_new() {
00055   return (dtls_hmac_context_t *)memb_alloc(&hmac_context_storage);
00056 }
00057 
00058 static inline void
00059 dtls_hmac_context_free(dtls_hmac_context_t *ctx) {
00060   memb_free(&hmac_context_storage, ctx);
00061 }
00062 #endif /* WITH_CONTIKI */
00063 
00064 void
00065 dtls_hmac_storage_init() {
00066 #ifdef WITH_CONTIKI
00067   memb_init(&hmac_context_storage);
00068 #endif /* WITH_CONTIKI */
00069 }
00070 
00071 void
00072 dtls_hmac_update(dtls_hmac_context_t *ctx,
00073          const unsigned char *input, size_t ilen) {
00074   assert(ctx);
00075   dtls_hash_update(&ctx->data, input, ilen);
00076 }
00077 
00078 dtls_hmac_context_t *
00079 dtls_hmac_new(const unsigned char *key, size_t klen) {
00080   dtls_hmac_context_t *ctx;
00081 
00082   ctx = dtls_hmac_context_new();
00083   if (ctx) 
00084     dtls_hmac_init(ctx, key, klen);
00085 
00086   return ctx;
00087 }
00088 
00089 void
00090 dtls_hmac_init(dtls_hmac_context_t *ctx, const unsigned char *key, size_t klen) {
00091   int i;
00092 
00093   assert(ctx);
00094 
00095   memset(ctx, 0, sizeof(dtls_hmac_context_t));
00096 
00097   if (klen > DTLS_HMAC_BLOCKSIZE) {
00098     dtls_hash_init(&ctx->data);
00099     dtls_hash_update(&ctx->data, key, klen);
00100     dtls_hash_finalize(ctx->pad, &ctx->data);
00101   } else
00102     memcpy(ctx->pad, key, klen);
00103 
00104   /* create ipad: */
00105   for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i)
00106     ctx->pad[i] ^= 0x36;
00107 
00108   dtls_hash_init(&ctx->data);
00109   dtls_hmac_update(ctx, ctx->pad, DTLS_HMAC_BLOCKSIZE);
00110 
00111   /* create opad by xor-ing pad[i] with 0x36 ^ 0x5C: */
00112   for (i=0; i < DTLS_HMAC_BLOCKSIZE; ++i)
00113     ctx->pad[i] ^= 0x6A;
00114 }
00115 
00116 void
00117 dtls_hmac_free(dtls_hmac_context_t *ctx) {
00118   if (ctx)
00119     dtls_hmac_context_free(ctx);
00120 }
00121 
00122 int
00123 dtls_hmac_finalize(dtls_hmac_context_t *ctx, unsigned char *result) {
00124   unsigned char buf[DTLS_HMAC_DIGEST_SIZE];
00125   size_t len; 
00126 
00127   assert(ctx);
00128   assert(result);
00129   
00130   len = dtls_hash_finalize(buf, &ctx->data);
00131 
00132   dtls_hash_init(&ctx->data);
00133   dtls_hash_update(&ctx->data, ctx->pad, DTLS_HMAC_BLOCKSIZE);
00134   dtls_hash_update(&ctx->data, buf, len);
00135 
00136   len = dtls_hash_finalize(result, &ctx->data);
00137 
00138   return len;
00139 }
00140 
00141 #ifdef HMAC_TEST
00142 #include <stdio.h>
00143 
00144 int main(int argc, char **argv) {
00145   static unsigned char buf[DTLS_HMAC_DIGEST_SIZE];
00146   size_t len, i;
00147   dtls_hmac_context_t *ctx;
00148 
00149   if (argc < 3) {
00150     fprintf(stderr, "usage: %s key text", argv[0]);
00151     return -1;
00152   }
00153 
00154   dtls_hmac_storage_init();
00155   ctx = dtls_hmac_new(argv[1], strlen(argv[1]));
00156   assert(ctx);
00157   dtls_hmac_update(ctx, argv[2], strlen(argv[2]));
00158   
00159   len = dtls_hmac_finalize(ctx, buf);
00160 
00161   for(i = 0; i < len; i++) 
00162     printf("%02x", buf[i]);
00163   printf("\n");
00164 
00165   dtls_hmac_free(ctx);
00166 
00167   return 0;
00168 }
00169 #endif