Derive master secret, create Finished message
[strongswan.git] / src / charon / plugins / eap_tls / tls / tls_crypto.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "tls_crypto.h"
17
18 #include <daemon.h>
19
20 typedef struct private_tls_crypto_t private_tls_crypto_t;
21
22 /**
23 * Private data of an tls_crypto_t object.
24 */
25 struct private_tls_crypto_t {
26
27 /**
28 * Public tls_crypto_t interface.
29 */
30 tls_crypto_t public;
31
32 /**
33 * List of supported/acceptable cipher suites
34 */
35 tls_cipher_suite_t *suites;
36
37 /**
38 * Number of supported suites
39 */
40 int suite_count;
41
42 /**
43 * Selected cipher suite
44 */
45 tls_cipher_suite_t suite;
46
47 /**
48 * TLS context
49 */
50 tls_t *tls;
51
52 /**
53 * Connection state TLS PRF
54 */
55 tls_prf_t *prf;
56 };
57
58 /**
59 * Initialize the cipher suite list
60 */
61 static void build_cipher_suite_list(private_tls_crypto_t *this)
62 {
63 encryption_algorithm_t encr;
64 integrity_algorithm_t mac;
65 enumerator_t *encrs, *macs;
66 tls_cipher_suite_t supported[64], unique[64];
67 int count = 0, i, j;
68
69 /* we assume that we support RSA, but no DHE yet */
70 macs = lib->crypto->create_signer_enumerator(lib->crypto);
71 while (macs->enumerate(macs, &mac))
72 {
73 switch (mac)
74 {
75 case AUTH_HMAC_SHA1_160:
76 supported[count++] = TLS_RSA_WITH_NULL_SHA;
77 break;
78 case AUTH_HMAC_SHA2_256_256:
79 supported[count++] = TLS_RSA_WITH_NULL_SHA256;
80 break;
81 case AUTH_HMAC_MD5_128:
82 supported[count++] = TLS_RSA_WITH_NULL_MD5;
83 break;
84 default:
85 break;
86 }
87 encrs = lib->crypto->create_crypter_enumerator(lib->crypto);
88 while (encrs->enumerate(encrs, &encr))
89 {
90 switch (encr)
91 {
92 case ENCR_AES_CBC:
93 switch (mac)
94 {
95 case AUTH_HMAC_SHA1_160:
96 supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
97 supported[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
98 break;
99 case AUTH_HMAC_SHA2_256_256:
100 supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
101 supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
102 break;
103 default:
104 break;
105 }
106 break;
107 case ENCR_3DES:
108 switch (mac)
109 {
110 case AUTH_HMAC_SHA1_160:
111 supported[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
112 break;
113 default:
114 break;
115 }
116 break;
117 default:
118 break;
119 }
120 }
121 encrs->destroy(encrs);
122 }
123 macs->destroy(macs);
124
125 /* remove duplicates */
126 this->suite_count = 0;
127 for (i = 0; i < count; i++)
128 {
129 bool match = FALSE;
130
131 for (j = 0; j < this->suite_count; j++)
132 {
133 if (supported[i] == unique[j])
134 {
135 match = TRUE;
136 break;
137 }
138 }
139 if (!match)
140 {
141 unique[this->suite_count++] = supported[i];
142 }
143 }
144 free(this->suites);
145 this->suites = malloc(sizeof(tls_cipher_suite_t) * this->suite_count);
146 memcpy(this->suites, unique, sizeof(tls_cipher_suite_t) * this->suite_count);
147 }
148
149 METHOD(tls_crypto_t, get_cipher_suites, int,
150 private_tls_crypto_t *this, tls_cipher_suite_t **suites)
151 {
152 *suites = this->suites;
153 return this->suite_count;
154 }
155
156 METHOD(tls_crypto_t, select_cipher_suite, tls_cipher_suite_t,
157 private_tls_crypto_t *this, tls_cipher_suite_t *suites, int count)
158 {
159 int i, j;
160
161 for (i = 0; i < this->suite_count; i++)
162 {
163 for (j = 0; j < count; j++)
164 {
165 if (this->suites[i] == suites[j])
166 {
167 this->suite = this->suites[i];
168 return this->suite;
169 }
170 }
171 }
172 return 0;
173 }
174
175 METHOD(tls_crypto_t, derive_master_secret, void,
176 private_tls_crypto_t *this, chunk_t premaster,
177 chunk_t client_random, chunk_t server_random)
178 {
179 if (!this->prf)
180 {
181 if (this->tls->get_version(this->tls) < TLS_1_2)
182 {
183 this->prf = tls_prf_create_10();
184 }
185 else
186 {
187 switch (this->suite)
188 {
189 case TLS_RSA_WITH_NULL_MD5:
190 this->prf = tls_prf_create_12(PRF_HMAC_MD5);
191 break;
192 case TLS_RSA_WITH_AES_128_CBC_SHA:
193 case TLS_RSA_WITH_AES_256_CBC_SHA:
194 case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
195 case TLS_RSA_WITH_NULL_SHA:
196 this->prf = tls_prf_create_12(PRF_HMAC_SHA1);
197 break;
198 case TLS_RSA_WITH_AES_128_CBC_SHA256:
199 case TLS_RSA_WITH_NULL_SHA256:
200 this->prf = tls_prf_create_12(PRF_HMAC_SHA2_256);
201 break;
202 default:
203 DBG1(DBG_IKE, "PRF for cipher suite unknown");
204 break;
205 }
206 }
207 }
208 if (this->prf)
209 {
210 char master[48];
211 chunk_t seed;
212
213 seed = chunk_cata("cc", client_random, server_random);
214 this->prf->set_key(this->prf, premaster);
215 this->prf->get_bytes(this->prf, "master secret", seed,
216 sizeof(master), master);
217
218 this->prf->set_key(this->prf, chunk_from_thing(master));
219 memset(master, 0, sizeof(master));
220 }
221 }
222
223 METHOD(tls_crypto_t, get_prf, tls_prf_t*,
224 private_tls_crypto_t *this)
225 {
226
227 return this->prf;
228 }
229
230 METHOD(tls_crypto_t, destroy, void,
231 private_tls_crypto_t *this)
232 {
233 free(this->suites);
234 DESTROY_IF(this->prf);
235 free(this);
236 }
237
238 /**
239 * See header
240 */
241 tls_crypto_t *tls_crypto_create(tls_t *tls)
242 {
243 private_tls_crypto_t *this;
244
245 INIT(this,
246 .public = {
247 .get_cipher_suites = _get_cipher_suites,
248 .select_cipher_suite = _select_cipher_suite,
249 .derive_master_secret = _derive_master_secret,
250 .get_prf = _get_prf,
251 .destroy = _destroy,
252 },
253 .tls = tls,
254 );
255
256 build_cipher_suite_list(this);
257
258 return &this->public;
259 }