ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Committer:
group-onsemi
Date:
Wed Jan 25 20:34:15 2017 +0000
Revision:
0:098463de4c5d
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
group-onsemi 0:098463de4c5d 1 /*
group-onsemi 0:098463de4c5d 2 * Copyright (c) 2007, Cameron Rich
group-onsemi 0:098463de4c5d 3 *
group-onsemi 0:098463de4c5d 4 * All rights reserved.
group-onsemi 0:098463de4c5d 5 *
group-onsemi 0:098463de4c5d 6 * Redistribution and use in source and binary forms, with or without
group-onsemi 0:098463de4c5d 7 * modification, are permitted provided that the following conditions are met:
group-onsemi 0:098463de4c5d 8 *
group-onsemi 0:098463de4c5d 9 * * Redistributions of source code must retain the above copyright notice,
group-onsemi 0:098463de4c5d 10 * this list of conditions and the following disclaimer.
group-onsemi 0:098463de4c5d 11 * * Redistributions in binary form must reproduce the above copyright notice,
group-onsemi 0:098463de4c5d 12 * this list of conditions and the following disclaimer in the documentation
group-onsemi 0:098463de4c5d 13 * and/or other materials provided with the distribution.
group-onsemi 0:098463de4c5d 14 * * Neither the name of the axTLS project nor the names of its contributors
group-onsemi 0:098463de4c5d 15 * may be used to endorse or promote products derived from this software
group-onsemi 0:098463de4c5d 16 * without specific prior written permission.
group-onsemi 0:098463de4c5d 17 *
group-onsemi 0:098463de4c5d 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
group-onsemi 0:098463de4c5d 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
group-onsemi 0:098463de4c5d 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
group-onsemi 0:098463de4c5d 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
group-onsemi 0:098463de4c5d 22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
group-onsemi 0:098463de4c5d 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
group-onsemi 0:098463de4c5d 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
group-onsemi 0:098463de4c5d 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
group-onsemi 0:098463de4c5d 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
group-onsemi 0:098463de4c5d 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
group-onsemi 0:098463de4c5d 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
group-onsemi 0:098463de4c5d 29 */
group-onsemi 0:098463de4c5d 30
group-onsemi 0:098463de4c5d 31 /**
group-onsemi 0:098463de4c5d 32 * Common ssl/tlsv1 code to both the client and server implementations.
group-onsemi 0:098463de4c5d 33 */
group-onsemi 0:098463de4c5d 34
group-onsemi 0:098463de4c5d 35
group-onsemi 0:098463de4c5d 36 #include <string.h>
group-onsemi 0:098463de4c5d 37 #include <stdlib.h>
group-onsemi 0:098463de4c5d 38 #include <stdio.h>
group-onsemi 0:098463de4c5d 39 #include <stdarg.h>
group-onsemi 0:098463de4c5d 40 #include <errno.h>
group-onsemi 0:098463de4c5d 41
group-onsemi 0:098463de4c5d 42
group-onsemi 0:098463de4c5d 43
group-onsemi 0:098463de4c5d 44 #include "lwip/sockets.h"
group-onsemi 0:098463de4c5d 45 #include "os_port.h"
group-onsemi 0:098463de4c5d 46 #include "ssl.h"
group-onsemi 0:098463de4c5d 47 #include "arch.h"
group-onsemi 0:098463de4c5d 48
group-onsemi 0:098463de4c5d 49
group-onsemi 0:098463de4c5d 50 /* The session expiry time */
group-onsemi 0:098463de4c5d 51 #define SSL_EXPIRY_TIME (CONFIG_SSL_EXPIRY_TIME*3600)
group-onsemi 0:098463de4c5d 52
group-onsemi 0:098463de4c5d 53 static const uint8_t g_hello_request[] = { HS_HELLO_REQUEST, 0, 0, 0 };
group-onsemi 0:098463de4c5d 54 static const uint8_t g_chg_cipher_spec_pkt[] = { 1 };
group-onsemi 0:098463de4c5d 55 static const char * server_finished = "server finished";
group-onsemi 0:098463de4c5d 56 static const char * client_finished = "client finished";
group-onsemi 0:098463de4c5d 57
group-onsemi 0:098463de4c5d 58 static int do_handshake(SSL *ssl, uint8_t *buf, int read_len);
group-onsemi 0:098463de4c5d 59 static int set_key_block(SSL *ssl, int is_write);
group-onsemi 0:098463de4c5d 60 static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len);
group-onsemi 0:098463de4c5d 61 static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt);
group-onsemi 0:098463de4c5d 62 static int send_raw_packet(SSL *ssl, uint8_t protocol);
group-onsemi 0:098463de4c5d 63
group-onsemi 0:098463de4c5d 64 /**
group-onsemi 0:098463de4c5d 65 * The server will pick the cipher based on the order that the order that the
group-onsemi 0:098463de4c5d 66 * ciphers are listed. This order is defined at compile time.
group-onsemi 0:098463de4c5d 67 */
group-onsemi 0:098463de4c5d 68 #ifdef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 69 const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
group-onsemi 0:098463de4c5d 70 { SSL_RC4_128_SHA };
group-onsemi 0:098463de4c5d 71 #else
group-onsemi 0:098463de4c5d 72 static void session_free(SSL_SESSION *ssl_sessions[], int sess_index);
group-onsemi 0:098463de4c5d 73
group-onsemi 0:098463de4c5d 74 const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
group-onsemi 0:098463de4c5d 75 #ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */
group-onsemi 0:098463de4c5d 76 { SSL_RC4_128_SHA, SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_MD5 };
group-onsemi 0:098463de4c5d 77 #elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */
group-onsemi 0:098463de4c5d 78 { SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 };
group-onsemi 0:098463de4c5d 79 #else /* CONFIG_SSL_PROT_HIGH */ /* high security, low speed */
group-onsemi 0:098463de4c5d 80 { SSL_AES256_SHA, SSL_AES128_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 };
group-onsemi 0:098463de4c5d 81 #endif
group-onsemi 0:098463de4c5d 82 #endif /* CONFIG_SSL_SKELETON_MODE */
group-onsemi 0:098463de4c5d 83
group-onsemi 0:098463de4c5d 84 /**
group-onsemi 0:098463de4c5d 85 * The cipher map containing all the essentials for each cipher.
group-onsemi 0:098463de4c5d 86 */
group-onsemi 0:098463de4c5d 87 #ifdef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 88 static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
group-onsemi 0:098463de4c5d 89 {
group-onsemi 0:098463de4c5d 90 { /* RC4-SHA */
group-onsemi 0:098463de4c5d 91 SSL_RC4_128_SHA, /* RC4-SHA */
group-onsemi 0:098463de4c5d 92 16, /* key size */
group-onsemi 0:098463de4c5d 93 0, /* iv size */
group-onsemi 0:098463de4c5d 94 2*(SHA1_SIZE+16), /* key block size */
group-onsemi 0:098463de4c5d 95 0, /* no padding */
group-onsemi 0:098463de4c5d 96 SHA1_SIZE, /* digest size */
group-onsemi 0:098463de4c5d 97 hmac_sha1, /* hmac algorithm */
group-onsemi 0:098463de4c5d 98 (crypt_func)RC4_crypt, /* encrypt */
group-onsemi 0:098463de4c5d 99 (crypt_func)RC4_crypt /* decrypt */
group-onsemi 0:098463de4c5d 100 },
group-onsemi 0:098463de4c5d 101 };
group-onsemi 0:098463de4c5d 102 #else
group-onsemi 0:098463de4c5d 103 static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
group-onsemi 0:098463de4c5d 104 {
group-onsemi 0:098463de4c5d 105 { /* AES128-SHA */
group-onsemi 0:098463de4c5d 106 SSL_AES128_SHA, /* AES128-SHA */
group-onsemi 0:098463de4c5d 107 16, /* key size */
group-onsemi 0:098463de4c5d 108 16, /* iv size */
group-onsemi 0:098463de4c5d 109 2*(SHA1_SIZE+16+16), /* key block size */
group-onsemi 0:098463de4c5d 110 16, /* block padding size */
group-onsemi 0:098463de4c5d 111 SHA1_SIZE, /* digest size */
group-onsemi 0:098463de4c5d 112 hmac_sha1, /* hmac algorithm */
group-onsemi 0:098463de4c5d 113 (crypt_func)AES_cbc_encrypt, /* encrypt */
group-onsemi 0:098463de4c5d 114 (crypt_func)AES_cbc_decrypt /* decrypt */
group-onsemi 0:098463de4c5d 115 },
group-onsemi 0:098463de4c5d 116 { /* AES256-SHA */
group-onsemi 0:098463de4c5d 117 SSL_AES256_SHA, /* AES256-SHA */
group-onsemi 0:098463de4c5d 118 32, /* key size */
group-onsemi 0:098463de4c5d 119 16, /* iv size */
group-onsemi 0:098463de4c5d 120 2*(SHA1_SIZE+32+16), /* key block size */
group-onsemi 0:098463de4c5d 121 16, /* block padding size */
group-onsemi 0:098463de4c5d 122 SHA1_SIZE, /* digest size */
group-onsemi 0:098463de4c5d 123 hmac_sha1, /* hmac algorithm */
group-onsemi 0:098463de4c5d 124 (crypt_func)AES_cbc_encrypt, /* encrypt */
group-onsemi 0:098463de4c5d 125 (crypt_func)AES_cbc_decrypt /* decrypt */
group-onsemi 0:098463de4c5d 126 },
group-onsemi 0:098463de4c5d 127 { /* RC4-SHA */
group-onsemi 0:098463de4c5d 128 SSL_RC4_128_SHA, /* RC4-SHA */
group-onsemi 0:098463de4c5d 129 16, /* key size */
group-onsemi 0:098463de4c5d 130 0, /* iv size */
group-onsemi 0:098463de4c5d 131 2*(SHA1_SIZE+16), /* key block size */
group-onsemi 0:098463de4c5d 132 0, /* no padding */
group-onsemi 0:098463de4c5d 133 SHA1_SIZE, /* digest size */
group-onsemi 0:098463de4c5d 134 hmac_sha1, /* hmac algorithm */
group-onsemi 0:098463de4c5d 135 (crypt_func)RC4_crypt, /* encrypt */
group-onsemi 0:098463de4c5d 136 (crypt_func)RC4_crypt /* decrypt */
group-onsemi 0:098463de4c5d 137 },
group-onsemi 0:098463de4c5d 138 /*
group-onsemi 0:098463de4c5d 139 * This protocol is from SSLv2 days and is unlikely to be used - but was
group-onsemi 0:098463de4c5d 140 * useful for testing different possible digest algorithms.
group-onsemi 0:098463de4c5d 141 */
group-onsemi 0:098463de4c5d 142 { /* RC4-MD5 */
group-onsemi 0:098463de4c5d 143 SSL_RC4_128_MD5, /* RC4-MD5 */
group-onsemi 0:098463de4c5d 144 16, /* key size */
group-onsemi 0:098463de4c5d 145 0, /* iv size */
group-onsemi 0:098463de4c5d 146 2*(MD5_SIZE+16), /* key block size */
group-onsemi 0:098463de4c5d 147 0, /* no padding */
group-onsemi 0:098463de4c5d 148 MD5_SIZE, /* digest size */
group-onsemi 0:098463de4c5d 149 hmac_md5, /* hmac algorithm */
group-onsemi 0:098463de4c5d 150 (crypt_func)RC4_crypt, /* encrypt */
group-onsemi 0:098463de4c5d 151 (crypt_func)RC4_crypt /* decrypt */
group-onsemi 0:098463de4c5d 152 },
group-onsemi 0:098463de4c5d 153 };
group-onsemi 0:098463de4c5d 154 #endif
group-onsemi 0:098463de4c5d 155
group-onsemi 0:098463de4c5d 156 static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
group-onsemi 0:098463de4c5d 157 uint8_t *out, int olen);
group-onsemi 0:098463de4c5d 158 static const cipher_info_t *get_cipher_info(uint8_t cipher);
group-onsemi 0:098463de4c5d 159 static void increment_read_sequence(SSL *ssl);
group-onsemi 0:098463de4c5d 160 static void increment_write_sequence(SSL *ssl);
group-onsemi 0:098463de4c5d 161 static void add_hmac_digest(SSL *ssl, int snd, uint8_t *hmac_header,
group-onsemi 0:098463de4c5d 162 const uint8_t *buf, int buf_len, uint8_t *hmac_buf);
group-onsemi 0:098463de4c5d 163
group-onsemi 0:098463de4c5d 164 /* win32 VC6.0 doesn't have variadic macros */
group-onsemi 0:098463de4c5d 165 #if defined(WIN32) && !defined(CONFIG_SSL_FULL_MODE)
group-onsemi 0:098463de4c5d 166 void DISPLAY_BYTES(SSL *ssl, const char *format,
group-onsemi 0:098463de4c5d 167 const uint8_t *data, int size, ...) {}
group-onsemi 0:098463de4c5d 168 #endif
group-onsemi 0:098463de4c5d 169
group-onsemi 0:098463de4c5d 170 /**
group-onsemi 0:098463de4c5d 171 * Establish a new client/server context.
group-onsemi 0:098463de4c5d 172 */
group-onsemi 0:098463de4c5d 173 EXP_FUNC SSL_CTX *STDCALL ssl_ctx_new(SSL_CTX *ssl_ctx, uint32_t options, int num_sessions)
group-onsemi 0:098463de4c5d 174 {
group-onsemi 0:098463de4c5d 175 ssl_ctx->options = options;
group-onsemi 0:098463de4c5d 176 RNG_initialize();
group-onsemi 0:098463de4c5d 177
group-onsemi 0:098463de4c5d 178 if (load_key_certs(ssl_ctx) < 0)
group-onsemi 0:098463de4c5d 179 {
group-onsemi 0:098463de4c5d 180 printf("error loading key certs\r\n");
group-onsemi 0:098463de4c5d 181 //free(ssl_ctx); /* can't load our key/certificate pair, so die */
group-onsemi 0:098463de4c5d 182 return NULL;
group-onsemi 0:098463de4c5d 183 }
group-onsemi 0:098463de4c5d 184
group-onsemi 0:098463de4c5d 185 #ifndef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 186 ssl_ctx->num_sessions = num_sessions;
group-onsemi 0:098463de4c5d 187 #endif
group-onsemi 0:098463de4c5d 188
group-onsemi 0:098463de4c5d 189 SSL_CTX_MUTEX_INIT(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 190
group-onsemi 0:098463de4c5d 191 #ifndef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 192 if (num_sessions)
group-onsemi 0:098463de4c5d 193 {
group-onsemi 0:098463de4c5d 194 ssl_ctx->ssl_sessions = (SSL_SESSION **)
group-onsemi 0:098463de4c5d 195 calloc(1, num_sessions*sizeof(SSL_SESSION *));
group-onsemi 0:098463de4c5d 196 }
group-onsemi 0:098463de4c5d 197 #endif
group-onsemi 0:098463de4c5d 198
group-onsemi 0:098463de4c5d 199 return ssl_ctx;
group-onsemi 0:098463de4c5d 200 }
group-onsemi 0:098463de4c5d 201
group-onsemi 0:098463de4c5d 202 /*
group-onsemi 0:098463de4c5d 203 * Remove a client/server context.
group-onsemi 0:098463de4c5d 204 */
group-onsemi 0:098463de4c5d 205 EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx)
group-onsemi 0:098463de4c5d 206 {
group-onsemi 0:098463de4c5d 207 SSL *ssl;
group-onsemi 0:098463de4c5d 208 int i;
group-onsemi 0:098463de4c5d 209
group-onsemi 0:098463de4c5d 210 if (ssl_ctx == NULL)
group-onsemi 0:098463de4c5d 211 return;
group-onsemi 0:098463de4c5d 212
group-onsemi 0:098463de4c5d 213 ssl = ssl_ctx->head;
group-onsemi 0:098463de4c5d 214
group-onsemi 0:098463de4c5d 215 /* clear out all the ssl entries */
group-onsemi 0:098463de4c5d 216 while (ssl)
group-onsemi 0:098463de4c5d 217 {
group-onsemi 0:098463de4c5d 218 SSL *next = ssl->next;
group-onsemi 0:098463de4c5d 219 ssl_free(ssl);
group-onsemi 0:098463de4c5d 220 ssl = next;
group-onsemi 0:098463de4c5d 221 }
group-onsemi 0:098463de4c5d 222
group-onsemi 0:098463de4c5d 223 #ifndef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 224 /* clear out all the sessions */
group-onsemi 0:098463de4c5d 225 for (i = 0; i < ssl_ctx->num_sessions; i++)
group-onsemi 0:098463de4c5d 226 session_free(ssl_ctx->ssl_sessions, i);
group-onsemi 0:098463de4c5d 227
group-onsemi 0:098463de4c5d 228 free(ssl_ctx->ssl_sessions);
group-onsemi 0:098463de4c5d 229 #endif
group-onsemi 0:098463de4c5d 230
group-onsemi 0:098463de4c5d 231 i = 0;
group-onsemi 0:098463de4c5d 232 //while (i < CONFIG_SSL_MAX_CERTS && ssl_ctx->certs[i].buf)
group-onsemi 0:098463de4c5d 233 {
group-onsemi 0:098463de4c5d 234 //free(ssl_ctx->certs[i].buf);
group-onsemi 0:098463de4c5d 235 //ssl_ctx->certs[i++].buf = NULL;
group-onsemi 0:098463de4c5d 236 }
group-onsemi 0:098463de4c5d 237
group-onsemi 0:098463de4c5d 238 #ifdef CONFIG_SSL_CERT_VERIFICATION
group-onsemi 0:098463de4c5d 239 remove_ca_certs(ssl_ctx->ca_cert_ctx);
group-onsemi 0:098463de4c5d 240 #endif
group-onsemi 0:098463de4c5d 241 ssl_ctx->chain_length = 0;
group-onsemi 0:098463de4c5d 242 SSL_CTX_MUTEX_DESTROY(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 243 RSA_free(ssl_ctx->rsa_ctx);
group-onsemi 0:098463de4c5d 244 RNG_terminate();
group-onsemi 0:098463de4c5d 245 //free(ssl_ctx);
group-onsemi 0:098463de4c5d 246 }
group-onsemi 0:098463de4c5d 247
group-onsemi 0:098463de4c5d 248 /*
group-onsemi 0:098463de4c5d 249 * Free any used resources used by this connection.
group-onsemi 0:098463de4c5d 250 */
group-onsemi 0:098463de4c5d 251 EXP_FUNC void STDCALL ssl_free(SSL *ssl)
group-onsemi 0:098463de4c5d 252 {
group-onsemi 0:098463de4c5d 253 SSL_CTX *ssl_ctx;
group-onsemi 0:098463de4c5d 254
group-onsemi 0:098463de4c5d 255 if (ssl == NULL) /* just ignore null pointers */
group-onsemi 0:098463de4c5d 256 return;
group-onsemi 0:098463de4c5d 257
group-onsemi 0:098463de4c5d 258 /* only notify if we weren't notified first */
group-onsemi 0:098463de4c5d 259 /* spec says we must notify when we are dying */
group-onsemi 0:098463de4c5d 260 if (!IS_SET_SSL_FLAG(SSL_SENT_CLOSE_NOTIFY))
group-onsemi 0:098463de4c5d 261 send_alert(ssl, SSL_ALERT_CLOSE_NOTIFY);
group-onsemi 0:098463de4c5d 262
group-onsemi 0:098463de4c5d 263 ssl_ctx = ssl->ssl_ctx;
group-onsemi 0:098463de4c5d 264
group-onsemi 0:098463de4c5d 265 SSL_CTX_LOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 266
group-onsemi 0:098463de4c5d 267 /* adjust the server SSL list */
group-onsemi 0:098463de4c5d 268 if (ssl->prev)
group-onsemi 0:098463de4c5d 269 ssl->prev->next = ssl->next;
group-onsemi 0:098463de4c5d 270 else
group-onsemi 0:098463de4c5d 271 ssl_ctx->head = ssl->next;
group-onsemi 0:098463de4c5d 272
group-onsemi 0:098463de4c5d 273 if (ssl->next)
group-onsemi 0:098463de4c5d 274 ssl->next->prev = ssl->prev;
group-onsemi 0:098463de4c5d 275 else
group-onsemi 0:098463de4c5d 276 ssl_ctx->tail = ssl->prev;
group-onsemi 0:098463de4c5d 277
group-onsemi 0:098463de4c5d 278 SSL_CTX_UNLOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 279
group-onsemi 0:098463de4c5d 280 /* may already be free - but be sure */
group-onsemi 0:098463de4c5d 281 free(ssl->encrypt_ctx);
group-onsemi 0:098463de4c5d 282 free(ssl->decrypt_ctx);
group-onsemi 0:098463de4c5d 283 disposable_free(ssl);
group-onsemi 0:098463de4c5d 284
group-onsemi 0:098463de4c5d 285 #ifdef CONFIG_SSL_CERT_VERIFICATION
group-onsemi 0:098463de4c5d 286 x509_free(ssl->x509_ctx);
group-onsemi 0:098463de4c5d 287 #endif
group-onsemi 0:098463de4c5d 288 //free(ssl->ssl_ctx);
group-onsemi 0:098463de4c5d 289 //free(ssl);
group-onsemi 0:098463de4c5d 290 }
group-onsemi 0:098463de4c5d 291
group-onsemi 0:098463de4c5d 292 /*
group-onsemi 0:098463de4c5d 293 * Write application data to the client
group-onsemi 0:098463de4c5d 294 */
group-onsemi 0:098463de4c5d 295 EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len)
group-onsemi 0:098463de4c5d 296 {
group-onsemi 0:098463de4c5d 297 int n = out_len, nw, i, tot = 0;
group-onsemi 0:098463de4c5d 298
group-onsemi 0:098463de4c5d 299 /* maximum size of a TLS packet is around 16kB, so fragment */
group-onsemi 0:098463de4c5d 300 do
group-onsemi 0:098463de4c5d 301 {
group-onsemi 0:098463de4c5d 302 nw = n;
group-onsemi 0:098463de4c5d 303
group-onsemi 0:098463de4c5d 304 if (nw > RT_MAX_PLAIN_LENGTH) /* fragment if necessary */
group-onsemi 0:098463de4c5d 305 nw = RT_MAX_PLAIN_LENGTH;
group-onsemi 0:098463de4c5d 306
group-onsemi 0:098463de4c5d 307 if ((i = send_packet(ssl, PT_APP_PROTOCOL_DATA,
group-onsemi 0:098463de4c5d 308 &out_data[tot], nw)) <= 0)
group-onsemi 0:098463de4c5d 309 {
group-onsemi 0:098463de4c5d 310 out_len = i; /* an error */
group-onsemi 0:098463de4c5d 311 break;
group-onsemi 0:098463de4c5d 312 }
group-onsemi 0:098463de4c5d 313
group-onsemi 0:098463de4c5d 314 tot += i;
group-onsemi 0:098463de4c5d 315 n -= i;
group-onsemi 0:098463de4c5d 316 } while (n > 0);
group-onsemi 0:098463de4c5d 317
group-onsemi 0:098463de4c5d 318 return out_len;
group-onsemi 0:098463de4c5d 319 }
group-onsemi 0:098463de4c5d 320
group-onsemi 0:098463de4c5d 321 /**
group-onsemi 0:098463de4c5d 322 * Add a certificate to the certificate chain.
group-onsemi 0:098463de4c5d 323 */
group-onsemi 0:098463de4c5d 324 int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
group-onsemi 0:098463de4c5d 325 {
group-onsemi 0:098463de4c5d 326 int ret = SSL_ERROR_NO_CERT_DEFINED, i = 0;
group-onsemi 0:098463de4c5d 327 SSL_CERT *ssl_cert;
group-onsemi 0:098463de4c5d 328 X509_CTX *cert = NULL;
group-onsemi 0:098463de4c5d 329 int offset;
group-onsemi 0:098463de4c5d 330
group-onsemi 0:098463de4c5d 331 while (ssl_ctx->certs[i].buf && i < CONFIG_SSL_MAX_CERTS)
group-onsemi 0:098463de4c5d 332 i++;
group-onsemi 0:098463de4c5d 333
group-onsemi 0:098463de4c5d 334 if (i == CONFIG_SSL_MAX_CERTS) /* too many certs */
group-onsemi 0:098463de4c5d 335 {
group-onsemi 0:098463de4c5d 336 #ifdef CONFIG_SSL_FULL_MODE
group-onsemi 0:098463de4c5d 337 printf("Error: maximum number of certs added (%d) - change of "
group-onsemi 0:098463de4c5d 338 "compile-time configuration required\n",
group-onsemi 0:098463de4c5d 339 CONFIG_SSL_MAX_CERTS);
group-onsemi 0:098463de4c5d 340 #endif
group-onsemi 0:098463de4c5d 341 goto error;
group-onsemi 0:098463de4c5d 342 }
group-onsemi 0:098463de4c5d 343
group-onsemi 0:098463de4c5d 344 if ((ret = x509_new(buf, &offset, &cert)))
group-onsemi 0:098463de4c5d 345 goto error;
group-onsemi 0:098463de4c5d 346
group-onsemi 0:098463de4c5d 347 #if defined (CONFIG_SSL_FULL_MODE)
group-onsemi 0:098463de4c5d 348 if (ssl_ctx->options & SSL_DISPLAY_CERTS)
group-onsemi 0:098463de4c5d 349 x509_print(cert, NULL);
group-onsemi 0:098463de4c5d 350 #endif
group-onsemi 0:098463de4c5d 351
group-onsemi 0:098463de4c5d 352 ssl_cert = &ssl_ctx->certs[i];
group-onsemi 0:098463de4c5d 353 ssl_cert->size = len;
group-onsemi 0:098463de4c5d 354 ssl_cert->buf = buf;
group-onsemi 0:098463de4c5d 355 ssl_ctx->chain_length++;
group-onsemi 0:098463de4c5d 356 len -= offset;
group-onsemi 0:098463de4c5d 357 ret = SSL_OK; /* ok so far */
group-onsemi 0:098463de4c5d 358
group-onsemi 0:098463de4c5d 359 /* recurse? */
group-onsemi 0:098463de4c5d 360 if (len > 0)
group-onsemi 0:098463de4c5d 361 {
group-onsemi 0:098463de4c5d 362 ret = add_cert(ssl_ctx, &buf[offset], len);
group-onsemi 0:098463de4c5d 363 }
group-onsemi 0:098463de4c5d 364
group-onsemi 0:098463de4c5d 365 error:
group-onsemi 0:098463de4c5d 366 x509_free(cert); /* don't need anymore */
group-onsemi 0:098463de4c5d 367 return ret;
group-onsemi 0:098463de4c5d 368 }
group-onsemi 0:098463de4c5d 369
group-onsemi 0:098463de4c5d 370 #ifdef CONFIG_SSL_CERT_VERIFICATION
group-onsemi 0:098463de4c5d 371 /**
group-onsemi 0:098463de4c5d 372 * Add a certificate authority.
group-onsemi 0:098463de4c5d 373 */
group-onsemi 0:098463de4c5d 374 int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
group-onsemi 0:098463de4c5d 375 {
group-onsemi 0:098463de4c5d 376 int ret = SSL_OK; /* ignore errors for now */
group-onsemi 0:098463de4c5d 377 int i = 0;
group-onsemi 0:098463de4c5d 378 CA_CERT_CTX *ca_cert_ctx;
group-onsemi 0:098463de4c5d 379
group-onsemi 0:098463de4c5d 380 if (ssl_ctx->ca_cert_ctx == NULL)
group-onsemi 0:098463de4c5d 381 ssl_ctx->ca_cert_ctx = (CA_CERT_CTX *)calloc(1, sizeof(CA_CERT_CTX));
group-onsemi 0:098463de4c5d 382
group-onsemi 0:098463de4c5d 383 ca_cert_ctx = ssl_ctx->ca_cert_ctx;
group-onsemi 0:098463de4c5d 384
group-onsemi 0:098463de4c5d 385 while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
group-onsemi 0:098463de4c5d 386 i++;
group-onsemi 0:098463de4c5d 387
group-onsemi 0:098463de4c5d 388 while (len > 0)
group-onsemi 0:098463de4c5d 389 {
group-onsemi 0:098463de4c5d 390 int offset;
group-onsemi 0:098463de4c5d 391 if (i >= CONFIG_X509_MAX_CA_CERTS)
group-onsemi 0:098463de4c5d 392 {
group-onsemi 0:098463de4c5d 393 #ifdef CONFIG_SSL_FULL_MODE
group-onsemi 0:098463de4c5d 394 printf("Error: maximum number of CA certs added (%d) - change of "
group-onsemi 0:098463de4c5d 395 "compile-time configuration required\n",
group-onsemi 0:098463de4c5d 396 CONFIG_X509_MAX_CA_CERTS);
group-onsemi 0:098463de4c5d 397 #endif
group-onsemi 0:098463de4c5d 398 break;
group-onsemi 0:098463de4c5d 399 }
group-onsemi 0:098463de4c5d 400
group-onsemi 0:098463de4c5d 401
group-onsemi 0:098463de4c5d 402 /* ignore the return code */
group-onsemi 0:098463de4c5d 403 if (x509_new(buf, &offset, &ca_cert_ctx->cert[i]) == X509_OK)
group-onsemi 0:098463de4c5d 404 {
group-onsemi 0:098463de4c5d 405 #if defined (CONFIG_SSL_FULL_MODE)
group-onsemi 0:098463de4c5d 406 if (ssl_ctx->options & SSL_DISPLAY_CERTS)
group-onsemi 0:098463de4c5d 407 x509_print(ca_cert_ctx->cert[i], NULL);
group-onsemi 0:098463de4c5d 408 #endif
group-onsemi 0:098463de4c5d 409 }
group-onsemi 0:098463de4c5d 410
group-onsemi 0:098463de4c5d 411 i++;
group-onsemi 0:098463de4c5d 412 len -= offset;
group-onsemi 0:098463de4c5d 413 }
group-onsemi 0:098463de4c5d 414
group-onsemi 0:098463de4c5d 415 return ret;
group-onsemi 0:098463de4c5d 416 }
group-onsemi 0:098463de4c5d 417
group-onsemi 0:098463de4c5d 418 /*
group-onsemi 0:098463de4c5d 419 * Retrieve an X.509 distinguished name component
group-onsemi 0:098463de4c5d 420 */
group-onsemi 0:098463de4c5d 421 EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
group-onsemi 0:098463de4c5d 422 {
group-onsemi 0:098463de4c5d 423 if (ssl->x509_ctx == NULL)
group-onsemi 0:098463de4c5d 424 return NULL;
group-onsemi 0:098463de4c5d 425
group-onsemi 0:098463de4c5d 426 switch (component)
group-onsemi 0:098463de4c5d 427 {
group-onsemi 0:098463de4c5d 428 case SSL_X509_CERT_COMMON_NAME:
group-onsemi 0:098463de4c5d 429 return ssl->x509_ctx->cert_dn[X509_COMMON_NAME];
group-onsemi 0:098463de4c5d 430
group-onsemi 0:098463de4c5d 431 case SSL_X509_CERT_ORGANIZATION:
group-onsemi 0:098463de4c5d 432 return ssl->x509_ctx->cert_dn[X509_ORGANIZATION];
group-onsemi 0:098463de4c5d 433
group-onsemi 0:098463de4c5d 434 case SSL_X509_CERT_ORGANIZATIONAL_NAME:
group-onsemi 0:098463de4c5d 435 return ssl->x509_ctx->cert_dn[X509_ORGANIZATIONAL_UNIT];
group-onsemi 0:098463de4c5d 436
group-onsemi 0:098463de4c5d 437 case SSL_X509_CA_CERT_COMMON_NAME:
group-onsemi 0:098463de4c5d 438 return ssl->x509_ctx->ca_cert_dn[X509_COMMON_NAME];
group-onsemi 0:098463de4c5d 439
group-onsemi 0:098463de4c5d 440 case SSL_X509_CA_CERT_ORGANIZATION:
group-onsemi 0:098463de4c5d 441 return ssl->x509_ctx->ca_cert_dn[X509_ORGANIZATION];
group-onsemi 0:098463de4c5d 442
group-onsemi 0:098463de4c5d 443 case SSL_X509_CA_CERT_ORGANIZATIONAL_NAME:
group-onsemi 0:098463de4c5d 444 return ssl->x509_ctx->ca_cert_dn[X509_ORGANIZATIONAL_UNIT];
group-onsemi 0:098463de4c5d 445
group-onsemi 0:098463de4c5d 446 default:
group-onsemi 0:098463de4c5d 447 return NULL;
group-onsemi 0:098463de4c5d 448 }
group-onsemi 0:098463de4c5d 449 }
group-onsemi 0:098463de4c5d 450
group-onsemi 0:098463de4c5d 451 /*
group-onsemi 0:098463de4c5d 452 * Retrieve a "Subject Alternative Name" from a v3 certificate
group-onsemi 0:098463de4c5d 453 */
group-onsemi 0:098463de4c5d 454 EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl,
group-onsemi 0:098463de4c5d 455 int dnsindex)
group-onsemi 0:098463de4c5d 456 {
group-onsemi 0:098463de4c5d 457 int i;
group-onsemi 0:098463de4c5d 458
group-onsemi 0:098463de4c5d 459 if (ssl->x509_ctx == NULL || ssl->x509_ctx->subject_alt_dnsnames == NULL)
group-onsemi 0:098463de4c5d 460 return NULL;
group-onsemi 0:098463de4c5d 461
group-onsemi 0:098463de4c5d 462 for (i = 0; i < dnsindex; ++i)
group-onsemi 0:098463de4c5d 463 {
group-onsemi 0:098463de4c5d 464 if (ssl->x509_ctx->subject_alt_dnsnames[i] == NULL)
group-onsemi 0:098463de4c5d 465 return NULL;
group-onsemi 0:098463de4c5d 466 }
group-onsemi 0:098463de4c5d 467
group-onsemi 0:098463de4c5d 468 return ssl->x509_ctx->subject_alt_dnsnames[dnsindex];
group-onsemi 0:098463de4c5d 469 }
group-onsemi 0:098463de4c5d 470
group-onsemi 0:098463de4c5d 471 #endif /* CONFIG_SSL_CERT_VERIFICATION */
group-onsemi 0:098463de4c5d 472
group-onsemi 0:098463de4c5d 473 /*
group-onsemi 0:098463de4c5d 474 * Find an ssl object based on the client's file descriptor.
group-onsemi 0:098463de4c5d 475 */
group-onsemi 0:098463de4c5d 476 EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, int client_fd)
group-onsemi 0:098463de4c5d 477 {
group-onsemi 0:098463de4c5d 478 SSL *ssl;
group-onsemi 0:098463de4c5d 479
group-onsemi 0:098463de4c5d 480 SSL_CTX_LOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 481 ssl = ssl_ctx->head;
group-onsemi 0:098463de4c5d 482
group-onsemi 0:098463de4c5d 483 /* search through all the ssl entries */
group-onsemi 0:098463de4c5d 484 while (ssl)
group-onsemi 0:098463de4c5d 485 {
group-onsemi 0:098463de4c5d 486 if (ssl->client_fd == client_fd)
group-onsemi 0:098463de4c5d 487 {
group-onsemi 0:098463de4c5d 488 SSL_CTX_UNLOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 489 return ssl;
group-onsemi 0:098463de4c5d 490 }
group-onsemi 0:098463de4c5d 491
group-onsemi 0:098463de4c5d 492 ssl = ssl->next;
group-onsemi 0:098463de4c5d 493 }
group-onsemi 0:098463de4c5d 494
group-onsemi 0:098463de4c5d 495 SSL_CTX_UNLOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 496 return NULL;
group-onsemi 0:098463de4c5d 497 }
group-onsemi 0:098463de4c5d 498
group-onsemi 0:098463de4c5d 499 /*
group-onsemi 0:098463de4c5d 500 * Force the client to perform its handshake again.
group-onsemi 0:098463de4c5d 501 */
group-onsemi 0:098463de4c5d 502 EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl)
group-onsemi 0:098463de4c5d 503 {
group-onsemi 0:098463de4c5d 504 int ret = SSL_OK;
group-onsemi 0:098463de4c5d 505
group-onsemi 0:098463de4c5d 506 disposable_new(ssl);
group-onsemi 0:098463de4c5d 507 #ifdef CONFIG_SSL_ENABLE_CLIENT
group-onsemi 0:098463de4c5d 508 if (IS_SET_SSL_FLAG(SSL_IS_CLIENT))
group-onsemi 0:098463de4c5d 509 {
group-onsemi 0:098463de4c5d 510 ret = do_client_connect(ssl);
group-onsemi 0:098463de4c5d 511 }
group-onsemi 0:098463de4c5d 512 else
group-onsemi 0:098463de4c5d 513 #endif
group-onsemi 0:098463de4c5d 514 {
group-onsemi 0:098463de4c5d 515 send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
group-onsemi 0:098463de4c5d 516 g_hello_request, sizeof(g_hello_request));
group-onsemi 0:098463de4c5d 517 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 518 }
group-onsemi 0:098463de4c5d 519
group-onsemi 0:098463de4c5d 520 return ret;
group-onsemi 0:098463de4c5d 521 }
group-onsemi 0:098463de4c5d 522
group-onsemi 0:098463de4c5d 523 /**
group-onsemi 0:098463de4c5d 524 * @brief Get what we need for key info.
group-onsemi 0:098463de4c5d 525 * @param cipher [in] The cipher information we are after
group-onsemi 0:098463de4c5d 526 * @param key_size [out] The key size for the cipher
group-onsemi 0:098463de4c5d 527 * @param iv_size [out] The iv size for the cipher
group-onsemi 0:098463de4c5d 528 * @return The amount of key information we need.
group-onsemi 0:098463de4c5d 529 */
group-onsemi 0:098463de4c5d 530 static const cipher_info_t *get_cipher_info(uint8_t cipher)
group-onsemi 0:098463de4c5d 531 {
group-onsemi 0:098463de4c5d 532 int i;
group-onsemi 0:098463de4c5d 533
group-onsemi 0:098463de4c5d 534 for (i = 0; i < NUM_PROTOCOLS; i++)
group-onsemi 0:098463de4c5d 535 {
group-onsemi 0:098463de4c5d 536 if (cipher_info[i].cipher == cipher)
group-onsemi 0:098463de4c5d 537 {
group-onsemi 0:098463de4c5d 538 return &cipher_info[i];
group-onsemi 0:098463de4c5d 539 }
group-onsemi 0:098463de4c5d 540 }
group-onsemi 0:098463de4c5d 541
group-onsemi 0:098463de4c5d 542 return NULL; /* error */
group-onsemi 0:098463de4c5d 543 }
group-onsemi 0:098463de4c5d 544
group-onsemi 0:098463de4c5d 545 /*
group-onsemi 0:098463de4c5d 546 * Get a new ssl context for a new connection.
group-onsemi 0:098463de4c5d 547 */
group-onsemi 0:098463de4c5d 548 SSL *ssl_new(SSL *ssl, int client_fd)
group-onsemi 0:098463de4c5d 549 {
group-onsemi 0:098463de4c5d 550 SSL_CTX* ssl_ctx = ssl->ssl_ctx;
group-onsemi 0:098463de4c5d 551 ssl->need_bytes = SSL_RECORD_SIZE; /* need a record */
group-onsemi 0:098463de4c5d 552 ssl->client_fd = 0;
group-onsemi 0:098463de4c5d 553 ssl->flag = SSL_NEED_RECORD;
group-onsemi 0:098463de4c5d 554 ssl->bm_data = ssl->bm_all_data + BM_RECORD_OFFSET;
group-onsemi 0:098463de4c5d 555 ssl->bm_read_index = 0;
group-onsemi 0:098463de4c5d 556 ssl->hs_status = SSL_NOT_OK; /* not connected */
group-onsemi 0:098463de4c5d 557 #ifdef CONFIG_ENABLE_VERIFICATION
group-onsemi 0:098463de4c5d 558 ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx;
group-onsemi 0:098463de4c5d 559 #endif
group-onsemi 0:098463de4c5d 560 disposable_new(ssl);
group-onsemi 0:098463de4c5d 561
group-onsemi 0:098463de4c5d 562 /* a bit hacky but saves a few bytes of memory */
group-onsemi 0:098463de4c5d 563 ssl->flag |= ssl_ctx->options;
group-onsemi 0:098463de4c5d 564 SSL_CTX_LOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 565
group-onsemi 0:098463de4c5d 566 if (ssl_ctx->head == NULL)
group-onsemi 0:098463de4c5d 567 {
group-onsemi 0:098463de4c5d 568 ssl_ctx->head = ssl;
group-onsemi 0:098463de4c5d 569 ssl_ctx->tail = ssl;
group-onsemi 0:098463de4c5d 570 }
group-onsemi 0:098463de4c5d 571 else
group-onsemi 0:098463de4c5d 572 {
group-onsemi 0:098463de4c5d 573 ssl->prev = ssl_ctx->tail;
group-onsemi 0:098463de4c5d 574 ssl_ctx->tail->next = ssl;
group-onsemi 0:098463de4c5d 575 ssl_ctx->tail = ssl;
group-onsemi 0:098463de4c5d 576 }
group-onsemi 0:098463de4c5d 577 ssl->encrypt_ctx = NULL;
group-onsemi 0:098463de4c5d 578 ssl->decrypt_ctx = NULL;
group-onsemi 0:098463de4c5d 579
group-onsemi 0:098463de4c5d 580 SSL_CTX_UNLOCK(ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 581 return ssl;
group-onsemi 0:098463de4c5d 582 }
group-onsemi 0:098463de4c5d 583
group-onsemi 0:098463de4c5d 584 /*
group-onsemi 0:098463de4c5d 585 * Add a private key to a context.
group-onsemi 0:098463de4c5d 586 */
group-onsemi 0:098463de4c5d 587 int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj)
group-onsemi 0:098463de4c5d 588 {
group-onsemi 0:098463de4c5d 589 int ret = SSL_OK;
group-onsemi 0:098463de4c5d 590
group-onsemi 0:098463de4c5d 591 /* get the private key details */
group-onsemi 0:098463de4c5d 592 if (asn1_get_private_key(ssl_obj->buf, ssl_obj->len, &ssl_ctx->rsa_ctx))
group-onsemi 0:098463de4c5d 593 {
group-onsemi 0:098463de4c5d 594 ret = SSL_ERROR_INVALID_KEY;
group-onsemi 0:098463de4c5d 595 goto error;
group-onsemi 0:098463de4c5d 596 }
group-onsemi 0:098463de4c5d 597
group-onsemi 0:098463de4c5d 598 error:
group-onsemi 0:098463de4c5d 599 return ret;
group-onsemi 0:098463de4c5d 600 }
group-onsemi 0:098463de4c5d 601
group-onsemi 0:098463de4c5d 602 /**
group-onsemi 0:098463de4c5d 603 * Increment the read sequence number (as a 64 bit endian indepenent #)
group-onsemi 0:098463de4c5d 604 */
group-onsemi 0:098463de4c5d 605 static void increment_read_sequence(SSL *ssl)
group-onsemi 0:098463de4c5d 606 {
group-onsemi 0:098463de4c5d 607 int i;
group-onsemi 0:098463de4c5d 608
group-onsemi 0:098463de4c5d 609 for (i = 7; i >= 0; i--)
group-onsemi 0:098463de4c5d 610 {
group-onsemi 0:098463de4c5d 611 if (++ssl->read_sequence[i])
group-onsemi 0:098463de4c5d 612 break;
group-onsemi 0:098463de4c5d 613 }
group-onsemi 0:098463de4c5d 614 }
group-onsemi 0:098463de4c5d 615
group-onsemi 0:098463de4c5d 616 /**
group-onsemi 0:098463de4c5d 617 * Increment the read sequence number (as a 64 bit endian indepenent #)
group-onsemi 0:098463de4c5d 618 */
group-onsemi 0:098463de4c5d 619 static void increment_write_sequence(SSL *ssl)
group-onsemi 0:098463de4c5d 620 {
group-onsemi 0:098463de4c5d 621 int i;
group-onsemi 0:098463de4c5d 622
group-onsemi 0:098463de4c5d 623 for (i = 7; i >= 0; i--)
group-onsemi 0:098463de4c5d 624 {
group-onsemi 0:098463de4c5d 625 if (++ssl->write_sequence[i])
group-onsemi 0:098463de4c5d 626 break;
group-onsemi 0:098463de4c5d 627 }
group-onsemi 0:098463de4c5d 628 }
group-onsemi 0:098463de4c5d 629
group-onsemi 0:098463de4c5d 630 /**
group-onsemi 0:098463de4c5d 631 * Work out the HMAC digest in a packet.
group-onsemi 0:098463de4c5d 632 */
group-onsemi 0:098463de4c5d 633 static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
group-onsemi 0:098463de4c5d 634 const uint8_t *buf, int buf_len, uint8_t *hmac_buf)
group-onsemi 0:098463de4c5d 635 {
group-onsemi 0:098463de4c5d 636 int hmac_len = buf_len + 8 + SSL_RECORD_SIZE;
group-onsemi 0:098463de4c5d 637 uint8_t *t_buf = (uint8_t *)alloca(hmac_len+10);
group-onsemi 0:098463de4c5d 638
group-onsemi 0:098463de4c5d 639 memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ?
group-onsemi 0:098463de4c5d 640 ssl->write_sequence : ssl->read_sequence, 8);
group-onsemi 0:098463de4c5d 641 memcpy(&t_buf[8], hmac_header, SSL_RECORD_SIZE);
group-onsemi 0:098463de4c5d 642 memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len);
group-onsemi 0:098463de4c5d 643
group-onsemi 0:098463de4c5d 644 ssl->cipher_info->hmac(t_buf, hmac_len,
group-onsemi 0:098463de4c5d 645 (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ?
group-onsemi 0:098463de4c5d 646 ssl->server_mac : ssl->client_mac,
group-onsemi 0:098463de4c5d 647 ssl->cipher_info->digest_size, hmac_buf);
group-onsemi 0:098463de4c5d 648
group-onsemi 0:098463de4c5d 649 #if 0
group-onsemi 0:098463de4c5d 650 print_blob("record", hmac_header, SSL_RECORD_SIZE);
group-onsemi 0:098463de4c5d 651 print_blob("buf", buf, buf_len);
group-onsemi 0:098463de4c5d 652 if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE)
group-onsemi 0:098463de4c5d 653 {
group-onsemi 0:098463de4c5d 654 print_blob("write seq", ssl->write_sequence, 8);
group-onsemi 0:098463de4c5d 655 }
group-onsemi 0:098463de4c5d 656 else
group-onsemi 0:098463de4c5d 657 {
group-onsemi 0:098463de4c5d 658 print_blob("read seq", ssl->read_sequence, 8);
group-onsemi 0:098463de4c5d 659 }
group-onsemi 0:098463de4c5d 660
group-onsemi 0:098463de4c5d 661 if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ)
group-onsemi 0:098463de4c5d 662 {
group-onsemi 0:098463de4c5d 663 print_blob("server mac",
group-onsemi 0:098463de4c5d 664 ssl->server_mac, ssl->cipher_info->digest_size);
group-onsemi 0:098463de4c5d 665 }
group-onsemi 0:098463de4c5d 666 else
group-onsemi 0:098463de4c5d 667 {
group-onsemi 0:098463de4c5d 668 print_blob("client mac",
group-onsemi 0:098463de4c5d 669 ssl->client_mac, ssl->cipher_info->digest_size);
group-onsemi 0:098463de4c5d 670 }
group-onsemi 0:098463de4c5d 671 print_blob("hmac", hmac_buf, SHA1_SIZE);
group-onsemi 0:098463de4c5d 672 #endif
group-onsemi 0:098463de4c5d 673 }
group-onsemi 0:098463de4c5d 674
group-onsemi 0:098463de4c5d 675 /**
group-onsemi 0:098463de4c5d 676 * Verify that the digest of a packet is correct.
group-onsemi 0:098463de4c5d 677 */
group-onsemi 0:098463de4c5d 678 static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
group-onsemi 0:098463de4c5d 679 {
group-onsemi 0:098463de4c5d 680 uint8_t hmac_buf[SHA1_SIZE];
group-onsemi 0:098463de4c5d 681 int hmac_offset;
group-onsemi 0:098463de4c5d 682
group-onsemi 0:098463de4c5d 683 if (ssl->cipher_info->padding_size)
group-onsemi 0:098463de4c5d 684 {
group-onsemi 0:098463de4c5d 685 int last_blk_size = buf[read_len-1], i;
group-onsemi 0:098463de4c5d 686 hmac_offset = read_len-last_blk_size-ssl->cipher_info->digest_size-1;
group-onsemi 0:098463de4c5d 687
group-onsemi 0:098463de4c5d 688 /* guard against a timing attack - make sure we do the digest */
group-onsemi 0:098463de4c5d 689 if (hmac_offset < 0)
group-onsemi 0:098463de4c5d 690 {
group-onsemi 0:098463de4c5d 691 hmac_offset = 0;
group-onsemi 0:098463de4c5d 692 }
group-onsemi 0:098463de4c5d 693 else
group-onsemi 0:098463de4c5d 694 {
group-onsemi 0:098463de4c5d 695 /* already looked at last byte */
group-onsemi 0:098463de4c5d 696 for (i = 1; i < last_blk_size; i++)
group-onsemi 0:098463de4c5d 697 {
group-onsemi 0:098463de4c5d 698 if (buf[read_len-i] != last_blk_size)
group-onsemi 0:098463de4c5d 699 {
group-onsemi 0:098463de4c5d 700 hmac_offset = 0;
group-onsemi 0:098463de4c5d 701 break;
group-onsemi 0:098463de4c5d 702 }
group-onsemi 0:098463de4c5d 703 }
group-onsemi 0:098463de4c5d 704 }
group-onsemi 0:098463de4c5d 705 }
group-onsemi 0:098463de4c5d 706 else /* stream cipher */
group-onsemi 0:098463de4c5d 707 {
group-onsemi 0:098463de4c5d 708 hmac_offset = read_len - ssl->cipher_info->digest_size;
group-onsemi 0:098463de4c5d 709
group-onsemi 0:098463de4c5d 710 if (hmac_offset < 0)
group-onsemi 0:098463de4c5d 711 {
group-onsemi 0:098463de4c5d 712 hmac_offset = 0;
group-onsemi 0:098463de4c5d 713 }
group-onsemi 0:098463de4c5d 714 }
group-onsemi 0:098463de4c5d 715
group-onsemi 0:098463de4c5d 716 /* sanity check the offset */
group-onsemi 0:098463de4c5d 717 ssl->hmac_header[3] = hmac_offset >> 8; /* insert size */
group-onsemi 0:098463de4c5d 718 ssl->hmac_header[4] = hmac_offset & 0xff;
group-onsemi 0:098463de4c5d 719 add_hmac_digest(ssl, mode, ssl->hmac_header, buf, hmac_offset, hmac_buf);
group-onsemi 0:098463de4c5d 720
group-onsemi 0:098463de4c5d 721 if (memcmp(hmac_buf, &buf[hmac_offset], ssl->cipher_info->digest_size))
group-onsemi 0:098463de4c5d 722 {
group-onsemi 0:098463de4c5d 723 return SSL_ERROR_INVALID_HMAC;
group-onsemi 0:098463de4c5d 724 }
group-onsemi 0:098463de4c5d 725
group-onsemi 0:098463de4c5d 726 return hmac_offset;
group-onsemi 0:098463de4c5d 727 }
group-onsemi 0:098463de4c5d 728
group-onsemi 0:098463de4c5d 729 /**
group-onsemi 0:098463de4c5d 730 * Add a packet to the end of our sent and received packets, so that we may use
group-onsemi 0:098463de4c5d 731 * it to calculate the hash at the end.
group-onsemi 0:098463de4c5d 732 */
group-onsemi 0:098463de4c5d 733 void add_packet(SSL *ssl, const uint8_t *pkt, int len)
group-onsemi 0:098463de4c5d 734 {
group-onsemi 0:098463de4c5d 735 MD5_Update(&ssl->dc->md5_ctx, pkt, len);
group-onsemi 0:098463de4c5d 736 SHA1_Update(&ssl->dc->sha1_ctx, pkt, len);
group-onsemi 0:098463de4c5d 737 }
group-onsemi 0:098463de4c5d 738
group-onsemi 0:098463de4c5d 739 /**
group-onsemi 0:098463de4c5d 740 * Work out the MD5 PRF.
group-onsemi 0:098463de4c5d 741 */
group-onsemi 0:098463de4c5d 742 static void p_hash_md5(const uint8_t *sec, int sec_len,
group-onsemi 0:098463de4c5d 743 uint8_t *seed, int seed_len, uint8_t *out, int olen)
group-onsemi 0:098463de4c5d 744 {
group-onsemi 0:098463de4c5d 745 uint8_t a1[128];
group-onsemi 0:098463de4c5d 746
group-onsemi 0:098463de4c5d 747 /* A(1) */
group-onsemi 0:098463de4c5d 748 hmac_md5(seed, seed_len, sec, sec_len, a1);
group-onsemi 0:098463de4c5d 749 memcpy(&a1[MD5_SIZE], seed, seed_len);
group-onsemi 0:098463de4c5d 750 hmac_md5(a1, MD5_SIZE+seed_len, sec, sec_len, out);
group-onsemi 0:098463de4c5d 751
group-onsemi 0:098463de4c5d 752 while (olen > MD5_SIZE)
group-onsemi 0:098463de4c5d 753 {
group-onsemi 0:098463de4c5d 754 uint8_t a2[MD5_SIZE];
group-onsemi 0:098463de4c5d 755 out += MD5_SIZE;
group-onsemi 0:098463de4c5d 756 olen -= MD5_SIZE;
group-onsemi 0:098463de4c5d 757
group-onsemi 0:098463de4c5d 758 /* A(N) */
group-onsemi 0:098463de4c5d 759 hmac_md5(a1, MD5_SIZE, sec, sec_len, a2);
group-onsemi 0:098463de4c5d 760 memcpy(a1, a2, MD5_SIZE);
group-onsemi 0:098463de4c5d 761
group-onsemi 0:098463de4c5d 762 /* work out the actual hash */
group-onsemi 0:098463de4c5d 763 hmac_md5(a1, MD5_SIZE+seed_len, sec, sec_len, out);
group-onsemi 0:098463de4c5d 764 }
group-onsemi 0:098463de4c5d 765 }
group-onsemi 0:098463de4c5d 766
group-onsemi 0:098463de4c5d 767 /**
group-onsemi 0:098463de4c5d 768 * Work out the SHA1 PRF.
group-onsemi 0:098463de4c5d 769 */
group-onsemi 0:098463de4c5d 770 static void p_hash_sha1(const uint8_t *sec, int sec_len,
group-onsemi 0:098463de4c5d 771 uint8_t *seed, int seed_len, uint8_t *out, int olen)
group-onsemi 0:098463de4c5d 772 {
group-onsemi 0:098463de4c5d 773 uint8_t a1[128];
group-onsemi 0:098463de4c5d 774
group-onsemi 0:098463de4c5d 775 /* A(1) */
group-onsemi 0:098463de4c5d 776 hmac_sha1(seed, seed_len, sec, sec_len, a1);
group-onsemi 0:098463de4c5d 777 memcpy(&a1[SHA1_SIZE], seed, seed_len);
group-onsemi 0:098463de4c5d 778 hmac_sha1(a1, SHA1_SIZE+seed_len, sec, sec_len, out);
group-onsemi 0:098463de4c5d 779
group-onsemi 0:098463de4c5d 780 while (olen > SHA1_SIZE)
group-onsemi 0:098463de4c5d 781 {
group-onsemi 0:098463de4c5d 782 uint8_t a2[SHA1_SIZE];
group-onsemi 0:098463de4c5d 783 out += SHA1_SIZE;
group-onsemi 0:098463de4c5d 784 olen -= SHA1_SIZE;
group-onsemi 0:098463de4c5d 785
group-onsemi 0:098463de4c5d 786 /* A(N) */
group-onsemi 0:098463de4c5d 787 hmac_sha1(a1, SHA1_SIZE, sec, sec_len, a2);
group-onsemi 0:098463de4c5d 788 memcpy(a1, a2, SHA1_SIZE);
group-onsemi 0:098463de4c5d 789
group-onsemi 0:098463de4c5d 790 /* work out the actual hash */
group-onsemi 0:098463de4c5d 791 hmac_sha1(a1, SHA1_SIZE+seed_len, sec, sec_len, out);
group-onsemi 0:098463de4c5d 792 }
group-onsemi 0:098463de4c5d 793 }
group-onsemi 0:098463de4c5d 794
group-onsemi 0:098463de4c5d 795 /**
group-onsemi 0:098463de4c5d 796 * Work out the PRF.
group-onsemi 0:098463de4c5d 797 */
group-onsemi 0:098463de4c5d 798 static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
group-onsemi 0:098463de4c5d 799 uint8_t *out, int olen)
group-onsemi 0:098463de4c5d 800 {
group-onsemi 0:098463de4c5d 801 int len, i;
group-onsemi 0:098463de4c5d 802 const uint8_t *S1, *S2;
group-onsemi 0:098463de4c5d 803 uint8_t xbuf[256]; /* needs to be > the amount of key data */
group-onsemi 0:098463de4c5d 804 uint8_t ybuf[256]; /* needs to be > the amount of key data */
group-onsemi 0:098463de4c5d 805
group-onsemi 0:098463de4c5d 806 len = sec_len/2;
group-onsemi 0:098463de4c5d 807 S1 = sec;
group-onsemi 0:098463de4c5d 808 S2 = &sec[len];
group-onsemi 0:098463de4c5d 809 len += (sec_len & 1); /* add for odd, make longer */
group-onsemi 0:098463de4c5d 810
group-onsemi 0:098463de4c5d 811 p_hash_md5(S1, len, seed, seed_len, xbuf, olen);
group-onsemi 0:098463de4c5d 812 p_hash_sha1(S2, len, seed, seed_len, ybuf, olen);
group-onsemi 0:098463de4c5d 813
group-onsemi 0:098463de4c5d 814 for (i = 0; i < olen; i++)
group-onsemi 0:098463de4c5d 815 out[i] = xbuf[i] ^ ybuf[i];
group-onsemi 0:098463de4c5d 816 }
group-onsemi 0:098463de4c5d 817
group-onsemi 0:098463de4c5d 818 /**
group-onsemi 0:098463de4c5d 819 * Generate a master secret based on the client/server random data and the
group-onsemi 0:098463de4c5d 820 * premaster secret.
group-onsemi 0:098463de4c5d 821 */
group-onsemi 0:098463de4c5d 822 void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret)
group-onsemi 0:098463de4c5d 823 {
group-onsemi 0:098463de4c5d 824 uint8_t buf[128]; /* needs to be > 13+32+32 in size */
group-onsemi 0:098463de4c5d 825 strcpy((char *)buf, "master secret");
group-onsemi 0:098463de4c5d 826 memcpy(&buf[13], ssl->dc->client_random, SSL_RANDOM_SIZE);
group-onsemi 0:098463de4c5d 827 memcpy(&buf[45], ssl->dc->server_random, SSL_RANDOM_SIZE);
group-onsemi 0:098463de4c5d 828 prf(premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
group-onsemi 0:098463de4c5d 829 SSL_SECRET_SIZE);
group-onsemi 0:098463de4c5d 830 }
group-onsemi 0:098463de4c5d 831
group-onsemi 0:098463de4c5d 832 /**
group-onsemi 0:098463de4c5d 833 * Generate a 'random' blob of data used for the generation of keys.
group-onsemi 0:098463de4c5d 834 */
group-onsemi 0:098463de4c5d 835 static void generate_key_block(uint8_t *client_random, uint8_t *server_random,
group-onsemi 0:098463de4c5d 836 uint8_t *master_secret, uint8_t *key_block, int key_block_size)
group-onsemi 0:098463de4c5d 837 {
group-onsemi 0:098463de4c5d 838 uint8_t buf[128];
group-onsemi 0:098463de4c5d 839 strcpy((char *)buf, "key expansion");
group-onsemi 0:098463de4c5d 840 memcpy(&buf[13], server_random, SSL_RANDOM_SIZE);
group-onsemi 0:098463de4c5d 841 memcpy(&buf[45], client_random, SSL_RANDOM_SIZE);
group-onsemi 0:098463de4c5d 842 prf(master_secret, SSL_SECRET_SIZE, buf, 77, key_block, key_block_size);
group-onsemi 0:098463de4c5d 843 }
group-onsemi 0:098463de4c5d 844
group-onsemi 0:098463de4c5d 845 /**
group-onsemi 0:098463de4c5d 846 * Calculate the digest used in the finished message. This function also
group-onsemi 0:098463de4c5d 847 * doubles up as a certificate verify function.
group-onsemi 0:098463de4c5d 848 */
group-onsemi 0:098463de4c5d 849 void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
group-onsemi 0:098463de4c5d 850 {
group-onsemi 0:098463de4c5d 851 uint8_t mac_buf[128];
group-onsemi 0:098463de4c5d 852 uint8_t *q = mac_buf;
group-onsemi 0:098463de4c5d 853 MD5_CTX md5_ctx = ssl->dc->md5_ctx;
group-onsemi 0:098463de4c5d 854 SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
group-onsemi 0:098463de4c5d 855
group-onsemi 0:098463de4c5d 856 if (label)
group-onsemi 0:098463de4c5d 857 {
group-onsemi 0:098463de4c5d 858 strcpy((char *)q, label);
group-onsemi 0:098463de4c5d 859 q += strlen(label);
group-onsemi 0:098463de4c5d 860 }
group-onsemi 0:098463de4c5d 861
group-onsemi 0:098463de4c5d 862 MD5_Final(q, &md5_ctx);
group-onsemi 0:098463de4c5d 863 q += MD5_SIZE;
group-onsemi 0:098463de4c5d 864
group-onsemi 0:098463de4c5d 865 SHA1_Final(q, &sha1_ctx);
group-onsemi 0:098463de4c5d 866 q += SHA1_SIZE;
group-onsemi 0:098463de4c5d 867
group-onsemi 0:098463de4c5d 868 if (label)
group-onsemi 0:098463de4c5d 869 {
group-onsemi 0:098463de4c5d 870 prf(ssl->dc->master_secret, SSL_SECRET_SIZE, mac_buf, (int)(q-mac_buf),
group-onsemi 0:098463de4c5d 871 digest, SSL_FINISHED_HASH_SIZE);
group-onsemi 0:098463de4c5d 872 }
group-onsemi 0:098463de4c5d 873 else /* for use in a certificate verify */
group-onsemi 0:098463de4c5d 874 {
group-onsemi 0:098463de4c5d 875 memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE);
group-onsemi 0:098463de4c5d 876 }
group-onsemi 0:098463de4c5d 877
group-onsemi 0:098463de4c5d 878 #if 0
group-onsemi 0:098463de4c5d 879 printf("label: %s\r\n", label);
group-onsemi 0:098463de4c5d 880 print_blob("master secret", ssl->dc->master_secret, 48);
group-onsemi 0:098463de4c5d 881 print_blob("mac_buf", mac_buf, q-mac_buf);
group-onsemi 0:098463de4c5d 882 print_blob("finished digest", digest, SSL_FINISHED_HASH_SIZE);
group-onsemi 0:098463de4c5d 883 #endif
group-onsemi 0:098463de4c5d 884 }
group-onsemi 0:098463de4c5d 885
group-onsemi 0:098463de4c5d 886 /**
group-onsemi 0:098463de4c5d 887 * Retrieve (and initialise) the context of a cipher.
group-onsemi 0:098463de4c5d 888 */
group-onsemi 0:098463de4c5d 889 static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
group-onsemi 0:098463de4c5d 890 {
group-onsemi 0:098463de4c5d 891 switch (ssl->cipher)
group-onsemi 0:098463de4c5d 892 {
group-onsemi 0:098463de4c5d 893 #ifndef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 894 case SSL_AES128_SHA:
group-onsemi 0:098463de4c5d 895 {
group-onsemi 0:098463de4c5d 896 AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
group-onsemi 0:098463de4c5d 897 AES_set_key(aes_ctx, key, iv, AES_MODE_128);
group-onsemi 0:098463de4c5d 898
group-onsemi 0:098463de4c5d 899 if (is_decrypt)
group-onsemi 0:098463de4c5d 900 {
group-onsemi 0:098463de4c5d 901 AES_convert_key(aes_ctx);
group-onsemi 0:098463de4c5d 902 }
group-onsemi 0:098463de4c5d 903
group-onsemi 0:098463de4c5d 904 return (void *)aes_ctx;
group-onsemi 0:098463de4c5d 905 }
group-onsemi 0:098463de4c5d 906
group-onsemi 0:098463de4c5d 907 case SSL_AES256_SHA:
group-onsemi 0:098463de4c5d 908 {
group-onsemi 0:098463de4c5d 909 AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
group-onsemi 0:098463de4c5d 910 AES_set_key(aes_ctx, key, iv, AES_MODE_256);
group-onsemi 0:098463de4c5d 911
group-onsemi 0:098463de4c5d 912 if (is_decrypt)
group-onsemi 0:098463de4c5d 913 {
group-onsemi 0:098463de4c5d 914 AES_convert_key(aes_ctx);
group-onsemi 0:098463de4c5d 915 }
group-onsemi 0:098463de4c5d 916
group-onsemi 0:098463de4c5d 917 return (void *)aes_ctx;
group-onsemi 0:098463de4c5d 918 }
group-onsemi 0:098463de4c5d 919
group-onsemi 0:098463de4c5d 920 case SSL_RC4_128_MD5:
group-onsemi 0:098463de4c5d 921 #endif
group-onsemi 0:098463de4c5d 922 case SSL_RC4_128_SHA:
group-onsemi 0:098463de4c5d 923 {
group-onsemi 0:098463de4c5d 924 RC4_CTX *rc4_ctx = (RC4_CTX *)malloc(sizeof(RC4_CTX));
group-onsemi 0:098463de4c5d 925 RC4_setup(rc4_ctx, key, 16);
group-onsemi 0:098463de4c5d 926 return (void *)rc4_ctx;
group-onsemi 0:098463de4c5d 927 }
group-onsemi 0:098463de4c5d 928 }
group-onsemi 0:098463de4c5d 929
group-onsemi 0:098463de4c5d 930 return NULL; /* its all gone wrong */
group-onsemi 0:098463de4c5d 931 }
group-onsemi 0:098463de4c5d 932
group-onsemi 0:098463de4c5d 933
group-onsemi 0:098463de4c5d 934 /**
group-onsemi 0:098463de4c5d 935 * Send a packet over the socket.
group-onsemi 0:098463de4c5d 936 */
group-onsemi 0:098463de4c5d 937 static int send_raw_packet(SSL *ssl, uint8_t protocol)
group-onsemi 0:098463de4c5d 938 {
group-onsemi 0:098463de4c5d 939 uint8_t *rec_buf = ssl->bm_all_data;
group-onsemi 0:098463de4c5d 940 int pkt_size = SSL_RECORD_SIZE+ssl->bm_index;
group-onsemi 0:098463de4c5d 941 int sent = 0;
group-onsemi 0:098463de4c5d 942 int ret = SSL_OK;
group-onsemi 0:098463de4c5d 943 rec_buf[0] = protocol;
group-onsemi 0:098463de4c5d 944 rec_buf[1] = 0x03; /* version = 3.1 or higher */
group-onsemi 0:098463de4c5d 945 rec_buf[2] = ssl->version & 0x0f;
group-onsemi 0:098463de4c5d 946 rec_buf[3] = ssl->bm_index >> 8;
group-onsemi 0:098463de4c5d 947 rec_buf[4] = ssl->bm_index & 0xff;
group-onsemi 0:098463de4c5d 948
group-onsemi 0:098463de4c5d 949 DISPLAY_BYTES(ssl, "sending %d bytes", ssl->bm_all_data,
group-onsemi 0:098463de4c5d 950 pkt_size, pkt_size);
group-onsemi 0:098463de4c5d 951
group-onsemi 0:098463de4c5d 952
group-onsemi 0:098463de4c5d 953
group-onsemi 0:098463de4c5d 954 while (sent < pkt_size)
group-onsemi 0:098463de4c5d 955 {
group-onsemi 0:098463de4c5d 956 ret = SOCKET_WRITE(ssl->client_fd,
group-onsemi 0:098463de4c5d 957 &ssl->bm_all_data[sent], pkt_size-sent);
group-onsemi 0:098463de4c5d 958 if (ret >= 0)
group-onsemi 0:098463de4c5d 959 sent += ret;
group-onsemi 0:098463de4c5d 960 else
group-onsemi 0:098463de4c5d 961 {
group-onsemi 0:098463de4c5d 962
group-onsemi 0:098463de4c5d 963 #ifdef WIN32
group-onsemi 0:098463de4c5d 964 if (GetLastError() != WSAEWOULDBLOCK)
group-onsemi 0:098463de4c5d 965 #else
group-onsemi 0:098463de4c5d 966 if (errno != EAGAIN && errno != EWOULDBLOCK)
group-onsemi 0:098463de4c5d 967 #endif
group-onsemi 0:098463de4c5d 968 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 969 }
group-onsemi 0:098463de4c5d 970
group-onsemi 0:098463de4c5d 971 /* keep going until the write buffer has some space */
group-onsemi 0:098463de4c5d 972 if (sent != pkt_size)
group-onsemi 0:098463de4c5d 973 {
group-onsemi 0:098463de4c5d 974 fd_set wfds;
group-onsemi 0:098463de4c5d 975 FD_ZERO(&wfds);
group-onsemi 0:098463de4c5d 976 FD_SET(ssl->client_fd, &wfds);
group-onsemi 0:098463de4c5d 977
group-onsemi 0:098463de4c5d 978 /* block and wait for it */
group-onsemi 0:098463de4c5d 979 if (lwip_select(FD_SETSIZE, NULL, &wfds, NULL, NULL) < 0)
group-onsemi 0:098463de4c5d 980 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 981
group-onsemi 0:098463de4c5d 982 }
group-onsemi 0:098463de4c5d 983 }
group-onsemi 0:098463de4c5d 984 fd_set wfds;
group-onsemi 0:098463de4c5d 985 FD_ZERO(&wfds);
group-onsemi 0:098463de4c5d 986 FD_SET(ssl->client_fd, &wfds);
group-onsemi 0:098463de4c5d 987
group-onsemi 0:098463de4c5d 988 /* block and wait for it */
group-onsemi 0:098463de4c5d 989 if (lwip_select(FD_SETSIZE, NULL, &wfds, NULL, NULL) < 0)
group-onsemi 0:098463de4c5d 990 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 991
group-onsemi 0:098463de4c5d 992 SET_SSL_FLAG(SSL_NEED_RECORD); /* reset for next time */
group-onsemi 0:098463de4c5d 993 ssl->bm_index = 0;
group-onsemi 0:098463de4c5d 994
group-onsemi 0:098463de4c5d 995 if (protocol != PT_APP_PROTOCOL_DATA)
group-onsemi 0:098463de4c5d 996 {
group-onsemi 0:098463de4c5d 997 /* always return SSL_OK during handshake */
group-onsemi 0:098463de4c5d 998 ret = SSL_OK;
group-onsemi 0:098463de4c5d 999 }
group-onsemi 0:098463de4c5d 1000
group-onsemi 0:098463de4c5d 1001 return ret;
group-onsemi 0:098463de4c5d 1002 }
group-onsemi 0:098463de4c5d 1003
group-onsemi 0:098463de4c5d 1004 /**
group-onsemi 0:098463de4c5d 1005 * Send an encrypted packet with padding bytes if necessary.
group-onsemi 0:098463de4c5d 1006 */
group-onsemi 0:098463de4c5d 1007 int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
group-onsemi 0:098463de4c5d 1008 {
group-onsemi 0:098463de4c5d 1009 int ret, msg_length = 0;
group-onsemi 0:098463de4c5d 1010
group-onsemi 0:098463de4c5d 1011 /* if our state is bad, don't bother */
group-onsemi 0:098463de4c5d 1012 if (ssl->hs_status == SSL_ERROR_DEAD)
group-onsemi 0:098463de4c5d 1013 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 1014
group-onsemi 0:098463de4c5d 1015 if (in) /* has the buffer already been initialised? */
group-onsemi 0:098463de4c5d 1016 {
group-onsemi 0:098463de4c5d 1017 memcpy(ssl->bm_data, in, length);
group-onsemi 0:098463de4c5d 1018 }
group-onsemi 0:098463de4c5d 1019
group-onsemi 0:098463de4c5d 1020 msg_length += length;
group-onsemi 0:098463de4c5d 1021
group-onsemi 0:098463de4c5d 1022 if (IS_SET_SSL_FLAG(SSL_TX_ENCRYPTED))
group-onsemi 0:098463de4c5d 1023 {
group-onsemi 0:098463de4c5d 1024 int mode = IS_SET_SSL_FLAG(SSL_IS_CLIENT) ?
group-onsemi 0:098463de4c5d 1025 SSL_CLIENT_WRITE : SSL_SERVER_WRITE;
group-onsemi 0:098463de4c5d 1026 uint8_t hmac_header[SSL_RECORD_SIZE] =
group-onsemi 0:098463de4c5d 1027 {
group-onsemi 0:098463de4c5d 1028 protocol,
group-onsemi 0:098463de4c5d 1029 0x03, /* version = 3.1 or higher */
group-onsemi 0:098463de4c5d 1030 ssl->version & 0x0f,
group-onsemi 0:098463de4c5d 1031 msg_length >> 8,
group-onsemi 0:098463de4c5d 1032 msg_length & 0xff
group-onsemi 0:098463de4c5d 1033 };
group-onsemi 0:098463de4c5d 1034
group-onsemi 0:098463de4c5d 1035 if (protocol == PT_HANDSHAKE_PROTOCOL)
group-onsemi 0:098463de4c5d 1036 {
group-onsemi 0:098463de4c5d 1037 DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
group-onsemi 0:098463de4c5d 1038
group-onsemi 0:098463de4c5d 1039 if (ssl->bm_data[0] != HS_HELLO_REQUEST)
group-onsemi 0:098463de4c5d 1040 {
group-onsemi 0:098463de4c5d 1041 add_packet(ssl, ssl->bm_data, msg_length);
group-onsemi 0:098463de4c5d 1042 }
group-onsemi 0:098463de4c5d 1043 }
group-onsemi 0:098463de4c5d 1044
group-onsemi 0:098463de4c5d 1045 /* add the packet digest */
group-onsemi 0:098463de4c5d 1046 add_hmac_digest(ssl, mode, hmac_header, ssl->bm_data, msg_length,
group-onsemi 0:098463de4c5d 1047 &ssl->bm_data[msg_length]);
group-onsemi 0:098463de4c5d 1048 msg_length += ssl->cipher_info->digest_size;
group-onsemi 0:098463de4c5d 1049
group-onsemi 0:098463de4c5d 1050 /* add padding? */
group-onsemi 0:098463de4c5d 1051 if (ssl->cipher_info->padding_size)
group-onsemi 0:098463de4c5d 1052 {
group-onsemi 0:098463de4c5d 1053 int last_blk_size = msg_length%ssl->cipher_info->padding_size;
group-onsemi 0:098463de4c5d 1054 int pad_bytes = ssl->cipher_info->padding_size - last_blk_size;
group-onsemi 0:098463de4c5d 1055
group-onsemi 0:098463de4c5d 1056 /* ensure we always have at least 1 padding byte */
group-onsemi 0:098463de4c5d 1057 if (pad_bytes == 0)
group-onsemi 0:098463de4c5d 1058 pad_bytes += ssl->cipher_info->padding_size;
group-onsemi 0:098463de4c5d 1059
group-onsemi 0:098463de4c5d 1060 memset(&ssl->bm_data[msg_length], pad_bytes-1, pad_bytes);
group-onsemi 0:098463de4c5d 1061 msg_length += pad_bytes;
group-onsemi 0:098463de4c5d 1062 }
group-onsemi 0:098463de4c5d 1063
group-onsemi 0:098463de4c5d 1064 DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_data, msg_length);
group-onsemi 0:098463de4c5d 1065 increment_write_sequence(ssl);
group-onsemi 0:098463de4c5d 1066
group-onsemi 0:098463de4c5d 1067 /* add the explicit IV for TLS1.1 */
group-onsemi 0:098463de4c5d 1068 if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
group-onsemi 0:098463de4c5d 1069 ssl->cipher_info->iv_size)
group-onsemi 0:098463de4c5d 1070 {
group-onsemi 0:098463de4c5d 1071 uint8_t iv_size = ssl->cipher_info->iv_size;
group-onsemi 0:098463de4c5d 1072 uint8_t *t_buf = alloca(msg_length + iv_size);
group-onsemi 0:098463de4c5d 1073 memcpy(t_buf + iv_size, ssl->bm_data, msg_length);
group-onsemi 0:098463de4c5d 1074 get_random(iv_size, t_buf);
group-onsemi 0:098463de4c5d 1075 msg_length += iv_size;
group-onsemi 0:098463de4c5d 1076 memcpy(ssl->bm_data, t_buf, msg_length);
group-onsemi 0:098463de4c5d 1077 }
group-onsemi 0:098463de4c5d 1078
group-onsemi 0:098463de4c5d 1079 /* now encrypt the packet */
group-onsemi 0:098463de4c5d 1080 ssl->cipher_info->encrypt(ssl->encrypt_ctx, ssl->bm_data,
group-onsemi 0:098463de4c5d 1081 ssl->bm_data, msg_length);
group-onsemi 0:098463de4c5d 1082 }
group-onsemi 0:098463de4c5d 1083 else if (protocol == PT_HANDSHAKE_PROTOCOL)
group-onsemi 0:098463de4c5d 1084 {
group-onsemi 0:098463de4c5d 1085 DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
group-onsemi 0:098463de4c5d 1086
group-onsemi 0:098463de4c5d 1087 if (ssl->bm_data[0] != HS_HELLO_REQUEST)
group-onsemi 0:098463de4c5d 1088 {
group-onsemi 0:098463de4c5d 1089 add_packet(ssl, ssl->bm_data, length);
group-onsemi 0:098463de4c5d 1090 }
group-onsemi 0:098463de4c5d 1091 }
group-onsemi 0:098463de4c5d 1092
group-onsemi 0:098463de4c5d 1093 ssl->bm_index = msg_length;
group-onsemi 0:098463de4c5d 1094 if ((ret = send_raw_packet(ssl, protocol)) <= 0)
group-onsemi 0:098463de4c5d 1095 return ret;
group-onsemi 0:098463de4c5d 1096
group-onsemi 0:098463de4c5d 1097 return length; /* just return what we wanted to send */
group-onsemi 0:098463de4c5d 1098 }
group-onsemi 0:098463de4c5d 1099
group-onsemi 0:098463de4c5d 1100 /**
group-onsemi 0:098463de4c5d 1101 * Work out the cipher keys we are going to use for this session based on the
group-onsemi 0:098463de4c5d 1102 * master secret.
group-onsemi 0:098463de4c5d 1103 */
group-onsemi 0:098463de4c5d 1104 static int set_key_block(SSL *ssl, int is_write)
group-onsemi 0:098463de4c5d 1105 {
group-onsemi 0:098463de4c5d 1106 const cipher_info_t *ciph_info = get_cipher_info(ssl->cipher);
group-onsemi 0:098463de4c5d 1107 uint8_t *q;
group-onsemi 0:098463de4c5d 1108 uint8_t client_key[32], server_key[32]; /* big enough for AES256 */
group-onsemi 0:098463de4c5d 1109 uint8_t client_iv[16], server_iv[16]; /* big enough for AES128/256 */
group-onsemi 0:098463de4c5d 1110 int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
group-onsemi 0:098463de4c5d 1111
group-onsemi 0:098463de4c5d 1112 if (ciph_info == NULL)
group-onsemi 0:098463de4c5d 1113 return -1;
group-onsemi 0:098463de4c5d 1114
group-onsemi 0:098463de4c5d 1115 uint8_t key_tmp[MAX_KEYBLOCK_SIZE] = {0};
group-onsemi 0:098463de4c5d 1116 /* only do once in a handshake */
group-onsemi 0:098463de4c5d 1117 if (memcmp(ssl->dc->key_block, key_tmp, MAX_KEYBLOCK_SIZE) == 0)
group-onsemi 0:098463de4c5d 1118 {
group-onsemi 0:098463de4c5d 1119 #if 0
group-onsemi 0:098463de4c5d 1120 print_blob("client", ssl->dc->client_random, 32);
group-onsemi 0:098463de4c5d 1121 print_blob("server", ssl->dc->server_random, 32);
group-onsemi 0:098463de4c5d 1122 print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
group-onsemi 0:098463de4c5d 1123 #endif
group-onsemi 0:098463de4c5d 1124 generate_key_block(ssl->dc->client_random, ssl->dc->server_random,
group-onsemi 0:098463de4c5d 1125 ssl->dc->master_secret, ssl->dc->key_block,
group-onsemi 0:098463de4c5d 1126 ciph_info->key_block_size);
group-onsemi 0:098463de4c5d 1127 #if 0
group-onsemi 0:098463de4c5d 1128 print_blob("keyblock", ssl->dc->key_block, ciph_info->key_block_size);
group-onsemi 0:098463de4c5d 1129 #endif
group-onsemi 0:098463de4c5d 1130 }
group-onsemi 0:098463de4c5d 1131
group-onsemi 0:098463de4c5d 1132 q = ssl->dc->key_block;
group-onsemi 0:098463de4c5d 1133
group-onsemi 0:098463de4c5d 1134 if ((is_client && is_write) || (!is_client && !is_write))
group-onsemi 0:098463de4c5d 1135 {
group-onsemi 0:098463de4c5d 1136 memcpy(ssl->client_mac, q, ciph_info->digest_size);
group-onsemi 0:098463de4c5d 1137 }
group-onsemi 0:098463de4c5d 1138
group-onsemi 0:098463de4c5d 1139 q += ciph_info->digest_size;
group-onsemi 0:098463de4c5d 1140
group-onsemi 0:098463de4c5d 1141 if ((!is_client && is_write) || (is_client && !is_write))
group-onsemi 0:098463de4c5d 1142 {
group-onsemi 0:098463de4c5d 1143 memcpy(ssl->server_mac, q, ciph_info->digest_size);
group-onsemi 0:098463de4c5d 1144 }
group-onsemi 0:098463de4c5d 1145
group-onsemi 0:098463de4c5d 1146 q += ciph_info->digest_size;
group-onsemi 0:098463de4c5d 1147 memcpy(client_key, q, ciph_info->key_size);
group-onsemi 0:098463de4c5d 1148 q += ciph_info->key_size;
group-onsemi 0:098463de4c5d 1149 memcpy(server_key, q, ciph_info->key_size);
group-onsemi 0:098463de4c5d 1150 q += ciph_info->key_size;
group-onsemi 0:098463de4c5d 1151
group-onsemi 0:098463de4c5d 1152 #ifndef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 1153 if (ciph_info->iv_size) /* RC4 has no IV, AES does */
group-onsemi 0:098463de4c5d 1154 {
group-onsemi 0:098463de4c5d 1155 memcpy(client_iv, q, ciph_info->iv_size);
group-onsemi 0:098463de4c5d 1156 q += ciph_info->iv_size;
group-onsemi 0:098463de4c5d 1157 memcpy(server_iv, q, ciph_info->iv_size);
group-onsemi 0:098463de4c5d 1158 q += ciph_info->iv_size;
group-onsemi 0:098463de4c5d 1159 }
group-onsemi 0:098463de4c5d 1160 #endif
group-onsemi 0:098463de4c5d 1161
group-onsemi 0:098463de4c5d 1162 if( (is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx) != NULL)
group-onsemi 0:098463de4c5d 1163 free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx);
group-onsemi 0:098463de4c5d 1164
group-onsemi 0:098463de4c5d 1165 /* now initialise the ciphers */
group-onsemi 0:098463de4c5d 1166 if (is_client)
group-onsemi 0:098463de4c5d 1167 {
group-onsemi 0:098463de4c5d 1168 finished_digest(ssl, server_finished, ssl->dc->final_finish_mac);
group-onsemi 0:098463de4c5d 1169
group-onsemi 0:098463de4c5d 1170 if (is_write)
group-onsemi 0:098463de4c5d 1171 ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0);
group-onsemi 0:098463de4c5d 1172 else
group-onsemi 0:098463de4c5d 1173 ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1);
group-onsemi 0:098463de4c5d 1174 }
group-onsemi 0:098463de4c5d 1175 else
group-onsemi 0:098463de4c5d 1176 {
group-onsemi 0:098463de4c5d 1177 finished_digest(ssl, client_finished, ssl->dc->final_finish_mac);
group-onsemi 0:098463de4c5d 1178
group-onsemi 0:098463de4c5d 1179 if (is_write)
group-onsemi 0:098463de4c5d 1180 ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0);
group-onsemi 0:098463de4c5d 1181 else
group-onsemi 0:098463de4c5d 1182 ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1);
group-onsemi 0:098463de4c5d 1183 }
group-onsemi 0:098463de4c5d 1184
group-onsemi 0:098463de4c5d 1185 ssl->cipher_info = ciph_info;
group-onsemi 0:098463de4c5d 1186 return 0;
group-onsemi 0:098463de4c5d 1187 }
group-onsemi 0:098463de4c5d 1188
group-onsemi 0:098463de4c5d 1189 /**
group-onsemi 0:098463de4c5d 1190 * Blocking read
group-onsemi 0:098463de4c5d 1191 * data must be valid buffer of size length at least
group-onsemi 0:098463de4c5d 1192 * length
group-onsemi 0:098463de4c5d 1193 */
group-onsemi 0:098463de4c5d 1194 int basic_read2(SSL *ssl, uint8_t *data, uint32_t length)
group-onsemi 0:098463de4c5d 1195 {
group-onsemi 0:098463de4c5d 1196 // printf("basic_read2\n");
group-onsemi 0:098463de4c5d 1197 if(data == NULL)
group-onsemi 0:098463de4c5d 1198 return -1;
group-onsemi 0:098463de4c5d 1199
group-onsemi 0:098463de4c5d 1200 int ret = 0;
group-onsemi 0:098463de4c5d 1201
group-onsemi 0:098463de4c5d 1202 do
group-onsemi 0:098463de4c5d 1203 {
group-onsemi 0:098463de4c5d 1204 //printf("before_lwip_select\n");
group-onsemi 0:098463de4c5d 1205 fd_set rfds;
group-onsemi 0:098463de4c5d 1206 FD_ZERO(&rfds);
group-onsemi 0:098463de4c5d 1207 FD_SET(ssl->client_fd, &rfds);
group-onsemi 0:098463de4c5d 1208
group-onsemi 0:098463de4c5d 1209 /* block and wait for it */
group-onsemi 0:098463de4c5d 1210 if (lwip_select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0)
group-onsemi 0:098463de4c5d 1211 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 1212 // printf("after_lwip_select\n");
group-onsemi 0:098463de4c5d 1213
group-onsemi 0:098463de4c5d 1214 int read_len = SOCKET_READ(ssl->client_fd, &data[ret], length-ret);
group-onsemi 0:098463de4c5d 1215 // printf("read_len = %d\n", read_len);
group-onsemi 0:098463de4c5d 1216
group-onsemi 0:098463de4c5d 1217 if (read_len < 0)
group-onsemi 0:098463de4c5d 1218 {
group-onsemi 0:098463de4c5d 1219
group-onsemi 0:098463de4c5d 1220 #ifdef WIN32
group-onsemi 0:098463de4c5d 1221 if (GetLastError() == WSAEWOULDBLOCK)
group-onsemi 0:098463de4c5d 1222 #else
group-onsemi 0:098463de4c5d 1223 if (errno == EAGAIN || errno == EWOULDBLOCK)
group-onsemi 0:098463de4c5d 1224 #endif
group-onsemi 0:098463de4c5d 1225 continue;
group-onsemi 0:098463de4c5d 1226 }
group-onsemi 0:098463de4c5d 1227
group-onsemi 0:098463de4c5d 1228 /* connection has gone, so die */
group-onsemi 0:098463de4c5d 1229 if (read_len <= 0)
group-onsemi 0:098463de4c5d 1230 {
group-onsemi 0:098463de4c5d 1231 printf("SSL_ERROR_CONN_LOST\n");
group-onsemi 0:098463de4c5d 1232 ssl->hs_status = SSL_ERROR_DEAD; /* make sure it stays dead */
group-onsemi 0:098463de4c5d 1233 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 1234 }
group-onsemi 0:098463de4c5d 1235
group-onsemi 0:098463de4c5d 1236 ret += read_len;
group-onsemi 0:098463de4c5d 1237
group-onsemi 0:098463de4c5d 1238 }while(ret < length);
group-onsemi 0:098463de4c5d 1239 DISPLAY_BYTES(ssl, "received %d bytes", data, ret, ret);
group-onsemi 0:098463de4c5d 1240 return ret;
group-onsemi 0:098463de4c5d 1241 }
group-onsemi 0:098463de4c5d 1242
group-onsemi 0:098463de4c5d 1243 int read_record(SSL *ssl)
group-onsemi 0:098463de4c5d 1244 {
group-onsemi 0:098463de4c5d 1245 if(!IS_SET_SSL_FLAG(SSL_NEED_RECORD))
group-onsemi 0:098463de4c5d 1246 return 0;
group-onsemi 0:098463de4c5d 1247 uint8_t record[SSL_RECORD_SIZE];
group-onsemi 0:098463de4c5d 1248 int ret = basic_read2(ssl, record, SSL_RECORD_SIZE);
group-onsemi 0:098463de4c5d 1249 if(ret != SSL_RECORD_SIZE)
group-onsemi 0:098463de4c5d 1250 return ret;
group-onsemi 0:098463de4c5d 1251
group-onsemi 0:098463de4c5d 1252 /* check for sslv2 "client hello" */
group-onsemi 0:098463de4c5d 1253 if (record[0] & 0x80 && record[2] == 1)
group-onsemi 0:098463de4c5d 1254 {
group-onsemi 0:098463de4c5d 1255 #ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
group-onsemi 0:098463de4c5d 1256 uint8_t version = (record[3] << 4) + record[4];
group-onsemi 0:098463de4c5d 1257 DISPLAY_BYTES(ssl, "ssl2 record", record, 5);
group-onsemi 0:098463de4c5d 1258
group-onsemi 0:098463de4c5d 1259 /* should be v3.1 (TLSv1) or better */
group-onsemi 0:098463de4c5d 1260 ssl->version = ssl->client_version = version;
group-onsemi 0:098463de4c5d 1261
group-onsemi 0:098463de4c5d 1262 if (version > SSL_PROTOCOL_VERSION_MAX)
group-onsemi 0:098463de4c5d 1263 {
group-onsemi 0:098463de4c5d 1264 /* use client's version */
group-onsemi 0:098463de4c5d 1265 ssl->version = SSL_PROTOCOL_VERSION_MAX;
group-onsemi 0:098463de4c5d 1266 }
group-onsemi 0:098463de4c5d 1267 else if (version < SSL_PROTOCOL_MIN_VERSION)
group-onsemi 0:098463de4c5d 1268 {
group-onsemi 0:098463de4c5d 1269 ret = SSL_ERROR_INVALID_VERSION;
group-onsemi 0:098463de4c5d 1270 ssl_display_error(ret);
group-onsemi 0:098463de4c5d 1271 return ret;
group-onsemi 0:098463de4c5d 1272 }
group-onsemi 0:098463de4c5d 1273
group-onsemi 0:098463de4c5d 1274 add_packet(ssl, &record[2], 3);
group-onsemi 0:098463de4c5d 1275 ret = process_sslv23_client_hello(ssl);
group-onsemi 0:098463de4c5d 1276 #else
group-onsemi 0:098463de4c5d 1277 printf("Error: no SSLv23 handshaking allowed\n"); TTY_FLUSH();
group-onsemi 0:098463de4c5d 1278 ret = SSL_ERROR_NOT_SUPPORTED;
group-onsemi 0:098463de4c5d 1279 #endif
group-onsemi 0:098463de4c5d 1280 return ret;
group-onsemi 0:098463de4c5d 1281 }
group-onsemi 0:098463de4c5d 1282
group-onsemi 0:098463de4c5d 1283 ssl->need_bytes = (record[3] << 8) + record[4];
group-onsemi 0:098463de4c5d 1284
group-onsemi 0:098463de4c5d 1285
group-onsemi 0:098463de4c5d 1286 memcpy(ssl->hmac_header, record, 3); /* store for hmac */
group-onsemi 0:098463de4c5d 1287 ssl->record_type = record[0];
group-onsemi 0:098463de4c5d 1288 CLR_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1289 return SSL_OK;
group-onsemi 0:098463de4c5d 1290 }
group-onsemi 0:098463de4c5d 1291
group-onsemi 0:098463de4c5d 1292 int basic_decrypt(SSL *ssl, uint8_t *buf, int len)
group-onsemi 0:098463de4c5d 1293 {
group-onsemi 0:098463de4c5d 1294 if (IS_SET_SSL_FLAG(SSL_RX_ENCRYPTED))
group-onsemi 0:098463de4c5d 1295 {
group-onsemi 0:098463de4c5d 1296 ssl->cipher_info->decrypt(ssl->decrypt_ctx, buf, buf, len);
group-onsemi 0:098463de4c5d 1297
group-onsemi 0:098463de4c5d 1298 if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
group-onsemi 0:098463de4c5d 1299 ssl->cipher_info->iv_size)
group-onsemi 0:098463de4c5d 1300 {
group-onsemi 0:098463de4c5d 1301 buf += ssl->cipher_info->iv_size;
group-onsemi 0:098463de4c5d 1302 ssl->need_bytes -= ssl->cipher_info->iv_size;
group-onsemi 0:098463de4c5d 1303 }
group-onsemi 0:098463de4c5d 1304 if(ssl->record_type != PT_APP_PROTOCOL_DATA)
group-onsemi 0:098463de4c5d 1305 len = verify_digest(ssl,
group-onsemi 0:098463de4c5d 1306 IS_SET_SSL_FLAG(SSL_IS_CLIENT) ? SSL_CLIENT_READ : SSL_SERVER_READ, buf, len);
group-onsemi 0:098463de4c5d 1307
group-onsemi 0:098463de4c5d 1308 /* does the hmac work? */
group-onsemi 0:098463de4c5d 1309 if (ssl->need_bytes < 0)
group-onsemi 0:098463de4c5d 1310 {
group-onsemi 0:098463de4c5d 1311 return ssl->need_bytes;
group-onsemi 0:098463de4c5d 1312 }
group-onsemi 0:098463de4c5d 1313
group-onsemi 0:098463de4c5d 1314 DISPLAY_BYTES(ssl, "decrypted", buf, len);
group-onsemi 0:098463de4c5d 1315 increment_read_sequence(ssl);
group-onsemi 0:098463de4c5d 1316 }
group-onsemi 0:098463de4c5d 1317 return len;
group-onsemi 0:098463de4c5d 1318 }
group-onsemi 0:098463de4c5d 1319
group-onsemi 0:098463de4c5d 1320 int ssl_read(SSL *ssl, uint8_t *in_data, int len)
group-onsemi 0:098463de4c5d 1321 {
group-onsemi 0:098463de4c5d 1322 if(len <= 0 || in_data == NULL)
group-onsemi 0:098463de4c5d 1323 return 0;
group-onsemi 0:098463de4c5d 1324
group-onsemi 0:098463de4c5d 1325 if(IS_SET_SSL_FLAG(SSL_NEED_RECORD))
group-onsemi 0:098463de4c5d 1326 {
group-onsemi 0:098463de4c5d 1327 read_record(ssl);
group-onsemi 0:098463de4c5d 1328 }
group-onsemi 0:098463de4c5d 1329
group-onsemi 0:098463de4c5d 1330 return process_data(ssl, in_data, len);
group-onsemi 0:098463de4c5d 1331 }
group-onsemi 0:098463de4c5d 1332
group-onsemi 0:098463de4c5d 1333 int process_data(SSL* ssl, uint8_t *in_data, int len)
group-onsemi 0:098463de4c5d 1334 {
group-onsemi 0:098463de4c5d 1335 /* The main part of the SSL packet */
group-onsemi 0:098463de4c5d 1336 switch (ssl->record_type)
group-onsemi 0:098463de4c5d 1337 {
group-onsemi 0:098463de4c5d 1338 case PT_HANDSHAKE_PROTOCOL:
group-onsemi 0:098463de4c5d 1339
group-onsemi 0:098463de4c5d 1340 if (ssl->dc != NULL)
group-onsemi 0:098463de4c5d 1341 {
group-onsemi 0:098463de4c5d 1342 ssl->dc->bm_proc_index = 0;
group-onsemi 0:098463de4c5d 1343 int ret = do_handshake(ssl, NULL, 0);
group-onsemi 0:098463de4c5d 1344 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1345 return ret;
group-onsemi 0:098463de4c5d 1346 }
group-onsemi 0:098463de4c5d 1347 else /* no client renegotiation allowed */
group-onsemi 0:098463de4c5d 1348 {
group-onsemi 0:098463de4c5d 1349 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1350 return SSL_ERROR_NO_CLIENT_RENOG;
group-onsemi 0:098463de4c5d 1351 }
group-onsemi 0:098463de4c5d 1352
group-onsemi 0:098463de4c5d 1353 case PT_CHANGE_CIPHER_SPEC:
group-onsemi 0:098463de4c5d 1354
group-onsemi 0:098463de4c5d 1355 if(basic_read2(ssl, ssl->bm_data, ssl->need_bytes) != ssl->need_bytes)
group-onsemi 0:098463de4c5d 1356 return -1;
group-onsemi 0:098463de4c5d 1357 ssl->need_bytes = basic_decrypt(ssl, ssl->bm_data, ssl->need_bytes);
group-onsemi 0:098463de4c5d 1358 if(ssl->need_bytes < 0)
group-onsemi 0:098463de4c5d 1359 return -1;
group-onsemi 0:098463de4c5d 1360
group-onsemi 0:098463de4c5d 1361 if (ssl->next_state != HS_FINISHED)
group-onsemi 0:098463de4c5d 1362 {
group-onsemi 0:098463de4c5d 1363 return SSL_ERROR_INVALID_HANDSHAKE;
group-onsemi 0:098463de4c5d 1364 }
group-onsemi 0:098463de4c5d 1365
group-onsemi 0:098463de4c5d 1366 /* all encrypted from now on */
group-onsemi 0:098463de4c5d 1367 SET_SSL_FLAG(SSL_RX_ENCRYPTED);
group-onsemi 0:098463de4c5d 1368 if (set_key_block(ssl, 0) < 0)
group-onsemi 0:098463de4c5d 1369 {
group-onsemi 0:098463de4c5d 1370 return SSL_ERROR_INVALID_HANDSHAKE;
group-onsemi 0:098463de4c5d 1371 }
group-onsemi 0:098463de4c5d 1372
group-onsemi 0:098463de4c5d 1373 memset(ssl->read_sequence, 0, 8);
group-onsemi 0:098463de4c5d 1374 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1375 break;
group-onsemi 0:098463de4c5d 1376
group-onsemi 0:098463de4c5d 1377 case PT_APP_PROTOCOL_DATA:
group-onsemi 0:098463de4c5d 1378 if(len <= 0)
group-onsemi 0:098463de4c5d 1379 return 0;
group-onsemi 0:098463de4c5d 1380 if(ssl->need_bytes == 0)
group-onsemi 0:098463de4c5d 1381 return 0;
group-onsemi 0:098463de4c5d 1382 if (in_data)
group-onsemi 0:098463de4c5d 1383 {
group-onsemi 0:098463de4c5d 1384 uint16_t index = ssl->bm_index % 2048;
group-onsemi 0:098463de4c5d 1385 if(ssl->bm_read_index == 0)
group-onsemi 0:098463de4c5d 1386 {
group-onsemi 0:098463de4c5d 1387 int read_len = len;
group-onsemi 0:098463de4c5d 1388 if(read_len > 2048-index)
group-onsemi 0:098463de4c5d 1389 read_len = 2048-index;
group-onsemi 0:098463de4c5d 1390 if(read_len > ssl->need_bytes)
group-onsemi 0:098463de4c5d 1391 read_len = ssl->need_bytes;
group-onsemi 0:098463de4c5d 1392 read_len -= read_len % AES_BLOCKSIZE;
group-onsemi 0:098463de4c5d 1393
group-onsemi 0:098463de4c5d 1394 if(read_len <= 0)
group-onsemi 0:098463de4c5d 1395 read_len = AES_BLOCKSIZE;
group-onsemi 0:098463de4c5d 1396 if(ssl->need_bytes < AES_BLOCKSIZE)
group-onsemi 0:098463de4c5d 1397 read_len = AES_BLOCKSIZE;
group-onsemi 0:098463de4c5d 1398 int ret = basic_read2(ssl, ssl->bm_all_data + index, read_len);
group-onsemi 0:098463de4c5d 1399 if(ret != read_len)
group-onsemi 0:098463de4c5d 1400 return 0;
group-onsemi 0:098463de4c5d 1401
group-onsemi 0:098463de4c5d 1402 ssl->bm_read_index = basic_decrypt(ssl, ssl->bm_all_data + index, read_len);
group-onsemi 0:098463de4c5d 1403 ssl->need_bytes -= ssl->bm_read_index;
group-onsemi 0:098463de4c5d 1404 if(ssl->need_bytes == 0)
group-onsemi 0:098463de4c5d 1405 {
group-onsemi 0:098463de4c5d 1406 ssl->bm_read_index = 0;
group-onsemi 0:098463de4c5d 1407 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1408 return ssl_read(ssl, in_data, len);
group-onsemi 0:098463de4c5d 1409 }
group-onsemi 0:098463de4c5d 1410 }
group-onsemi 0:098463de4c5d 1411 if(len > ssl->bm_read_index)
group-onsemi 0:098463de4c5d 1412 len = ssl->bm_read_index;
group-onsemi 0:098463de4c5d 1413 memcpy(in_data, ssl->bm_all_data+index, len);
group-onsemi 0:098463de4c5d 1414 ssl->bm_index += len;
group-onsemi 0:098463de4c5d 1415 ssl->bm_read_index -= len;
group-onsemi 0:098463de4c5d 1416
group-onsemi 0:098463de4c5d 1417 if(ssl->need_bytes == 0)
group-onsemi 0:098463de4c5d 1418 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1419 if(ssl->bm_index >= 2048)
group-onsemi 0:098463de4c5d 1420 ssl->bm_index = 0;
group-onsemi 0:098463de4c5d 1421 return len;
group-onsemi 0:098463de4c5d 1422 }
group-onsemi 0:098463de4c5d 1423 return 0;
group-onsemi 0:098463de4c5d 1424
group-onsemi 0:098463de4c5d 1425 case PT_ALERT_PROTOCOL:
group-onsemi 0:098463de4c5d 1426 if(basic_read2(ssl, ssl->bm_data, ssl->need_bytes) != ssl->need_bytes)
group-onsemi 0:098463de4c5d 1427 return -1;
group-onsemi 0:098463de4c5d 1428 ssl->need_bytes = basic_decrypt(ssl, ssl->bm_data, ssl->need_bytes);
group-onsemi 0:098463de4c5d 1429 if(ssl->need_bytes < 0)
group-onsemi 0:098463de4c5d 1430 return -1;
group-onsemi 0:098463de4c5d 1431
group-onsemi 0:098463de4c5d 1432 SET_SSL_FLAG(SSL_NEED_RECORD);
group-onsemi 0:098463de4c5d 1433
group-onsemi 0:098463de4c5d 1434 /* return the alert # with alert bit set */
group-onsemi 0:098463de4c5d 1435 if(ssl->bm_data[0] == SSL_ALERT_TYPE_WARNING &&
group-onsemi 0:098463de4c5d 1436 ssl->bm_data[1] == SSL_ALERT_CLOSE_NOTIFY)
group-onsemi 0:098463de4c5d 1437 {
group-onsemi 0:098463de4c5d 1438 send_alert(ssl, SSL_ALERT_CLOSE_NOTIFY);
group-onsemi 0:098463de4c5d 1439 SET_SSL_FLAG(SSL_SENT_CLOSE_NOTIFY);
group-onsemi 0:098463de4c5d 1440 return SSL_CLOSE_NOTIFY;
group-onsemi 0:098463de4c5d 1441 }
group-onsemi 0:098463de4c5d 1442 else
group-onsemi 0:098463de4c5d 1443 {
group-onsemi 0:098463de4c5d 1444 int ret = -ssl->bm_data[1];
group-onsemi 0:098463de4c5d 1445 DISPLAY_ALERT(ssl, -ret);
group-onsemi 0:098463de4c5d 1446 return ret;
group-onsemi 0:098463de4c5d 1447 }
group-onsemi 0:098463de4c5d 1448
group-onsemi 0:098463de4c5d 1449 default:
group-onsemi 0:098463de4c5d 1450 return SSL_ERROR_INVALID_PROT_MSG;
group-onsemi 0:098463de4c5d 1451
group-onsemi 0:098463de4c5d 1452 }
group-onsemi 0:098463de4c5d 1453 }
group-onsemi 0:098463de4c5d 1454
group-onsemi 0:098463de4c5d 1455
group-onsemi 0:098463de4c5d 1456 /**
group-onsemi 0:098463de4c5d 1457 * Do some basic checking of data and then perform the appropriate handshaking.
group-onsemi 0:098463de4c5d 1458 */
group-onsemi 0:098463de4c5d 1459 static int do_handshake(SSL *ssl, uint8_t *buf, int read_len)
group-onsemi 0:098463de4c5d 1460 {
group-onsemi 0:098463de4c5d 1461 uint8_t hs_hdr[SSL_HS_HDR_SIZE];
group-onsemi 0:098463de4c5d 1462 if (IS_SET_SSL_FLAG(SSL_RX_ENCRYPTED))
group-onsemi 0:098463de4c5d 1463 {
group-onsemi 0:098463de4c5d 1464 if(basic_read2(ssl, ssl->bm_data, ssl->need_bytes) != ssl->need_bytes)
group-onsemi 0:098463de4c5d 1465 return -1;
group-onsemi 0:098463de4c5d 1466 ssl->need_bytes = basic_decrypt(ssl, ssl->bm_data, ssl->need_bytes);
group-onsemi 0:098463de4c5d 1467 if(ssl->need_bytes < 0)
group-onsemi 0:098463de4c5d 1468 return -1;
group-onsemi 0:098463de4c5d 1469 buf = ssl->bm_data;
group-onsemi 0:098463de4c5d 1470 }
group-onsemi 0:098463de4c5d 1471 else
group-onsemi 0:098463de4c5d 1472 {
group-onsemi 0:098463de4c5d 1473 if(basic_read2(ssl, hs_hdr, SSL_HS_HDR_SIZE) != SSL_HS_HDR_SIZE)
group-onsemi 0:098463de4c5d 1474 return -1;
group-onsemi 0:098463de4c5d 1475 buf = hs_hdr;
group-onsemi 0:098463de4c5d 1476 }
group-onsemi 0:098463de4c5d 1477
group-onsemi 0:098463de4c5d 1478 int hs_len = (buf[2]<<8) + buf[3];
group-onsemi 0:098463de4c5d 1479 uint8_t handshake_type = buf[0];
group-onsemi 0:098463de4c5d 1480 int ret = SSL_OK;
group-onsemi 0:098463de4c5d 1481 int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
group-onsemi 0:098463de4c5d 1482
group-onsemi 0:098463de4c5d 1483 /* some integrity checking on the handshake */
group-onsemi 0:098463de4c5d 1484 //PARANOIA_CHECK(read_len-SSL_HS_HDR_SIZE, hs_len);
group-onsemi 0:098463de4c5d 1485
group-onsemi 0:098463de4c5d 1486 if (handshake_type != ssl->next_state)
group-onsemi 0:098463de4c5d 1487 {
group-onsemi 0:098463de4c5d 1488 /* handle a special case on the client */
group-onsemi 0:098463de4c5d 1489 if (!is_client || handshake_type != HS_CERT_REQ ||
group-onsemi 0:098463de4c5d 1490 ssl->next_state != HS_SERVER_HELLO_DONE)
group-onsemi 0:098463de4c5d 1491 {
group-onsemi 0:098463de4c5d 1492 return SSL_ERROR_INVALID_HANDSHAKE;
group-onsemi 0:098463de4c5d 1493 }
group-onsemi 0:098463de4c5d 1494 }
group-onsemi 0:098463de4c5d 1495
group-onsemi 0:098463de4c5d 1496 //hs_len += SSL_HS_HDR_SIZE; /* adjust for when adding packets */
group-onsemi 0:098463de4c5d 1497 ssl->bm_index = hs_len+SSL_HS_HDR_SIZE; /* store the size and check later */
group-onsemi 0:098463de4c5d 1498 DISPLAY_STATE(ssl, 0, handshake_type, 0);
group-onsemi 0:098463de4c5d 1499
group-onsemi 0:098463de4c5d 1500 if (handshake_type != HS_CERT_VERIFY && handshake_type != HS_HELLO_REQUEST)
group-onsemi 0:098463de4c5d 1501 {
group-onsemi 0:098463de4c5d 1502 add_packet(ssl, buf, SSL_HS_HDR_SIZE);
group-onsemi 0:098463de4c5d 1503 }
group-onsemi 0:098463de4c5d 1504
group-onsemi 0:098463de4c5d 1505 if(!IS_SET_SSL_FLAG(SSL_RX_ENCRYPTED))
group-onsemi 0:098463de4c5d 1506 {
group-onsemi 0:098463de4c5d 1507 if(hs_len != 0 && handshake_type != HS_CERTIFICATE)
group-onsemi 0:098463de4c5d 1508 {
group-onsemi 0:098463de4c5d 1509 if(basic_read2(ssl, ssl->bm_data, hs_len) != hs_len)
group-onsemi 0:098463de4c5d 1510 return -1;
group-onsemi 0:098463de4c5d 1511 hs_len = basic_decrypt(ssl, ssl->bm_data, hs_len);
group-onsemi 0:098463de4c5d 1512 if(hs_len < 0)
group-onsemi 0:098463de4c5d 1513 return -1;
group-onsemi 0:098463de4c5d 1514
group-onsemi 0:098463de4c5d 1515 buf = ssl->bm_data;
group-onsemi 0:098463de4c5d 1516 if (handshake_type != HS_CERT_VERIFY && handshake_type != HS_HELLO_REQUEST)
group-onsemi 0:098463de4c5d 1517 add_packet(ssl, buf, hs_len);
group-onsemi 0:098463de4c5d 1518 }
group-onsemi 0:098463de4c5d 1519 }
group-onsemi 0:098463de4c5d 1520 else if (handshake_type != HS_CERT_VERIFY && handshake_type != HS_HELLO_REQUEST)
group-onsemi 0:098463de4c5d 1521 add_packet(ssl, ssl->bm_data+SSL_HS_HDR_SIZE, hs_len-SSL_HS_HDR_SIZE);
group-onsemi 0:098463de4c5d 1522
group-onsemi 0:098463de4c5d 1523 #if defined(CONFIG_SSL_ENABLE_CLIENT)
group-onsemi 0:098463de4c5d 1524 ret = is_client ?
group-onsemi 0:098463de4c5d 1525 do_clnt_handshake(ssl, handshake_type, buf, hs_len) :
group-onsemi 0:098463de4c5d 1526 do_svr_handshake(ssl, handshake_type, buf, hs_len);
group-onsemi 0:098463de4c5d 1527 #else
group-onsemi 0:098463de4c5d 1528 ret = do_svr_handshake(ssl, handshake_type, buf, hs_len);
group-onsemi 0:098463de4c5d 1529 #endif
group-onsemi 0:098463de4c5d 1530
group-onsemi 0:098463de4c5d 1531 /* just use recursion to get the rest */
group-onsemi 0:098463de4c5d 1532 //if (hs_len < read_len && ret == SSL_OK)
group-onsemi 0:098463de4c5d 1533 //ret = do_handshake(ssl, &buf[hs_len], read_len-hs_len);
group-onsemi 0:098463de4c5d 1534
group-onsemi 0:098463de4c5d 1535 return ret;
group-onsemi 0:098463de4c5d 1536 }
group-onsemi 0:098463de4c5d 1537
group-onsemi 0:098463de4c5d 1538 /**
group-onsemi 0:098463de4c5d 1539 * Sends the change cipher spec message. We have just read a finished message
group-onsemi 0:098463de4c5d 1540 * from the client.
group-onsemi 0:098463de4c5d 1541 */
group-onsemi 0:098463de4c5d 1542 int send_change_cipher_spec(SSL *ssl)
group-onsemi 0:098463de4c5d 1543 {
group-onsemi 0:098463de4c5d 1544 int ret = send_packet(ssl, PT_CHANGE_CIPHER_SPEC,
group-onsemi 0:098463de4c5d 1545 g_chg_cipher_spec_pkt, sizeof(g_chg_cipher_spec_pkt));
group-onsemi 0:098463de4c5d 1546 SET_SSL_FLAG(SSL_TX_ENCRYPTED);
group-onsemi 0:098463de4c5d 1547
group-onsemi 0:098463de4c5d 1548 if (ret >= 0 && set_key_block(ssl, 1) < 0)
group-onsemi 0:098463de4c5d 1549 ret = SSL_ERROR_INVALID_HANDSHAKE;
group-onsemi 0:098463de4c5d 1550
group-onsemi 0:098463de4c5d 1551 memset(ssl->write_sequence, 0, 8);
group-onsemi 0:098463de4c5d 1552 return ret;
group-onsemi 0:098463de4c5d 1553 }
group-onsemi 0:098463de4c5d 1554
group-onsemi 0:098463de4c5d 1555 /**
group-onsemi 0:098463de4c5d 1556 * Send a "finished" message
group-onsemi 0:098463de4c5d 1557 */
group-onsemi 0:098463de4c5d 1558 int send_finished(SSL *ssl)
group-onsemi 0:098463de4c5d 1559 {
group-onsemi 0:098463de4c5d 1560 uint8_t buf[SSL_FINISHED_HASH_SIZE+4] = {
group-onsemi 0:098463de4c5d 1561 HS_FINISHED, 0, 0, SSL_FINISHED_HASH_SIZE };
group-onsemi 0:098463de4c5d 1562
group-onsemi 0:098463de4c5d 1563 /* now add the finished digest mac (12 bytes) */
group-onsemi 0:098463de4c5d 1564 finished_digest(ssl,
group-onsemi 0:098463de4c5d 1565 IS_SET_SSL_FLAG(SSL_IS_CLIENT) ?
group-onsemi 0:098463de4c5d 1566 client_finished : server_finished, &buf[4]);
group-onsemi 0:098463de4c5d 1567
group-onsemi 0:098463de4c5d 1568 #ifndef CONFIG_SSL_SKELETON_MODE
group-onsemi 0:098463de4c5d 1569 /* store in the session cache */
group-onsemi 0:098463de4c5d 1570 if (!IS_SET_SSL_FLAG(SSL_SESSION_RESUME) && ssl->ssl_ctx->num_sessions)
group-onsemi 0:098463de4c5d 1571 {
group-onsemi 0:098463de4c5d 1572 memcpy(ssl->session->master_secret,
group-onsemi 0:098463de4c5d 1573 ssl->dc->master_secret, SSL_SECRET_SIZE);
group-onsemi 0:098463de4c5d 1574 }
group-onsemi 0:098463de4c5d 1575 #endif
group-onsemi 0:098463de4c5d 1576
group-onsemi 0:098463de4c5d 1577 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
group-onsemi 0:098463de4c5d 1578 buf, SSL_FINISHED_HASH_SIZE+4);
group-onsemi 0:098463de4c5d 1579 }
group-onsemi 0:098463de4c5d 1580
group-onsemi 0:098463de4c5d 1581 /**
group-onsemi 0:098463de4c5d 1582 * Send an alert message.
group-onsemi 0:098463de4c5d 1583 * Return 1 if the alert was an "error".
group-onsemi 0:098463de4c5d 1584 */
group-onsemi 0:098463de4c5d 1585 int send_alert(SSL *ssl, int error_code)
group-onsemi 0:098463de4c5d 1586 {
group-onsemi 0:098463de4c5d 1587 int alert_num = 0;
group-onsemi 0:098463de4c5d 1588 int is_warning = 0;
group-onsemi 0:098463de4c5d 1589 uint8_t buf[2];
group-onsemi 0:098463de4c5d 1590
group-onsemi 0:098463de4c5d 1591 /* Don't bother we're already dead */
group-onsemi 0:098463de4c5d 1592 if (ssl->hs_status == SSL_ERROR_DEAD)
group-onsemi 0:098463de4c5d 1593 {
group-onsemi 0:098463de4c5d 1594 return SSL_ERROR_CONN_LOST;
group-onsemi 0:098463de4c5d 1595 }
group-onsemi 0:098463de4c5d 1596
group-onsemi 0:098463de4c5d 1597 #ifdef CONFIG_SSL_FULL_MODE
group-onsemi 0:098463de4c5d 1598 if (IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
group-onsemi 0:098463de4c5d 1599 ssl_display_error(error_code);
group-onsemi 0:098463de4c5d 1600 #endif
group-onsemi 0:098463de4c5d 1601
group-onsemi 0:098463de4c5d 1602 switch (error_code)
group-onsemi 0:098463de4c5d 1603 {
group-onsemi 0:098463de4c5d 1604 case SSL_ALERT_CLOSE_NOTIFY:
group-onsemi 0:098463de4c5d 1605 is_warning = 1;
group-onsemi 0:098463de4c5d 1606 alert_num = SSL_ALERT_CLOSE_NOTIFY;
group-onsemi 0:098463de4c5d 1607 break;
group-onsemi 0:098463de4c5d 1608
group-onsemi 0:098463de4c5d 1609 case SSL_ERROR_CONN_LOST: /* don't send alert just yet */
group-onsemi 0:098463de4c5d 1610 is_warning = 1;
group-onsemi 0:098463de4c5d 1611 break;
group-onsemi 0:098463de4c5d 1612
group-onsemi 0:098463de4c5d 1613 case SSL_ERROR_INVALID_HANDSHAKE:
group-onsemi 0:098463de4c5d 1614 case SSL_ERROR_INVALID_PROT_MSG:
group-onsemi 0:098463de4c5d 1615 alert_num = SSL_ALERT_HANDSHAKE_FAILURE;
group-onsemi 0:098463de4c5d 1616 break;
group-onsemi 0:098463de4c5d 1617
group-onsemi 0:098463de4c5d 1618 case SSL_ERROR_INVALID_HMAC:
group-onsemi 0:098463de4c5d 1619 case SSL_ERROR_FINISHED_INVALID:
group-onsemi 0:098463de4c5d 1620 alert_num = SSL_ALERT_BAD_RECORD_MAC;
group-onsemi 0:098463de4c5d 1621 break;
group-onsemi 0:098463de4c5d 1622
group-onsemi 0:098463de4c5d 1623 case SSL_ERROR_INVALID_VERSION:
group-onsemi 0:098463de4c5d 1624 alert_num = SSL_ALERT_INVALID_VERSION;
group-onsemi 0:098463de4c5d 1625 break;
group-onsemi 0:098463de4c5d 1626
group-onsemi 0:098463de4c5d 1627 case SSL_ERROR_INVALID_SESSION:
group-onsemi 0:098463de4c5d 1628 case SSL_ERROR_NO_CIPHER:
group-onsemi 0:098463de4c5d 1629 case SSL_ERROR_INVALID_KEY:
group-onsemi 0:098463de4c5d 1630 alert_num = SSL_ALERT_ILLEGAL_PARAMETER;
group-onsemi 0:098463de4c5d 1631 break;
group-onsemi 0:098463de4c5d 1632
group-onsemi 0:098463de4c5d 1633 case SSL_ERROR_BAD_CERTIFICATE:
group-onsemi 0:098463de4c5d 1634 alert_num = SSL_ALERT_BAD_CERTIFICATE;
group-onsemi 0:098463de4c5d 1635 break;
group-onsemi 0:098463de4c5d 1636
group-onsemi 0:098463de4c5d 1637 case SSL_ERROR_NO_CLIENT_RENOG:
group-onsemi 0:098463de4c5d 1638 alert_num = SSL_ALERT_NO_RENEGOTIATION;
group-onsemi 0:098463de4c5d 1639 break;
group-onsemi 0:098463de4c5d 1640
group-onsemi 0:098463de4c5d 1641 default:
group-onsemi 0:098463de4c5d 1642 /* a catch-all for any badly verified certificates */
group-onsemi 0:098463de4c5d 1643 alert_num = (error_code <= SSL_X509_OFFSET) ?
group-onsemi 0:098463de4c5d 1644 SSL_ALERT_BAD_CERTIFICATE : SSL_ALERT_UNEXPECTED_MESSAGE;
group-onsemi 0:098463de4c5d 1645 break;
group-onsemi 0:098463de4c5d 1646 }
group-onsemi 0:098463de4c5d 1647
group-onsemi 0:098463de4c5d 1648 buf[0] = is_warning ? 1 : 2;
group-onsemi 0:098463de4c5d 1649 buf[1] = alert_num;
group-onsemi 0:098463de4c5d 1650
group-onsemi 0:098463de4c5d 1651 send_packet(ssl, PT_ALERT_PROTOCOL, buf, sizeof(buf));
group-onsemi 0:098463de4c5d 1652 DISPLAY_ALERT(ssl, alert_num);
group-onsemi 0:098463de4c5d 1653 return is_warning ? 0 : 1;
group-onsemi 0:098463de4c5d 1654 }
group-onsemi 0:098463de4c5d 1655
group-onsemi 0:098463de4c5d 1656 /**
group-onsemi 0:098463de4c5d 1657 * Process a client finished message.
group-onsemi 0:098463de4c5d 1658 */
group-onsemi 0:098463de4c5d 1659 int process_finished(SSL *ssl, uint8_t *buf, int hs_len)
group-onsemi 0:098463de4c5d 1660 {
group-onsemi 0:098463de4c5d 1661 int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
group-onsemi 0:098463de4c5d 1662 int ret = SSL_OK;
group-onsemi 0:098463de4c5d 1663 int resume = IS_SET_SSL_FLAG(SSL_SESSION_RESUME);
group-onsemi 0:098463de4c5d 1664
group-onsemi 0:098463de4c5d 1665 PARANOIA_CHECK(ssl->bm_index, SSL_FINISHED_HASH_SIZE);
group-onsemi 0:098463de4c5d 1666
group-onsemi 0:098463de4c5d 1667 /* check that we all work before we continue */
group-onsemi 0:098463de4c5d 1668 if (memcmp(ssl->dc->final_finish_mac, &buf[4], SSL_FINISHED_HASH_SIZE))
group-onsemi 0:098463de4c5d 1669 {
group-onsemi 0:098463de4c5d 1670 return SSL_ERROR_FINISHED_INVALID;
group-onsemi 0:098463de4c5d 1671 }
group-onsemi 0:098463de4c5d 1672 if ((!is_client && !resume) || (is_client && resume))
group-onsemi 0:098463de4c5d 1673 {
group-onsemi 0:098463de4c5d 1674 if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
group-onsemi 0:098463de4c5d 1675 ret = send_finished(ssl);
group-onsemi 0:098463de4c5d 1676 }
group-onsemi 0:098463de4c5d 1677
group-onsemi 0:098463de4c5d 1678 /* if we ever renegotiate */
group-onsemi 0:098463de4c5d 1679 ssl->next_state = is_client ? HS_HELLO_REQUEST : HS_CLIENT_HELLO;
group-onsemi 0:098463de4c5d 1680 ssl->hs_status = ret; /* set the final handshake status */
group-onsemi 0:098463de4c5d 1681 error:
group-onsemi 0:098463de4c5d 1682 return ret;
group-onsemi 0:098463de4c5d 1683 }
group-onsemi 0:098463de4c5d 1684
group-onsemi 0:098463de4c5d 1685 /**
group-onsemi 0:098463de4c5d 1686 * Send a certificate.
group-onsemi 0:098463de4c5d 1687 */
group-onsemi 0:098463de4c5d 1688 int send_certificate(SSL *ssl)
group-onsemi 0:098463de4c5d 1689 {
group-onsemi 0:098463de4c5d 1690 int i = 0;
group-onsemi 0:098463de4c5d 1691 uint8_t *buf = ssl->bm_data;
group-onsemi 0:098463de4c5d 1692 int offset = 7;
group-onsemi 0:098463de4c5d 1693 int chain_length;
group-onsemi 0:098463de4c5d 1694
group-onsemi 0:098463de4c5d 1695 buf[0] = HS_CERTIFICATE;
group-onsemi 0:098463de4c5d 1696 buf[1] = 0;
group-onsemi 0:098463de4c5d 1697 buf[4] = 0;
group-onsemi 0:098463de4c5d 1698
group-onsemi 0:098463de4c5d 1699 while (i < ssl->ssl_ctx->chain_length)
group-onsemi 0:098463de4c5d 1700 {
group-onsemi 0:098463de4c5d 1701 SSL_CERT *cert = &ssl->ssl_ctx->certs[i];
group-onsemi 0:098463de4c5d 1702 buf[offset++] = 0;
group-onsemi 0:098463de4c5d 1703 buf[offset++] = cert->size >> 8; /* cert 1 length */
group-onsemi 0:098463de4c5d 1704 buf[offset++] = cert->size & 0xff;
group-onsemi 0:098463de4c5d 1705 memcpy(&buf[offset], cert->buf, cert->size);
group-onsemi 0:098463de4c5d 1706 offset += cert->size;
group-onsemi 0:098463de4c5d 1707 i++;
group-onsemi 0:098463de4c5d 1708 }
group-onsemi 0:098463de4c5d 1709
group-onsemi 0:098463de4c5d 1710 chain_length = offset - 7;
group-onsemi 0:098463de4c5d 1711 buf[5] = chain_length >> 8; /* cert chain length */
group-onsemi 0:098463de4c5d 1712 buf[6] = chain_length & 0xff;
group-onsemi 0:098463de4c5d 1713 chain_length += 3;
group-onsemi 0:098463de4c5d 1714 buf[2] = chain_length >> 8; /* handshake length */
group-onsemi 0:098463de4c5d 1715 buf[3] = chain_length & 0xff;
group-onsemi 0:098463de4c5d 1716 ssl->bm_index = offset;
group-onsemi 0:098463de4c5d 1717 return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
group-onsemi 0:098463de4c5d 1718 }
group-onsemi 0:098463de4c5d 1719
group-onsemi 0:098463de4c5d 1720 /**
group-onsemi 0:098463de4c5d 1721 * Create a blob of memory that we'll get rid of once the handshake is
group-onsemi 0:098463de4c5d 1722 * complete.
group-onsemi 0:098463de4c5d 1723 */
group-onsemi 0:098463de4c5d 1724 void disposable_new(SSL *ssl)
group-onsemi 0:098463de4c5d 1725 {
group-onsemi 0:098463de4c5d 1726 if (ssl->dc == NULL)
group-onsemi 0:098463de4c5d 1727 {
group-onsemi 0:098463de4c5d 1728 ssl->dc = (DISPOSABLE_CTX *)calloc(1, sizeof(DISPOSABLE_CTX));
group-onsemi 0:098463de4c5d 1729 memset(ssl->dc->key_block, 0, MAX_KEYBLOCK_SIZE);
group-onsemi 0:098463de4c5d 1730 MD5_Init(&ssl->dc->md5_ctx);
group-onsemi 0:098463de4c5d 1731 SHA1_Init(&ssl->dc->sha1_ctx);
group-onsemi 0:098463de4c5d 1732 }
group-onsemi 0:098463de4c5d 1733 }
group-onsemi 0:098463de4c5d 1734
group-onsemi 0:098463de4c5d 1735 /**
group-onsemi 0:098463de4c5d 1736 * Remove the temporary blob of memory.
group-onsemi 0:098463de4c5d 1737 */
group-onsemi 0:098463de4c5d 1738 void disposable_free(SSL *ssl)
group-onsemi 0:098463de4c5d 1739 {
group-onsemi 0:098463de4c5d 1740 if (ssl->dc)
group-onsemi 0:098463de4c5d 1741 {
group-onsemi 0:098463de4c5d 1742 //free(ssl->dc->key_block);
group-onsemi 0:098463de4c5d 1743 memset(ssl->dc, 0, sizeof(DISPOSABLE_CTX));
group-onsemi 0:098463de4c5d 1744 free(ssl->dc);
group-onsemi 0:098463de4c5d 1745 ssl->dc = NULL;
group-onsemi 0:098463de4c5d 1746 }
group-onsemi 0:098463de4c5d 1747
group-onsemi 0:098463de4c5d 1748 }
group-onsemi 0:098463de4c5d 1749
group-onsemi 0:098463de4c5d 1750 #ifndef CONFIG_SSL_SKELETON_MODE /* no session resumption in this mode */
group-onsemi 0:098463de4c5d 1751 /**
group-onsemi 0:098463de4c5d 1752 * Find if an existing session has the same session id. If so, use the
group-onsemi 0:098463de4c5d 1753 * master secret from this session for session resumption.
group-onsemi 0:098463de4c5d 1754 */
group-onsemi 0:098463de4c5d 1755 SSL_SESSION *ssl_session_update(int max_sessions, SSL_SESSION *ssl_sessions[],
group-onsemi 0:098463de4c5d 1756 SSL *ssl, const uint8_t *session_id)
group-onsemi 0:098463de4c5d 1757 {
group-onsemi 0:098463de4c5d 1758 time_t tm = time(NULL);
group-onsemi 0:098463de4c5d 1759 time_t oldest_sess_time = tm;
group-onsemi 0:098463de4c5d 1760 SSL_SESSION *oldest_sess = NULL;
group-onsemi 0:098463de4c5d 1761 int i;
group-onsemi 0:098463de4c5d 1762
group-onsemi 0:098463de4c5d 1763 /* no sessions? Then bail */
group-onsemi 0:098463de4c5d 1764 if (max_sessions == 0)
group-onsemi 0:098463de4c5d 1765 return NULL;
group-onsemi 0:098463de4c5d 1766
group-onsemi 0:098463de4c5d 1767 SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1768 if (session_id)
group-onsemi 0:098463de4c5d 1769 {
group-onsemi 0:098463de4c5d 1770 for (i = 0; i < max_sessions; i++)
group-onsemi 0:098463de4c5d 1771 {
group-onsemi 0:098463de4c5d 1772 if (ssl_sessions[i])
group-onsemi 0:098463de4c5d 1773 {
group-onsemi 0:098463de4c5d 1774 /* kill off any expired sessions (including those in
group-onsemi 0:098463de4c5d 1775 the future) */
group-onsemi 0:098463de4c5d 1776 if ((tm > ssl_sessions[i]->conn_time + SSL_EXPIRY_TIME) ||
group-onsemi 0:098463de4c5d 1777 (tm < ssl_sessions[i]->conn_time))
group-onsemi 0:098463de4c5d 1778 {
group-onsemi 0:098463de4c5d 1779 session_free(ssl_sessions, i);
group-onsemi 0:098463de4c5d 1780 continue;
group-onsemi 0:098463de4c5d 1781 }
group-onsemi 0:098463de4c5d 1782
group-onsemi 0:098463de4c5d 1783 /* if the session id matches, it must still be less than
group-onsemi 0:098463de4c5d 1784 the expiry time */
group-onsemi 0:098463de4c5d 1785 if (memcmp(ssl_sessions[i]->session_id, session_id,
group-onsemi 0:098463de4c5d 1786 SSL_SESSION_ID_SIZE) == 0)
group-onsemi 0:098463de4c5d 1787 {
group-onsemi 0:098463de4c5d 1788 ssl->session_index = i;
group-onsemi 0:098463de4c5d 1789 memcpy(ssl->dc->master_secret,
group-onsemi 0:098463de4c5d 1790 ssl_sessions[i]->master_secret, SSL_SECRET_SIZE);
group-onsemi 0:098463de4c5d 1791 SET_SSL_FLAG(SSL_SESSION_RESUME);
group-onsemi 0:098463de4c5d 1792 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1793 return ssl_sessions[i]; /* a session was found */
group-onsemi 0:098463de4c5d 1794 }
group-onsemi 0:098463de4c5d 1795 }
group-onsemi 0:098463de4c5d 1796 }
group-onsemi 0:098463de4c5d 1797 }
group-onsemi 0:098463de4c5d 1798
group-onsemi 0:098463de4c5d 1799 /* If we've got here, no matching session was found - so create one */
group-onsemi 0:098463de4c5d 1800 for (i = 0; i < max_sessions; i++)
group-onsemi 0:098463de4c5d 1801 {
group-onsemi 0:098463de4c5d 1802 if (ssl_sessions[i] == NULL)
group-onsemi 0:098463de4c5d 1803 {
group-onsemi 0:098463de4c5d 1804 /* perfect, this will do */
group-onsemi 0:098463de4c5d 1805 ssl_sessions[i] = (SSL_SESSION *)calloc(1, sizeof(SSL_SESSION));
group-onsemi 0:098463de4c5d 1806 ssl_sessions[i]->conn_time = tm;
group-onsemi 0:098463de4c5d 1807 ssl->session_index = i;
group-onsemi 0:098463de4c5d 1808 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1809 return ssl_sessions[i]; /* return the session object */
group-onsemi 0:098463de4c5d 1810 }
group-onsemi 0:098463de4c5d 1811 else if (ssl_sessions[i]->conn_time <= oldest_sess_time)
group-onsemi 0:098463de4c5d 1812 {
group-onsemi 0:098463de4c5d 1813 /* find the oldest session */
group-onsemi 0:098463de4c5d 1814 oldest_sess_time = ssl_sessions[i]->conn_time;
group-onsemi 0:098463de4c5d 1815 oldest_sess = ssl_sessions[i];
group-onsemi 0:098463de4c5d 1816 ssl->session_index = i;
group-onsemi 0:098463de4c5d 1817 }
group-onsemi 0:098463de4c5d 1818 }
group-onsemi 0:098463de4c5d 1819
group-onsemi 0:098463de4c5d 1820 /* ok, we've used up all of our sessions. So blow the oldest session away */
group-onsemi 0:098463de4c5d 1821 oldest_sess->conn_time = tm;
group-onsemi 0:098463de4c5d 1822 memset(oldest_sess->session_id, 0, sizeof(SSL_SESSION_ID_SIZE));
group-onsemi 0:098463de4c5d 1823 memset(oldest_sess->master_secret, 0, sizeof(SSL_SECRET_SIZE));
group-onsemi 0:098463de4c5d 1824 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1825 return oldest_sess;
group-onsemi 0:098463de4c5d 1826 }
group-onsemi 0:098463de4c5d 1827
group-onsemi 0:098463de4c5d 1828 /**
group-onsemi 0:098463de4c5d 1829 * Free an existing session.
group-onsemi 0:098463de4c5d 1830 */
group-onsemi 0:098463de4c5d 1831 static void session_free(SSL_SESSION *ssl_sessions[], int sess_index)
group-onsemi 0:098463de4c5d 1832 {
group-onsemi 0:098463de4c5d 1833 if (ssl_sessions[sess_index])
group-onsemi 0:098463de4c5d 1834 {
group-onsemi 0:098463de4c5d 1835 free(ssl_sessions[sess_index]);
group-onsemi 0:098463de4c5d 1836 ssl_sessions[sess_index] = NULL;
group-onsemi 0:098463de4c5d 1837 }
group-onsemi 0:098463de4c5d 1838 }
group-onsemi 0:098463de4c5d 1839
group-onsemi 0:098463de4c5d 1840 /**
group-onsemi 0:098463de4c5d 1841 * This ssl object doesn't want this session anymore.
group-onsemi 0:098463de4c5d 1842 */
group-onsemi 0:098463de4c5d 1843 void kill_ssl_session(SSL_SESSION **ssl_sessions, SSL *ssl)
group-onsemi 0:098463de4c5d 1844 {
group-onsemi 0:098463de4c5d 1845 SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1846
group-onsemi 0:098463de4c5d 1847 if (ssl->ssl_ctx->num_sessions)
group-onsemi 0:098463de4c5d 1848 {
group-onsemi 0:098463de4c5d 1849 session_free(ssl_sessions, ssl->session_index);
group-onsemi 0:098463de4c5d 1850 ssl->session = NULL;
group-onsemi 0:098463de4c5d 1851 }
group-onsemi 0:098463de4c5d 1852
group-onsemi 0:098463de4c5d 1853 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1854 }
group-onsemi 0:098463de4c5d 1855 #endif /* CONFIG_SSL_SKELETON_MODE */
group-onsemi 0:098463de4c5d 1856
group-onsemi 0:098463de4c5d 1857 /*
group-onsemi 0:098463de4c5d 1858 * Get the session id for a handshake. This will be a 32 byte sequence.
group-onsemi 0:098463de4c5d 1859 */
group-onsemi 0:098463de4c5d 1860 EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl)
group-onsemi 0:098463de4c5d 1861 {
group-onsemi 0:098463de4c5d 1862 return ssl->session_id;
group-onsemi 0:098463de4c5d 1863 }
group-onsemi 0:098463de4c5d 1864
group-onsemi 0:098463de4c5d 1865 /*
group-onsemi 0:098463de4c5d 1866 * Get the session id size for a handshake.
group-onsemi 0:098463de4c5d 1867 */
group-onsemi 0:098463de4c5d 1868 EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl)
group-onsemi 0:098463de4c5d 1869 {
group-onsemi 0:098463de4c5d 1870 return ssl->sess_id_size;
group-onsemi 0:098463de4c5d 1871 }
group-onsemi 0:098463de4c5d 1872
group-onsemi 0:098463de4c5d 1873 /*
group-onsemi 0:098463de4c5d 1874 * Return the cipher id (in the SSL form).
group-onsemi 0:098463de4c5d 1875 */
group-onsemi 0:098463de4c5d 1876 EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl)
group-onsemi 0:098463de4c5d 1877 {
group-onsemi 0:098463de4c5d 1878 return ssl->cipher;
group-onsemi 0:098463de4c5d 1879 }
group-onsemi 0:098463de4c5d 1880
group-onsemi 0:098463de4c5d 1881 /*
group-onsemi 0:098463de4c5d 1882 * Return the status of the handshake.
group-onsemi 0:098463de4c5d 1883 */
group-onsemi 0:098463de4c5d 1884 EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl)
group-onsemi 0:098463de4c5d 1885 {
group-onsemi 0:098463de4c5d 1886 return ssl->hs_status;
group-onsemi 0:098463de4c5d 1887 }
group-onsemi 0:098463de4c5d 1888
group-onsemi 0:098463de4c5d 1889 /*
group-onsemi 0:098463de4c5d 1890 * Retrieve various parameters about the SSL engine.
group-onsemi 0:098463de4c5d 1891 */
group-onsemi 0:098463de4c5d 1892 EXP_FUNC int STDCALL ssl_get_config(int offset)
group-onsemi 0:098463de4c5d 1893 {
group-onsemi 0:098463de4c5d 1894 switch (offset)
group-onsemi 0:098463de4c5d 1895 {
group-onsemi 0:098463de4c5d 1896 /* return the appropriate build mode */
group-onsemi 0:098463de4c5d 1897 case SSL_BUILD_MODE:
group-onsemi 0:098463de4c5d 1898 #if defined(CONFIG_SSL_FULL_MODE)
group-onsemi 0:098463de4c5d 1899 return SSL_BUILD_FULL_MODE;
group-onsemi 0:098463de4c5d 1900 #elif defined(CONFIG_SSL_ENABLE_CLIENT)
group-onsemi 0:098463de4c5d 1901 return SSL_BUILD_ENABLE_CLIENT;
group-onsemi 0:098463de4c5d 1902 #elif defined(CONFIG_ENABLE_VERIFICATION)
group-onsemi 0:098463de4c5d 1903 return SSL_BUILD_ENABLE_VERIFICATION;
group-onsemi 0:098463de4c5d 1904 #elif defined(CONFIG_SSL_SERVER_ONLY )
group-onsemi 0:098463de4c5d 1905 return SSL_BUILD_SERVER_ONLY;
group-onsemi 0:098463de4c5d 1906 #else
group-onsemi 0:098463de4c5d 1907 return SSL_BUILD_SKELETON_MODE;
group-onsemi 0:098463de4c5d 1908 #endif
group-onsemi 0:098463de4c5d 1909
group-onsemi 0:098463de4c5d 1910 case SSL_MAX_CERT_CFG_OFFSET:
group-onsemi 0:098463de4c5d 1911 return CONFIG_SSL_MAX_CERTS;
group-onsemi 0:098463de4c5d 1912
group-onsemi 0:098463de4c5d 1913 #ifdef CONFIG_SSL_CERT_VERIFICATION
group-onsemi 0:098463de4c5d 1914 case SSL_MAX_CA_CERT_CFG_OFFSET:
group-onsemi 0:098463de4c5d 1915 return CONFIG_X509_MAX_CA_CERTS;
group-onsemi 0:098463de4c5d 1916 #endif
group-onsemi 0:098463de4c5d 1917 #ifdef CONFIG_SSL_HAS_PEM
group-onsemi 0:098463de4c5d 1918 case SSL_HAS_PEM:
group-onsemi 0:098463de4c5d 1919 return 1;
group-onsemi 0:098463de4c5d 1920 #endif
group-onsemi 0:098463de4c5d 1921 default:
group-onsemi 0:098463de4c5d 1922 return 0;
group-onsemi 0:098463de4c5d 1923 }
group-onsemi 0:098463de4c5d 1924 }
group-onsemi 0:098463de4c5d 1925
group-onsemi 0:098463de4c5d 1926 #ifdef CONFIG_SSL_CERT_VERIFICATION
group-onsemi 0:098463de4c5d 1927 /**
group-onsemi 0:098463de4c5d 1928 * Authenticate a received certificate.
group-onsemi 0:098463de4c5d 1929 */
group-onsemi 0:098463de4c5d 1930 EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
group-onsemi 0:098463de4c5d 1931 {
group-onsemi 0:098463de4c5d 1932 int ret;
group-onsemi 0:098463de4c5d 1933 SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1934 ret = x509_verify(ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
group-onsemi 0:098463de4c5d 1935 SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
group-onsemi 0:098463de4c5d 1936
group-onsemi 0:098463de4c5d 1937 if (ret) /* modify into an SSL error type */
group-onsemi 0:098463de4c5d 1938 {
group-onsemi 0:098463de4c5d 1939 ret = SSL_X509_ERROR(ret);
group-onsemi 0:098463de4c5d 1940 }
group-onsemi 0:098463de4c5d 1941
group-onsemi 0:098463de4c5d 1942 return ret;
group-onsemi 0:098463de4c5d 1943 }
group-onsemi 0:098463de4c5d 1944
group-onsemi 0:098463de4c5d 1945 /**
group-onsemi 0:098463de4c5d 1946 * Process a certificate message.
group-onsemi 0:098463de4c5d 1947 */
group-onsemi 0:098463de4c5d 1948 int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
group-onsemi 0:098463de4c5d 1949 {
group-onsemi 0:098463de4c5d 1950 int ret = SSL_OK;
group-onsemi 0:098463de4c5d 1951
group-onsemi 0:098463de4c5d 1952 uint8_t cert_hdr[3];
group-onsemi 0:098463de4c5d 1953 if(basic_read2(ssl, cert_hdr, 3) != 3)
group-onsemi 0:098463de4c5d 1954 {
group-onsemi 0:098463de4c5d 1955 ret = SSL_NOT_OK;
group-onsemi 0:098463de4c5d 1956 return ret;
group-onsemi 0:098463de4c5d 1957 }
group-onsemi 0:098463de4c5d 1958
group-onsemi 0:098463de4c5d 1959 add_packet(ssl, cert_hdr, 3);
group-onsemi 0:098463de4c5d 1960 int len = 5;
group-onsemi 0:098463de4c5d 1961 int pkt_size = ssl->bm_index;
group-onsemi 0:098463de4c5d 1962 int cert_size;
group-onsemi 0:098463de4c5d 1963 int total_cert_size = (cert_hdr[1]<<8) + cert_hdr[2];
group-onsemi 0:098463de4c5d 1964 int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
group-onsemi 0:098463de4c5d 1965 X509_CTX **chain = x509_ctx;
group-onsemi 0:098463de4c5d 1966 len += 2;
group-onsemi 0:098463de4c5d 1967 PARANOIA_CHECK(total_cert_size, 3);
group-onsemi 0:098463de4c5d 1968
group-onsemi 0:098463de4c5d 1969 while (len < total_cert_size)
group-onsemi 0:098463de4c5d 1970 {
group-onsemi 0:098463de4c5d 1971
group-onsemi 0:098463de4c5d 1972 if(basic_read2(ssl, cert_hdr, 3) != 3)
group-onsemi 0:098463de4c5d 1973 {
group-onsemi 0:098463de4c5d 1974 ret = SSL_NOT_OK;
group-onsemi 0:098463de4c5d 1975 return ret;
group-onsemi 0:098463de4c5d 1976 }
group-onsemi 0:098463de4c5d 1977
group-onsemi 0:098463de4c5d 1978 add_packet(ssl, cert_hdr, 3);
group-onsemi 0:098463de4c5d 1979
group-onsemi 0:098463de4c5d 1980 cert_size = (cert_hdr[1]<<8) + cert_hdr[2];
group-onsemi 0:098463de4c5d 1981 if(cert_size > RT_MAX_PLAIN_LENGTH)
group-onsemi 0:098463de4c5d 1982 {
group-onsemi 0:098463de4c5d 1983 ret = SSL_NOT_OK;
group-onsemi 0:098463de4c5d 1984 return ret;
group-onsemi 0:098463de4c5d 1985 }
group-onsemi 0:098463de4c5d 1986
group-onsemi 0:098463de4c5d 1987 len += 3;
group-onsemi 0:098463de4c5d 1988
group-onsemi 0:098463de4c5d 1989 if(basic_read2(ssl, ssl->bm_data, cert_size) != cert_size)
group-onsemi 0:098463de4c5d 1990 {
group-onsemi 0:098463de4c5d 1991 return SSL_NOT_OK;
group-onsemi 0:098463de4c5d 1992 }
group-onsemi 0:098463de4c5d 1993
group-onsemi 0:098463de4c5d 1994 add_packet(ssl, ssl->bm_data, cert_size);
group-onsemi 0:098463de4c5d 1995
group-onsemi 0:098463de4c5d 1996 if (x509_new(ssl->bm_data, NULL, chain))
group-onsemi 0:098463de4c5d 1997 {
group-onsemi 0:098463de4c5d 1998 ret = SSL_ERROR_BAD_CERTIFICATE;
group-onsemi 0:098463de4c5d 1999 goto error;
group-onsemi 0:098463de4c5d 2000 }
group-onsemi 0:098463de4c5d 2001
group-onsemi 0:098463de4c5d 2002 chain = &((*chain)->next);
group-onsemi 0:098463de4c5d 2003 len += cert_size;
group-onsemi 0:098463de4c5d 2004 }
group-onsemi 0:098463de4c5d 2005 PARANOIA_CHECK(pkt_size, len);
group-onsemi 0:098463de4c5d 2006
group-onsemi 0:098463de4c5d 2007 /* if we are client we can do the verify now or later */
group-onsemi 0:098463de4c5d 2008 if (is_client && !IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER))
group-onsemi 0:098463de4c5d 2009 {
group-onsemi 0:098463de4c5d 2010 ret = ssl_verify_cert(ssl);
group-onsemi 0:098463de4c5d 2011 }
group-onsemi 0:098463de4c5d 2012
group-onsemi 0:098463de4c5d 2013 ssl->next_state = is_client ? HS_SERVER_HELLO_DONE : HS_CLIENT_KEY_XCHG;
group-onsemi 0:098463de4c5d 2014 ssl->dc->bm_proc_index += len;
group-onsemi 0:098463de4c5d 2015 error:
group-onsemi 0:098463de4c5d 2016
group-onsemi 0:098463de4c5d 2017 return ret;
group-onsemi 0:098463de4c5d 2018 }
group-onsemi 0:098463de4c5d 2019
group-onsemi 0:098463de4c5d 2020 #endif /* CONFIG_SSL_CERT_VERIFICATION */
group-onsemi 0:098463de4c5d 2021
group-onsemi 0:098463de4c5d 2022 /**
group-onsemi 0:098463de4c5d 2023 * Debugging routine to display SSL handshaking stuff.
group-onsemi 0:098463de4c5d 2024 */
group-onsemi 0:098463de4c5d 2025 #ifdef CONFIG_SSL_FULL_MODE
group-onsemi 0:098463de4c5d 2026 /**
group-onsemi 0:098463de4c5d 2027 * Debugging routine to display SSL states.
group-onsemi 0:098463de4c5d 2028 */
group-onsemi 0:098463de4c5d 2029 void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok)
group-onsemi 0:098463de4c5d 2030 {
group-onsemi 0:098463de4c5d 2031 const char *str;
group-onsemi 0:098463de4c5d 2032
group-onsemi 0:098463de4c5d 2033 if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
group-onsemi 0:098463de4c5d 2034 return;
group-onsemi 0:098463de4c5d 2035
group-onsemi 0:098463de4c5d 2036 printf(not_ok ? "Error - invalid State:\t" : "State:\t");
group-onsemi 0:098463de4c5d 2037 printf(is_send ? "sending " : "receiving ");
group-onsemi 0:098463de4c5d 2038
group-onsemi 0:098463de4c5d 2039 switch (state)
group-onsemi 0:098463de4c5d 2040 {
group-onsemi 0:098463de4c5d 2041 case HS_HELLO_REQUEST:
group-onsemi 0:098463de4c5d 2042 str = "Hello Request (0)";
group-onsemi 0:098463de4c5d 2043 break;
group-onsemi 0:098463de4c5d 2044
group-onsemi 0:098463de4c5d 2045 case HS_CLIENT_HELLO:
group-onsemi 0:098463de4c5d 2046 str = "Client Hello (1)";
group-onsemi 0:098463de4c5d 2047 break;
group-onsemi 0:098463de4c5d 2048
group-onsemi 0:098463de4c5d 2049 case HS_SERVER_HELLO:
group-onsemi 0:098463de4c5d 2050 str = "Server Hello (2)";
group-onsemi 0:098463de4c5d 2051 break;
group-onsemi 0:098463de4c5d 2052
group-onsemi 0:098463de4c5d 2053 case HS_CERTIFICATE:
group-onsemi 0:098463de4c5d 2054 str = "Certificate (11)";
group-onsemi 0:098463de4c5d 2055 break;
group-onsemi 0:098463de4c5d 2056
group-onsemi 0:098463de4c5d 2057 case HS_SERVER_KEY_XCHG:
group-onsemi 0:098463de4c5d 2058 str = "Certificate Request (12)";
group-onsemi 0:098463de4c5d 2059 break;
group-onsemi 0:098463de4c5d 2060
group-onsemi 0:098463de4c5d 2061 case HS_CERT_REQ:
group-onsemi 0:098463de4c5d 2062 str = "Certificate Request (13)";
group-onsemi 0:098463de4c5d 2063 break;
group-onsemi 0:098463de4c5d 2064
group-onsemi 0:098463de4c5d 2065 case HS_SERVER_HELLO_DONE:
group-onsemi 0:098463de4c5d 2066 str = "Server Hello Done (14)";
group-onsemi 0:098463de4c5d 2067 break;
group-onsemi 0:098463de4c5d 2068
group-onsemi 0:098463de4c5d 2069 case HS_CERT_VERIFY:
group-onsemi 0:098463de4c5d 2070 str = "Certificate Verify (15)";
group-onsemi 0:098463de4c5d 2071 break;
group-onsemi 0:098463de4c5d 2072
group-onsemi 0:098463de4c5d 2073 case HS_CLIENT_KEY_XCHG:
group-onsemi 0:098463de4c5d 2074 str = "Client Key Exchange (16)";
group-onsemi 0:098463de4c5d 2075 break;
group-onsemi 0:098463de4c5d 2076
group-onsemi 0:098463de4c5d 2077 case HS_FINISHED:
group-onsemi 0:098463de4c5d 2078 str = "Finished (16)";
group-onsemi 0:098463de4c5d 2079 break;
group-onsemi 0:098463de4c5d 2080
group-onsemi 0:098463de4c5d 2081 default:
group-onsemi 0:098463de4c5d 2082 str = "Error (Unknown)";
group-onsemi 0:098463de4c5d 2083
group-onsemi 0:098463de4c5d 2084 break;
group-onsemi 0:098463de4c5d 2085 }
group-onsemi 0:098463de4c5d 2086
group-onsemi 0:098463de4c5d 2087 printf("%s\r\n", str);
group-onsemi 0:098463de4c5d 2088 TTY_FLUSH();
group-onsemi 0:098463de4c5d 2089 }
group-onsemi 0:098463de4c5d 2090
group-onsemi 0:098463de4c5d 2091 /**
group-onsemi 0:098463de4c5d 2092 * Debugging routine to display RSA objects
group-onsemi 0:098463de4c5d 2093 */
group-onsemi 0:098463de4c5d 2094 void DISPLAY_RSA(SSL *ssl, const RSA_CTX *rsa_ctx)
group-onsemi 0:098463de4c5d 2095 {
group-onsemi 0:098463de4c5d 2096 if (!IS_SET_SSL_FLAG(SSL_DISPLAY_RSA))
group-onsemi 0:098463de4c5d 2097 return;
group-onsemi 0:098463de4c5d 2098
group-onsemi 0:098463de4c5d 2099 RSA_print(rsa_ctx);
group-onsemi 0:098463de4c5d 2100 TTY_FLUSH();
group-onsemi 0:098463de4c5d 2101 }
group-onsemi 0:098463de4c5d 2102
group-onsemi 0:098463de4c5d 2103 /**
group-onsemi 0:098463de4c5d 2104 * Debugging routine to display SSL handshaking bytes.
group-onsemi 0:098463de4c5d 2105 */
group-onsemi 0:098463de4c5d 2106 void DISPLAY_BYTES(SSL *ssl, const char *format,
group-onsemi 0:098463de4c5d 2107 const uint8_t *data, int size, ...)
group-onsemi 0:098463de4c5d 2108 {
group-onsemi 0:098463de4c5d 2109 va_list(ap);
group-onsemi 0:098463de4c5d 2110
group-onsemi 0:098463de4c5d 2111 if (!IS_SET_SSL_FLAG(SSL_DISPLAY_BYTES))
group-onsemi 0:098463de4c5d 2112 return;
group-onsemi 0:098463de4c5d 2113
group-onsemi 0:098463de4c5d 2114 va_start(ap, size);
group-onsemi 0:098463de4c5d 2115 print_blob(format, data, size, va_arg(ap, char *));
group-onsemi 0:098463de4c5d 2116 va_end(ap);
group-onsemi 0:098463de4c5d 2117 TTY_FLUSH();
group-onsemi 0:098463de4c5d 2118 }
group-onsemi 0:098463de4c5d 2119
group-onsemi 0:098463de4c5d 2120 /**
group-onsemi 0:098463de4c5d 2121 * Debugging routine to display SSL handshaking errors.
group-onsemi 0:098463de4c5d 2122 */
group-onsemi 0:098463de4c5d 2123 EXP_FUNC void STDCALL ssl_display_error(int error_code)
group-onsemi 0:098463de4c5d 2124 {
group-onsemi 0:098463de4c5d 2125 if (error_code == SSL_OK)
group-onsemi 0:098463de4c5d 2126 return;
group-onsemi 0:098463de4c5d 2127
group-onsemi 0:098463de4c5d 2128 printf("Error: ");
group-onsemi 0:098463de4c5d 2129
group-onsemi 0:098463de4c5d 2130 /* X509 error? */
group-onsemi 0:098463de4c5d 2131 if (error_code < SSL_X509_OFFSET)
group-onsemi 0:098463de4c5d 2132 {
group-onsemi 0:098463de4c5d 2133 printf("%s\r\n", x509_display_error(error_code - SSL_X509_OFFSET));
group-onsemi 0:098463de4c5d 2134 return;
group-onsemi 0:098463de4c5d 2135 }
group-onsemi 0:098463de4c5d 2136
group-onsemi 0:098463de4c5d 2137 /* SSL alert error code */
group-onsemi 0:098463de4c5d 2138 if (error_code > SSL_ERROR_CONN_LOST)
group-onsemi 0:098463de4c5d 2139 {
group-onsemi 0:098463de4c5d 2140 printf("SSL error %d\n", -error_code);
group-onsemi 0:098463de4c5d 2141 return;
group-onsemi 0:098463de4c5d 2142 }
group-onsemi 0:098463de4c5d 2143
group-onsemi 0:098463de4c5d 2144 switch (error_code)
group-onsemi 0:098463de4c5d 2145 {
group-onsemi 0:098463de4c5d 2146 case SSL_ERROR_DEAD:
group-onsemi 0:098463de4c5d 2147 printf("connection dead");
group-onsemi 0:098463de4c5d 2148 break;
group-onsemi 0:098463de4c5d 2149
group-onsemi 0:098463de4c5d 2150 case SSL_ERROR_INVALID_HANDSHAKE:
group-onsemi 0:098463de4c5d 2151 printf("invalid handshake");
group-onsemi 0:098463de4c5d 2152 break;
group-onsemi 0:098463de4c5d 2153
group-onsemi 0:098463de4c5d 2154 case SSL_ERROR_INVALID_PROT_MSG:
group-onsemi 0:098463de4c5d 2155 printf("invalid protocol message");
group-onsemi 0:098463de4c5d 2156 break;
group-onsemi 0:098463de4c5d 2157
group-onsemi 0:098463de4c5d 2158 case SSL_ERROR_INVALID_HMAC:
group-onsemi 0:098463de4c5d 2159 printf("invalid mac");
group-onsemi 0:098463de4c5d 2160 break;
group-onsemi 0:098463de4c5d 2161
group-onsemi 0:098463de4c5d 2162 case SSL_ERROR_INVALID_VERSION:
group-onsemi 0:098463de4c5d 2163 printf("invalid version");
group-onsemi 0:098463de4c5d 2164 break;
group-onsemi 0:098463de4c5d 2165
group-onsemi 0:098463de4c5d 2166 case SSL_ERROR_INVALID_SESSION:
group-onsemi 0:098463de4c5d 2167 printf("invalid session");
group-onsemi 0:098463de4c5d 2168 break;
group-onsemi 0:098463de4c5d 2169
group-onsemi 0:098463de4c5d 2170 case SSL_ERROR_NO_CIPHER:
group-onsemi 0:098463de4c5d 2171 printf("no cipher");
group-onsemi 0:098463de4c5d 2172 break;
group-onsemi 0:098463de4c5d 2173
group-onsemi 0:098463de4c5d 2174 case SSL_ERROR_CONN_LOST:
group-onsemi 0:098463de4c5d 2175 printf("connection lost");
group-onsemi 0:098463de4c5d 2176 break;
group-onsemi 0:098463de4c5d 2177
group-onsemi 0:098463de4c5d 2178 case SSL_ERROR_BAD_CERTIFICATE:
group-onsemi 0:098463de4c5d 2179 printf("bad certificate");
group-onsemi 0:098463de4c5d 2180 break;
group-onsemi 0:098463de4c5d 2181
group-onsemi 0:098463de4c5d 2182 case SSL_ERROR_INVALID_KEY:
group-onsemi 0:098463de4c5d 2183 printf("invalid key");
group-onsemi 0:098463de4c5d 2184 break;
group-onsemi 0:098463de4c5d 2185
group-onsemi 0:098463de4c5d 2186 case SSL_ERROR_FINISHED_INVALID:
group-onsemi 0:098463de4c5d 2187 printf("finished invalid");
group-onsemi 0:098463de4c5d 2188 break;
group-onsemi 0:098463de4c5d 2189
group-onsemi 0:098463de4c5d 2190 case SSL_ERROR_NO_CERT_DEFINED:
group-onsemi 0:098463de4c5d 2191 printf("no certificate defined");
group-onsemi 0:098463de4c5d 2192 break;
group-onsemi 0:098463de4c5d 2193
group-onsemi 0:098463de4c5d 2194 case SSL_ERROR_NO_CLIENT_RENOG:
group-onsemi 0:098463de4c5d 2195 printf("client renegotiation not supported");
group-onsemi 0:098463de4c5d 2196 break;
group-onsemi 0:098463de4c5d 2197
group-onsemi 0:098463de4c5d 2198 case SSL_ERROR_NOT_SUPPORTED:
group-onsemi 0:098463de4c5d 2199 printf("Option not supported");
group-onsemi 0:098463de4c5d 2200 break;
group-onsemi 0:098463de4c5d 2201
group-onsemi 0:098463de4c5d 2202 default:
group-onsemi 0:098463de4c5d 2203 printf("undefined as yet - %d", error_code);
group-onsemi 0:098463de4c5d 2204 break;
group-onsemi 0:098463de4c5d 2205 }
group-onsemi 0:098463de4c5d 2206
group-onsemi 0:098463de4c5d 2207 printf("\r\n");
group-onsemi 0:098463de4c5d 2208 TTY_FLUSH();
group-onsemi 0:098463de4c5d 2209 }
group-onsemi 0:098463de4c5d 2210
group-onsemi 0:098463de4c5d 2211 /**
group-onsemi 0:098463de4c5d 2212 * Debugging routine to display alerts.
group-onsemi 0:098463de4c5d 2213 */
group-onsemi 0:098463de4c5d 2214 void DISPLAY_ALERT(SSL *ssl, int alert)
group-onsemi 0:098463de4c5d 2215 {
group-onsemi 0:098463de4c5d 2216 if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
group-onsemi 0:098463de4c5d 2217 return;
group-onsemi 0:098463de4c5d 2218
group-onsemi 0:098463de4c5d 2219 printf("Alert: ");
group-onsemi 0:098463de4c5d 2220
group-onsemi 0:098463de4c5d 2221 switch (alert)
group-onsemi 0:098463de4c5d 2222 {
group-onsemi 0:098463de4c5d 2223 case SSL_ALERT_CLOSE_NOTIFY:
group-onsemi 0:098463de4c5d 2224 printf("close notify");
group-onsemi 0:098463de4c5d 2225 break;
group-onsemi 0:098463de4c5d 2226
group-onsemi 0:098463de4c5d 2227 case SSL_ALERT_INVALID_VERSION:
group-onsemi 0:098463de4c5d 2228 printf("invalid version");
group-onsemi 0:098463de4c5d 2229 break;
group-onsemi 0:098463de4c5d 2230
group-onsemi 0:098463de4c5d 2231 case SSL_ALERT_BAD_CERTIFICATE:
group-onsemi 0:098463de4c5d 2232 printf("bad certificate");
group-onsemi 0:098463de4c5d 2233 break;
group-onsemi 0:098463de4c5d 2234
group-onsemi 0:098463de4c5d 2235 case SSL_ALERT_UNEXPECTED_MESSAGE:
group-onsemi 0:098463de4c5d 2236 printf("unexpected message");
group-onsemi 0:098463de4c5d 2237 break;
group-onsemi 0:098463de4c5d 2238
group-onsemi 0:098463de4c5d 2239 case SSL_ALERT_BAD_RECORD_MAC:
group-onsemi 0:098463de4c5d 2240 printf("bad record mac");
group-onsemi 0:098463de4c5d 2241 break;
group-onsemi 0:098463de4c5d 2242
group-onsemi 0:098463de4c5d 2243 case SSL_ALERT_HANDSHAKE_FAILURE:
group-onsemi 0:098463de4c5d 2244 printf("handshake failure");
group-onsemi 0:098463de4c5d 2245 break;
group-onsemi 0:098463de4c5d 2246
group-onsemi 0:098463de4c5d 2247 case SSL_ALERT_ILLEGAL_PARAMETER:
group-onsemi 0:098463de4c5d 2248 printf("illegal parameter");
group-onsemi 0:098463de4c5d 2249 break;
group-onsemi 0:098463de4c5d 2250
group-onsemi 0:098463de4c5d 2251 case SSL_ALERT_DECODE_ERROR:
group-onsemi 0:098463de4c5d 2252 printf("decode error");
group-onsemi 0:098463de4c5d 2253 break;
group-onsemi 0:098463de4c5d 2254
group-onsemi 0:098463de4c5d 2255 case SSL_ALERT_DECRYPT_ERROR:
group-onsemi 0:098463de4c5d 2256 printf("decrypt error");
group-onsemi 0:098463de4c5d 2257 break;
group-onsemi 0:098463de4c5d 2258
group-onsemi 0:098463de4c5d 2259 case SSL_ALERT_NO_RENEGOTIATION:
group-onsemi 0:098463de4c5d 2260 printf("no renegotiation");
group-onsemi 0:098463de4c5d 2261 break;
group-onsemi 0:098463de4c5d 2262
group-onsemi 0:098463de4c5d 2263 default:
group-onsemi 0:098463de4c5d 2264 printf("alert - (unknown %d)", alert);
group-onsemi 0:098463de4c5d 2265 break;
group-onsemi 0:098463de4c5d 2266 }
group-onsemi 0:098463de4c5d 2267
group-onsemi 0:098463de4c5d 2268 printf("\r\n");
group-onsemi 0:098463de4c5d 2269 TTY_FLUSH();
group-onsemi 0:098463de4c5d 2270 }
group-onsemi 0:098463de4c5d 2271
group-onsemi 0:098463de4c5d 2272 #endif /* CONFIG_SSL_FULL_MODE */
group-onsemi 0:098463de4c5d 2273
group-onsemi 0:098463de4c5d 2274 /**
group-onsemi 0:098463de4c5d 2275 * Return the version of this library.
group-onsemi 0:098463de4c5d 2276 */
group-onsemi 0:098463de4c5d 2277 EXP_FUNC const char * STDCALL ssl_version()
group-onsemi 0:098463de4c5d 2278 {
group-onsemi 0:098463de4c5d 2279 static const char * axtls_version = AXTLS_VERSION;
group-onsemi 0:098463de4c5d 2280 return axtls_version;
group-onsemi 0:098463de4c5d 2281 }
group-onsemi 0:098463de4c5d 2282
group-onsemi 0:098463de4c5d 2283 /**
group-onsemi 0:098463de4c5d 2284 * Enable the various language bindings to work regardless of the
group-onsemi 0:098463de4c5d 2285 * configuration - they just return an error statement and a bad return code.
group-onsemi 0:098463de4c5d 2286 */
group-onsemi 0:098463de4c5d 2287 #if !defined(CONFIG_SSL_FULL_MODE)
group-onsemi 0:098463de4c5d 2288 EXP_FUNC void STDCALL ssl_display_error(int error_code) {}
group-onsemi 0:098463de4c5d 2289 #endif
group-onsemi 0:098463de4c5d 2290
group-onsemi 0:098463de4c5d 2291 #ifdef CONFIG_BINDINGS
group-onsemi 0:098463de4c5d 2292 #if !defined(CONFIG_SSL_ENABLE_CLIENT)
group-onsemi 0:098463de4c5d 2293 EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
group-onsemi 0:098463de4c5d 2294 uint8_t *session_id, uint8_t sess_id_size)
group-onsemi 0:098463de4c5d 2295 {
group-onsemi 0:098463de4c5d 2296 printf(unsupported_str);
group-onsemi 0:098463de4c5d 2297 return NULL;
group-onsemi 0:098463de4c5d 2298 }
group-onsemi 0:098463de4c5d 2299 #endif
group-onsemi 0:098463de4c5d 2300
group-onsemi 0:098463de4c5d 2301 #if !defined(CONFIG_SSL_CERT_VERIFICATION)
group-onsemi 0:098463de4c5d 2302 EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
group-onsemi 0:098463de4c5d 2303 {
group-onsemi 0:098463de4c5d 2304 printf(unsupported_str);
group-onsemi 0:098463de4c5d 2305 return -1;
group-onsemi 0:098463de4c5d 2306 }
group-onsemi 0:098463de4c5d 2307
group-onsemi 0:098463de4c5d 2308
group-onsemi 0:098463de4c5d 2309 EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
group-onsemi 0:098463de4c5d 2310 {
group-onsemi 0:098463de4c5d 2311 printf(unsupported_str);
group-onsemi 0:098463de4c5d 2312 return NULL;
group-onsemi 0:098463de4c5d 2313 }
group-onsemi 0:098463de4c5d 2314
group-onsemi 0:098463de4c5d 2315 EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int index)
group-onsemi 0:098463de4c5d 2316 {
group-onsemi 0:098463de4c5d 2317 printf(unsupported_str);
group-onsemi 0:098463de4c5d 2318 return NULL;
group-onsemi 0:098463de4c5d 2319 }
group-onsemi 0:098463de4c5d 2320
group-onsemi 0:098463de4c5d 2321 #endif /* CONFIG_SSL_CERT_VERIFICATION */
group-onsemi 0:098463de4c5d 2322
group-onsemi 0:098463de4c5d 2323 #endif /* CONFIG_BINDINGS */
group-onsemi 0:098463de4c5d 2324