2
* This file is part of libESMTP, a library for submission of RFC 2822
3
* formatted electronic mail messages using the SMTP protocol described
6
* Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include <sys/types.h>
33
* the HMAC_MD5 transform looks like:
35
* MD5(K XOR opad, MD5(K XOR ipad, challenge))
37
* where K is an n byte secret
38
* ipad is the byte 0x36 repeated 64 times
39
* opad is the byte 0x5c repeated 64 times
40
* and challenge is the data being protected
43
/* Precompute HMAC-MD5 contexts from a secret
46
hmac_md5_pre (const void *secret, size_t secret_len,
47
MD5_CTX *inner, MD5_CTX *outer)
49
unsigned char ipad[PAD_SIZE];
50
unsigned char opad[PAD_SIZE];
54
/* If secret is longer than 64 bytes reset it to secret = MD5 (secret)
56
if (secret_len > PAD_SIZE)
61
MD5_Update (&tctx, secret, secret_len);
62
MD5_Final (tk, &tctx);
64
secret_len = sizeof tk;
67
/* start out by storing secret in pads */
68
memcpy (ipad, secret, secret_len);
69
if (secret_len < sizeof ipad)
70
memset (ipad + secret_len, 0, sizeof ipad - secret_len);
71
memcpy (opad, secret, secret_len);
72
if (secret_len < sizeof opad)
73
memset (opad + secret_len, 0, sizeof opad - secret_len);
75
/* XOR secret with ipad and opad values */
76
for (i = 0; i < PAD_SIZE; i++)
82
/* perform inner MD5 */
84
MD5_Update (inner, ipad, sizeof ipad);
86
/* perform outer MD5 */
88
MD5_Update (outer, opad, sizeof opad);
91
/* Finalise HMAC-MD5 contexts from a challenge
94
hmac_md5_post (const void *challenge, size_t challenge_len,
95
MD5_CTX *inner, MD5_CTX *outer, unsigned char digest[16])
99
/* perform inner MD5 */
100
MD5_Update (inner, challenge, challenge_len);
101
MD5_Final (id, inner);
103
/* perform outer MD5 */
104
MD5_Update (outer, id, sizeof id);
105
MD5_Final (digest, outer);
108
/* Digest a challenge and a secret.
111
hmac_md5 (const void *challenge, size_t challenge_len,
112
const void *secret, size_t secret_len,
113
unsigned char digest[16])
115
MD5_CTX inner, outer;
117
hmac_md5_pre (secret, secret_len, &inner, &outer);
118
hmac_md5_post (challenge, challenge_len, &inner, &outer, digest);