tlsv1_client_read.c
Go to the documentation of this file.
00001 /*
00002  * TLSv1 client - read handshake message
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 "crypto/tls.h"
00021 #include "x509v3.h"
00022 #include "tlsv1_common.h"
00023 #include "tlsv1_record.h"
00024 #include "tlsv1_client.h"
00025 #include "tlsv1_client_i.h"
00026 
00027 static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
00028                                            const u8 *in_data, size_t *in_len);
00029 static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
00030                                            const u8 *in_data, size_t *in_len);
00031 static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
00032                                          const u8 *in_data, size_t *in_len);
00033 
00034 
00035 static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
00036                                     const u8 *in_data, size_t *in_len)
00037 {
00038         const u8 *pos, *end;
00039         size_t left, len, i;
00040         u16 cipher_suite;
00041 
00042         if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
00043                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
00044                            "received content type 0x%x", ct);
00045                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00046                           TLS_ALERT_UNEXPECTED_MESSAGE);
00047                 return -1;
00048         }
00049 
00050         pos = in_data;
00051         left = *in_len;
00052 
00053         if (left < 4)
00054                 goto decode_error;
00055 
00056         /* HandshakeType msg_type */
00057         if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
00058                 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
00059                            "message %d (expected ServerHello)", *pos);
00060                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00061                           TLS_ALERT_UNEXPECTED_MESSAGE);
00062                 return -1;
00063         }
00064         wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
00065         pos++;
00066         /* uint24 length */
00067         len = WPA_GET_BE24(pos);
00068         pos += 3;
00069         left -= 4;
00070 
00071         if (len > left)
00072                 goto decode_error;
00073 
00074         /* body - ServerHello */
00075 
00076         wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
00077         end = pos + len;
00078 
00079         /* ProtocolVersion server_version */
00080         if (end - pos < 2)
00081                 goto decode_error;
00082         if (WPA_GET_BE16(pos) != TLS_VERSION) {
00083                 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
00084                            "ServerHello");
00085                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00086                           TLS_ALERT_PROTOCOL_VERSION);
00087                 return -1;
00088         }
00089         pos += 2;
00090 
00091         /* Random random */
00092         if (end - pos < TLS_RANDOM_LEN)
00093                 goto decode_error;
00094 
00095         os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
00096         pos += TLS_RANDOM_LEN;
00097         wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
00098                     conn->server_random, TLS_RANDOM_LEN);
00099 
00100         /* SessionID session_id */
00101         if (end - pos < 1)
00102                 goto decode_error;
00103         if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
00104                 goto decode_error;
00105         if (conn->session_id_len && conn->session_id_len == *pos &&
00106             os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
00107                 pos += 1 + conn->session_id_len;
00108                 wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
00109                 conn->session_resumed = 1;
00110         } else {
00111                 conn->session_id_len = *pos;
00112                 pos++;
00113                 os_memcpy(conn->session_id, pos, conn->session_id_len);
00114                 pos += conn->session_id_len;
00115         }
00116         wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
00117                     conn->session_id, conn->session_id_len);
00118 
00119         /* CipherSuite cipher_suite */
00120         if (end - pos < 2)
00121                 goto decode_error;
00122         cipher_suite = WPA_GET_BE16(pos);
00123         pos += 2;
00124         for (i = 0; i < conn->num_cipher_suites; i++) {
00125                 if (cipher_suite == conn->cipher_suites[i])
00126                         break;
00127         }
00128         if (i == conn->num_cipher_suites) {
00129                 wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
00130                            "cipher suite 0x%04x", cipher_suite);
00131                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00132                           TLS_ALERT_ILLEGAL_PARAMETER);
00133                 return -1;
00134         }
00135 
00136         if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
00137                 wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
00138                            "cipher suite for a resumed connection (0x%04x != "
00139                            "0x%04x)", cipher_suite, conn->prev_cipher_suite);
00140                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00141                           TLS_ALERT_ILLEGAL_PARAMETER);
00142                 return -1;
00143         }
00144 
00145         if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
00146                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
00147                            "record layer");
00148                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00149                           TLS_ALERT_INTERNAL_ERROR);
00150                 return -1;
00151         }
00152 
00153         conn->prev_cipher_suite = cipher_suite;
00154 
00155         /* CompressionMethod compression_method */
00156         if (end - pos < 1)
00157                 goto decode_error;
00158         if (*pos != TLS_COMPRESSION_NULL) {
00159                 wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
00160                            "compression 0x%02x", *pos);
00161                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00162                           TLS_ALERT_ILLEGAL_PARAMETER);
00163                 return -1;
00164         }
00165         pos++;
00166 
00167         if (end != pos) {
00168                 /* TODO: ServerHello extensions */
00169                 wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
00170                             "end of ServerHello", pos, end - pos);
00171                 goto decode_error;
00172         }
00173 
00174         if (conn->session_ticket_included && conn->session_ticket_cb) {
00175                 /* TODO: include SessionTicket extension if one was included in
00176                  * ServerHello */
00177                 int res = conn->session_ticket_cb(
00178                         conn->session_ticket_cb_ctx, NULL, 0,
00179                         conn->client_random, conn->server_random,
00180                         conn->master_secret);
00181                 if (res < 0) {
00182                         wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
00183                                    "indicated failure");
00184                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00185                                   TLS_ALERT_HANDSHAKE_FAILURE);
00186                         return -1;
00187                 }
00188                 conn->use_session_ticket = !!res;
00189         }
00190 
00191         if ((conn->session_resumed || conn->use_session_ticket) &&
00192             tls_derive_keys(conn, NULL, 0)) {
00193                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
00194                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00195                           TLS_ALERT_INTERNAL_ERROR);
00196                 return -1;
00197         }
00198 
00199         *in_len = end - in_data;
00200 
00201         conn->state = (conn->session_resumed || conn->use_session_ticket) ?
00202                 SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
00203 
00204         return 0;
00205 
00206 decode_error:
00207         wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
00208         tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00209         return -1;
00210 }
00211 
00212 
00213 static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
00214                                    const u8 *in_data, size_t *in_len)
00215 {
00216         const u8 *pos, *end;
00217         size_t left, len, list_len, cert_len, idx;
00218         u8 type;
00219         struct x509_certificate *chain = NULL, *last = NULL, *cert;
00220         int reason;
00221 
00222         if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
00223                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
00224                            "received content type 0x%x", ct);
00225                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00226                           TLS_ALERT_UNEXPECTED_MESSAGE);
00227                 return -1;
00228         }
00229 
00230         pos = in_data;
00231         left = *in_len;
00232 
00233         if (left < 4) {
00234                 wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
00235                            "(len=%lu)", (unsigned long) left);
00236                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00237                 return -1;
00238         }
00239 
00240         type = *pos++;
00241         len = WPA_GET_BE24(pos);
00242         pos += 3;
00243         left -= 4;
00244 
00245         if (len > left) {
00246                 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
00247                            "length (len=%lu != left=%lu)",
00248                            (unsigned long) len, (unsigned long) left);
00249                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00250                 return -1;
00251         }
00252 
00253         if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
00254                 return tls_process_server_key_exchange(conn, ct, in_data,
00255                                                        in_len);
00256         if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
00257                 return tls_process_certificate_request(conn, ct, in_data,
00258                                                        in_len);
00259         if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
00260                 return tls_process_server_hello_done(conn, ct, in_data,
00261                                                      in_len);
00262         if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
00263                 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
00264                            "message %d (expected Certificate/"
00265                            "ServerKeyExchange/CertificateRequest/"
00266                            "ServerHelloDone)", type);
00267                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00268                           TLS_ALERT_UNEXPECTED_MESSAGE);
00269                 return -1;
00270         }
00271 
00272         wpa_printf(MSG_DEBUG,
00273                    "TLSv1: Received Certificate (certificate_list len %lu)",
00274                    (unsigned long) len);
00275 
00276         /*
00277          * opaque ASN.1Cert<2^24-1>;
00278          *
00279          * struct {
00280          *     ASN.1Cert certificate_list<1..2^24-1>;
00281          * } Certificate;
00282          */
00283 
00284         end = pos + len;
00285 
00286         if (end - pos < 3) {
00287                 wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
00288                            "(left=%lu)", (unsigned long) left);
00289                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00290                 return -1;
00291         }
00292 
00293         list_len = WPA_GET_BE24(pos);
00294         pos += 3;
00295 
00296         if ((size_t) (end - pos) != list_len) {
00297                 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
00298                            "length (len=%lu left=%lu)",
00299                            (unsigned long) list_len,
00300                            (unsigned long) (end - pos));
00301                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00302                 return -1;
00303         }
00304 
00305         idx = 0;
00306         while (pos < end) {
00307                 if (end - pos < 3) {
00308                         wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
00309                                    "certificate_list");
00310                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00311                                   TLS_ALERT_DECODE_ERROR);
00312                         x509_certificate_chain_free(chain);
00313                         return -1;
00314                 }
00315 
00316                 cert_len = WPA_GET_BE24(pos);
00317                 pos += 3;
00318 
00319                 if ((size_t) (end - pos) < cert_len) {
00320                         wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
00321                                    "length (len=%lu left=%lu)",
00322                                    (unsigned long) cert_len,
00323                                    (unsigned long) (end - pos));
00324                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00325                                   TLS_ALERT_DECODE_ERROR);
00326                         x509_certificate_chain_free(chain);
00327                         return -1;
00328                 }
00329 
00330                 wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
00331                            (unsigned long) idx, (unsigned long) cert_len);
00332 
00333                 if (idx == 0) {
00334                         crypto_public_key_free(conn->server_rsa_key);
00335                         if (tls_parse_cert(pos, cert_len,
00336                                            &conn->server_rsa_key)) {
00337                                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
00338                                            "the certificate");
00339                                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00340                                           TLS_ALERT_BAD_CERTIFICATE);
00341                                 x509_certificate_chain_free(chain);
00342                                 return -1;
00343                         }
00344                 }
00345 
00346                 cert = x509_certificate_parse(pos, cert_len);
00347                 if (cert == NULL) {
00348                         wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
00349                                    "the certificate");
00350                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00351                                   TLS_ALERT_BAD_CERTIFICATE);
00352                         x509_certificate_chain_free(chain);
00353                         return -1;
00354                 }
00355 
00356                 if (last == NULL)
00357                         chain = cert;
00358                 else
00359                         last->next = cert;
00360                 last = cert;
00361 
00362                 idx++;
00363                 pos += cert_len;
00364         }
00365 
00366         if (conn->cred &&
00367             x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
00368                                             &reason) < 0) {
00369                 int tls_reason;
00370                 wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
00371                            "validation failed (reason=%d)", reason);
00372                 switch (reason) {
00373                 case X509_VALIDATE_BAD_CERTIFICATE:
00374                         tls_reason = TLS_ALERT_BAD_CERTIFICATE;
00375                         break;
00376                 case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
00377                         tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
00378                         break;
00379                 case X509_VALIDATE_CERTIFICATE_REVOKED:
00380                         tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
00381                         break;
00382                 case X509_VALIDATE_CERTIFICATE_EXPIRED:
00383                         tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
00384                         break;
00385                 case X509_VALIDATE_CERTIFICATE_UNKNOWN:
00386                         tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
00387                         break;
00388                 case X509_VALIDATE_UNKNOWN_CA:
00389                         tls_reason = TLS_ALERT_UNKNOWN_CA;
00390                         break;
00391                 default:
00392                         tls_reason = TLS_ALERT_BAD_CERTIFICATE;
00393                         break;
00394                 }
00395                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
00396                 x509_certificate_chain_free(chain);
00397                 return -1;
00398         }
00399 
00400         x509_certificate_chain_free(chain);
00401 
00402         *in_len = end - in_data;
00403 
00404         conn->state = SERVER_KEY_EXCHANGE;
00405 
00406         return 0;
00407 }
00408 
00409 
00410 static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
00411                                         const u8 *buf, size_t len)
00412 {
00413         const u8 *pos, *end;
00414 
00415         tlsv1_client_free_dh(conn);
00416 
00417         pos = buf;
00418         end = buf + len;
00419 
00420         if (end - pos < 3)
00421                 goto fail;
00422         conn->dh_p_len = WPA_GET_BE16(pos);
00423         pos += 2;
00424         if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) {
00425                 wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu",
00426                            (unsigned long) conn->dh_p_len);
00427                 goto fail;
00428         }
00429         conn->dh_p = os_malloc(conn->dh_p_len);
00430         if (conn->dh_p == NULL)
00431                 goto fail;
00432         os_memcpy(conn->dh_p, pos, conn->dh_p_len);
00433         pos += conn->dh_p_len;
00434         wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
00435                     conn->dh_p, conn->dh_p_len);
00436 
00437         if (end - pos < 3)
00438                 goto fail;
00439         conn->dh_g_len = WPA_GET_BE16(pos);
00440         pos += 2;
00441         if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len)
00442                 goto fail;
00443         conn->dh_g = os_malloc(conn->dh_g_len);
00444         if (conn->dh_g == NULL)
00445                 goto fail;
00446         os_memcpy(conn->dh_g, pos, conn->dh_g_len);
00447         pos += conn->dh_g_len;
00448         wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
00449                     conn->dh_g, conn->dh_g_len);
00450         if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
00451                 goto fail;
00452 
00453         if (end - pos < 3)
00454                 goto fail;
00455         conn->dh_ys_len = WPA_GET_BE16(pos);
00456         pos += 2;
00457         if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len)
00458                 goto fail;
00459         conn->dh_ys = os_malloc(conn->dh_ys_len);
00460         if (conn->dh_ys == NULL)
00461                 goto fail;
00462         os_memcpy(conn->dh_ys, pos, conn->dh_ys_len);
00463         pos += conn->dh_ys_len;
00464         wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
00465                     conn->dh_ys, conn->dh_ys_len);
00466 
00467         return 0;
00468 
00469 fail:
00470         wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
00471         tlsv1_client_free_dh(conn);
00472         return -1;
00473 }
00474 
00475 
00476 static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
00477                                            const u8 *in_data, size_t *in_len)
00478 {
00479         const u8 *pos, *end;
00480         size_t left, len;
00481         u8 type;
00482         const struct tls_cipher_suite *suite;
00483 
00484         if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
00485                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
00486                            "received content type 0x%x", ct);
00487                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00488                           TLS_ALERT_UNEXPECTED_MESSAGE);
00489                 return -1;
00490         }
00491 
00492         pos = in_data;
00493         left = *in_len;
00494 
00495         if (left < 4) {
00496                 wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
00497                            "(Left=%lu)", (unsigned long) left);
00498                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00499                 return -1;
00500         }
00501 
00502         type = *pos++;
00503         len = WPA_GET_BE24(pos);
00504         pos += 3;
00505         left -= 4;
00506 
00507         if (len > left) {
00508                 wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
00509                            "length (len=%lu != left=%lu)",
00510                            (unsigned long) len, (unsigned long) left);
00511                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00512                 return -1;
00513         }
00514 
00515         end = pos + len;
00516 
00517         if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
00518                 return tls_process_certificate_request(conn, ct, in_data,
00519                                                        in_len);
00520         if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
00521                 return tls_process_server_hello_done(conn, ct, in_data,
00522                                                      in_len);
00523         if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
00524                 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
00525                            "message %d (expected ServerKeyExchange/"
00526                            "CertificateRequest/ServerHelloDone)", type);
00527                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00528                           TLS_ALERT_UNEXPECTED_MESSAGE);
00529                 return -1;
00530         }
00531 
00532         wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
00533 
00534         if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
00535                 wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
00536                            "with the selected cipher suite");
00537                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00538                           TLS_ALERT_UNEXPECTED_MESSAGE);
00539                 return -1;
00540         }
00541 
00542         wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
00543         suite = tls_get_cipher_suite(conn->rl.cipher_suite);
00544         if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
00545                 if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) {
00546                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00547                                   TLS_ALERT_DECODE_ERROR);
00548                         return -1;
00549                 }
00550         } else {
00551                 wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
00552                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00553                           TLS_ALERT_UNEXPECTED_MESSAGE);
00554                 return -1;
00555         }
00556 
00557         *in_len = end - in_data;
00558 
00559         conn->state = SERVER_CERTIFICATE_REQUEST;
00560 
00561         return 0;
00562 }
00563 
00564 
00565 static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
00566                                            const u8 *in_data, size_t *in_len)
00567 {
00568         const u8 *pos, *end;
00569         size_t left, len;
00570         u8 type;
00571 
00572         if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
00573                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
00574                            "received content type 0x%x", ct);
00575                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00576                           TLS_ALERT_UNEXPECTED_MESSAGE);
00577                 return -1;
00578         }
00579 
00580         pos = in_data;
00581         left = *in_len;
00582 
00583         if (left < 4) {
00584                 wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
00585                            "(left=%lu)", (unsigned long) left);
00586                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00587                 return -1;
00588         }
00589 
00590         type = *pos++;
00591         len = WPA_GET_BE24(pos);
00592         pos += 3;
00593         left -= 4;
00594 
00595         if (len > left) {
00596                 wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
00597                            "length (len=%lu != left=%lu)",
00598                            (unsigned long) len, (unsigned long) left);
00599                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00600                 return -1;
00601         }
00602 
00603         end = pos + len;
00604 
00605         if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
00606                 return tls_process_server_hello_done(conn, ct, in_data,
00607                                                      in_len);
00608         if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
00609                 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
00610                            "message %d (expected CertificateRequest/"
00611                            "ServerHelloDone)", type);
00612                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00613                           TLS_ALERT_UNEXPECTED_MESSAGE);
00614                 return -1;
00615         }
00616 
00617         wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
00618 
00619         conn->certificate_requested = 1;
00620 
00621         *in_len = end - in_data;
00622 
00623         conn->state = SERVER_HELLO_DONE;
00624 
00625         return 0;
00626 }
00627 
00628 
00629 static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
00630                                          const u8 *in_data, size_t *in_len)
00631 {
00632         const u8 *pos, *end;
00633         size_t left, len;
00634         u8 type;
00635 
00636         if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
00637                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
00638                            "received content type 0x%x", ct);
00639                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00640                           TLS_ALERT_UNEXPECTED_MESSAGE);
00641                 return -1;
00642         }
00643 
00644         pos = in_data;
00645         left = *in_len;
00646 
00647         if (left < 4) {
00648                 wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
00649                            "(left=%lu)", (unsigned long) left);
00650                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00651                 return -1;
00652         }
00653 
00654         type = *pos++;
00655         len = WPA_GET_BE24(pos);
00656         pos += 3;
00657         left -= 4;
00658 
00659         if (len > left) {
00660                 wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
00661                            "length (len=%lu != left=%lu)",
00662                            (unsigned long) len, (unsigned long) left);
00663                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00664                 return -1;
00665         }
00666         end = pos + len;
00667 
00668         if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
00669                 wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
00670                            "message %d (expected ServerHelloDone)", type);
00671                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00672                           TLS_ALERT_UNEXPECTED_MESSAGE);
00673                 return -1;
00674         }
00675 
00676         wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
00677 
00678         *in_len = end - in_data;
00679 
00680         conn->state = CLIENT_KEY_EXCHANGE;
00681 
00682         return 0;
00683 }
00684 
00685 
00686 static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
00687                                                  u8 ct, const u8 *in_data,
00688                                                  size_t *in_len)
00689 {
00690         const u8 *pos;
00691         size_t left;
00692 
00693         if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
00694                 wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
00695                            "received content type 0x%x", ct);
00696                 if (conn->use_session_ticket) {
00697                         int res;
00698                         wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
00699                                    "rejected SessionTicket");
00700                         conn->use_session_ticket = 0;
00701 
00702                         /* Notify upper layers that SessionTicket failed */
00703                         res = conn->session_ticket_cb(
00704                                 conn->session_ticket_cb_ctx, NULL, 0, NULL,
00705                                 NULL, NULL);
00706                         if (res < 0) {
00707                                 wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
00708                                            "callback indicated failure");
00709                                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00710                                           TLS_ALERT_HANDSHAKE_FAILURE);
00711                                 return -1;
00712                         }
00713 
00714                         conn->state = SERVER_CERTIFICATE;
00715                         return tls_process_certificate(conn, ct, in_data,
00716                                                        in_len);
00717                 }
00718                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00719                           TLS_ALERT_UNEXPECTED_MESSAGE);
00720                 return -1;
00721         }
00722 
00723         pos = in_data;
00724         left = *in_len;
00725 
00726         if (left < 1) {
00727                 wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
00728                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
00729                 return -1;
00730         }
00731 
00732         if (*pos != TLS_CHANGE_CIPHER_SPEC) {
00733                 wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
00734                            "received data 0x%x", *pos);
00735                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00736                           TLS_ALERT_UNEXPECTED_MESSAGE);
00737                 return -1;
00738         }
00739 
00740         wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
00741         if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
00742                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
00743                            "for record layer");
00744                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00745                           TLS_ALERT_INTERNAL_ERROR);
00746                 return -1;
00747         }
00748 
00749         *in_len = pos + 1 - in_data;
00750 
00751         conn->state = SERVER_FINISHED;
00752 
00753         return 0;
00754 }
00755 
00756 
00757 static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
00758                                        const u8 *in_data, size_t *in_len)
00759 {
00760         const u8 *pos, *end;
00761         size_t left, len, hlen;
00762         u8 verify_data[TLS_VERIFY_DATA_LEN];
00763         u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
00764 
00765         if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
00766                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
00767                            "received content type 0x%x", ct);
00768                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00769                           TLS_ALERT_UNEXPECTED_MESSAGE);
00770                 return -1;
00771         }
00772 
00773         pos = in_data;
00774         left = *in_len;
00775 
00776         if (left < 4) {
00777                 wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
00778                            "Finished",
00779                            (unsigned long) left);
00780                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00781                           TLS_ALERT_DECODE_ERROR);
00782                 return -1;
00783         }
00784 
00785         if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
00786                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
00787                            "type 0x%x", pos[0]);
00788                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00789                           TLS_ALERT_UNEXPECTED_MESSAGE);
00790                 return -1;
00791         }
00792 
00793         len = WPA_GET_BE24(pos + 1);
00794 
00795         pos += 4;
00796         left -= 4;
00797 
00798         if (len > left) {
00799                 wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
00800                            "(len=%lu > left=%lu)",
00801                            (unsigned long) len, (unsigned long) left);
00802                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00803                           TLS_ALERT_DECODE_ERROR);
00804                 return -1;
00805         }
00806         end = pos + len;
00807         if (len != TLS_VERIFY_DATA_LEN) {
00808                 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
00809                            "in Finished: %lu (expected %d)",
00810                            (unsigned long) len, TLS_VERIFY_DATA_LEN);
00811                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00812                           TLS_ALERT_DECODE_ERROR);
00813                 return -1;
00814         }
00815         wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
00816                     pos, TLS_VERIFY_DATA_LEN);
00817 
00818         hlen = MD5_MAC_LEN;
00819         if (conn->verify.md5_server == NULL ||
00820             crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
00821                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00822                           TLS_ALERT_INTERNAL_ERROR);
00823                 conn->verify.md5_server = NULL;
00824                 crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
00825                 conn->verify.sha1_server = NULL;
00826                 return -1;
00827         }
00828         conn->verify.md5_server = NULL;
00829         hlen = SHA1_MAC_LEN;
00830         if (conn->verify.sha1_server == NULL ||
00831             crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
00832                                &hlen) < 0) {
00833                 conn->verify.sha1_server = NULL;
00834                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00835                           TLS_ALERT_INTERNAL_ERROR);
00836                 return -1;
00837         }
00838         conn->verify.sha1_server = NULL;
00839 
00840         if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
00841                     "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
00842                     verify_data, TLS_VERIFY_DATA_LEN)) {
00843                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
00844                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00845                           TLS_ALERT_DECRYPT_ERROR);
00846                 return -1;
00847         }
00848         wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
00849                         verify_data, TLS_VERIFY_DATA_LEN);
00850 
00851         if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
00852                 wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
00853                 return -1;
00854         }
00855 
00856         wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
00857 
00858         *in_len = end - in_data;
00859 
00860         conn->state = (conn->session_resumed || conn->use_session_ticket) ?
00861                 CHANGE_CIPHER_SPEC : ACK_FINISHED;
00862 
00863         return 0;
00864 }
00865 
00866 
00867 static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
00868                                         const u8 *in_data, size_t *in_len,
00869                                         u8 **out_data, size_t *out_len)
00870 {
00871         const u8 *pos;
00872         size_t left;
00873 
00874         if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
00875                 wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
00876                            "received content type 0x%x", ct);
00877                 tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00878                           TLS_ALERT_UNEXPECTED_MESSAGE);
00879                 return -1;
00880         }
00881 
00882         pos = in_data;
00883         left = *in_len;
00884 
00885         wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
00886                     pos, left);
00887 
00888         *out_data = os_malloc(left);
00889         if (*out_data) {
00890                 os_memcpy(*out_data, pos, left);
00891                 *out_len = left;
00892         }
00893 
00894         return 0;
00895 }
00896 
00897 
00898 int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
00899                                    const u8 *buf, size_t *len,
00900                                    u8 **out_data, size_t *out_len)
00901 {
00902         if (ct == TLS_CONTENT_TYPE_ALERT) {
00903                 if (*len < 2) {
00904                         wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
00905                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00906                                   TLS_ALERT_DECODE_ERROR);
00907                         return -1;
00908                 }
00909                 wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
00910                            buf[0], buf[1]);
00911                 *len = 2;
00912                 conn->state = FAILED;
00913                 return -1;
00914         }
00915 
00916         if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
00917             buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
00918                 size_t hr_len = WPA_GET_BE24(buf + 1);
00919                 if (hr_len > *len - 4) {
00920                         wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
00921                         tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
00922                                   TLS_ALERT_DECODE_ERROR);
00923                         return -1;
00924                 }
00925                 wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
00926                 *len = 4 + hr_len;
00927                 return 0;
00928         }
00929 
00930         switch (conn->state) {
00931         case SERVER_HELLO:
00932                 if (tls_process_server_hello(conn, ct, buf, len))
00933                         return -1;
00934                 break;
00935         case SERVER_CERTIFICATE:
00936                 if (tls_process_certificate(conn, ct, buf, len))
00937                         return -1;
00938                 break;
00939         case SERVER_KEY_EXCHANGE:
00940                 if (tls_process_server_key_exchange(conn, ct, buf, len))
00941                         return -1;
00942                 break;
00943         case SERVER_CERTIFICATE_REQUEST:
00944                 if (tls_process_certificate_request(conn, ct, buf, len))
00945                         return -1;
00946                 break;
00947         case SERVER_HELLO_DONE:
00948                 if (tls_process_server_hello_done(conn, ct, buf, len))
00949                         return -1;
00950                 break;
00951         case SERVER_CHANGE_CIPHER_SPEC:
00952                 if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
00953                         return -1;
00954                 break;
00955         case SERVER_FINISHED:
00956                 if (tls_process_server_finished(conn, ct, buf, len))
00957                         return -1;
00958                 break;
00959         case ACK_FINISHED:
00960                 if (out_data &&
00961                     tls_process_application_data(conn, ct, buf, len, out_data,
00962                                                  out_len))
00963                         return -1;
00964                 break;
00965         default:
00966                 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
00967                            "while processing received message",
00968                            conn->state);
00969                 return -1;
00970         }
00971 
00972         if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
00973                 tls_verify_hash_add(&conn->verify, buf, *len);
00974 
00975         return 0;
00976 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:36