00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "md5.h"
00020 #include "sha1.h"
00021 #include "tlsv1_common.h"
00022 #include "tlsv1_record.h"
00023
00024
00037 int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl,
00038 u16 cipher_suite)
00039 {
00040 const struct tls_cipher_suite *suite;
00041 const struct tls_cipher_data *data;
00042
00043 wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x",
00044 cipher_suite);
00045 rl->cipher_suite = cipher_suite;
00046
00047 suite = tls_get_cipher_suite(cipher_suite);
00048 if (suite == NULL)
00049 return -1;
00050
00051 if (suite->hash == TLS_HASH_MD5) {
00052 rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5;
00053 rl->hash_size = MD5_MAC_LEN;
00054 } else if (suite->hash == TLS_HASH_SHA) {
00055 rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1;
00056 rl->hash_size = SHA1_MAC_LEN;
00057 }
00058
00059 data = tls_get_cipher_data(suite->cipher);
00060 if (data == NULL)
00061 return -1;
00062
00063 rl->key_material_len = data->key_material;
00064 rl->iv_size = data->block_size;
00065 rl->cipher_alg = data->alg;
00066
00067 return 0;
00068 }
00069
00070
00080 int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl)
00081 {
00082 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite "
00083 "0x%04x", rl->cipher_suite);
00084 rl->write_cipher_suite = rl->cipher_suite;
00085 os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN);
00086
00087 if (rl->write_cbc) {
00088 crypto_cipher_deinit(rl->write_cbc);
00089 rl->write_cbc = NULL;
00090 }
00091 if (rl->cipher_alg != CRYPTO_CIPHER_NULL) {
00092 rl->write_cbc = crypto_cipher_init(rl->cipher_alg,
00093 rl->write_iv, rl->write_key,
00094 rl->key_material_len);
00095 if (rl->write_cbc == NULL) {
00096 wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize "
00097 "cipher");
00098 return -1;
00099 }
00100 }
00101
00102 return 0;
00103 }
00104
00105
00115 int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl)
00116 {
00117 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite "
00118 "0x%04x", rl->cipher_suite);
00119 rl->read_cipher_suite = rl->cipher_suite;
00120 os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN);
00121
00122 if (rl->read_cbc) {
00123 crypto_cipher_deinit(rl->read_cbc);
00124 rl->read_cbc = NULL;
00125 }
00126 if (rl->cipher_alg != CRYPTO_CIPHER_NULL) {
00127 rl->read_cbc = crypto_cipher_init(rl->cipher_alg,
00128 rl->read_iv, rl->read_key,
00129 rl->key_material_len);
00130 if (rl->read_cbc == NULL) {
00131 wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize "
00132 "cipher");
00133 return -1;
00134 }
00135 }
00136
00137 return 0;
00138 }
00139
00140
00157 int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
00158 size_t buf_size, size_t payload_len, size_t *out_len)
00159 {
00160 u8 *pos, *ct_start, *length, *payload;
00161 struct crypto_hash *hmac;
00162 size_t clen;
00163
00164 pos = buf;
00165
00166 ct_start = pos;
00167 *pos++ = content_type;
00168
00169 WPA_PUT_BE16(pos, TLS_VERSION);
00170 pos += 2;
00171
00172 length = pos;
00173 WPA_PUT_BE16(length, payload_len);
00174 pos += 2;
00175
00176
00177 payload = pos;
00178 pos += payload_len;
00179
00180 if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
00181 hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret,
00182 rl->hash_size);
00183 if (hmac == NULL) {
00184 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
00185 "to initialize HMAC");
00186 return -1;
00187 }
00188 crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN);
00189
00190 crypto_hash_update(hmac, ct_start, pos - ct_start);
00191 clen = buf + buf_size - pos;
00192 if (clen < rl->hash_size) {
00193 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not "
00194 "enough room for MAC");
00195 crypto_hash_finish(hmac, NULL, NULL);
00196 return -1;
00197 }
00198
00199 if (crypto_hash_finish(hmac, pos, &clen) < 0) {
00200 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
00201 "to calculate HMAC");
00202 return -1;
00203 }
00204 wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC",
00205 pos, clen);
00206 pos += clen;
00207 if (rl->iv_size) {
00208 size_t len = pos - payload;
00209 size_t pad;
00210 pad = (len + 1) % rl->iv_size;
00211 if (pad)
00212 pad = rl->iv_size - pad;
00213 if (pos + pad + 1 > buf + buf_size) {
00214 wpa_printf(MSG_DEBUG, "TLSv1: No room for "
00215 "block cipher padding");
00216 return -1;
00217 }
00218 os_memset(pos, pad, pad + 1);
00219 pos += pad + 1;
00220 }
00221
00222 if (crypto_cipher_encrypt(rl->write_cbc, payload,
00223 payload, pos - payload) < 0)
00224 return -1;
00225 }
00226
00227 WPA_PUT_BE16(length, pos - length - 2);
00228 inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN);
00229
00230 *out_len = pos - buf;
00231
00232 return 0;
00233 }
00234
00235
00251 int tlsv1_record_receive(struct tlsv1_record_layer *rl,
00252 const u8 *in_data, size_t in_len,
00253 u8 *out_data, size_t *out_len, u8 *alert)
00254 {
00255 size_t i, rlen, hlen;
00256 u8 padlen;
00257 struct crypto_hash *hmac;
00258 u8 len[2], hash[100];
00259
00260 wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received",
00261 in_data, in_len);
00262
00263 if (in_len < TLS_RECORD_HEADER_LEN) {
00264 wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)",
00265 (unsigned long) in_len);
00266 *alert = TLS_ALERT_DECODE_ERROR;
00267 return -1;
00268 }
00269
00270 wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d "
00271 "length %d", in_data[0], in_data[1], in_data[2],
00272 WPA_GET_BE16(in_data + 3));
00273
00274 if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE &&
00275 in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC &&
00276 in_data[0] != TLS_CONTENT_TYPE_ALERT &&
00277 in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) {
00278 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x",
00279 in_data[0]);
00280 *alert = TLS_ALERT_UNEXPECTED_MESSAGE;
00281 return -1;
00282 }
00283
00284 if (WPA_GET_BE16(in_data + 1) != TLS_VERSION) {
00285 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version "
00286 "%d.%d", in_data[1], in_data[2]);
00287 *alert = TLS_ALERT_PROTOCOL_VERSION;
00288 return -1;
00289 }
00290
00291 rlen = WPA_GET_BE16(in_data + 3);
00292
00293
00294 if (TLS_RECORD_HEADER_LEN + rlen > 18432) {
00295 wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)",
00296 (unsigned long) (TLS_RECORD_HEADER_LEN + rlen));
00297 *alert = TLS_ALERT_RECORD_OVERFLOW;
00298 return -1;
00299 }
00300
00301 in_data += TLS_RECORD_HEADER_LEN;
00302 in_len -= TLS_RECORD_HEADER_LEN;
00303
00304 if (rlen > in_len) {
00305 wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included "
00306 "(rlen=%lu > in_len=%lu)",
00307 (unsigned long) rlen, (unsigned long) in_len);
00308 *alert = TLS_ALERT_DECODE_ERROR;
00309 return -1;
00310 }
00311
00312 in_len = rlen;
00313
00314 if (*out_len < in_len) {
00315 wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for "
00316 "processing received record");
00317 *alert = TLS_ALERT_INTERNAL_ERROR;
00318 return -1;
00319 }
00320
00321 os_memcpy(out_data, in_data, in_len);
00322 *out_len = in_len;
00323
00324 if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
00325 if (crypto_cipher_decrypt(rl->read_cbc, out_data,
00326 out_data, in_len) < 0) {
00327 *alert = TLS_ALERT_DECRYPTION_FAILED;
00328 return -1;
00329 }
00330 if (rl->iv_size) {
00331 if (in_len == 0) {
00332 wpa_printf(MSG_DEBUG, "TLSv1: Too short record"
00333 " (no pad)");
00334 *alert = TLS_ALERT_DECODE_ERROR;
00335 return -1;
00336 }
00337 padlen = out_data[in_len - 1];
00338 if (padlen >= in_len) {
00339 wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad "
00340 "length (%u, in_len=%lu) in "
00341 "received record",
00342 padlen, (unsigned long) in_len);
00343 *alert = TLS_ALERT_DECRYPTION_FAILED;
00344 return -1;
00345 }
00346 for (i = in_len - padlen; i < in_len; i++) {
00347 if (out_data[i] != padlen) {
00348 wpa_hexdump(MSG_DEBUG,
00349 "TLSv1: Invalid pad in "
00350 "received record",
00351 out_data + in_len - padlen,
00352 padlen);
00353 *alert = TLS_ALERT_DECRYPTION_FAILED;
00354 return -1;
00355 }
00356 }
00357
00358 *out_len -= padlen + 1;
00359 }
00360
00361 wpa_hexdump(MSG_MSGDUMP,
00362 "TLSv1: Record Layer - Decrypted data",
00363 out_data, in_len);
00364
00365 if (*out_len < rl->hash_size) {
00366 wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no "
00367 "hash value");
00368 *alert = TLS_ALERT_INTERNAL_ERROR;
00369 return -1;
00370 }
00371
00372 *out_len -= rl->hash_size;
00373
00374 hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret,
00375 rl->hash_size);
00376 if (hmac == NULL) {
00377 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
00378 "to initialize HMAC");
00379 *alert = TLS_ALERT_INTERNAL_ERROR;
00380 return -1;
00381 }
00382
00383 crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN);
00384
00385 crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3);
00386 WPA_PUT_BE16(len, *out_len);
00387 crypto_hash_update(hmac, len, 2);
00388 crypto_hash_update(hmac, out_data, *out_len);
00389 hlen = sizeof(hash);
00390 if (crypto_hash_finish(hmac, hash, &hlen) < 0) {
00391 wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
00392 "to calculate HMAC");
00393 return -1;
00394 }
00395 if (hlen != rl->hash_size ||
00396 os_memcmp(hash, out_data + *out_len, hlen) != 0) {
00397 wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in "
00398 "received message");
00399 *alert = TLS_ALERT_BAD_RECORD_MAC;
00400 return -1;
00401 }
00402 }
00403
00404
00405 if (TLS_RECORD_HEADER_LEN + *out_len > 17408) {
00406 wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)",
00407 (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len));
00408 *alert = TLS_ALERT_RECORD_OVERFLOW;
00409 return -1;
00410 }
00411
00412 inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN);
00413
00414 return 0;
00415 }
00416