Annotation of embedaddon/axTLS/ssl/tls1_svr.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 2007, Cameron Rich
! 3: *
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions are met:
! 8: *
! 9: * * Redistributions of source code must retain the above copyright notice,
! 10: * this list of conditions and the following disclaimer.
! 11: * * Redistributions in binary form must reproduce the above copyright notice,
! 12: * this list of conditions and the following disclaimer in the documentation
! 13: * and/or other materials provided with the distribution.
! 14: * * Neither the name of the axTLS project nor the names of its contributors
! 15: * may be used to endorse or promote products derived from this software
! 16: * without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
! 19: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
! 20: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
! 21: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
! 22: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 23: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 24: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
! 25: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
! 26: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
! 27: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
! 28: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 29: */
! 30:
! 31: #include <stdlib.h>
! 32: #include <string.h>
! 33: #include <stdio.h>
! 34: #include "os_port.h"
! 35: #include "ssl.h"
! 36:
! 37: static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
! 38:
! 39: static int process_client_hello(SSL *ssl);
! 40: static int send_server_hello_sequence(SSL *ssl);
! 41: static int send_server_hello(SSL *ssl);
! 42: static int send_server_hello_done(SSL *ssl);
! 43: static int process_client_key_xchg(SSL *ssl);
! 44: #ifdef CONFIG_SSL_CERT_VERIFICATION
! 45: static int send_certificate_request(SSL *ssl);
! 46: static int process_cert_verify(SSL *ssl);
! 47: #endif
! 48:
! 49: /*
! 50: * Establish a new SSL connection to an SSL client.
! 51: */
! 52: EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd)
! 53: {
! 54: SSL *ssl;
! 55:
! 56: ssl = ssl_new(ssl_ctx, client_fd);
! 57: ssl->next_state = HS_CLIENT_HELLO;
! 58:
! 59: #ifdef CONFIG_SSL_FULL_MODE
! 60: if (ssl_ctx->chain_length == 0)
! 61: printf("Warning - no server certificate defined\n"); TTY_FLUSH();
! 62: #endif
! 63:
! 64: return ssl;
! 65: }
! 66:
! 67: /*
! 68: * Process the handshake record.
! 69: */
! 70: int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
! 71: {
! 72: int ret = SSL_OK;
! 73: ssl->hs_status = SSL_NOT_OK; /* not connected */
! 74:
! 75: /* To get here the state must be valid */
! 76: switch (handshake_type)
! 77: {
! 78: case HS_CLIENT_HELLO:
! 79: if ((ret = process_client_hello(ssl)) == SSL_OK)
! 80: ret = send_server_hello_sequence(ssl);
! 81: break;
! 82:
! 83: #ifdef CONFIG_SSL_CERT_VERIFICATION
! 84: case HS_CERTIFICATE:/* the client sends its cert */
! 85: ret = process_certificate(ssl, &ssl->x509_ctx);
! 86:
! 87: if (ret == SSL_OK) /* verify the cert */
! 88: {
! 89: int cert_res;
! 90: cert_res = x509_verify(
! 91: ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
! 92: ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res);
! 93: }
! 94: break;
! 95:
! 96: case HS_CERT_VERIFY:
! 97: ret = process_cert_verify(ssl);
! 98: add_packet(ssl, buf, hs_len); /* needs to be done after */
! 99: break;
! 100: #endif
! 101: case HS_CLIENT_KEY_XCHG:
! 102: ret = process_client_key_xchg(ssl);
! 103: break;
! 104:
! 105: case HS_FINISHED:
! 106: ret = process_finished(ssl, buf, hs_len);
! 107: disposable_free(ssl); /* free up some memory */
! 108: break;
! 109: }
! 110:
! 111: return ret;
! 112: }
! 113:
! 114: /*
! 115: * Process a client hello message.
! 116: */
! 117: static int process_client_hello(SSL *ssl)
! 118: {
! 119: uint8_t *buf = ssl->bm_data;
! 120: uint8_t *record_buf = ssl->hmac_header;
! 121: int pkt_size = ssl->bm_index;
! 122: int i, j, cs_len, id_len, offset = 6 + SSL_RANDOM_SIZE;
! 123: int ret = SSL_OK;
! 124:
! 125: uint8_t version = (record_buf[1] << 4) + record_buf[2];
! 126: ssl->version = ssl->client_version = version;
! 127:
! 128: if (version > SSL_PROTOCOL_VERSION_MAX)
! 129: {
! 130: /* use client's version instead */
! 131: ssl->version = SSL_PROTOCOL_VERSION_MAX;
! 132: }
! 133: else if (version < SSL_PROTOCOL_MIN_VERSION) /* old version supported? */
! 134: {
! 135: ret = SSL_ERROR_INVALID_VERSION;
! 136: ssl_display_error(ret);
! 137: goto error;
! 138: }
! 139:
! 140: memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE);
! 141:
! 142: /* process the session id */
! 143: id_len = buf[offset++];
! 144: if (id_len > SSL_SESSION_ID_SIZE)
! 145: {
! 146: return SSL_ERROR_INVALID_SESSION;
! 147: }
! 148:
! 149: #ifndef CONFIG_SSL_SKELETON_MODE
! 150: ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
! 151: ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
! 152: #endif
! 153:
! 154: offset += id_len;
! 155: cs_len = (buf[offset]<<8) + buf[offset+1];
! 156: offset += 3; /* add 1 due to all cipher suites being 8 bit */
! 157:
! 158: PARANOIA_CHECK(pkt_size, offset);
! 159:
! 160: /* work out what cipher suite we are going to use - client defines
! 161: the preference */
! 162: for (i = 0; i < cs_len; i += 2)
! 163: {
! 164: for (j = 0; j < NUM_PROTOCOLS; j++)
! 165: {
! 166: if (ssl_prot_prefs[j] == buf[offset+i]) /* got a match? */
! 167: {
! 168: ssl->cipher = ssl_prot_prefs[j];
! 169: goto do_state;
! 170: }
! 171: }
! 172: }
! 173:
! 174: /* ouch! protocol is not supported */
! 175: ret = SSL_ERROR_NO_CIPHER;
! 176:
! 177: do_state:
! 178: error:
! 179: return ret;
! 180: }
! 181:
! 182: #ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
! 183: /*
! 184: * Some browsers use a hybrid SSLv2 "client hello"
! 185: */
! 186: int process_sslv23_client_hello(SSL *ssl)
! 187: {
! 188: uint8_t *buf = ssl->bm_data;
! 189: int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
! 190: int ret = SSL_OK;
! 191:
! 192: /* we have already read 3 extra bytes so far */
! 193: int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
! 194: int cs_len = buf[1];
! 195: int id_len = buf[3];
! 196: int ch_len = buf[5];
! 197: int i, j, offset = 8; /* start at first cipher */
! 198: int random_offset = 0;
! 199:
! 200: DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
! 201:
! 202: add_packet(ssl, buf, read_len);
! 203:
! 204: /* connection has gone, so die */
! 205: if (bytes_needed < 0)
! 206: {
! 207: return SSL_ERROR_CONN_LOST;
! 208: }
! 209:
! 210: /* now work out what cipher suite we are going to use */
! 211: for (j = 0; j < NUM_PROTOCOLS; j++)
! 212: {
! 213: for (i = 0; i < cs_len; i += 3)
! 214: {
! 215: if (ssl_prot_prefs[j] == buf[offset+i])
! 216: {
! 217: ssl->cipher = ssl_prot_prefs[j];
! 218: goto server_hello;
! 219: }
! 220: }
! 221: }
! 222:
! 223: /* ouch! protocol is not supported */
! 224: ret = SSL_ERROR_NO_CIPHER;
! 225: goto error;
! 226:
! 227: server_hello:
! 228: /* get the session id */
! 229: offset += cs_len - 2; /* we've gone 2 bytes past the end */
! 230: #ifndef CONFIG_SSL_SKELETON_MODE
! 231: ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
! 232: ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
! 233: #endif
! 234:
! 235: /* get the client random data */
! 236: offset += id_len;
! 237:
! 238: /* random can be anywhere between 16 and 32 bytes long - so it is padded
! 239: * with 0's to the left */
! 240: if (ch_len == 0x10)
! 241: {
! 242: random_offset += 0x10;
! 243: }
! 244:
! 245: memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len);
! 246: ret = send_server_hello_sequence(ssl);
! 247:
! 248: error:
! 249: return ret;
! 250: }
! 251: #endif
! 252:
! 253: /*
! 254: * Send the entire server hello sequence
! 255: */
! 256: static int send_server_hello_sequence(SSL *ssl)
! 257: {
! 258: int ret;
! 259:
! 260: if ((ret = send_server_hello(ssl)) == SSL_OK)
! 261: {
! 262: #ifndef CONFIG_SSL_SKELETON_MODE
! 263: /* resume handshake? */
! 264: if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
! 265: {
! 266: if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
! 267: {
! 268: ret = send_finished(ssl);
! 269: ssl->next_state = HS_FINISHED;
! 270: }
! 271: }
! 272: else
! 273: #endif
! 274: if ((ret = send_certificate(ssl)) == SSL_OK)
! 275: {
! 276: #ifdef CONFIG_SSL_CERT_VERIFICATION
! 277: /* ask the client for its certificate */
! 278: if (IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION))
! 279: {
! 280: if ((ret = send_certificate_request(ssl)) == SSL_OK)
! 281: {
! 282: ret = send_server_hello_done(ssl);
! 283: ssl->next_state = HS_CERTIFICATE;
! 284: }
! 285: }
! 286: else
! 287: #endif
! 288: {
! 289: ret = send_server_hello_done(ssl);
! 290: ssl->next_state = HS_CLIENT_KEY_XCHG;
! 291: }
! 292: }
! 293: }
! 294:
! 295: return ret;
! 296: }
! 297:
! 298: /*
! 299: * Send a server hello message.
! 300: */
! 301: static int send_server_hello(SSL *ssl)
! 302: {
! 303: uint8_t *buf = ssl->bm_data;
! 304: int offset = 0;
! 305:
! 306: buf[0] = HS_SERVER_HELLO;
! 307: buf[1] = 0;
! 308: buf[2] = 0;
! 309: /* byte 3 is calculated later */
! 310: buf[4] = 0x03;
! 311: buf[5] = ssl->version & 0x0f;
! 312:
! 313: /* server random value */
! 314: get_random(SSL_RANDOM_SIZE, &buf[6]);
! 315: memcpy(ssl->dc->server_random, &buf[6], SSL_RANDOM_SIZE);
! 316: offset = 6 + SSL_RANDOM_SIZE;
! 317:
! 318: #ifndef CONFIG_SSL_SKELETON_MODE
! 319: if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
! 320: {
! 321: /* retrieve id from session cache */
! 322: buf[offset++] = SSL_SESSION_ID_SIZE;
! 323: memcpy(&buf[offset], ssl->session->session_id, SSL_SESSION_ID_SIZE);
! 324: memcpy(ssl->session_id, ssl->session->session_id, SSL_SESSION_ID_SIZE);
! 325: ssl->sess_id_size = SSL_SESSION_ID_SIZE;
! 326: offset += SSL_SESSION_ID_SIZE;
! 327: }
! 328: else /* generate our own session id */
! 329: #endif
! 330: {
! 331: #ifndef CONFIG_SSL_SKELETON_MODE
! 332: buf[offset++] = SSL_SESSION_ID_SIZE;
! 333: get_random(SSL_SESSION_ID_SIZE, &buf[offset]);
! 334: memcpy(ssl->session_id, &buf[offset], SSL_SESSION_ID_SIZE);
! 335: ssl->sess_id_size = SSL_SESSION_ID_SIZE;
! 336:
! 337: /* store id in session cache */
! 338: if (ssl->ssl_ctx->num_sessions)
! 339: {
! 340: memcpy(ssl->session->session_id,
! 341: ssl->session_id, SSL_SESSION_ID_SIZE);
! 342: }
! 343:
! 344: offset += SSL_SESSION_ID_SIZE;
! 345: #else
! 346: buf[offset++] = 0; /* don't bother with session id in skelton mode */
! 347: #endif
! 348: }
! 349:
! 350: buf[offset++] = 0; /* cipher we are using */
! 351: buf[offset++] = ssl->cipher;
! 352: buf[offset++] = 0; /* no compression */
! 353: buf[3] = offset - 4; /* handshake size */
! 354: return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
! 355: }
! 356:
! 357: /*
! 358: * Send the server hello done message.
! 359: */
! 360: static int send_server_hello_done(SSL *ssl)
! 361: {
! 362: return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
! 363: g_hello_done, sizeof(g_hello_done));
! 364: }
! 365:
! 366: /*
! 367: * Pull apart a client key exchange message. Decrypt the pre-master key (using
! 368: * our RSA private key) and then work out the master key. Initialise the
! 369: * ciphers.
! 370: */
! 371: static int process_client_key_xchg(SSL *ssl)
! 372: {
! 373: uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
! 374: int pkt_size = ssl->bm_index;
! 375: int premaster_size, secret_length = (buf[2] << 8) + buf[3];
! 376: uint8_t premaster_secret[MAX_KEY_BYTE_SIZE];
! 377: RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
! 378: int offset = 4;
! 379: int ret = SSL_OK;
! 380:
! 381: if (rsa_ctx == NULL)
! 382: {
! 383: ret = SSL_ERROR_NO_CERT_DEFINED;
! 384: goto error;
! 385: }
! 386:
! 387: /* is there an extra size field? */
! 388: if ((secret_length - 2) == rsa_ctx->num_octets)
! 389: offset += 2;
! 390:
! 391: PARANOIA_CHECK(pkt_size, rsa_ctx->num_octets+offset);
! 392:
! 393: /* rsa_ctx->bi_ctx is not thread-safe */
! 394: SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
! 395: premaster_size = RSA_decrypt(rsa_ctx, &buf[offset], premaster_secret, 1);
! 396: SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
! 397:
! 398: if (premaster_size != SSL_SECRET_SIZE ||
! 399: premaster_secret[0] != 0x03 || /* must be the same as client
! 400: offered version */
! 401: premaster_secret[1] != (ssl->client_version & 0x0f))
! 402: {
! 403: /* guard against a Bleichenbacher attack */
! 404: get_random(SSL_SECRET_SIZE, premaster_secret);
! 405: /* and continue - will die eventually when checking the mac */
! 406: }
! 407:
! 408: #if 0
! 409: print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
! 410: #endif
! 411:
! 412: generate_master_secret(ssl, premaster_secret);
! 413:
! 414: #ifdef CONFIG_SSL_CERT_VERIFICATION
! 415: ssl->next_state = IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION) ?
! 416: HS_CERT_VERIFY : HS_FINISHED;
! 417: #else
! 418: ssl->next_state = HS_FINISHED;
! 419: #endif
! 420:
! 421: ssl->dc->bm_proc_index += rsa_ctx->num_octets+offset;
! 422: error:
! 423: return ret;
! 424: }
! 425:
! 426: #ifdef CONFIG_SSL_CERT_VERIFICATION
! 427: static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
! 428:
! 429: /*
! 430: * Send the certificate request message.
! 431: */
! 432: static int send_certificate_request(SSL *ssl)
! 433: {
! 434: return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
! 435: g_cert_request, sizeof(g_cert_request));
! 436: }
! 437:
! 438: /*
! 439: * Ensure the client has the private key by first decrypting the packet and
! 440: * then checking the packet digests.
! 441: */
! 442: static int process_cert_verify(SSL *ssl)
! 443: {
! 444: uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
! 445: int pkt_size = ssl->bm_index;
! 446: uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
! 447: uint8_t dgst[MD5_SIZE+SHA1_SIZE];
! 448: X509_CTX *x509_ctx = ssl->x509_ctx;
! 449: int ret = SSL_OK;
! 450: int n;
! 451:
! 452: PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6);
! 453: DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
! 454:
! 455: /* rsa_ctx->bi_ctx is not thread-safe */
! 456: SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
! 457: n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, 0);
! 458: SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
! 459:
! 460: if (n != SHA1_SIZE + MD5_SIZE)
! 461: {
! 462: ret = SSL_ERROR_INVALID_KEY;
! 463: goto end_cert_vfy;
! 464: }
! 465:
! 466: finished_digest(ssl, NULL, dgst); /* calculate the digest */
! 467: if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE))
! 468: {
! 469: ret = SSL_ERROR_INVALID_KEY;
! 470: }
! 471:
! 472: end_cert_vfy:
! 473: ssl->next_state = HS_FINISHED;
! 474: error:
! 475: return ret;
! 476: }
! 477:
! 478: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>