CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

Committer:
toddouska
Date:
Sat Feb 05 01:09:17 2011 +0000
Revision:
0:5045d2638c29
Beta Version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
toddouska 0:5045d2638c29 1 /* cyassl_int.c
toddouska 0:5045d2638c29 2 *
toddouska 0:5045d2638c29 3 * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
toddouska 0:5045d2638c29 4 *
toddouska 0:5045d2638c29 5 * This file is part of CyaSSL.
toddouska 0:5045d2638c29 6 *
toddouska 0:5045d2638c29 7 * CyaSSL is free software; you can redistribute it and/or modify
toddouska 0:5045d2638c29 8 * it under the terms of the GNU General Public License as published by
toddouska 0:5045d2638c29 9 * the Free Software Foundation; either version 2 of the License, or
toddouska 0:5045d2638c29 10 * (at your option) any later version.
toddouska 0:5045d2638c29 11 *
toddouska 0:5045d2638c29 12 * CyaSSL is distributed in the hope that it will be useful,
toddouska 0:5045d2638c29 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
toddouska 0:5045d2638c29 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
toddouska 0:5045d2638c29 15 * GNU General Public License for more details.
toddouska 0:5045d2638c29 16 *
toddouska 0:5045d2638c29 17 * You should have received a copy of the GNU General Public License
toddouska 0:5045d2638c29 18 * along with this program; if not, write to the Free Software
toddouska 0:5045d2638c29 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
toddouska 0:5045d2638c29 20 */
toddouska 0:5045d2638c29 21
toddouska 0:5045d2638c29 22
toddouska 0:5045d2638c29 23
toddouska 0:5045d2638c29 24 #include "cyassl_int.h"
toddouska 0:5045d2638c29 25 #include "cyassl_error.h"
toddouska 0:5045d2638c29 26 #include "asn.h"
toddouska 0:5045d2638c29 27
toddouska 0:5045d2638c29 28 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 29 #include "zlib.h"
toddouska 0:5045d2638c29 30 #endif
toddouska 0:5045d2638c29 31
toddouska 0:5045d2638c29 32 #ifdef HAVE_NTRU
toddouska 0:5045d2638c29 33 #include "crypto_ntru.h"
toddouska 0:5045d2638c29 34 #endif
toddouska 0:5045d2638c29 35
toddouska 0:5045d2638c29 36 #if defined(DEBUG_CYASSL) || defined(SHOW_SECRETS)
toddouska 0:5045d2638c29 37 #include <stdio.h>
toddouska 0:5045d2638c29 38 #endif
toddouska 0:5045d2638c29 39
toddouska 0:5045d2638c29 40 #ifdef __sun
toddouska 0:5045d2638c29 41 #include <sys/filio.h>
toddouska 0:5045d2638c29 42 #endif
toddouska 0:5045d2638c29 43
toddouska 0:5045d2638c29 44 #define TRUE 1
toddouska 0:5045d2638c29 45 #define FALSE 0
toddouska 0:5045d2638c29 46
toddouska 0:5045d2638c29 47
toddouska 0:5045d2638c29 48 int CyaSSL_negotiate(SSL*);
toddouska 0:5045d2638c29 49
toddouska 0:5045d2638c29 50
toddouska 0:5045d2638c29 51 #ifndef NO_CYASSL_CLIENT
toddouska 0:5045d2638c29 52 static int DoHelloVerifyRequest(SSL* ssl, const byte* input, word32*);
toddouska 0:5045d2638c29 53 static int DoServerHello(SSL* ssl, const byte* input, word32*);
toddouska 0:5045d2638c29 54 static int DoCertificateRequest(SSL* ssl, const byte* input, word32*);
toddouska 0:5045d2638c29 55 static int DoServerKeyExchange(SSL* ssl, const byte* input, word32*);
toddouska 0:5045d2638c29 56 #endif
toddouska 0:5045d2638c29 57
toddouska 0:5045d2638c29 58
toddouska 0:5045d2638c29 59 #ifndef NO_CYASSL_SERVER
toddouska 0:5045d2638c29 60 static int DoClientHello(SSL* ssl, const byte* input, word32*, word32,
toddouska 0:5045d2638c29 61 word32);
toddouska 0:5045d2638c29 62 static int DoCertificateVerify(SSL* ssl, byte*, word32*, word32);
toddouska 0:5045d2638c29 63 static int DoClientKeyExchange(SSL* ssl, byte* input, word32*);
toddouska 0:5045d2638c29 64 #endif
toddouska 0:5045d2638c29 65
toddouska 0:5045d2638c29 66 typedef enum {
toddouska 0:5045d2638c29 67 doProcessInit = 0,
toddouska 0:5045d2638c29 68 #ifndef NO_CYASSL_SERVER
toddouska 0:5045d2638c29 69 runProcessOldClientHello,
toddouska 0:5045d2638c29 70 #endif
toddouska 0:5045d2638c29 71 getRecordLayerHeader,
toddouska 0:5045d2638c29 72 getData,
toddouska 0:5045d2638c29 73 runProcessingOneMessage
toddouska 0:5045d2638c29 74 } processReply;
toddouska 0:5045d2638c29 75
toddouska 0:5045d2638c29 76 static void Hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
toddouska 0:5045d2638c29 77 int content, int verify);
toddouska 0:5045d2638c29 78
toddouska 0:5045d2638c29 79 static void BuildCertHashes(SSL* ssl, Hashes* hashes);
toddouska 0:5045d2638c29 80
toddouska 0:5045d2638c29 81
toddouska 0:5045d2638c29 82 void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender);
toddouska 0:5045d2638c29 83
toddouska 0:5045d2638c29 84
toddouska 0:5045d2638c29 85 #ifndef min
toddouska 0:5045d2638c29 86
toddouska 0:5045d2638c29 87 static INLINE word32 min(word32 a, word32 b)
toddouska 0:5045d2638c29 88 {
toddouska 0:5045d2638c29 89 return a > b ? b : a;
toddouska 0:5045d2638c29 90 }
toddouska 0:5045d2638c29 91
toddouska 0:5045d2638c29 92 #endif /* min */
toddouska 0:5045d2638c29 93
toddouska 0:5045d2638c29 94
toddouska 0:5045d2638c29 95 int IsTLS(const SSL* ssl)
toddouska 0:5045d2638c29 96 {
toddouska 0:5045d2638c29 97 if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
toddouska 0:5045d2638c29 98 return 1;
toddouska 0:5045d2638c29 99
toddouska 0:5045d2638c29 100 return 0;
toddouska 0:5045d2638c29 101 }
toddouska 0:5045d2638c29 102
toddouska 0:5045d2638c29 103
toddouska 0:5045d2638c29 104 int IsAtLeastTLSv1_2(const SSL* ssl)
toddouska 0:5045d2638c29 105 {
toddouska 0:5045d2638c29 106 if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
toddouska 0:5045d2638c29 107 return 1;
toddouska 0:5045d2638c29 108
toddouska 0:5045d2638c29 109 return 0;
toddouska 0:5045d2638c29 110 }
toddouska 0:5045d2638c29 111
toddouska 0:5045d2638c29 112
toddouska 0:5045d2638c29 113 #ifdef HAVE_NTRU
toddouska 0:5045d2638c29 114
toddouska 0:5045d2638c29 115 static byte GetEntropy(ENTROPY_CMD cmd, byte* out)
toddouska 0:5045d2638c29 116 {
toddouska 0:5045d2638c29 117 /* TODO: add locking? */
toddouska 0:5045d2638c29 118 static RNG rng;
toddouska 0:5045d2638c29 119
toddouska 0:5045d2638c29 120 if (cmd == INIT) {
toddouska 0:5045d2638c29 121 int ret = InitRng(&rng);
toddouska 0:5045d2638c29 122 if (ret == 0)
toddouska 0:5045d2638c29 123 return 1;
toddouska 0:5045d2638c29 124 else
toddouska 0:5045d2638c29 125 return 0;
toddouska 0:5045d2638c29 126 }
toddouska 0:5045d2638c29 127
toddouska 0:5045d2638c29 128 if (out == NULL)
toddouska 0:5045d2638c29 129 return 0;
toddouska 0:5045d2638c29 130
toddouska 0:5045d2638c29 131 if (cmd == GET_BYTE_OF_ENTROPY) {
toddouska 0:5045d2638c29 132 RNG_GenerateBlock(&rng, out, 1);
toddouska 0:5045d2638c29 133 return 1;
toddouska 0:5045d2638c29 134 }
toddouska 0:5045d2638c29 135
toddouska 0:5045d2638c29 136 if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
toddouska 0:5045d2638c29 137 *out = 1;
toddouska 0:5045d2638c29 138 return 1;
toddouska 0:5045d2638c29 139 }
toddouska 0:5045d2638c29 140
toddouska 0:5045d2638c29 141 return 0;
toddouska 0:5045d2638c29 142 }
toddouska 0:5045d2638c29 143
toddouska 0:5045d2638c29 144 #endif /* HAVE_NTRU */
toddouska 0:5045d2638c29 145
toddouska 0:5045d2638c29 146 static INLINE void c32to24(word32 in, word24 out)
toddouska 0:5045d2638c29 147 {
toddouska 0:5045d2638c29 148 out[0] = (in >> 16) & 0xff;
toddouska 0:5045d2638c29 149 out[1] = (in >> 8) & 0xff;
toddouska 0:5045d2638c29 150 out[2] = in & 0xff;
toddouska 0:5045d2638c29 151 }
toddouska 0:5045d2638c29 152
toddouska 0:5045d2638c29 153
toddouska 0:5045d2638c29 154 static INLINE void c32to48(word32 in, byte out[6])
toddouska 0:5045d2638c29 155 {
toddouska 0:5045d2638c29 156 out[0] = 0;
toddouska 0:5045d2638c29 157 out[1] = 0;
toddouska 0:5045d2638c29 158 out[2] = (in >> 24) & 0xff;
toddouska 0:5045d2638c29 159 out[3] = (in >> 16) & 0xff;
toddouska 0:5045d2638c29 160 out[4] = (in >> 8) & 0xff;
toddouska 0:5045d2638c29 161 out[5] = in & 0xff;
toddouska 0:5045d2638c29 162 }
toddouska 0:5045d2638c29 163
toddouska 0:5045d2638c29 164
toddouska 0:5045d2638c29 165 /* convert 16 bit integer to opaque */
toddouska 0:5045d2638c29 166 static void INLINE c16toa(word16 u16, byte* c)
toddouska 0:5045d2638c29 167 {
toddouska 0:5045d2638c29 168 c[0] = (u16 >> 8) & 0xff;
toddouska 0:5045d2638c29 169 c[1] = u16 & 0xff;
toddouska 0:5045d2638c29 170 }
toddouska 0:5045d2638c29 171
toddouska 0:5045d2638c29 172
toddouska 0:5045d2638c29 173 /* convert 32 bit integer to opaque */
toddouska 0:5045d2638c29 174 static INLINE void c32toa(word32 u32, byte* c)
toddouska 0:5045d2638c29 175 {
toddouska 0:5045d2638c29 176 c[0] = (u32 >> 24) & 0xff;
toddouska 0:5045d2638c29 177 c[1] = (u32 >> 16) & 0xff;
toddouska 0:5045d2638c29 178 c[2] = (u32 >> 8) & 0xff;
toddouska 0:5045d2638c29 179 c[3] = u32 & 0xff;
toddouska 0:5045d2638c29 180 }
toddouska 0:5045d2638c29 181
toddouska 0:5045d2638c29 182
toddouska 0:5045d2638c29 183 /* convert a 24 bit integer into a 32 bit one */
toddouska 0:5045d2638c29 184 static INLINE void c24to32(const word24 u24, word32* u32)
toddouska 0:5045d2638c29 185 {
toddouska 0:5045d2638c29 186 *u32 = 0;
toddouska 0:5045d2638c29 187 *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
toddouska 0:5045d2638c29 188 }
toddouska 0:5045d2638c29 189
toddouska 0:5045d2638c29 190
toddouska 0:5045d2638c29 191 /* convert opaque to 16 bit integer */
toddouska 0:5045d2638c29 192 static INLINE void ato16(const byte* c, word16* u16)
toddouska 0:5045d2638c29 193 {
toddouska 0:5045d2638c29 194 *u16 = 0;
toddouska 0:5045d2638c29 195 *u16 = (c[0] << 8) | (c[1]);
toddouska 0:5045d2638c29 196 }
toddouska 0:5045d2638c29 197
toddouska 0:5045d2638c29 198
toddouska 0:5045d2638c29 199 /* convert opaque to 32 bit integer */
toddouska 0:5045d2638c29 200 static INLINE void ato32(const byte* c, word32* u32)
toddouska 0:5045d2638c29 201 {
toddouska 0:5045d2638c29 202 *u32 = 0;
toddouska 0:5045d2638c29 203 *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
toddouska 0:5045d2638c29 204 }
toddouska 0:5045d2638c29 205
toddouska 0:5045d2638c29 206
toddouska 0:5045d2638c29 207 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 208
toddouska 0:5045d2638c29 209 /* alloc user allocs to work with zlib */
toddouska 0:5045d2638c29 210 void* myAlloc(void* opaque, unsigned int item, unsigned int size)
toddouska 0:5045d2638c29 211 {
toddouska 0:5045d2638c29 212 return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
toddouska 0:5045d2638c29 213 }
toddouska 0:5045d2638c29 214
toddouska 0:5045d2638c29 215
toddouska 0:5045d2638c29 216 void myFree(void* opaque, void* memory)
toddouska 0:5045d2638c29 217 {
toddouska 0:5045d2638c29 218 XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
toddouska 0:5045d2638c29 219 }
toddouska 0:5045d2638c29 220
toddouska 0:5045d2638c29 221
toddouska 0:5045d2638c29 222 /* init zlib comp/decomp streams, 0 on success */
toddouska 0:5045d2638c29 223 static int InitStreams(SSL* ssl)
toddouska 0:5045d2638c29 224 {
toddouska 0:5045d2638c29 225 ssl->c_stream.zalloc = (alloc_func)myAlloc;
toddouska 0:5045d2638c29 226 ssl->c_stream.zfree = (free_func)myFree;
toddouska 0:5045d2638c29 227 ssl->c_stream.opaque = (voidpf)ssl->heap;
toddouska 0:5045d2638c29 228
toddouska 0:5045d2638c29 229 if (deflateInit(&ssl->c_stream, 8) != Z_OK) return ZLIB_INIT_ERROR;
toddouska 0:5045d2638c29 230
toddouska 0:5045d2638c29 231 ssl->didStreamInit = 1;
toddouska 0:5045d2638c29 232
toddouska 0:5045d2638c29 233 ssl->d_stream.zalloc = (alloc_func)myAlloc;
toddouska 0:5045d2638c29 234 ssl->d_stream.zfree = (free_func)myFree;
toddouska 0:5045d2638c29 235 ssl->d_stream.opaque = (voidpf)ssl->heap;
toddouska 0:5045d2638c29 236
toddouska 0:5045d2638c29 237 if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
toddouska 0:5045d2638c29 238
toddouska 0:5045d2638c29 239 return 0;
toddouska 0:5045d2638c29 240 }
toddouska 0:5045d2638c29 241
toddouska 0:5045d2638c29 242
toddouska 0:5045d2638c29 243 static void FreeStreams(SSL* ssl)
toddouska 0:5045d2638c29 244 {
toddouska 0:5045d2638c29 245 if (ssl->didStreamInit) {
toddouska 0:5045d2638c29 246 deflateEnd(&ssl->c_stream);
toddouska 0:5045d2638c29 247 inflateEnd(&ssl->d_stream);
toddouska 0:5045d2638c29 248 }
toddouska 0:5045d2638c29 249 }
toddouska 0:5045d2638c29 250
toddouska 0:5045d2638c29 251
toddouska 0:5045d2638c29 252 /* compress in to out, return out size or error */
toddouska 0:5045d2638c29 253 static int Compress(SSL* ssl, byte* in, int inSz, byte* out, int outSz)
toddouska 0:5045d2638c29 254 {
toddouska 0:5045d2638c29 255 int err;
toddouska 0:5045d2638c29 256 int currTotal = ssl->c_stream.total_out;
toddouska 0:5045d2638c29 257
toddouska 0:5045d2638c29 258 /* put size in front of compression */
toddouska 0:5045d2638c29 259 c16toa((word16)inSz, out);
toddouska 0:5045d2638c29 260 out += 2;
toddouska 0:5045d2638c29 261 outSz -= 2;
toddouska 0:5045d2638c29 262
toddouska 0:5045d2638c29 263 ssl->c_stream.next_in = in;
toddouska 0:5045d2638c29 264 ssl->c_stream.avail_in = inSz;
toddouska 0:5045d2638c29 265 ssl->c_stream.next_out = out;
toddouska 0:5045d2638c29 266 ssl->c_stream.avail_out = outSz;
toddouska 0:5045d2638c29 267
toddouska 0:5045d2638c29 268 err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
toddouska 0:5045d2638c29 269 if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
toddouska 0:5045d2638c29 270
toddouska 0:5045d2638c29 271 return ssl->c_stream.total_out - currTotal + sizeof(word16);
toddouska 0:5045d2638c29 272 }
toddouska 0:5045d2638c29 273
toddouska 0:5045d2638c29 274
toddouska 0:5045d2638c29 275 /* decompress in to out, returnn out size or error */
toddouska 0:5045d2638c29 276 static int DeCompress(SSL* ssl, byte* in, int inSz, byte* out, int outSz)
toddouska 0:5045d2638c29 277 {
toddouska 0:5045d2638c29 278 int err;
toddouska 0:5045d2638c29 279 int currTotal = ssl->d_stream.total_out;
toddouska 0:5045d2638c29 280 word16 len;
toddouska 0:5045d2638c29 281
toddouska 0:5045d2638c29 282 /* find size in front of compression */
toddouska 0:5045d2638c29 283 ato16(in, &len);
toddouska 0:5045d2638c29 284 in += 2;
toddouska 0:5045d2638c29 285 inSz -= 2;
toddouska 0:5045d2638c29 286
toddouska 0:5045d2638c29 287 ssl->d_stream.next_in = in;
toddouska 0:5045d2638c29 288 ssl->d_stream.avail_in = inSz;
toddouska 0:5045d2638c29 289 ssl->d_stream.next_out = out;
toddouska 0:5045d2638c29 290 ssl->d_stream.avail_out = outSz;
toddouska 0:5045d2638c29 291
toddouska 0:5045d2638c29 292 err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
toddouska 0:5045d2638c29 293 if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
toddouska 0:5045d2638c29 294
toddouska 0:5045d2638c29 295 return ssl->d_stream.total_out - currTotal;
toddouska 0:5045d2638c29 296 }
toddouska 0:5045d2638c29 297
toddouska 0:5045d2638c29 298 #endif /* HAVE_LIBZ */
toddouska 0:5045d2638c29 299
toddouska 0:5045d2638c29 300
toddouska 0:5045d2638c29 301 void InitSSL_Method(SSL_METHOD* method, ProtocolVersion pv)
toddouska 0:5045d2638c29 302 {
toddouska 0:5045d2638c29 303 method->version = pv;
toddouska 0:5045d2638c29 304 method->side = CLIENT_END;
toddouska 0:5045d2638c29 305 method->verifyPeer = 0;
toddouska 0:5045d2638c29 306 method->verifyNone = 0;
toddouska 0:5045d2638c29 307 method->failNoCert = 0;
toddouska 0:5045d2638c29 308 method->downgrade = 0;
toddouska 0:5045d2638c29 309 }
toddouska 0:5045d2638c29 310
toddouska 0:5045d2638c29 311
toddouska 0:5045d2638c29 312 void InitSSL_Ctx(SSL_CTX* ctx, SSL_METHOD* method)
toddouska 0:5045d2638c29 313 {
toddouska 0:5045d2638c29 314 ctx->method = method;
toddouska 0:5045d2638c29 315 ctx->certificate.buffer = 0;
toddouska 0:5045d2638c29 316 ctx->privateKey.buffer = 0;
toddouska 0:5045d2638c29 317 ctx->haveDH = 0;
toddouska 0:5045d2638c29 318 ctx->haveNTRU = 0; /* start off */
toddouska 0:5045d2638c29 319 ctx->heap = ctx; /* defaults to self */
toddouska 0:5045d2638c29 320 #ifndef NO_PSK
toddouska 0:5045d2638c29 321 ctx->havePSK = 0;
toddouska 0:5045d2638c29 322 ctx->server_hint[0] = 0;
toddouska 0:5045d2638c29 323 ctx->client_psk_cb = 0;
toddouska 0:5045d2638c29 324 ctx->server_psk_cb = 0;
toddouska 0:5045d2638c29 325 #endif /* NO_PSK */
toddouska 0:5045d2638c29 326
toddouska 0:5045d2638c29 327 #ifdef OPENSSL_EXTRA
toddouska 0:5045d2638c29 328 ctx->passwd_cb = 0;
toddouska 0:5045d2638c29 329 ctx->userdata = 0;
toddouska 0:5045d2638c29 330 #endif /* OPENSSL_EXTRA */
toddouska 0:5045d2638c29 331
toddouska 0:5045d2638c29 332 #ifndef CYASSL_USER_IO
toddouska 0:5045d2638c29 333 ctx->CBIORecv = EmbedReceive;
toddouska 0:5045d2638c29 334 ctx->CBIOSend = EmbedSend;
toddouska 0:5045d2638c29 335 #else
toddouska 0:5045d2638c29 336 /* user will set */
toddouska 0:5045d2638c29 337 ctx->CBIORecv = NULL;
toddouska 0:5045d2638c29 338 ctx->CBIOSend = NULL;
toddouska 0:5045d2638c29 339 #endif
toddouska 0:5045d2638c29 340 ctx->partialWrite = 0;
toddouska 0:5045d2638c29 341 ctx->verifyCallback = 0;
toddouska 0:5045d2638c29 342
toddouska 0:5045d2638c29 343 ctx->caList = 0;
toddouska 0:5045d2638c29 344 #ifdef HAVE_NTRU
toddouska 0:5045d2638c29 345 if (method->side == CLIENT_END)
toddouska 0:5045d2638c29 346 ctx->haveNTRU = 1; /* always on cliet side */
toddouska 0:5045d2638c29 347 /* server can turn on by loading key */
toddouska 0:5045d2638c29 348 #endif
toddouska 0:5045d2638c29 349 /* remove DH later if server didn't set, add psk later */
toddouska 0:5045d2638c29 350 InitSuites(&ctx->suites, method->version, TRUE, FALSE, ctx->haveNTRU);
toddouska 0:5045d2638c29 351 ctx->verifyPeer = 0;
toddouska 0:5045d2638c29 352 ctx->verifyNone = 0;
toddouska 0:5045d2638c29 353 ctx->failNoCert = 0;
toddouska 0:5045d2638c29 354 ctx->sessionCacheOff = 0; /* initially on */
toddouska 0:5045d2638c29 355 ctx->sessionCacheFlushOff = 0; /* initially on */
toddouska 0:5045d2638c29 356 ctx->sendVerify = 0;
toddouska 0:5045d2638c29 357 ctx->quietShutdown = 0;
toddouska 0:5045d2638c29 358
toddouska 0:5045d2638c29 359 }
toddouska 0:5045d2638c29 360
toddouska 0:5045d2638c29 361
toddouska 0:5045d2638c29 362 /* In case contexts are held in array and don't want to free actual ctx */
toddouska 0:5045d2638c29 363 void SSL_CtxResourceFree(SSL_CTX* ctx)
toddouska 0:5045d2638c29 364 {
toddouska 0:5045d2638c29 365 XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
toddouska 0:5045d2638c29 366 XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
toddouska 0:5045d2638c29 367 XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
toddouska 0:5045d2638c29 368
toddouska 0:5045d2638c29 369 FreeSigners(ctx->caList, ctx->heap);
toddouska 0:5045d2638c29 370 }
toddouska 0:5045d2638c29 371
toddouska 0:5045d2638c29 372
toddouska 0:5045d2638c29 373 void FreeSSL_Ctx(SSL_CTX* ctx)
toddouska 0:5045d2638c29 374 {
toddouska 0:5045d2638c29 375 SSL_CtxResourceFree(ctx);
toddouska 0:5045d2638c29 376 XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
toddouska 0:5045d2638c29 377 }
toddouska 0:5045d2638c29 378
toddouska 0:5045d2638c29 379
toddouska 0:5045d2638c29 380
toddouska 0:5045d2638c29 381 void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
toddouska 0:5045d2638c29 382 byte haveNTRU)
toddouska 0:5045d2638c29 383 {
toddouska 0:5045d2638c29 384 word32 idx = 0;
toddouska 0:5045d2638c29 385 int tls = pv.major == 3 && pv.minor >= 1;
toddouska 0:5045d2638c29 386
toddouska 0:5045d2638c29 387 (void)tls; /* shut up compiler */
toddouska 0:5045d2638c29 388
toddouska 0:5045d2638c29 389 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 390 if (pv.major == DTLS_MAJOR && pv.minor == DTLS_MINOR)
toddouska 0:5045d2638c29 391 tls = 1;
toddouska 0:5045d2638c29 392 #endif
toddouska 0:5045d2638c29 393
toddouska 0:5045d2638c29 394 suites->setSuites = 0; /* user hasn't set yet */
toddouska 0:5045d2638c29 395
toddouska 0:5045d2638c29 396 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 397 if (tls && haveNTRU) {
toddouska 0:5045d2638c29 398 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 399 suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
toddouska 0:5045d2638c29 400 }
toddouska 0:5045d2638c29 401 #endif
toddouska 0:5045d2638c29 402
toddouska 0:5045d2638c29 403 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 404 if (tls && haveNTRU) {
toddouska 0:5045d2638c29 405 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 406 suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
toddouska 0:5045d2638c29 407 }
toddouska 0:5045d2638c29 408 #endif
toddouska 0:5045d2638c29 409
toddouska 0:5045d2638c29 410 #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
toddouska 0:5045d2638c29 411 if (tls && haveNTRU) {
toddouska 0:5045d2638c29 412 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 413 suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
toddouska 0:5045d2638c29 414 }
toddouska 0:5045d2638c29 415 #endif
toddouska 0:5045d2638c29 416
toddouska 0:5045d2638c29 417 #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
toddouska 0:5045d2638c29 418 if (tls && haveNTRU) {
toddouska 0:5045d2638c29 419 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 420 suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
toddouska 0:5045d2638c29 421 }
toddouska 0:5045d2638c29 422 #endif
toddouska 0:5045d2638c29 423
toddouska 0:5045d2638c29 424 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 425 if (tls && haveDH) {
toddouska 0:5045d2638c29 426 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 427 suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
toddouska 0:5045d2638c29 428 }
toddouska 0:5045d2638c29 429 #endif
toddouska 0:5045d2638c29 430
toddouska 0:5045d2638c29 431 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 432 if (tls && haveDH) {
toddouska 0:5045d2638c29 433 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 434 suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
toddouska 0:5045d2638c29 435 }
toddouska 0:5045d2638c29 436 #endif
toddouska 0:5045d2638c29 437
toddouska 0:5045d2638c29 438 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 439 if (tls) {
toddouska 0:5045d2638c29 440 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 441 suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
toddouska 0:5045d2638c29 442 }
toddouska 0:5045d2638c29 443 #endif
toddouska 0:5045d2638c29 444
toddouska 0:5045d2638c29 445 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 446 if (tls) {
toddouska 0:5045d2638c29 447 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 448 suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
toddouska 0:5045d2638c29 449 }
toddouska 0:5045d2638c29 450 #endif
toddouska 0:5045d2638c29 451
toddouska 0:5045d2638c29 452 #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 453 if (tls && havePSK) {
toddouska 0:5045d2638c29 454 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 455 suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
toddouska 0:5045d2638c29 456 }
toddouska 0:5045d2638c29 457 #endif
toddouska 0:5045d2638c29 458
toddouska 0:5045d2638c29 459 #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 460 if (tls && havePSK) {
toddouska 0:5045d2638c29 461 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 462 suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
toddouska 0:5045d2638c29 463 }
toddouska 0:5045d2638c29 464 #endif
toddouska 0:5045d2638c29 465
toddouska 0:5045d2638c29 466 #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
toddouska 0:5045d2638c29 467 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 468 suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
toddouska 0:5045d2638c29 469 #endif
toddouska 0:5045d2638c29 470
toddouska 0:5045d2638c29 471 #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
toddouska 0:5045d2638c29 472 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 473 suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
toddouska 0:5045d2638c29 474 #endif
toddouska 0:5045d2638c29 475
toddouska 0:5045d2638c29 476 #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
toddouska 0:5045d2638c29 477 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 478 suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
toddouska 0:5045d2638c29 479 #endif
toddouska 0:5045d2638c29 480
toddouska 0:5045d2638c29 481 #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
toddouska 0:5045d2638c29 482 if (tls) {
toddouska 0:5045d2638c29 483 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 484 suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_MD5;
toddouska 0:5045d2638c29 485 }
toddouska 0:5045d2638c29 486 #endif
toddouska 0:5045d2638c29 487
toddouska 0:5045d2638c29 488 #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
toddouska 0:5045d2638c29 489 if (tls) {
toddouska 0:5045d2638c29 490 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 491 suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_SHA;
toddouska 0:5045d2638c29 492 }
toddouska 0:5045d2638c29 493 #endif
toddouska 0:5045d2638c29 494
toddouska 0:5045d2638c29 495 #ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
toddouska 0:5045d2638c29 496 if (tls) {
toddouska 0:5045d2638c29 497 suites->suites[idx++] = 0;
toddouska 0:5045d2638c29 498 suites->suites[idx++] = TLS_RSA_WITH_RABBIT_CBC_SHA;
toddouska 0:5045d2638c29 499 }
toddouska 0:5045d2638c29 500 #endif
toddouska 0:5045d2638c29 501
toddouska 0:5045d2638c29 502 suites->suiteSz = idx;
toddouska 0:5045d2638c29 503 }
toddouska 0:5045d2638c29 504
toddouska 0:5045d2638c29 505
toddouska 0:5045d2638c29 506 int InitSSL(SSL* ssl, SSL_CTX* ctx)
toddouska 0:5045d2638c29 507 {
toddouska 0:5045d2638c29 508 int ret;
toddouska 0:5045d2638c29 509 byte havePSK = 0;
toddouska 0:5045d2638c29 510
toddouska 0:5045d2638c29 511 ssl->ctx = ctx; /* only for passing to calls, options could change */
toddouska 0:5045d2638c29 512 ssl->version = ctx->method->version;
toddouska 0:5045d2638c29 513 ssl->suites = ctx->suites;
toddouska 0:5045d2638c29 514
toddouska 0:5045d2638c29 515 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 516 ssl->didStreamInit = 0;
toddouska 0:5045d2638c29 517 #endif
toddouska 0:5045d2638c29 518
toddouska 0:5045d2638c29 519 ssl->buffers.certificate.buffer = 0;
toddouska 0:5045d2638c29 520 ssl->buffers.key.buffer = 0;
toddouska 0:5045d2638c29 521 ssl->buffers.inputBuffer.length = 0;
toddouska 0:5045d2638c29 522 ssl->buffers.inputBuffer.idx = 0;
toddouska 0:5045d2638c29 523 ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
toddouska 0:5045d2638c29 524 ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
toddouska 0:5045d2638c29 525 ssl->buffers.inputBuffer.dynamicFlag = 0;
toddouska 0:5045d2638c29 526 ssl->buffers.outputBuffer.length = 0;
toddouska 0:5045d2638c29 527 ssl->buffers.outputBuffer.idx = 0;
toddouska 0:5045d2638c29 528 ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
toddouska 0:5045d2638c29 529 ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
toddouska 0:5045d2638c29 530 ssl->buffers.outputBuffer.dynamicFlag = 0;
toddouska 0:5045d2638c29 531 ssl->buffers.domainName.buffer = 0;
toddouska 0:5045d2638c29 532 ssl->buffers.serverDH_P.buffer = 0;
toddouska 0:5045d2638c29 533 ssl->buffers.serverDH_G.buffer = 0;
toddouska 0:5045d2638c29 534 ssl->buffers.serverDH_Pub.buffer = 0;
toddouska 0:5045d2638c29 535 ssl->buffers.serverDH_Priv.buffer = 0;
toddouska 0:5045d2638c29 536 ssl->buffers.clearOutputBuffer.buffer = 0;
toddouska 0:5045d2638c29 537 ssl->buffers.clearOutputBuffer.length = 0;
toddouska 0:5045d2638c29 538 ssl->buffers.prevSent = 0;
toddouska 0:5045d2638c29 539 ssl->buffers.plainSz = 0;
toddouska 0:5045d2638c29 540
toddouska 0:5045d2638c29 541 if ( (ret = InitRng(&ssl->rng)) )
toddouska 0:5045d2638c29 542 return ret;
toddouska 0:5045d2638c29 543
toddouska 0:5045d2638c29 544 InitMd5(&ssl->hashMd5);
toddouska 0:5045d2638c29 545 InitSha(&ssl->hashSha);
toddouska 0:5045d2638c29 546 InitRsaKey(&ssl->peerRsaKey, ctx->heap);
toddouska 0:5045d2638c29 547
toddouska 0:5045d2638c29 548 ssl->peerRsaKeyPresent = 0;
toddouska 0:5045d2638c29 549 ssl->options.side = ctx->method->side;
toddouska 0:5045d2638c29 550 ssl->options.downgrade = ctx->method->downgrade;
toddouska 0:5045d2638c29 551 ssl->error = 0;
toddouska 0:5045d2638c29 552 ssl->options.connReset = 0;
toddouska 0:5045d2638c29 553 ssl->options.isClosed = 0;
toddouska 0:5045d2638c29 554 ssl->options.closeNotify = 0;
toddouska 0:5045d2638c29 555 ssl->options.sentNotify = 0;
toddouska 0:5045d2638c29 556 ssl->options.usingCompression = 0;
toddouska 0:5045d2638c29 557 ssl->options.haveDH = ctx->haveDH;
toddouska 0:5045d2638c29 558 ssl->options.haveNTRU = ctx->haveNTRU;
toddouska 0:5045d2638c29 559 ssl->options.havePeerCert = 0;
toddouska 0:5045d2638c29 560 ssl->options.usingPSK_cipher = 0;
toddouska 0:5045d2638c29 561 ssl->options.sendAlertState = 0;
toddouska 0:5045d2638c29 562 #ifndef NO_PSK
toddouska 0:5045d2638c29 563 havePSK = ctx->havePSK;
toddouska 0:5045d2638c29 564 ssl->options.havePSK = ctx->havePSK;
toddouska 0:5045d2638c29 565 ssl->options.client_psk_cb = ctx->client_psk_cb;
toddouska 0:5045d2638c29 566 ssl->options.server_psk_cb = ctx->server_psk_cb;
toddouska 0:5045d2638c29 567 #endif /* NO_PSK */
toddouska 0:5045d2638c29 568
toddouska 0:5045d2638c29 569 ssl->options.serverState = NULL_STATE;
toddouska 0:5045d2638c29 570 ssl->options.clientState = NULL_STATE;
toddouska 0:5045d2638c29 571 ssl->options.connectState = CONNECT_BEGIN;
toddouska 0:5045d2638c29 572 ssl->options.acceptState = ACCEPT_BEGIN;
toddouska 0:5045d2638c29 573 ssl->options.handShakeState = NULL_STATE;
toddouska 0:5045d2638c29 574 ssl->options.processReply = doProcessInit;
toddouska 0:5045d2638c29 575
toddouska 0:5045d2638c29 576 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 577 ssl->keys.dtls_sequence_number = 0;
toddouska 0:5045d2638c29 578 ssl->keys.dtls_peer_sequence_number = 0;
toddouska 0:5045d2638c29 579 ssl->keys.dtls_handshake_number = 0;
toddouska 0:5045d2638c29 580 ssl->keys.dtls_epoch = 0;
toddouska 0:5045d2638c29 581 ssl->keys.dtls_peer_epoch = 0;
toddouska 0:5045d2638c29 582 #endif
toddouska 0:5045d2638c29 583 ssl->keys.encryptionOn = 0; /* initially off */
toddouska 0:5045d2638c29 584 ssl->options.sessionCacheOff = ctx->sessionCacheOff;
toddouska 0:5045d2638c29 585 ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
toddouska 0:5045d2638c29 586
toddouska 0:5045d2638c29 587 ssl->options.verifyPeer = ctx->verifyPeer;
toddouska 0:5045d2638c29 588 ssl->options.verifyNone = ctx->verifyNone;
toddouska 0:5045d2638c29 589 ssl->options.failNoCert = ctx->failNoCert;
toddouska 0:5045d2638c29 590 ssl->options.sendVerify = ctx->sendVerify;
toddouska 0:5045d2638c29 591
toddouska 0:5045d2638c29 592 ssl->options.resuming = 0;
toddouska 0:5045d2638c29 593 ssl->hmac = Hmac; /* default to SSLv3 */
toddouska 0:5045d2638c29 594 ssl->heap = ctx->heap; /* defaults to self */
toddouska 0:5045d2638c29 595 ssl->options.tls = 0;
toddouska 0:5045d2638c29 596 ssl->options.tls1_1 = 0;
toddouska 0:5045d2638c29 597 ssl->options.dtls = 0;
toddouska 0:5045d2638c29 598 ssl->options.partialWrite = ctx->partialWrite;
toddouska 0:5045d2638c29 599 ssl->options.quietShutdown = ctx->quietShutdown;
toddouska 0:5045d2638c29 600
toddouska 0:5045d2638c29 601 /* SSL_CTX still owns certificate, key, and caList buffers */
toddouska 0:5045d2638c29 602 ssl->buffers.certificate = ctx->certificate;
toddouska 0:5045d2638c29 603 ssl->buffers.key = ctx->privateKey;
toddouska 0:5045d2638c29 604 ssl->caList = ctx->caList;
toddouska 0:5045d2638c29 605
toddouska 0:5045d2638c29 606 #ifdef OPENSSL_EXTRA
toddouska 0:5045d2638c29 607 ssl->peerCert.issuer.sz = 0;
toddouska 0:5045d2638c29 608 ssl->peerCert.subject.sz = 0;
toddouska 0:5045d2638c29 609 #endif
toddouska 0:5045d2638c29 610
toddouska 0:5045d2638c29 611 /* make sure server has cert and key unless using PSK */
toddouska 0:5045d2638c29 612 if (ssl->options.side == SERVER_END && !havePSK)
toddouska 0:5045d2638c29 613 if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer)
toddouska 0:5045d2638c29 614 return NO_PRIVATE_KEY;
toddouska 0:5045d2638c29 615
toddouska 0:5045d2638c29 616 #ifndef NO_PSK
toddouska 0:5045d2638c29 617 ssl->arrays.client_identity[0] = 0;
toddouska 0:5045d2638c29 618 if (ctx->server_hint[0]) /* set in CTX */
toddouska 0:5045d2638c29 619 XSTRNCPY(ssl->arrays.server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
toddouska 0:5045d2638c29 620 else
toddouska 0:5045d2638c29 621 ssl->arrays.server_hint[0] = 0;
toddouska 0:5045d2638c29 622 #endif /* NO_PSK */
toddouska 0:5045d2638c29 623
toddouska 0:5045d2638c29 624 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 625 ssl->hsInfoOn = 0;
toddouska 0:5045d2638c29 626 ssl->toInfoOn = 0;
toddouska 0:5045d2638c29 627 #endif
toddouska 0:5045d2638c29 628
toddouska 0:5045d2638c29 629 /* make sure server has DH parms, and add PSK if there, add NTRU too */
toddouska 0:5045d2638c29 630 if (!ssl->ctx->suites.setSuites) { /* trust user override */
toddouska 0:5045d2638c29 631 if (ssl->options.side == SERVER_END)
toddouska 0:5045d2638c29 632 InitSuites(&ssl->suites, ssl->version,ssl->options.haveDH, havePSK,
toddouska 0:5045d2638c29 633 ssl->options.haveNTRU);
toddouska 0:5045d2638c29 634 else
toddouska 0:5045d2638c29 635 InitSuites(&ssl->suites, ssl->version, TRUE, havePSK,
toddouska 0:5045d2638c29 636 ssl->options.haveNTRU);
toddouska 0:5045d2638c29 637 }
toddouska 0:5045d2638c29 638
toddouska 0:5045d2638c29 639 ssl->rfd = -1; /* set to invalid descriptor */
toddouska 0:5045d2638c29 640 ssl->wfd = -1;
toddouska 0:5045d2638c29 641 ssl->biord = 0;
toddouska 0:5045d2638c29 642 ssl->biowr = 0;
toddouska 0:5045d2638c29 643
toddouska 0:5045d2638c29 644 ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer acess if not */
toddouska 0:5045d2638c29 645 ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
toddouska 0:5045d2638c29 646
toddouska 0:5045d2638c29 647 #ifdef SESSION_CERTS
toddouska 0:5045d2638c29 648 ssl->session.chain.count = 0;
toddouska 0:5045d2638c29 649 #endif
toddouska 0:5045d2638c29 650
toddouska 0:5045d2638c29 651 ssl->cipher.ssl = ssl;
toddouska 0:5045d2638c29 652
toddouska 0:5045d2638c29 653 return 0;
toddouska 0:5045d2638c29 654 }
toddouska 0:5045d2638c29 655
toddouska 0:5045d2638c29 656
toddouska 0:5045d2638c29 657 int BIO_free(BIO*); /* cyassl_int doesn't have */
toddouska 0:5045d2638c29 658
toddouska 0:5045d2638c29 659
toddouska 0:5045d2638c29 660 /* In case holding SSL object in array and don't want to free actual ssl */
toddouska 0:5045d2638c29 661 void SSL_ResourceFree(SSL* ssl)
toddouska 0:5045d2638c29 662 {
toddouska 0:5045d2638c29 663 XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 664 XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 665 XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 666 XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 667 XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
toddouska 0:5045d2638c29 668 FreeRsaKey(&ssl->peerRsaKey);
toddouska 0:5045d2638c29 669 if (ssl->buffers.inputBuffer.dynamicFlag)
toddouska 0:5045d2638c29 670 ShrinkInputBuffer(ssl, FORCED_FREE);
toddouska 0:5045d2638c29 671 if (ssl->buffers.outputBuffer.dynamicFlag)
toddouska 0:5045d2638c29 672 ShrinkOutputBuffer(ssl);
toddouska 0:5045d2638c29 673 #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
toddouska 0:5045d2638c29 674 BIO_free(ssl->biord);
toddouska 0:5045d2638c29 675 if (ssl->biord != ssl->biowr) /* in case same as write */
toddouska 0:5045d2638c29 676 BIO_free(ssl->biowr);
toddouska 0:5045d2638c29 677 #endif
toddouska 0:5045d2638c29 678 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 679 FreeStreams(ssl);
toddouska 0:5045d2638c29 680 #endif
toddouska 0:5045d2638c29 681 }
toddouska 0:5045d2638c29 682
toddouska 0:5045d2638c29 683
toddouska 0:5045d2638c29 684 void FreeSSL(SSL* ssl)
toddouska 0:5045d2638c29 685 {
toddouska 0:5045d2638c29 686 SSL_ResourceFree(ssl);
toddouska 0:5045d2638c29 687 XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
toddouska 0:5045d2638c29 688 }
toddouska 0:5045d2638c29 689
toddouska 0:5045d2638c29 690
toddouska 0:5045d2638c29 691 ProtocolVersion MakeSSLv3(void)
toddouska 0:5045d2638c29 692 {
toddouska 0:5045d2638c29 693 ProtocolVersion pv;
toddouska 0:5045d2638c29 694 pv.major = SSLv3_MAJOR;
toddouska 0:5045d2638c29 695 pv.minor = SSLv3_MINOR;
toddouska 0:5045d2638c29 696
toddouska 0:5045d2638c29 697 return pv;
toddouska 0:5045d2638c29 698 }
toddouska 0:5045d2638c29 699
toddouska 0:5045d2638c29 700
toddouska 0:5045d2638c29 701 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 702
toddouska 0:5045d2638c29 703 ProtocolVersion MakeDTLSv1(void)
toddouska 0:5045d2638c29 704 {
toddouska 0:5045d2638c29 705 ProtocolVersion pv;
toddouska 0:5045d2638c29 706 pv.major = DTLS_MAJOR;
toddouska 0:5045d2638c29 707 pv.minor = DTLS_MINOR;
toddouska 0:5045d2638c29 708
toddouska 0:5045d2638c29 709 return pv;
toddouska 0:5045d2638c29 710 }
toddouska 0:5045d2638c29 711
toddouska 0:5045d2638c29 712 #endif /* CYASSL_DTLS */
toddouska 0:5045d2638c29 713
toddouska 0:5045d2638c29 714
toddouska 0:5045d2638c29 715
toddouska 0:5045d2638c29 716
toddouska 0:5045d2638c29 717 #ifdef USE_WINDOWS_API
toddouska 0:5045d2638c29 718
toddouska 0:5045d2638c29 719 timer_d Timer(void)
toddouska 0:5045d2638c29 720 {
toddouska 0:5045d2638c29 721 static int init = 0;
toddouska 0:5045d2638c29 722 static LARGE_INTEGER freq;
toddouska 0:5045d2638c29 723 LARGE_INTEGER count;
toddouska 0:5045d2638c29 724
toddouska 0:5045d2638c29 725 if (!init) {
toddouska 0:5045d2638c29 726 QueryPerformanceFrequency(&freq);
toddouska 0:5045d2638c29 727 init = 1;
toddouska 0:5045d2638c29 728 }
toddouska 0:5045d2638c29 729
toddouska 0:5045d2638c29 730 QueryPerformanceCounter(&count);
toddouska 0:5045d2638c29 731
toddouska 0:5045d2638c29 732 return (double)count.QuadPart / freq.QuadPart;
toddouska 0:5045d2638c29 733 }
toddouska 0:5045d2638c29 734
toddouska 0:5045d2638c29 735
toddouska 0:5045d2638c29 736 word32 LowResTimer(void)
toddouska 0:5045d2638c29 737 {
toddouska 0:5045d2638c29 738 return (word32)Timer();
toddouska 0:5045d2638c29 739 }
toddouska 0:5045d2638c29 740
toddouska 0:5045d2638c29 741
toddouska 0:5045d2638c29 742 #elif defined(THREADX)
toddouska 0:5045d2638c29 743
toddouska 0:5045d2638c29 744 #include "rtptime.h"
toddouska 0:5045d2638c29 745
toddouska 0:5045d2638c29 746 word32 LowResTimer(void)
toddouska 0:5045d2638c29 747 {
toddouska 0:5045d2638c29 748 return (word32)rtp_get_system_sec();
toddouska 0:5045d2638c29 749 }
toddouska 0:5045d2638c29 750
toddouska 0:5045d2638c29 751
toddouska 0:5045d2638c29 752 #elif defined(MICRIUM)
toddouska 0:5045d2638c29 753
toddouska 0:5045d2638c29 754 word32 LowResTimer(void)
toddouska 0:5045d2638c29 755 {
toddouska 0:5045d2638c29 756 NET_SECURE_OS_TICK clk;
toddouska 0:5045d2638c29 757
toddouska 0:5045d2638c29 758 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
toddouska 0:5045d2638c29 759 clk = NetSecure_OS_TimeGet();
toddouska 0:5045d2638c29 760 #endif
toddouska 0:5045d2638c29 761 return (word32)clk;
toddouska 0:5045d2638c29 762 }
toddouska 0:5045d2638c29 763
toddouska 0:5045d2638c29 764 #elif defined(USER_TICKS)
toddouska 0:5045d2638c29 765
toddouska 0:5045d2638c29 766 word32 LowResTimer(void)
toddouska 0:5045d2638c29 767 {
toddouska 0:5045d2638c29 768 /*
toddouska 0:5045d2638c29 769 write your own clock tick function if don't want time(0)
toddouska 0:5045d2638c29 770 needs second accuracy but doesn't have to correlated to EPOCH
toddouska 0:5045d2638c29 771 */
toddouska 0:5045d2638c29 772 }
toddouska 0:5045d2638c29 773
toddouska 0:5045d2638c29 774 #else /* !USE_WINDOWS_API && !THREADX && !MICRIUM && !USER_TICKS */
toddouska 0:5045d2638c29 775
toddouska 0:5045d2638c29 776 #include <time.h>
toddouska 0:5045d2638c29 777
toddouska 0:5045d2638c29 778 word32 LowResTimer(void)
toddouska 0:5045d2638c29 779 {
toddouska 0:5045d2638c29 780 return time(0);
toddouska 0:5045d2638c29 781 }
toddouska 0:5045d2638c29 782
toddouska 0:5045d2638c29 783
toddouska 0:5045d2638c29 784 #endif /* USE_WINDOWS_API */
toddouska 0:5045d2638c29 785
toddouska 0:5045d2638c29 786
toddouska 0:5045d2638c29 787 /* add output to md5 and sha handshake hashes, exclude record header */
toddouska 0:5045d2638c29 788 static void HashOutput(SSL* ssl, const byte* output, int sz, int ivSz)
toddouska 0:5045d2638c29 789 {
toddouska 0:5045d2638c29 790 const byte* buffer = output + RECORD_HEADER_SZ + ivSz;
toddouska 0:5045d2638c29 791 sz -= RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 792
toddouska 0:5045d2638c29 793 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 794 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 795 buffer += DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 796 sz -= DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 797 }
toddouska 0:5045d2638c29 798 #endif
toddouska 0:5045d2638c29 799
toddouska 0:5045d2638c29 800 Md5Update(&ssl->hashMd5, buffer, sz);
toddouska 0:5045d2638c29 801 ShaUpdate(&ssl->hashSha, buffer, sz);
toddouska 0:5045d2638c29 802 }
toddouska 0:5045d2638c29 803
toddouska 0:5045d2638c29 804
toddouska 0:5045d2638c29 805 /* add input to md5 and sha handshake hashes, include handshake header */
toddouska 0:5045d2638c29 806 static void HashInput(SSL* ssl, const byte* input, int sz)
toddouska 0:5045d2638c29 807 {
toddouska 0:5045d2638c29 808 const byte* buffer = input - HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 809 sz += HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 810
toddouska 0:5045d2638c29 811 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 812 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 813 buffer -= DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 814 sz += DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 815 }
toddouska 0:5045d2638c29 816 #endif
toddouska 0:5045d2638c29 817
toddouska 0:5045d2638c29 818 Md5Update(&ssl->hashMd5, buffer, sz);
toddouska 0:5045d2638c29 819 ShaUpdate(&ssl->hashSha, buffer, sz);
toddouska 0:5045d2638c29 820 }
toddouska 0:5045d2638c29 821
toddouska 0:5045d2638c29 822
toddouska 0:5045d2638c29 823 /* add record layer header for message */
toddouska 0:5045d2638c29 824 static void AddRecordHeader(byte* output, word32 length, byte type, SSL* ssl)
toddouska 0:5045d2638c29 825 {
toddouska 0:5045d2638c29 826 RecordLayerHeader* rl;
toddouska 0:5045d2638c29 827
toddouska 0:5045d2638c29 828 /* record layer header */
toddouska 0:5045d2638c29 829 rl = (RecordLayerHeader*)output;
toddouska 0:5045d2638c29 830 rl->type = type;
toddouska 0:5045d2638c29 831 rl->version = ssl->version; /* type and version same in each */
toddouska 0:5045d2638c29 832
toddouska 0:5045d2638c29 833 if (!ssl->options.dtls)
toddouska 0:5045d2638c29 834 c16toa((word16)length, rl->length);
toddouska 0:5045d2638c29 835 else {
toddouska 0:5045d2638c29 836 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 837 DtlsRecordLayerHeader* dtls;
toddouska 0:5045d2638c29 838
toddouska 0:5045d2638c29 839 /* dtls record layer header extensions */
toddouska 0:5045d2638c29 840 dtls = (DtlsRecordLayerHeader*)output;
toddouska 0:5045d2638c29 841 c16toa(ssl->keys.dtls_epoch, dtls->epoch);
toddouska 0:5045d2638c29 842 c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
toddouska 0:5045d2638c29 843 c16toa((word16)length, dtls->length);
toddouska 0:5045d2638c29 844 #endif
toddouska 0:5045d2638c29 845 }
toddouska 0:5045d2638c29 846 }
toddouska 0:5045d2638c29 847
toddouska 0:5045d2638c29 848
toddouska 0:5045d2638c29 849 /* add handshake header for message */
toddouska 0:5045d2638c29 850 static void AddHandShakeHeader(byte* output, word32 length, byte type, SSL* ssl)
toddouska 0:5045d2638c29 851 {
toddouska 0:5045d2638c29 852 HandShakeHeader* hs;
toddouska 0:5045d2638c29 853
toddouska 0:5045d2638c29 854 /* handshake header */
toddouska 0:5045d2638c29 855 hs = (HandShakeHeader*)output;
toddouska 0:5045d2638c29 856 hs->type = type;
toddouska 0:5045d2638c29 857 c32to24(length, hs->length); /* type and length same for each */
toddouska 0:5045d2638c29 858 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 859 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 860 DtlsHandShakeHeader* dtls;
toddouska 0:5045d2638c29 861
toddouska 0:5045d2638c29 862 /* dtls handshake header extensions */
toddouska 0:5045d2638c29 863 dtls = (DtlsHandShakeHeader*)output;
toddouska 0:5045d2638c29 864 c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
toddouska 0:5045d2638c29 865 c32to24(0, dtls->fragment_offset);
toddouska 0:5045d2638c29 866 c32to24(length, dtls->fragment_length);
toddouska 0:5045d2638c29 867 }
toddouska 0:5045d2638c29 868 #endif
toddouska 0:5045d2638c29 869 }
toddouska 0:5045d2638c29 870
toddouska 0:5045d2638c29 871
toddouska 0:5045d2638c29 872 /* add both headers for handshake message */
toddouska 0:5045d2638c29 873 static void AddHeaders(byte* output, word32 length, byte type, SSL* ssl)
toddouska 0:5045d2638c29 874 {
toddouska 0:5045d2638c29 875 if (!ssl->options.dtls) {
toddouska 0:5045d2638c29 876 AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl);
toddouska 0:5045d2638c29 877 AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl);
toddouska 0:5045d2638c29 878 }
toddouska 0:5045d2638c29 879 else {
toddouska 0:5045d2638c29 880 AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl);
toddouska 0:5045d2638c29 881 AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl);
toddouska 0:5045d2638c29 882 }
toddouska 0:5045d2638c29 883 }
toddouska 0:5045d2638c29 884
toddouska 0:5045d2638c29 885
toddouska 0:5045d2638c29 886 static int Receive(SSL* ssl, byte* buf, word32 sz, int flags)
toddouska 0:5045d2638c29 887 {
toddouska 0:5045d2638c29 888 int recvd;
toddouska 0:5045d2638c29 889
toddouska 0:5045d2638c29 890 retry:
toddouska 0:5045d2638c29 891 recvd = ssl->ctx->CBIORecv((char *)buf, (int)sz, ssl->IOCB_ReadCtx);
toddouska 0:5045d2638c29 892 if (recvd < 0)
toddouska 0:5045d2638c29 893 switch (recvd) {
toddouska 0:5045d2638c29 894 case IO_ERR_GENERAL: /* general/unknown error */
toddouska 0:5045d2638c29 895 return -1;
toddouska 0:5045d2638c29 896
toddouska 0:5045d2638c29 897 case IO_ERR_WANT_READ: /* want read, would block */
toddouska 0:5045d2638c29 898 return WANT_READ;
toddouska 0:5045d2638c29 899
toddouska 0:5045d2638c29 900 case IO_ERR_CONN_RST: /* connection reset */
toddouska 0:5045d2638c29 901 ssl->options.connReset = 1;
toddouska 0:5045d2638c29 902 return -1;
toddouska 0:5045d2638c29 903
toddouska 0:5045d2638c29 904 case IO_ERR_ISR: /* interrupt */
toddouska 0:5045d2638c29 905 /* see if we got our timeout */
toddouska 0:5045d2638c29 906 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 907 if (ssl->toInfoOn) {
toddouska 0:5045d2638c29 908 struct itimerval timeout;
toddouska 0:5045d2638c29 909 getitimer(ITIMER_REAL, &timeout);
toddouska 0:5045d2638c29 910 if (timeout.it_value.tv_sec == 0 &&
toddouska 0:5045d2638c29 911 timeout.it_value.tv_usec == 0) {
toddouska 0:5045d2638c29 912 XSTRNCPY(ssl->timeoutInfo.timeoutName,
toddouska 0:5045d2638c29 913 "recv() timeout", MAX_TIMEOUT_NAME_SZ);
toddouska 0:5045d2638c29 914 return 0;
toddouska 0:5045d2638c29 915 }
toddouska 0:5045d2638c29 916 }
toddouska 0:5045d2638c29 917 #endif
toddouska 0:5045d2638c29 918 goto retry;
toddouska 0:5045d2638c29 919
toddouska 0:5045d2638c29 920 case IO_ERR_CONN_CLOSE: /* peer closed connection */
toddouska 0:5045d2638c29 921 ssl->options.isClosed = 1;
toddouska 0:5045d2638c29 922 return -1;
toddouska 0:5045d2638c29 923 }
toddouska 0:5045d2638c29 924
toddouska 0:5045d2638c29 925 return recvd;
toddouska 0:5045d2638c29 926 }
toddouska 0:5045d2638c29 927
toddouska 0:5045d2638c29 928
toddouska 0:5045d2638c29 929 /* Switch dynamic output buffer back to static, buffer is assumed clear */
toddouska 0:5045d2638c29 930 void ShrinkOutputBuffer(SSL* ssl)
toddouska 0:5045d2638c29 931 {
toddouska 0:5045d2638c29 932 CYASSL_MSG("Shrinking output buffer\n");
toddouska 0:5045d2638c29 933 XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
toddouska 0:5045d2638c29 934 ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
toddouska 0:5045d2638c29 935 ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
toddouska 0:5045d2638c29 936 ssl->buffers.outputBuffer.dynamicFlag = 0;
toddouska 0:5045d2638c29 937 }
toddouska 0:5045d2638c29 938
toddouska 0:5045d2638c29 939
toddouska 0:5045d2638c29 940 /* Switch dynamic input buffer back to static, keep any remaining input */
toddouska 0:5045d2638c29 941 /* forced free means cleaning up */
toddouska 0:5045d2638c29 942 void ShrinkInputBuffer(SSL* ssl, int forcedFree)
toddouska 0:5045d2638c29 943 {
toddouska 0:5045d2638c29 944 int usedLength = ssl->buffers.inputBuffer.length -
toddouska 0:5045d2638c29 945 ssl->buffers.inputBuffer.idx;
toddouska 0:5045d2638c29 946 if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
toddouska 0:5045d2638c29 947 return;
toddouska 0:5045d2638c29 948
toddouska 0:5045d2638c29 949 CYASSL_MSG("Shrinking input buffer\n");
toddouska 0:5045d2638c29 950
toddouska 0:5045d2638c29 951 if (!forcedFree && usedLength)
toddouska 0:5045d2638c29 952 XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
toddouska 0:5045d2638c29 953 ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 954 usedLength);
toddouska 0:5045d2638c29 955
toddouska 0:5045d2638c29 956 XFREE(ssl->buffers.inputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
toddouska 0:5045d2638c29 957 ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
toddouska 0:5045d2638c29 958 ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
toddouska 0:5045d2638c29 959 ssl->buffers.inputBuffer.dynamicFlag = 0;
toddouska 0:5045d2638c29 960 ssl->buffers.inputBuffer.idx = 0;
toddouska 0:5045d2638c29 961 ssl->buffers.inputBuffer.length = usedLength;
toddouska 0:5045d2638c29 962 }
toddouska 0:5045d2638c29 963
toddouska 0:5045d2638c29 964
toddouska 0:5045d2638c29 965 int SendBuffered(SSL* ssl)
toddouska 0:5045d2638c29 966 {
toddouska 0:5045d2638c29 967 while (ssl->buffers.outputBuffer.length > 0) {
toddouska 0:5045d2638c29 968 int sent = ssl->ctx->CBIOSend((char*)ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 969 ssl->buffers.outputBuffer.idx,
toddouska 0:5045d2638c29 970 (int)ssl->buffers.outputBuffer.length,
toddouska 0:5045d2638c29 971 ssl->IOCB_WriteCtx);
toddouska 0:5045d2638c29 972 if (sent < 0) {
toddouska 0:5045d2638c29 973 switch (sent) {
toddouska 0:5045d2638c29 974
toddouska 0:5045d2638c29 975 case IO_ERR_WANT_WRITE: /* would block */
toddouska 0:5045d2638c29 976 return WANT_WRITE;
toddouska 0:5045d2638c29 977
toddouska 0:5045d2638c29 978 case IO_ERR_CONN_RST: /* connection reset */
toddouska 0:5045d2638c29 979 ssl->options.connReset = 1;
toddouska 0:5045d2638c29 980 break;
toddouska 0:5045d2638c29 981
toddouska 0:5045d2638c29 982 case IO_ERR_ISR: /* interrupt */
toddouska 0:5045d2638c29 983 /* see if we got our timeout */
toddouska 0:5045d2638c29 984 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 985 if (ssl->toInfoOn) {
toddouska 0:5045d2638c29 986 struct itimerval timeout;
toddouska 0:5045d2638c29 987 getitimer(ITIMER_REAL, &timeout);
toddouska 0:5045d2638c29 988 if (timeout.it_value.tv_sec == 0 &&
toddouska 0:5045d2638c29 989 timeout.it_value.tv_usec == 0) {
toddouska 0:5045d2638c29 990 XSTRNCPY(ssl->timeoutInfo.timeoutName,
toddouska 0:5045d2638c29 991 "send() timeout", MAX_TIMEOUT_NAME_SZ);
toddouska 0:5045d2638c29 992 return WANT_WRITE;
toddouska 0:5045d2638c29 993 }
toddouska 0:5045d2638c29 994 }
toddouska 0:5045d2638c29 995 #endif
toddouska 0:5045d2638c29 996 continue;
toddouska 0:5045d2638c29 997
toddouska 0:5045d2638c29 998 case IO_ERR_CONN_CLOSE: /* epipe / conn closed, same as reset */
toddouska 0:5045d2638c29 999 ssl->options.connReset = 1;
toddouska 0:5045d2638c29 1000 break;
toddouska 0:5045d2638c29 1001 }
toddouska 0:5045d2638c29 1002
toddouska 0:5045d2638c29 1003 return SOCKET_ERROR_E;
toddouska 0:5045d2638c29 1004 }
toddouska 0:5045d2638c29 1005
toddouska 0:5045d2638c29 1006 ssl->buffers.outputBuffer.idx += sent;
toddouska 0:5045d2638c29 1007 ssl->buffers.outputBuffer.length -= sent;
toddouska 0:5045d2638c29 1008 }
toddouska 0:5045d2638c29 1009
toddouska 0:5045d2638c29 1010 ssl->buffers.outputBuffer.idx = 0;
toddouska 0:5045d2638c29 1011
toddouska 0:5045d2638c29 1012 if (ssl->buffers.outputBuffer.dynamicFlag)
toddouska 0:5045d2638c29 1013 ShrinkOutputBuffer(ssl);
toddouska 0:5045d2638c29 1014
toddouska 0:5045d2638c29 1015 return 0;
toddouska 0:5045d2638c29 1016 }
toddouska 0:5045d2638c29 1017
toddouska 0:5045d2638c29 1018
toddouska 0:5045d2638c29 1019 /* Grow the output buffer, should only be to send cert, should be blank */
toddouska 0:5045d2638c29 1020 static INLINE int GrowOutputBuffer(SSL* ssl, int size)
toddouska 0:5045d2638c29 1021 {
toddouska 0:5045d2638c29 1022 byte* tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length,
toddouska 0:5045d2638c29 1023 ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
toddouska 0:5045d2638c29 1024 CYASSL_MSG("growing output buffer\n");
toddouska 0:5045d2638c29 1025
toddouska 0:5045d2638c29 1026 if (!tmp) return -1;
toddouska 0:5045d2638c29 1027
toddouska 0:5045d2638c29 1028 if (ssl->buffers.outputBuffer.length)
toddouska 0:5045d2638c29 1029 XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
toddouska 0:5045d2638c29 1030 ssl->buffers.outputBuffer.length);
toddouska 0:5045d2638c29 1031
toddouska 0:5045d2638c29 1032 if (ssl->buffers.outputBuffer.dynamicFlag)
toddouska 0:5045d2638c29 1033 XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap,
toddouska 0:5045d2638c29 1034 DYNAMIC_TYPE_OUT_BUFFER);
toddouska 0:5045d2638c29 1035 ssl->buffers.outputBuffer.dynamicFlag = 1;
toddouska 0:5045d2638c29 1036 ssl->buffers.outputBuffer.buffer = tmp;
toddouska 0:5045d2638c29 1037 ssl->buffers.outputBuffer.bufferSize = size +
toddouska 0:5045d2638c29 1038 ssl->buffers.outputBuffer.length;
toddouska 0:5045d2638c29 1039 return 0;
toddouska 0:5045d2638c29 1040 }
toddouska 0:5045d2638c29 1041
toddouska 0:5045d2638c29 1042
toddouska 0:5045d2638c29 1043 /* Grow the input buffer, should only be to read cert or big app data */
toddouska 0:5045d2638c29 1044 static INLINE int GrowInputBuffer(SSL* ssl, int size, int usedLength)
toddouska 0:5045d2638c29 1045 {
toddouska 0:5045d2638c29 1046 byte* tmp = (byte*) XMALLOC(size + usedLength, ssl->heap,
toddouska 0:5045d2638c29 1047 DYNAMIC_TYPE_IN_BUFFER);
toddouska 0:5045d2638c29 1048 CYASSL_MSG("growing input buffer\n");
toddouska 0:5045d2638c29 1049
toddouska 0:5045d2638c29 1050 if (!tmp) return -1;
toddouska 0:5045d2638c29 1051
toddouska 0:5045d2638c29 1052 if (usedLength)
toddouska 0:5045d2638c29 1053 XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
toddouska 0:5045d2638c29 1054 ssl->buffers.inputBuffer.idx, usedLength);
toddouska 0:5045d2638c29 1055
toddouska 0:5045d2638c29 1056 if (ssl->buffers.inputBuffer.dynamicFlag)
toddouska 0:5045d2638c29 1057 XFREE(ssl->buffers.inputBuffer.buffer,ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
toddouska 0:5045d2638c29 1058
toddouska 0:5045d2638c29 1059 ssl->buffers.inputBuffer.dynamicFlag = 1;
toddouska 0:5045d2638c29 1060 ssl->buffers.inputBuffer.buffer = tmp;
toddouska 0:5045d2638c29 1061 ssl->buffers.inputBuffer.bufferSize = size + usedLength;
toddouska 0:5045d2638c29 1062 ssl->buffers.inputBuffer.idx = 0;
toddouska 0:5045d2638c29 1063 ssl->buffers.inputBuffer.length = usedLength;
toddouska 0:5045d2638c29 1064
toddouska 0:5045d2638c29 1065 return 0;
toddouska 0:5045d2638c29 1066 }
toddouska 0:5045d2638c29 1067
toddouska 0:5045d2638c29 1068
toddouska 0:5045d2638c29 1069 /* check avalaible size into outbut buffer */
toddouska 0:5045d2638c29 1070 static INLINE int CheckAvalaibleSize(SSL *ssl, int size)
toddouska 0:5045d2638c29 1071 {
toddouska 0:5045d2638c29 1072 if ((word32)size > ssl->buffers.outputBuffer.bufferSize)
toddouska 0:5045d2638c29 1073 if (GrowOutputBuffer(ssl, size) < 0)
toddouska 0:5045d2638c29 1074 return MEMORY_E;
toddouska 0:5045d2638c29 1075
toddouska 0:5045d2638c29 1076 if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
toddouska 0:5045d2638c29 1077 < (word32)size) {
toddouska 0:5045d2638c29 1078 if (SendBuffered(ssl) == SOCKET_ERROR_E)
toddouska 0:5045d2638c29 1079 return SOCKET_ERROR_E;
toddouska 0:5045d2638c29 1080 if (ssl->buffers.outputBuffer.bufferSize -
toddouska 0:5045d2638c29 1081 ssl->buffers.outputBuffer.length < (word32)size)
toddouska 0:5045d2638c29 1082 return WANT_WRITE;
toddouska 0:5045d2638c29 1083 }
toddouska 0:5045d2638c29 1084 return 0;
toddouska 0:5045d2638c29 1085 }
toddouska 0:5045d2638c29 1086
toddouska 0:5045d2638c29 1087 /* do all verify and sanity checks on record header */
toddouska 0:5045d2638c29 1088 static int GetRecordHeader(SSL* ssl, const byte* input, word32* inOutIdx,
toddouska 0:5045d2638c29 1089 RecordLayerHeader* rh, word16 *size)
toddouska 0:5045d2638c29 1090 {
toddouska 0:5045d2638c29 1091 if (!ssl->options.dtls) {
toddouska 0:5045d2638c29 1092 XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
toddouska 0:5045d2638c29 1093 *inOutIdx += RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 1094 ato16(rh->length, size);
toddouska 0:5045d2638c29 1095 }
toddouska 0:5045d2638c29 1096 else {
toddouska 0:5045d2638c29 1097 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1098 /* type and version in same sport */
toddouska 0:5045d2638c29 1099 XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
toddouska 0:5045d2638c29 1100 *inOutIdx += ENUM_LEN + VERSION_SZ;
toddouska 0:5045d2638c29 1101 *inOutIdx += 4; /* skip epoch and first 2 seq bytes for now */
toddouska 0:5045d2638c29 1102 ato32(input + *inOutIdx, &ssl->keys.dtls_peer_sequence_number);
toddouska 0:5045d2638c29 1103 *inOutIdx += 4; /* advance past rest of seq */
toddouska 0:5045d2638c29 1104 ato16(input + *inOutIdx, size);
toddouska 0:5045d2638c29 1105 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 1106 #endif
toddouska 0:5045d2638c29 1107 }
toddouska 0:5045d2638c29 1108
toddouska 0:5045d2638c29 1109 /* catch version mismatch */
toddouska 0:5045d2638c29 1110 if (rh->version.major != ssl->version.major ||
toddouska 0:5045d2638c29 1111 rh->version.minor != ssl->version.minor) {
toddouska 0:5045d2638c29 1112
toddouska 0:5045d2638c29 1113 if (ssl->options.side == SERVER_END && ssl->options.downgrade == 1 &&
toddouska 0:5045d2638c29 1114 ssl->options.acceptState == ACCEPT_BEGIN)
toddouska 0:5045d2638c29 1115 ; /* haven't negotiated yet */
toddouska 0:5045d2638c29 1116 else
toddouska 0:5045d2638c29 1117 return VERSION_ERROR; /* only use requested version */
toddouska 0:5045d2638c29 1118 }
toddouska 0:5045d2638c29 1119
toddouska 0:5045d2638c29 1120 /* record layer length check */
toddouska 0:5045d2638c29 1121 if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
toddouska 0:5045d2638c29 1122 return LENGTH_ERROR;
toddouska 0:5045d2638c29 1123
toddouska 0:5045d2638c29 1124 /* verify record type here as well */
toddouska 0:5045d2638c29 1125 switch ((enum ContentType)rh->type) {
toddouska 0:5045d2638c29 1126 case handshake:
toddouska 0:5045d2638c29 1127 case change_cipher_spec:
toddouska 0:5045d2638c29 1128 case application_data:
toddouska 0:5045d2638c29 1129 case alert:
toddouska 0:5045d2638c29 1130 break;
toddouska 0:5045d2638c29 1131 default:
toddouska 0:5045d2638c29 1132 return UNKNOWN_RECORD_TYPE;
toddouska 0:5045d2638c29 1133 }
toddouska 0:5045d2638c29 1134
toddouska 0:5045d2638c29 1135 return 0;
toddouska 0:5045d2638c29 1136 }
toddouska 0:5045d2638c29 1137
toddouska 0:5045d2638c29 1138
toddouska 0:5045d2638c29 1139 static int GetHandShakeHeader(SSL* ssl, const byte* input, word32* inOutIdx,
toddouska 0:5045d2638c29 1140 byte *type, word32 *size)
toddouska 0:5045d2638c29 1141 {
toddouska 0:5045d2638c29 1142 const byte *ptr = input + *inOutIdx;
toddouska 0:5045d2638c29 1143 *inOutIdx += HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 1144
toddouska 0:5045d2638c29 1145 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1146 if (ssl->options.dtls)
toddouska 0:5045d2638c29 1147 *inOutIdx += DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 1148 #endif
toddouska 0:5045d2638c29 1149
toddouska 0:5045d2638c29 1150 *type = ptr[0];
toddouska 0:5045d2638c29 1151 c24to32(&ptr[1], size);
toddouska 0:5045d2638c29 1152
toddouska 0:5045d2638c29 1153 return 0;
toddouska 0:5045d2638c29 1154 }
toddouska 0:5045d2638c29 1155
toddouska 0:5045d2638c29 1156
toddouska 0:5045d2638c29 1157 /* fill with MD5 pad size since biggest required */
toddouska 0:5045d2638c29 1158 static const byte PAD1[PAD_MD5] =
toddouska 0:5045d2638c29 1159 { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
toddouska 0:5045d2638c29 1160 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
toddouska 0:5045d2638c29 1161 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
toddouska 0:5045d2638c29 1162 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
toddouska 0:5045d2638c29 1163 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
toddouska 0:5045d2638c29 1164 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
toddouska 0:5045d2638c29 1165 };
toddouska 0:5045d2638c29 1166 static const byte PAD2[PAD_MD5] =
toddouska 0:5045d2638c29 1167 { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
toddouska 0:5045d2638c29 1168 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
toddouska 0:5045d2638c29 1169 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
toddouska 0:5045d2638c29 1170 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
toddouska 0:5045d2638c29 1171 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
toddouska 0:5045d2638c29 1172 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
toddouska 0:5045d2638c29 1173 };
toddouska 0:5045d2638c29 1174
toddouska 0:5045d2638c29 1175 /* calculate MD5 hash for finished */
toddouska 0:5045d2638c29 1176 static void BuildMD5(SSL* ssl, Hashes* hashes, const byte* sender)
toddouska 0:5045d2638c29 1177 {
toddouska 0:5045d2638c29 1178 byte md5_result[MD5_DIGEST_SIZE];
toddouska 0:5045d2638c29 1179
toddouska 0:5045d2638c29 1180 /* make md5 inner */
toddouska 0:5045d2638c29 1181 Md5Update(&ssl->hashMd5, sender, SIZEOF_SENDER);
toddouska 0:5045d2638c29 1182 Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 1183 Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
toddouska 0:5045d2638c29 1184 Md5Final(&ssl->hashMd5, md5_result);
toddouska 0:5045d2638c29 1185
toddouska 0:5045d2638c29 1186 /* make md5 outer */
toddouska 0:5045d2638c29 1187 Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 1188 Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
toddouska 0:5045d2638c29 1189 Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
toddouska 0:5045d2638c29 1190
toddouska 0:5045d2638c29 1191 Md5Final(&ssl->hashMd5, hashes->md5);
toddouska 0:5045d2638c29 1192 }
toddouska 0:5045d2638c29 1193
toddouska 0:5045d2638c29 1194
toddouska 0:5045d2638c29 1195 /* calculate SHA hash for finished */
toddouska 0:5045d2638c29 1196 static void BuildSHA(SSL* ssl, Hashes* hashes, const byte* sender)
toddouska 0:5045d2638c29 1197 {
toddouska 0:5045d2638c29 1198 byte sha_result[SHA_DIGEST_SIZE];
toddouska 0:5045d2638c29 1199
toddouska 0:5045d2638c29 1200 /* make sha inner */
toddouska 0:5045d2638c29 1201 ShaUpdate(&ssl->hashSha, sender, SIZEOF_SENDER);
toddouska 0:5045d2638c29 1202 ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 1203 ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
toddouska 0:5045d2638c29 1204 ShaFinal(&ssl->hashSha, sha_result);
toddouska 0:5045d2638c29 1205
toddouska 0:5045d2638c29 1206 /* make sha outer */
toddouska 0:5045d2638c29 1207 ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 1208 ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
toddouska 0:5045d2638c29 1209 ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
toddouska 0:5045d2638c29 1210
toddouska 0:5045d2638c29 1211 ShaFinal(&ssl->hashSha, hashes->sha);
toddouska 0:5045d2638c29 1212 }
toddouska 0:5045d2638c29 1213
toddouska 0:5045d2638c29 1214
toddouska 0:5045d2638c29 1215 static void BuildFinished(SSL* ssl, Hashes* hashes, const byte* sender)
toddouska 0:5045d2638c29 1216 {
toddouska 0:5045d2638c29 1217 /* store current states, building requires get_digest which resets state */
toddouska 0:5045d2638c29 1218 Md5 md5 = ssl->hashMd5;
toddouska 0:5045d2638c29 1219 Sha sha = ssl->hashSha;
toddouska 0:5045d2638c29 1220
toddouska 0:5045d2638c29 1221 if (ssl->options.tls)
toddouska 0:5045d2638c29 1222 BuildTlsFinished(ssl, hashes, sender);
toddouska 0:5045d2638c29 1223 else {
toddouska 0:5045d2638c29 1224 BuildMD5(ssl, hashes, sender);
toddouska 0:5045d2638c29 1225 BuildSHA(ssl, hashes, sender);
toddouska 0:5045d2638c29 1226 }
toddouska 0:5045d2638c29 1227
toddouska 0:5045d2638c29 1228 /* restore */
toddouska 0:5045d2638c29 1229 ssl->hashMd5 = md5;
toddouska 0:5045d2638c29 1230 ssl->hashSha = sha;
toddouska 0:5045d2638c29 1231 }
toddouska 0:5045d2638c29 1232
toddouska 0:5045d2638c29 1233
toddouska 0:5045d2638c29 1234 static int DoCertificate(SSL* ssl, byte* input, word32* inOutIdx)
toddouska 0:5045d2638c29 1235 {
toddouska 0:5045d2638c29 1236 word32 listSz, i = *inOutIdx;
toddouska 0:5045d2638c29 1237 int ret = 0;
toddouska 0:5045d2638c29 1238 int firstTime = 1; /* peer's is at front */
toddouska 0:5045d2638c29 1239 char domain[ASN_NAME_MAX];
toddouska 0:5045d2638c29 1240
toddouska 0:5045d2638c29 1241 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 1242 if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 1243 if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 1244 #endif
toddouska 0:5045d2638c29 1245 c24to32(&input[i], &listSz);
toddouska 0:5045d2638c29 1246 i += CERT_HEADER_SZ;
toddouska 0:5045d2638c29 1247
toddouska 0:5045d2638c29 1248 while (listSz && ret == 0) {
toddouska 0:5045d2638c29 1249 /* cert size */
toddouska 0:5045d2638c29 1250 buffer myCert;
toddouska 0:5045d2638c29 1251 word32 certSz;
toddouska 0:5045d2638c29 1252 DecodedCert dCert;
toddouska 0:5045d2638c29 1253 word32 idx = 0;
toddouska 0:5045d2638c29 1254
toddouska 0:5045d2638c29 1255 c24to32(&input[i], &certSz);
toddouska 0:5045d2638c29 1256 i += CERT_HEADER_SZ;
toddouska 0:5045d2638c29 1257
toddouska 0:5045d2638c29 1258 myCert.length = certSz;
toddouska 0:5045d2638c29 1259 myCert.buffer = input + i;
toddouska 0:5045d2638c29 1260 i += certSz;
toddouska 0:5045d2638c29 1261
toddouska 0:5045d2638c29 1262 listSz -= certSz + CERT_HEADER_SZ;
toddouska 0:5045d2638c29 1263
toddouska 0:5045d2638c29 1264 #ifdef SESSION_CERTS
toddouska 0:5045d2638c29 1265 if (ssl->session.chain.count < MAX_CHAIN_DEPTH &&
toddouska 0:5045d2638c29 1266 myCert.length < MAX_X509_SIZE) {
toddouska 0:5045d2638c29 1267 ssl->session.chain.certs[ssl->session.chain.count].length =
toddouska 0:5045d2638c29 1268 myCert.length;
toddouska 0:5045d2638c29 1269 XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer,
toddouska 0:5045d2638c29 1270 myCert.buffer, myCert.length);
toddouska 0:5045d2638c29 1271 ssl->session.chain.count++;
toddouska 0:5045d2638c29 1272 } else {
toddouska 0:5045d2638c29 1273 CYASSL_MSG("Couldn't store chain cert for session");
toddouska 0:5045d2638c29 1274 }
toddouska 0:5045d2638c29 1275 #endif
toddouska 0:5045d2638c29 1276
toddouska 0:5045d2638c29 1277 InitDecodedCert(&dCert, myCert.buffer, ssl->heap);
toddouska 0:5045d2638c29 1278 ret = ParseCertRelative(&dCert, myCert.length, CERT_TYPE,
toddouska 0:5045d2638c29 1279 !ssl->options.verifyNone, ssl->caList);
toddouska 0:5045d2638c29 1280
toddouska 0:5045d2638c29 1281 if (!firstTime) {
toddouska 0:5045d2638c29 1282 FreeDecodedCert(&dCert);
toddouska 0:5045d2638c29 1283 continue;
toddouska 0:5045d2638c29 1284 }
toddouska 0:5045d2638c29 1285
toddouska 0:5045d2638c29 1286 /* get rest of peer info in case user wants to continue */
toddouska 0:5045d2638c29 1287 if (ret != 0) {
toddouska 0:5045d2638c29 1288 if (!(ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E ||
toddouska 0:5045d2638c29 1289 ret == ASN_SIG_CONFIRM_E)) {
toddouska 0:5045d2638c29 1290 FreeDecodedCert(&dCert);
toddouska 0:5045d2638c29 1291 continue;
toddouska 0:5045d2638c29 1292 }
toddouska 0:5045d2638c29 1293 }
toddouska 0:5045d2638c29 1294
toddouska 0:5045d2638c29 1295 /* first one has peer's key */
toddouska 0:5045d2638c29 1296 firstTime = 0;
toddouska 0:5045d2638c29 1297
toddouska 0:5045d2638c29 1298 ssl->options.havePeerCert = 1;
toddouska 0:5045d2638c29 1299 /* set X509 format */
toddouska 0:5045d2638c29 1300 #ifdef OPENSSL_EXTRA
toddouska 0:5045d2638c29 1301 ssl->peerCert.issuer.sz = (int)XSTRLEN(dCert.issuer) + 1;
toddouska 0:5045d2638c29 1302 XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
toddouska 0:5045d2638c29 1303 ssl->peerCert.subject.sz = (int)XSTRLEN(dCert.subject) + 1;
toddouska 0:5045d2638c29 1304 XSTRNCPY(ssl->peerCert.subject.name, dCert.subject, ASN_NAME_MAX);
toddouska 0:5045d2638c29 1305 #endif
toddouska 0:5045d2638c29 1306
toddouska 0:5045d2638c29 1307 XMEMCPY(domain, dCert.subjectCN, dCert.subjectCNLen);
toddouska 0:5045d2638c29 1308 domain[dCert.subjectCNLen] = '\0';
toddouska 0:5045d2638c29 1309
toddouska 0:5045d2638c29 1310 if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer)
toddouska 0:5045d2638c29 1311 if (XSTRNCMP((char*)ssl->buffers.domainName.buffer,
toddouska 0:5045d2638c29 1312 dCert.subjectCN,
toddouska 0:5045d2638c29 1313 ssl->buffers.domainName.length - 1)) {
toddouska 0:5045d2638c29 1314 ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */
toddouska 0:5045d2638c29 1315 }
toddouska 0:5045d2638c29 1316
toddouska 0:5045d2638c29 1317 /* decode peer key */
toddouska 0:5045d2638c29 1318 if (dCert.keyOID == RSAk) {
toddouska 0:5045d2638c29 1319 if (RsaPublicKeyDecode(dCert.publicKey, &idx,
toddouska 0:5045d2638c29 1320 &ssl->peerRsaKey, dCert.pubKeySize) != 0) {
toddouska 0:5045d2638c29 1321 ret = PEER_KEY_ERROR;
toddouska 0:5045d2638c29 1322 FreeDecodedCert(&dCert);
toddouska 0:5045d2638c29 1323 continue;
toddouska 0:5045d2638c29 1324 }
toddouska 0:5045d2638c29 1325 ssl->peerRsaKeyPresent = 1;
toddouska 0:5045d2638c29 1326 }
toddouska 0:5045d2638c29 1327 #ifdef HAVE_NTRU
toddouska 0:5045d2638c29 1328 else if (dCert.keyOID == NTRUk) {
toddouska 0:5045d2638c29 1329 if (dCert.pubKeySize > sizeof(ssl->peerNtruKey)) {
toddouska 0:5045d2638c29 1330 ret = PEER_KEY_ERROR;
toddouska 0:5045d2638c29 1331 FreeDecodedCert(&dCert);
toddouska 0:5045d2638c29 1332 continue;
toddouska 0:5045d2638c29 1333 }
toddouska 0:5045d2638c29 1334 XMEMCPY(ssl->peerNtruKey, dCert.publicKey, dCert.pubKeySize);
toddouska 0:5045d2638c29 1335 ssl->peerNtruKeyLen = (word16)dCert.pubKeySize;
toddouska 0:5045d2638c29 1336 ssl->peerNtruKeyPresent = 1;
toddouska 0:5045d2638c29 1337 }
toddouska 0:5045d2638c29 1338 #endif
toddouska 0:5045d2638c29 1339
toddouska 0:5045d2638c29 1340 FreeDecodedCert(&dCert);
toddouska 0:5045d2638c29 1341 }
toddouska 0:5045d2638c29 1342
toddouska 0:5045d2638c29 1343 if (ret == 0 && ssl->options.side == CLIENT_END)
toddouska 0:5045d2638c29 1344 ssl->options.serverState = SERVER_CERT_COMPLETE;
toddouska 0:5045d2638c29 1345
toddouska 0:5045d2638c29 1346 if (ret != 0) {
toddouska 0:5045d2638c29 1347 if (!ssl->options.verifyNone) {
toddouska 0:5045d2638c29 1348 int why = bad_certificate;
toddouska 0:5045d2638c29 1349 if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E)
toddouska 0:5045d2638c29 1350 why = certificate_expired;
toddouska 0:5045d2638c29 1351 if (ssl->ctx->verifyCallback) {
toddouska 0:5045d2638c29 1352 int ok;
toddouska 0:5045d2638c29 1353 X509_STORE_CTX store;
toddouska 0:5045d2638c29 1354
toddouska 0:5045d2638c29 1355 store.error = ret;
toddouska 0:5045d2638c29 1356 store.error_depth = 1;
toddouska 0:5045d2638c29 1357 store.domain = domain;
toddouska 0:5045d2638c29 1358 #ifdef OPENSSL_EXTRA
toddouska 0:5045d2638c29 1359 store.current_cert = &ssl->peerCert;
toddouska 0:5045d2638c29 1360 #else
toddouska 0:5045d2638c29 1361 store.current_cert = NULL;
toddouska 0:5045d2638c29 1362 #endif
toddouska 0:5045d2638c29 1363 ok = ssl->ctx->verifyCallback(0, &store);
toddouska 0:5045d2638c29 1364 if (ok)
toddouska 0:5045d2638c29 1365 ret = 0;
toddouska 0:5045d2638c29 1366 }
toddouska 0:5045d2638c29 1367 if (ret != 0) {
toddouska 0:5045d2638c29 1368 SendAlert(ssl, alert_fatal, why); /* try to send */
toddouska 0:5045d2638c29 1369 ssl->options.isClosed = 1;
toddouska 0:5045d2638c29 1370 }
toddouska 0:5045d2638c29 1371 }
toddouska 0:5045d2638c29 1372 ssl->error = ret;
toddouska 0:5045d2638c29 1373 }
toddouska 0:5045d2638c29 1374
toddouska 0:5045d2638c29 1375 *inOutIdx = i;
toddouska 0:5045d2638c29 1376 return ret;
toddouska 0:5045d2638c29 1377 }
toddouska 0:5045d2638c29 1378
toddouska 0:5045d2638c29 1379
toddouska 0:5045d2638c29 1380 int DoFinished(SSL* ssl, const byte* input, word32* inOutIdx, int sniff)
toddouska 0:5045d2638c29 1381 {
toddouska 0:5045d2638c29 1382 byte verifyMAC[SHA_DIGEST_SIZE];
toddouska 0:5045d2638c29 1383 int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
toddouska 0:5045d2638c29 1384 int headerSz = HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 1385 word32 macSz = finishedSz + HANDSHAKE_HEADER_SZ,
toddouska 0:5045d2638c29 1386 idx = *inOutIdx,
toddouska 0:5045d2638c29 1387 padSz = ssl->keys.encryptSz - HANDSHAKE_HEADER_SZ - finishedSz -
toddouska 0:5045d2638c29 1388 ssl->specs.hash_size;
toddouska 0:5045d2638c29 1389 const byte* mac;
toddouska 0:5045d2638c29 1390
toddouska 0:5045d2638c29 1391 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1392 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 1393 headerSz += DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 1394 macSz += DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 1395 padSz -= DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 1396 }
toddouska 0:5045d2638c29 1397 #endif
toddouska 0:5045d2638c29 1398
toddouska 0:5045d2638c29 1399 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 1400 if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 1401 if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 1402 #endif
toddouska 0:5045d2638c29 1403 if (sniff == NO_SNIFF) {
toddouska 0:5045d2638c29 1404 if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz))
toddouska 0:5045d2638c29 1405 return VERIFY_FINISHED_ERROR;
toddouska 0:5045d2638c29 1406 }
toddouska 0:5045d2638c29 1407
toddouska 0:5045d2638c29 1408 ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
toddouska 0:5045d2638c29 1409 handshake, 1);
toddouska 0:5045d2638c29 1410 idx += finishedSz;
toddouska 0:5045d2638c29 1411
toddouska 0:5045d2638c29 1412 /* read mac and fill */
toddouska 0:5045d2638c29 1413 mac = input + idx;
toddouska 0:5045d2638c29 1414 idx += ssl->specs.hash_size;
toddouska 0:5045d2638c29 1415
toddouska 0:5045d2638c29 1416 if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
toddouska 0:5045d2638c29 1417 padSz -= ssl->specs.block_size;
toddouska 0:5045d2638c29 1418
toddouska 0:5045d2638c29 1419 idx += padSz;
toddouska 0:5045d2638c29 1420
toddouska 0:5045d2638c29 1421 /* verify mac */
toddouska 0:5045d2638c29 1422 if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size))
toddouska 0:5045d2638c29 1423 return VERIFY_MAC_ERROR;
toddouska 0:5045d2638c29 1424
toddouska 0:5045d2638c29 1425 if (ssl->options.side == CLIENT_END) {
toddouska 0:5045d2638c29 1426 ssl->options.serverState = SERVER_FINISHED_COMPLETE;
toddouska 0:5045d2638c29 1427 if (!ssl->options.resuming)
toddouska 0:5045d2638c29 1428 ssl->options.handShakeState = HANDSHAKE_DONE;
toddouska 0:5045d2638c29 1429 }
toddouska 0:5045d2638c29 1430 else {
toddouska 0:5045d2638c29 1431 ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
toddouska 0:5045d2638c29 1432 if (ssl->options.resuming)
toddouska 0:5045d2638c29 1433 ssl->options.handShakeState = HANDSHAKE_DONE;
toddouska 0:5045d2638c29 1434 }
toddouska 0:5045d2638c29 1435
toddouska 0:5045d2638c29 1436 *inOutIdx = idx;
toddouska 0:5045d2638c29 1437 return 0;
toddouska 0:5045d2638c29 1438 }
toddouska 0:5045d2638c29 1439
toddouska 0:5045d2638c29 1440
toddouska 0:5045d2638c29 1441 static int DoHandShakeMsg(SSL* ssl, byte* input, word32* inOutIdx,
toddouska 0:5045d2638c29 1442 word32 totalSz)
toddouska 0:5045d2638c29 1443 {
toddouska 0:5045d2638c29 1444 byte type;
toddouska 0:5045d2638c29 1445 word32 size;
toddouska 0:5045d2638c29 1446 int ret = 0;
toddouska 0:5045d2638c29 1447
toddouska 0:5045d2638c29 1448 CYASSL_ENTER("DoHandShakeMsg()");
toddouska 0:5045d2638c29 1449
toddouska 0:5045d2638c29 1450 if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size) != 0)
toddouska 0:5045d2638c29 1451 return PARSE_ERROR;
toddouska 0:5045d2638c29 1452
toddouska 0:5045d2638c29 1453 if (*inOutIdx + size > totalSz)
toddouska 0:5045d2638c29 1454 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 1455
toddouska 0:5045d2638c29 1456 HashInput(ssl, input + *inOutIdx, size);
toddouska 0:5045d2638c29 1457 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 1458 /* add name later, add on record and handshake header part back on */
toddouska 0:5045d2638c29 1459 if (ssl->toInfoOn) {
toddouska 0:5045d2638c29 1460 int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 1461 AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add,
toddouska 0:5045d2638c29 1462 size + add, ssl->heap);
toddouska 0:5045d2638c29 1463 AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
toddouska 0:5045d2638c29 1464 }
toddouska 0:5045d2638c29 1465 #endif
toddouska 0:5045d2638c29 1466
toddouska 0:5045d2638c29 1467 switch (type) {
toddouska 0:5045d2638c29 1468
toddouska 0:5045d2638c29 1469 #ifndef NO_CYASSL_CLIENT
toddouska 0:5045d2638c29 1470 case hello_verify_request:
toddouska 0:5045d2638c29 1471 CYASSL_MSG("processing hello verify request");
toddouska 0:5045d2638c29 1472 ret = DoHelloVerifyRequest(ssl, input,inOutIdx);
toddouska 0:5045d2638c29 1473 break;
toddouska 0:5045d2638c29 1474
toddouska 0:5045d2638c29 1475 case server_hello:
toddouska 0:5045d2638c29 1476 CYASSL_MSG("processing server hello");
toddouska 0:5045d2638c29 1477 ret = DoServerHello(ssl, input, inOutIdx);
toddouska 0:5045d2638c29 1478 break;
toddouska 0:5045d2638c29 1479
toddouska 0:5045d2638c29 1480 case certificate_request:
toddouska 0:5045d2638c29 1481 CYASSL_MSG("processing certificate request");
toddouska 0:5045d2638c29 1482 ret = DoCertificateRequest(ssl, input, inOutIdx);
toddouska 0:5045d2638c29 1483 break;
toddouska 0:5045d2638c29 1484
toddouska 0:5045d2638c29 1485 case server_key_exchange:
toddouska 0:5045d2638c29 1486 CYASSL_MSG("processing server key exchange");
toddouska 0:5045d2638c29 1487 ret = DoServerKeyExchange(ssl, input, inOutIdx);
toddouska 0:5045d2638c29 1488 break;
toddouska 0:5045d2638c29 1489 #endif
toddouska 0:5045d2638c29 1490
toddouska 0:5045d2638c29 1491 case certificate:
toddouska 0:5045d2638c29 1492 CYASSL_MSG("processing certificate");
toddouska 0:5045d2638c29 1493 ret = DoCertificate(ssl, input, inOutIdx);
toddouska 0:5045d2638c29 1494 break;
toddouska 0:5045d2638c29 1495
toddouska 0:5045d2638c29 1496 case server_hello_done:
toddouska 0:5045d2638c29 1497 CYASSL_MSG("processing server hello done");
toddouska 0:5045d2638c29 1498 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 1499 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 1500 AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 1501 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 1502 AddLateName("ServerHelloDone", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 1503 #endif
toddouska 0:5045d2638c29 1504 ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
toddouska 0:5045d2638c29 1505 break;
toddouska 0:5045d2638c29 1506
toddouska 0:5045d2638c29 1507 case finished:
toddouska 0:5045d2638c29 1508 CYASSL_MSG("processing finished");
toddouska 0:5045d2638c29 1509 ret = DoFinished(ssl, input, inOutIdx, NO_SNIFF);
toddouska 0:5045d2638c29 1510 break;
toddouska 0:5045d2638c29 1511
toddouska 0:5045d2638c29 1512 #ifndef NO_CYASSL_SERVER
toddouska 0:5045d2638c29 1513 case client_hello:
toddouska 0:5045d2638c29 1514 CYASSL_MSG("processing client hello");
toddouska 0:5045d2638c29 1515 ret = DoClientHello(ssl, input, inOutIdx, totalSz, size);
toddouska 0:5045d2638c29 1516 break;
toddouska 0:5045d2638c29 1517
toddouska 0:5045d2638c29 1518 case client_key_exchange:
toddouska 0:5045d2638c29 1519 CYASSL_MSG("processing client key exchange");
toddouska 0:5045d2638c29 1520 ret = DoClientKeyExchange(ssl, input, inOutIdx);
toddouska 0:5045d2638c29 1521 break;
toddouska 0:5045d2638c29 1522
toddouska 0:5045d2638c29 1523 case certificate_verify:
toddouska 0:5045d2638c29 1524 CYASSL_MSG("processing certificate verify");
toddouska 0:5045d2638c29 1525 ret = DoCertificateVerify(ssl, input, inOutIdx, totalSz);
toddouska 0:5045d2638c29 1526 break;
toddouska 0:5045d2638c29 1527
toddouska 0:5045d2638c29 1528 #endif
toddouska 0:5045d2638c29 1529
toddouska 0:5045d2638c29 1530 default:
toddouska 0:5045d2638c29 1531 ret = UNKNOWN_HANDSHAKE_TYPE;
toddouska 0:5045d2638c29 1532 }
toddouska 0:5045d2638c29 1533
toddouska 0:5045d2638c29 1534 CYASSL_LEAVE("DoHandShakeMsg()", ret);
toddouska 0:5045d2638c29 1535 return ret;
toddouska 0:5045d2638c29 1536 }
toddouska 0:5045d2638c29 1537
toddouska 0:5045d2638c29 1538
toddouska 0:5045d2638c29 1539 static INLINE void Encrypt(SSL* ssl, byte* out, const byte* input, word32 sz)
toddouska 0:5045d2638c29 1540 {
toddouska 0:5045d2638c29 1541 switch (ssl->specs.bulk_cipher_algorithm) {
toddouska 0:5045d2638c29 1542 #ifdef BUILD_ARC4
toddouska 0:5045d2638c29 1543 case rc4:
toddouska 0:5045d2638c29 1544 Arc4Process(&ssl->encrypt.arc4, out, input, sz);
toddouska 0:5045d2638c29 1545 break;
toddouska 0:5045d2638c29 1546 #endif
toddouska 0:5045d2638c29 1547
toddouska 0:5045d2638c29 1548 #ifdef BUILD_DES3
toddouska 0:5045d2638c29 1549 case triple_des:
toddouska 0:5045d2638c29 1550 Des3_CbcEncrypt(&ssl->encrypt.des3, out, input, sz);
toddouska 0:5045d2638c29 1551 break;
toddouska 0:5045d2638c29 1552 #endif
toddouska 0:5045d2638c29 1553
toddouska 0:5045d2638c29 1554 #ifdef BUILD_AES
toddouska 0:5045d2638c29 1555 case aes:
toddouska 0:5045d2638c29 1556 #ifdef CYASSL_AESNI
toddouska 0:5045d2638c29 1557 if ((word)input % 16) {
toddouska 0:5045d2638c29 1558 byte buffer[MAX_RECORD_SIZE + MAX_COMP_EXTRA+MAX_MSG_EXTRA];
toddouska 0:5045d2638c29 1559 XMEMCPY(buffer, input, sz);
toddouska 0:5045d2638c29 1560 AesCbcEncrypt(&ssl->encrypt.aes, buffer, buffer, sz);
toddouska 0:5045d2638c29 1561 XMEMCPY(out, buffer, sz);
toddouska 0:5045d2638c29 1562 break;
toddouska 0:5045d2638c29 1563 }
toddouska 0:5045d2638c29 1564 #endif
toddouska 0:5045d2638c29 1565 AesCbcEncrypt(&ssl->encrypt.aes, out, input, sz);
toddouska 0:5045d2638c29 1566 break;
toddouska 0:5045d2638c29 1567 #endif
toddouska 0:5045d2638c29 1568
toddouska 0:5045d2638c29 1569 #ifdef BUILD_HC128
toddouska 0:5045d2638c29 1570 case hc128:
toddouska 0:5045d2638c29 1571 Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
toddouska 0:5045d2638c29 1572 break;
toddouska 0:5045d2638c29 1573 #endif
toddouska 0:5045d2638c29 1574
toddouska 0:5045d2638c29 1575 #ifdef BUILD_RABBIT
toddouska 0:5045d2638c29 1576 case rabbit:
toddouska 0:5045d2638c29 1577 RabbitProcess(&ssl->encrypt.rabbit, out, input, sz);
toddouska 0:5045d2638c29 1578 break;
toddouska 0:5045d2638c29 1579 #endif
toddouska 0:5045d2638c29 1580 }
toddouska 0:5045d2638c29 1581 }
toddouska 0:5045d2638c29 1582
toddouska 0:5045d2638c29 1583
toddouska 0:5045d2638c29 1584 static INLINE void Decrypt(SSL* ssl, byte* plain, const byte* input, word32 sz)
toddouska 0:5045d2638c29 1585 {
toddouska 0:5045d2638c29 1586 switch (ssl->specs.bulk_cipher_algorithm) {
toddouska 0:5045d2638c29 1587 #ifdef BUILD_ARC4
toddouska 0:5045d2638c29 1588 case rc4:
toddouska 0:5045d2638c29 1589 Arc4Process(&ssl->decrypt.arc4, plain, input, sz);
toddouska 0:5045d2638c29 1590 break;
toddouska 0:5045d2638c29 1591 #endif
toddouska 0:5045d2638c29 1592
toddouska 0:5045d2638c29 1593 #ifdef BUILD_DES3
toddouska 0:5045d2638c29 1594 case triple_des:
toddouska 0:5045d2638c29 1595 Des3_CbcDecrypt(&ssl->decrypt.des3, plain, input, sz);
toddouska 0:5045d2638c29 1596 break;
toddouska 0:5045d2638c29 1597 #endif
toddouska 0:5045d2638c29 1598
toddouska 0:5045d2638c29 1599 #ifdef BUILD_AES
toddouska 0:5045d2638c29 1600 case aes:
toddouska 0:5045d2638c29 1601 AesCbcDecrypt(&ssl->decrypt.aes, plain, input, sz);
toddouska 0:5045d2638c29 1602 break;
toddouska 0:5045d2638c29 1603 #endif
toddouska 0:5045d2638c29 1604
toddouska 0:5045d2638c29 1605 #ifdef BUILD_HC128
toddouska 0:5045d2638c29 1606 case hc128:
toddouska 0:5045d2638c29 1607 Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
toddouska 0:5045d2638c29 1608 break;
toddouska 0:5045d2638c29 1609 #endif
toddouska 0:5045d2638c29 1610
toddouska 0:5045d2638c29 1611 #ifdef BUILD_RABBIT
toddouska 0:5045d2638c29 1612 case rabbit:
toddouska 0:5045d2638c29 1613 RabbitProcess(&ssl->decrypt.rabbit, plain, input, sz);
toddouska 0:5045d2638c29 1614 break;
toddouska 0:5045d2638c29 1615 #endif
toddouska 0:5045d2638c29 1616 }
toddouska 0:5045d2638c29 1617 }
toddouska 0:5045d2638c29 1618
toddouska 0:5045d2638c29 1619
toddouska 0:5045d2638c29 1620 /* decrypt input message in place */
toddouska 0:5045d2638c29 1621 static int DecryptMessage(SSL* ssl, byte* input, word32 sz, word32* idx)
toddouska 0:5045d2638c29 1622 {
toddouska 0:5045d2638c29 1623 Decrypt(ssl, input, input, sz);
toddouska 0:5045d2638c29 1624 ssl->keys.encryptSz = sz;
toddouska 0:5045d2638c29 1625 if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
toddouska 0:5045d2638c29 1626 *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
toddouska 0:5045d2638c29 1627
toddouska 0:5045d2638c29 1628 return 0;
toddouska 0:5045d2638c29 1629 }
toddouska 0:5045d2638c29 1630
toddouska 0:5045d2638c29 1631
toddouska 0:5045d2638c29 1632 static INLINE word32 GetSEQIncrement(SSL* ssl, int verify)
toddouska 0:5045d2638c29 1633 {
toddouska 0:5045d2638c29 1634 if (verify)
toddouska 0:5045d2638c29 1635 return ssl->keys.peer_sequence_number++;
toddouska 0:5045d2638c29 1636 else
toddouska 0:5045d2638c29 1637 return ssl->keys.sequence_number++;
toddouska 0:5045d2638c29 1638 }
toddouska 0:5045d2638c29 1639
toddouska 0:5045d2638c29 1640
toddouska 0:5045d2638c29 1641 int DoApplicationData(SSL* ssl, byte* input, word32* inOutIdx)
toddouska 0:5045d2638c29 1642 {
toddouska 0:5045d2638c29 1643 word32 msgSz = ssl->keys.encryptSz;
toddouska 0:5045d2638c29 1644 word32 pad = 0,
toddouska 0:5045d2638c29 1645 padByte = 0,
toddouska 0:5045d2638c29 1646 idx = *inOutIdx,
toddouska 0:5045d2638c29 1647 digestSz = ssl->specs.hash_size;
toddouska 0:5045d2638c29 1648 int dataSz;
toddouska 0:5045d2638c29 1649 int ivExtra = 0;
toddouska 0:5045d2638c29 1650 byte* rawData = input + idx; /* keep current for hmac */
toddouska 0:5045d2638c29 1651 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 1652 byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
toddouska 0:5045d2638c29 1653 #endif
toddouska 0:5045d2638c29 1654
toddouska 0:5045d2638c29 1655 byte verify[SHA_DIGEST_SIZE];
toddouska 0:5045d2638c29 1656 const byte* mac;
toddouska 0:5045d2638c29 1657
toddouska 0:5045d2638c29 1658 if (ssl->specs.cipher_type == block) {
toddouska 0:5045d2638c29 1659 if (ssl->options.tls1_1)
toddouska 0:5045d2638c29 1660 ivExtra = ssl->specs.block_size;
toddouska 0:5045d2638c29 1661 pad = *(input + idx + msgSz - ivExtra - 1);
toddouska 0:5045d2638c29 1662 padByte = 1;
toddouska 0:5045d2638c29 1663 }
toddouska 0:5045d2638c29 1664
toddouska 0:5045d2638c29 1665 dataSz = msgSz - ivExtra - digestSz - pad - padByte;
toddouska 0:5045d2638c29 1666 if (dataSz < 0)
toddouska 0:5045d2638c29 1667 return BUFFER_ERROR;
toddouska 0:5045d2638c29 1668
toddouska 0:5045d2638c29 1669 /* read data */
toddouska 0:5045d2638c29 1670 if (dataSz) {
toddouska 0:5045d2638c29 1671 int rawSz = dataSz; /* keep raw size for hmac */
toddouska 0:5045d2638c29 1672
toddouska 0:5045d2638c29 1673 ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
toddouska 0:5045d2638c29 1674
toddouska 0:5045d2638c29 1675 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 1676 byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
toddouska 0:5045d2638c29 1677
toddouska 0:5045d2638c29 1678 if (ssl->options.usingCompression) {
toddouska 0:5045d2638c29 1679 dataSz = DeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
toddouska 0:5045d2638c29 1680 if (dataSz < 0) return dataSz;
toddouska 0:5045d2638c29 1681 }
toddouska 0:5045d2638c29 1682 #endif
toddouska 0:5045d2638c29 1683
toddouska 0:5045d2638c29 1684 if (ssl->options.usingCompression)
toddouska 0:5045d2638c29 1685 idx += rawSz;
toddouska 0:5045d2638c29 1686 else
toddouska 0:5045d2638c29 1687 idx += dataSz;
toddouska 0:5045d2638c29 1688
toddouska 0:5045d2638c29 1689 ssl->buffers.clearOutputBuffer.buffer = rawData;
toddouska 0:5045d2638c29 1690 ssl->buffers.clearOutputBuffer.length = dataSz;
toddouska 0:5045d2638c29 1691 }
toddouska 0:5045d2638c29 1692
toddouska 0:5045d2638c29 1693 /* read mac and fill */
toddouska 0:5045d2638c29 1694 mac = input + idx;
toddouska 0:5045d2638c29 1695 idx += digestSz;
toddouska 0:5045d2638c29 1696
toddouska 0:5045d2638c29 1697 idx += pad;
toddouska 0:5045d2638c29 1698 if (padByte)
toddouska 0:5045d2638c29 1699 idx++;
toddouska 0:5045d2638c29 1700
toddouska 0:5045d2638c29 1701 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 1702 if (ssl->options.usingCompression)
toddouska 0:5045d2638c29 1703 XMEMMOVE(rawData, decomp, dataSz);
toddouska 0:5045d2638c29 1704 #endif
toddouska 0:5045d2638c29 1705
toddouska 0:5045d2638c29 1706 /* verify */
toddouska 0:5045d2638c29 1707 if (dataSz) {
toddouska 0:5045d2638c29 1708 if (XMEMCMP(mac, verify, digestSz))
toddouska 0:5045d2638c29 1709 return VERIFY_MAC_ERROR;
toddouska 0:5045d2638c29 1710 }
toddouska 0:5045d2638c29 1711 else
toddouska 0:5045d2638c29 1712 GetSEQIncrement(ssl, 1); /* even though no data, increment verify */
toddouska 0:5045d2638c29 1713
toddouska 0:5045d2638c29 1714 *inOutIdx = idx;
toddouska 0:5045d2638c29 1715 return 0;
toddouska 0:5045d2638c29 1716 }
toddouska 0:5045d2638c29 1717
toddouska 0:5045d2638c29 1718
toddouska 0:5045d2638c29 1719 /* process alert, return level */
toddouska 0:5045d2638c29 1720 static int DoAlert(SSL* ssl, byte* input, word32* inOutIdx, int* type)
toddouska 0:5045d2638c29 1721 {
toddouska 0:5045d2638c29 1722 byte level;
toddouska 0:5045d2638c29 1723
toddouska 0:5045d2638c29 1724 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 1725 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 1726 AddPacketName("Alert", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 1727 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 1728 /* add record header back on to info + 2 byte level, data */
toddouska 0:5045d2638c29 1729 AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
toddouska 0:5045d2638c29 1730 RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap);
toddouska 0:5045d2638c29 1731 #endif
toddouska 0:5045d2638c29 1732 level = input[(*inOutIdx)++];
toddouska 0:5045d2638c29 1733 *type = (int)input[(*inOutIdx)++];
toddouska 0:5045d2638c29 1734
toddouska 0:5045d2638c29 1735 if (*type == close_notify)
toddouska 0:5045d2638c29 1736 ssl->options.closeNotify = 1;
toddouska 0:5045d2638c29 1737
toddouska 0:5045d2638c29 1738 if (ssl->keys.encryptionOn) {
toddouska 0:5045d2638c29 1739 int aSz = ALERT_SIZE;
toddouska 0:5045d2638c29 1740 const byte* mac;
toddouska 0:5045d2638c29 1741 byte verify[SHA_DIGEST_SIZE];
toddouska 0:5045d2638c29 1742 int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
toddouska 0:5045d2638c29 1743
toddouska 0:5045d2638c29 1744 ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
toddouska 0:5045d2638c29 1745
toddouska 0:5045d2638c29 1746 /* read mac and fill */
toddouska 0:5045d2638c29 1747 mac = input + *inOutIdx;
toddouska 0:5045d2638c29 1748 *inOutIdx += (ssl->specs.hash_size + padSz);
toddouska 0:5045d2638c29 1749
toddouska 0:5045d2638c29 1750 /* verify */
toddouska 0:5045d2638c29 1751 if (XMEMCMP(mac, verify, ssl->specs.hash_size))
toddouska 0:5045d2638c29 1752 return VERIFY_MAC_ERROR;
toddouska 0:5045d2638c29 1753 }
toddouska 0:5045d2638c29 1754
toddouska 0:5045d2638c29 1755 return level;
toddouska 0:5045d2638c29 1756 }
toddouska 0:5045d2638c29 1757
toddouska 0:5045d2638c29 1758 static int GetInputData(SSL *ssl, size_t size)
toddouska 0:5045d2638c29 1759 {
toddouska 0:5045d2638c29 1760 int in;
toddouska 0:5045d2638c29 1761 int inSz;
toddouska 0:5045d2638c29 1762 int maxLength;
toddouska 0:5045d2638c29 1763 int usedLength;
toddouska 0:5045d2638c29 1764
toddouska 0:5045d2638c29 1765
toddouska 0:5045d2638c29 1766 /* check max input length */
toddouska 0:5045d2638c29 1767 usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
toddouska 0:5045d2638c29 1768 maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength;
toddouska 0:5045d2638c29 1769 inSz = (int)(size - usedLength); /* from last partial read */
toddouska 0:5045d2638c29 1770
toddouska 0:5045d2638c29 1771 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1772 if (ssl->options.dtls)
toddouska 0:5045d2638c29 1773 inSz = 1500; /* read ahead up to MTU */
toddouska 0:5045d2638c29 1774 #endif
toddouska 0:5045d2638c29 1775
toddouska 0:5045d2638c29 1776 if (inSz > maxLength) {
toddouska 0:5045d2638c29 1777 if (GrowInputBuffer(ssl, size, usedLength) < 0)
toddouska 0:5045d2638c29 1778 return MEMORY_E;
toddouska 0:5045d2638c29 1779 }
toddouska 0:5045d2638c29 1780
toddouska 0:5045d2638c29 1781 if (inSz <= 0)
toddouska 0:5045d2638c29 1782 return BUFFER_ERROR;
toddouska 0:5045d2638c29 1783
toddouska 0:5045d2638c29 1784 /* Put buffer data at start if not there */
toddouska 0:5045d2638c29 1785 if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
toddouska 0:5045d2638c29 1786 XMEMMOVE(ssl->buffers.inputBuffer.buffer,
toddouska 0:5045d2638c29 1787 ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 1788 usedLength);
toddouska 0:5045d2638c29 1789
toddouska 0:5045d2638c29 1790 /* remove processed data */
toddouska 0:5045d2638c29 1791 ssl->buffers.inputBuffer.idx = 0;
toddouska 0:5045d2638c29 1792 ssl->buffers.inputBuffer.length = usedLength;
toddouska 0:5045d2638c29 1793
toddouska 0:5045d2638c29 1794 /* read data from network */
toddouska 0:5045d2638c29 1795 do {
toddouska 0:5045d2638c29 1796 in = Receive(ssl,
toddouska 0:5045d2638c29 1797 ssl->buffers.inputBuffer.buffer +
toddouska 0:5045d2638c29 1798 ssl->buffers.inputBuffer.length,
toddouska 0:5045d2638c29 1799 inSz, 0);
toddouska 0:5045d2638c29 1800 if (in == -1)
toddouska 0:5045d2638c29 1801 return SOCKET_ERROR_E;
toddouska 0:5045d2638c29 1802
toddouska 0:5045d2638c29 1803 if (in == WANT_READ)
toddouska 0:5045d2638c29 1804 return WANT_READ;
toddouska 0:5045d2638c29 1805
toddouska 0:5045d2638c29 1806 ssl->buffers.inputBuffer.length += in;
toddouska 0:5045d2638c29 1807 inSz -= in;
toddouska 0:5045d2638c29 1808
toddouska 0:5045d2638c29 1809 } while (ssl->buffers.inputBuffer.length < size);
toddouska 0:5045d2638c29 1810
toddouska 0:5045d2638c29 1811 return 0;
toddouska 0:5045d2638c29 1812 }
toddouska 0:5045d2638c29 1813
toddouska 0:5045d2638c29 1814 /* process input requests, return 0 is done, 1 is call again to complete, and
toddouska 0:5045d2638c29 1815 negative number is error */
toddouska 0:5045d2638c29 1816 int ProcessReply(SSL* ssl)
toddouska 0:5045d2638c29 1817 {
toddouska 0:5045d2638c29 1818 int ret, type, readSz;
toddouska 0:5045d2638c29 1819 word32 startIdx = 0;
toddouska 0:5045d2638c29 1820 byte b0, b1;
toddouska 0:5045d2638c29 1821 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1822 int used;
toddouska 0:5045d2638c29 1823 #endif
toddouska 0:5045d2638c29 1824
toddouska 0:5045d2638c29 1825 for (;;) {
toddouska 0:5045d2638c29 1826 switch ((processReply)ssl->options.processReply) {
toddouska 0:5045d2638c29 1827
toddouska 0:5045d2638c29 1828 /* in the CYASSL_SERVER case, get the first byte for detecting
toddouska 0:5045d2638c29 1829 * old client hello */
toddouska 0:5045d2638c29 1830 case doProcessInit:
toddouska 0:5045d2638c29 1831
toddouska 0:5045d2638c29 1832 readSz = RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 1833
toddouska 0:5045d2638c29 1834 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1835 if (ssl->options.dtls)
toddouska 0:5045d2638c29 1836 readSz = DTLS_RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 1837 #endif
toddouska 0:5045d2638c29 1838
toddouska 0:5045d2638c29 1839 /* get header or return error */
toddouska 0:5045d2638c29 1840 if (!ssl->options.dtls) {
toddouska 0:5045d2638c29 1841 if ((ret = GetInputData(ssl, readSz)) < 0)
toddouska 0:5045d2638c29 1842 return ret;
toddouska 0:5045d2638c29 1843 } else {
toddouska 0:5045d2638c29 1844 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1845 /* read ahead may already have header */
toddouska 0:5045d2638c29 1846 used = ssl->buffers.inputBuffer.length -
toddouska 0:5045d2638c29 1847 ssl->buffers.inputBuffer.idx;
toddouska 0:5045d2638c29 1848 if (used < readSz)
toddouska 0:5045d2638c29 1849 if ((ret = GetInputData(ssl, readSz)) < 0)
toddouska 0:5045d2638c29 1850 return ret;
toddouska 0:5045d2638c29 1851 #endif
toddouska 0:5045d2638c29 1852 }
toddouska 0:5045d2638c29 1853
toddouska 0:5045d2638c29 1854 #ifndef NO_CYASSL_SERVER
toddouska 0:5045d2638c29 1855
toddouska 0:5045d2638c29 1856 /* see if sending SSLv2 client hello */
toddouska 0:5045d2638c29 1857 if ( ssl->options.side == SERVER_END &&
toddouska 0:5045d2638c29 1858 ssl->options.clientState == NULL_STATE &&
toddouska 0:5045d2638c29 1859 ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
toddouska 0:5045d2638c29 1860 != handshake) {
toddouska 0:5045d2638c29 1861 ssl->options.processReply = runProcessOldClientHello;
toddouska 0:5045d2638c29 1862
toddouska 0:5045d2638c29 1863 /* how many bytes need ProcessOldClientHello */
toddouska 0:5045d2638c29 1864 b0 =
toddouska 0:5045d2638c29 1865 ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
toddouska 0:5045d2638c29 1866 b1 =
toddouska 0:5045d2638c29 1867 ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
toddouska 0:5045d2638c29 1868 ssl->curSize = ((b0 & 0x7f) << 8) | b1;
toddouska 0:5045d2638c29 1869 }
toddouska 0:5045d2638c29 1870 else {
toddouska 0:5045d2638c29 1871 ssl->options.processReply = getRecordLayerHeader;
toddouska 0:5045d2638c29 1872 continue;
toddouska 0:5045d2638c29 1873 }
toddouska 0:5045d2638c29 1874
toddouska 0:5045d2638c29 1875 /* in the CYASSL_SERVER case, run the old client hello */
toddouska 0:5045d2638c29 1876 case runProcessOldClientHello:
toddouska 0:5045d2638c29 1877
toddouska 0:5045d2638c29 1878 /* get sz bytes or return error */
toddouska 0:5045d2638c29 1879 if (!ssl->options.dtls) {
toddouska 0:5045d2638c29 1880 if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
toddouska 0:5045d2638c29 1881 return ret;
toddouska 0:5045d2638c29 1882 } else {
toddouska 0:5045d2638c29 1883 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1884 /* read ahead may already have */
toddouska 0:5045d2638c29 1885 used = ssl->buffers.inputBuffer.length -
toddouska 0:5045d2638c29 1886 ssl->buffers.inputBuffer.idx;
toddouska 0:5045d2638c29 1887 if (used < ssl->curSize)
toddouska 0:5045d2638c29 1888 if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
toddouska 0:5045d2638c29 1889 return ret;
toddouska 0:5045d2638c29 1890 #endif /* CYASSL_DTLS */
toddouska 0:5045d2638c29 1891 }
toddouska 0:5045d2638c29 1892
toddouska 0:5045d2638c29 1893 ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
toddouska 0:5045d2638c29 1894 &ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 1895 ssl->buffers.inputBuffer.length -
toddouska 0:5045d2638c29 1896 ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 1897 ssl->curSize);
toddouska 0:5045d2638c29 1898 if (ret < 0)
toddouska 0:5045d2638c29 1899 return ret;
toddouska 0:5045d2638c29 1900
toddouska 0:5045d2638c29 1901 else if (ssl->buffers.inputBuffer.idx ==
toddouska 0:5045d2638c29 1902 ssl->buffers.inputBuffer.length) {
toddouska 0:5045d2638c29 1903 ssl->options.processReply = doProcessInit;
toddouska 0:5045d2638c29 1904 return 0;
toddouska 0:5045d2638c29 1905 }
toddouska 0:5045d2638c29 1906
toddouska 0:5045d2638c29 1907 #endif /* NO_CYASSL_SERVER */
toddouska 0:5045d2638c29 1908
toddouska 0:5045d2638c29 1909 /* get the record layer header */
toddouska 0:5045d2638c29 1910 case getRecordLayerHeader:
toddouska 0:5045d2638c29 1911
toddouska 0:5045d2638c29 1912 ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
toddouska 0:5045d2638c29 1913 &ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 1914 &ssl->curRL, &ssl->curSize);
toddouska 0:5045d2638c29 1915 if (ret != 0)
toddouska 0:5045d2638c29 1916 return ret;
toddouska 0:5045d2638c29 1917
toddouska 0:5045d2638c29 1918 ssl->options.processReply = getData;
toddouska 0:5045d2638c29 1919
toddouska 0:5045d2638c29 1920 /* retrieve record layer data */
toddouska 0:5045d2638c29 1921 case getData:
toddouska 0:5045d2638c29 1922
toddouska 0:5045d2638c29 1923 /* get sz bytes or return error */
toddouska 0:5045d2638c29 1924 if (!ssl->options.dtls) {
toddouska 0:5045d2638c29 1925 if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
toddouska 0:5045d2638c29 1926 return ret;
toddouska 0:5045d2638c29 1927 } else {
toddouska 0:5045d2638c29 1928 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1929 /* read ahead may already have */
toddouska 0:5045d2638c29 1930 used = ssl->buffers.inputBuffer.length -
toddouska 0:5045d2638c29 1931 ssl->buffers.inputBuffer.idx;
toddouska 0:5045d2638c29 1932 if (used < ssl->curSize)
toddouska 0:5045d2638c29 1933 if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
toddouska 0:5045d2638c29 1934 return ret;
toddouska 0:5045d2638c29 1935 #endif
toddouska 0:5045d2638c29 1936 }
toddouska 0:5045d2638c29 1937
toddouska 0:5045d2638c29 1938 ssl->options.processReply = runProcessingOneMessage;
toddouska 0:5045d2638c29 1939 startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
toddouska 0:5045d2638c29 1940
toddouska 0:5045d2638c29 1941 /* the record layer is here */
toddouska 0:5045d2638c29 1942 case runProcessingOneMessage:
toddouska 0:5045d2638c29 1943
toddouska 0:5045d2638c29 1944 if (ssl->keys.encryptionOn)
toddouska 0:5045d2638c29 1945 if (DecryptMessage(ssl, ssl->buffers.inputBuffer.buffer +
toddouska 0:5045d2638c29 1946 ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 1947 ssl->curSize,
toddouska 0:5045d2638c29 1948 &ssl->buffers.inputBuffer.idx) < 0)
toddouska 0:5045d2638c29 1949 return DECRYPT_ERROR;
toddouska 0:5045d2638c29 1950
toddouska 0:5045d2638c29 1951 CYASSL_MSG("received record layer msg");
toddouska 0:5045d2638c29 1952
toddouska 0:5045d2638c29 1953 switch (ssl->curRL.type) {
toddouska 0:5045d2638c29 1954 case handshake :
toddouska 0:5045d2638c29 1955 /* debugging in DoHandShakeMsg */
toddouska 0:5045d2638c29 1956 if ((ret = DoHandShakeMsg(ssl,
toddouska 0:5045d2638c29 1957 ssl->buffers.inputBuffer.buffer,
toddouska 0:5045d2638c29 1958 &ssl->buffers.inputBuffer.idx,
toddouska 0:5045d2638c29 1959 ssl->buffers.inputBuffer.length))
toddouska 0:5045d2638c29 1960 != 0)
toddouska 0:5045d2638c29 1961 return ret;
toddouska 0:5045d2638c29 1962 break;
toddouska 0:5045d2638c29 1963
toddouska 0:5045d2638c29 1964 case change_cipher_spec:
toddouska 0:5045d2638c29 1965 CYASSL_MSG("got CHANGE CIPHER SPEC");
toddouska 0:5045d2638c29 1966 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 1967 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 1968 AddPacketName("ChangeCipher", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 1969 /* add record header back on info */
toddouska 0:5045d2638c29 1970 if (ssl->toInfoOn) {
toddouska 0:5045d2638c29 1971 AddPacketInfo("ChangeCipher", &ssl->timeoutInfo,
toddouska 0:5045d2638c29 1972 ssl->buffers.inputBuffer.buffer +
toddouska 0:5045d2638c29 1973 ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
toddouska 0:5045d2638c29 1974 1 + RECORD_HEADER_SZ, ssl->heap);
toddouska 0:5045d2638c29 1975 AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
toddouska 0:5045d2638c29 1976 }
toddouska 0:5045d2638c29 1977 #endif
toddouska 0:5045d2638c29 1978 ssl->buffers.inputBuffer.idx++;
toddouska 0:5045d2638c29 1979 ssl->keys.encryptionOn = 1;
toddouska 0:5045d2638c29 1980
toddouska 0:5045d2638c29 1981 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 1982 if (ssl->options.dtls)
toddouska 0:5045d2638c29 1983 ssl->keys.dtls_peer_epoch++;
toddouska 0:5045d2638c29 1984 #endif
toddouska 0:5045d2638c29 1985
toddouska 0:5045d2638c29 1986 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 1987 if (ssl->options.usingCompression)
toddouska 0:5045d2638c29 1988 if ( (ret = InitStreams(ssl)) != 0)
toddouska 0:5045d2638c29 1989 return ret;
toddouska 0:5045d2638c29 1990 #endif
toddouska 0:5045d2638c29 1991 if (ssl->options.resuming && ssl->options.side ==
toddouska 0:5045d2638c29 1992 CLIENT_END)
toddouska 0:5045d2638c29 1993 BuildFinished(ssl, &ssl->verifyHashes, server);
toddouska 0:5045d2638c29 1994 else if (!ssl->options.resuming && ssl->options.side ==
toddouska 0:5045d2638c29 1995 SERVER_END)
toddouska 0:5045d2638c29 1996 BuildFinished(ssl, &ssl->verifyHashes, client);
toddouska 0:5045d2638c29 1997 break;
toddouska 0:5045d2638c29 1998
toddouska 0:5045d2638c29 1999 case application_data:
toddouska 0:5045d2638c29 2000 CYASSL_MSG("got app DATA");
toddouska 0:5045d2638c29 2001 if ((ret = DoApplicationData(ssl,
toddouska 0:5045d2638c29 2002 ssl->buffers.inputBuffer.buffer,
toddouska 0:5045d2638c29 2003 &ssl->buffers.inputBuffer.idx))
toddouska 0:5045d2638c29 2004 != 0) {
toddouska 0:5045d2638c29 2005 CYASSL_ERROR(ret);
toddouska 0:5045d2638c29 2006 return ret;
toddouska 0:5045d2638c29 2007 }
toddouska 0:5045d2638c29 2008 break;
toddouska 0:5045d2638c29 2009
toddouska 0:5045d2638c29 2010 case alert:
toddouska 0:5045d2638c29 2011 CYASSL_MSG("got ALERT!");
toddouska 0:5045d2638c29 2012 if (DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
toddouska 0:5045d2638c29 2013 &ssl->buffers.inputBuffer.idx, &type) == alert_fatal)
toddouska 0:5045d2638c29 2014 return FATAL_ERROR;
toddouska 0:5045d2638c29 2015
toddouska 0:5045d2638c29 2016 /* catch warnings that are handled as errors */
toddouska 0:5045d2638c29 2017 if (type == close_notify)
toddouska 0:5045d2638c29 2018 return ssl->error = ZERO_RETURN;
toddouska 0:5045d2638c29 2019
toddouska 0:5045d2638c29 2020 if (type == decrypt_error)
toddouska 0:5045d2638c29 2021 return FATAL_ERROR;
toddouska 0:5045d2638c29 2022 break;
toddouska 0:5045d2638c29 2023
toddouska 0:5045d2638c29 2024 default:
toddouska 0:5045d2638c29 2025 CYASSL_ERROR(UNKNOWN_RECORD_TYPE);
toddouska 0:5045d2638c29 2026 return UNKNOWN_RECORD_TYPE;
toddouska 0:5045d2638c29 2027 }
toddouska 0:5045d2638c29 2028
toddouska 0:5045d2638c29 2029 ssl->options.processReply = doProcessInit;
toddouska 0:5045d2638c29 2030
toddouska 0:5045d2638c29 2031 /* input exhausted? */
toddouska 0:5045d2638c29 2032 if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length)
toddouska 0:5045d2638c29 2033 return 0;
toddouska 0:5045d2638c29 2034 /* more messages per record */
toddouska 0:5045d2638c29 2035 else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
toddouska 0:5045d2638c29 2036 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2037 /* read-ahead but dtls doesn't bundle messages per record */
toddouska 0:5045d2638c29 2038 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2039 ssl->options.processReply = doProcessInit;
toddouska 0:5045d2638c29 2040 continue;
toddouska 0:5045d2638c29 2041 }
toddouska 0:5045d2638c29 2042 #endif
toddouska 0:5045d2638c29 2043 ssl->options.processReply = runProcessingOneMessage;
toddouska 0:5045d2638c29 2044 continue;
toddouska 0:5045d2638c29 2045 }
toddouska 0:5045d2638c29 2046 /* more records */
toddouska 0:5045d2638c29 2047 else {
toddouska 0:5045d2638c29 2048 ssl->options.processReply = doProcessInit;
toddouska 0:5045d2638c29 2049 continue;
toddouska 0:5045d2638c29 2050 }
toddouska 0:5045d2638c29 2051 }
toddouska 0:5045d2638c29 2052 }
toddouska 0:5045d2638c29 2053 }
toddouska 0:5045d2638c29 2054
toddouska 0:5045d2638c29 2055
toddouska 0:5045d2638c29 2056 int SendChangeCipher(SSL* ssl)
toddouska 0:5045d2638c29 2057 {
toddouska 0:5045d2638c29 2058 byte *output;
toddouska 0:5045d2638c29 2059 int sendSz = RECORD_HEADER_SZ + ENUM_LEN;
toddouska 0:5045d2638c29 2060 int idx = RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 2061 int ret;
toddouska 0:5045d2638c29 2062
toddouska 0:5045d2638c29 2063 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2064 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2065 sendSz += DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 2066 idx += DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 2067 }
toddouska 0:5045d2638c29 2068 #endif
toddouska 0:5045d2638c29 2069
toddouska 0:5045d2638c29 2070 /* check for avalaible size */
toddouska 0:5045d2638c29 2071 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 2072 return ret;
toddouska 0:5045d2638c29 2073
toddouska 0:5045d2638c29 2074 /* get ouput buffer */
toddouska 0:5045d2638c29 2075 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 2076 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 2077
toddouska 0:5045d2638c29 2078 AddRecordHeader(output, 1, change_cipher_spec, ssl);
toddouska 0:5045d2638c29 2079
toddouska 0:5045d2638c29 2080 output[idx] = 1; /* turn it on */
toddouska 0:5045d2638c29 2081
toddouska 0:5045d2638c29 2082 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 2083 if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 2084 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 2085 AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz,
toddouska 0:5045d2638c29 2086 ssl->heap);
toddouska 0:5045d2638c29 2087 #endif
toddouska 0:5045d2638c29 2088 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 2089 return SendBuffered(ssl);
toddouska 0:5045d2638c29 2090 }
toddouska 0:5045d2638c29 2091
toddouska 0:5045d2638c29 2092
toddouska 0:5045d2638c29 2093 static INLINE const byte* GetMacSecret(SSL* ssl, int verify)
toddouska 0:5045d2638c29 2094 {
toddouska 0:5045d2638c29 2095 if ( (ssl->options.side == CLIENT_END && !verify) ||
toddouska 0:5045d2638c29 2096 (ssl->options.side == SERVER_END && verify) )
toddouska 0:5045d2638c29 2097 return ssl->keys.client_write_MAC_secret;
toddouska 0:5045d2638c29 2098 else
toddouska 0:5045d2638c29 2099 return ssl->keys.server_write_MAC_secret;
toddouska 0:5045d2638c29 2100 }
toddouska 0:5045d2638c29 2101
toddouska 0:5045d2638c29 2102
toddouska 0:5045d2638c29 2103 static void Hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
toddouska 0:5045d2638c29 2104 int content, int verify)
toddouska 0:5045d2638c29 2105 {
toddouska 0:5045d2638c29 2106 byte result[SHA_DIGEST_SIZE]; /* max possible sizes */
toddouska 0:5045d2638c29 2107 word32 digestSz = ssl->specs.hash_size; /* actual sizes */
toddouska 0:5045d2638c29 2108 word32 padSz = ssl->specs.pad_size;
toddouska 0:5045d2638c29 2109
toddouska 0:5045d2638c29 2110 Md5 md5;
toddouska 0:5045d2638c29 2111 Sha sha;
toddouska 0:5045d2638c29 2112
toddouska 0:5045d2638c29 2113 /* data */
toddouska 0:5045d2638c29 2114 byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
toddouska 0:5045d2638c29 2115 byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
toddouska 0:5045d2638c29 2116 const byte* macSecret = GetMacSecret(ssl, verify);
toddouska 0:5045d2638c29 2117
toddouska 0:5045d2638c29 2118 conLen[0] = content;
toddouska 0:5045d2638c29 2119 c16toa((word16)sz, &conLen[ENUM_LEN]);
toddouska 0:5045d2638c29 2120 c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
toddouska 0:5045d2638c29 2121
toddouska 0:5045d2638c29 2122 if (ssl->specs.mac_algorithm == md5_mac) {
toddouska 0:5045d2638c29 2123 InitMd5(&md5);
toddouska 0:5045d2638c29 2124 /* inner */
toddouska 0:5045d2638c29 2125 Md5Update(&md5, macSecret, digestSz);
toddouska 0:5045d2638c29 2126 Md5Update(&md5, PAD1, padSz);
toddouska 0:5045d2638c29 2127 Md5Update(&md5, seq, SEQ_SZ);
toddouska 0:5045d2638c29 2128 Md5Update(&md5, conLen, sizeof(conLen));
toddouska 0:5045d2638c29 2129 /* buffer */
toddouska 0:5045d2638c29 2130 Md5Update(&md5, buffer, sz);
toddouska 0:5045d2638c29 2131 Md5Final(&md5, result);
toddouska 0:5045d2638c29 2132 /* outer */
toddouska 0:5045d2638c29 2133 Md5Update(&md5, macSecret, digestSz);
toddouska 0:5045d2638c29 2134 Md5Update(&md5, PAD2, padSz);
toddouska 0:5045d2638c29 2135 Md5Update(&md5, result, digestSz);
toddouska 0:5045d2638c29 2136 Md5Final(&md5, digest);
toddouska 0:5045d2638c29 2137 }
toddouska 0:5045d2638c29 2138 else {
toddouska 0:5045d2638c29 2139 InitSha(&sha);
toddouska 0:5045d2638c29 2140 /* inner */
toddouska 0:5045d2638c29 2141 ShaUpdate(&sha, macSecret, digestSz);
toddouska 0:5045d2638c29 2142 ShaUpdate(&sha, PAD1, padSz);
toddouska 0:5045d2638c29 2143 ShaUpdate(&sha, seq, SEQ_SZ);
toddouska 0:5045d2638c29 2144 ShaUpdate(&sha, conLen, sizeof(conLen));
toddouska 0:5045d2638c29 2145 /* buffer */
toddouska 0:5045d2638c29 2146 ShaUpdate(&sha, buffer, sz);
toddouska 0:5045d2638c29 2147 ShaFinal(&sha, result);
toddouska 0:5045d2638c29 2148 /* outer */
toddouska 0:5045d2638c29 2149 ShaUpdate(&sha, macSecret, digestSz);
toddouska 0:5045d2638c29 2150 ShaUpdate(&sha, PAD2, padSz);
toddouska 0:5045d2638c29 2151 ShaUpdate(&sha, result, digestSz);
toddouska 0:5045d2638c29 2152 ShaFinal(&sha, digest);
toddouska 0:5045d2638c29 2153 }
toddouska 0:5045d2638c29 2154 }
toddouska 0:5045d2638c29 2155
toddouska 0:5045d2638c29 2156
toddouska 0:5045d2638c29 2157 static void BuildMD5_CertVerify(SSL* ssl, byte* digest)
toddouska 0:5045d2638c29 2158 {
toddouska 0:5045d2638c29 2159 byte md5_result[MD5_DIGEST_SIZE];
toddouska 0:5045d2638c29 2160
toddouska 0:5045d2638c29 2161 /* make md5 inner */
toddouska 0:5045d2638c29 2162 Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 2163 Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
toddouska 0:5045d2638c29 2164 Md5Final(&ssl->hashMd5, md5_result);
toddouska 0:5045d2638c29 2165
toddouska 0:5045d2638c29 2166 /* make md5 outer */
toddouska 0:5045d2638c29 2167 Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 2168 Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
toddouska 0:5045d2638c29 2169 Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
toddouska 0:5045d2638c29 2170
toddouska 0:5045d2638c29 2171 Md5Final(&ssl->hashMd5, digest);
toddouska 0:5045d2638c29 2172 }
toddouska 0:5045d2638c29 2173
toddouska 0:5045d2638c29 2174
toddouska 0:5045d2638c29 2175 static void BuildSHA_CertVerify(SSL* ssl, byte* digest)
toddouska 0:5045d2638c29 2176 {
toddouska 0:5045d2638c29 2177 byte sha_result[SHA_DIGEST_SIZE];
toddouska 0:5045d2638c29 2178
toddouska 0:5045d2638c29 2179 /* make sha inner */
toddouska 0:5045d2638c29 2180 ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 2181 ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
toddouska 0:5045d2638c29 2182 ShaFinal(&ssl->hashSha, sha_result);
toddouska 0:5045d2638c29 2183
toddouska 0:5045d2638c29 2184 /* make sha outer */
toddouska 0:5045d2638c29 2185 ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
toddouska 0:5045d2638c29 2186 ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
toddouska 0:5045d2638c29 2187 ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
toddouska 0:5045d2638c29 2188
toddouska 0:5045d2638c29 2189 ShaFinal(&ssl->hashSha, digest);
toddouska 0:5045d2638c29 2190 }
toddouska 0:5045d2638c29 2191
toddouska 0:5045d2638c29 2192
toddouska 0:5045d2638c29 2193 static void BuildCertHashes(SSL* ssl, Hashes* hashes)
toddouska 0:5045d2638c29 2194 {
toddouska 0:5045d2638c29 2195 /* store current states, building requires get_digest which resets state */
toddouska 0:5045d2638c29 2196 Md5 md5 = ssl->hashMd5;
toddouska 0:5045d2638c29 2197 Sha sha = ssl->hashSha;
toddouska 0:5045d2638c29 2198
toddouska 0:5045d2638c29 2199 if (ssl->options.tls) {
toddouska 0:5045d2638c29 2200 Md5Final(&ssl->hashMd5, hashes->md5);
toddouska 0:5045d2638c29 2201 ShaFinal(&ssl->hashSha, hashes->sha);
toddouska 0:5045d2638c29 2202 }
toddouska 0:5045d2638c29 2203 else {
toddouska 0:5045d2638c29 2204 BuildMD5_CertVerify(ssl, hashes->md5);
toddouska 0:5045d2638c29 2205 BuildSHA_CertVerify(ssl, hashes->sha);
toddouska 0:5045d2638c29 2206 }
toddouska 0:5045d2638c29 2207
toddouska 0:5045d2638c29 2208 /* restore */
toddouska 0:5045d2638c29 2209 ssl->hashMd5 = md5;
toddouska 0:5045d2638c29 2210 ssl->hashSha = sha;
toddouska 0:5045d2638c29 2211 }
toddouska 0:5045d2638c29 2212
toddouska 0:5045d2638c29 2213
toddouska 0:5045d2638c29 2214 /* Build SSL Message, encrypted */
toddouska 0:5045d2638c29 2215 static int BuildMessage(SSL* ssl, byte* output, const byte* input, int inSz,
toddouska 0:5045d2638c29 2216 int type)
toddouska 0:5045d2638c29 2217 {
toddouska 0:5045d2638c29 2218 word32 digestSz = ssl->specs.hash_size;
toddouska 0:5045d2638c29 2219 word32 sz = RECORD_HEADER_SZ + inSz + digestSz;
toddouska 0:5045d2638c29 2220 word32 pad = 0, i;
toddouska 0:5045d2638c29 2221 word32 idx = RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 2222 word32 ivSz = 0; /* TLSv1.1 IV */
toddouska 0:5045d2638c29 2223 word32 headerSz = RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 2224 word16 size;
toddouska 0:5045d2638c29 2225 byte iv[AES_BLOCK_SIZE]; /* max size */
toddouska 0:5045d2638c29 2226
toddouska 0:5045d2638c29 2227 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2228 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2229 sz += DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 2230 idx += DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 2231 headerSz += DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 2232 }
toddouska 0:5045d2638c29 2233 #endif
toddouska 0:5045d2638c29 2234
toddouska 0:5045d2638c29 2235 if (ssl->specs.cipher_type == block) {
toddouska 0:5045d2638c29 2236 word32 blockSz = ssl->specs.block_size;
toddouska 0:5045d2638c29 2237 if (ssl->options.tls1_1) {
toddouska 0:5045d2638c29 2238 ivSz = blockSz;
toddouska 0:5045d2638c29 2239 sz += ivSz;
toddouska 0:5045d2638c29 2240 RNG_GenerateBlock(&ssl->rng, iv, ivSz);
toddouska 0:5045d2638c29 2241 }
toddouska 0:5045d2638c29 2242 sz += 1; /* pad byte */
toddouska 0:5045d2638c29 2243 pad = (sz - headerSz) % blockSz;
toddouska 0:5045d2638c29 2244 pad = blockSz - pad;
toddouska 0:5045d2638c29 2245 sz += pad;
toddouska 0:5045d2638c29 2246 }
toddouska 0:5045d2638c29 2247
toddouska 0:5045d2638c29 2248 size = sz - headerSz; /* include mac and digest */
toddouska 0:5045d2638c29 2249 AddRecordHeader(output, size, type, ssl);
toddouska 0:5045d2638c29 2250
toddouska 0:5045d2638c29 2251 /* write to output */
toddouska 0:5045d2638c29 2252 if (ivSz) {
toddouska 0:5045d2638c29 2253 XMEMCPY(output + idx, iv, ivSz);
toddouska 0:5045d2638c29 2254 idx += ivSz;
toddouska 0:5045d2638c29 2255 }
toddouska 0:5045d2638c29 2256 XMEMCPY(output + idx, input, inSz);
toddouska 0:5045d2638c29 2257 idx += inSz;
toddouska 0:5045d2638c29 2258
toddouska 0:5045d2638c29 2259 if (type == handshake)
toddouska 0:5045d2638c29 2260 HashOutput(ssl, output, headerSz + inSz, ivSz);
toddouska 0:5045d2638c29 2261 ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
toddouska 0:5045d2638c29 2262 idx += digestSz;
toddouska 0:5045d2638c29 2263
toddouska 0:5045d2638c29 2264 if (ssl->specs.cipher_type == block)
toddouska 0:5045d2638c29 2265 for (i = 0; i <= pad; i++) output[idx++] = pad; /* pad byte gets */
toddouska 0:5045d2638c29 2266 /* pad value too */
toddouska 0:5045d2638c29 2267 Encrypt(ssl, output + headerSz, output + headerSz, size);
toddouska 0:5045d2638c29 2268
toddouska 0:5045d2638c29 2269 return sz;
toddouska 0:5045d2638c29 2270 }
toddouska 0:5045d2638c29 2271
toddouska 0:5045d2638c29 2272
toddouska 0:5045d2638c29 2273 int SendFinished(SSL* ssl)
toddouska 0:5045d2638c29 2274 {
toddouska 0:5045d2638c29 2275 int sendSz,
toddouska 0:5045d2638c29 2276 finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
toddouska 0:5045d2638c29 2277 FINISHED_SZ;
toddouska 0:5045d2638c29 2278 byte input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ]; /* max */
toddouska 0:5045d2638c29 2279 byte *output;
toddouska 0:5045d2638c29 2280 Hashes* hashes;
toddouska 0:5045d2638c29 2281 int ret;
toddouska 0:5045d2638c29 2282 int headerSz = HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 2283
toddouska 0:5045d2638c29 2284
toddouska 0:5045d2638c29 2285 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2286 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2287 headerSz += DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 2288 ssl->keys.dtls_epoch++;
toddouska 0:5045d2638c29 2289 ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */
toddouska 0:5045d2638c29 2290 }
toddouska 0:5045d2638c29 2291 #endif
toddouska 0:5045d2638c29 2292
toddouska 0:5045d2638c29 2293 /* check for avalaible size */
toddouska 0:5045d2638c29 2294 if ((ret = CheckAvalaibleSize(ssl, sizeof(input) + MAX_MSG_EXTRA)) != 0)
toddouska 0:5045d2638c29 2295 return ret;
toddouska 0:5045d2638c29 2296
toddouska 0:5045d2638c29 2297 /* get ouput buffer */
toddouska 0:5045d2638c29 2298 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 2299 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 2300
toddouska 0:5045d2638c29 2301 AddHandShakeHeader(input, finishedSz, finished, ssl);
toddouska 0:5045d2638c29 2302
toddouska 0:5045d2638c29 2303 /* make finished hashes */
toddouska 0:5045d2638c29 2304 hashes = (Hashes*)&input[headerSz];
toddouska 0:5045d2638c29 2305 BuildFinished(ssl, hashes, ssl->options.side == CLIENT_END ? client :
toddouska 0:5045d2638c29 2306 server);
toddouska 0:5045d2638c29 2307
toddouska 0:5045d2638c29 2308 if ( (sendSz = BuildMessage(ssl, output, input, headerSz +
toddouska 0:5045d2638c29 2309 finishedSz, handshake)) == -1)
toddouska 0:5045d2638c29 2310 return BUILD_MSG_ERROR;
toddouska 0:5045d2638c29 2311
toddouska 0:5045d2638c29 2312 if (!ssl->options.resuming) {
toddouska 0:5045d2638c29 2313 AddSession(ssl); /* just try */
toddouska 0:5045d2638c29 2314 if (ssl->options.side == CLIENT_END)
toddouska 0:5045d2638c29 2315 BuildFinished(ssl, &ssl->verifyHashes, server);
toddouska 0:5045d2638c29 2316 else
toddouska 0:5045d2638c29 2317 ssl->options.handShakeState = HANDSHAKE_DONE;
toddouska 0:5045d2638c29 2318 }
toddouska 0:5045d2638c29 2319 else {
toddouska 0:5045d2638c29 2320 if (ssl->options.side == CLIENT_END)
toddouska 0:5045d2638c29 2321 ssl->options.handShakeState = HANDSHAKE_DONE;
toddouska 0:5045d2638c29 2322 else
toddouska 0:5045d2638c29 2323 BuildFinished(ssl, &ssl->verifyHashes, client);
toddouska 0:5045d2638c29 2324 }
toddouska 0:5045d2638c29 2325
toddouska 0:5045d2638c29 2326 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 2327 if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 2328 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 2329 AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz,
toddouska 0:5045d2638c29 2330 ssl->heap);
toddouska 0:5045d2638c29 2331 #endif
toddouska 0:5045d2638c29 2332
toddouska 0:5045d2638c29 2333 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 2334
toddouska 0:5045d2638c29 2335 return SendBuffered(ssl);
toddouska 0:5045d2638c29 2336 }
toddouska 0:5045d2638c29 2337
toddouska 0:5045d2638c29 2338
toddouska 0:5045d2638c29 2339 int SendCertificate(SSL* ssl)
toddouska 0:5045d2638c29 2340 {
toddouska 0:5045d2638c29 2341 int sendSz, length, ret = 0;
toddouska 0:5045d2638c29 2342 word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 2343 word32 certSz, listSz;
toddouska 0:5045d2638c29 2344 byte* output = 0;
toddouska 0:5045d2638c29 2345
toddouska 0:5045d2638c29 2346 if (ssl->options.usingPSK_cipher) return 0; /* not needed */
toddouska 0:5045d2638c29 2347
toddouska 0:5045d2638c29 2348 if (ssl->options.sendVerify == SEND_BLANK_CERT) {
toddouska 0:5045d2638c29 2349 certSz = 0;
toddouska 0:5045d2638c29 2350 length = CERT_HEADER_SZ;
toddouska 0:5045d2638c29 2351 listSz = 0;
toddouska 0:5045d2638c29 2352 }
toddouska 0:5045d2638c29 2353 else {
toddouska 0:5045d2638c29 2354 certSz = ssl->buffers.certificate.length;
toddouska 0:5045d2638c29 2355 /* list + cert size */
toddouska 0:5045d2638c29 2356 length = certSz + 2 * CERT_HEADER_SZ;
toddouska 0:5045d2638c29 2357 listSz = certSz + CERT_HEADER_SZ;
toddouska 0:5045d2638c29 2358 }
toddouska 0:5045d2638c29 2359 sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 2360
toddouska 0:5045d2638c29 2361 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2362 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2363 sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 2364 i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 2365 }
toddouska 0:5045d2638c29 2366 #endif
toddouska 0:5045d2638c29 2367
toddouska 0:5045d2638c29 2368 /* check for avalaible size */
toddouska 0:5045d2638c29 2369 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 2370 return ret;
toddouska 0:5045d2638c29 2371
toddouska 0:5045d2638c29 2372 /* get ouput buffer */
toddouska 0:5045d2638c29 2373 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 2374 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 2375
toddouska 0:5045d2638c29 2376 AddHeaders(output, length, certificate, ssl);
toddouska 0:5045d2638c29 2377
toddouska 0:5045d2638c29 2378 /* list total */
toddouska 0:5045d2638c29 2379 c32to24(listSz, output + i);
toddouska 0:5045d2638c29 2380 i += CERT_HEADER_SZ;
toddouska 0:5045d2638c29 2381
toddouska 0:5045d2638c29 2382 /* member */
toddouska 0:5045d2638c29 2383 if (certSz) {
toddouska 0:5045d2638c29 2384 c32to24(certSz, output + i);
toddouska 0:5045d2638c29 2385 i += CERT_HEADER_SZ;
toddouska 0:5045d2638c29 2386 XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz);
toddouska 0:5045d2638c29 2387 i += certSz;
toddouska 0:5045d2638c29 2388 }
toddouska 0:5045d2638c29 2389 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 2390 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 2391 if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 2392 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 2393 AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz,
toddouska 0:5045d2638c29 2394 ssl->heap);
toddouska 0:5045d2638c29 2395 #endif
toddouska 0:5045d2638c29 2396
toddouska 0:5045d2638c29 2397 if (ssl->options.side == SERVER_END)
toddouska 0:5045d2638c29 2398 ssl->options.serverState = SERVER_CERT_COMPLETE;
toddouska 0:5045d2638c29 2399
toddouska 0:5045d2638c29 2400 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 2401 return SendBuffered(ssl);
toddouska 0:5045d2638c29 2402 }
toddouska 0:5045d2638c29 2403
toddouska 0:5045d2638c29 2404
toddouska 0:5045d2638c29 2405 int SendCertificateRequest(SSL* ssl)
toddouska 0:5045d2638c29 2406 {
toddouska 0:5045d2638c29 2407 byte *output;
toddouska 0:5045d2638c29 2408 int ret;
toddouska 0:5045d2638c29 2409 int sendSz;
toddouska 0:5045d2638c29 2410 word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 2411
toddouska 0:5045d2638c29 2412 int typeTotal = 1; /* only rsa for now */
toddouska 0:5045d2638c29 2413 int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
toddouska 0:5045d2638c29 2414
toddouska 0:5045d2638c29 2415 if (ssl->options.usingPSK_cipher) return 0; /* not needed */
toddouska 0:5045d2638c29 2416
toddouska 0:5045d2638c29 2417 sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
toddouska 0:5045d2638c29 2418
toddouska 0:5045d2638c29 2419 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2420 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2421 sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 2422 i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 2423 }
toddouska 0:5045d2638c29 2424 #endif
toddouska 0:5045d2638c29 2425 /* check for avalaible size */
toddouska 0:5045d2638c29 2426 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 2427 return ret;
toddouska 0:5045d2638c29 2428
toddouska 0:5045d2638c29 2429 /* get ouput buffer */
toddouska 0:5045d2638c29 2430 output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 2431
toddouska 0:5045d2638c29 2432 AddHeaders(output, reqSz, certificate_request, ssl);
toddouska 0:5045d2638c29 2433
toddouska 0:5045d2638c29 2434 /* write to output */
toddouska 0:5045d2638c29 2435 output[i++] = typeTotal; /* # of types */
toddouska 0:5045d2638c29 2436 output[i++] = rsa_sign;
toddouska 0:5045d2638c29 2437
toddouska 0:5045d2638c29 2438 c16toa(0, &output[i]); /* auth's */
toddouska 0:5045d2638c29 2439 i += REQ_HEADER_SZ;
toddouska 0:5045d2638c29 2440
toddouska 0:5045d2638c29 2441 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 2442
toddouska 0:5045d2638c29 2443 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 2444 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 2445 AddPacketName("CertificateRequest", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 2446 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 2447 AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output,
toddouska 0:5045d2638c29 2448 sendSz, ssl->heap);
toddouska 0:5045d2638c29 2449 #endif
toddouska 0:5045d2638c29 2450 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 2451 return SendBuffered(ssl);
toddouska 0:5045d2638c29 2452 }
toddouska 0:5045d2638c29 2453
toddouska 0:5045d2638c29 2454
toddouska 0:5045d2638c29 2455 int SendData(SSL* ssl, const void* buffer, int sz)
toddouska 0:5045d2638c29 2456 {
toddouska 0:5045d2638c29 2457 int sent = 0, /* plainText size */
toddouska 0:5045d2638c29 2458 sendSz,
toddouska 0:5045d2638c29 2459 ret;
toddouska 0:5045d2638c29 2460
toddouska 0:5045d2638c29 2461 if (ssl->error == WANT_WRITE)
toddouska 0:5045d2638c29 2462 ssl->error = 0;
toddouska 0:5045d2638c29 2463
toddouska 0:5045d2638c29 2464 if (ssl->options.handShakeState != HANDSHAKE_DONE) {
toddouska 0:5045d2638c29 2465 int err;
toddouska 0:5045d2638c29 2466 if ( (err = CyaSSL_negotiate(ssl)) != 0)
toddouska 0:5045d2638c29 2467 return err;
toddouska 0:5045d2638c29 2468 }
toddouska 0:5045d2638c29 2469
toddouska 0:5045d2638c29 2470 /* last time system socket output buffer was full, try again to send */
toddouska 0:5045d2638c29 2471 if (ssl->buffers.outputBuffer.length > 0) {
toddouska 0:5045d2638c29 2472 if ( (ssl->error = SendBuffered(ssl)) < 0) {
toddouska 0:5045d2638c29 2473 CYASSL_ERROR(ssl->error);
toddouska 0:5045d2638c29 2474 if (ssl->error == SOCKET_ERROR_E && ssl->options.connReset)
toddouska 0:5045d2638c29 2475 return 0; /* peer reset */
toddouska 0:5045d2638c29 2476 return ssl->error;
toddouska 0:5045d2638c29 2477 }
toddouska 0:5045d2638c29 2478 else {
toddouska 0:5045d2638c29 2479 /* advance sent to previous sent + plain size just sent */
toddouska 0:5045d2638c29 2480 sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
toddouska 0:5045d2638c29 2481 CYASSL_MSG("sent write buffered data");
toddouska 0:5045d2638c29 2482 }
toddouska 0:5045d2638c29 2483 }
toddouska 0:5045d2638c29 2484
toddouska 0:5045d2638c29 2485 for (;;) {
toddouska 0:5045d2638c29 2486 int len = min(sz - sent, OUTPUT_RECORD_SIZE);
toddouska 0:5045d2638c29 2487 byte* out;
toddouska 0:5045d2638c29 2488 byte* sendBuffer = (byte*)buffer + sent; /* may switch on comp */
toddouska 0:5045d2638c29 2489 int buffSz = len; /* may switch on comp */
toddouska 0:5045d2638c29 2490 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 2491 byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
toddouska 0:5045d2638c29 2492 #endif
toddouska 0:5045d2638c29 2493
toddouska 0:5045d2638c29 2494 if (sent == sz) break;
toddouska 0:5045d2638c29 2495
toddouska 0:5045d2638c29 2496 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 2497 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 2498 len = min(len, MAX_UDP_SIZE);
toddouska 0:5045d2638c29 2499 buffSz = len;
toddouska 0:5045d2638c29 2500 }
toddouska 0:5045d2638c29 2501 #endif
toddouska 0:5045d2638c29 2502
toddouska 0:5045d2638c29 2503 /* check for avalaible size */
toddouska 0:5045d2638c29 2504 if ((ret = CheckAvalaibleSize(ssl, len + COMP_EXTRA +
toddouska 0:5045d2638c29 2505 MAX_MSG_EXTRA)) != 0)
toddouska 0:5045d2638c29 2506 return ret;
toddouska 0:5045d2638c29 2507
toddouska 0:5045d2638c29 2508 /* get ouput buffer */
toddouska 0:5045d2638c29 2509 out = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 2510 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 2511
toddouska 0:5045d2638c29 2512 #ifdef HAVE_LIBZ
toddouska 0:5045d2638c29 2513 if (ssl->options.usingCompression) {
toddouska 0:5045d2638c29 2514 buffSz = Compress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
toddouska 0:5045d2638c29 2515 if (buffSz < 0) {
toddouska 0:5045d2638c29 2516 return buffSz;
toddouska 0:5045d2638c29 2517 }
toddouska 0:5045d2638c29 2518 sendBuffer = comp;
toddouska 0:5045d2638c29 2519 }
toddouska 0:5045d2638c29 2520 #endif
toddouska 0:5045d2638c29 2521 sendSz = BuildMessage(ssl, out, sendBuffer, buffSz,
toddouska 0:5045d2638c29 2522 application_data);
toddouska 0:5045d2638c29 2523
toddouska 0:5045d2638c29 2524 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 2525
toddouska 0:5045d2638c29 2526 if ( (ret = SendBuffered(ssl)) < 0) {
toddouska 0:5045d2638c29 2527 CYASSL_ERROR(ret);
toddouska 0:5045d2638c29 2528 /* store for next call if WANT_WRITE or user embedSend() that
toddouska 0:5045d2638c29 2529 doesn't present like WANT_WRITE */
toddouska 0:5045d2638c29 2530 ssl->buffers.plainSz = len;
toddouska 0:5045d2638c29 2531 ssl->buffers.prevSent = sent;
toddouska 0:5045d2638c29 2532 if (ret == SOCKET_ERROR_E && ssl->options.connReset)
toddouska 0:5045d2638c29 2533 return 0; /* peer reset */
toddouska 0:5045d2638c29 2534 return ssl->error = ret;
toddouska 0:5045d2638c29 2535 }
toddouska 0:5045d2638c29 2536
toddouska 0:5045d2638c29 2537 sent += len;
toddouska 0:5045d2638c29 2538
toddouska 0:5045d2638c29 2539 /* only one message per attempt */
toddouska 0:5045d2638c29 2540 if (ssl->options.partialWrite == 1)
toddouska 0:5045d2638c29 2541 break;
toddouska 0:5045d2638c29 2542 }
toddouska 0:5045d2638c29 2543
toddouska 0:5045d2638c29 2544 return sent;
toddouska 0:5045d2638c29 2545 }
toddouska 0:5045d2638c29 2546
toddouska 0:5045d2638c29 2547 /* process input data */
toddouska 0:5045d2638c29 2548 int ReceiveData(SSL* ssl, byte* output, int sz)
toddouska 0:5045d2638c29 2549 {
toddouska 0:5045d2638c29 2550 int size;
toddouska 0:5045d2638c29 2551
toddouska 0:5045d2638c29 2552 CYASSL_ENTER("ReceiveData()");
toddouska 0:5045d2638c29 2553
toddouska 0:5045d2638c29 2554 if (ssl->error == WANT_READ)
toddouska 0:5045d2638c29 2555 ssl->error = 0;
toddouska 0:5045d2638c29 2556
toddouska 0:5045d2638c29 2557 if (ssl->options.handShakeState != HANDSHAKE_DONE) {
toddouska 0:5045d2638c29 2558 int err;
toddouska 0:5045d2638c29 2559 if ( (err = CyaSSL_negotiate(ssl)) != 0)
toddouska 0:5045d2638c29 2560 return err;
toddouska 0:5045d2638c29 2561 }
toddouska 0:5045d2638c29 2562
toddouska 0:5045d2638c29 2563 while (ssl->buffers.clearOutputBuffer.length == 0)
toddouska 0:5045d2638c29 2564 if ( (ssl->error = ProcessReply(ssl)) < 0) {
toddouska 0:5045d2638c29 2565 CYASSL_ERROR(ssl->error);
toddouska 0:5045d2638c29 2566 if (ssl->error == ZERO_RETURN) {
toddouska 0:5045d2638c29 2567 ssl->options.isClosed = 1;
toddouska 0:5045d2638c29 2568 return 0; /* no more data coming */
toddouska 0:5045d2638c29 2569 }
toddouska 0:5045d2638c29 2570 if (ssl->error == SOCKET_ERROR_E)
toddouska 0:5045d2638c29 2571 if (ssl->options.connReset || ssl->options.isClosed)
toddouska 0:5045d2638c29 2572 return 0; /* peer reset or closed */
toddouska 0:5045d2638c29 2573 return ssl->error;
toddouska 0:5045d2638c29 2574 }
toddouska 0:5045d2638c29 2575
toddouska 0:5045d2638c29 2576 if (sz < (int)ssl->buffers.clearOutputBuffer.length)
toddouska 0:5045d2638c29 2577 size = sz;
toddouska 0:5045d2638c29 2578 else
toddouska 0:5045d2638c29 2579 size = ssl->buffers.clearOutputBuffer.length;
toddouska 0:5045d2638c29 2580
toddouska 0:5045d2638c29 2581 XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
toddouska 0:5045d2638c29 2582 ssl->buffers.clearOutputBuffer.length -= size;
toddouska 0:5045d2638c29 2583 ssl->buffers.clearOutputBuffer.buffer += size;
toddouska 0:5045d2638c29 2584
toddouska 0:5045d2638c29 2585 if (ssl->buffers.clearOutputBuffer.length == 0 &&
toddouska 0:5045d2638c29 2586 ssl->buffers.inputBuffer.dynamicFlag)
toddouska 0:5045d2638c29 2587 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
toddouska 0:5045d2638c29 2588
toddouska 0:5045d2638c29 2589 CYASSL_LEAVE("ReceiveData()", size);
toddouska 0:5045d2638c29 2590 return size;
toddouska 0:5045d2638c29 2591 }
toddouska 0:5045d2638c29 2592
toddouska 0:5045d2638c29 2593
toddouska 0:5045d2638c29 2594 /* send alert message */
toddouska 0:5045d2638c29 2595 int SendAlert(SSL* ssl, int severity, int type)
toddouska 0:5045d2638c29 2596 {
toddouska 0:5045d2638c29 2597 byte input[ALERT_SIZE];
toddouska 0:5045d2638c29 2598 byte *output;
toddouska 0:5045d2638c29 2599 int sendSz;
toddouska 0:5045d2638c29 2600 int ret;
toddouska 0:5045d2638c29 2601
toddouska 0:5045d2638c29 2602 /* if sendalert is called again for nonbloking */
toddouska 0:5045d2638c29 2603 if (ssl->options.sendAlertState != 0) {
toddouska 0:5045d2638c29 2604 ret = SendBuffered(ssl);
toddouska 0:5045d2638c29 2605 if (ret == 0)
toddouska 0:5045d2638c29 2606 ssl->options.sendAlertState = 0;
toddouska 0:5045d2638c29 2607 return ret;
toddouska 0:5045d2638c29 2608 }
toddouska 0:5045d2638c29 2609
toddouska 0:5045d2638c29 2610 /* check for avalaible size */
toddouska 0:5045d2638c29 2611 if ((ret = CheckAvalaibleSize(ssl, ALERT_SIZE + MAX_MSG_EXTRA)) != 0)
toddouska 0:5045d2638c29 2612 return ret;
toddouska 0:5045d2638c29 2613
toddouska 0:5045d2638c29 2614 /* get ouput buffer */
toddouska 0:5045d2638c29 2615 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 2616 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 2617
toddouska 0:5045d2638c29 2618 input[0] = severity;
toddouska 0:5045d2638c29 2619 input[1] = type;
toddouska 0:5045d2638c29 2620
toddouska 0:5045d2638c29 2621 if (ssl->keys.encryptionOn)
toddouska 0:5045d2638c29 2622 sendSz = BuildMessage(ssl, output, input, sizeof(input), alert);
toddouska 0:5045d2638c29 2623 else {
toddouska 0:5045d2638c29 2624 RecordLayerHeader *const rl = (RecordLayerHeader*)output;
toddouska 0:5045d2638c29 2625 rl->type = alert;
toddouska 0:5045d2638c29 2626 rl->version = ssl->version;
toddouska 0:5045d2638c29 2627 c16toa(ALERT_SIZE, rl->length);
toddouska 0:5045d2638c29 2628
toddouska 0:5045d2638c29 2629 XMEMCPY(output + RECORD_HEADER_SZ, input, sizeof(input));
toddouska 0:5045d2638c29 2630 sendSz = RECORD_HEADER_SZ + sizeof(input);
toddouska 0:5045d2638c29 2631 }
toddouska 0:5045d2638c29 2632
toddouska 0:5045d2638c29 2633 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 2634 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 2635 AddPacketName("Alert", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 2636 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 2637 AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap);
toddouska 0:5045d2638c29 2638 #endif
toddouska 0:5045d2638c29 2639
toddouska 0:5045d2638c29 2640 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 2641 ssl->options.sendAlertState = 1;
toddouska 0:5045d2638c29 2642
toddouska 0:5045d2638c29 2643 return SendBuffered(ssl);
toddouska 0:5045d2638c29 2644 }
toddouska 0:5045d2638c29 2645
toddouska 0:5045d2638c29 2646
toddouska 0:5045d2638c29 2647
toddouska 0:5045d2638c29 2648 void SetErrorString(int error, char* buffer)
toddouska 0:5045d2638c29 2649 {
toddouska 0:5045d2638c29 2650 const int max = MAX_ERROR_SZ; /* shorthand */
toddouska 0:5045d2638c29 2651
toddouska 0:5045d2638c29 2652 #ifdef NO_ERROR_STRINGS
toddouska 0:5045d2638c29 2653
toddouska 0:5045d2638c29 2654 XSTRNCPY(buffer, "no support for error strings built in", max);
toddouska 0:5045d2638c29 2655
toddouska 0:5045d2638c29 2656 #else
toddouska 0:5045d2638c29 2657
toddouska 0:5045d2638c29 2658 /* pass to CTaoCrypt */
toddouska 0:5045d2638c29 2659 if (error < MAX_CODE_E && error > MIN_CODE_E) {
toddouska 0:5045d2638c29 2660 CTaoCryptErrorString(error, buffer);
toddouska 0:5045d2638c29 2661 return;
toddouska 0:5045d2638c29 2662 }
toddouska 0:5045d2638c29 2663
toddouska 0:5045d2638c29 2664 switch (error) {
toddouska 0:5045d2638c29 2665
toddouska 0:5045d2638c29 2666 case UNSUPPORTED_SUITE :
toddouska 0:5045d2638c29 2667 XSTRNCPY(buffer, "unsupported cipher suite", max);
toddouska 0:5045d2638c29 2668 break;
toddouska 0:5045d2638c29 2669
toddouska 0:5045d2638c29 2670 case PREFIX_ERROR :
toddouska 0:5045d2638c29 2671 XSTRNCPY(buffer, "bad index to key rounds", max);
toddouska 0:5045d2638c29 2672 break;
toddouska 0:5045d2638c29 2673
toddouska 0:5045d2638c29 2674 case MEMORY_ERROR :
toddouska 0:5045d2638c29 2675 XSTRNCPY(buffer, "out of memory", max);
toddouska 0:5045d2638c29 2676 break;
toddouska 0:5045d2638c29 2677
toddouska 0:5045d2638c29 2678 case VERIFY_FINISHED_ERROR :
toddouska 0:5045d2638c29 2679 XSTRNCPY(buffer, "verify problem on finished", max);
toddouska 0:5045d2638c29 2680 break;
toddouska 0:5045d2638c29 2681
toddouska 0:5045d2638c29 2682 case VERIFY_MAC_ERROR :
toddouska 0:5045d2638c29 2683 XSTRNCPY(buffer, "verify mac problem", max);
toddouska 0:5045d2638c29 2684 break;
toddouska 0:5045d2638c29 2685
toddouska 0:5045d2638c29 2686 case PARSE_ERROR :
toddouska 0:5045d2638c29 2687 XSTRNCPY(buffer, "parse error on header", max);
toddouska 0:5045d2638c29 2688 break;
toddouska 0:5045d2638c29 2689
toddouska 0:5045d2638c29 2690 case SIDE_ERROR :
toddouska 0:5045d2638c29 2691 XSTRNCPY(buffer, "wrong client/server type", max);
toddouska 0:5045d2638c29 2692 break;
toddouska 0:5045d2638c29 2693
toddouska 0:5045d2638c29 2694 case NO_PEER_CERT :
toddouska 0:5045d2638c29 2695 XSTRNCPY(buffer, "peer didn't send cert", max);
toddouska 0:5045d2638c29 2696 break;
toddouska 0:5045d2638c29 2697
toddouska 0:5045d2638c29 2698 case UNKNOWN_HANDSHAKE_TYPE :
toddouska 0:5045d2638c29 2699 XSTRNCPY(buffer, "weird handshake type", max);
toddouska 0:5045d2638c29 2700 break;
toddouska 0:5045d2638c29 2701
toddouska 0:5045d2638c29 2702 case SOCKET_ERROR_E :
toddouska 0:5045d2638c29 2703 XSTRNCPY(buffer, "error state on socket", max);
toddouska 0:5045d2638c29 2704 break;
toddouska 0:5045d2638c29 2705
toddouska 0:5045d2638c29 2706 case SOCKET_NODATA :
toddouska 0:5045d2638c29 2707 XSTRNCPY(buffer, "expected data, not there", max);
toddouska 0:5045d2638c29 2708 break;
toddouska 0:5045d2638c29 2709
toddouska 0:5045d2638c29 2710 case INCOMPLETE_DATA :
toddouska 0:5045d2638c29 2711 XSTRNCPY(buffer, "don't have enough data to complete task", max);
toddouska 0:5045d2638c29 2712 break;
toddouska 0:5045d2638c29 2713
toddouska 0:5045d2638c29 2714 case UNKNOWN_RECORD_TYPE :
toddouska 0:5045d2638c29 2715 XSTRNCPY(buffer, "unknown type in record hdr", max);
toddouska 0:5045d2638c29 2716 break;
toddouska 0:5045d2638c29 2717
toddouska 0:5045d2638c29 2718 case DECRYPT_ERROR :
toddouska 0:5045d2638c29 2719 XSTRNCPY(buffer, "error during decryption", max);
toddouska 0:5045d2638c29 2720 break;
toddouska 0:5045d2638c29 2721
toddouska 0:5045d2638c29 2722 case FATAL_ERROR :
toddouska 0:5045d2638c29 2723 XSTRNCPY(buffer, "revcd alert fatal error", max);
toddouska 0:5045d2638c29 2724 break;
toddouska 0:5045d2638c29 2725
toddouska 0:5045d2638c29 2726 case ENCRYPT_ERROR :
toddouska 0:5045d2638c29 2727 XSTRNCPY(buffer, "error during encryption", max);
toddouska 0:5045d2638c29 2728 break;
toddouska 0:5045d2638c29 2729
toddouska 0:5045d2638c29 2730 case FREAD_ERROR :
toddouska 0:5045d2638c29 2731 XSTRNCPY(buffer, "fread problem", max);
toddouska 0:5045d2638c29 2732 break;
toddouska 0:5045d2638c29 2733
toddouska 0:5045d2638c29 2734 case NO_PEER_KEY :
toddouska 0:5045d2638c29 2735 XSTRNCPY(buffer, "need peer's key", max);
toddouska 0:5045d2638c29 2736 break;
toddouska 0:5045d2638c29 2737
toddouska 0:5045d2638c29 2738 case NO_PRIVATE_KEY :
toddouska 0:5045d2638c29 2739 XSTRNCPY(buffer, "need the private key", max);
toddouska 0:5045d2638c29 2740 break;
toddouska 0:5045d2638c29 2741
toddouska 0:5045d2638c29 2742 case RSA_PRIVATE_ERROR :
toddouska 0:5045d2638c29 2743 XSTRNCPY(buffer, "error during rsa priv op", max);
toddouska 0:5045d2638c29 2744 break;
toddouska 0:5045d2638c29 2745
toddouska 0:5045d2638c29 2746 case MATCH_SUITE_ERROR :
toddouska 0:5045d2638c29 2747 XSTRNCPY(buffer, "can't match cipher suite", max);
toddouska 0:5045d2638c29 2748 break;
toddouska 0:5045d2638c29 2749
toddouska 0:5045d2638c29 2750 case BUILD_MSG_ERROR :
toddouska 0:5045d2638c29 2751 XSTRNCPY(buffer, "build message failure", max);
toddouska 0:5045d2638c29 2752 break;
toddouska 0:5045d2638c29 2753
toddouska 0:5045d2638c29 2754 case BAD_HELLO :
toddouska 0:5045d2638c29 2755 XSTRNCPY(buffer, "client hello malformed", max);
toddouska 0:5045d2638c29 2756 break;
toddouska 0:5045d2638c29 2757
toddouska 0:5045d2638c29 2758 case DOMAIN_NAME_MISMATCH :
toddouska 0:5045d2638c29 2759 XSTRNCPY(buffer, "peer subject name mismatch", max);
toddouska 0:5045d2638c29 2760 break;
toddouska 0:5045d2638c29 2761
toddouska 0:5045d2638c29 2762 case WANT_READ :
toddouska 0:5045d2638c29 2763 XSTRNCPY(buffer, "non-blocking socket wants data to be read", max);
toddouska 0:5045d2638c29 2764 break;
toddouska 0:5045d2638c29 2765
toddouska 0:5045d2638c29 2766 case NOT_READY_ERROR :
toddouska 0:5045d2638c29 2767 XSTRNCPY(buffer, "handshake layer not ready yet, complete first", max);
toddouska 0:5045d2638c29 2768 break;
toddouska 0:5045d2638c29 2769
toddouska 0:5045d2638c29 2770 case PMS_VERSION_ERROR :
toddouska 0:5045d2638c29 2771 XSTRNCPY(buffer, "premaster secret version mismatch error", max);
toddouska 0:5045d2638c29 2772 break;
toddouska 0:5045d2638c29 2773
toddouska 0:5045d2638c29 2774 case VERSION_ERROR :
toddouska 0:5045d2638c29 2775 XSTRNCPY(buffer, "record layer version error", max);
toddouska 0:5045d2638c29 2776 break;
toddouska 0:5045d2638c29 2777
toddouska 0:5045d2638c29 2778 case WANT_WRITE :
toddouska 0:5045d2638c29 2779 XSTRNCPY(buffer, "non-blocking socket write buffer full", max);
toddouska 0:5045d2638c29 2780 break;
toddouska 0:5045d2638c29 2781
toddouska 0:5045d2638c29 2782 case BUFFER_ERROR :
toddouska 0:5045d2638c29 2783 XSTRNCPY(buffer, "malformed buffer input error", max);
toddouska 0:5045d2638c29 2784 break;
toddouska 0:5045d2638c29 2785
toddouska 0:5045d2638c29 2786 case VERIFY_CERT_ERROR :
toddouska 0:5045d2638c29 2787 XSTRNCPY(buffer, "verify problem on certificate", max);
toddouska 0:5045d2638c29 2788 break;
toddouska 0:5045d2638c29 2789
toddouska 0:5045d2638c29 2790 case VERIFY_SIGN_ERROR :
toddouska 0:5045d2638c29 2791 XSTRNCPY(buffer, "verify problem based on signature", max);
toddouska 0:5045d2638c29 2792 break;
toddouska 0:5045d2638c29 2793
toddouska 0:5045d2638c29 2794 case CLIENT_ID_ERROR :
toddouska 0:5045d2638c29 2795 XSTRNCPY(buffer, "psk client identity error", max);
toddouska 0:5045d2638c29 2796 break;
toddouska 0:5045d2638c29 2797
toddouska 0:5045d2638c29 2798 case SERVER_HINT_ERROR:
toddouska 0:5045d2638c29 2799 XSTRNCPY(buffer, "psk server hint error", max);
toddouska 0:5045d2638c29 2800 break;
toddouska 0:5045d2638c29 2801
toddouska 0:5045d2638c29 2802 case PSK_KEY_ERROR:
toddouska 0:5045d2638c29 2803 XSTRNCPY(buffer, "psk key callback error", max);
toddouska 0:5045d2638c29 2804 break;
toddouska 0:5045d2638c29 2805
toddouska 0:5045d2638c29 2806 case NTRU_KEY_ERROR:
toddouska 0:5045d2638c29 2807 XSTRNCPY(buffer, "NTRU key error", max);
toddouska 0:5045d2638c29 2808 break;
toddouska 0:5045d2638c29 2809
toddouska 0:5045d2638c29 2810 case NTRU_DRBG_ERROR:
toddouska 0:5045d2638c29 2811 XSTRNCPY(buffer, "NTRU drbg error", max);
toddouska 0:5045d2638c29 2812 break;
toddouska 0:5045d2638c29 2813
toddouska 0:5045d2638c29 2814 case NTRU_ENCRYPT_ERROR:
toddouska 0:5045d2638c29 2815 XSTRNCPY(buffer, "NTRU encrypt error", max);
toddouska 0:5045d2638c29 2816 break;
toddouska 0:5045d2638c29 2817
toddouska 0:5045d2638c29 2818 case NTRU_DECRYPT_ERROR:
toddouska 0:5045d2638c29 2819 XSTRNCPY(buffer, "NTRU decrypt error", max);
toddouska 0:5045d2638c29 2820 break;
toddouska 0:5045d2638c29 2821
toddouska 0:5045d2638c29 2822 case ZLIB_INIT_ERROR:
toddouska 0:5045d2638c29 2823 XSTRNCPY(buffer, "zlib init error", max);
toddouska 0:5045d2638c29 2824 break;
toddouska 0:5045d2638c29 2825
toddouska 0:5045d2638c29 2826 case ZLIB_COMPRESS_ERROR:
toddouska 0:5045d2638c29 2827 XSTRNCPY(buffer, "zlib compress error", max);
toddouska 0:5045d2638c29 2828 break;
toddouska 0:5045d2638c29 2829
toddouska 0:5045d2638c29 2830 case ZLIB_DECOMPRESS_ERROR:
toddouska 0:5045d2638c29 2831 XSTRNCPY(buffer, "zlib decompress error", max);
toddouska 0:5045d2638c29 2832 break;
toddouska 0:5045d2638c29 2833
toddouska 0:5045d2638c29 2834 case GETTIME_ERROR:
toddouska 0:5045d2638c29 2835 XSTRNCPY(buffer, "gettimeofday() error", max);
toddouska 0:5045d2638c29 2836 break;
toddouska 0:5045d2638c29 2837
toddouska 0:5045d2638c29 2838 case GETITIMER_ERROR:
toddouska 0:5045d2638c29 2839 XSTRNCPY(buffer, "getitimer() error", max);
toddouska 0:5045d2638c29 2840 break;
toddouska 0:5045d2638c29 2841
toddouska 0:5045d2638c29 2842 case SIGACT_ERROR:
toddouska 0:5045d2638c29 2843 XSTRNCPY(buffer, "sigaction() error", max);
toddouska 0:5045d2638c29 2844 break;
toddouska 0:5045d2638c29 2845
toddouska 0:5045d2638c29 2846 case SETITIMER_ERROR:
toddouska 0:5045d2638c29 2847 XSTRNCPY(buffer, "setitimer() error", max);
toddouska 0:5045d2638c29 2848 break;
toddouska 0:5045d2638c29 2849
toddouska 0:5045d2638c29 2850 case LENGTH_ERROR:
toddouska 0:5045d2638c29 2851 XSTRNCPY(buffer, "record layer length error", max);
toddouska 0:5045d2638c29 2852 break;
toddouska 0:5045d2638c29 2853
toddouska 0:5045d2638c29 2854 case PEER_KEY_ERROR:
toddouska 0:5045d2638c29 2855 XSTRNCPY(buffer, "cant decode peer key", max);
toddouska 0:5045d2638c29 2856 break;
toddouska 0:5045d2638c29 2857
toddouska 0:5045d2638c29 2858 case ZERO_RETURN:
toddouska 0:5045d2638c29 2859 XSTRNCPY(buffer, "peer sent close notify alert", max);
toddouska 0:5045d2638c29 2860 break;
toddouska 0:5045d2638c29 2861
toddouska 0:5045d2638c29 2862 default :
toddouska 0:5045d2638c29 2863 XSTRNCPY(buffer, "unknown error number", max);
toddouska 0:5045d2638c29 2864 }
toddouska 0:5045d2638c29 2865
toddouska 0:5045d2638c29 2866 #endif /* NO_ERROR_STRINGS */
toddouska 0:5045d2638c29 2867 }
toddouska 0:5045d2638c29 2868
toddouska 0:5045d2638c29 2869
toddouska 0:5045d2638c29 2870
toddouska 0:5045d2638c29 2871 /* be sure to add to cipher_name_idx too !!!! */
toddouska 0:5045d2638c29 2872 const char* const cipher_names[] =
toddouska 0:5045d2638c29 2873 {
toddouska 0:5045d2638c29 2874 #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
toddouska 0:5045d2638c29 2875 "RC4-SHA",
toddouska 0:5045d2638c29 2876 #endif
toddouska 0:5045d2638c29 2877
toddouska 0:5045d2638c29 2878 #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
toddouska 0:5045d2638c29 2879 "RC4-MD5",
toddouska 0:5045d2638c29 2880 #endif
toddouska 0:5045d2638c29 2881
toddouska 0:5045d2638c29 2882 #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
toddouska 0:5045d2638c29 2883 "DES-CBC3-SHA",
toddouska 0:5045d2638c29 2884 #endif
toddouska 0:5045d2638c29 2885
toddouska 0:5045d2638c29 2886 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2887 "AES128-SHA",
toddouska 0:5045d2638c29 2888 #endif
toddouska 0:5045d2638c29 2889
toddouska 0:5045d2638c29 2890 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2891 "AES256-SHA",
toddouska 0:5045d2638c29 2892 #endif
toddouska 0:5045d2638c29 2893
toddouska 0:5045d2638c29 2894 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2895 "DHE-RSA-AES128-SHA",
toddouska 0:5045d2638c29 2896 #endif
toddouska 0:5045d2638c29 2897
toddouska 0:5045d2638c29 2898 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2899 "DHE-RSA-AES256-SHA",
toddouska 0:5045d2638c29 2900 #endif
toddouska 0:5045d2638c29 2901
toddouska 0:5045d2638c29 2902 #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2903 "PSK-AES128-CBC-SHA",
toddouska 0:5045d2638c29 2904 #endif
toddouska 0:5045d2638c29 2905
toddouska 0:5045d2638c29 2906 #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2907 "PSK-AES256-CBC-SHA",
toddouska 0:5045d2638c29 2908 #endif
toddouska 0:5045d2638c29 2909
toddouska 0:5045d2638c29 2910 #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
toddouska 0:5045d2638c29 2911 "HC128-MD5",
toddouska 0:5045d2638c29 2912 #endif
toddouska 0:5045d2638c29 2913
toddouska 0:5045d2638c29 2914 #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
toddouska 0:5045d2638c29 2915 "HC128-SHA",
toddouska 0:5045d2638c29 2916 #endif
toddouska 0:5045d2638c29 2917
toddouska 0:5045d2638c29 2918 #ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
toddouska 0:5045d2638c29 2919 "RABBIT-SHA",
toddouska 0:5045d2638c29 2920 #endif
toddouska 0:5045d2638c29 2921
toddouska 0:5045d2638c29 2922 #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
toddouska 0:5045d2638c29 2923 "NTRU-RC4-SHA",
toddouska 0:5045d2638c29 2924 #endif
toddouska 0:5045d2638c29 2925
toddouska 0:5045d2638c29 2926 #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
toddouska 0:5045d2638c29 2927 "NTRU-DES-CBC3-SHA",
toddouska 0:5045d2638c29 2928 #endif
toddouska 0:5045d2638c29 2929
toddouska 0:5045d2638c29 2930 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2931 "NTRU-AES128-SHA",
toddouska 0:5045d2638c29 2932 #endif
toddouska 0:5045d2638c29 2933
toddouska 0:5045d2638c29 2934 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2935 "NTRU-AES256-SHA",
toddouska 0:5045d2638c29 2936 #endif
toddouska 0:5045d2638c29 2937 };
toddouska 0:5045d2638c29 2938
toddouska 0:5045d2638c29 2939
toddouska 0:5045d2638c29 2940
toddouska 0:5045d2638c29 2941 /* cipher suite number that matches above name table */
toddouska 0:5045d2638c29 2942 int cipher_name_idx[] =
toddouska 0:5045d2638c29 2943 {
toddouska 0:5045d2638c29 2944
toddouska 0:5045d2638c29 2945 #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
toddouska 0:5045d2638c29 2946 SSL_RSA_WITH_RC4_128_SHA,
toddouska 0:5045d2638c29 2947 #endif
toddouska 0:5045d2638c29 2948
toddouska 0:5045d2638c29 2949 #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
toddouska 0:5045d2638c29 2950 SSL_RSA_WITH_RC4_128_MD5,
toddouska 0:5045d2638c29 2951 #endif
toddouska 0:5045d2638c29 2952
toddouska 0:5045d2638c29 2953 #ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
toddouska 0:5045d2638c29 2954 SSL_RSA_WITH_3DES_EDE_CBC_SHA,
toddouska 0:5045d2638c29 2955 #endif
toddouska 0:5045d2638c29 2956
toddouska 0:5045d2638c29 2957 #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2958 TLS_RSA_WITH_AES_128_CBC_SHA,
toddouska 0:5045d2638c29 2959 #endif
toddouska 0:5045d2638c29 2960
toddouska 0:5045d2638c29 2961 #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2962 TLS_RSA_WITH_AES_256_CBC_SHA,
toddouska 0:5045d2638c29 2963 #endif
toddouska 0:5045d2638c29 2964
toddouska 0:5045d2638c29 2965 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2966 TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
toddouska 0:5045d2638c29 2967 #endif
toddouska 0:5045d2638c29 2968
toddouska 0:5045d2638c29 2969 #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2970 TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
toddouska 0:5045d2638c29 2971 #endif
toddouska 0:5045d2638c29 2972
toddouska 0:5045d2638c29 2973 #ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 2974 TLS_PSK_WITH_AES_128_CBC_SHA,
toddouska 0:5045d2638c29 2975 #endif
toddouska 0:5045d2638c29 2976
toddouska 0:5045d2638c29 2977 #ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 2978 TLS_PSK_WITH_AES_256_CBC_SHA,
toddouska 0:5045d2638c29 2979 #endif
toddouska 0:5045d2638c29 2980
toddouska 0:5045d2638c29 2981 #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
toddouska 0:5045d2638c29 2982 TLS_RSA_WITH_HC_128_CBC_MD5,
toddouska 0:5045d2638c29 2983 #endif
toddouska 0:5045d2638c29 2984
toddouska 0:5045d2638c29 2985 #ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
toddouska 0:5045d2638c29 2986 TLS_RSA_WITH_HC_128_CBC_SHA,
toddouska 0:5045d2638c29 2987 #endif
toddouska 0:5045d2638c29 2988
toddouska 0:5045d2638c29 2989 #ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
toddouska 0:5045d2638c29 2990 TLS_RSA_WITH_RABBIT_CBC_SHA,
toddouska 0:5045d2638c29 2991 #endif
toddouska 0:5045d2638c29 2992
toddouska 0:5045d2638c29 2993 #ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
toddouska 0:5045d2638c29 2994 TLS_NTRU_RSA_WITH_RC4_128_SHA,
toddouska 0:5045d2638c29 2995 #endif
toddouska 0:5045d2638c29 2996
toddouska 0:5045d2638c29 2997 #ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
toddouska 0:5045d2638c29 2998 TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
toddouska 0:5045d2638c29 2999 #endif
toddouska 0:5045d2638c29 3000
toddouska 0:5045d2638c29 3001 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
toddouska 0:5045d2638c29 3002 TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
toddouska 0:5045d2638c29 3003 #endif
toddouska 0:5045d2638c29 3004
toddouska 0:5045d2638c29 3005 #ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
toddouska 0:5045d2638c29 3006 TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
toddouska 0:5045d2638c29 3007 #endif
toddouska 0:5045d2638c29 3008 };
toddouska 0:5045d2638c29 3009
toddouska 0:5045d2638c29 3010
toddouska 0:5045d2638c29 3011 /* return true if set, else false */
toddouska 0:5045d2638c29 3012 /* only supports full name from cipher_name[] delimited by : */
toddouska 0:5045d2638c29 3013 int SetCipherList(SSL_CTX* ctx, const char* list)
toddouska 0:5045d2638c29 3014 {
toddouska 0:5045d2638c29 3015 int ret = 0, i;
toddouska 0:5045d2638c29 3016 char name[MAX_SUITE_NAME];
toddouska 0:5045d2638c29 3017
toddouska 0:5045d2638c29 3018 char needle[] = ":";
toddouska 0:5045d2638c29 3019 char* haystack = (char*)list;
toddouska 0:5045d2638c29 3020 char* prev;
toddouska 0:5045d2638c29 3021
toddouska 0:5045d2638c29 3022 const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
toddouska 0:5045d2638c29 3023 int idx = 0;
toddouska 0:5045d2638c29 3024
toddouska 0:5045d2638c29 3025 if (!list)
toddouska 0:5045d2638c29 3026 return 0;
toddouska 0:5045d2638c29 3027
toddouska 0:5045d2638c29 3028 if (*list == 0) return 1; /* CyaSSL default */
toddouska 0:5045d2638c29 3029
toddouska 0:5045d2638c29 3030 if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL defualt */
toddouska 0:5045d2638c29 3031
toddouska 0:5045d2638c29 3032 for(;;) {
toddouska 0:5045d2638c29 3033 size_t len;
toddouska 0:5045d2638c29 3034 prev = haystack;
toddouska 0:5045d2638c29 3035 haystack = XSTRSTR(haystack, needle);
toddouska 0:5045d2638c29 3036
toddouska 0:5045d2638c29 3037 if (!haystack) /* last cipher */
toddouska 0:5045d2638c29 3038 len = min(sizeof(name), XSTRLEN(prev));
toddouska 0:5045d2638c29 3039 else
toddouska 0:5045d2638c29 3040 len = min(sizeof(name), (size_t)(haystack - prev));
toddouska 0:5045d2638c29 3041
toddouska 0:5045d2638c29 3042 XSTRNCPY(name, prev, len);
toddouska 0:5045d2638c29 3043 name[(len == sizeof(name)) ? len - 1 : len] = 0;
toddouska 0:5045d2638c29 3044
toddouska 0:5045d2638c29 3045 for (i = 0; i < suiteSz; i++)
toddouska 0:5045d2638c29 3046 if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
toddouska 0:5045d2638c29 3047
toddouska 0:5045d2638c29 3048 ctx->suites.suites[idx++] = 0x00; /* first byte always zero */
toddouska 0:5045d2638c29 3049 ctx->suites.suites[idx++] = cipher_name_idx[i];
toddouska 0:5045d2638c29 3050
toddouska 0:5045d2638c29 3051 if (!ret) ret = 1; /* found at least one */
toddouska 0:5045d2638c29 3052 break;
toddouska 0:5045d2638c29 3053 }
toddouska 0:5045d2638c29 3054 if (!haystack) break;
toddouska 0:5045d2638c29 3055 haystack++;
toddouska 0:5045d2638c29 3056 }
toddouska 0:5045d2638c29 3057
toddouska 0:5045d2638c29 3058 if (ret) {
toddouska 0:5045d2638c29 3059 ctx->suites.setSuites = 1;
toddouska 0:5045d2638c29 3060 ctx->suites.suiteSz = idx;
toddouska 0:5045d2638c29 3061 }
toddouska 0:5045d2638c29 3062
toddouska 0:5045d2638c29 3063 return ret;
toddouska 0:5045d2638c29 3064 }
toddouska 0:5045d2638c29 3065
toddouska 0:5045d2638c29 3066
toddouska 0:5045d2638c29 3067 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3068
toddouska 0:5045d2638c29 3069 /* Initialisze HandShakeInfo */
toddouska 0:5045d2638c29 3070 void InitHandShakeInfo(HandShakeInfo* info)
toddouska 0:5045d2638c29 3071 {
toddouska 0:5045d2638c29 3072 int i;
toddouska 0:5045d2638c29 3073
toddouska 0:5045d2638c29 3074 info->cipherName[0] = 0;
toddouska 0:5045d2638c29 3075 for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
toddouska 0:5045d2638c29 3076 info->packetNames[i][0] = 0;
toddouska 0:5045d2638c29 3077 info->numberPackets = 0;
toddouska 0:5045d2638c29 3078 info->negotiationError = 0;
toddouska 0:5045d2638c29 3079 }
toddouska 0:5045d2638c29 3080
toddouska 0:5045d2638c29 3081 /* Set Final HandShakeInfo parameters */
toddouska 0:5045d2638c29 3082 void FinishHandShakeInfo(HandShakeInfo* info, const SSL* ssl)
toddouska 0:5045d2638c29 3083 {
toddouska 0:5045d2638c29 3084 int i;
toddouska 0:5045d2638c29 3085 int sz = sizeof(cipher_name_idx)/sizeof(int);
toddouska 0:5045d2638c29 3086
toddouska 0:5045d2638c29 3087 for (i = 0; i < sz; i++)
toddouska 0:5045d2638c29 3088 if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
toddouska 0:5045d2638c29 3089 XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ);
toddouska 0:5045d2638c29 3090 break;
toddouska 0:5045d2638c29 3091 }
toddouska 0:5045d2638c29 3092
toddouska 0:5045d2638c29 3093 /* error max and min are negative numbers */
toddouska 0:5045d2638c29 3094 if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR)
toddouska 0:5045d2638c29 3095 info->negotiationError = ssl->error;
toddouska 0:5045d2638c29 3096 }
toddouska 0:5045d2638c29 3097
toddouska 0:5045d2638c29 3098
toddouska 0:5045d2638c29 3099 /* Add name to info packet names, increase packet name count */
toddouska 0:5045d2638c29 3100 void AddPacketName(const char* name, HandShakeInfo* info)
toddouska 0:5045d2638c29 3101 {
toddouska 0:5045d2638c29 3102 if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
toddouska 0:5045d2638c29 3103 XSTRNCPY(info->packetNames[info->numberPackets++], name,
toddouska 0:5045d2638c29 3104 MAX_PACKETNAME_SZ);
toddouska 0:5045d2638c29 3105 }
toddouska 0:5045d2638c29 3106 }
toddouska 0:5045d2638c29 3107
toddouska 0:5045d2638c29 3108
toddouska 0:5045d2638c29 3109 /* Initialisze TimeoutInfo */
toddouska 0:5045d2638c29 3110 void InitTimeoutInfo(TimeoutInfo* info)
toddouska 0:5045d2638c29 3111 {
toddouska 0:5045d2638c29 3112 int i;
toddouska 0:5045d2638c29 3113
toddouska 0:5045d2638c29 3114 info->timeoutName[0] = 0;
toddouska 0:5045d2638c29 3115 info->flags = 0;
toddouska 0:5045d2638c29 3116
toddouska 0:5045d2638c29 3117 for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
toddouska 0:5045d2638c29 3118 info->packets[i].packetName[0] = 0;
toddouska 0:5045d2638c29 3119 info->packets[i].timestamp.tv_sec = 0;
toddouska 0:5045d2638c29 3120 info->packets[i].timestamp.tv_usec = 0;
toddouska 0:5045d2638c29 3121 info->packets[i].bufferValue = 0;
toddouska 0:5045d2638c29 3122 info->packets[i].valueSz = 0;
toddouska 0:5045d2638c29 3123 }
toddouska 0:5045d2638c29 3124 info->numberPackets = 0;
toddouska 0:5045d2638c29 3125 info->timeoutValue.tv_sec = 0;
toddouska 0:5045d2638c29 3126 info->timeoutValue.tv_usec = 0;
toddouska 0:5045d2638c29 3127 }
toddouska 0:5045d2638c29 3128
toddouska 0:5045d2638c29 3129
toddouska 0:5045d2638c29 3130 /* Free TimeoutInfo */
toddouska 0:5045d2638c29 3131 void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
toddouska 0:5045d2638c29 3132 {
toddouska 0:5045d2638c29 3133 int i;
toddouska 0:5045d2638c29 3134 for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
toddouska 0:5045d2638c29 3135 if (info->packets[i].bufferValue) {
toddouska 0:5045d2638c29 3136 XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
toddouska 0:5045d2638c29 3137 info->packets[i].bufferValue = 0;
toddouska 0:5045d2638c29 3138 }
toddouska 0:5045d2638c29 3139
toddouska 0:5045d2638c29 3140 }
toddouska 0:5045d2638c29 3141
toddouska 0:5045d2638c29 3142
toddouska 0:5045d2638c29 3143 /* Add PacketInfo to TimeoutInfo */
toddouska 0:5045d2638c29 3144 void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
toddouska 0:5045d2638c29 3145 int sz, void* heap)
toddouska 0:5045d2638c29 3146 {
toddouska 0:5045d2638c29 3147 if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
toddouska 0:5045d2638c29 3148 Timeval currTime;
toddouska 0:5045d2638c29 3149
toddouska 0:5045d2638c29 3150 /* may add name after */
toddouska 0:5045d2638c29 3151 if (name)
toddouska 0:5045d2638c29 3152 XSTRNCPY(info->packets[info->numberPackets].packetName, name,
toddouska 0:5045d2638c29 3153 MAX_PACKETNAME_SZ);
toddouska 0:5045d2638c29 3154
toddouska 0:5045d2638c29 3155 /* add data, put in buffer if bigger than static buffer */
toddouska 0:5045d2638c29 3156 info->packets[info->numberPackets].valueSz = sz;
toddouska 0:5045d2638c29 3157 if (sz < MAX_VALUE_SZ)
toddouska 0:5045d2638c29 3158 XMEMCPY(info->packets[info->numberPackets].value, data, sz);
toddouska 0:5045d2638c29 3159 else {
toddouska 0:5045d2638c29 3160 info->packets[info->numberPackets].bufferValue =
toddouska 0:5045d2638c29 3161 XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
toddouska 0:5045d2638c29 3162 if (!info->packets[info->numberPackets].bufferValue)
toddouska 0:5045d2638c29 3163 /* let next alloc catch, just don't fill, not fatal here */
toddouska 0:5045d2638c29 3164 info->packets[info->numberPackets].valueSz = 0;
toddouska 0:5045d2638c29 3165 else
toddouska 0:5045d2638c29 3166 XMEMCPY(info->packets[info->numberPackets].bufferValue,
toddouska 0:5045d2638c29 3167 data, sz);
toddouska 0:5045d2638c29 3168 }
toddouska 0:5045d2638c29 3169 gettimeofday(&currTime, 0);
toddouska 0:5045d2638c29 3170 info->packets[info->numberPackets].timestamp.tv_sec =
toddouska 0:5045d2638c29 3171 currTime.tv_sec;
toddouska 0:5045d2638c29 3172 info->packets[info->numberPackets].timestamp.tv_usec =
toddouska 0:5045d2638c29 3173 currTime.tv_usec;
toddouska 0:5045d2638c29 3174 info->numberPackets++;
toddouska 0:5045d2638c29 3175 }
toddouska 0:5045d2638c29 3176 }
toddouska 0:5045d2638c29 3177
toddouska 0:5045d2638c29 3178
toddouska 0:5045d2638c29 3179 /* Add packet name to previsouly added packet info */
toddouska 0:5045d2638c29 3180 void AddLateName(const char* name, TimeoutInfo* info)
toddouska 0:5045d2638c29 3181 {
toddouska 0:5045d2638c29 3182 /* make sure we have a valid previous one */
toddouska 0:5045d2638c29 3183 if (info->numberPackets > 0 && info->numberPackets <
toddouska 0:5045d2638c29 3184 MAX_PACKETS_HANDSHAKE) {
toddouska 0:5045d2638c29 3185 XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name,
toddouska 0:5045d2638c29 3186 MAX_PACKETNAME_SZ);
toddouska 0:5045d2638c29 3187 }
toddouska 0:5045d2638c29 3188 }
toddouska 0:5045d2638c29 3189
toddouska 0:5045d2638c29 3190 /* Add record header to previsouly added packet info */
toddouska 0:5045d2638c29 3191 void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
toddouska 0:5045d2638c29 3192 {
toddouska 0:5045d2638c29 3193 /* make sure we have a valid previous one */
toddouska 0:5045d2638c29 3194 if (info->numberPackets > 0 && info->numberPackets <
toddouska 0:5045d2638c29 3195 MAX_PACKETS_HANDSHAKE) {
toddouska 0:5045d2638c29 3196 if (info->packets[info->numberPackets - 1].bufferValue)
toddouska 0:5045d2638c29 3197 XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
toddouska 0:5045d2638c29 3198 RECORD_HEADER_SZ);
toddouska 0:5045d2638c29 3199 else
toddouska 0:5045d2638c29 3200 XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
toddouska 0:5045d2638c29 3201 RECORD_HEADER_SZ);
toddouska 0:5045d2638c29 3202 }
toddouska 0:5045d2638c29 3203 }
toddouska 0:5045d2638c29 3204
toddouska 0:5045d2638c29 3205 #endif /* CYASSL_CALLBACKS */
toddouska 0:5045d2638c29 3206
toddouska 0:5045d2638c29 3207
toddouska 0:5045d2638c29 3208
toddouska 0:5045d2638c29 3209 /* client only parts */
toddouska 0:5045d2638c29 3210 #ifndef NO_CYASSL_CLIENT
toddouska 0:5045d2638c29 3211
toddouska 0:5045d2638c29 3212 int SendClientHello(SSL* ssl)
toddouska 0:5045d2638c29 3213 {
toddouska 0:5045d2638c29 3214 byte *output;
toddouska 0:5045d2638c29 3215 word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 3216 int sendSz;
toddouska 0:5045d2638c29 3217 int idSz = ssl->options.resuming ? ID_LEN : 0;
toddouska 0:5045d2638c29 3218 int ret;
toddouska 0:5045d2638c29 3219
toddouska 0:5045d2638c29 3220 length = sizeof(ProtocolVersion) + RAN_LEN
toddouska 0:5045d2638c29 3221 + idSz + ENUM_LEN
toddouska 0:5045d2638c29 3222 + ssl->suites.suiteSz + SUITE_LEN
toddouska 0:5045d2638c29 3223 + COMP_LEN + ENUM_LEN;
toddouska 0:5045d2638c29 3224
toddouska 0:5045d2638c29 3225 sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 3226
toddouska 0:5045d2638c29 3227 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3228 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 3229 length += ENUM_LEN; /* cookie */
toddouska 0:5045d2638c29 3230 sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 3231 idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 3232 }
toddouska 0:5045d2638c29 3233 #endif
toddouska 0:5045d2638c29 3234
toddouska 0:5045d2638c29 3235 /* check for avalaible size */
toddouska 0:5045d2638c29 3236 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 3237 return ret;
toddouska 0:5045d2638c29 3238
toddouska 0:5045d2638c29 3239 /* get ouput buffer */
toddouska 0:5045d2638c29 3240 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 3241 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 3242
toddouska 0:5045d2638c29 3243 AddHeaders(output, length, client_hello, ssl);
toddouska 0:5045d2638c29 3244
toddouska 0:5045d2638c29 3245 /* client hello, first version */
toddouska 0:5045d2638c29 3246 XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
toddouska 0:5045d2638c29 3247 idx += sizeof(ProtocolVersion);
toddouska 0:5045d2638c29 3248 ssl->chVersion = ssl->version; /* store in case changed */
toddouska 0:5045d2638c29 3249
toddouska 0:5045d2638c29 3250 /* then random */
toddouska 0:5045d2638c29 3251 if (ssl->options.connectState == CONNECT_BEGIN) {
toddouska 0:5045d2638c29 3252 RNG_GenerateBlock(&ssl->rng, output + idx, RAN_LEN);
toddouska 0:5045d2638c29 3253
toddouska 0:5045d2638c29 3254 /* store random */
toddouska 0:5045d2638c29 3255 XMEMCPY(ssl->arrays.clientRandom, output + idx, RAN_LEN);
toddouska 0:5045d2638c29 3256 } else {
toddouska 0:5045d2638c29 3257 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3258 /* send same random on hello again */
toddouska 0:5045d2638c29 3259 XMEMCPY(output + idx, ssl->arrays.clientRandom, RAN_LEN);
toddouska 0:5045d2638c29 3260 #endif
toddouska 0:5045d2638c29 3261 }
toddouska 0:5045d2638c29 3262 idx += RAN_LEN;
toddouska 0:5045d2638c29 3263
toddouska 0:5045d2638c29 3264 /* then session id */
toddouska 0:5045d2638c29 3265 output[idx++] = idSz;
toddouska 0:5045d2638c29 3266 if (idSz) {
toddouska 0:5045d2638c29 3267 XMEMCPY(output + idx, ssl->session.sessionID, ID_LEN);
toddouska 0:5045d2638c29 3268 idx += ID_LEN;
toddouska 0:5045d2638c29 3269 }
toddouska 0:5045d2638c29 3270
toddouska 0:5045d2638c29 3271 /* then DTLS cookie */
toddouska 0:5045d2638c29 3272 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3273 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 3274 output[idx++] = 0;
toddouska 0:5045d2638c29 3275 }
toddouska 0:5045d2638c29 3276 #endif
toddouska 0:5045d2638c29 3277 /* then cipher suites */
toddouska 0:5045d2638c29 3278 c16toa(ssl->suites.suiteSz, output + idx);
toddouska 0:5045d2638c29 3279 idx += 2;
toddouska 0:5045d2638c29 3280 XMEMCPY(output + idx, &ssl->suites.suites, ssl->suites.suiteSz);
toddouska 0:5045d2638c29 3281 idx += ssl->suites.suiteSz;
toddouska 0:5045d2638c29 3282
toddouska 0:5045d2638c29 3283 /* last, compression */
toddouska 0:5045d2638c29 3284 output[idx++] = COMP_LEN;
toddouska 0:5045d2638c29 3285 if (ssl->options.usingCompression)
toddouska 0:5045d2638c29 3286 output[idx++] = ZLIB_COMPRESSION;
toddouska 0:5045d2638c29 3287 else
toddouska 0:5045d2638c29 3288 output[idx++] = NO_COMPRESSION;
toddouska 0:5045d2638c29 3289
toddouska 0:5045d2638c29 3290 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 3291
toddouska 0:5045d2638c29 3292 ssl->options.clientState = CLIENT_HELLO_COMPLETE;
toddouska 0:5045d2638c29 3293
toddouska 0:5045d2638c29 3294 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3295 if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3296 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3297 AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz,
toddouska 0:5045d2638c29 3298 ssl->heap);
toddouska 0:5045d2638c29 3299 #endif
toddouska 0:5045d2638c29 3300
toddouska 0:5045d2638c29 3301 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 3302
toddouska 0:5045d2638c29 3303 return SendBuffered(ssl);
toddouska 0:5045d2638c29 3304 }
toddouska 0:5045d2638c29 3305
toddouska 0:5045d2638c29 3306
toddouska 0:5045d2638c29 3307 static int DoHelloVerifyRequest(SSL* ssl, const byte* input,
toddouska 0:5045d2638c29 3308 word32* inOutIdx)
toddouska 0:5045d2638c29 3309 {
toddouska 0:5045d2638c29 3310 ProtocolVersion pv;
toddouska 0:5045d2638c29 3311 byte cookieSz;
toddouska 0:5045d2638c29 3312
toddouska 0:5045d2638c29 3313 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3314 if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
toddouska 0:5045d2638c29 3315 &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3316 if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 3317 #endif
toddouska 0:5045d2638c29 3318 XMEMCPY(&pv, input + *inOutIdx, sizeof(pv));
toddouska 0:5045d2638c29 3319 *inOutIdx += sizeof(pv);
toddouska 0:5045d2638c29 3320
toddouska 0:5045d2638c29 3321 cookieSz = input[(*inOutIdx)++];
toddouska 0:5045d2638c29 3322
toddouska 0:5045d2638c29 3323 if (cookieSz)
toddouska 0:5045d2638c29 3324 *inOutIdx += cookieSz; /* skip for now */
toddouska 0:5045d2638c29 3325
toddouska 0:5045d2638c29 3326 ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
toddouska 0:5045d2638c29 3327 return 0;
toddouska 0:5045d2638c29 3328 }
toddouska 0:5045d2638c29 3329
toddouska 0:5045d2638c29 3330
toddouska 0:5045d2638c29 3331 static int DoServerHello(SSL* ssl, const byte* input, word32* inOutIdx)
toddouska 0:5045d2638c29 3332 {
toddouska 0:5045d2638c29 3333 byte b;
toddouska 0:5045d2638c29 3334 byte compression;
toddouska 0:5045d2638c29 3335 ProtocolVersion pv;
toddouska 0:5045d2638c29 3336 word32 i = *inOutIdx;
toddouska 0:5045d2638c29 3337
toddouska 0:5045d2638c29 3338 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3339 if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3340 if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 3341 #endif
toddouska 0:5045d2638c29 3342 XMEMCPY(&pv, input + i, sizeof(pv));
toddouska 0:5045d2638c29 3343 i += sizeof(pv);
toddouska 0:5045d2638c29 3344 XMEMCPY(ssl->arrays.serverRandom, input + i, RAN_LEN);
toddouska 0:5045d2638c29 3345 i += RAN_LEN;
toddouska 0:5045d2638c29 3346 b = input[i++];
toddouska 0:5045d2638c29 3347 if (b) {
toddouska 0:5045d2638c29 3348 XMEMCPY(ssl->arrays.sessionID, input + i, b);
toddouska 0:5045d2638c29 3349 i += b;
toddouska 0:5045d2638c29 3350 }
toddouska 0:5045d2638c29 3351 ssl->options.cipherSuite = input[++i];
toddouska 0:5045d2638c29 3352 compression = input[++i];
toddouska 0:5045d2638c29 3353 ++i; /* 2nd byte */
toddouska 0:5045d2638c29 3354
toddouska 0:5045d2638c29 3355 if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression)
toddouska 0:5045d2638c29 3356 ssl->options.usingCompression = 0; /* turn off if server refused */
toddouska 0:5045d2638c29 3357
toddouska 0:5045d2638c29 3358 ssl->options.serverState = SERVER_HELLO_COMPLETE;
toddouska 0:5045d2638c29 3359
toddouska 0:5045d2638c29 3360 *inOutIdx = i;
toddouska 0:5045d2638c29 3361
toddouska 0:5045d2638c29 3362 if (ssl->options.resuming) {
toddouska 0:5045d2638c29 3363 if (XMEMCMP(ssl->arrays.sessionID, ssl->session.sessionID, ID_LEN)
toddouska 0:5045d2638c29 3364 == 0) {
toddouska 0:5045d2638c29 3365 if (SetCipherSpecs(ssl) == 0) {
toddouska 0:5045d2638c29 3366 XMEMCPY(ssl->arrays.masterSecret, ssl->session.masterSecret,
toddouska 0:5045d2638c29 3367 SECRET_LEN);
toddouska 0:5045d2638c29 3368 if (ssl->options.tls)
toddouska 0:5045d2638c29 3369 DeriveTlsKeys(ssl);
toddouska 0:5045d2638c29 3370 else
toddouska 0:5045d2638c29 3371 DeriveKeys(ssl);
toddouska 0:5045d2638c29 3372 ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
toddouska 0:5045d2638c29 3373 return 0;
toddouska 0:5045d2638c29 3374 }
toddouska 0:5045d2638c29 3375 else
toddouska 0:5045d2638c29 3376 return UNSUPPORTED_SUITE;
toddouska 0:5045d2638c29 3377 }
toddouska 0:5045d2638c29 3378 else
toddouska 0:5045d2638c29 3379 ssl->options.resuming = 0; /* server denied resumption try */
toddouska 0:5045d2638c29 3380 }
toddouska 0:5045d2638c29 3381
toddouska 0:5045d2638c29 3382 return SetCipherSpecs(ssl);
toddouska 0:5045d2638c29 3383 }
toddouska 0:5045d2638c29 3384
toddouska 0:5045d2638c29 3385
toddouska 0:5045d2638c29 3386 /* just read in and ignore for now TODO: */
toddouska 0:5045d2638c29 3387 static int DoCertificateRequest(SSL* ssl, const byte* input, word32*
toddouska 0:5045d2638c29 3388 inOutIdx)
toddouska 0:5045d2638c29 3389 {
toddouska 0:5045d2638c29 3390 word16 len;
toddouska 0:5045d2638c29 3391
toddouska 0:5045d2638c29 3392 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3393 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 3394 AddPacketName("CertificateRequest", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3395 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3396 AddLateName("CertificateRequest", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 3397 #endif
toddouska 0:5045d2638c29 3398 len = input[(*inOutIdx)++];
toddouska 0:5045d2638c29 3399
toddouska 0:5045d2638c29 3400 /* types, read in here */
toddouska 0:5045d2638c29 3401 *inOutIdx += len;
toddouska 0:5045d2638c29 3402 ato16(&input[*inOutIdx], &len);
toddouska 0:5045d2638c29 3403 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 3404
toddouska 0:5045d2638c29 3405 /* authorities */
toddouska 0:5045d2638c29 3406 while (len) {
toddouska 0:5045d2638c29 3407 word16 dnSz;
toddouska 0:5045d2638c29 3408
toddouska 0:5045d2638c29 3409 ato16(&input[*inOutIdx], &dnSz);
toddouska 0:5045d2638c29 3410 *inOutIdx += (REQUEST_HEADER + dnSz);
toddouska 0:5045d2638c29 3411 len -= dnSz + REQUEST_HEADER;
toddouska 0:5045d2638c29 3412 }
toddouska 0:5045d2638c29 3413
toddouska 0:5045d2638c29 3414 /* don't send client cert or cert verify if user hasn't provided
toddouska 0:5045d2638c29 3415 cert and private key */
toddouska 0:5045d2638c29 3416 if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer)
toddouska 0:5045d2638c29 3417 ssl->options.sendVerify = SEND_CERT;
toddouska 0:5045d2638c29 3418 else if (IsAtLeastTLSv1_2(ssl))
toddouska 0:5045d2638c29 3419 ssl->options.sendVerify = SEND_BLANK_CERT;
toddouska 0:5045d2638c29 3420
toddouska 0:5045d2638c29 3421 return 0;
toddouska 0:5045d2638c29 3422 }
toddouska 0:5045d2638c29 3423
toddouska 0:5045d2638c29 3424
toddouska 0:5045d2638c29 3425 static int DoServerKeyExchange(SSL* ssl, const byte* input, word32*
toddouska 0:5045d2638c29 3426 inOutIdx)
toddouska 0:5045d2638c29 3427 {
toddouska 0:5045d2638c29 3428 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3429 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 3430 AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3431 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3432 AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 3433 #endif
toddouska 0:5045d2638c29 3434
toddouska 0:5045d2638c29 3435 #ifndef NO_PSK
toddouska 0:5045d2638c29 3436 if (ssl->specs.kea == psk_kea) {
toddouska 0:5045d2638c29 3437 word16 length;
toddouska 0:5045d2638c29 3438
toddouska 0:5045d2638c29 3439 ato16(&input[*inOutIdx], &length);
toddouska 0:5045d2638c29 3440 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 3441 XMEMCPY(ssl->arrays.server_hint, &input[*inOutIdx],
toddouska 0:5045d2638c29 3442 min(length, MAX_PSK_ID_LEN));
toddouska 0:5045d2638c29 3443 if (length < MAX_PSK_ID_LEN)
toddouska 0:5045d2638c29 3444 ssl->arrays.server_hint[length] = 0;
toddouska 0:5045d2638c29 3445 else
toddouska 0:5045d2638c29 3446 ssl->arrays.server_hint[MAX_PSK_ID_LEN - 1] = 0;
toddouska 0:5045d2638c29 3447 *inOutIdx += length;
toddouska 0:5045d2638c29 3448
toddouska 0:5045d2638c29 3449 return 0;
toddouska 0:5045d2638c29 3450 }
toddouska 0:5045d2638c29 3451 #endif
toddouska 0:5045d2638c29 3452 #ifdef OPENSSL_EXTRA
toddouska 0:5045d2638c29 3453 if (ssl->specs.kea == diffie_hellman_kea)
toddouska 0:5045d2638c29 3454 {
toddouska 0:5045d2638c29 3455 word16 length, verifySz, messageTotal = 6; /* pSz + gSz + pubSz */
toddouska 0:5045d2638c29 3456 byte messageVerify[MAX_DH_SZ];
toddouska 0:5045d2638c29 3457 byte* signature;
toddouska 0:5045d2638c29 3458 byte hash[FINISHED_SZ];
toddouska 0:5045d2638c29 3459 Md5 md5;
toddouska 0:5045d2638c29 3460 Sha sha;
toddouska 0:5045d2638c29 3461
toddouska 0:5045d2638c29 3462 /* p */
toddouska 0:5045d2638c29 3463 ato16(&input[*inOutIdx], &length);
toddouska 0:5045d2638c29 3464 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 3465 messageTotal += length;
toddouska 0:5045d2638c29 3466
toddouska 0:5045d2638c29 3467 ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
toddouska 0:5045d2638c29 3468 DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 3469 if (ssl->buffers.serverDH_P.buffer)
toddouska 0:5045d2638c29 3470 ssl->buffers.serverDH_P.length = length;
toddouska 0:5045d2638c29 3471 else
toddouska 0:5045d2638c29 3472 return MEMORY_ERROR;
toddouska 0:5045d2638c29 3473 XMEMCPY(ssl->buffers.serverDH_P.buffer, &input[*inOutIdx], length);
toddouska 0:5045d2638c29 3474 *inOutIdx += length;
toddouska 0:5045d2638c29 3475
toddouska 0:5045d2638c29 3476 /* g */
toddouska 0:5045d2638c29 3477 ato16(&input[*inOutIdx], &length);
toddouska 0:5045d2638c29 3478 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 3479 messageTotal += length;
toddouska 0:5045d2638c29 3480
toddouska 0:5045d2638c29 3481 ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
toddouska 0:5045d2638c29 3482 DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 3483 if (ssl->buffers.serverDH_G.buffer)
toddouska 0:5045d2638c29 3484 ssl->buffers.serverDH_G.length = length;
toddouska 0:5045d2638c29 3485 else
toddouska 0:5045d2638c29 3486 return MEMORY_ERROR;
toddouska 0:5045d2638c29 3487 XMEMCPY(ssl->buffers.serverDH_G.buffer, &input[*inOutIdx], length);
toddouska 0:5045d2638c29 3488 *inOutIdx += length;
toddouska 0:5045d2638c29 3489
toddouska 0:5045d2638c29 3490 /* pub */
toddouska 0:5045d2638c29 3491 ato16(&input[*inOutIdx], &length);
toddouska 0:5045d2638c29 3492 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 3493 messageTotal += length;
toddouska 0:5045d2638c29 3494
toddouska 0:5045d2638c29 3495 ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
toddouska 0:5045d2638c29 3496 DYNAMIC_TYPE_DH);
toddouska 0:5045d2638c29 3497 if (ssl->buffers.serverDH_Pub.buffer)
toddouska 0:5045d2638c29 3498 ssl->buffers.serverDH_Pub.length = length;
toddouska 0:5045d2638c29 3499 else
toddouska 0:5045d2638c29 3500 return MEMORY_ERROR;
toddouska 0:5045d2638c29 3501 XMEMCPY(ssl->buffers.serverDH_Pub.buffer, &input[*inOutIdx], length);
toddouska 0:5045d2638c29 3502 *inOutIdx += length;
toddouska 0:5045d2638c29 3503
toddouska 0:5045d2638c29 3504 /* save message for hash verify */
toddouska 0:5045d2638c29 3505 if (messageTotal > sizeof(messageVerify))
toddouska 0:5045d2638c29 3506 return BUFFER_ERROR;
toddouska 0:5045d2638c29 3507 XMEMCPY(messageVerify, &input[*inOutIdx - messageTotal], messageTotal);
toddouska 0:5045d2638c29 3508 verifySz = messageTotal;
toddouska 0:5045d2638c29 3509
toddouska 0:5045d2638c29 3510 /* signature */
toddouska 0:5045d2638c29 3511 ato16(&input[*inOutIdx], &length);
toddouska 0:5045d2638c29 3512 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 3513
toddouska 0:5045d2638c29 3514 signature = (byte*)&input[*inOutIdx];
toddouska 0:5045d2638c29 3515 *inOutIdx += length;
toddouska 0:5045d2638c29 3516
toddouska 0:5045d2638c29 3517 /* verify signature */
toddouska 0:5045d2638c29 3518
toddouska 0:5045d2638c29 3519 /* md5 */
toddouska 0:5045d2638c29 3520 InitMd5(&md5);
toddouska 0:5045d2638c29 3521 Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
toddouska 0:5045d2638c29 3522 Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
toddouska 0:5045d2638c29 3523 Md5Update(&md5, messageVerify, verifySz);
toddouska 0:5045d2638c29 3524 Md5Final(&md5, hash);
toddouska 0:5045d2638c29 3525
toddouska 0:5045d2638c29 3526 /* sha */
toddouska 0:5045d2638c29 3527 InitSha(&sha);
toddouska 0:5045d2638c29 3528 ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
toddouska 0:5045d2638c29 3529 ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
toddouska 0:5045d2638c29 3530 ShaUpdate(&sha, messageVerify, verifySz);
toddouska 0:5045d2638c29 3531 ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
toddouska 0:5045d2638c29 3532
toddouska 0:5045d2638c29 3533 /* rsa for now */
toddouska 0:5045d2638c29 3534 {
toddouska 0:5045d2638c29 3535 int ret;
toddouska 0:5045d2638c29 3536 byte* out;
toddouska 0:5045d2638c29 3537
toddouska 0:5045d2638c29 3538 if (!ssl->peerRsaKeyPresent)
toddouska 0:5045d2638c29 3539 return NO_PEER_KEY;
toddouska 0:5045d2638c29 3540
toddouska 0:5045d2638c29 3541 ret = RsaSSL_VerifyInline(signature, length,&out, &ssl->peerRsaKey);
toddouska 0:5045d2638c29 3542
toddouska 0:5045d2638c29 3543 if (IsAtLeastTLSv1_2(ssl)) {
toddouska 0:5045d2638c29 3544 byte encodedSig[MAX_ENCODED_SIG_SZ];
toddouska 0:5045d2638c29 3545 word32 sigSz;
toddouska 0:5045d2638c29 3546 byte* digest;
toddouska 0:5045d2638c29 3547 int hashType;
toddouska 0:5045d2638c29 3548 int digestSz;
toddouska 0:5045d2638c29 3549
toddouska 0:5045d2638c29 3550 /* sha1 for now */
toddouska 0:5045d2638c29 3551 digest = &hash[MD5_DIGEST_SIZE];
toddouska 0:5045d2638c29 3552 hashType = SHAh;
toddouska 0:5045d2638c29 3553 digestSz = SHA_DIGEST_SIZE;
toddouska 0:5045d2638c29 3554
toddouska 0:5045d2638c29 3555 sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType);
toddouska 0:5045d2638c29 3556
toddouska 0:5045d2638c29 3557 if (sigSz != ret || XMEMCMP(out, encodedSig, sigSz) != 0)
toddouska 0:5045d2638c29 3558 return VERIFY_SIGN_ERROR;
toddouska 0:5045d2638c29 3559 }
toddouska 0:5045d2638c29 3560 else {
toddouska 0:5045d2638c29 3561 if (ret != sizeof(hash) || XMEMCMP(out, hash, sizeof(hash)))
toddouska 0:5045d2638c29 3562 return VERIFY_SIGN_ERROR;
toddouska 0:5045d2638c29 3563 }
toddouska 0:5045d2638c29 3564 }
toddouska 0:5045d2638c29 3565
toddouska 0:5045d2638c29 3566 ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
toddouska 0:5045d2638c29 3567
toddouska 0:5045d2638c29 3568 return 0;
toddouska 0:5045d2638c29 3569 } /* dh_kea */
toddouska 0:5045d2638c29 3570 #endif /* OPENSSL_EXTRA */
toddouska 0:5045d2638c29 3571 return -1; /* not supported by build */
toddouska 0:5045d2638c29 3572 }
toddouska 0:5045d2638c29 3573
toddouska 0:5045d2638c29 3574
toddouska 0:5045d2638c29 3575 int SendClientKeyExchange(SSL* ssl)
toddouska 0:5045d2638c29 3576 {
toddouska 0:5045d2638c29 3577 byte encSecret[MAX_NTRU_ENCRYPT_SZ];
toddouska 0:5045d2638c29 3578 word32 encSz = 0;
toddouska 0:5045d2638c29 3579 word32 idx = 0;
toddouska 0:5045d2638c29 3580 int ret = 0;
toddouska 0:5045d2638c29 3581
toddouska 0:5045d2638c29 3582 if (ssl->specs.kea == rsa_kea) {
toddouska 0:5045d2638c29 3583 RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
toddouska 0:5045d2638c29 3584 SECRET_LEN);
toddouska 0:5045d2638c29 3585 ssl->arrays.preMasterSecret[0] = ssl->chVersion.major;
toddouska 0:5045d2638c29 3586 ssl->arrays.preMasterSecret[1] = ssl->chVersion.minor;
toddouska 0:5045d2638c29 3587 ssl->arrays.preMasterSz = SECRET_LEN;
toddouska 0:5045d2638c29 3588
toddouska 0:5045d2638c29 3589 if (ssl->peerRsaKeyPresent == 0)
toddouska 0:5045d2638c29 3590 return NO_PEER_KEY;
toddouska 0:5045d2638c29 3591
toddouska 0:5045d2638c29 3592 ret = RsaPublicEncrypt(ssl->arrays.preMasterSecret, SECRET_LEN,
toddouska 0:5045d2638c29 3593 encSecret, sizeof(encSecret), &ssl->peerRsaKey,
toddouska 0:5045d2638c29 3594 &ssl->rng);
toddouska 0:5045d2638c29 3595 if (ret > 0) {
toddouska 0:5045d2638c29 3596 encSz = ret;
toddouska 0:5045d2638c29 3597 ret = 0; /* set success to 0 */
toddouska 0:5045d2638c29 3598 }
toddouska 0:5045d2638c29 3599 #ifdef OPENSSL_EXTRA
toddouska 0:5045d2638c29 3600 } else if (ssl->specs.kea == diffie_hellman_kea) {
toddouska 0:5045d2638c29 3601 buffer serverP = ssl->buffers.serverDH_P;
toddouska 0:5045d2638c29 3602 buffer serverG = ssl->buffers.serverDH_G;
toddouska 0:5045d2638c29 3603 buffer serverPub = ssl->buffers.serverDH_Pub;
toddouska 0:5045d2638c29 3604 byte priv[ENCRYPT_LEN];
toddouska 0:5045d2638c29 3605 word32 privSz;
toddouska 0:5045d2638c29 3606 DhKey key;
toddouska 0:5045d2638c29 3607
toddouska 0:5045d2638c29 3608 if (serverP.buffer == 0 || serverG.buffer == 0 ||
toddouska 0:5045d2638c29 3609 serverPub.buffer == 0)
toddouska 0:5045d2638c29 3610 return NO_PEER_KEY;
toddouska 0:5045d2638c29 3611
toddouska 0:5045d2638c29 3612 InitDhKey(&key);
toddouska 0:5045d2638c29 3613 ret = DhSetKey(&key, serverP.buffer, serverP.length,
toddouska 0:5045d2638c29 3614 serverG.buffer, serverG.length);
toddouska 0:5045d2638c29 3615 if (ret == 0)
toddouska 0:5045d2638c29 3616 /* for DH, encSecret is Yc, agree is pre-master */
toddouska 0:5045d2638c29 3617 ret = DhGenerateKeyPair(&key, &ssl->rng, priv, &privSz,
toddouska 0:5045d2638c29 3618 encSecret, &encSz);
toddouska 0:5045d2638c29 3619 if (ret == 0)
toddouska 0:5045d2638c29 3620 ret = DhAgree(&key, ssl->arrays.preMasterSecret,
toddouska 0:5045d2638c29 3621 &ssl->arrays.preMasterSz, priv, privSz,
toddouska 0:5045d2638c29 3622 serverPub.buffer, serverPub.length);
toddouska 0:5045d2638c29 3623 FreeDhKey(&key);
toddouska 0:5045d2638c29 3624 #endif /* OPENSSL_EXTRA */
toddouska 0:5045d2638c29 3625 #ifndef NO_PSK
toddouska 0:5045d2638c29 3626 } else if (ssl->specs.kea == psk_kea) {
toddouska 0:5045d2638c29 3627 byte* pms = ssl->arrays.preMasterSecret;
toddouska 0:5045d2638c29 3628
toddouska 0:5045d2638c29 3629 ssl->arrays.psk_keySz = ssl->options.client_psk_cb(ssl,
toddouska 0:5045d2638c29 3630 ssl->arrays.server_hint, ssl->arrays.client_identity,
toddouska 0:5045d2638c29 3631 MAX_PSK_ID_LEN, ssl->arrays.psk_key, MAX_PSK_KEY_LEN);
toddouska 0:5045d2638c29 3632 if (ssl->arrays.psk_keySz == 0 ||
toddouska 0:5045d2638c29 3633 ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN)
toddouska 0:5045d2638c29 3634 return PSK_KEY_ERROR;
toddouska 0:5045d2638c29 3635 encSz = (word32)XSTRLEN(ssl->arrays.client_identity);
toddouska 0:5045d2638c29 3636 if (encSz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
toddouska 0:5045d2638c29 3637 XMEMCPY(encSecret, ssl->arrays.client_identity, encSz);
toddouska 0:5045d2638c29 3638
toddouska 0:5045d2638c29 3639 /* make psk pre master secret */
toddouska 0:5045d2638c29 3640 /* length of key + length 0s + length of key + key */
toddouska 0:5045d2638c29 3641 c16toa((word16)ssl->arrays.psk_keySz, pms);
toddouska 0:5045d2638c29 3642 pms += 2;
toddouska 0:5045d2638c29 3643 XMEMSET(pms, 0, ssl->arrays.psk_keySz);
toddouska 0:5045d2638c29 3644 pms += ssl->arrays.psk_keySz;
toddouska 0:5045d2638c29 3645 c16toa((word16)ssl->arrays.psk_keySz, pms);
toddouska 0:5045d2638c29 3646 pms += 2;
toddouska 0:5045d2638c29 3647 XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
toddouska 0:5045d2638c29 3648 ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
toddouska 0:5045d2638c29 3649 #endif /* NO_PSK */
toddouska 0:5045d2638c29 3650 #ifdef HAVE_NTRU
toddouska 0:5045d2638c29 3651 } else if (ssl->specs.kea == ntru_kea) {
toddouska 0:5045d2638c29 3652 word32 rc;
toddouska 0:5045d2638c29 3653 word16 cipherLen = sizeof(encSecret);
toddouska 0:5045d2638c29 3654 DRBG_HANDLE drbg;
toddouska 0:5045d2638c29 3655 static uint8_t const cyasslStr[] = {
toddouska 0:5045d2638c29 3656 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U'
toddouska 0:5045d2638c29 3657 };
toddouska 0:5045d2638c29 3658
toddouska 0:5045d2638c29 3659 RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
toddouska 0:5045d2638c29 3660 SECRET_LEN);
toddouska 0:5045d2638c29 3661 ssl->arrays.preMasterSz = SECRET_LEN;
toddouska 0:5045d2638c29 3662
toddouska 0:5045d2638c29 3663 if (ssl->peerNtruKeyPresent == 0)
toddouska 0:5045d2638c29 3664 return NO_PEER_KEY;
toddouska 0:5045d2638c29 3665
toddouska 0:5045d2638c29 3666 rc = crypto_drbg_instantiate(MAX_NTRU_BITS, cyasslStr,
toddouska 0:5045d2638c29 3667 sizeof(cyasslStr), GetEntropy, &drbg);
toddouska 0:5045d2638c29 3668 if (rc != DRBG_OK)
toddouska 0:5045d2638c29 3669 return NTRU_DRBG_ERROR;
toddouska 0:5045d2638c29 3670
toddouska 0:5045d2638c29 3671 rc = crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,ssl->peerNtruKey,
toddouska 0:5045d2638c29 3672 ssl->arrays.preMasterSz,
toddouska 0:5045d2638c29 3673 ssl->arrays.preMasterSecret,
toddouska 0:5045d2638c29 3674 &cipherLen, encSecret);
toddouska 0:5045d2638c29 3675 crypto_drbg_uninstantiate(drbg);
toddouska 0:5045d2638c29 3676 if (rc != NTRU_OK)
toddouska 0:5045d2638c29 3677 return NTRU_ENCRYPT_ERROR;
toddouska 0:5045d2638c29 3678
toddouska 0:5045d2638c29 3679 encSz = cipherLen;
toddouska 0:5045d2638c29 3680 ret = 0;
toddouska 0:5045d2638c29 3681 #endif /* HAVE_NTRU */
toddouska 0:5045d2638c29 3682 } else
toddouska 0:5045d2638c29 3683 return -1; /* unsupported kea */
toddouska 0:5045d2638c29 3684
toddouska 0:5045d2638c29 3685 if (ret == 0) {
toddouska 0:5045d2638c29 3686 byte *output;
toddouska 0:5045d2638c29 3687 int sendSz;
toddouska 0:5045d2638c29 3688 word32 tlsSz = 0;
toddouska 0:5045d2638c29 3689
toddouska 0:5045d2638c29 3690 if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea)
toddouska 0:5045d2638c29 3691 tlsSz = 2;
toddouska 0:5045d2638c29 3692
toddouska 0:5045d2638c29 3693 sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 3694 idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 3695
toddouska 0:5045d2638c29 3696 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3697 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 3698 sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 3699 idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
toddouska 0:5045d2638c29 3700 }
toddouska 0:5045d2638c29 3701 #endif
toddouska 0:5045d2638c29 3702
toddouska 0:5045d2638c29 3703 /* check for avalaible size */
toddouska 0:5045d2638c29 3704 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 3705 return ret;
toddouska 0:5045d2638c29 3706
toddouska 0:5045d2638c29 3707 /* get ouput buffer */
toddouska 0:5045d2638c29 3708 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 3709 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 3710
toddouska 0:5045d2638c29 3711 AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl);
toddouska 0:5045d2638c29 3712
toddouska 0:5045d2638c29 3713 if (tlsSz) {
toddouska 0:5045d2638c29 3714 c16toa((word16)encSz, &output[idx]);
toddouska 0:5045d2638c29 3715 idx += 2;
toddouska 0:5045d2638c29 3716 }
toddouska 0:5045d2638c29 3717 XMEMCPY(output + idx, encSecret, encSz);
toddouska 0:5045d2638c29 3718 idx += encSz;
toddouska 0:5045d2638c29 3719
toddouska 0:5045d2638c29 3720 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 3721
toddouska 0:5045d2638c29 3722 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3723 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 3724 AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3725 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3726 AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
toddouska 0:5045d2638c29 3727 output, sendSz, ssl->heap);
toddouska 0:5045d2638c29 3728 #endif
toddouska 0:5045d2638c29 3729
toddouska 0:5045d2638c29 3730 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 3731
toddouska 0:5045d2638c29 3732 ret = SendBuffered(ssl);
toddouska 0:5045d2638c29 3733 }
toddouska 0:5045d2638c29 3734
toddouska 0:5045d2638c29 3735 if (ret == 0 || ret == WANT_WRITE) {
toddouska 0:5045d2638c29 3736 int tmpRet = MakeMasterSecret(ssl);
toddouska 0:5045d2638c29 3737 if (tmpRet != 0)
toddouska 0:5045d2638c29 3738 ret = tmpRet; /* save WANT_WRITE unless more serious */
toddouska 0:5045d2638c29 3739 ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
toddouska 0:5045d2638c29 3740 }
toddouska 0:5045d2638c29 3741
toddouska 0:5045d2638c29 3742 return ret;
toddouska 0:5045d2638c29 3743 }
toddouska 0:5045d2638c29 3744
toddouska 0:5045d2638c29 3745 int SendCertificateVerify(SSL* ssl)
toddouska 0:5045d2638c29 3746 {
toddouska 0:5045d2638c29 3747 byte *output;
toddouska 0:5045d2638c29 3748 int sendSz = 0, length, ret;
toddouska 0:5045d2638c29 3749 word32 idx = 0;
toddouska 0:5045d2638c29 3750 RsaKey key;
toddouska 0:5045d2638c29 3751
toddouska 0:5045d2638c29 3752 if (ssl->options.sendVerify == SEND_BLANK_CERT)
toddouska 0:5045d2638c29 3753 return 0; /* sent blank cert, can't verify */
toddouska 0:5045d2638c29 3754
toddouska 0:5045d2638c29 3755 /* check for avalaible size */
toddouska 0:5045d2638c29 3756 if ((ret = CheckAvalaibleSize(ssl, MAX_CERT_VERIFY_SZ)) != 0)
toddouska 0:5045d2638c29 3757 return ret;
toddouska 0:5045d2638c29 3758
toddouska 0:5045d2638c29 3759 /* get ouput buffer */
toddouska 0:5045d2638c29 3760 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 3761 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 3762
toddouska 0:5045d2638c29 3763 BuildCertHashes(ssl, &ssl->certHashes);
toddouska 0:5045d2638c29 3764
toddouska 0:5045d2638c29 3765 /* TODO: when add DSS support check here */
toddouska 0:5045d2638c29 3766 InitRsaKey(&key, ssl->heap);
toddouska 0:5045d2638c29 3767 ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
toddouska 0:5045d2638c29 3768 ssl->buffers.key.length);
toddouska 0:5045d2638c29 3769 if (ret == 0) {
toddouska 0:5045d2638c29 3770 byte* verify = (byte*)&output[RECORD_HEADER_SZ +
toddouska 0:5045d2638c29 3771 HANDSHAKE_HEADER_SZ];
toddouska 0:5045d2638c29 3772 byte* signBuffer = ssl->certHashes.md5;
toddouska 0:5045d2638c29 3773 word32 signSz = sizeof(Hashes);
toddouska 0:5045d2638c29 3774
toddouska 0:5045d2638c29 3775 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3776 if (ssl->options.dtls)
toddouska 0:5045d2638c29 3777 verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 3778 #endif
toddouska 0:5045d2638c29 3779 length = RsaEncryptSize(&key);
toddouska 0:5045d2638c29 3780 c16toa((word16)length, verify); /* prepend verify header */
toddouska 0:5045d2638c29 3781
toddouska 0:5045d2638c29 3782 if (IsAtLeastTLSv1_2(ssl)) {
toddouska 0:5045d2638c29 3783 byte encodedSig[MAX_ENCODED_SIG_SZ];
toddouska 0:5045d2638c29 3784 byte* digest;
toddouska 0:5045d2638c29 3785 int hashType;
toddouska 0:5045d2638c29 3786 int digestSz;
toddouska 0:5045d2638c29 3787
toddouska 0:5045d2638c29 3788 /* sha1 for now */
toddouska 0:5045d2638c29 3789 digest = ssl->certHashes.sha;
toddouska 0:5045d2638c29 3790 hashType = SHAh;
toddouska 0:5045d2638c29 3791 digestSz = SHA_DIGEST_SIZE;
toddouska 0:5045d2638c29 3792
toddouska 0:5045d2638c29 3793 signSz = EncodeSignature(encodedSig, digest, digestSz,hashType);
toddouska 0:5045d2638c29 3794 signBuffer = encodedSig;
toddouska 0:5045d2638c29 3795 }
toddouska 0:5045d2638c29 3796
toddouska 0:5045d2638c29 3797 ret = RsaSSL_Sign(signBuffer, signSz, verify +
toddouska 0:5045d2638c29 3798 VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
toddouska 0:5045d2638c29 3799
toddouska 0:5045d2638c29 3800 if (ret > 0) {
toddouska 0:5045d2638c29 3801 ret = 0; /* reset */
toddouska 0:5045d2638c29 3802
toddouska 0:5045d2638c29 3803 AddHeaders(output, length + VERIFY_HEADER, certificate_verify,
toddouska 0:5045d2638c29 3804 ssl);
toddouska 0:5045d2638c29 3805
toddouska 0:5045d2638c29 3806 sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
toddouska 0:5045d2638c29 3807 VERIFY_HEADER;
toddouska 0:5045d2638c29 3808 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3809 if (ssl->options.dtls)
toddouska 0:5045d2638c29 3810 sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 3811 #endif
toddouska 0:5045d2638c29 3812 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 3813 }
toddouska 0:5045d2638c29 3814 }
toddouska 0:5045d2638c29 3815
toddouska 0:5045d2638c29 3816 FreeRsaKey(&key);
toddouska 0:5045d2638c29 3817
toddouska 0:5045d2638c29 3818 if (ret == 0) {
toddouska 0:5045d2638c29 3819 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3820 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 3821 AddPacketName("CertificateVerify", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3822 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3823 AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
toddouska 0:5045d2638c29 3824 output, sendSz, ssl->heap);
toddouska 0:5045d2638c29 3825 #endif
toddouska 0:5045d2638c29 3826 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 3827 return SendBuffered(ssl);
toddouska 0:5045d2638c29 3828 }
toddouska 0:5045d2638c29 3829 else
toddouska 0:5045d2638c29 3830 return ret;
toddouska 0:5045d2638c29 3831 }
toddouska 0:5045d2638c29 3832
toddouska 0:5045d2638c29 3833
toddouska 0:5045d2638c29 3834
toddouska 0:5045d2638c29 3835 #endif /* NO_CYASSL_CLIENT */
toddouska 0:5045d2638c29 3836
toddouska 0:5045d2638c29 3837
toddouska 0:5045d2638c29 3838 #ifndef NO_CYASSL_SERVER
toddouska 0:5045d2638c29 3839
toddouska 0:5045d2638c29 3840 int SendServerHello(SSL* ssl)
toddouska 0:5045d2638c29 3841 {
toddouska 0:5045d2638c29 3842 byte *output;
toddouska 0:5045d2638c29 3843 word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 3844 int sendSz;
toddouska 0:5045d2638c29 3845 int ret;
toddouska 0:5045d2638c29 3846
toddouska 0:5045d2638c29 3847 length = sizeof(ProtocolVersion) + RAN_LEN
toddouska 0:5045d2638c29 3848 + ID_LEN + ENUM_LEN
toddouska 0:5045d2638c29 3849 + SUITE_LEN
toddouska 0:5045d2638c29 3850 + ENUM_LEN;
toddouska 0:5045d2638c29 3851
toddouska 0:5045d2638c29 3852 /* check for avalaible size */
toddouska 0:5045d2638c29 3853 if ((ret = CheckAvalaibleSize(ssl, MAX_HELLO_SZ)) != 0)
toddouska 0:5045d2638c29 3854 return ret;
toddouska 0:5045d2638c29 3855
toddouska 0:5045d2638c29 3856 /* get ouput buffer */
toddouska 0:5045d2638c29 3857 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 3858 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 3859
toddouska 0:5045d2638c29 3860 sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 3861 AddHeaders(output, length, server_hello, ssl);
toddouska 0:5045d2638c29 3862
toddouska 0:5045d2638c29 3863 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3864 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 3865 idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 3866 sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 3867 }
toddouska 0:5045d2638c29 3868 #endif
toddouska 0:5045d2638c29 3869 /* now write to output */
toddouska 0:5045d2638c29 3870 /* first version */
toddouska 0:5045d2638c29 3871 XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
toddouska 0:5045d2638c29 3872 idx += sizeof(ProtocolVersion);
toddouska 0:5045d2638c29 3873
toddouska 0:5045d2638c29 3874 /* then random */
toddouska 0:5045d2638c29 3875 if (!ssl->options.resuming)
toddouska 0:5045d2638c29 3876 RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
toddouska 0:5045d2638c29 3877 XMEMCPY(output + idx, ssl->arrays.serverRandom, RAN_LEN);
toddouska 0:5045d2638c29 3878 idx += RAN_LEN;
toddouska 0:5045d2638c29 3879
toddouska 0:5045d2638c29 3880 #ifdef SHOW_SECRETS
toddouska 0:5045d2638c29 3881 {
toddouska 0:5045d2638c29 3882 int j;
toddouska 0:5045d2638c29 3883 printf("server random: ");
toddouska 0:5045d2638c29 3884 for (j = 0; j < RAN_LEN; j++)
toddouska 0:5045d2638c29 3885 printf("%02x", ssl->arrays.serverRandom[j]);
toddouska 0:5045d2638c29 3886 printf("\n");
toddouska 0:5045d2638c29 3887 }
toddouska 0:5045d2638c29 3888 #endif
toddouska 0:5045d2638c29 3889 /* then session id */
toddouska 0:5045d2638c29 3890 output[idx++] = ID_LEN;
toddouska 0:5045d2638c29 3891 if (!ssl->options.resuming)
toddouska 0:5045d2638c29 3892 RNG_GenerateBlock(&ssl->rng, ssl->arrays.sessionID, ID_LEN);
toddouska 0:5045d2638c29 3893 XMEMCPY(output + idx, ssl->arrays.sessionID, ID_LEN);
toddouska 0:5045d2638c29 3894 idx += ID_LEN;
toddouska 0:5045d2638c29 3895
toddouska 0:5045d2638c29 3896 /* then cipher suite */
toddouska 0:5045d2638c29 3897 output[idx++] = 0x00;
toddouska 0:5045d2638c29 3898 output[idx++] = ssl->options.cipherSuite;
toddouska 0:5045d2638c29 3899
toddouska 0:5045d2638c29 3900 /* last, compression */
toddouska 0:5045d2638c29 3901 if (ssl->options.usingCompression)
toddouska 0:5045d2638c29 3902 output[idx++] = ZLIB_COMPRESSION;
toddouska 0:5045d2638c29 3903 else
toddouska 0:5045d2638c29 3904 output[idx++] = NO_COMPRESSION;
toddouska 0:5045d2638c29 3905
toddouska 0:5045d2638c29 3906 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 3907 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 3908
toddouska 0:5045d2638c29 3909 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3910 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 3911 AddPacketName("ServerHello", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3912 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3913 AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
toddouska 0:5045d2638c29 3914 ssl->heap);
toddouska 0:5045d2638c29 3915 #endif
toddouska 0:5045d2638c29 3916
toddouska 0:5045d2638c29 3917 ssl->options.serverState = SERVER_HELLO_COMPLETE;
toddouska 0:5045d2638c29 3918
toddouska 0:5045d2638c29 3919 return SendBuffered(ssl);
toddouska 0:5045d2638c29 3920 }
toddouska 0:5045d2638c29 3921
toddouska 0:5045d2638c29 3922 int SendServerKeyExchange(SSL* ssl)
toddouska 0:5045d2638c29 3923 {
toddouska 0:5045d2638c29 3924 int ret = 0;
toddouska 0:5045d2638c29 3925
toddouska 0:5045d2638c29 3926 if (ssl->specs.kea != psk_kea) return 0;
toddouska 0:5045d2638c29 3927
toddouska 0:5045d2638c29 3928 #ifndef NO_PSK
toddouska 0:5045d2638c29 3929 {
toddouska 0:5045d2638c29 3930 byte *output;
toddouska 0:5045d2638c29 3931 word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 3932 int sendSz;
toddouska 0:5045d2638c29 3933 if (ssl->arrays.server_hint[0] == 0) return 0; /* don't send */
toddouska 0:5045d2638c29 3934
toddouska 0:5045d2638c29 3935 /* include size part */
toddouska 0:5045d2638c29 3936 length = (word32)XSTRLEN(ssl->arrays.server_hint);
toddouska 0:5045d2638c29 3937 if (length > MAX_PSK_ID_LEN) return SERVER_HINT_ERROR;
toddouska 0:5045d2638c29 3938 length += + HINT_LEN_SZ;
toddouska 0:5045d2638c29 3939 sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
toddouska 0:5045d2638c29 3940
toddouska 0:5045d2638c29 3941 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 3942 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 3943 sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 3944 idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 3945 }
toddouska 0:5045d2638c29 3946 #endif
toddouska 0:5045d2638c29 3947 /* check for avalaible size */
toddouska 0:5045d2638c29 3948 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 3949 return ret;
toddouska 0:5045d2638c29 3950
toddouska 0:5045d2638c29 3951 /* get ouput buffer */
toddouska 0:5045d2638c29 3952 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 3953 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 3954
toddouska 0:5045d2638c29 3955 AddHeaders(output, length, server_key_exchange, ssl);
toddouska 0:5045d2638c29 3956
toddouska 0:5045d2638c29 3957 /* key data */
toddouska 0:5045d2638c29 3958 c16toa((word16)(length - HINT_LEN_SZ), output + idx);
toddouska 0:5045d2638c29 3959 idx += HINT_LEN_SZ;
toddouska 0:5045d2638c29 3960 XMEMCPY(output + idx, ssl->arrays.server_hint, length - HINT_LEN_SZ);
toddouska 0:5045d2638c29 3961
toddouska 0:5045d2638c29 3962 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 3963
toddouska 0:5045d2638c29 3964 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 3965 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 3966 AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 3967 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 3968 AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
toddouska 0:5045d2638c29 3969 output, sendSz, ssl->heap);
toddouska 0:5045d2638c29 3970 #endif
toddouska 0:5045d2638c29 3971
toddouska 0:5045d2638c29 3972 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 3973 ret = SendBuffered(ssl);
toddouska 0:5045d2638c29 3974 ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
toddouska 0:5045d2638c29 3975 }
toddouska 0:5045d2638c29 3976 #endif /*NO_PSK */
toddouska 0:5045d2638c29 3977
toddouska 0:5045d2638c29 3978 return ret;
toddouska 0:5045d2638c29 3979 }
toddouska 0:5045d2638c29 3980
toddouska 0:5045d2638c29 3981
toddouska 0:5045d2638c29 3982 static int MatchSuite(SSL* ssl, Suites* peerSuites)
toddouska 0:5045d2638c29 3983 {
toddouska 0:5045d2638c29 3984 word16 i, j;
toddouska 0:5045d2638c29 3985
toddouska 0:5045d2638c29 3986 /* & 0x1 equivalent % 2 */
toddouska 0:5045d2638c29 3987 if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
toddouska 0:5045d2638c29 3988 return MATCH_SUITE_ERROR;
toddouska 0:5045d2638c29 3989
toddouska 0:5045d2638c29 3990 /* start with best, if a match we are good, Ciphers are at odd index
toddouska 0:5045d2638c29 3991 since all SSL and TLS ciphers have 0x00 first byte */
toddouska 0:5045d2638c29 3992 for (i = 1; i < ssl->suites.suiteSz; i += 2)
toddouska 0:5045d2638c29 3993 for (j = 1; j < peerSuites->suiteSz; j += 2)
toddouska 0:5045d2638c29 3994 if (ssl->suites.suites[i] == peerSuites->suites[j]) {
toddouska 0:5045d2638c29 3995 ssl->options.cipherSuite = ssl->suites.suites[i];
toddouska 0:5045d2638c29 3996 return SetCipherSpecs(ssl);
toddouska 0:5045d2638c29 3997 }
toddouska 0:5045d2638c29 3998
toddouska 0:5045d2638c29 3999 return MATCH_SUITE_ERROR;
toddouska 0:5045d2638c29 4000 }
toddouska 0:5045d2638c29 4001
toddouska 0:5045d2638c29 4002
toddouska 0:5045d2638c29 4003 /* process alert, return level */
toddouska 0:5045d2638c29 4004 int ProcessOldClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
toddouska 0:5045d2638c29 4005 word32 inSz, word16 sz)
toddouska 0:5045d2638c29 4006 {
toddouska 0:5045d2638c29 4007 word32 idx = *inOutIdx;
toddouska 0:5045d2638c29 4008 word16 sessionSz;
toddouska 0:5045d2638c29 4009 word16 randomSz;
toddouska 0:5045d2638c29 4010 word16 i, j;
toddouska 0:5045d2638c29 4011 ProtocolVersion pv;
toddouska 0:5045d2638c29 4012 Suites clSuites;
toddouska 0:5045d2638c29 4013
toddouska 0:5045d2638c29 4014 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 4015 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 4016 AddPacketName("ClientHello", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 4017 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 4018 AddLateName("ClientHello", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 4019 #endif
toddouska 0:5045d2638c29 4020
toddouska 0:5045d2638c29 4021 /* manually hash input since different format */
toddouska 0:5045d2638c29 4022 Md5Update(&ssl->hashMd5, input + idx, sz);
toddouska 0:5045d2638c29 4023 ShaUpdate(&ssl->hashSha, input + idx, sz);
toddouska 0:5045d2638c29 4024
toddouska 0:5045d2638c29 4025 /* does this value mean client_hello? */
toddouska 0:5045d2638c29 4026 idx++;
toddouska 0:5045d2638c29 4027
toddouska 0:5045d2638c29 4028 /* version */
toddouska 0:5045d2638c29 4029 pv.major = input[idx++];
toddouska 0:5045d2638c29 4030 pv.minor = input[idx++];
toddouska 0:5045d2638c29 4031 ssl->chVersion = pv; /* store */
toddouska 0:5045d2638c29 4032
toddouska 0:5045d2638c29 4033 if (ssl->version.minor > 0 && pv.minor == 0) {
toddouska 0:5045d2638c29 4034 if (!ssl->options.downgrade)
toddouska 0:5045d2638c29 4035 return VERSION_ERROR;
toddouska 0:5045d2638c29 4036 /* turn off tls */
toddouska 0:5045d2638c29 4037 ssl->options.tls = 0;
toddouska 0:5045d2638c29 4038 ssl->options.tls1_1 = 0;
toddouska 0:5045d2638c29 4039 ssl->version.minor = 0;
toddouska 0:5045d2638c29 4040 InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, FALSE,
toddouska 0:5045d2638c29 4041 ssl->options.haveNTRU);
toddouska 0:5045d2638c29 4042 }
toddouska 0:5045d2638c29 4043
toddouska 0:5045d2638c29 4044 /* suite size */
toddouska 0:5045d2638c29 4045 ato16(&input[idx], &clSuites.suiteSz);
toddouska 0:5045d2638c29 4046 idx += 2;
toddouska 0:5045d2638c29 4047
toddouska 0:5045d2638c29 4048 if (clSuites.suiteSz > MAX_SUITE_SZ)
toddouska 0:5045d2638c29 4049 return BUFFER_ERROR;
toddouska 0:5045d2638c29 4050
toddouska 0:5045d2638c29 4051 /* session size */
toddouska 0:5045d2638c29 4052 ato16(&input[idx], &sessionSz);
toddouska 0:5045d2638c29 4053 idx += 2;
toddouska 0:5045d2638c29 4054
toddouska 0:5045d2638c29 4055 if (sessionSz > ID_LEN)
toddouska 0:5045d2638c29 4056 return BUFFER_ERROR;
toddouska 0:5045d2638c29 4057
toddouska 0:5045d2638c29 4058 /* random size */
toddouska 0:5045d2638c29 4059 ato16(&input[idx], &randomSz);
toddouska 0:5045d2638c29 4060 idx += 2;
toddouska 0:5045d2638c29 4061
toddouska 0:5045d2638c29 4062 if (randomSz > RAN_LEN)
toddouska 0:5045d2638c29 4063 return BUFFER_ERROR;
toddouska 0:5045d2638c29 4064
toddouska 0:5045d2638c29 4065 /* suites */
toddouska 0:5045d2638c29 4066 for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
toddouska 0:5045d2638c29 4067 byte first = input[idx++];
toddouska 0:5045d2638c29 4068 if (!first) { /* implicit: skip sslv2 type */
toddouska 0:5045d2638c29 4069 XMEMCPY(&clSuites.suites[j], &input[idx], 2);
toddouska 0:5045d2638c29 4070 j += 2;
toddouska 0:5045d2638c29 4071 }
toddouska 0:5045d2638c29 4072 idx += 2;
toddouska 0:5045d2638c29 4073 }
toddouska 0:5045d2638c29 4074 clSuites.suiteSz = j;
toddouska 0:5045d2638c29 4075
toddouska 0:5045d2638c29 4076 /* session id */
toddouska 0:5045d2638c29 4077 if (sessionSz) {
toddouska 0:5045d2638c29 4078 XMEMCPY(ssl->arrays.sessionID, input + idx, sessionSz);
toddouska 0:5045d2638c29 4079 idx += sessionSz;
toddouska 0:5045d2638c29 4080 ssl->options.resuming = 1;
toddouska 0:5045d2638c29 4081 }
toddouska 0:5045d2638c29 4082
toddouska 0:5045d2638c29 4083 /* random */
toddouska 0:5045d2638c29 4084 if (randomSz < RAN_LEN)
toddouska 0:5045d2638c29 4085 XMEMSET(ssl->arrays.clientRandom, 0, RAN_LEN - randomSz);
toddouska 0:5045d2638c29 4086 XMEMCPY(&ssl->arrays.clientRandom[RAN_LEN - randomSz], input + idx,
toddouska 0:5045d2638c29 4087 randomSz);
toddouska 0:5045d2638c29 4088 idx += randomSz;
toddouska 0:5045d2638c29 4089
toddouska 0:5045d2638c29 4090 if (ssl->options.usingCompression)
toddouska 0:5045d2638c29 4091 ssl->options.usingCompression = 0; /* turn off */
toddouska 0:5045d2638c29 4092
toddouska 0:5045d2638c29 4093 ssl->options.clientState = CLIENT_HELLO_COMPLETE;
toddouska 0:5045d2638c29 4094 *inOutIdx = idx;
toddouska 0:5045d2638c29 4095
toddouska 0:5045d2638c29 4096 /* DoClientHello uses same resume code */
toddouska 0:5045d2638c29 4097 while (ssl->options.resuming) { /* let's try */
toddouska 0:5045d2638c29 4098 SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
toddouska 0:5045d2638c29 4099 if (!session) {
toddouska 0:5045d2638c29 4100 ssl->options.resuming = 0;
toddouska 0:5045d2638c29 4101 break; /* session lookup failed */
toddouska 0:5045d2638c29 4102 }
toddouska 0:5045d2638c29 4103 if (MatchSuite(ssl, &clSuites) < 0)
toddouska 0:5045d2638c29 4104 return UNSUPPORTED_SUITE;
toddouska 0:5045d2638c29 4105
toddouska 0:5045d2638c29 4106 RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
toddouska 0:5045d2638c29 4107 if (ssl->options.tls)
toddouska 0:5045d2638c29 4108 DeriveTlsKeys(ssl);
toddouska 0:5045d2638c29 4109 else
toddouska 0:5045d2638c29 4110 DeriveKeys(ssl);
toddouska 0:5045d2638c29 4111 ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
toddouska 0:5045d2638c29 4112
toddouska 0:5045d2638c29 4113 return 0;
toddouska 0:5045d2638c29 4114 }
toddouska 0:5045d2638c29 4115
toddouska 0:5045d2638c29 4116 return MatchSuite(ssl, &clSuites);
toddouska 0:5045d2638c29 4117 }
toddouska 0:5045d2638c29 4118
toddouska 0:5045d2638c29 4119
toddouska 0:5045d2638c29 4120 static int DoClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
toddouska 0:5045d2638c29 4121 word32 totalSz, word32 helloSz)
toddouska 0:5045d2638c29 4122 {
toddouska 0:5045d2638c29 4123 byte b;
toddouska 0:5045d2638c29 4124 ProtocolVersion pv;
toddouska 0:5045d2638c29 4125 Suites clSuites;
toddouska 0:5045d2638c29 4126 word32 i = *inOutIdx;
toddouska 0:5045d2638c29 4127 word32 begin = i;
toddouska 0:5045d2638c29 4128
toddouska 0:5045d2638c29 4129 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 4130 if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 4131 if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 4132 #endif
toddouska 0:5045d2638c29 4133 /* make sure can read up to session */
toddouska 0:5045d2638c29 4134 if (i + sizeof(pv) + RAN_LEN + ENUM_LEN > totalSz)
toddouska 0:5045d2638c29 4135 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4136
toddouska 0:5045d2638c29 4137 XMEMCPY(&pv, input + i, sizeof(pv));
toddouska 0:5045d2638c29 4138 ssl->chVersion = pv; /* store */
toddouska 0:5045d2638c29 4139 i += sizeof(pv);
toddouska 0:5045d2638c29 4140 if (ssl->version.minor > 0 && pv.minor == 0) {
toddouska 0:5045d2638c29 4141 if (!ssl->options.downgrade)
toddouska 0:5045d2638c29 4142 return VERSION_ERROR;
toddouska 0:5045d2638c29 4143 /* turn off tls */
toddouska 0:5045d2638c29 4144 ssl->options.tls = 0;
toddouska 0:5045d2638c29 4145 ssl->options.tls1_1 = 0;
toddouska 0:5045d2638c29 4146 ssl->version.minor = 0;
toddouska 0:5045d2638c29 4147 InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, FALSE,
toddouska 0:5045d2638c29 4148 ssl->options.haveNTRU);
toddouska 0:5045d2638c29 4149 }
toddouska 0:5045d2638c29 4150 /* random */
toddouska 0:5045d2638c29 4151 XMEMCPY(ssl->arrays.clientRandom, input + i, RAN_LEN);
toddouska 0:5045d2638c29 4152 i += RAN_LEN;
toddouska 0:5045d2638c29 4153
toddouska 0:5045d2638c29 4154 #ifdef SHOW_SECRETS
toddouska 0:5045d2638c29 4155 {
toddouska 0:5045d2638c29 4156 int j;
toddouska 0:5045d2638c29 4157 printf("client random: ");
toddouska 0:5045d2638c29 4158 for (j = 0; j < RAN_LEN; j++)
toddouska 0:5045d2638c29 4159 printf("%02x", ssl->arrays.clientRandom[j]);
toddouska 0:5045d2638c29 4160 printf("\n");
toddouska 0:5045d2638c29 4161 }
toddouska 0:5045d2638c29 4162 #endif
toddouska 0:5045d2638c29 4163 /* session id */
toddouska 0:5045d2638c29 4164 b = input[i++];
toddouska 0:5045d2638c29 4165 if (b) {
toddouska 0:5045d2638c29 4166 if (i + ID_LEN > totalSz)
toddouska 0:5045d2638c29 4167 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4168 XMEMCPY(ssl->arrays.sessionID, input + i, ID_LEN);
toddouska 0:5045d2638c29 4169 i += b;
toddouska 0:5045d2638c29 4170 ssl->options.resuming= 1; /* client wants to resume */
toddouska 0:5045d2638c29 4171 }
toddouska 0:5045d2638c29 4172
toddouska 0:5045d2638c29 4173 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 4174 /* cookie */
toddouska 0:5045d2638c29 4175 if (ssl->options.dtls) {
toddouska 0:5045d2638c29 4176 b = input[i++];
toddouska 0:5045d2638c29 4177 if (b) {
toddouska 0:5045d2638c29 4178 if (b > MAX_COOKIE_LEN)
toddouska 0:5045d2638c29 4179 return BUFFER_ERROR;
toddouska 0:5045d2638c29 4180 if (i + b > totalSz)
toddouska 0:5045d2638c29 4181 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4182 XMEMCPY(ssl->arrays.cookie, input + i, b);
toddouska 0:5045d2638c29 4183 i += b;
toddouska 0:5045d2638c29 4184 }
toddouska 0:5045d2638c29 4185 }
toddouska 0:5045d2638c29 4186 #endif
toddouska 0:5045d2638c29 4187
toddouska 0:5045d2638c29 4188 if (i + LENGTH_SZ > totalSz)
toddouska 0:5045d2638c29 4189 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4190 /* suites */
toddouska 0:5045d2638c29 4191 ato16(&input[i], &clSuites.suiteSz);
toddouska 0:5045d2638c29 4192 i += 2;
toddouska 0:5045d2638c29 4193
toddouska 0:5045d2638c29 4194 /* suites and comp len */
toddouska 0:5045d2638c29 4195 if (i + clSuites.suiteSz + ENUM_LEN > totalSz)
toddouska 0:5045d2638c29 4196 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4197 if (clSuites.suiteSz > MAX_SUITE_SZ)
toddouska 0:5045d2638c29 4198 return BUFFER_ERROR;
toddouska 0:5045d2638c29 4199 XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
toddouska 0:5045d2638c29 4200 i += clSuites.suiteSz;
toddouska 0:5045d2638c29 4201
toddouska 0:5045d2638c29 4202 b = input[i++]; /* comp len */
toddouska 0:5045d2638c29 4203 if (i + b > totalSz)
toddouska 0:5045d2638c29 4204 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4205
toddouska 0:5045d2638c29 4206 if (ssl->options.usingCompression) {
toddouska 0:5045d2638c29 4207 int match = 0;
toddouska 0:5045d2638c29 4208 while (b--) {
toddouska 0:5045d2638c29 4209 byte comp = input[i++];
toddouska 0:5045d2638c29 4210 if (comp == ZLIB_COMPRESSION)
toddouska 0:5045d2638c29 4211 match = 1;
toddouska 0:5045d2638c29 4212 }
toddouska 0:5045d2638c29 4213 if (!match)
toddouska 0:5045d2638c29 4214 ssl->options.usingCompression = 0; /* turn off */
toddouska 0:5045d2638c29 4215 }
toddouska 0:5045d2638c29 4216 else
toddouska 0:5045d2638c29 4217 i += b; /* ignore, since we're not on */
toddouska 0:5045d2638c29 4218
toddouska 0:5045d2638c29 4219 ssl->options.clientState = CLIENT_HELLO_COMPLETE;
toddouska 0:5045d2638c29 4220
toddouska 0:5045d2638c29 4221 *inOutIdx = i;
toddouska 0:5045d2638c29 4222 if ( (i - begin) < helloSz)
toddouska 0:5045d2638c29 4223 *inOutIdx = begin + helloSz; /* skip extensions */
toddouska 0:5045d2638c29 4224
toddouska 0:5045d2638c29 4225 /* ProcessOld uses same resume code */
toddouska 0:5045d2638c29 4226 while (ssl->options.resuming) { /* let's try */
toddouska 0:5045d2638c29 4227 SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
toddouska 0:5045d2638c29 4228 if (!session) {
toddouska 0:5045d2638c29 4229 ssl->options.resuming = 0;
toddouska 0:5045d2638c29 4230 break; /* session lookup failed */
toddouska 0:5045d2638c29 4231 }
toddouska 0:5045d2638c29 4232 if (MatchSuite(ssl, &clSuites) < 0)
toddouska 0:5045d2638c29 4233 return UNSUPPORTED_SUITE;
toddouska 0:5045d2638c29 4234
toddouska 0:5045d2638c29 4235 RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
toddouska 0:5045d2638c29 4236 if (ssl->options.tls)
toddouska 0:5045d2638c29 4237 DeriveTlsKeys(ssl);
toddouska 0:5045d2638c29 4238 else
toddouska 0:5045d2638c29 4239 DeriveKeys(ssl);
toddouska 0:5045d2638c29 4240 ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
toddouska 0:5045d2638c29 4241
toddouska 0:5045d2638c29 4242 return 0;
toddouska 0:5045d2638c29 4243 }
toddouska 0:5045d2638c29 4244 return MatchSuite(ssl, &clSuites);
toddouska 0:5045d2638c29 4245 }
toddouska 0:5045d2638c29 4246
toddouska 0:5045d2638c29 4247
toddouska 0:5045d2638c29 4248 static int DoCertificateVerify(SSL* ssl, byte* input, word32* inOutsz,
toddouska 0:5045d2638c29 4249 word32 totalSz)
toddouska 0:5045d2638c29 4250 {
toddouska 0:5045d2638c29 4251 word16 sz = 0;
toddouska 0:5045d2638c29 4252 word32 i = *inOutsz;
toddouska 0:5045d2638c29 4253 int ret = VERIFY_CERT_ERROR; /* start in error state */
toddouska 0:5045d2638c29 4254 byte* sig;
toddouska 0:5045d2638c29 4255 byte* out;
toddouska 0:5045d2638c29 4256 int outLen;
toddouska 0:5045d2638c29 4257
toddouska 0:5045d2638c29 4258 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 4259 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 4260 AddPacketName("CertificateVerify", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 4261 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 4262 AddLateName("CertificateVerify", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 4263 #endif
toddouska 0:5045d2638c29 4264 if ( (i + VERIFY_HEADER) > totalSz)
toddouska 0:5045d2638c29 4265 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4266
toddouska 0:5045d2638c29 4267 ato16(&input[i], &sz);
toddouska 0:5045d2638c29 4268 i += VERIFY_HEADER;
toddouska 0:5045d2638c29 4269
toddouska 0:5045d2638c29 4270 if ( (i + sz) > totalSz)
toddouska 0:5045d2638c29 4271 return INCOMPLETE_DATA;
toddouska 0:5045d2638c29 4272
toddouska 0:5045d2638c29 4273 if (sz > ENCRYPT_LEN)
toddouska 0:5045d2638c29 4274 return BUFFER_ERROR;
toddouska 0:5045d2638c29 4275
toddouska 0:5045d2638c29 4276 sig = &input[i];
toddouska 0:5045d2638c29 4277 *inOutsz = i + sz;
toddouska 0:5045d2638c29 4278 /* TODO: when add DSS support check here */
toddouska 0:5045d2638c29 4279 if (ssl->peerRsaKeyPresent != 0) {
toddouska 0:5045d2638c29 4280 outLen = RsaSSL_VerifyInline(sig, sz, &out, &ssl->peerRsaKey);
toddouska 0:5045d2638c29 4281
toddouska 0:5045d2638c29 4282 if (IsAtLeastTLSv1_2(ssl)) {
toddouska 0:5045d2638c29 4283 byte encodedSig[MAX_ENCODED_SIG_SZ];
toddouska 0:5045d2638c29 4284 word32 sigSz;
toddouska 0:5045d2638c29 4285 byte* digest;
toddouska 0:5045d2638c29 4286 int hashType;
toddouska 0:5045d2638c29 4287 int digestSz;
toddouska 0:5045d2638c29 4288
toddouska 0:5045d2638c29 4289 /* sha1 for now */
toddouska 0:5045d2638c29 4290 digest = ssl->certHashes.sha;
toddouska 0:5045d2638c29 4291 hashType = SHAh;
toddouska 0:5045d2638c29 4292 digestSz = SHA_DIGEST_SIZE;
toddouska 0:5045d2638c29 4293
toddouska 0:5045d2638c29 4294 sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType);
toddouska 0:5045d2638c29 4295
toddouska 0:5045d2638c29 4296 if (outLen == sigSz && XMEMCMP(out, encodedSig, sigSz) == 0)
toddouska 0:5045d2638c29 4297 ret = 0;
toddouska 0:5045d2638c29 4298 }
toddouska 0:5045d2638c29 4299 else {
toddouska 0:5045d2638c29 4300 if (outLen == sizeof(ssl->certHashes) && XMEMCMP(out,
toddouska 0:5045d2638c29 4301 ssl->certHashes.md5, sizeof(ssl->certHashes)) == 0)
toddouska 0:5045d2638c29 4302 ret = 0;
toddouska 0:5045d2638c29 4303 }
toddouska 0:5045d2638c29 4304 }
toddouska 0:5045d2638c29 4305 return ret;
toddouska 0:5045d2638c29 4306 }
toddouska 0:5045d2638c29 4307
toddouska 0:5045d2638c29 4308
toddouska 0:5045d2638c29 4309 int SendServerHelloDone(SSL* ssl)
toddouska 0:5045d2638c29 4310 {
toddouska 0:5045d2638c29 4311 byte *output;
toddouska 0:5045d2638c29 4312 int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 4313 int ret;
toddouska 0:5045d2638c29 4314
toddouska 0:5045d2638c29 4315 #ifdef CYASSL_DTLS
toddouska 0:5045d2638c29 4316 if (ssl->options.dtls)
toddouska 0:5045d2638c29 4317 sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
toddouska 0:5045d2638c29 4318 #endif
toddouska 0:5045d2638c29 4319 /* check for avalaible size */
toddouska 0:5045d2638c29 4320 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 4321 return ret;
toddouska 0:5045d2638c29 4322
toddouska 0:5045d2638c29 4323 /* get ouput buffer */
toddouska 0:5045d2638c29 4324 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 4325 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 4326
toddouska 0:5045d2638c29 4327 AddHeaders(output, 0, server_hello_done, ssl);
toddouska 0:5045d2638c29 4328
toddouska 0:5045d2638c29 4329 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 4330 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 4331 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 4332 AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 4333 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 4334 AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz,
toddouska 0:5045d2638c29 4335 ssl->heap);
toddouska 0:5045d2638c29 4336 #endif
toddouska 0:5045d2638c29 4337 ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
toddouska 0:5045d2638c29 4338
toddouska 0:5045d2638c29 4339 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 4340
toddouska 0:5045d2638c29 4341 return SendBuffered(ssl);
toddouska 0:5045d2638c29 4342 }
toddouska 0:5045d2638c29 4343
toddouska 0:5045d2638c29 4344
toddouska 0:5045d2638c29 4345 int SendHelloVerifyRequest(SSL* ssl)
toddouska 0:5045d2638c29 4346 {
toddouska 0:5045d2638c29 4347 byte* output;
toddouska 0:5045d2638c29 4348 int length = VERSION_SZ + ENUM_LEN;
toddouska 0:5045d2638c29 4349 int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
toddouska 0:5045d2638c29 4350 int sendSz = length + idx;
toddouska 0:5045d2638c29 4351 int ret;
toddouska 0:5045d2638c29 4352
toddouska 0:5045d2638c29 4353 /* check for avalaible size */
toddouska 0:5045d2638c29 4354 if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
toddouska 0:5045d2638c29 4355 return ret;
toddouska 0:5045d2638c29 4356
toddouska 0:5045d2638c29 4357 /* get ouput buffer */
toddouska 0:5045d2638c29 4358 output = ssl->buffers.outputBuffer.buffer +
toddouska 0:5045d2638c29 4359 ssl->buffers.outputBuffer.idx;
toddouska 0:5045d2638c29 4360
toddouska 0:5045d2638c29 4361 AddHeaders(output, length, hello_verify_request, ssl);
toddouska 0:5045d2638c29 4362
toddouska 0:5045d2638c29 4363 XMEMCPY(output + idx, &ssl->chVersion, VERSION_SZ);
toddouska 0:5045d2638c29 4364 idx += VERSION_SZ;
toddouska 0:5045d2638c29 4365 output[idx++] = 0; /* no cookie for now */
toddouska 0:5045d2638c29 4366
toddouska 0:5045d2638c29 4367 HashOutput(ssl, output, sendSz, 0);
toddouska 0:5045d2638c29 4368 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 4369 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 4370 AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 4371 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 4372 AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
toddouska 0:5045d2638c29 4373 sendSz, ssl->heap);
toddouska 0:5045d2638c29 4374 #endif
toddouska 0:5045d2638c29 4375 ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
toddouska 0:5045d2638c29 4376
toddouska 0:5045d2638c29 4377 ssl->buffers.outputBuffer.length += sendSz;
toddouska 0:5045d2638c29 4378
toddouska 0:5045d2638c29 4379 return SendBuffered(ssl);
toddouska 0:5045d2638c29 4380 }
toddouska 0:5045d2638c29 4381
toddouska 0:5045d2638c29 4382
toddouska 0:5045d2638c29 4383 static int DoClientKeyExchange(SSL* ssl, byte* input,
toddouska 0:5045d2638c29 4384 word32* inOutIdx)
toddouska 0:5045d2638c29 4385 {
toddouska 0:5045d2638c29 4386 int ret = 0;
toddouska 0:5045d2638c29 4387 word32 length = 0;
toddouska 0:5045d2638c29 4388 byte* out;
toddouska 0:5045d2638c29 4389
toddouska 0:5045d2638c29 4390 if (ssl->options.verifyPeer && ssl->options.failNoCert)
toddouska 0:5045d2638c29 4391 if (!ssl->options.havePeerCert) {
toddouska 0:5045d2638c29 4392 CYASSL_MSG("client didn't present peer cert");
toddouska 0:5045d2638c29 4393 return NO_PEER_CERT;
toddouska 0:5045d2638c29 4394 }
toddouska 0:5045d2638c29 4395
toddouska 0:5045d2638c29 4396 #ifdef CYASSL_CALLBACKS
toddouska 0:5045d2638c29 4397 if (ssl->hsInfoOn)
toddouska 0:5045d2638c29 4398 AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
toddouska 0:5045d2638c29 4399 if (ssl->toInfoOn)
toddouska 0:5045d2638c29 4400 AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
toddouska 0:5045d2638c29 4401 #endif
toddouska 0:5045d2638c29 4402 if (ssl->specs.kea == rsa_kea) {
toddouska 0:5045d2638c29 4403 word32 idx = 0;
toddouska 0:5045d2638c29 4404 RsaKey key;
toddouska 0:5045d2638c29 4405 byte* tmp = 0;
toddouska 0:5045d2638c29 4406
toddouska 0:5045d2638c29 4407 InitRsaKey(&key, ssl->heap);
toddouska 0:5045d2638c29 4408
toddouska 0:5045d2638c29 4409 if (ssl->buffers.key.buffer)
toddouska 0:5045d2638c29 4410 ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
toddouska 0:5045d2638c29 4411 ssl->buffers.key.length);
toddouska 0:5045d2638c29 4412 else
toddouska 0:5045d2638c29 4413 return NO_PRIVATE_KEY;
toddouska 0:5045d2638c29 4414
toddouska 0:5045d2638c29 4415 if (ret == 0) {
toddouska 0:5045d2638c29 4416 length = RsaEncryptSize(&key);
toddouska 0:5045d2638c29 4417 ssl->arrays.preMasterSz = SECRET_LEN;
toddouska 0:5045d2638c29 4418
toddouska 0:5045d2638c29 4419 if (ssl->options.tls)
toddouska 0:5045d2638c29 4420 (*inOutIdx) += 2;
toddouska 0:5045d2638c29 4421 tmp = input + *inOutIdx;
toddouska 0:5045d2638c29 4422 *inOutIdx += length;
toddouska 0:5045d2638c29 4423
toddouska 0:5045d2638c29 4424 if (RsaPrivateDecryptInline(tmp, length, &out, &key) ==
toddouska 0:5045d2638c29 4425 SECRET_LEN) {
toddouska 0:5045d2638c29 4426 XMEMCPY(ssl->arrays.preMasterSecret, out, SECRET_LEN);
toddouska 0:5045d2638c29 4427 if (ssl->arrays.preMasterSecret[0] != ssl->chVersion.major
toddouska 0:5045d2638c29 4428 ||
toddouska 0:5045d2638c29 4429 ssl->arrays.preMasterSecret[1] != ssl->chVersion.minor)
toddouska 0:5045d2638c29 4430
toddouska 0:5045d2638c29 4431 ret = PMS_VERSION_ERROR;
toddouska 0:5045d2638c29 4432 else
toddouska 0:5045d2638c29 4433 ret = MakeMasterSecret(ssl);
toddouska 0:5045d2638c29 4434 }
toddouska 0:5045d2638c29 4435 else
toddouska 0:5045d2638c29 4436 ret = RSA_PRIVATE_ERROR;
toddouska 0:5045d2638c29 4437 }
toddouska 0:5045d2638c29 4438
toddouska 0:5045d2638c29 4439 FreeRsaKey(&key);
toddouska 0:5045d2638c29 4440 #ifndef NO_PSK
toddouska 0:5045d2638c29 4441 } else if (ssl->specs.kea == psk_kea) {
toddouska 0:5045d2638c29 4442 byte* pms = ssl->arrays.preMasterSecret;
toddouska 0:5045d2638c29 4443 word16 ci_sz;
toddouska 0:5045d2638c29 4444
toddouska 0:5045d2638c29 4445 ato16(&input[*inOutIdx], &ci_sz);
toddouska 0:5045d2638c29 4446 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 4447 if (ci_sz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
toddouska 0:5045d2638c29 4448
toddouska 0:5045d2638c29 4449 XMEMCPY(ssl->arrays.client_identity, &input[*inOutIdx], ci_sz);
toddouska 0:5045d2638c29 4450 *inOutIdx += ci_sz;
toddouska 0:5045d2638c29 4451 ssl->arrays.client_identity[ci_sz] = 0;
toddouska 0:5045d2638c29 4452
toddouska 0:5045d2638c29 4453 ssl->arrays.psk_keySz = ssl->options.server_psk_cb(ssl,
toddouska 0:5045d2638c29 4454 ssl->arrays.client_identity, ssl->arrays.psk_key,
toddouska 0:5045d2638c29 4455 MAX_PSK_KEY_LEN);
toddouska 0:5045d2638c29 4456 if (ssl->arrays.psk_keySz == 0 ||
toddouska 0:5045d2638c29 4457 ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN) return PSK_KEY_ERROR;
toddouska 0:5045d2638c29 4458
toddouska 0:5045d2638c29 4459 /* make psk pre master secret */
toddouska 0:5045d2638c29 4460 /* length of key + length 0s + length of key + key */
toddouska 0:5045d2638c29 4461 c16toa((word16)ssl->arrays.psk_keySz, pms);
toddouska 0:5045d2638c29 4462 pms += 2;
toddouska 0:5045d2638c29 4463 XMEMSET(pms, 0, ssl->arrays.psk_keySz);
toddouska 0:5045d2638c29 4464 pms += ssl->arrays.psk_keySz;
toddouska 0:5045d2638c29 4465 c16toa((word16)ssl->arrays.psk_keySz, pms);
toddouska 0:5045d2638c29 4466 pms += 2;
toddouska 0:5045d2638c29 4467 XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
toddouska 0:5045d2638c29 4468 ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
toddouska 0:5045d2638c29 4469
toddouska 0:5045d2638c29 4470 ret = MakeMasterSecret(ssl);
toddouska 0:5045d2638c29 4471 #endif /* NO_PSK */
toddouska 0:5045d2638c29 4472 #ifdef HAVE_NTRU
toddouska 0:5045d2638c29 4473 } else if (ssl->specs.kea == ntru_kea) {
toddouska 0:5045d2638c29 4474 word32 rc;
toddouska 0:5045d2638c29 4475 word16 cipherLen;
toddouska 0:5045d2638c29 4476 word16 plainLen = sizeof(ssl->arrays.preMasterSecret);
toddouska 0:5045d2638c29 4477 byte* tmp;
toddouska 0:5045d2638c29 4478
toddouska 0:5045d2638c29 4479 if (!ssl->buffers.key.buffer)
toddouska 0:5045d2638c29 4480 return NO_PRIVATE_KEY;
toddouska 0:5045d2638c29 4481
toddouska 0:5045d2638c29 4482 ato16(&input[*inOutIdx], &cipherLen);
toddouska 0:5045d2638c29 4483 *inOutIdx += LENGTH_SZ;
toddouska 0:5045d2638c29 4484 if (cipherLen > MAX_NTRU_ENCRYPT_SZ)
toddouska 0:5045d2638c29 4485 return NTRU_KEY_ERROR;
toddouska 0:5045d2638c29 4486
toddouska 0:5045d2638c29 4487 tmp = input + *inOutIdx;
toddouska 0:5045d2638c29 4488 rc = crypto_ntru_decrypt((word16)ssl->buffers.key.length,
toddouska 0:5045d2638c29 4489 ssl->buffers.key.buffer, cipherLen, tmp, &plainLen,
toddouska 0:5045d2638c29 4490 ssl->arrays.preMasterSecret);
toddouska 0:5045d2638c29 4491
toddouska 0:5045d2638c29 4492 if (rc != NTRU_OK || plainLen != SECRET_LEN)
toddouska 0:5045d2638c29 4493 return NTRU_DECRYPT_ERROR;
toddouska 0:5045d2638c29 4494 *inOutIdx += cipherLen;
toddouska 0:5045d2638c29 4495
toddouska 0:5045d2638c29 4496 ssl->arrays.preMasterSz = plainLen;
toddouska 0:5045d2638c29 4497 ret = MakeMasterSecret(ssl);
toddouska 0:5045d2638c29 4498 #endif /* HAVE_NTRU */
toddouska 0:5045d2638c29 4499 }
toddouska 0:5045d2638c29 4500
toddouska 0:5045d2638c29 4501 if (ret == 0) {
toddouska 0:5045d2638c29 4502 ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
toddouska 0:5045d2638c29 4503 if (ssl->options.verifyPeer)
toddouska 0:5045d2638c29 4504 BuildCertHashes(ssl, &ssl->certHashes);
toddouska 0:5045d2638c29 4505 }
toddouska 0:5045d2638c29 4506
toddouska 0:5045d2638c29 4507 return ret;
toddouska 0:5045d2638c29 4508 }
toddouska 0:5045d2638c29 4509
toddouska 0:5045d2638c29 4510 #endif /* NO_CYASSL_SERVER */
toddouska 0:5045d2638c29 4511
toddouska 0:5045d2638c29 4512
toddouska 0:5045d2638c29 4513 #ifdef SINGLE_THREADED
toddouska 0:5045d2638c29 4514
toddouska 0:5045d2638c29 4515 int InitMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4516 {
toddouska 0:5045d2638c29 4517 return 0;
toddouska 0:5045d2638c29 4518 }
toddouska 0:5045d2638c29 4519
toddouska 0:5045d2638c29 4520
toddouska 0:5045d2638c29 4521 int FreeMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4522 {
toddouska 0:5045d2638c29 4523 return 0;
toddouska 0:5045d2638c29 4524 }
toddouska 0:5045d2638c29 4525
toddouska 0:5045d2638c29 4526
toddouska 0:5045d2638c29 4527 int LockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4528 {
toddouska 0:5045d2638c29 4529 return 0;
toddouska 0:5045d2638c29 4530 }
toddouska 0:5045d2638c29 4531
toddouska 0:5045d2638c29 4532
toddouska 0:5045d2638c29 4533 int UnLockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4534 {
toddouska 0:5045d2638c29 4535 return 0;
toddouska 0:5045d2638c29 4536 }
toddouska 0:5045d2638c29 4537
toddouska 0:5045d2638c29 4538 #else /* MULTI_THREAD */
toddouska 0:5045d2638c29 4539
toddouska 0:5045d2638c29 4540 #ifdef USE_WINDOWS_API
toddouska 0:5045d2638c29 4541
toddouska 0:5045d2638c29 4542 int InitMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4543 {
toddouska 0:5045d2638c29 4544 InitializeCriticalSection(m);
toddouska 0:5045d2638c29 4545 return 0;
toddouska 0:5045d2638c29 4546 }
toddouska 0:5045d2638c29 4547
toddouska 0:5045d2638c29 4548
toddouska 0:5045d2638c29 4549 int FreeMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4550 {
toddouska 0:5045d2638c29 4551 DeleteCriticalSection(m);
toddouska 0:5045d2638c29 4552 return 0;
toddouska 0:5045d2638c29 4553 }
toddouska 0:5045d2638c29 4554
toddouska 0:5045d2638c29 4555
toddouska 0:5045d2638c29 4556 int LockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4557 {
toddouska 0:5045d2638c29 4558 EnterCriticalSection(m);
toddouska 0:5045d2638c29 4559 return 0;
toddouska 0:5045d2638c29 4560 }
toddouska 0:5045d2638c29 4561
toddouska 0:5045d2638c29 4562
toddouska 0:5045d2638c29 4563 int UnLockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4564 {
toddouska 0:5045d2638c29 4565 LeaveCriticalSection(m);
toddouska 0:5045d2638c29 4566 return 0;
toddouska 0:5045d2638c29 4567 }
toddouska 0:5045d2638c29 4568
toddouska 0:5045d2638c29 4569 #elif defined(CYASSL_PTHREADS)
toddouska 0:5045d2638c29 4570
toddouska 0:5045d2638c29 4571 int InitMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4572 {
toddouska 0:5045d2638c29 4573 if (pthread_mutex_init(m, 0) == 0)
toddouska 0:5045d2638c29 4574 return 0;
toddouska 0:5045d2638c29 4575 else
toddouska 0:5045d2638c29 4576 return -1;
toddouska 0:5045d2638c29 4577 }
toddouska 0:5045d2638c29 4578
toddouska 0:5045d2638c29 4579
toddouska 0:5045d2638c29 4580 int FreeMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4581 {
toddouska 0:5045d2638c29 4582 if (pthread_mutex_destroy(m) == 0)
toddouska 0:5045d2638c29 4583 return 0;
toddouska 0:5045d2638c29 4584 else
toddouska 0:5045d2638c29 4585 return -1;
toddouska 0:5045d2638c29 4586 }
toddouska 0:5045d2638c29 4587
toddouska 0:5045d2638c29 4588
toddouska 0:5045d2638c29 4589 int LockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4590 {
toddouska 0:5045d2638c29 4591 if (pthread_mutex_lock(m) == 0)
toddouska 0:5045d2638c29 4592 return 0;
toddouska 0:5045d2638c29 4593 else
toddouska 0:5045d2638c29 4594 return -1;
toddouska 0:5045d2638c29 4595 }
toddouska 0:5045d2638c29 4596
toddouska 0:5045d2638c29 4597
toddouska 0:5045d2638c29 4598 int UnLockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4599 {
toddouska 0:5045d2638c29 4600 if (pthread_mutex_unlock(m) == 0)
toddouska 0:5045d2638c29 4601 return 0;
toddouska 0:5045d2638c29 4602 else
toddouska 0:5045d2638c29 4603 return -1;
toddouska 0:5045d2638c29 4604 }
toddouska 0:5045d2638c29 4605
toddouska 0:5045d2638c29 4606 #elif defined(THREADX)
toddouska 0:5045d2638c29 4607
toddouska 0:5045d2638c29 4608 int InitMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4609 {
toddouska 0:5045d2638c29 4610 if (tx_mutex_create(m, "CyaSSL Mutex", TX_NO_INHERIT) == 0)
toddouska 0:5045d2638c29 4611 return 0;
toddouska 0:5045d2638c29 4612 else
toddouska 0:5045d2638c29 4613 return -1;
toddouska 0:5045d2638c29 4614 }
toddouska 0:5045d2638c29 4615
toddouska 0:5045d2638c29 4616
toddouska 0:5045d2638c29 4617 int FreeMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4618 {
toddouska 0:5045d2638c29 4619 if (tx_mutex_delete(m) == 0)
toddouska 0:5045d2638c29 4620 return 0;
toddouska 0:5045d2638c29 4621 else
toddouska 0:5045d2638c29 4622 return -1;
toddouska 0:5045d2638c29 4623 }
toddouska 0:5045d2638c29 4624
toddouska 0:5045d2638c29 4625
toddouska 0:5045d2638c29 4626 int LockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4627 {
toddouska 0:5045d2638c29 4628 if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
toddouska 0:5045d2638c29 4629 return 0;
toddouska 0:5045d2638c29 4630 else
toddouska 0:5045d2638c29 4631 return -1;
toddouska 0:5045d2638c29 4632 }
toddouska 0:5045d2638c29 4633
toddouska 0:5045d2638c29 4634
toddouska 0:5045d2638c29 4635 int UnLockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4636 {
toddouska 0:5045d2638c29 4637 if (tx_mutex_put(m) == 0)
toddouska 0:5045d2638c29 4638 return 0;
toddouska 0:5045d2638c29 4639 else
toddouska 0:5045d2638c29 4640 return -1;
toddouska 0:5045d2638c29 4641 }
toddouska 0:5045d2638c29 4642
toddouska 0:5045d2638c29 4643 #elif defined(MICRIUM)
toddouska 0:5045d2638c29 4644
toddouska 0:5045d2638c29 4645 int InitMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4646 {
toddouska 0:5045d2638c29 4647 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
toddouska 0:5045d2638c29 4648 if (NetSecure_OS_MutexCreate(m) == 0)
toddouska 0:5045d2638c29 4649 return 0;
toddouska 0:5045d2638c29 4650 else
toddouska 0:5045d2638c29 4651 return -1;
toddouska 0:5045d2638c29 4652 #else
toddouska 0:5045d2638c29 4653 return 0;
toddouska 0:5045d2638c29 4654 #endif
toddouska 0:5045d2638c29 4655 }
toddouska 0:5045d2638c29 4656
toddouska 0:5045d2638c29 4657
toddouska 0:5045d2638c29 4658 int FreeMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4659 {
toddouska 0:5045d2638c29 4660 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
toddouska 0:5045d2638c29 4661 if (NetSecure_OS_FreeMutex(m) == 0)
toddouska 0:5045d2638c29 4662 return 0;
toddouska 0:5045d2638c29 4663 else
toddouska 0:5045d2638c29 4664 return -1;
toddouska 0:5045d2638c29 4665 #else
toddouska 0:5045d2638c29 4666 return 0;
toddouska 0:5045d2638c29 4667 #endif
toddouska 0:5045d2638c29 4668 }
toddouska 0:5045d2638c29 4669
toddouska 0:5045d2638c29 4670
toddouska 0:5045d2638c29 4671 int LockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4672 {
toddouska 0:5045d2638c29 4673 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
toddouska 0:5045d2638c29 4674 if (NetSecure_OS_LockMutex(m) == 0)
toddouska 0:5045d2638c29 4675 return 0;
toddouska 0:5045d2638c29 4676 else
toddouska 0:5045d2638c29 4677 return -1;
toddouska 0:5045d2638c29 4678 #else
toddouska 0:5045d2638c29 4679 return 0;
toddouska 0:5045d2638c29 4680 #endif
toddouska 0:5045d2638c29 4681 }
toddouska 0:5045d2638c29 4682
toddouska 0:5045d2638c29 4683
toddouska 0:5045d2638c29 4684 int UnLockMutex(CyaSSL_Mutex* m)
toddouska 0:5045d2638c29 4685 {
toddouska 0:5045d2638c29 4686 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
toddouska 0:5045d2638c29 4687 if (NetSecure_OS_UnLockMutex(m) == 0)
toddouska 0:5045d2638c29 4688 return 0;
toddouska 0:5045d2638c29 4689 else
toddouska 0:5045d2638c29 4690 return -1;
toddouska 0:5045d2638c29 4691 #else
toddouska 0:5045d2638c29 4692 return 0;
toddouska 0:5045d2638c29 4693 #endif
toddouska 0:5045d2638c29 4694
toddouska 0:5045d2638c29 4695 }
toddouska 0:5045d2638c29 4696
toddouska 0:5045d2638c29 4697 #endif /* USE_WINDOWS_API */
toddouska 0:5045d2638c29 4698 #endif /* SINGLE_THREADED */
toddouska 0:5045d2638c29 4699
toddouska 0:5045d2638c29 4700
toddouska 0:5045d2638c29 4701 #ifdef DEBUG_CYASSL
toddouska 0:5045d2638c29 4702
toddouska 0:5045d2638c29 4703 static int logging = 0;
toddouska 0:5045d2638c29 4704
toddouska 0:5045d2638c29 4705
toddouska 0:5045d2638c29 4706 int CyaSSL_Debugging_ON(void)
toddouska 0:5045d2638c29 4707 {
toddouska 0:5045d2638c29 4708 logging = 1;
toddouska 0:5045d2638c29 4709 return 0;
toddouska 0:5045d2638c29 4710 }
toddouska 0:5045d2638c29 4711
toddouska 0:5045d2638c29 4712
toddouska 0:5045d2638c29 4713 void CyaSSL_Debugging_OFF(void)
toddouska 0:5045d2638c29 4714 {
toddouska 0:5045d2638c29 4715 logging = 0;
toddouska 0:5045d2638c29 4716 }
toddouska 0:5045d2638c29 4717
toddouska 0:5045d2638c29 4718
toddouska 0:5045d2638c29 4719 #ifdef THREADX
toddouska 0:5045d2638c29 4720 int dc_log_printf(char*, ...);
toddouska 0:5045d2638c29 4721 #endif
toddouska 0:5045d2638c29 4722
toddouska 0:5045d2638c29 4723 void CYASSL_MSG(const char* msg)
toddouska 0:5045d2638c29 4724 {
toddouska 0:5045d2638c29 4725 if (logging) {
toddouska 0:5045d2638c29 4726 #ifdef THREADX
toddouska 0:5045d2638c29 4727 dc_log_printf("%s\n", msg);
toddouska 0:5045d2638c29 4728 #elif defined(MICRIUM)
toddouska 0:5045d2638c29 4729 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
toddouska 0:5045d2638c29 4730 NetSecure_TraceOut((CPU_CHAR *)msg);
toddouska 0:5045d2638c29 4731 #endif
toddouska 0:5045d2638c29 4732 #else
toddouska 0:5045d2638c29 4733 fprintf(stderr, "%s\n", msg);
toddouska 0:5045d2638c29 4734 #endif
toddouska 0:5045d2638c29 4735 }
toddouska 0:5045d2638c29 4736 }
toddouska 0:5045d2638c29 4737
toddouska 0:5045d2638c29 4738
toddouska 0:5045d2638c29 4739 void CYASSL_ENTER(const char* msg)
toddouska 0:5045d2638c29 4740 {
toddouska 0:5045d2638c29 4741 if (logging) {
toddouska 0:5045d2638c29 4742 char buffer[80];
toddouska 0:5045d2638c29 4743 sprintf(buffer, "CyaSSL Entering %s", msg);
toddouska 0:5045d2638c29 4744 CYASSL_MSG(buffer);
toddouska 0:5045d2638c29 4745 }
toddouska 0:5045d2638c29 4746 }
toddouska 0:5045d2638c29 4747
toddouska 0:5045d2638c29 4748
toddouska 0:5045d2638c29 4749 void CYASSL_LEAVE(const char* msg, int ret)
toddouska 0:5045d2638c29 4750 {
toddouska 0:5045d2638c29 4751 if (logging) {
toddouska 0:5045d2638c29 4752 char buffer[80];
toddouska 0:5045d2638c29 4753 sprintf(buffer, "CyaSSL Leaving %s, return %d", msg, ret);
toddouska 0:5045d2638c29 4754 CYASSL_MSG(buffer);
toddouska 0:5045d2638c29 4755 }
toddouska 0:5045d2638c29 4756 }
toddouska 0:5045d2638c29 4757
toddouska 0:5045d2638c29 4758
toddouska 0:5045d2638c29 4759 void CYASSL_ERROR(int error)
toddouska 0:5045d2638c29 4760 {
toddouska 0:5045d2638c29 4761 if (logging) {
toddouska 0:5045d2638c29 4762 char buffer[80];
toddouska 0:5045d2638c29 4763 sprintf(buffer, "CyaSSL error occured, error = %d", error);
toddouska 0:5045d2638c29 4764 CYASSL_MSG(buffer);
toddouska 0:5045d2638c29 4765 }
toddouska 0:5045d2638c29 4766 }
toddouska 0:5045d2638c29 4767
toddouska 0:5045d2638c29 4768
toddouska 0:5045d2638c29 4769 #else /* DEBUG_CYASSL */
toddouska 0:5045d2638c29 4770
toddouska 0:5045d2638c29 4771 int CyaSSL_Debugging_ON(void)
toddouska 0:5045d2638c29 4772 {
toddouska 0:5045d2638c29 4773 return -1; /* not compiled in */
toddouska 0:5045d2638c29 4774 }
toddouska 0:5045d2638c29 4775
toddouska 0:5045d2638c29 4776
toddouska 0:5045d2638c29 4777 void CyaSSL_Debugging_OFF(void)
toddouska 0:5045d2638c29 4778 {
toddouska 0:5045d2638c29 4779 /* already off */
toddouska 0:5045d2638c29 4780 }
toddouska 0:5045d2638c29 4781
toddouska 0:5045d2638c29 4782 #endif /* DEBUG_CYASSL */