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