tlsv1_server_write.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "md5.h"
00020 #include "sha1.h"
00021 #include "x509v3.h"
00022 #include "tls.h"
00023 #include "tlsv1_common.h"
00024 #include "tlsv1_record.h"
00025 #include "tlsv1_server.h"
00026 #include "tlsv1_server_i.h"
00027 
00028 
00029 static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn)
00030 {
00031         size_t len = 0;
00032         struct x509_certificate *cert;
00033 
00034         cert = conn->cred->cert;
00035         while (cert) {
00036                 len += 3 + cert->cert_len;
00037                 if (x509_certificate_self_signed(cert))
00038                         break;
00039                 cert = x509_certificate_get_subject(conn->cred->trusted_certs,
00040                                                     &cert->issuer);
00041         }
00042 
00043         return len;
00044 }
00045 
00046 
00047 static int tls_write_server_hello(struct tlsv1_server *conn,
00048                                   u8 **msgpos, u8 *end)
00049 {
00050         u8 *pos, *rhdr, *hs_start, *hs_length;
00051         struct os_time now;
00052         size_t rlen;
00053 
00054         pos = *msgpos;
00055 
00056         wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello");
00057         rhdr = pos;
00058         pos += TLS_RECORD_HEADER_LEN;
00059 
00060         os_get_time(&now);
00061         WPA_PUT_BE32(conn->server_random, now.sec);
00062         if (os_get_random(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
00063                 wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
00064                            "server_random");
00065                 return -1;
00066         }
00067         wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
00068                     conn->server_random, TLS_RANDOM_LEN);
00069 
00070         conn->session_id_len = TLS_SESSION_ID_MAX_LEN;
00071         if (os_get_random(conn->session_id, conn->session_id_len)) {
00072                 wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
00073                            "session_id");
00074                 return -1;
00075         }
00076         wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
00077                     conn->session_id, conn->session_id_len);
00078 
00079         /* opaque fragment[TLSPlaintext.length] */
00080 
00081         /* Handshake */
00082         hs_start = pos;
00083         /* HandshakeType msg_type */
00084         *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO;
00085         /* uint24 length (to be filled) */
00086         hs_length = pos;
00087         pos += 3;
00088         /* body - ServerHello */
00089         /* ProtocolVersion server_version */
00090         WPA_PUT_BE16(pos, TLS_VERSION);
00091         pos += 2;
00092         /* Random random: uint32 gmt_unix_time, opaque random_bytes */
00093         os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN);
00094         pos += TLS_RANDOM_LEN;
00095         /* SessionID session_id */
00096         *pos++ = conn->session_id_len;
00097         os_memcpy(pos, conn->session_id, conn->session_id_len);
00098         pos += conn->session_id_len;
00099         /* CipherSuite cipher_suite */
00100         WPA_PUT_BE16(pos, conn->cipher_suite);
00101         pos += 2;
00102         /* CompressionMethod compression_method */
00103         *pos++ = TLS_COMPRESSION_NULL;
00104 
00105         if (conn->session_ticket && conn->session_ticket_cb) {
00106                 int res = conn->session_ticket_cb(
00107                         conn->session_ticket_cb_ctx,
00108                         conn->session_ticket, conn->session_ticket_len,
00109                         conn->client_random, conn->server_random,
00110                         conn->master_secret);
00111                 if (res < 0) {
00112                         wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
00113                                    "indicated failure");
00114                         tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00115                                            TLS_ALERT_HANDSHAKE_FAILURE);
00116                         return -1;
00117                 }
00118                 conn->use_session_ticket = res;
00119 
00120                 if (conn->use_session_ticket) {
00121                         if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) {
00122                                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
00123                                            "derive keys");
00124                                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00125                                                    TLS_ALERT_INTERNAL_ERROR);
00126                                 return -1;
00127                         }
00128                 }
00129 
00130                 /*
00131                  * RFC 4507 specifies that server would include an empty
00132                  * SessionTicket extension in ServerHello and a
00133                  * NewSessionTicket message after the ServerHello. However,
00134                  * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket
00135                  * extension at the moment, does not use such extensions.
00136                  *
00137                  * TODO: Add support for configuring RFC 4507 behavior and make
00138                  * EAP-FAST disable it.
00139                  */
00140         }
00141 
00142         WPA_PUT_BE24(hs_length, pos - hs_length - 3);
00143         tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
00144 
00145         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
00146                               rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
00147                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
00148                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00149                                    TLS_ALERT_INTERNAL_ERROR);
00150                 return -1;
00151         }
00152         pos = rhdr + rlen;
00153 
00154         *msgpos = pos;
00155 
00156         return 0;
00157 }
00158 
00159 
00160 static int tls_write_server_certificate(struct tlsv1_server *conn,
00161                                         u8 **msgpos, u8 *end)
00162 {
00163         u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
00164         size_t rlen;
00165         struct x509_certificate *cert;
00166         const struct tls_cipher_suite *suite;
00167 
00168         suite = tls_get_cipher_suite(conn->rl.cipher_suite);
00169         if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
00170                 wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when "
00171                            "using anonymous DH");
00172                 return 0;
00173         }
00174 
00175         pos = *msgpos;
00176 
00177         wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
00178         rhdr = pos;
00179         pos += TLS_RECORD_HEADER_LEN;
00180 
00181         /* opaque fragment[TLSPlaintext.length] */
00182 
00183         /* Handshake */
00184         hs_start = pos;
00185         /* HandshakeType msg_type */
00186         *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
00187         /* uint24 length (to be filled) */
00188         hs_length = pos;
00189         pos += 3;
00190         /* body - Certificate */
00191         /* uint24 length (to be filled) */
00192         cert_start = pos;
00193         pos += 3;
00194         cert = conn->cred->cert;
00195         while (cert) {
00196                 if (pos + 3 + cert->cert_len > end) {
00197                         wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
00198                                    "for Certificate (cert_len=%lu left=%lu)",
00199                                    (unsigned long) cert->cert_len,
00200                                    (unsigned long) (end - pos));
00201                         tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00202                                            TLS_ALERT_INTERNAL_ERROR);
00203                         return -1;
00204                 }
00205                 WPA_PUT_BE24(pos, cert->cert_len);
00206                 pos += 3;
00207                 os_memcpy(pos, cert->cert_start, cert->cert_len);
00208                 pos += cert->cert_len;
00209 
00210                 if (x509_certificate_self_signed(cert))
00211                         break;
00212                 cert = x509_certificate_get_subject(conn->cred->trusted_certs,
00213                                                     &cert->issuer);
00214         }
00215         if (cert == conn->cred->cert || cert == NULL) {
00216                 /*
00217                  * Server was not configured with all the needed certificates
00218                  * to form a full certificate chain. The client may fail to
00219                  * validate the chain unless it is configured with all the
00220                  * missing CA certificates.
00221                  */
00222                 wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain "
00223                            "not configured - validation may fail");
00224         }
00225         WPA_PUT_BE24(cert_start, pos - cert_start - 3);
00226 
00227         WPA_PUT_BE24(hs_length, pos - hs_length - 3);
00228 
00229         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
00230                               rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
00231                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
00232                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00233                                    TLS_ALERT_INTERNAL_ERROR);
00234                 return -1;
00235         }
00236         pos = rhdr + rlen;
00237 
00238         tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
00239 
00240         *msgpos = pos;
00241 
00242         return 0;
00243 }
00244 
00245 
00246 static int tls_write_server_key_exchange(struct tlsv1_server *conn,
00247                                          u8 **msgpos, u8 *end)
00248 {
00249         tls_key_exchange keyx;
00250         const struct tls_cipher_suite *suite;
00251 #ifdef EAP_SERVER_FAST
00252         u8 *pos, *rhdr, *hs_start, *hs_length;
00253         size_t rlen;
00254         u8 *dh_ys;
00255         size_t dh_ys_len;
00256 #endif /* EAP_SERVER_FAST */
00257 
00258         suite = tls_get_cipher_suite(conn->rl.cipher_suite);
00259         if (suite == NULL)
00260                 keyx = TLS_KEY_X_NULL;
00261         else
00262                 keyx = suite->key_exchange;
00263 
00264         if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
00265                 wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed");
00266                 return 0;
00267         }
00268 
00269         if (keyx != TLS_KEY_X_DH_anon) {
00270                 /* TODO? */
00271                 wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet "
00272                            "supported with key exchange type %d", keyx);
00273                 return -1;
00274         }
00275 
00276 #ifdef EAP_SERVER_FAST
00277         if (conn->cred == NULL || conn->cred->dh_p == NULL ||
00278             conn->cred->dh_g == NULL) {
00279                 wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for "
00280                            "ServerKeyExhcange");
00281                 return -1;
00282         }
00283 
00284         os_free(conn->dh_secret);
00285         conn->dh_secret_len = conn->cred->dh_p_len;
00286         conn->dh_secret = os_malloc(conn->dh_secret_len);
00287         if (conn->dh_secret == NULL) {
00288                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
00289                            "memory for secret (Diffie-Hellman)");
00290                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00291                                    TLS_ALERT_INTERNAL_ERROR);
00292                 return -1;
00293         }
00294         if (os_get_random(conn->dh_secret, conn->dh_secret_len)) {
00295                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
00296                            "data for Diffie-Hellman");
00297                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00298                                    TLS_ALERT_INTERNAL_ERROR);
00299                 os_free(conn->dh_secret);
00300                 conn->dh_secret = NULL;
00301                 return -1;
00302         }
00303 
00304         if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) >
00305             0)
00306                 conn->dh_secret[0] = 0; /* make sure secret < p */
00307 
00308         pos = conn->dh_secret;
00309         while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0)
00310                 pos++;
00311         if (pos != conn->dh_secret) {
00312                 os_memmove(conn->dh_secret, pos,
00313                            conn->dh_secret_len - (pos - conn->dh_secret));
00314                 conn->dh_secret_len -= pos - conn->dh_secret;
00315         }
00316         wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value",
00317                         conn->dh_secret, conn->dh_secret_len);
00318 
00319         /* Ys = g^secret mod p */
00320         dh_ys_len = conn->cred->dh_p_len;
00321         dh_ys = os_malloc(dh_ys_len);
00322         if (dh_ys == NULL) {
00323                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for "
00324                            "Diffie-Hellman");
00325                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00326                                    TLS_ALERT_INTERNAL_ERROR);
00327                 return -1;
00328         }
00329         if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len,
00330                            conn->dh_secret, conn->dh_secret_len,
00331                            conn->cred->dh_p, conn->cred->dh_p_len,
00332                            dh_ys, &dh_ys_len)) {
00333                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00334                                    TLS_ALERT_INTERNAL_ERROR);
00335                 os_free(dh_ys);
00336                 return -1;
00337         }
00338 
00339         wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
00340                     dh_ys, dh_ys_len);
00341 
00342         /*
00343          * struct {
00344          *    select (KeyExchangeAlgorithm) {
00345          *       case diffie_hellman:
00346          *          ServerDHParams params;
00347          *          Signature signed_params;
00348          *       case rsa:
00349          *          ServerRSAParams params;
00350          *          Signature signed_params;
00351          *    };
00352          * } ServerKeyExchange;
00353          *
00354          * struct {
00355          *    opaque dh_p<1..2^16-1>;
00356          *    opaque dh_g<1..2^16-1>;
00357          *    opaque dh_Ys<1..2^16-1>;
00358          * } ServerDHParams;
00359          */
00360 
00361         pos = *msgpos;
00362 
00363         wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange");
00364         rhdr = pos;
00365         pos += TLS_RECORD_HEADER_LEN;
00366 
00367         /* opaque fragment[TLSPlaintext.length] */
00368 
00369         /* Handshake */
00370         hs_start = pos;
00371         /* HandshakeType msg_type */
00372         *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE;
00373         /* uint24 length (to be filled) */
00374         hs_length = pos;
00375         pos += 3;
00376 
00377         /* body - ServerDHParams */
00378         /* dh_p */
00379         if (pos + 2 + conn->cred->dh_p_len > end) {
00380                 wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
00381                            "dh_p");
00382                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00383                                    TLS_ALERT_INTERNAL_ERROR);
00384                 os_free(dh_ys);
00385                 return -1;
00386         }
00387         WPA_PUT_BE16(pos, conn->cred->dh_p_len);
00388         pos += 2;
00389         os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len);
00390         pos += conn->cred->dh_p_len;
00391 
00392         /* dh_g */
00393         if (pos + 2 + conn->cred->dh_g_len > end) {
00394                 wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
00395                            "dh_g");
00396                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00397                                    TLS_ALERT_INTERNAL_ERROR);
00398                 os_free(dh_ys);
00399                 return -1;
00400         }
00401         WPA_PUT_BE16(pos, conn->cred->dh_g_len);
00402         pos += 2;
00403         os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len);
00404         pos += conn->cred->dh_g_len;
00405 
00406         /* dh_Ys */
00407         if (pos + 2 + dh_ys_len > end) {
00408                 wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
00409                            "dh_Ys");
00410                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00411                                    TLS_ALERT_INTERNAL_ERROR);
00412                 os_free(dh_ys);
00413                 return -1;
00414         }
00415         WPA_PUT_BE16(pos, dh_ys_len);
00416         pos += 2;
00417         os_memcpy(pos, dh_ys, dh_ys_len);
00418         pos += dh_ys_len;
00419         os_free(dh_ys);
00420 
00421         WPA_PUT_BE24(hs_length, pos - hs_length - 3);
00422 
00423         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
00424                               rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
00425                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
00426                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00427                                    TLS_ALERT_INTERNAL_ERROR);
00428                 return -1;
00429         }
00430         pos = rhdr + rlen;
00431 
00432         tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
00433 
00434         *msgpos = pos;
00435 
00436         return 0;
00437 #else /* EAP_SERVER_FAST */
00438         return -1;
00439 #endif /* EAP_SERVER_FAST */
00440 }
00441 
00442 
00443 static int tls_write_server_certificate_request(struct tlsv1_server *conn,
00444                                                 u8 **msgpos, u8 *end)
00445 {
00446         u8 *pos, *rhdr, *hs_start, *hs_length;
00447         size_t rlen;
00448 
00449         if (!conn->verify_peer) {
00450                 wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed");
00451                 return 0;
00452         }
00453 
00454         pos = *msgpos;
00455 
00456         wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest");
00457         rhdr = pos;
00458         pos += TLS_RECORD_HEADER_LEN;
00459 
00460         /* opaque fragment[TLSPlaintext.length] */
00461 
00462         /* Handshake */
00463         hs_start = pos;
00464         /* HandshakeType msg_type */
00465         *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST;
00466         /* uint24 length (to be filled) */
00467         hs_length = pos;
00468         pos += 3;
00469         /* body - CertificateRequest */
00470 
00471         /*
00472          * enum {
00473          *   rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
00474          *   (255)
00475          * } ClientCertificateType;
00476          * ClientCertificateType certificate_types<1..2^8-1>
00477          */
00478         *pos++ = 1;
00479         *pos++ = 1; /* rsa_sign */
00480 
00481         /*
00482          * opaque DistinguishedName<1..2^16-1>
00483          * DistinguishedName certificate_authorities<3..2^16-1>
00484          */
00485         /* TODO: add support for listing DNs for trusted CAs */
00486         WPA_PUT_BE16(pos, 0);
00487         pos += 2;
00488 
00489         WPA_PUT_BE24(hs_length, pos - hs_length - 3);
00490 
00491         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
00492                               rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
00493                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
00494                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00495                                    TLS_ALERT_INTERNAL_ERROR);
00496                 return -1;
00497         }
00498         pos = rhdr + rlen;
00499 
00500         tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
00501 
00502         *msgpos = pos;
00503 
00504         return 0;
00505 }
00506 
00507 
00508 static int tls_write_server_hello_done(struct tlsv1_server *conn,
00509                                        u8 **msgpos, u8 *end)
00510 {
00511         u8 *pos, *rhdr, *hs_start, *hs_length;
00512         size_t rlen;
00513 
00514         pos = *msgpos;
00515 
00516         wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone");
00517         rhdr = pos;
00518         pos += TLS_RECORD_HEADER_LEN;
00519 
00520         /* opaque fragment[TLSPlaintext.length] */
00521 
00522         /* Handshake */
00523         hs_start = pos;
00524         /* HandshakeType msg_type */
00525         *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE;
00526         /* uint24 length (to be filled) */
00527         hs_length = pos;
00528         pos += 3;
00529         /* body - ServerHelloDone (empty) */
00530 
00531         WPA_PUT_BE24(hs_length, pos - hs_length - 3);
00532 
00533         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
00534                               rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
00535                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
00536                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00537                                    TLS_ALERT_INTERNAL_ERROR);
00538                 return -1;
00539         }
00540         pos = rhdr + rlen;
00541 
00542         tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
00543 
00544         *msgpos = pos;
00545 
00546         return 0;
00547 }
00548 
00549 
00550 static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
00551                                                u8 **msgpos, u8 *end)
00552 {
00553         u8 *pos, *rhdr;
00554         size_t rlen;
00555 
00556         pos = *msgpos;
00557 
00558         wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
00559         rhdr = pos;
00560         pos += TLS_RECORD_HEADER_LEN;
00561         *pos = TLS_CHANGE_CIPHER_SPEC;
00562         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
00563                               rhdr, end - rhdr, 1, &rlen) < 0) {
00564                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
00565                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00566                                    TLS_ALERT_INTERNAL_ERROR);
00567                 return -1;
00568         }
00569 
00570         if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
00571                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
00572                            "record layer");
00573                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00574                                    TLS_ALERT_INTERNAL_ERROR);
00575                 return -1;
00576         }
00577 
00578         *msgpos = rhdr + rlen;
00579 
00580         return 0;
00581 }
00582 
00583 
00584 static int tls_write_server_finished(struct tlsv1_server *conn,
00585                                      u8 **msgpos, u8 *end)
00586 {
00587         u8 *pos, *rhdr, *hs_start, *hs_length;
00588         size_t rlen, hlen;
00589         u8 verify_data[TLS_VERIFY_DATA_LEN];
00590         u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
00591 
00592         pos = *msgpos;
00593 
00594         wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");
00595 
00596         /* Encrypted Handshake Message: Finished */
00597 
00598         hlen = MD5_MAC_LEN;
00599         if (conn->verify.md5_server == NULL ||
00600             crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
00601                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00602                                    TLS_ALERT_INTERNAL_ERROR);
00603                 conn->verify.md5_server = NULL;
00604                 crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
00605                 conn->verify.sha1_server = NULL;
00606                 return -1;
00607         }
00608         conn->verify.md5_server = NULL;
00609         hlen = SHA1_MAC_LEN;
00610         if (conn->verify.sha1_server == NULL ||
00611             crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
00612                                &hlen) < 0) {
00613                 conn->verify.sha1_server = NULL;
00614                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00615                                    TLS_ALERT_INTERNAL_ERROR);
00616                 return -1;
00617         }
00618         conn->verify.sha1_server = NULL;
00619 
00620         if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
00621                     "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
00622                     verify_data, TLS_VERIFY_DATA_LEN)) {
00623                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
00624                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00625                                    TLS_ALERT_INTERNAL_ERROR);
00626                 return -1;
00627         }
00628         wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
00629                         verify_data, TLS_VERIFY_DATA_LEN);
00630 
00631         rhdr = pos;
00632         pos += TLS_RECORD_HEADER_LEN;
00633         /* Handshake */
00634         hs_start = pos;
00635         /* HandshakeType msg_type */
00636         *pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
00637         /* uint24 length (to be filled) */
00638         hs_length = pos;
00639         pos += 3;
00640         os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN);
00641         pos += TLS_VERIFY_DATA_LEN;
00642         WPA_PUT_BE24(hs_length, pos - hs_length - 3);
00643         tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
00644 
00645         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
00646                               rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
00647                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
00648                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00649                                    TLS_ALERT_INTERNAL_ERROR);
00650                 return -1;
00651         }
00652 
00653         pos = rhdr + rlen;
00654 
00655         *msgpos = pos;
00656 
00657         return 0;
00658 }
00659 
00660 
00661 static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len)
00662 {
00663         u8 *msg, *end, *pos;
00664         size_t msglen;
00665 
00666         *out_len = 0;
00667 
00668         msglen = 1000 + tls_server_cert_chain_der_len(conn);
00669 
00670         msg = os_malloc(msglen);
00671         if (msg == NULL)
00672                 return NULL;
00673 
00674         pos = msg;
00675         end = msg + msglen;
00676 
00677         if (tls_write_server_hello(conn, &pos, end) < 0) {
00678                 os_free(msg);
00679                 return NULL;
00680         }
00681 
00682         if (conn->use_session_ticket) {
00683                 /* Abbreviated handshake using session ticket; RFC 4507 */
00684                 if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
00685                     tls_write_server_finished(conn, &pos, end) < 0) {
00686                         os_free(msg);
00687                         return NULL;
00688                 }
00689 
00690                 *out_len = pos - msg;
00691 
00692                 conn->state = CHANGE_CIPHER_SPEC;
00693 
00694                 return msg;
00695         }
00696 
00697         /* Full handshake */
00698         if (tls_write_server_certificate(conn, &pos, end) < 0 ||
00699             tls_write_server_key_exchange(conn, &pos, end) < 0 ||
00700             tls_write_server_certificate_request(conn, &pos, end) < 0 ||
00701             tls_write_server_hello_done(conn, &pos, end) < 0) {
00702                 os_free(msg);
00703                 return NULL;
00704         }
00705 
00706         *out_len = pos - msg;
00707 
00708         conn->state = CLIENT_CERTIFICATE;
00709 
00710         return msg;
00711 }
00712 
00713 
00714 static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn,
00715                                         size_t *out_len)
00716 {
00717         u8 *msg, *end, *pos;
00718 
00719         *out_len = 0;
00720 
00721         msg = os_malloc(1000);
00722         if (msg == NULL)
00723                 return NULL;
00724 
00725         pos = msg;
00726         end = msg + 1000;
00727 
00728         if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
00729             tls_write_server_finished(conn, &pos, end) < 0) {
00730                 os_free(msg);
00731                 return NULL;
00732         }
00733 
00734         *out_len = pos - msg;
00735 
00736         wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully");
00737         conn->state = ESTABLISHED;
00738 
00739         return msg;
00740 }
00741 
00742 
00743 u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len)
00744 {
00745         switch (conn->state) {
00746         case SERVER_HELLO:
00747                 return tls_send_server_hello(conn, out_len);
00748         case SERVER_CHANGE_CIPHER_SPEC:
00749                 return tls_send_change_cipher_spec(conn, out_len);
00750         default:
00751                 if (conn->state == ESTABLISHED && conn->use_session_ticket) {
00752                         /* Abbreviated handshake was already completed. */
00753                         return NULL;
00754                 }
00755                 wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "
00756                            "generating reply", conn->state);
00757                 return NULL;
00758         }
00759 }
00760 
00761 
00762 u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
00763                              u8 description, size_t *out_len)
00764 {
00765         u8 *alert, *pos, *length;
00766 
00767         wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);
00768         *out_len = 0;
00769 
00770         alert = os_malloc(10);
00771         if (alert == NULL)
00772                 return NULL;
00773 
00774         pos = alert;
00775 
00776         /* TLSPlaintext */
00777         /* ContentType type */
00778         *pos++ = TLS_CONTENT_TYPE_ALERT;
00779         /* ProtocolVersion version */
00780         WPA_PUT_BE16(pos, TLS_VERSION);
00781         pos += 2;
00782         /* uint16 length (to be filled) */
00783         length = pos;
00784         pos += 2;
00785         /* opaque fragment[TLSPlaintext.length] */
00786 
00787         /* Alert */
00788         /* AlertLevel level */
00789         *pos++ = level;
00790         /* AlertDescription description */
00791         *pos++ = description;
00792 
00793         WPA_PUT_BE16(length, pos - length - 2);
00794         *out_len = pos - alert;
00795 
00796         return alert;
00797 }
00798 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:53 2009 for hostapd by  doxygen 1.6.1