Rough and ready port of axTLS

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

Who changed what in which revision?

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