Rough and ready port of axTLS

Committer:
ashleymills
Date:
Mon May 13 18:15:18 2013 +0000
Revision:
0:5a29fd060ac8
initial commit

Who changed what in which revision?

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