cya_u
Fork of CyaSSL-forEncrypt by
cyassl_int.c@2:d0516dc143b1, 2017-05-10 (annotated)
- Committer:
- vbahl2
- Date:
- Wed May 10 18:20:47 2017 +0000
- Revision:
- 2:d0516dc143b1
- Parent:
- 0:5045d2638c29
updated
Who changed what in which revision?
User | Revision | Line number | New 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 */ |