1214501Srpaulo/* 2214501Srpaulo * MD5 hash implementation and interface functions (non-FIPS allowed cases) 3214501Srpaulo * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5214501Srpaulo * This program is free software; you can redistribute it and/or modify 6214501Srpaulo * it under the terms of the GNU General Public License version 2 as 7214501Srpaulo * published by the Free Software Foundation. 8214501Srpaulo * 9214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD 10214501Srpaulo * license. 11214501Srpaulo * 12214501Srpaulo * See README and COPYING for more details. 13214501Srpaulo */ 14214501Srpaulo 15214501Srpaulo#include "includes.h" 16214501Srpaulo 17214501Srpaulo#include "common.h" 18214501Srpaulo#include "md5.h" 19214501Srpaulo#include "crypto.h" 20214501Srpaulo 21214501Srpaulo 22214501Srpaulo/** 23214501Srpaulo * hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104) 24214501Srpaulo * @key: Key for HMAC operations 25214501Srpaulo * @key_len: Length of the key in bytes 26214501Srpaulo * @num_elem: Number of elements in the data vector 27214501Srpaulo * @addr: Pointers to the data areas 28214501Srpaulo * @len: Lengths of the data blocks 29214501Srpaulo * @mac: Buffer for the hash (16 bytes) 30214501Srpaulo * Returns: 0 on success, -1 on failure 31214501Srpaulo */ 32214501Srpauloint hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, 33214501Srpaulo size_t num_elem, const u8 *addr[], 34214501Srpaulo const size_t *len, u8 *mac) 35214501Srpaulo{ 36214501Srpaulo u8 k_pad[64]; /* padding - key XORd with ipad/opad */ 37214501Srpaulo u8 tk[16]; 38214501Srpaulo const u8 *_addr[6]; 39214501Srpaulo size_t i, _len[6]; 40214501Srpaulo 41214501Srpaulo if (num_elem > 5) { 42214501Srpaulo /* 43214501Srpaulo * Fixed limit on the number of fragments to avoid having to 44214501Srpaulo * allocate memory (which could fail). 45214501Srpaulo */ 46214501Srpaulo return -1; 47214501Srpaulo } 48214501Srpaulo 49214501Srpaulo /* if key is longer than 64 bytes reset it to key = MD5(key) */ 50214501Srpaulo if (key_len > 64) { 51214501Srpaulo if (md5_vector_non_fips_allow(1, &key, &key_len, tk)) 52214501Srpaulo return -1; 53214501Srpaulo key = tk; 54214501Srpaulo key_len = 16; 55214501Srpaulo } 56214501Srpaulo 57214501Srpaulo /* the HMAC_MD5 transform looks like: 58214501Srpaulo * 59214501Srpaulo * MD5(K XOR opad, MD5(K XOR ipad, text)) 60214501Srpaulo * 61214501Srpaulo * where K is an n byte key 62214501Srpaulo * ipad is the byte 0x36 repeated 64 times 63214501Srpaulo * opad is the byte 0x5c repeated 64 times 64214501Srpaulo * and text is the data being protected */ 65214501Srpaulo 66214501Srpaulo /* start out by storing key in ipad */ 67214501Srpaulo os_memset(k_pad, 0, sizeof(k_pad)); 68214501Srpaulo os_memcpy(k_pad, key, key_len); 69214501Srpaulo 70214501Srpaulo /* XOR key with ipad values */ 71214501Srpaulo for (i = 0; i < 64; i++) 72214501Srpaulo k_pad[i] ^= 0x36; 73214501Srpaulo 74214501Srpaulo /* perform inner MD5 */ 75214501Srpaulo _addr[0] = k_pad; 76214501Srpaulo _len[0] = 64; 77214501Srpaulo for (i = 0; i < num_elem; i++) { 78214501Srpaulo _addr[i + 1] = addr[i]; 79214501Srpaulo _len[i + 1] = len[i]; 80214501Srpaulo } 81214501Srpaulo if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac)) 82214501Srpaulo return -1; 83214501Srpaulo 84214501Srpaulo os_memset(k_pad, 0, sizeof(k_pad)); 85214501Srpaulo os_memcpy(k_pad, key, key_len); 86214501Srpaulo /* XOR key with opad values */ 87214501Srpaulo for (i = 0; i < 64; i++) 88214501Srpaulo k_pad[i] ^= 0x5c; 89214501Srpaulo 90214501Srpaulo /* perform outer MD5 */ 91214501Srpaulo _addr[0] = k_pad; 92214501Srpaulo _len[0] = 64; 93214501Srpaulo _addr[1] = mac; 94214501Srpaulo _len[1] = MD5_MAC_LEN; 95214501Srpaulo return md5_vector_non_fips_allow(2, _addr, _len, mac); 96214501Srpaulo} 97214501Srpaulo 98214501Srpaulo 99214501Srpaulo/** 100214501Srpaulo * hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104) 101214501Srpaulo * @key: Key for HMAC operations 102214501Srpaulo * @key_len: Length of the key in bytes 103214501Srpaulo * @data: Pointers to the data area 104214501Srpaulo * @data_len: Length of the data area 105214501Srpaulo * @mac: Buffer for the hash (16 bytes) 106214501Srpaulo * Returns: 0 on success, -1 on failure 107214501Srpaulo */ 108214501Srpauloint hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, 109214501Srpaulo size_t data_len, u8 *mac) 110214501Srpaulo{ 111214501Srpaulo return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data, 112214501Srpaulo &data_len, mac); 113214501Srpaulo} 114