Line data Source code
1 : /*
2 : * MD5 hash implementation and interface functions
3 : * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "md5.h"
13 : #include "crypto.h"
14 :
15 :
16 : /**
17 : * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104)
18 : * @key: Key for HMAC operations
19 : * @key_len: Length of the key in bytes
20 : * @num_elem: Number of elements in the data vector
21 : * @addr: Pointers to the data areas
22 : * @len: Lengths of the data blocks
23 : * @mac: Buffer for the hash (16 bytes)
24 : * Returns: 0 on success, -1 on failure
25 : */
26 7305 : int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
27 : const u8 *addr[], const size_t *len, u8 *mac)
28 : {
29 : u8 k_pad[64]; /* padding - key XORd with ipad/opad */
30 : u8 tk[16];
31 : const u8 *_addr[6];
32 : size_t i, _len[6];
33 :
34 7305 : if (num_elem > 5) {
35 : /*
36 : * Fixed limit on the number of fragments to avoid having to
37 : * allocate memory (which could fail).
38 : */
39 0 : return -1;
40 : }
41 :
42 : /* if key is longer than 64 bytes reset it to key = MD5(key) */
43 7305 : if (key_len > 64) {
44 0 : if (md5_vector(1, &key, &key_len, tk))
45 0 : return -1;
46 0 : key = tk;
47 0 : key_len = 16;
48 : }
49 :
50 : /* the HMAC_MD5 transform looks like:
51 : *
52 : * MD5(K XOR opad, MD5(K XOR ipad, text))
53 : *
54 : * where K is an n byte key
55 : * ipad is the byte 0x36 repeated 64 times
56 : * opad is the byte 0x5c repeated 64 times
57 : * and text is the data being protected */
58 :
59 : /* start out by storing key in ipad */
60 7305 : os_memset(k_pad, 0, sizeof(k_pad));
61 7305 : os_memcpy(k_pad, key, key_len);
62 :
63 : /* XOR key with ipad values */
64 474825 : for (i = 0; i < 64; i++)
65 467520 : k_pad[i] ^= 0x36;
66 :
67 : /* perform inner MD5 */
68 7305 : _addr[0] = k_pad;
69 7305 : _len[0] = 64;
70 15326 : for (i = 0; i < num_elem; i++) {
71 8021 : _addr[i + 1] = addr[i];
72 8021 : _len[i + 1] = len[i];
73 : }
74 7305 : if (md5_vector(1 + num_elem, _addr, _len, mac))
75 0 : return -1;
76 :
77 7305 : os_memset(k_pad, 0, sizeof(k_pad));
78 7305 : os_memcpy(k_pad, key, key_len);
79 : /* XOR key with opad values */
80 474825 : for (i = 0; i < 64; i++)
81 467520 : k_pad[i] ^= 0x5c;
82 :
83 : /* perform outer MD5 */
84 7305 : _addr[0] = k_pad;
85 7305 : _len[0] = 64;
86 7305 : _addr[1] = mac;
87 7305 : _len[1] = MD5_MAC_LEN;
88 7305 : return md5_vector(2, _addr, _len, mac);
89 : }
90 :
91 :
92 : /**
93 : * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104)
94 : * @key: Key for HMAC operations
95 : * @key_len: Length of the key in bytes
96 : * @data: Pointers to the data area
97 : * @data_len: Length of the data area
98 : * @mac: Buffer for the hash (16 bytes)
99 : * Returns: 0 on success, -1 on failure
100 : */
101 6929 : int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
102 : u8 *mac)
103 : {
104 6929 : return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
105 : }
|