void openvpn_hmac_calc (unsigned char *dest, unsigned char *src, uint16_t len) { const unsigned char *hmac_key = (const unsigned char *)CONF_OPENVPN_HMAC_KEY; unsigned char buf[64]; /* perform inner part of hmac */ md5_ctx_t ctx_inner; md5_init (&ctx_inner); for (int i = 0; i < 16; i ++) buf[i] = hmac_key[i] ^ 0x36; for (int i = 16; i < 64; i ++) buf[i] = 0x36; md5_nextBlock (&ctx_inner, buf); md5_lastBlock (&ctx_inner, src, len << 3); /* perform outer part of hmac */ md5_ctx_t ctx_outer; md5_init (&ctx_outer); for (int i = 0; i < 16; i ++) buf[i] = hmac_key[i] ^ 0x5c; for (int i = 16; i < 64; i ++) buf[i] = 0x5c; md5_nextBlock (&ctx_outer, buf); md5_lastBlock (&ctx_outer, (void *) &ctx_inner.a[0], 128); memmove (dest, (void *) &ctx_outer.a[0], 16); }
/* * keylength in bits! * message length in bits! */ void hmac_md5(void *dest, void *key, uint16_t keylength_b, void *msg, uint32_t msglength_b){ /* a one-shot*/ md5_ctx_t s; uint8_t i; uint8_t buffer[MD5_BLOCK_BYTES]; memset(buffer, 0, MD5_BLOCK_BYTES); /* if key is larger than a block we have to hash it*/ if (keylength_b > MD5_BLOCK_BITS){ md5((void*)buffer, key, keylength_b); } else { memcpy(buffer, key, (keylength_b+7)/8); } for (i=0; i<MD5_BLOCK_BYTES; ++i){ buffer[i] ^= IPAD; } md5_init(&s); md5_nextBlock(&s, buffer); while (msglength_b >= MD5_BLOCK_BITS){ md5_nextBlock(&s, msg); msg = (uint8_t*)msg + MD5_BLOCK_BYTES; msglength_b -= MD5_BLOCK_BITS; } md5_lastBlock(&s, msg, msglength_b); /* since buffer still contains key xor ipad we can do ... */ for (i=0; i<MD5_BLOCK_BYTES; ++i){ buffer[i] ^= IPAD ^ OPAD; } md5_ctx2hash(dest, &s); /* save inner hash temporary to dest */ md5_init(&s); md5_nextBlock(&s, buffer); md5_lastBlock(&s, dest, MD5_HASH_BITS); md5_ctx2hash(dest, &s); }
void hmac_md5_final(void *dest, hmac_md5_ctx_t *s){ md5_ctx2hash((md5_hash_t*)dest, &(s->a)); md5_lastBlock(&(s->b), dest, MD5_HASH_BITS); md5_ctx2hash((md5_hash_t*)dest, &(s->b)); }
void hmac_md5_lastBlock(hmac_md5_ctx_t *s, const void *block, uint16_t length_b){ md5_lastBlock(&(s->a), block, length_b); }