4
* Version: $Id: mppe_keys.c,v 1.3 2004/02/26 19:04:31 aland Exp $
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* Copyright 2002 Axis Communications AB
21
* Authors: Henrik Eriksson <henriken@axis.com> & Lars Viklund <larsv@axis.com>
24
#include <openssl/hmac.h>
28
* Add value pair to reply
30
static void add_reply(VALUE_PAIR** vp,
31
const char* name, const char* value, int len)
33
VALUE_PAIR *reply_attr;
34
reply_attr = pairmake(name, "", T_OP_EQ);
37
"add_reply failed to create attribute %s: %s\n",
42
memcpy(reply_attr->strvalue, value, len);
43
reply_attr->length = len;
44
pairadd(vp, reply_attr);
48
* TLS PRF from RFC 2246
50
static void P_hash(const EVP_MD *evp_md,
51
const unsigned char *secret, unsigned int secret_len,
52
const unsigned char *seed, unsigned int seed_len,
53
unsigned char *out, unsigned int out_len)
55
HMAC_CTX ctx_a, ctx_out;
56
unsigned char a[HMAC_MAX_MD_CBLOCK];
59
HMAC_CTX_init(&ctx_a);
60
HMAC_CTX_init(&ctx_out);
61
HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL);
62
HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL);
64
size = HMAC_size(&ctx_out);
67
HMAC_Update(&ctx_a, seed, seed_len);
68
HMAC_Final(&ctx_a, a, NULL);
71
/* Calculate next part of output */
72
HMAC_Update(&ctx_out, a, size);
73
HMAC_Update(&ctx_out, seed, seed_len);
75
/* Check if last part */
77
HMAC_Final(&ctx_out, a, NULL);
78
memcpy(out, a, out_len);
82
/* Place digest in output buffer */
83
HMAC_Final(&ctx_out, out, NULL);
84
HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL);
88
/* Calculate next A(i) */
89
HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL);
90
HMAC_Update(&ctx_a, a, size);
91
HMAC_Final(&ctx_a, a, NULL);
94
HMAC_CTX_cleanup(&ctx_a);
95
HMAC_CTX_cleanup(&ctx_out);
96
memset(a, 0, sizeof(a));
99
static void PRF(const unsigned char *secret, unsigned int secret_len,
100
const unsigned char *seed, unsigned int seed_len,
101
unsigned char *out, unsigned char *buf, unsigned int out_len)
104
unsigned int len = (secret_len + 1) / 2;
105
const unsigned char *s1 = secret;
106
const unsigned char *s2 = secret + (secret_len - len);
108
P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len);
109
P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len);
111
for (i=0; i < out_len; i++) {
116
#define EAPTLS_MPPE_KEY_LEN 32
118
#define EAPTLS_PRF_LABEL "ttls keying material"
121
* Generate keys according to RFC 2716 and add to reply
123
void eaptls_gen_mppe_keys(VALUE_PAIR **reply_vps, SSL *s,
124
const char *prf_label)
126
unsigned char out[2*EAPTLS_MPPE_KEY_LEN], buf[2*EAPTLS_MPPE_KEY_LEN];
127
unsigned char seed[64 + 2*SSL3_RANDOM_SIZE];
128
unsigned char *p = seed;
131
prf_size = strlen(prf_label);
133
memcpy(p, prf_label, prf_size);
136
memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
137
p += SSL3_RANDOM_SIZE;
138
prf_size += SSL3_RANDOM_SIZE;
140
memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
141
prf_size += SSL3_RANDOM_SIZE;
143
PRF(s->session->master_key, s->session->master_key_length,
144
seed, prf_size, out, buf, sizeof(out));
147
add_reply(reply_vps, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN);
148
p += EAPTLS_MPPE_KEY_LEN;
149
add_reply(reply_vps, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN);
153
#define EAPTLS_PRF_CHALLENGE "ttls challenge"
156
* Generate the TTLS challenge
158
* It's in the TLS module simply because it's only a few lines
159
* of code, and it needs access to the TLS PRF functions.
161
void eapttls_gen_challenge(SSL *s, char *buffer, int size)
163
unsigned char out[32], buf[32];
164
unsigned char seed[sizeof(EAPTLS_PRF_CHALLENGE)-1 + 2*SSL3_RANDOM_SIZE];
165
unsigned char *p = seed;
167
memcpy(p, EAPTLS_PRF_CHALLENGE, sizeof(EAPTLS_PRF_CHALLENGE)-1);
168
p += sizeof(EAPTLS_PRF_CHALLENGE)-1;
169
memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
170
p += SSL3_RANDOM_SIZE;
171
memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
173
PRF(s->session->master_key, s->session->master_key_length,
174
seed, sizeof(seed), out, buf, sizeof(out));
176
memcpy(buffer, out, size);