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