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.
Dependents: blinky_max32630fthr
tls1_clnt.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 <time.h> 00034 #include <stdio.h> 00035 #include "os_port.h" 00036 #include "ssl.h" 00037 00038 #ifdef CONFIG_SSL_ENABLE_CLIENT /* all commented out if no client */ 00039 00040 static int send_client_hello(SSL *ssl); 00041 static int process_server_hello(SSL *ssl); 00042 static int process_server_hello_done(SSL *ssl); 00043 static int send_client_key_xchg(SSL *ssl); 00044 static int process_cert_req(SSL *ssl); 00045 static int send_cert_verify(SSL *ssl); 00046 00047 /* 00048 * Establish a new SSL connection to an SSL server. 00049 */ 00050 EXP_FUNC SSL * STDCALL ssl_client_new(SSL *ssl, int client_fd, const 00051 uint8_t *session_id, uint8_t sess_id_size) 00052 { 00053 SSL_CTX *ssl_ctx = ssl->ssl_ctx; 00054 ssl_new(ssl, client_fd); 00055 ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */ 00056 00057 if (session_id && ssl_ctx->num_sessions) 00058 { 00059 if (sess_id_size > SSL_SESSION_ID_SIZE) /* validity check */ 00060 { 00061 ssl_free(ssl); 00062 return NULL; 00063 } 00064 00065 memcpy(ssl->session_id, session_id, sess_id_size); 00066 ssl->sess_id_size = sess_id_size; 00067 SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */ 00068 } 00069 00070 SET_SSL_FLAG(SSL_IS_CLIENT); 00071 do_client_connect(ssl); 00072 return ssl; 00073 } 00074 00075 /* 00076 * Process the handshake record. 00077 */ 00078 int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len) 00079 { 00080 int ret; 00081 00082 /* To get here the state must be valid */ 00083 switch (handshake_type) 00084 { 00085 case HS_SERVER_HELLO: 00086 ret = process_server_hello(ssl); 00087 break; 00088 00089 case HS_CERTIFICATE: 00090 ret = process_certificate(ssl, &ssl->x509_ctx); 00091 break; 00092 00093 case HS_SERVER_HELLO_DONE: 00094 if ((ret = process_server_hello_done(ssl)) == SSL_OK) 00095 { 00096 if (IS_SET_SSL_FLAG(SSL_HAS_CERT_REQ)) 00097 { 00098 if ((ret = send_certificate(ssl)) == SSL_OK && 00099 (ret = send_client_key_xchg(ssl)) == SSL_OK) 00100 { 00101 send_cert_verify(ssl); 00102 } 00103 } 00104 else 00105 { 00106 ret = send_client_key_xchg(ssl); 00107 } 00108 00109 if (ret == SSL_OK && 00110 (ret = send_change_cipher_spec(ssl)) == SSL_OK) 00111 { 00112 ret = send_finished(ssl); 00113 } 00114 } 00115 break; 00116 00117 case HS_CERT_REQ: 00118 ret = process_cert_req(ssl); 00119 break; 00120 00121 case HS_FINISHED: 00122 ret = process_finished(ssl, buf, hs_len); 00123 disposable_free(ssl); /* free up some memory */ 00124 /* note: client renegotiation is not allowed after this */ 00125 break; 00126 00127 case HS_HELLO_REQUEST: 00128 disposable_new(ssl); 00129 ret = do_client_connect(ssl); 00130 break; 00131 00132 default: 00133 ret = SSL_ERROR_INVALID_HANDSHAKE; 00134 break; 00135 } 00136 00137 return ret; 00138 } 00139 00140 /* 00141 * Do the handshaking from the beginning. 00142 */ 00143 int do_client_connect(SSL *ssl) 00144 { 00145 int ret = SSL_OK; 00146 00147 send_client_hello(ssl); /* send the client hello */ 00148 ssl->bm_read_index = 0; 00149 ssl->next_state = HS_SERVER_HELLO; 00150 ssl->hs_status = SSL_NOT_OK; /* not connected */ 00151 00152 /* sit in a loop until it all looks good */ 00153 if (!IS_SET_SSL_FLAG(SSL_CONNECT_IN_PARTS)) 00154 { 00155 while (ssl->hs_status != SSL_OK) 00156 { 00157 ret = read_record(ssl); 00158 if (ret < SSL_OK) 00159 break; 00160 ret = process_data(ssl, NULL, 0); 00161 if (ret < SSL_OK) 00162 break; 00163 } 00164 ssl->hs_status = ret; /* connected? */ 00165 } 00166 return ret; 00167 } 00168 00169 static int compute_size_send_client_hello(SSL *ssl) 00170 { 00171 int size = 6 + SSL_RANDOM_SIZE; 00172 size++; 00173 if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME)) 00174 { 00175 00176 size += ssl->sess_id_size; 00177 } 00178 size += 2; 00179 int i; 00180 for (i = 0; i < NUM_PROTOCOLS; i++) 00181 size += 2; 00182 size += 2; 00183 return size+BM_RECORD_OFFSET; 00184 } 00185 00186 /* 00187 * Send the initial client hello. 00188 */ 00189 static int send_client_hello(SSL *ssl) 00190 { 00191 uint8_t *buf = ssl->bm_data; 00192 time_t tm = time(NULL); 00193 uint8_t *tm_ptr = &buf[6]; /* time will go here */ 00194 int i, offset; 00195 00196 buf[0] = HS_CLIENT_HELLO; 00197 buf[1] = 0; 00198 buf[2] = 0; 00199 /* byte 3 is calculated later */ 00200 buf[4] = 0x03; 00201 buf[5] = ssl->version & 0x0f; 00202 00203 /* client random value - spec says that 1st 4 bytes are big endian time */ 00204 *tm_ptr++ = (uint8_t)(((long)tm & 0xff000000) >> 24); 00205 *tm_ptr++ = (uint8_t)(((long)tm & 0x00ff0000) >> 16); 00206 *tm_ptr++ = (uint8_t)(((long)tm & 0x0000ff00) >> 8); 00207 *tm_ptr++ = (uint8_t)(((long)tm & 0x000000ff)); 00208 get_random(SSL_RANDOM_SIZE-4, &buf[10]); 00209 memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE); 00210 offset = 6 + SSL_RANDOM_SIZE; 00211 00212 /* give session resumption a go */ 00213 if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME)) /* set initially by user */ 00214 { 00215 buf[offset++] = ssl->sess_id_size; 00216 memcpy(&buf[offset], ssl->session_id, ssl->sess_id_size); 00217 offset += ssl->sess_id_size; 00218 CLR_SSL_FLAG(SSL_SESSION_RESUME); /* clear so we can set later */ 00219 } 00220 else 00221 { 00222 /* no session id - because no session resumption just yet */ 00223 buf[offset++] = 0; 00224 } 00225 00226 buf[offset++] = 0; /* number of ciphers */ 00227 buf[offset++] = NUM_PROTOCOLS*2;/* number of ciphers */ 00228 00229 /* put all our supported protocols in our request */ 00230 for (i = 0; i < NUM_PROTOCOLS; i++) 00231 { 00232 buf[offset++] = 0; /* cipher we are using */ 00233 buf[offset++] = ssl_prot_prefs[i]; 00234 } 00235 00236 buf[offset++] = 1; /* no compression */ 00237 buf[offset++] = 0; 00238 buf[3] = offset - 4; /* handshake size */ 00239 00240 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset); 00241 } 00242 00243 /* 00244 * Process the server hello. 00245 */ 00246 static int process_server_hello(SSL *ssl) 00247 { 00248 uint8_t *buf = ssl->bm_data; 00249 int pkt_size = ssl->bm_index; 00250 int num_sessions = ssl->ssl_ctx->num_sessions; 00251 uint8_t sess_id_size; 00252 int offset, ret = SSL_OK; 00253 00254 /* check that we are talking to a TLSv1 server */ 00255 uint8_t version = (buf[0] << 4) + buf[1]; 00256 if (version > SSL_PROTOCOL_VERSION_MAX) 00257 { 00258 version = SSL_PROTOCOL_VERSION_MAX; 00259 } 00260 else if (ssl->version < SSL_PROTOCOL_MIN_VERSION) 00261 { 00262 ret = SSL_ERROR_INVALID_VERSION; 00263 ssl_display_error(ret); 00264 goto error; 00265 } 00266 00267 ssl->version = version; 00268 00269 /* get the server random value */ 00270 memcpy(ssl->dc->server_random, &buf[2], SSL_RANDOM_SIZE); 00271 offset = 2 + SSL_RANDOM_SIZE; /* skip of session id size */ 00272 sess_id_size = buf[offset++]; 00273 00274 if (sess_id_size > SSL_SESSION_ID_SIZE) 00275 { 00276 ret = SSL_ERROR_INVALID_SESSION; 00277 goto error; 00278 } 00279 00280 if (num_sessions) 00281 { 00282 ssl->session = ssl_session_update(num_sessions, 00283 ssl->ssl_ctx->ssl_sessions, ssl, &buf[offset]); 00284 memcpy(ssl->session->session_id, &buf[offset], sess_id_size); 00285 00286 /* pad the rest with 0's */ 00287 if (sess_id_size < SSL_SESSION_ID_SIZE) 00288 { 00289 memset(&ssl->session->session_id[sess_id_size], 0, 00290 SSL_SESSION_ID_SIZE-sess_id_size); 00291 } 00292 } 00293 00294 memcpy(ssl->session_id, &buf[offset], sess_id_size); 00295 ssl->sess_id_size = sess_id_size; 00296 offset += sess_id_size; 00297 00298 /* get the real cipher we are using */ 00299 ssl->cipher = buf[++offset]; 00300 ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ? 00301 HS_FINISHED : HS_CERTIFICATE; 00302 00303 offset++; // skip the compr 00304 PARANOIA_CHECK(pkt_size, offset); 00305 ssl->dc->bm_proc_index = offset+1; 00306 00307 error: 00308 return ret; 00309 } 00310 00311 /** 00312 * Process the server hello done message. 00313 */ 00314 static int process_server_hello_done(SSL *ssl) 00315 { 00316 ssl->next_state = HS_FINISHED; 00317 return SSL_OK; 00318 } 00319 00320 /* 00321 * Send a client key exchange message. 00322 */ 00323 static int send_client_key_xchg(SSL *ssl) 00324 { 00325 uint8_t *buf = ssl->bm_data; 00326 uint8_t premaster_secret[SSL_SECRET_SIZE]; 00327 int enc_secret_size = -1; 00328 00329 buf[0] = HS_CLIENT_KEY_XCHG; 00330 buf[1] = 0; 00331 00332 premaster_secret[0] = 0x03; /* encode the version number */ 00333 premaster_secret[1] = SSL_PROTOCOL_MINOR_VERSION; /* must be TLS 1.1 */ 00334 get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]); 00335 DISPLAY_RSA(ssl, ssl->x509_ctx->rsa_ctx); 00336 00337 /* rsa_ctx->bi_ctx is not thread-safe */ 00338 SSL_CTX_LOCK(ssl->ssl_ctx->mutex); 00339 enc_secret_size = RSA_encrypt(ssl->x509_ctx->rsa_ctx, premaster_secret, 00340 SSL_SECRET_SIZE, &buf[6], 0); 00341 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); 00342 00343 buf[2] = (enc_secret_size + 2) >> 8; 00344 buf[3] = (enc_secret_size + 2) & 0xff; 00345 buf[4] = enc_secret_size >> 8; 00346 buf[5] = enc_secret_size & 0xff; 00347 00348 generate_master_secret(ssl, premaster_secret); 00349 00350 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, enc_secret_size+6); 00351 } 00352 00353 /* 00354 * Process the certificate request. 00355 */ 00356 static int process_cert_req(SSL *ssl) 00357 { 00358 uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index]; 00359 int ret = SSL_OK; 00360 int offset = (buf[2] << 4) + buf[3]; 00361 int pkt_size = ssl->bm_index; 00362 00363 /* don't do any processing - we will send back an RSA certificate anyway */ 00364 ssl->next_state = HS_SERVER_HELLO_DONE; 00365 SET_SSL_FLAG(SSL_HAS_CERT_REQ); 00366 ssl->dc->bm_proc_index += offset; 00367 PARANOIA_CHECK(pkt_size, offset); 00368 error: 00369 return ret; 00370 } 00371 00372 /* 00373 * Send a certificate verify message. 00374 */ 00375 static int send_cert_verify(SSL *ssl) 00376 { 00377 uint8_t *buf = ssl->bm_data; 00378 uint8_t dgst[MD5_SIZE+SHA1_SIZE]; 00379 RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx; 00380 int n = 0, ret; 00381 00382 DISPLAY_RSA(ssl, rsa_ctx); 00383 00384 buf[0] = HS_CERT_VERIFY; 00385 buf[1] = 0; 00386 00387 finished_digest(ssl, NULL, dgst); /* calculate the digest */ 00388 00389 /* rsa_ctx->bi_ctx is not thread-safe */ 00390 if (rsa_ctx) 00391 { 00392 SSL_CTX_LOCK(ssl->ssl_ctx->mutex); 00393 n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1); 00394 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); 00395 00396 if (n == 0) 00397 { 00398 ret = SSL_ERROR_INVALID_KEY; 00399 goto error; 00400 } 00401 } 00402 00403 buf[4] = n >> 8; /* add the RSA size (not officially documented) */ 00404 buf[5] = n & 0xff; 00405 n += 2; 00406 buf[2] = n >> 8; 00407 buf[3] = n & 0xff; 00408 ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4); 00409 00410 error: 00411 return ret; 00412 } 00413 00414 #endif /* CONFIG_SSL_ENABLE_CLIENT */
Generated on Tue Jul 12 2022 14:21:24 by
1.7.2
