tlsv1_server.c
Go to the documentation of this file.
00001 /*
00002  * TLSv1 server (RFC 2246)
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/sha1.h"
00019 #include "crypto/tls.h"
00020 #include "tlsv1_common.h"
00021 #include "tlsv1_record.h"
00022 #include "tlsv1_server.h"
00023 #include "tlsv1_server_i.h"
00024 
00025 /* TODO:
00026  * Support for a message fragmented across several records (RFC 2246, 6.2.1)
00027  */
00028 
00029 
00030 void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description)
00031 {
00032         conn->alert_level = level;
00033         conn->alert_description = description;
00034 }
00035 
00036 
00037 int tlsv1_server_derive_keys(struct tlsv1_server *conn,
00038                              const u8 *pre_master_secret,
00039                              size_t pre_master_secret_len)
00040 {
00041         u8 seed[2 * TLS_RANDOM_LEN];
00042         u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
00043         u8 *pos;
00044         size_t key_block_len;
00045 
00046         if (pre_master_secret) {
00047                 wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret",
00048                                 pre_master_secret, pre_master_secret_len);
00049                 os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
00050                 os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
00051                           TLS_RANDOM_LEN);
00052                 if (tls_prf(pre_master_secret, pre_master_secret_len,
00053                             "master secret", seed, 2 * TLS_RANDOM_LEN,
00054                             conn->master_secret, TLS_MASTER_SECRET_LEN)) {
00055                         wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive "
00056                                    "master_secret");
00057                         return -1;
00058                 }
00059                 wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret",
00060                                 conn->master_secret, TLS_MASTER_SECRET_LEN);
00061         }
00062 
00063         os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
00064         os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
00065         key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len +
00066                              conn->rl.iv_size);
00067         if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
00068                     "key expansion", seed, 2 * TLS_RANDOM_LEN,
00069                     key_block, key_block_len)) {
00070                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block");
00071                 return -1;
00072         }
00073         wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block",
00074                         key_block, key_block_len);
00075 
00076         pos = key_block;
00077 
00078         /* client_write_MAC_secret */
00079         os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size);
00080         pos += conn->rl.hash_size;
00081         /* server_write_MAC_secret */
00082         os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size);
00083         pos += conn->rl.hash_size;
00084 
00085         /* client_write_key */
00086         os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
00087         pos += conn->rl.key_material_len;
00088         /* server_write_key */
00089         os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len);
00090         pos += conn->rl.key_material_len;
00091 
00092         /* client_write_IV */
00093         os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
00094         pos += conn->rl.iv_size;
00095         /* server_write_IV */
00096         os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
00097         pos += conn->rl.iv_size;
00098 
00099         return 0;
00100 }
00101 
00102 
00111 u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
00112                             const u8 *in_data, size_t in_len,
00113                             size_t *out_len)
00114 {
00115         const u8 *pos, *end;
00116         u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct;
00117         size_t in_msg_len;
00118 
00119         if (in_data == NULL || in_len == 0) {
00120                 wpa_printf(MSG_DEBUG, "TLSv1: No input data to server");
00121                 return NULL;
00122         }
00123 
00124         pos = in_data;
00125         end = in_data + in_len;
00126         in_msg = os_malloc(in_len);
00127         if (in_msg == NULL)
00128                 return NULL;
00129 
00130         /* Each received packet may include multiple records */
00131         while (pos < end) {
00132                 in_msg_len = in_len;
00133                 if (tlsv1_record_receive(&conn->rl, pos, end - pos,
00134                                          in_msg, &in_msg_len, &alert)) {
00135                         wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
00136                                    "record failed");
00137                         tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
00138                         goto failed;
00139                 }
00140                 ct = pos[0];
00141 
00142                 in_pos = in_msg;
00143                 in_end = in_msg + in_msg_len;
00144 
00145                 /* Each received record may include multiple messages of the
00146                  * same ContentType. */
00147                 while (in_pos < in_end) {
00148                         in_msg_len = in_end - in_pos;
00149                         if (tlsv1_server_process_handshake(conn, ct, in_pos,
00150                                                            &in_msg_len) < 0)
00151                                 goto failed;
00152                         in_pos += in_msg_len;
00153                 }
00154 
00155                 pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);
00156         }
00157 
00158         os_free(in_msg);
00159         in_msg = NULL;
00160 
00161         msg = tlsv1_server_handshake_write(conn, out_len);
00162 
00163 failed:
00164         os_free(in_msg);
00165         if (conn->alert_level) {
00166                 if (conn->state == FAILED) {
00167                         /* Avoid alert loops */
00168                         wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop");
00169                         os_free(msg);
00170                         return NULL;
00171                 }
00172                 conn->state = FAILED;
00173                 os_free(msg);
00174                 msg = tlsv1_server_send_alert(conn, conn->alert_level,
00175                                               conn->alert_description,
00176                                               out_len);
00177         }
00178 
00179         return msg;
00180 }
00181 
00182 
00195 int tlsv1_server_encrypt(struct tlsv1_server *conn,
00196                          const u8 *in_data, size_t in_len,
00197                          u8 *out_data, size_t out_len)
00198 {
00199         size_t rlen;
00200 
00201         wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",
00202                         in_data, in_len);
00203 
00204         os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len);
00205 
00206         if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,
00207                               out_data, out_len, in_len, &rlen) < 0) {
00208                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
00209                 tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00210                                    TLS_ALERT_INTERNAL_ERROR);
00211                 return -1;
00212         }
00213 
00214         return rlen;
00215 }
00216 
00217 
00230 int tlsv1_server_decrypt(struct tlsv1_server *conn,
00231                          const u8 *in_data, size_t in_len,
00232                          u8 *out_data, size_t out_len)
00233 {
00234         const u8 *in_end, *pos;
00235         int res;
00236         u8 alert, *out_end, *out_pos;
00237         size_t olen;
00238 
00239         pos = in_data;
00240         in_end = in_data + in_len;
00241         out_pos = out_data;
00242         out_end = out_data + out_len;
00243 
00244         while (pos < in_end) {
00245                 if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) {
00246                         wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "
00247                                    "0x%x", pos[0]);
00248                         tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00249                                            TLS_ALERT_UNEXPECTED_MESSAGE);
00250                         return -1;
00251                 }
00252 
00253                 olen = out_end - out_pos;
00254                 res = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
00255                                            out_pos, &olen, &alert);
00256                 if (res < 0) {
00257                         wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
00258                                    "failed");
00259                         tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
00260                         return -1;
00261                 }
00262                 out_pos += olen;
00263                 if (out_pos > out_end) {
00264                         wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough "
00265                                    "for processing the received record");
00266                         tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
00267                                            TLS_ALERT_INTERNAL_ERROR);
00268                         return -1;
00269                 }
00270 
00271                 pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);
00272         }
00273 
00274         return out_pos - out_data;
00275 }
00276 
00277 
00284 int tlsv1_server_global_init(void)
00285 {
00286         return crypto_global_init();
00287 }
00288 
00289 
00297 void tlsv1_server_global_deinit(void)
00298 {
00299         crypto_global_deinit();
00300 }
00301 
00302 
00308 struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred)
00309 {
00310         struct tlsv1_server *conn;
00311         size_t count;
00312         u16 *suites;
00313 
00314         conn = os_zalloc(sizeof(*conn));
00315         if (conn == NULL)
00316                 return NULL;
00317 
00318         conn->cred = cred;
00319 
00320         conn->state = CLIENT_HELLO;
00321 
00322         if (tls_verify_hash_init(&conn->verify) < 0) {
00323                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
00324                            "hash");
00325                 os_free(conn);
00326                 return NULL;
00327         }
00328 
00329         count = 0;
00330         suites = conn->cipher_suites;
00331 #ifndef CONFIG_CRYPTO_INTERNAL
00332         suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
00333 #endif /* CONFIG_CRYPTO_INTERNAL */
00334         suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
00335         suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
00336         suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
00337         suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
00338         conn->num_cipher_suites = count;
00339 
00340         return conn;
00341 }
00342 
00343 
00344 static void tlsv1_server_clear_data(struct tlsv1_server *conn)
00345 {
00346         tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
00347         tlsv1_record_change_write_cipher(&conn->rl);
00348         tlsv1_record_change_read_cipher(&conn->rl);
00349         tls_verify_hash_free(&conn->verify);
00350 
00351         crypto_public_key_free(conn->client_rsa_key);
00352         conn->client_rsa_key = NULL;
00353 
00354         os_free(conn->session_ticket);
00355         conn->session_ticket = NULL;
00356         conn->session_ticket_len = 0;
00357         conn->use_session_ticket = 0;
00358 
00359         os_free(conn->dh_secret);
00360         conn->dh_secret = NULL;
00361         conn->dh_secret_len = 0;
00362 }
00363 
00364 
00369 void tlsv1_server_deinit(struct tlsv1_server *conn)
00370 {
00371         tlsv1_server_clear_data(conn);
00372         os_free(conn);
00373 }
00374 
00375 
00381 int tlsv1_server_established(struct tlsv1_server *conn)
00382 {
00383         return conn->state == ESTABLISHED;
00384 }
00385 
00386 
00397 int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
00398                      int server_random_first, u8 *out, size_t out_len)
00399 {
00400         u8 seed[2 * TLS_RANDOM_LEN];
00401 
00402         if (conn->state != ESTABLISHED)
00403                 return -1;
00404 
00405         if (server_random_first) {
00406                 os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
00407                 os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
00408                           TLS_RANDOM_LEN);
00409         } else {
00410                 os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
00411                 os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
00412                           TLS_RANDOM_LEN);
00413         }
00414 
00415         return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
00416                        label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
00417 }
00418 
00419 
00429 int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf,
00430                             size_t buflen)
00431 {
00432         char *cipher;
00433 
00434         switch (conn->rl.cipher_suite) {
00435         case TLS_RSA_WITH_RC4_128_MD5:
00436                 cipher = "RC4-MD5";
00437                 break;
00438         case TLS_RSA_WITH_RC4_128_SHA:
00439                 cipher = "RC4-SHA";
00440                 break;
00441         case TLS_RSA_WITH_DES_CBC_SHA:
00442                 cipher = "DES-CBC-SHA";
00443                 break;
00444         case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
00445                 cipher = "DES-CBC3-SHA";
00446                 break;
00447         case TLS_DH_anon_WITH_AES_128_CBC_SHA:
00448                 cipher = "ADH-AES-128-SHA";
00449                 break;
00450         case TLS_RSA_WITH_AES_256_CBC_SHA:
00451                 cipher = "AES-256-SHA";
00452                 break;
00453         case TLS_RSA_WITH_AES_128_CBC_SHA:
00454                 cipher = "AES-128-SHA";
00455                 break;
00456         default:
00457                 return -1;
00458         }
00459 
00460         if (os_strlcpy(buf, cipher, buflen) >= buflen)
00461                 return -1;
00462         return 0;
00463 }
00464 
00465 
00471 int tlsv1_server_shutdown(struct tlsv1_server *conn)
00472 {
00473         conn->state = CLIENT_HELLO;
00474 
00475         if (tls_verify_hash_init(&conn->verify) < 0) {
00476                 wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
00477                            "hash");
00478                 return -1;
00479         }
00480 
00481         tlsv1_server_clear_data(conn);
00482 
00483         return 0;
00484 }
00485 
00486 
00492 int tlsv1_server_resumed(struct tlsv1_server *conn)
00493 {
00494         return 0;
00495 }
00496 
00497 
00504 int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys)
00505 {
00506         os_memset(keys, 0, sizeof(*keys));
00507         if (conn->state == CLIENT_HELLO)
00508                 return -1;
00509 
00510         keys->client_random = conn->client_random;
00511         keys->client_random_len = TLS_RANDOM_LEN;
00512 
00513         if (conn->state != SERVER_HELLO) {
00514                 keys->server_random = conn->server_random;
00515                 keys->server_random_len = TLS_RANDOM_LEN;
00516                 keys->master_key = conn->master_secret;
00517                 keys->master_key_len = TLS_MASTER_SECRET_LEN;
00518         }
00519 
00520         return 0;
00521 }
00522 
00523 
00530 int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn)
00531 {
00532         if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO)
00533                 return -1;
00534 
00535         return 2 * (conn->rl.hash_size + conn->rl.key_material_len +
00536                     conn->rl.iv_size);
00537 }
00538 
00539 
00547 int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers)
00548 {
00549         size_t count;
00550         u16 *suites;
00551 
00552         /* TODO: implement proper configuration of cipher suites */
00553         if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
00554                 count = 0;
00555                 suites = conn->cipher_suites;
00556 #ifndef CONFIG_CRYPTO_INTERNAL
00557                 suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
00558 #endif /* CONFIG_CRYPTO_INTERNAL */
00559                 suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
00560                 suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
00561                 suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
00562                 suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
00563 #ifndef CONFIG_CRYPTO_INTERNAL
00564                 suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
00565 #endif /* CONFIG_CRYPTO_INTERNAL */
00566                 suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
00567                 suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
00568                 suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
00569                 suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA;
00570                 conn->num_cipher_suites = count;
00571         }
00572 
00573         return 0;
00574 }
00575 
00576 
00577 int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer)
00578 {
00579         conn->verify_peer = verify_peer;
00580         return 0;
00581 }
00582 
00583 
00584 void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn,
00585                                         tlsv1_server_session_ticket_cb cb,
00586                                         void *ctx)
00587 {
00588         wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
00589                    cb, ctx);
00590         conn->session_ticket_cb = cb;
00591         conn->session_ticket_cb_ctx = ctx;
00592 }


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