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_init(hmac_md5_ctx_t *s, void *key, uint16_t keylength_b){ uint8_t buffer[MD5_BLOCK_BYTES]; uint8_t i; memset(buffer, 0, MD5_BLOCK_BYTES); 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->a)); md5_nextBlock(&(s->a), buffer); for (i=0; i<MD5_BLOCK_BYTES; ++i){ buffer[i] ^= IPAD^OPAD; } md5_init(&(s->b)); md5_nextBlock(&(s->b), buffer); #if defined SECURE_WIPE_BUFFER memset(buffer, 0, MD5_BLOCK_BYTES); #endif }
void md5_lastBlock(md5_ctx_t *state, const void* block, uint16_t length_b){ uint16_t l; uint8_t b[64]; while (length_b >= 512){ md5_nextBlock(state, block); length_b -= 512; block = ((uint8_t*)block) + 512/8; } memset(b, 0, 64); memcpy(b, block, length_b/8); /* insert padding one */ l=length_b/8; if(length_b%8){ uint8_t t; t = ((uint8_t*)block)[l]; t |= (0x80>>(length_b%8)); b[l]=t; }else{
void hmac_md5_nextBlock(hmac_md5_ctx_t *s, const void *block){ md5_nextBlock(&(s->a), block); }