Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
tls1_svr.c
00001 /* 00002 * Copyright (c) 2007, Cameron Rich 00003 * 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * 00009 * * Redistributions of source code must retain the above copyright notice, 00010 * this list of conditions and the following disclaimer. 00011 * * Redistributions in binary form must reproduce the above copyright notice, 00012 * this list of conditions and the following disclaimer in the documentation 00013 * and/or other materials provided with the distribution. 00014 * * Neither the name of the axTLS project nor the names of its contributors 00015 * may be used to endorse or promote products derived from this software 00016 * without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00025 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00026 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <stdio.h> 00034 #include "os_port.h" 00035 #include "ssl.h" 00036 00037 static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 }; 00038 00039 static int process_client_hello(SSL *ssl); 00040 static int send_server_hello_sequence(SSL *ssl); 00041 static int send_server_hello(SSL *ssl); 00042 static int send_server_hello_done(SSL *ssl); 00043 static int process_client_key_xchg(SSL *ssl); 00044 #ifdef CONFIG_SSL_CERT_VERIFICATION 00045 static int send_certificate_request(SSL *ssl); 00046 static int process_cert_verify(SSL *ssl); 00047 #endif 00048 00049 /* 00050 * Establish a new SSL connection to an SSL client. 00051 */ 00052 EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd) 00053 { 00054 SSL *ssl; 00055 00056 ssl = ssl_new(ssl_ctx, client_fd); 00057 ssl->next_state = HS_CLIENT_HELLO; 00058 00059 #ifdef CONFIG_SSL_FULL_MODE 00060 if (ssl_ctx->chain_length == 0) 00061 printf("Warning - no server certificate defined\n"); TTY_FLUSH(); 00062 #endif 00063 00064 return ssl; 00065 } 00066 00067 /* 00068 * Process the handshake record. 00069 */ 00070 int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) 00071 { 00072 int ret = SSL_OK; 00073 ssl->hs_status = SSL_NOT_OK; /* not connected */ 00074 00075 /* To get here the state must be valid */ 00076 switch (handshake_type) 00077 { 00078 case HS_CLIENT_HELLO: 00079 if ((ret = process_client_hello(ssl)) == SSL_OK) 00080 ret = send_server_hello_sequence(ssl); 00081 break; 00082 00083 #ifdef CONFIG_SSL_CERT_VERIFICATION 00084 case HS_CERTIFICATE:/* the client sends its cert */ 00085 ret = process_certificate(ssl, &ssl->x509_ctx); 00086 00087 if (ret == SSL_OK) /* verify the cert */ 00088 { 00089 int cert_res; 00090 cert_res = x509_verify( 00091 ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx); 00092 ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res); 00093 } 00094 break; 00095 00096 case HS_CERT_VERIFY: 00097 ret = process_cert_verify(ssl); 00098 add_packet(ssl, buf, hs_len); /* needs to be done after */ 00099 break; 00100 #endif 00101 case HS_CLIENT_KEY_XCHG: 00102 ret = process_client_key_xchg(ssl); 00103 break; 00104 00105 case HS_FINISHED: 00106 ret = process_finished(ssl, buf, hs_len); 00107 disposable_free(ssl); /* free up some memory */ 00108 break; 00109 } 00110 00111 return ret; 00112 } 00113 00114 /* 00115 * Process a client hello message. 00116 */ 00117 static int process_client_hello(SSL *ssl) 00118 { 00119 uint8_t *buf = ssl->bm_data; 00120 uint8_t *record_buf = ssl->hmac_header; 00121 int pkt_size = ssl->bm_index; 00122 int i, j, cs_len, id_len, offset = 6 + SSL_RANDOM_SIZE; 00123 int ret = SSL_OK; 00124 00125 uint8_t version = (buf[4] << 4) + buf[5]; 00126 ssl->version = ssl->client_version = version; 00127 00128 if (version > SSL_PROTOCOL_VERSION_MAX) 00129 { 00130 /* use client's version instead */ 00131 ssl->version = SSL_PROTOCOL_VERSION_MAX; 00132 } 00133 else if (version < SSL_PROTOCOL_MIN_VERSION) /* old version supported? */ 00134 { 00135 ret = SSL_ERROR_INVALID_VERSION; 00136 ssl_display_error(ret); 00137 goto error; 00138 } 00139 00140 memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE); 00141 00142 /* process the session id */ 00143 id_len = buf[offset++]; 00144 if (id_len > SSL_SESSION_ID_SIZE) 00145 { 00146 return SSL_ERROR_INVALID_SESSION; 00147 } 00148 00149 #ifndef CONFIG_SSL_SKELETON_MODE 00150 ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions, 00151 ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL); 00152 #endif 00153 00154 offset += id_len; 00155 cs_len = (buf[offset]<<8) + buf[offset+1]; 00156 offset += 3; /* add 1 due to all cipher suites being 8 bit */ 00157 00158 PARANOIA_CHECK(pkt_size, offset); 00159 00160 /* work out what cipher suite we are going to use - client defines 00161 the preference */ 00162 for (i = 0; i < cs_len; i += 2) 00163 { 00164 for (j = 0; j < NUM_PROTOCOLS; j++) 00165 { 00166 if (ssl_prot_prefs[j] == buf[offset+i]) /* got a match? */ 00167 { 00168 ssl->cipher = ssl_prot_prefs[j]; 00169 goto do_state; 00170 } 00171 } 00172 } 00173 00174 /* ouch! protocol is not supported */ 00175 ret = SSL_ERROR_NO_CIPHER; 00176 00177 do_state: 00178 error: 00179 return ret; 00180 } 00181 00182 #ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE 00183 /* 00184 * Some browsers use a hybrid SSLv2 "client hello" 00185 */ 00186 int process_sslv23_client_hello(SSL *ssl) 00187 { 00188 uint8_t *buf = ssl->bm_data; 00189 int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1]; 00190 int ret = SSL_OK; 00191 00192 /* we have already read 3 extra bytes so far */ 00193 int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3); 00194 int cs_len = buf[1]; 00195 int id_len = buf[3]; 00196 int ch_len = buf[5]; 00197 int i, j, offset = 8; /* start at first cipher */ 00198 int random_offset = 0; 00199 00200 DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len); 00201 00202 add_packet(ssl, buf, read_len); 00203 00204 /* connection has gone, so die */ 00205 if (bytes_needed < 0) 00206 { 00207 return SSL_ERROR_CONN_LOST; 00208 } 00209 00210 /* now work out what cipher suite we are going to use */ 00211 for (j = 0; j < NUM_PROTOCOLS; j++) 00212 { 00213 for (i = 0; i < cs_len; i += 3) 00214 { 00215 if (ssl_prot_prefs[j] == buf[offset+i]) 00216 { 00217 ssl->cipher = ssl_prot_prefs[j]; 00218 goto server_hello; 00219 } 00220 } 00221 } 00222 00223 /* ouch! protocol is not supported */ 00224 ret = SSL_ERROR_NO_CIPHER; 00225 goto error; 00226 00227 server_hello: 00228 /* get the session id */ 00229 offset += cs_len - 2; /* we've gone 2 bytes past the end */ 00230 #ifndef CONFIG_SSL_SKELETON_MODE 00231 ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions, 00232 ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL); 00233 #endif 00234 00235 /* get the client random data */ 00236 offset += id_len; 00237 00238 /* random can be anywhere between 16 and 32 bytes long - so it is padded 00239 * with 0's to the left */ 00240 if (ch_len == 0x10) 00241 { 00242 random_offset += 0x10; 00243 } 00244 00245 memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len); 00246 ret = send_server_hello_sequence(ssl); 00247 00248 error: 00249 return ret; 00250 } 00251 #endif 00252 00253 /* 00254 * Send the entire server hello sequence 00255 */ 00256 static int send_server_hello_sequence(SSL *ssl) 00257 { 00258 int ret; 00259 00260 if ((ret = send_server_hello(ssl)) == SSL_OK) 00261 { 00262 #ifndef CONFIG_SSL_SKELETON_MODE 00263 /* resume handshake? */ 00264 if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME)) 00265 { 00266 if ((ret = send_change_cipher_spec(ssl)) == SSL_OK) 00267 { 00268 ret = send_finished(ssl); 00269 ssl->next_state = HS_FINISHED; 00270 } 00271 } 00272 else 00273 #endif 00274 if ((ret = send_certificate(ssl)) == SSL_OK) 00275 { 00276 #ifdef CONFIG_SSL_CERT_VERIFICATION 00277 /* ask the client for its certificate */ 00278 if (IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION)) 00279 { 00280 if ((ret = send_certificate_request(ssl)) == SSL_OK) 00281 { 00282 ret = send_server_hello_done(ssl); 00283 ssl->next_state = HS_CERTIFICATE; 00284 } 00285 } 00286 else 00287 #endif 00288 { 00289 ret = send_server_hello_done(ssl); 00290 ssl->next_state = HS_CLIENT_KEY_XCHG; 00291 } 00292 } 00293 } 00294 00295 return ret; 00296 } 00297 00298 /* 00299 * Send a server hello message. 00300 */ 00301 static int send_server_hello(SSL *ssl) 00302 { 00303 uint8_t *buf = ssl->bm_data; 00304 int offset = 0; 00305 00306 buf[0] = HS_SERVER_HELLO; 00307 buf[1] = 0; 00308 buf[2] = 0; 00309 /* byte 3 is calculated later */ 00310 buf[4] = 0x03; 00311 buf[5] = ssl->version & 0x0f; 00312 00313 /* server random value */ 00314 get_random(SSL_RANDOM_SIZE, &buf[6]); 00315 memcpy(ssl->dc->server_random, &buf[6], SSL_RANDOM_SIZE); 00316 offset = 6 + SSL_RANDOM_SIZE; 00317 00318 #ifndef CONFIG_SSL_SKELETON_MODE 00319 if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME)) 00320 { 00321 /* retrieve id from session cache */ 00322 buf[offset++] = SSL_SESSION_ID_SIZE; 00323 memcpy(&buf[offset], ssl->session->session_id, SSL_SESSION_ID_SIZE); 00324 memcpy(ssl->session_id, ssl->session->session_id, SSL_SESSION_ID_SIZE); 00325 ssl->sess_id_size = SSL_SESSION_ID_SIZE; 00326 offset += SSL_SESSION_ID_SIZE; 00327 } 00328 else /* generate our own session id */ 00329 #endif 00330 { 00331 #ifndef CONFIG_SSL_SKELETON_MODE 00332 buf[offset++] = SSL_SESSION_ID_SIZE; 00333 get_random(SSL_SESSION_ID_SIZE, &buf[offset]); 00334 memcpy(ssl->session_id, &buf[offset], SSL_SESSION_ID_SIZE); 00335 ssl->sess_id_size = SSL_SESSION_ID_SIZE; 00336 00337 /* store id in session cache */ 00338 if (ssl->ssl_ctx->num_sessions) 00339 { 00340 memcpy(ssl->session->session_id, 00341 ssl->session_id, SSL_SESSION_ID_SIZE); 00342 } 00343 00344 offset += SSL_SESSION_ID_SIZE; 00345 #else 00346 buf[offset++] = 0; /* don't bother with session id in skelton mode */ 00347 #endif 00348 } 00349 00350 buf[offset++] = 0; /* cipher we are using */ 00351 buf[offset++] = ssl->cipher; 00352 buf[offset++] = 0; /* no compression */ 00353 buf[3] = offset - 4; /* handshake size */ 00354 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset); 00355 } 00356 00357 /* 00358 * Send the server hello done message. 00359 */ 00360 static int send_server_hello_done(SSL *ssl) 00361 { 00362 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 00363 g_hello_done, sizeof(g_hello_done)); 00364 } 00365 00366 /* 00367 * Pull apart a client key exchange message. Decrypt the pre-master key (using 00368 * our RSA private key) and then work out the master key. Initialise the 00369 * ciphers. 00370 */ 00371 static int process_client_key_xchg(SSL *ssl) 00372 { 00373 uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index]; 00374 int pkt_size = ssl->bm_index; 00375 int premaster_size, secret_length = (buf[2] << 8) + buf[3]; 00376 uint8_t premaster_secret[MAX_KEY_BYTE_SIZE]; 00377 RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx; 00378 int offset = 4; 00379 int ret = SSL_OK; 00380 00381 if (rsa_ctx == NULL) 00382 { 00383 ret = SSL_ERROR_NO_CERT_DEFINED; 00384 goto error; 00385 } 00386 00387 /* is there an extra size field? */ 00388 if ((secret_length - 2) == rsa_ctx->num_octets) 00389 offset += 2; 00390 00391 PARANOIA_CHECK(pkt_size, rsa_ctx->num_octets+offset); 00392 00393 /* rsa_ctx->bi_ctx is not thread-safe */ 00394 SSL_CTX_LOCK(ssl->ssl_ctx->mutex); 00395 premaster_size = RSA_decrypt(rsa_ctx, &buf[offset], premaster_secret, 1); 00396 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); 00397 00398 if (premaster_size != SSL_SECRET_SIZE || 00399 premaster_secret[0] != 0x03 || /* must be the same as client 00400 offered version */ 00401 premaster_secret[1] != (ssl->client_version & 0x0f)) 00402 { 00403 /* guard against a Bleichenbacher attack */ 00404 get_random(SSL_SECRET_SIZE, premaster_secret); 00405 /* and continue - will die eventually when checking the mac */ 00406 } 00407 00408 #if 0 00409 print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE); 00410 #endif 00411 00412 generate_master_secret(ssl, premaster_secret); 00413 00414 #ifdef CONFIG_SSL_CERT_VERIFICATION 00415 ssl->next_state = IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION) ? 00416 HS_CERT_VERIFY : HS_FINISHED; 00417 #else 00418 ssl->next_state = HS_FINISHED; 00419 #endif 00420 00421 ssl->dc->bm_proc_index += rsa_ctx->num_octets+offset; 00422 error: 00423 return ret; 00424 } 00425 00426 #ifdef CONFIG_SSL_CERT_VERIFICATION 00427 static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 }; 00428 00429 /* 00430 * Send the certificate request message. 00431 */ 00432 static int send_certificate_request(SSL *ssl) 00433 { 00434 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 00435 g_cert_request, sizeof(g_cert_request)); 00436 } 00437 00438 /* 00439 * Ensure the client has the private key by first decrypting the packet and 00440 * then checking the packet digests. 00441 */ 00442 static int process_cert_verify(SSL *ssl) 00443 { 00444 uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index]; 00445 int pkt_size = ssl->bm_index; 00446 uint8_t dgst_buf[MAX_KEY_BYTE_SIZE]; 00447 uint8_t dgst[MD5_SIZE+SHA1_SIZE]; 00448 X509_CTX *x509_ctx = ssl->x509_ctx; 00449 int ret = SSL_OK; 00450 int n; 00451 00452 PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6); 00453 DISPLAY_RSA(ssl, x509_ctx->rsa_ctx); 00454 00455 /* rsa_ctx->bi_ctx is not thread-safe */ 00456 SSL_CTX_LOCK(ssl->ssl_ctx->mutex); 00457 n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, 0); 00458 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); 00459 00460 if (n != SHA1_SIZE + MD5_SIZE) 00461 { 00462 ret = SSL_ERROR_INVALID_KEY; 00463 goto end_cert_vfy; 00464 } 00465 00466 finished_digest(ssl, NULL, dgst); /* calculate the digest */ 00467 if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE)) 00468 { 00469 ret = SSL_ERROR_INVALID_KEY; 00470 } 00471 00472 end_cert_vfy: 00473 ssl->next_state = HS_FINISHED; 00474 error: 00475 return ret; 00476 } 00477 00478 #endif
Generated on Tue Jul 12 2022 13:16:17 by
