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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:38