This is a port of cyaSSL 2.7.0.
Dependents: CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet
tls.c@0:714293de3836, 2013-09-05 (annotated)
- Committer:
- ashleymills
- Date:
- Thu Sep 05 10:33:04 2013 +0000
- Revision:
- 0:714293de3836
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ashleymills | 0:714293de3836 | 1 | /* tls.c |
ashleymills | 0:714293de3836 | 2 | * |
ashleymills | 0:714293de3836 | 3 | * Copyright (C) 2006-2013 wolfSSL Inc. |
ashleymills | 0:714293de3836 | 4 | * |
ashleymills | 0:714293de3836 | 5 | * This file is part of CyaSSL. |
ashleymills | 0:714293de3836 | 6 | * |
ashleymills | 0:714293de3836 | 7 | * CyaSSL is free software; you can redistribute it and/or modify |
ashleymills | 0:714293de3836 | 8 | * it under the terms of the GNU General Public License as published by |
ashleymills | 0:714293de3836 | 9 | * the Free Software Foundation; either version 2 of the License, or |
ashleymills | 0:714293de3836 | 10 | * (at your option) any later version. |
ashleymills | 0:714293de3836 | 11 | * |
ashleymills | 0:714293de3836 | 12 | * CyaSSL is distributed in the hope that it will be useful, |
ashleymills | 0:714293de3836 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
ashleymills | 0:714293de3836 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
ashleymills | 0:714293de3836 | 15 | * GNU General Public License for more details. |
ashleymills | 0:714293de3836 | 16 | * |
ashleymills | 0:714293de3836 | 17 | * You should have received a copy of the GNU General Public License |
ashleymills | 0:714293de3836 | 18 | * along with this program; if not, write to the Free Software |
ashleymills | 0:714293de3836 | 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
ashleymills | 0:714293de3836 | 20 | */ |
ashleymills | 0:714293de3836 | 21 | |
ashleymills | 0:714293de3836 | 22 | #ifdef HAVE_CONFIG_H |
ashleymills | 0:714293de3836 | 23 | #include <config.h> |
ashleymills | 0:714293de3836 | 24 | #endif |
ashleymills | 0:714293de3836 | 25 | |
ashleymills | 0:714293de3836 | 26 | #include <cyassl/ctaocrypt/settings.h> |
ashleymills | 0:714293de3836 | 27 | |
ashleymills | 0:714293de3836 | 28 | #include <cyassl/ssl.h> |
ashleymills | 0:714293de3836 | 29 | #include <cyassl/internal.h> |
ashleymills | 0:714293de3836 | 30 | #include <cyassl/ctaoerror.h> |
ashleymills | 0:714293de3836 | 31 | #include <cyassl/ctaocrypt/hmac.h> |
ashleymills | 0:714293de3836 | 32 | |
ashleymills | 0:714293de3836 | 33 | |
ashleymills | 0:714293de3836 | 34 | |
ashleymills | 0:714293de3836 | 35 | #ifndef NO_TLS |
ashleymills | 0:714293de3836 | 36 | |
ashleymills | 0:714293de3836 | 37 | |
ashleymills | 0:714293de3836 | 38 | #ifndef min |
ashleymills | 0:714293de3836 | 39 | |
ashleymills | 0:714293de3836 | 40 | static INLINE word32 min(word32 a, word32 b) |
ashleymills | 0:714293de3836 | 41 | { |
ashleymills | 0:714293de3836 | 42 | return a > b ? b : a; |
ashleymills | 0:714293de3836 | 43 | } |
ashleymills | 0:714293de3836 | 44 | |
ashleymills | 0:714293de3836 | 45 | #endif /* min */ |
ashleymills | 0:714293de3836 | 46 | |
ashleymills | 0:714293de3836 | 47 | |
ashleymills | 0:714293de3836 | 48 | #ifdef CYASSL_SHA384 |
ashleymills | 0:714293de3836 | 49 | #define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE |
ashleymills | 0:714293de3836 | 50 | #else |
ashleymills | 0:714293de3836 | 51 | #define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE |
ashleymills | 0:714293de3836 | 52 | #endif |
ashleymills | 0:714293de3836 | 53 | |
ashleymills | 0:714293de3836 | 54 | /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ |
ashleymills | 0:714293de3836 | 55 | static void p_hash(byte* result, word32 resLen, const byte* secret, |
ashleymills | 0:714293de3836 | 56 | word32 secLen, const byte* seed, word32 seedLen, int hash) |
ashleymills | 0:714293de3836 | 57 | { |
ashleymills | 0:714293de3836 | 58 | word32 len = PHASH_MAX_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 59 | word32 times; |
ashleymills | 0:714293de3836 | 60 | word32 lastLen; |
ashleymills | 0:714293de3836 | 61 | word32 lastTime; |
ashleymills | 0:714293de3836 | 62 | word32 i; |
ashleymills | 0:714293de3836 | 63 | word32 idx = 0; |
ashleymills | 0:714293de3836 | 64 | byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */ |
ashleymills | 0:714293de3836 | 65 | byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */ |
ashleymills | 0:714293de3836 | 66 | |
ashleymills | 0:714293de3836 | 67 | Hmac hmac; |
ashleymills | 0:714293de3836 | 68 | |
ashleymills | 0:714293de3836 | 69 | switch (hash) { |
ashleymills | 0:714293de3836 | 70 | #ifndef NO_MD5 |
ashleymills | 0:714293de3836 | 71 | case md5_mac: |
ashleymills | 0:714293de3836 | 72 | { |
ashleymills | 0:714293de3836 | 73 | len = MD5_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 74 | hash = MD5; |
ashleymills | 0:714293de3836 | 75 | } |
ashleymills | 0:714293de3836 | 76 | break; |
ashleymills | 0:714293de3836 | 77 | #endif |
ashleymills | 0:714293de3836 | 78 | #ifndef NO_SHA256 |
ashleymills | 0:714293de3836 | 79 | case sha256_mac: |
ashleymills | 0:714293de3836 | 80 | { |
ashleymills | 0:714293de3836 | 81 | len = SHA256_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 82 | hash = SHA256; |
ashleymills | 0:714293de3836 | 83 | } |
ashleymills | 0:714293de3836 | 84 | break; |
ashleymills | 0:714293de3836 | 85 | #endif |
ashleymills | 0:714293de3836 | 86 | #ifdef CYASSL_SHA384 |
ashleymills | 0:714293de3836 | 87 | case sha384_mac: |
ashleymills | 0:714293de3836 | 88 | { |
ashleymills | 0:714293de3836 | 89 | len = SHA384_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 90 | hash = SHA384; |
ashleymills | 0:714293de3836 | 91 | } |
ashleymills | 0:714293de3836 | 92 | break; |
ashleymills | 0:714293de3836 | 93 | #endif |
ashleymills | 0:714293de3836 | 94 | #ifndef NO_SHA |
ashleymills | 0:714293de3836 | 95 | case sha_mac: |
ashleymills | 0:714293de3836 | 96 | default: |
ashleymills | 0:714293de3836 | 97 | { |
ashleymills | 0:714293de3836 | 98 | len = SHA_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 99 | hash = SHA; |
ashleymills | 0:714293de3836 | 100 | } |
ashleymills | 0:714293de3836 | 101 | break; |
ashleymills | 0:714293de3836 | 102 | #endif |
ashleymills | 0:714293de3836 | 103 | } |
ashleymills | 0:714293de3836 | 104 | |
ashleymills | 0:714293de3836 | 105 | times = resLen / len; |
ashleymills | 0:714293de3836 | 106 | lastLen = resLen % len; |
ashleymills | 0:714293de3836 | 107 | if (lastLen) times += 1; |
ashleymills | 0:714293de3836 | 108 | lastTime = times - 1; |
ashleymills | 0:714293de3836 | 109 | |
ashleymills | 0:714293de3836 | 110 | HmacSetKey(&hmac, hash, secret, secLen); |
ashleymills | 0:714293de3836 | 111 | HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ |
ashleymills | 0:714293de3836 | 112 | HmacFinal(&hmac, previous); /* A1 */ |
ashleymills | 0:714293de3836 | 113 | |
ashleymills | 0:714293de3836 | 114 | for (i = 0; i < times; i++) { |
ashleymills | 0:714293de3836 | 115 | HmacUpdate(&hmac, previous, len); |
ashleymills | 0:714293de3836 | 116 | HmacUpdate(&hmac, seed, seedLen); |
ashleymills | 0:714293de3836 | 117 | HmacFinal(&hmac, current); |
ashleymills | 0:714293de3836 | 118 | |
ashleymills | 0:714293de3836 | 119 | if ( (i == lastTime) && lastLen) |
ashleymills | 0:714293de3836 | 120 | XMEMCPY(&result[idx], current, min(lastLen, sizeof(current))); |
ashleymills | 0:714293de3836 | 121 | else { |
ashleymills | 0:714293de3836 | 122 | XMEMCPY(&result[idx], current, len); |
ashleymills | 0:714293de3836 | 123 | idx += len; |
ashleymills | 0:714293de3836 | 124 | HmacUpdate(&hmac, previous, len); |
ashleymills | 0:714293de3836 | 125 | HmacFinal(&hmac, previous); |
ashleymills | 0:714293de3836 | 126 | } |
ashleymills | 0:714293de3836 | 127 | } |
ashleymills | 0:714293de3836 | 128 | XMEMSET(previous, 0, sizeof previous); |
ashleymills | 0:714293de3836 | 129 | XMEMSET(current, 0, sizeof current); |
ashleymills | 0:714293de3836 | 130 | XMEMSET(&hmac, 0, sizeof hmac); |
ashleymills | 0:714293de3836 | 131 | } |
ashleymills | 0:714293de3836 | 132 | |
ashleymills | 0:714293de3836 | 133 | |
ashleymills | 0:714293de3836 | 134 | |
ashleymills | 0:714293de3836 | 135 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 136 | |
ashleymills | 0:714293de3836 | 137 | /* calculate XOR for TLSv1 PRF */ |
ashleymills | 0:714293de3836 | 138 | static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) |
ashleymills | 0:714293de3836 | 139 | { |
ashleymills | 0:714293de3836 | 140 | word32 i; |
ashleymills | 0:714293de3836 | 141 | |
ashleymills | 0:714293de3836 | 142 | for (i = 0; i < digLen; i++) |
ashleymills | 0:714293de3836 | 143 | digest[i] = md5[i] ^ sha[i]; |
ashleymills | 0:714293de3836 | 144 | } |
ashleymills | 0:714293de3836 | 145 | |
ashleymills | 0:714293de3836 | 146 | |
ashleymills | 0:714293de3836 | 147 | /* compute TLSv1 PRF (pseudo random function using HMAC) */ |
ashleymills | 0:714293de3836 | 148 | static void doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, |
ashleymills | 0:714293de3836 | 149 | const byte* label, word32 labLen, const byte* seed, word32 seedLen) |
ashleymills | 0:714293de3836 | 150 | { |
ashleymills | 0:714293de3836 | 151 | word32 half = (secLen + 1) / 2; |
ashleymills | 0:714293de3836 | 152 | |
ashleymills | 0:714293de3836 | 153 | byte md5_half[MAX_PRF_HALF]; /* half is real size */ |
ashleymills | 0:714293de3836 | 154 | byte sha_half[MAX_PRF_HALF]; /* half is real size */ |
ashleymills | 0:714293de3836 | 155 | byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ |
ashleymills | 0:714293de3836 | 156 | byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ |
ashleymills | 0:714293de3836 | 157 | byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ |
ashleymills | 0:714293de3836 | 158 | |
ashleymills | 0:714293de3836 | 159 | if (half > MAX_PRF_HALF) |
ashleymills | 0:714293de3836 | 160 | return; |
ashleymills | 0:714293de3836 | 161 | if (labLen + seedLen > MAX_PRF_LABSEED) |
ashleymills | 0:714293de3836 | 162 | return; |
ashleymills | 0:714293de3836 | 163 | if (digLen > MAX_PRF_DIG) |
ashleymills | 0:714293de3836 | 164 | return; |
ashleymills | 0:714293de3836 | 165 | |
ashleymills | 0:714293de3836 | 166 | XMEMSET(md5_result, 0, digLen); |
ashleymills | 0:714293de3836 | 167 | XMEMSET(sha_result, 0, digLen); |
ashleymills | 0:714293de3836 | 168 | |
ashleymills | 0:714293de3836 | 169 | XMEMCPY(md5_half, secret, half); |
ashleymills | 0:714293de3836 | 170 | XMEMCPY(sha_half, secret + half - secLen % 2, half); |
ashleymills | 0:714293de3836 | 171 | |
ashleymills | 0:714293de3836 | 172 | XMEMCPY(labelSeed, label, labLen); |
ashleymills | 0:714293de3836 | 173 | XMEMCPY(labelSeed + labLen, seed, seedLen); |
ashleymills | 0:714293de3836 | 174 | |
ashleymills | 0:714293de3836 | 175 | p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen, |
ashleymills | 0:714293de3836 | 176 | md5_mac); |
ashleymills | 0:714293de3836 | 177 | p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen, |
ashleymills | 0:714293de3836 | 178 | sha_mac); |
ashleymills | 0:714293de3836 | 179 | get_xor(digest, digLen, md5_result, sha_result); |
ashleymills | 0:714293de3836 | 180 | } |
ashleymills | 0:714293de3836 | 181 | |
ashleymills | 0:714293de3836 | 182 | #endif |
ashleymills | 0:714293de3836 | 183 | |
ashleymills | 0:714293de3836 | 184 | |
ashleymills | 0:714293de3836 | 185 | /* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack |
ashleymills | 0:714293de3836 | 186 | use */ |
ashleymills | 0:714293de3836 | 187 | static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, |
ashleymills | 0:714293de3836 | 188 | const byte* label, word32 labLen, const byte* seed, word32 seedLen, |
ashleymills | 0:714293de3836 | 189 | int useAtLeastSha256, int hash_type) |
ashleymills | 0:714293de3836 | 190 | { |
ashleymills | 0:714293de3836 | 191 | if (useAtLeastSha256) { |
ashleymills | 0:714293de3836 | 192 | byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */ |
ashleymills | 0:714293de3836 | 193 | |
ashleymills | 0:714293de3836 | 194 | if (labLen + seedLen > MAX_PRF_LABSEED) |
ashleymills | 0:714293de3836 | 195 | return; |
ashleymills | 0:714293de3836 | 196 | |
ashleymills | 0:714293de3836 | 197 | XMEMCPY(labelSeed, label, labLen); |
ashleymills | 0:714293de3836 | 198 | XMEMCPY(labelSeed + labLen, seed, seedLen); |
ashleymills | 0:714293de3836 | 199 | |
ashleymills | 0:714293de3836 | 200 | /* If a cipher suite wants an algorithm better than sha256, it |
ashleymills | 0:714293de3836 | 201 | * should use better. */ |
ashleymills | 0:714293de3836 | 202 | if (hash_type < sha256_mac) |
ashleymills | 0:714293de3836 | 203 | hash_type = sha256_mac; |
ashleymills | 0:714293de3836 | 204 | p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen, |
ashleymills | 0:714293de3836 | 205 | hash_type); |
ashleymills | 0:714293de3836 | 206 | } |
ashleymills | 0:714293de3836 | 207 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 208 | else |
ashleymills | 0:714293de3836 | 209 | doPRF(digest, digLen, secret, secLen, label, labLen, seed, seedLen); |
ashleymills | 0:714293de3836 | 210 | #endif |
ashleymills | 0:714293de3836 | 211 | } |
ashleymills | 0:714293de3836 | 212 | |
ashleymills | 0:714293de3836 | 213 | |
ashleymills | 0:714293de3836 | 214 | #ifdef CYASSL_SHA384 |
ashleymills | 0:714293de3836 | 215 | #define HSHASH_SZ SHA384_DIGEST_SIZE |
ashleymills | 0:714293de3836 | 216 | #else |
ashleymills | 0:714293de3836 | 217 | #define HSHASH_SZ FINISHED_SZ |
ashleymills | 0:714293de3836 | 218 | #endif |
ashleymills | 0:714293de3836 | 219 | |
ashleymills | 0:714293de3836 | 220 | |
ashleymills | 0:714293de3836 | 221 | void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender) |
ashleymills | 0:714293de3836 | 222 | { |
ashleymills | 0:714293de3836 | 223 | const byte* side; |
ashleymills | 0:714293de3836 | 224 | byte handshake_hash[HSHASH_SZ]; |
ashleymills | 0:714293de3836 | 225 | word32 hashSz = FINISHED_SZ; |
ashleymills | 0:714293de3836 | 226 | |
ashleymills | 0:714293de3836 | 227 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 228 | Md5Final(&ssl->hashMd5, handshake_hash); |
ashleymills | 0:714293de3836 | 229 | ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]); |
ashleymills | 0:714293de3836 | 230 | #endif |
ashleymills | 0:714293de3836 | 231 | |
ashleymills | 0:714293de3836 | 232 | if (IsAtLeastTLSv1_2(ssl)) { |
ashleymills | 0:714293de3836 | 233 | #ifndef NO_SHA256 |
ashleymills | 0:714293de3836 | 234 | if (ssl->specs.mac_algorithm <= sha256_mac) { |
ashleymills | 0:714293de3836 | 235 | Sha256Final(&ssl->hashSha256, handshake_hash); |
ashleymills | 0:714293de3836 | 236 | hashSz = SHA256_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 237 | } |
ashleymills | 0:714293de3836 | 238 | #endif |
ashleymills | 0:714293de3836 | 239 | #ifdef CYASSL_SHA384 |
ashleymills | 0:714293de3836 | 240 | if (ssl->specs.mac_algorithm == sha384_mac) { |
ashleymills | 0:714293de3836 | 241 | Sha384Final(&ssl->hashSha384, handshake_hash); |
ashleymills | 0:714293de3836 | 242 | hashSz = SHA384_DIGEST_SIZE; |
ashleymills | 0:714293de3836 | 243 | } |
ashleymills | 0:714293de3836 | 244 | #endif |
ashleymills | 0:714293de3836 | 245 | } |
ashleymills | 0:714293de3836 | 246 | |
ashleymills | 0:714293de3836 | 247 | if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) |
ashleymills | 0:714293de3836 | 248 | side = tls_client; |
ashleymills | 0:714293de3836 | 249 | else |
ashleymills | 0:714293de3836 | 250 | side = tls_server; |
ashleymills | 0:714293de3836 | 251 | |
ashleymills | 0:714293de3836 | 252 | PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, |
ashleymills | 0:714293de3836 | 253 | side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), |
ashleymills | 0:714293de3836 | 254 | ssl->specs.mac_algorithm); |
ashleymills | 0:714293de3836 | 255 | } |
ashleymills | 0:714293de3836 | 256 | |
ashleymills | 0:714293de3836 | 257 | |
ashleymills | 0:714293de3836 | 258 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 259 | |
ashleymills | 0:714293de3836 | 260 | ProtocolVersion MakeTLSv1(void) |
ashleymills | 0:714293de3836 | 261 | { |
ashleymills | 0:714293de3836 | 262 | ProtocolVersion pv; |
ashleymills | 0:714293de3836 | 263 | pv.major = SSLv3_MAJOR; |
ashleymills | 0:714293de3836 | 264 | pv.minor = TLSv1_MINOR; |
ashleymills | 0:714293de3836 | 265 | |
ashleymills | 0:714293de3836 | 266 | return pv; |
ashleymills | 0:714293de3836 | 267 | } |
ashleymills | 0:714293de3836 | 268 | |
ashleymills | 0:714293de3836 | 269 | |
ashleymills | 0:714293de3836 | 270 | ProtocolVersion MakeTLSv1_1(void) |
ashleymills | 0:714293de3836 | 271 | { |
ashleymills | 0:714293de3836 | 272 | ProtocolVersion pv; |
ashleymills | 0:714293de3836 | 273 | pv.major = SSLv3_MAJOR; |
ashleymills | 0:714293de3836 | 274 | pv.minor = TLSv1_1_MINOR; |
ashleymills | 0:714293de3836 | 275 | |
ashleymills | 0:714293de3836 | 276 | return pv; |
ashleymills | 0:714293de3836 | 277 | } |
ashleymills | 0:714293de3836 | 278 | |
ashleymills | 0:714293de3836 | 279 | #endif |
ashleymills | 0:714293de3836 | 280 | |
ashleymills | 0:714293de3836 | 281 | |
ashleymills | 0:714293de3836 | 282 | ProtocolVersion MakeTLSv1_2(void) |
ashleymills | 0:714293de3836 | 283 | { |
ashleymills | 0:714293de3836 | 284 | ProtocolVersion pv; |
ashleymills | 0:714293de3836 | 285 | pv.major = SSLv3_MAJOR; |
ashleymills | 0:714293de3836 | 286 | pv.minor = TLSv1_2_MINOR; |
ashleymills | 0:714293de3836 | 287 | |
ashleymills | 0:714293de3836 | 288 | return pv; |
ashleymills | 0:714293de3836 | 289 | } |
ashleymills | 0:714293de3836 | 290 | |
ashleymills | 0:714293de3836 | 291 | |
ashleymills | 0:714293de3836 | 292 | static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret"; |
ashleymills | 0:714293de3836 | 293 | static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion"; |
ashleymills | 0:714293de3836 | 294 | |
ashleymills | 0:714293de3836 | 295 | |
ashleymills | 0:714293de3836 | 296 | int DeriveTlsKeys(CYASSL* ssl) |
ashleymills | 0:714293de3836 | 297 | { |
ashleymills | 0:714293de3836 | 298 | int length = 2 * ssl->specs.hash_size + |
ashleymills | 0:714293de3836 | 299 | 2 * ssl->specs.key_size + |
ashleymills | 0:714293de3836 | 300 | 2 * ssl->specs.iv_size; |
ashleymills | 0:714293de3836 | 301 | byte seed[SEED_LEN]; |
ashleymills | 0:714293de3836 | 302 | byte key_data[MAX_PRF_DIG]; |
ashleymills | 0:714293de3836 | 303 | |
ashleymills | 0:714293de3836 | 304 | XMEMCPY(seed, ssl->arrays->serverRandom, RAN_LEN); |
ashleymills | 0:714293de3836 | 305 | XMEMCPY(&seed[RAN_LEN], ssl->arrays->clientRandom, RAN_LEN); |
ashleymills | 0:714293de3836 | 306 | |
ashleymills | 0:714293de3836 | 307 | PRF(key_data, length, ssl->arrays->masterSecret, SECRET_LEN, key_label, |
ashleymills | 0:714293de3836 | 308 | KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), |
ashleymills | 0:714293de3836 | 309 | ssl->specs.mac_algorithm); |
ashleymills | 0:714293de3836 | 310 | |
ashleymills | 0:714293de3836 | 311 | return StoreKeys(ssl, key_data); |
ashleymills | 0:714293de3836 | 312 | } |
ashleymills | 0:714293de3836 | 313 | |
ashleymills | 0:714293de3836 | 314 | |
ashleymills | 0:714293de3836 | 315 | int MakeTlsMasterSecret(CYASSL* ssl) |
ashleymills | 0:714293de3836 | 316 | { |
ashleymills | 0:714293de3836 | 317 | byte seed[SEED_LEN]; |
ashleymills | 0:714293de3836 | 318 | |
ashleymills | 0:714293de3836 | 319 | XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); |
ashleymills | 0:714293de3836 | 320 | XMEMCPY(&seed[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN); |
ashleymills | 0:714293de3836 | 321 | |
ashleymills | 0:714293de3836 | 322 | PRF(ssl->arrays->masterSecret, SECRET_LEN, |
ashleymills | 0:714293de3836 | 323 | ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, |
ashleymills | 0:714293de3836 | 324 | master_label, MASTER_LABEL_SZ, |
ashleymills | 0:714293de3836 | 325 | seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); |
ashleymills | 0:714293de3836 | 326 | |
ashleymills | 0:714293de3836 | 327 | #ifdef SHOW_SECRETS |
ashleymills | 0:714293de3836 | 328 | { |
ashleymills | 0:714293de3836 | 329 | int i; |
ashleymills | 0:714293de3836 | 330 | printf("master secret: "); |
ashleymills | 0:714293de3836 | 331 | for (i = 0; i < SECRET_LEN; i++) |
ashleymills | 0:714293de3836 | 332 | printf("%02x", ssl->arrays->masterSecret[i]); |
ashleymills | 0:714293de3836 | 333 | printf("\n"); |
ashleymills | 0:714293de3836 | 334 | } |
ashleymills | 0:714293de3836 | 335 | #endif |
ashleymills | 0:714293de3836 | 336 | |
ashleymills | 0:714293de3836 | 337 | return DeriveTlsKeys(ssl); |
ashleymills | 0:714293de3836 | 338 | } |
ashleymills | 0:714293de3836 | 339 | |
ashleymills | 0:714293de3836 | 340 | |
ashleymills | 0:714293de3836 | 341 | /* Used by EAP-TLS and EAP-TTLS to derive keying material from |
ashleymills | 0:714293de3836 | 342 | * the master_secret. */ |
ashleymills | 0:714293de3836 | 343 | int CyaSSL_make_eap_keys(CYASSL* ssl, void* msk, unsigned int len, |
ashleymills | 0:714293de3836 | 344 | const char* label) |
ashleymills | 0:714293de3836 | 345 | { |
ashleymills | 0:714293de3836 | 346 | byte seed[SEED_LEN]; |
ashleymills | 0:714293de3836 | 347 | |
ashleymills | 0:714293de3836 | 348 | /* |
ashleymills | 0:714293de3836 | 349 | * As per RFC-5281, the order of the client and server randoms is reversed |
ashleymills | 0:714293de3836 | 350 | * from that used by the TLS protocol to derive keys. |
ashleymills | 0:714293de3836 | 351 | */ |
ashleymills | 0:714293de3836 | 352 | XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); |
ashleymills | 0:714293de3836 | 353 | XMEMCPY(&seed[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN); |
ashleymills | 0:714293de3836 | 354 | |
ashleymills | 0:714293de3836 | 355 | PRF((byte*)msk, len, |
ashleymills | 0:714293de3836 | 356 | ssl->arrays->masterSecret, SECRET_LEN, |
ashleymills | 0:714293de3836 | 357 | (const byte *)label, (word32)strlen(label), |
ashleymills | 0:714293de3836 | 358 | seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); |
ashleymills | 0:714293de3836 | 359 | |
ashleymills | 0:714293de3836 | 360 | return 0; |
ashleymills | 0:714293de3836 | 361 | } |
ashleymills | 0:714293de3836 | 362 | |
ashleymills | 0:714293de3836 | 363 | |
ashleymills | 0:714293de3836 | 364 | /*** next for static INLINE s copied from cyassl_int.c ***/ |
ashleymills | 0:714293de3836 | 365 | |
ashleymills | 0:714293de3836 | 366 | /* convert 16 bit integer to opaque */ |
ashleymills | 0:714293de3836 | 367 | static INLINE void c16toa(word16 u16, byte* c) |
ashleymills | 0:714293de3836 | 368 | { |
ashleymills | 0:714293de3836 | 369 | c[0] = (u16 >> 8) & 0xff; |
ashleymills | 0:714293de3836 | 370 | c[1] = u16 & 0xff; |
ashleymills | 0:714293de3836 | 371 | } |
ashleymills | 0:714293de3836 | 372 | |
ashleymills | 0:714293de3836 | 373 | /* convert opaque to 16 bit integer */ |
ashleymills | 0:714293de3836 | 374 | static INLINE void ato16(const byte* c, word16* u16) |
ashleymills | 0:714293de3836 | 375 | { |
ashleymills | 0:714293de3836 | 376 | *u16 = (c[0] << 8) | (c[1]); |
ashleymills | 0:714293de3836 | 377 | } |
ashleymills | 0:714293de3836 | 378 | |
ashleymills | 0:714293de3836 | 379 | |
ashleymills | 0:714293de3836 | 380 | /* convert 32 bit integer to opaque */ |
ashleymills | 0:714293de3836 | 381 | static INLINE void c32toa(word32 u32, byte* c) |
ashleymills | 0:714293de3836 | 382 | { |
ashleymills | 0:714293de3836 | 383 | c[0] = (u32 >> 24) & 0xff; |
ashleymills | 0:714293de3836 | 384 | c[1] = (u32 >> 16) & 0xff; |
ashleymills | 0:714293de3836 | 385 | c[2] = (u32 >> 8) & 0xff; |
ashleymills | 0:714293de3836 | 386 | c[3] = u32 & 0xff; |
ashleymills | 0:714293de3836 | 387 | } |
ashleymills | 0:714293de3836 | 388 | |
ashleymills | 0:714293de3836 | 389 | |
ashleymills | 0:714293de3836 | 390 | static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify) |
ashleymills | 0:714293de3836 | 391 | { |
ashleymills | 0:714293de3836 | 392 | #ifdef CYASSL_DTLS |
ashleymills | 0:714293de3836 | 393 | if (ssl->options.dtls) { |
ashleymills | 0:714293de3836 | 394 | if (verify) |
ashleymills | 0:714293de3836 | 395 | return ssl->keys.dtls_peer_sequence_number; /* explicit from peer */ |
ashleymills | 0:714293de3836 | 396 | else |
ashleymills | 0:714293de3836 | 397 | return ssl->keys.dtls_sequence_number - 1; /* already incremented */ |
ashleymills | 0:714293de3836 | 398 | } |
ashleymills | 0:714293de3836 | 399 | #endif |
ashleymills | 0:714293de3836 | 400 | if (verify) |
ashleymills | 0:714293de3836 | 401 | return ssl->keys.peer_sequence_number++; |
ashleymills | 0:714293de3836 | 402 | else |
ashleymills | 0:714293de3836 | 403 | return ssl->keys.sequence_number++; |
ashleymills | 0:714293de3836 | 404 | } |
ashleymills | 0:714293de3836 | 405 | |
ashleymills | 0:714293de3836 | 406 | |
ashleymills | 0:714293de3836 | 407 | #ifdef CYASSL_DTLS |
ashleymills | 0:714293de3836 | 408 | |
ashleymills | 0:714293de3836 | 409 | static INLINE word32 GetEpoch(CYASSL* ssl, int verify) |
ashleymills | 0:714293de3836 | 410 | { |
ashleymills | 0:714293de3836 | 411 | if (verify) |
ashleymills | 0:714293de3836 | 412 | return ssl->keys.dtls_peer_epoch; |
ashleymills | 0:714293de3836 | 413 | else |
ashleymills | 0:714293de3836 | 414 | return ssl->keys.dtls_epoch; |
ashleymills | 0:714293de3836 | 415 | } |
ashleymills | 0:714293de3836 | 416 | |
ashleymills | 0:714293de3836 | 417 | #endif /* CYASSL_DTLS */ |
ashleymills | 0:714293de3836 | 418 | |
ashleymills | 0:714293de3836 | 419 | |
ashleymills | 0:714293de3836 | 420 | static INLINE const byte* GetMacSecret(CYASSL* ssl, int verify) |
ashleymills | 0:714293de3836 | 421 | { |
ashleymills | 0:714293de3836 | 422 | if ( (ssl->options.side == CLIENT_END && !verify) || |
ashleymills | 0:714293de3836 | 423 | (ssl->options.side == SERVER_END && verify) ) |
ashleymills | 0:714293de3836 | 424 | return ssl->keys.client_write_MAC_secret; |
ashleymills | 0:714293de3836 | 425 | else |
ashleymills | 0:714293de3836 | 426 | return ssl->keys.server_write_MAC_secret; |
ashleymills | 0:714293de3836 | 427 | } |
ashleymills | 0:714293de3836 | 428 | |
ashleymills | 0:714293de3836 | 429 | /*** end copy ***/ |
ashleymills | 0:714293de3836 | 430 | |
ashleymills | 0:714293de3836 | 431 | |
ashleymills | 0:714293de3836 | 432 | /* TLS type HMAC */ |
ashleymills | 0:714293de3836 | 433 | void TLS_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, |
ashleymills | 0:714293de3836 | 434 | int content, int verify) |
ashleymills | 0:714293de3836 | 435 | { |
ashleymills | 0:714293de3836 | 436 | Hmac hmac; |
ashleymills | 0:714293de3836 | 437 | byte seq[SEQ_SZ]; |
ashleymills | 0:714293de3836 | 438 | byte length[LENGTH_SZ]; |
ashleymills | 0:714293de3836 | 439 | byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */ |
ashleymills | 0:714293de3836 | 440 | int type; |
ashleymills | 0:714293de3836 | 441 | |
ashleymills | 0:714293de3836 | 442 | XMEMSET(seq, 0, SEQ_SZ); |
ashleymills | 0:714293de3836 | 443 | c16toa((word16)sz, length); |
ashleymills | 0:714293de3836 | 444 | #ifdef CYASSL_DTLS |
ashleymills | 0:714293de3836 | 445 | if (ssl->options.dtls) |
ashleymills | 0:714293de3836 | 446 | c16toa((word16)GetEpoch(ssl, verify), seq); |
ashleymills | 0:714293de3836 | 447 | #endif |
ashleymills | 0:714293de3836 | 448 | c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]); |
ashleymills | 0:714293de3836 | 449 | |
ashleymills | 0:714293de3836 | 450 | switch (ssl->specs.mac_algorithm) { |
ashleymills | 0:714293de3836 | 451 | #ifndef NO_MD5 |
ashleymills | 0:714293de3836 | 452 | case md5_mac: |
ashleymills | 0:714293de3836 | 453 | { |
ashleymills | 0:714293de3836 | 454 | type = MD5; |
ashleymills | 0:714293de3836 | 455 | } |
ashleymills | 0:714293de3836 | 456 | break; |
ashleymills | 0:714293de3836 | 457 | #endif |
ashleymills | 0:714293de3836 | 458 | #ifndef NO_SHA256 |
ashleymills | 0:714293de3836 | 459 | case sha256_mac: |
ashleymills | 0:714293de3836 | 460 | { |
ashleymills | 0:714293de3836 | 461 | type = SHA256; |
ashleymills | 0:714293de3836 | 462 | } |
ashleymills | 0:714293de3836 | 463 | break; |
ashleymills | 0:714293de3836 | 464 | #endif |
ashleymills | 0:714293de3836 | 465 | #ifdef CYASSL_SHA384 |
ashleymills | 0:714293de3836 | 466 | case sha384_mac: |
ashleymills | 0:714293de3836 | 467 | { |
ashleymills | 0:714293de3836 | 468 | type = SHA384; |
ashleymills | 0:714293de3836 | 469 | } |
ashleymills | 0:714293de3836 | 470 | break; |
ashleymills | 0:714293de3836 | 471 | #endif |
ashleymills | 0:714293de3836 | 472 | #ifndef NO_SHA |
ashleymills | 0:714293de3836 | 473 | case sha_mac: |
ashleymills | 0:714293de3836 | 474 | default: |
ashleymills | 0:714293de3836 | 475 | { |
ashleymills | 0:714293de3836 | 476 | type = SHA; |
ashleymills | 0:714293de3836 | 477 | } |
ashleymills | 0:714293de3836 | 478 | break; |
ashleymills | 0:714293de3836 | 479 | #endif |
ashleymills | 0:714293de3836 | 480 | } |
ashleymills | 0:714293de3836 | 481 | HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size); |
ashleymills | 0:714293de3836 | 482 | |
ashleymills | 0:714293de3836 | 483 | HmacUpdate(&hmac, seq, SEQ_SZ); /* seq_num */ |
ashleymills | 0:714293de3836 | 484 | inner[0] = (byte)content; /* type */ |
ashleymills | 0:714293de3836 | 485 | inner[ENUM_LEN] = ssl->version.major; |
ashleymills | 0:714293de3836 | 486 | inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor; /* version */ |
ashleymills | 0:714293de3836 | 487 | XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ); /* length */ |
ashleymills | 0:714293de3836 | 488 | HmacUpdate(&hmac, inner, sizeof(inner)); |
ashleymills | 0:714293de3836 | 489 | HmacUpdate(&hmac, in, sz); /* content */ |
ashleymills | 0:714293de3836 | 490 | HmacFinal(&hmac, digest); |
ashleymills | 0:714293de3836 | 491 | } |
ashleymills | 0:714293de3836 | 492 | |
ashleymills | 0:714293de3836 | 493 | #ifdef HAVE_TLS_EXTENSIONS |
ashleymills | 0:714293de3836 | 494 | |
ashleymills | 0:714293de3836 | 495 | static int TLSX_Append(TLSX** list, TLSX_Type type) |
ashleymills | 0:714293de3836 | 496 | { |
ashleymills | 0:714293de3836 | 497 | TLSX* extension; |
ashleymills | 0:714293de3836 | 498 | |
ashleymills | 0:714293de3836 | 499 | if (list == NULL) /* won't check type since this function is static */ |
ashleymills | 0:714293de3836 | 500 | return BAD_FUNC_ARG; |
ashleymills | 0:714293de3836 | 501 | |
ashleymills | 0:714293de3836 | 502 | if ((extension = XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX)) == NULL) |
ashleymills | 0:714293de3836 | 503 | return MEMORY_E; |
ashleymills | 0:714293de3836 | 504 | |
ashleymills | 0:714293de3836 | 505 | extension->type = type; |
ashleymills | 0:714293de3836 | 506 | extension->data = NULL; |
ashleymills | 0:714293de3836 | 507 | extension->resp = 0; |
ashleymills | 0:714293de3836 | 508 | extension->next = *list; |
ashleymills | 0:714293de3836 | 509 | *list = extension; |
ashleymills | 0:714293de3836 | 510 | |
ashleymills | 0:714293de3836 | 511 | return 0; |
ashleymills | 0:714293de3836 | 512 | } |
ashleymills | 0:714293de3836 | 513 | |
ashleymills | 0:714293de3836 | 514 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 515 | |
ashleymills | 0:714293de3836 | 516 | static void TLSX_SetResponse(CYASSL* ssl, TLSX_Type type) |
ashleymills | 0:714293de3836 | 517 | { |
ashleymills | 0:714293de3836 | 518 | TLSX *ext = TLSX_Find(ssl->extensions, type); |
ashleymills | 0:714293de3836 | 519 | |
ashleymills | 0:714293de3836 | 520 | if (ext) |
ashleymills | 0:714293de3836 | 521 | ext->resp = 1; |
ashleymills | 0:714293de3836 | 522 | } |
ashleymills | 0:714293de3836 | 523 | |
ashleymills | 0:714293de3836 | 524 | #endif |
ashleymills | 0:714293de3836 | 525 | |
ashleymills | 0:714293de3836 | 526 | /* SNI - Server Name Indication */ |
ashleymills | 0:714293de3836 | 527 | |
ashleymills | 0:714293de3836 | 528 | #ifdef HAVE_SNI |
ashleymills | 0:714293de3836 | 529 | |
ashleymills | 0:714293de3836 | 530 | static void TLSX_SNI_Free(SNI* sni) |
ashleymills | 0:714293de3836 | 531 | { |
ashleymills | 0:714293de3836 | 532 | if (sni) { |
ashleymills | 0:714293de3836 | 533 | switch (sni->type) { |
ashleymills | 0:714293de3836 | 534 | case CYASSL_SNI_HOST_NAME: |
ashleymills | 0:714293de3836 | 535 | XFREE(sni->data.host_name, 0, DYNAMIC_TYPE_TLSX); |
ashleymills | 0:714293de3836 | 536 | break; |
ashleymills | 0:714293de3836 | 537 | } |
ashleymills | 0:714293de3836 | 538 | |
ashleymills | 0:714293de3836 | 539 | XFREE(sni, 0, DYNAMIC_TYPE_TLSX); |
ashleymills | 0:714293de3836 | 540 | } |
ashleymills | 0:714293de3836 | 541 | } |
ashleymills | 0:714293de3836 | 542 | |
ashleymills | 0:714293de3836 | 543 | static void TLSX_SNI_FreeAll(SNI* list) |
ashleymills | 0:714293de3836 | 544 | { |
ashleymills | 0:714293de3836 | 545 | SNI* sni; |
ashleymills | 0:714293de3836 | 546 | |
ashleymills | 0:714293de3836 | 547 | while ((sni = list)) { |
ashleymills | 0:714293de3836 | 548 | list = sni->next; |
ashleymills | 0:714293de3836 | 549 | TLSX_SNI_Free(sni); |
ashleymills | 0:714293de3836 | 550 | } |
ashleymills | 0:714293de3836 | 551 | } |
ashleymills | 0:714293de3836 | 552 | |
ashleymills | 0:714293de3836 | 553 | static int TLSX_SNI_Append(SNI** list, byte type, const void* data, word16 size) |
ashleymills | 0:714293de3836 | 554 | { |
ashleymills | 0:714293de3836 | 555 | SNI* sni; |
ashleymills | 0:714293de3836 | 556 | |
ashleymills | 0:714293de3836 | 557 | if (list == NULL) |
ashleymills | 0:714293de3836 | 558 | return BAD_FUNC_ARG; |
ashleymills | 0:714293de3836 | 559 | |
ashleymills | 0:714293de3836 | 560 | if ((sni = XMALLOC(sizeof(SNI), 0, DYNAMIC_TYPE_TLSX)) == NULL) |
ashleymills | 0:714293de3836 | 561 | return MEMORY_E; |
ashleymills | 0:714293de3836 | 562 | |
ashleymills | 0:714293de3836 | 563 | switch (type) { |
ashleymills | 0:714293de3836 | 564 | case CYASSL_SNI_HOST_NAME: { |
ashleymills | 0:714293de3836 | 565 | sni->data.host_name = XMALLOC(size + 1, 0, DYNAMIC_TYPE_TLSX); |
ashleymills | 0:714293de3836 | 566 | |
ashleymills | 0:714293de3836 | 567 | if (sni->data.host_name) { |
ashleymills | 0:714293de3836 | 568 | XSTRNCPY(sni->data.host_name, (const char*) data, size); |
ashleymills | 0:714293de3836 | 569 | sni->data.host_name[size] = 0; |
ashleymills | 0:714293de3836 | 570 | } else { |
ashleymills | 0:714293de3836 | 571 | XFREE(sni, 0, DYNAMIC_TYPE_TLSX); |
ashleymills | 0:714293de3836 | 572 | return MEMORY_E; |
ashleymills | 0:714293de3836 | 573 | } |
ashleymills | 0:714293de3836 | 574 | } |
ashleymills | 0:714293de3836 | 575 | break; |
ashleymills | 0:714293de3836 | 576 | |
ashleymills | 0:714293de3836 | 577 | default: /* invalid type */ |
ashleymills | 0:714293de3836 | 578 | XFREE(sni, 0, DYNAMIC_TYPE_TLSX); |
ashleymills | 0:714293de3836 | 579 | return BAD_FUNC_ARG; |
ashleymills | 0:714293de3836 | 580 | break; |
ashleymills | 0:714293de3836 | 581 | } |
ashleymills | 0:714293de3836 | 582 | |
ashleymills | 0:714293de3836 | 583 | sni->type = type; |
ashleymills | 0:714293de3836 | 584 | sni->next = *list; |
ashleymills | 0:714293de3836 | 585 | |
ashleymills | 0:714293de3836 | 586 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 587 | sni->options = 0; |
ashleymills | 0:714293de3836 | 588 | sni->matched = 0; |
ashleymills | 0:714293de3836 | 589 | #endif |
ashleymills | 0:714293de3836 | 590 | |
ashleymills | 0:714293de3836 | 591 | *list = sni; |
ashleymills | 0:714293de3836 | 592 | |
ashleymills | 0:714293de3836 | 593 | return 0; |
ashleymills | 0:714293de3836 | 594 | } |
ashleymills | 0:714293de3836 | 595 | |
ashleymills | 0:714293de3836 | 596 | static word16 TLSX_SNI_GetSize(SNI* list) |
ashleymills | 0:714293de3836 | 597 | { |
ashleymills | 0:714293de3836 | 598 | SNI* sni; |
ashleymills | 0:714293de3836 | 599 | word16 length = OPAQUE16_LEN; /* list length */ |
ashleymills | 0:714293de3836 | 600 | |
ashleymills | 0:714293de3836 | 601 | while ((sni = list)) { |
ashleymills | 0:714293de3836 | 602 | list = sni->next; |
ashleymills | 0:714293de3836 | 603 | |
ashleymills | 0:714293de3836 | 604 | length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */ |
ashleymills | 0:714293de3836 | 605 | |
ashleymills | 0:714293de3836 | 606 | switch (sni->type) { |
ashleymills | 0:714293de3836 | 607 | case CYASSL_SNI_HOST_NAME: |
ashleymills | 0:714293de3836 | 608 | length += XSTRLEN((char*) sni->data.host_name); |
ashleymills | 0:714293de3836 | 609 | break; |
ashleymills | 0:714293de3836 | 610 | } |
ashleymills | 0:714293de3836 | 611 | } |
ashleymills | 0:714293de3836 | 612 | |
ashleymills | 0:714293de3836 | 613 | return length; |
ashleymills | 0:714293de3836 | 614 | } |
ashleymills | 0:714293de3836 | 615 | |
ashleymills | 0:714293de3836 | 616 | static word16 TLSX_SNI_Write(SNI* list, byte* output) |
ashleymills | 0:714293de3836 | 617 | { |
ashleymills | 0:714293de3836 | 618 | SNI* sni; |
ashleymills | 0:714293de3836 | 619 | word16 length = 0; |
ashleymills | 0:714293de3836 | 620 | word16 offset = OPAQUE16_LEN; /* list length offset */ |
ashleymills | 0:714293de3836 | 621 | |
ashleymills | 0:714293de3836 | 622 | while ((sni = list)) { |
ashleymills | 0:714293de3836 | 623 | list = sni->next; |
ashleymills | 0:714293de3836 | 624 | |
ashleymills | 0:714293de3836 | 625 | output[offset++] = sni->type; /* sni type */ |
ashleymills | 0:714293de3836 | 626 | |
ashleymills | 0:714293de3836 | 627 | switch (sni->type) { |
ashleymills | 0:714293de3836 | 628 | case CYASSL_SNI_HOST_NAME: |
ashleymills | 0:714293de3836 | 629 | length = XSTRLEN((char*) sni->data.host_name); |
ashleymills | 0:714293de3836 | 630 | |
ashleymills | 0:714293de3836 | 631 | c16toa(length, output + offset); /* sni length */ |
ashleymills | 0:714293de3836 | 632 | offset += OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 633 | |
ashleymills | 0:714293de3836 | 634 | XMEMCPY(output + offset, sni->data.host_name, length); |
ashleymills | 0:714293de3836 | 635 | |
ashleymills | 0:714293de3836 | 636 | offset += length; |
ashleymills | 0:714293de3836 | 637 | break; |
ashleymills | 0:714293de3836 | 638 | } |
ashleymills | 0:714293de3836 | 639 | } |
ashleymills | 0:714293de3836 | 640 | |
ashleymills | 0:714293de3836 | 641 | c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ |
ashleymills | 0:714293de3836 | 642 | |
ashleymills | 0:714293de3836 | 643 | return offset; |
ashleymills | 0:714293de3836 | 644 | } |
ashleymills | 0:714293de3836 | 645 | |
ashleymills | 0:714293de3836 | 646 | static SNI* TLSX_SNI_Find(SNI *list, byte type) |
ashleymills | 0:714293de3836 | 647 | { |
ashleymills | 0:714293de3836 | 648 | SNI *sni = list; |
ashleymills | 0:714293de3836 | 649 | |
ashleymills | 0:714293de3836 | 650 | while (sni && sni->type != type) |
ashleymills | 0:714293de3836 | 651 | sni = sni->next; |
ashleymills | 0:714293de3836 | 652 | |
ashleymills | 0:714293de3836 | 653 | return sni; |
ashleymills | 0:714293de3836 | 654 | } |
ashleymills | 0:714293de3836 | 655 | |
ashleymills | 0:714293de3836 | 656 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 657 | static void TLSX_SNI_SetMatched(TLSX* extensions, byte type) |
ashleymills | 0:714293de3836 | 658 | { |
ashleymills | 0:714293de3836 | 659 | TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); |
ashleymills | 0:714293de3836 | 660 | SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); |
ashleymills | 0:714293de3836 | 661 | |
ashleymills | 0:714293de3836 | 662 | if (sni) { |
ashleymills | 0:714293de3836 | 663 | sni->matched = 1; |
ashleymills | 0:714293de3836 | 664 | CYASSL_MSG("SNI did match!"); |
ashleymills | 0:714293de3836 | 665 | } |
ashleymills | 0:714293de3836 | 666 | } |
ashleymills | 0:714293de3836 | 667 | |
ashleymills | 0:714293de3836 | 668 | byte TLSX_SNI_Matched(TLSX* extensions, byte type) |
ashleymills | 0:714293de3836 | 669 | { |
ashleymills | 0:714293de3836 | 670 | TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); |
ashleymills | 0:714293de3836 | 671 | SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); |
ashleymills | 0:714293de3836 | 672 | |
ashleymills | 0:714293de3836 | 673 | if (sni) |
ashleymills | 0:714293de3836 | 674 | return sni->matched; |
ashleymills | 0:714293de3836 | 675 | |
ashleymills | 0:714293de3836 | 676 | return 0; |
ashleymills | 0:714293de3836 | 677 | } |
ashleymills | 0:714293de3836 | 678 | #endif |
ashleymills | 0:714293de3836 | 679 | |
ashleymills | 0:714293de3836 | 680 | static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length, |
ashleymills | 0:714293de3836 | 681 | byte isRequest) |
ashleymills | 0:714293de3836 | 682 | { |
ashleymills | 0:714293de3836 | 683 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 684 | word16 size = 0; |
ashleymills | 0:714293de3836 | 685 | word16 offset = 0; |
ashleymills | 0:714293de3836 | 686 | #endif |
ashleymills | 0:714293de3836 | 687 | |
ashleymills | 0:714293de3836 | 688 | TLSX *extension = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION); |
ashleymills | 0:714293de3836 | 689 | |
ashleymills | 0:714293de3836 | 690 | if (!extension) |
ashleymills | 0:714293de3836 | 691 | extension = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION); |
ashleymills | 0:714293de3836 | 692 | |
ashleymills | 0:714293de3836 | 693 | if (!extension || !extension->data) { |
ashleymills | 0:714293de3836 | 694 | if (!isRequest) { |
ashleymills | 0:714293de3836 | 695 | CYASSL_MSG("Unexpected SNI response from server"); |
ashleymills | 0:714293de3836 | 696 | } |
ashleymills | 0:714293de3836 | 697 | |
ashleymills | 0:714293de3836 | 698 | return 0; /* not using SNI */ |
ashleymills | 0:714293de3836 | 699 | } |
ashleymills | 0:714293de3836 | 700 | |
ashleymills | 0:714293de3836 | 701 | if (!isRequest) { |
ashleymills | 0:714293de3836 | 702 | if (length) { |
ashleymills | 0:714293de3836 | 703 | CYASSL_MSG("SNI response should be empty!"); |
ashleymills | 0:714293de3836 | 704 | } |
ashleymills | 0:714293de3836 | 705 | |
ashleymills | 0:714293de3836 | 706 | return 0; /* nothing to do */ |
ashleymills | 0:714293de3836 | 707 | } |
ashleymills | 0:714293de3836 | 708 | |
ashleymills | 0:714293de3836 | 709 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 710 | |
ashleymills | 0:714293de3836 | 711 | if (OPAQUE16_LEN > length) |
ashleymills | 0:714293de3836 | 712 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 713 | |
ashleymills | 0:714293de3836 | 714 | ato16(input, &size); |
ashleymills | 0:714293de3836 | 715 | offset += OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 716 | |
ashleymills | 0:714293de3836 | 717 | /* validating sni list length */ |
ashleymills | 0:714293de3836 | 718 | if (length != OPAQUE16_LEN + size) |
ashleymills | 0:714293de3836 | 719 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 720 | |
ashleymills | 0:714293de3836 | 721 | for (size = 0; offset < length; offset += size) { |
ashleymills | 0:714293de3836 | 722 | SNI *sni; |
ashleymills | 0:714293de3836 | 723 | byte type = input[offset++]; |
ashleymills | 0:714293de3836 | 724 | |
ashleymills | 0:714293de3836 | 725 | if (offset + OPAQUE16_LEN > length) |
ashleymills | 0:714293de3836 | 726 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 727 | |
ashleymills | 0:714293de3836 | 728 | ato16(input + offset, &size); |
ashleymills | 0:714293de3836 | 729 | offset += OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 730 | |
ashleymills | 0:714293de3836 | 731 | if (offset + size > length) |
ashleymills | 0:714293de3836 | 732 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 733 | |
ashleymills | 0:714293de3836 | 734 | if (!(sni = TLSX_SNI_Find((SNI *) extension->data, type))) { |
ashleymills | 0:714293de3836 | 735 | continue; /* not using this SNI type */ |
ashleymills | 0:714293de3836 | 736 | } |
ashleymills | 0:714293de3836 | 737 | |
ashleymills | 0:714293de3836 | 738 | switch(type) { |
ashleymills | 0:714293de3836 | 739 | case CYASSL_SNI_HOST_NAME: { |
ashleymills | 0:714293de3836 | 740 | byte matched = (XSTRLEN(sni->data.host_name) == size) |
ashleymills | 0:714293de3836 | 741 | && (XSTRNCMP(sni->data.host_name, |
ashleymills | 0:714293de3836 | 742 | (const char *) input + offset, size) == 0); |
ashleymills | 0:714293de3836 | 743 | |
ashleymills | 0:714293de3836 | 744 | if (matched || sni->options & CYASSL_SNI_ANSWER_ON_MISMATCH) { |
ashleymills | 0:714293de3836 | 745 | int r = TLSX_UseSNI(&ssl->extensions, type, (byte *) "", 0); |
ashleymills | 0:714293de3836 | 746 | |
ashleymills | 0:714293de3836 | 747 | if (r) return r; /* throw error */ |
ashleymills | 0:714293de3836 | 748 | |
ashleymills | 0:714293de3836 | 749 | if (matched) TLSX_SNI_SetMatched(ssl->extensions, type); |
ashleymills | 0:714293de3836 | 750 | } else if (!(sni->options & CYASSL_SNI_CONTINUE_ON_MISMATCH)) { |
ashleymills | 0:714293de3836 | 751 | SendAlert(ssl, alert_fatal, unrecognized_name); |
ashleymills | 0:714293de3836 | 752 | |
ashleymills | 0:714293de3836 | 753 | return UNKNOWN_SNI_HOST_NAME_E; |
ashleymills | 0:714293de3836 | 754 | } |
ashleymills | 0:714293de3836 | 755 | break; |
ashleymills | 0:714293de3836 | 756 | } |
ashleymills | 0:714293de3836 | 757 | } |
ashleymills | 0:714293de3836 | 758 | |
ashleymills | 0:714293de3836 | 759 | TLSX_SetResponse(ssl, SERVER_NAME_INDICATION); |
ashleymills | 0:714293de3836 | 760 | } |
ashleymills | 0:714293de3836 | 761 | |
ashleymills | 0:714293de3836 | 762 | #endif |
ashleymills | 0:714293de3836 | 763 | |
ashleymills | 0:714293de3836 | 764 | return 0; |
ashleymills | 0:714293de3836 | 765 | } |
ashleymills | 0:714293de3836 | 766 | |
ashleymills | 0:714293de3836 | 767 | int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) |
ashleymills | 0:714293de3836 | 768 | { |
ashleymills | 0:714293de3836 | 769 | TLSX* extension = NULL; |
ashleymills | 0:714293de3836 | 770 | SNI* sni = NULL; |
ashleymills | 0:714293de3836 | 771 | int ret = 0; |
ashleymills | 0:714293de3836 | 772 | |
ashleymills | 0:714293de3836 | 773 | if (extensions == NULL || data == NULL) |
ashleymills | 0:714293de3836 | 774 | return BAD_FUNC_ARG; |
ashleymills | 0:714293de3836 | 775 | |
ashleymills | 0:714293de3836 | 776 | if ((ret = TLSX_SNI_Append(&sni, type, data, size)) != 0) |
ashleymills | 0:714293de3836 | 777 | return ret; |
ashleymills | 0:714293de3836 | 778 | |
ashleymills | 0:714293de3836 | 779 | extension = *extensions; |
ashleymills | 0:714293de3836 | 780 | |
ashleymills | 0:714293de3836 | 781 | /* find SNI extension if it already exists. */ |
ashleymills | 0:714293de3836 | 782 | while (extension && extension->type != SERVER_NAME_INDICATION) |
ashleymills | 0:714293de3836 | 783 | extension = extension->next; |
ashleymills | 0:714293de3836 | 784 | |
ashleymills | 0:714293de3836 | 785 | /* push new SNI extension if it doesn't exists. */ |
ashleymills | 0:714293de3836 | 786 | if (!extension) { |
ashleymills | 0:714293de3836 | 787 | if ((ret = TLSX_Append(extensions, SERVER_NAME_INDICATION)) != 0) { |
ashleymills | 0:714293de3836 | 788 | TLSX_SNI_Free(sni); |
ashleymills | 0:714293de3836 | 789 | return ret; |
ashleymills | 0:714293de3836 | 790 | } |
ashleymills | 0:714293de3836 | 791 | |
ashleymills | 0:714293de3836 | 792 | extension = *extensions; |
ashleymills | 0:714293de3836 | 793 | } |
ashleymills | 0:714293de3836 | 794 | |
ashleymills | 0:714293de3836 | 795 | /* push new SNI object to extension data. */ |
ashleymills | 0:714293de3836 | 796 | sni->next = (SNI*) extension->data; |
ashleymills | 0:714293de3836 | 797 | extension->data = (void*) sni; |
ashleymills | 0:714293de3836 | 798 | |
ashleymills | 0:714293de3836 | 799 | /* look for another server name of the same type to remove (replacement) */ |
ashleymills | 0:714293de3836 | 800 | while ((sni = sni->next)) { |
ashleymills | 0:714293de3836 | 801 | if (sni->next && sni->next->type == type) { |
ashleymills | 0:714293de3836 | 802 | SNI *next = sni->next; |
ashleymills | 0:714293de3836 | 803 | |
ashleymills | 0:714293de3836 | 804 | sni->next = next->next; |
ashleymills | 0:714293de3836 | 805 | TLSX_SNI_Free(next); |
ashleymills | 0:714293de3836 | 806 | |
ashleymills | 0:714293de3836 | 807 | break; |
ashleymills | 0:714293de3836 | 808 | } |
ashleymills | 0:714293de3836 | 809 | } |
ashleymills | 0:714293de3836 | 810 | |
ashleymills | 0:714293de3836 | 811 | return 0; |
ashleymills | 0:714293de3836 | 812 | } |
ashleymills | 0:714293de3836 | 813 | |
ashleymills | 0:714293de3836 | 814 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 815 | void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) |
ashleymills | 0:714293de3836 | 816 | { |
ashleymills | 0:714293de3836 | 817 | TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); |
ashleymills | 0:714293de3836 | 818 | SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); |
ashleymills | 0:714293de3836 | 819 | |
ashleymills | 0:714293de3836 | 820 | if (sni) |
ashleymills | 0:714293de3836 | 821 | sni->options = options; |
ashleymills | 0:714293de3836 | 822 | } |
ashleymills | 0:714293de3836 | 823 | #endif |
ashleymills | 0:714293de3836 | 824 | |
ashleymills | 0:714293de3836 | 825 | #define SNI_FREE_ALL TLSX_SNI_FreeAll |
ashleymills | 0:714293de3836 | 826 | #define SNI_GET_SIZE TLSX_SNI_GetSize |
ashleymills | 0:714293de3836 | 827 | #define SNI_WRITE TLSX_SNI_Write |
ashleymills | 0:714293de3836 | 828 | #define SNI_PARSE TLSX_SNI_Parse |
ashleymills | 0:714293de3836 | 829 | |
ashleymills | 0:714293de3836 | 830 | #else |
ashleymills | 0:714293de3836 | 831 | |
ashleymills | 0:714293de3836 | 832 | #define SNI_FREE_ALL(x) |
ashleymills | 0:714293de3836 | 833 | #define SNI_GET_SIZE(x) 0 |
ashleymills | 0:714293de3836 | 834 | #define SNI_WRITE(x) 0 |
ashleymills | 0:714293de3836 | 835 | #define SNI_PARSE(x) 0 |
ashleymills | 0:714293de3836 | 836 | |
ashleymills | 0:714293de3836 | 837 | #endif /* HAVE_SNI */ |
ashleymills | 0:714293de3836 | 838 | |
ashleymills | 0:714293de3836 | 839 | TLSX* TLSX_Find(TLSX* list, TLSX_Type type) |
ashleymills | 0:714293de3836 | 840 | { |
ashleymills | 0:714293de3836 | 841 | TLSX* extension = list; |
ashleymills | 0:714293de3836 | 842 | |
ashleymills | 0:714293de3836 | 843 | while (extension && extension->type != type) |
ashleymills | 0:714293de3836 | 844 | extension = extension->next; |
ashleymills | 0:714293de3836 | 845 | |
ashleymills | 0:714293de3836 | 846 | return extension; |
ashleymills | 0:714293de3836 | 847 | } |
ashleymills | 0:714293de3836 | 848 | |
ashleymills | 0:714293de3836 | 849 | void TLSX_FreeAll(TLSX* list) |
ashleymills | 0:714293de3836 | 850 | { |
ashleymills | 0:714293de3836 | 851 | TLSX* extension; |
ashleymills | 0:714293de3836 | 852 | |
ashleymills | 0:714293de3836 | 853 | while ((extension = list)) { |
ashleymills | 0:714293de3836 | 854 | list = extension->next; |
ashleymills | 0:714293de3836 | 855 | |
ashleymills | 0:714293de3836 | 856 | switch (extension->type) { |
ashleymills | 0:714293de3836 | 857 | case SERVER_NAME_INDICATION: |
ashleymills | 0:714293de3836 | 858 | SNI_FREE_ALL((SNI *) extension->data); |
ashleymills | 0:714293de3836 | 859 | break; |
ashleymills | 0:714293de3836 | 860 | } |
ashleymills | 0:714293de3836 | 861 | |
ashleymills | 0:714293de3836 | 862 | XFREE(extension, 0, DYNAMIC_TYPE_TLSX); |
ashleymills | 0:714293de3836 | 863 | } |
ashleymills | 0:714293de3836 | 864 | } |
ashleymills | 0:714293de3836 | 865 | |
ashleymills | 0:714293de3836 | 866 | #define IS_OFF(semaphore, light) \ |
ashleymills | 0:714293de3836 | 867 | ((semaphore)[(light) / 8] ^ (byte) (0x01 << ((light) % 8))) |
ashleymills | 0:714293de3836 | 868 | |
ashleymills | 0:714293de3836 | 869 | #define TURN_ON(semaphore, light) \ |
ashleymills | 0:714293de3836 | 870 | ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8))) |
ashleymills | 0:714293de3836 | 871 | |
ashleymills | 0:714293de3836 | 872 | static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) |
ashleymills | 0:714293de3836 | 873 | { |
ashleymills | 0:714293de3836 | 874 | TLSX* extension; |
ashleymills | 0:714293de3836 | 875 | word16 length = 0; |
ashleymills | 0:714293de3836 | 876 | |
ashleymills | 0:714293de3836 | 877 | while ((extension = list)) { |
ashleymills | 0:714293de3836 | 878 | list = extension->next; |
ashleymills | 0:714293de3836 | 879 | |
ashleymills | 0:714293de3836 | 880 | if (!isRequest && !extension->resp) |
ashleymills | 0:714293de3836 | 881 | continue; /* skip! */ |
ashleymills | 0:714293de3836 | 882 | |
ashleymills | 0:714293de3836 | 883 | if (IS_OFF(semaphore, extension->type)) { |
ashleymills | 0:714293de3836 | 884 | /* type + data length */ |
ashleymills | 0:714293de3836 | 885 | length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 886 | |
ashleymills | 0:714293de3836 | 887 | switch (extension->type) { |
ashleymills | 0:714293de3836 | 888 | case SERVER_NAME_INDICATION: |
ashleymills | 0:714293de3836 | 889 | if (isRequest) |
ashleymills | 0:714293de3836 | 890 | length += SNI_GET_SIZE((SNI *) extension->data); |
ashleymills | 0:714293de3836 | 891 | break; |
ashleymills | 0:714293de3836 | 892 | } |
ashleymills | 0:714293de3836 | 893 | |
ashleymills | 0:714293de3836 | 894 | TURN_ON(semaphore, extension->type); |
ashleymills | 0:714293de3836 | 895 | } |
ashleymills | 0:714293de3836 | 896 | } |
ashleymills | 0:714293de3836 | 897 | |
ashleymills | 0:714293de3836 | 898 | return length; |
ashleymills | 0:714293de3836 | 899 | } |
ashleymills | 0:714293de3836 | 900 | |
ashleymills | 0:714293de3836 | 901 | static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, |
ashleymills | 0:714293de3836 | 902 | byte isRequest) |
ashleymills | 0:714293de3836 | 903 | { |
ashleymills | 0:714293de3836 | 904 | TLSX* extension; |
ashleymills | 0:714293de3836 | 905 | word16 offset = 0; |
ashleymills | 0:714293de3836 | 906 | word16 length_offset = 0; |
ashleymills | 0:714293de3836 | 907 | |
ashleymills | 0:714293de3836 | 908 | while ((extension = list)) { |
ashleymills | 0:714293de3836 | 909 | list = extension->next; |
ashleymills | 0:714293de3836 | 910 | |
ashleymills | 0:714293de3836 | 911 | if (!isRequest && !extension->resp) |
ashleymills | 0:714293de3836 | 912 | continue; /* skip! */ |
ashleymills | 0:714293de3836 | 913 | |
ashleymills | 0:714293de3836 | 914 | if (IS_OFF(semaphore, extension->type)) { |
ashleymills | 0:714293de3836 | 915 | /* extension type */ |
ashleymills | 0:714293de3836 | 916 | c16toa(extension->type, output + offset); |
ashleymills | 0:714293de3836 | 917 | offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 918 | length_offset = offset; |
ashleymills | 0:714293de3836 | 919 | |
ashleymills | 0:714293de3836 | 920 | /* extension data should be written internally */ |
ashleymills | 0:714293de3836 | 921 | switch (extension->type) { |
ashleymills | 0:714293de3836 | 922 | case SERVER_NAME_INDICATION: |
ashleymills | 0:714293de3836 | 923 | if (isRequest) |
ashleymills | 0:714293de3836 | 924 | offset += SNI_WRITE((SNI *) extension->data, |
ashleymills | 0:714293de3836 | 925 | output + offset); |
ashleymills | 0:714293de3836 | 926 | break; |
ashleymills | 0:714293de3836 | 927 | } |
ashleymills | 0:714293de3836 | 928 | |
ashleymills | 0:714293de3836 | 929 | /* writing extension data length */ |
ashleymills | 0:714293de3836 | 930 | c16toa(offset - length_offset, |
ashleymills | 0:714293de3836 | 931 | output + length_offset - OPAQUE16_LEN); |
ashleymills | 0:714293de3836 | 932 | |
ashleymills | 0:714293de3836 | 933 | TURN_ON(semaphore, extension->type); |
ashleymills | 0:714293de3836 | 934 | } |
ashleymills | 0:714293de3836 | 935 | } |
ashleymills | 0:714293de3836 | 936 | |
ashleymills | 0:714293de3836 | 937 | return offset; |
ashleymills | 0:714293de3836 | 938 | } |
ashleymills | 0:714293de3836 | 939 | |
ashleymills | 0:714293de3836 | 940 | #ifndef NO_CYASSL_CLIENT |
ashleymills | 0:714293de3836 | 941 | |
ashleymills | 0:714293de3836 | 942 | word16 TLSX_GetRequestSize(CYASSL* ssl) |
ashleymills | 0:714293de3836 | 943 | { |
ashleymills | 0:714293de3836 | 944 | word16 length = 0; |
ashleymills | 0:714293de3836 | 945 | |
ashleymills | 0:714293de3836 | 946 | if (ssl && IsTLS(ssl)) { |
ashleymills | 0:714293de3836 | 947 | byte semaphore[16] = {0}; |
ashleymills | 0:714293de3836 | 948 | |
ashleymills | 0:714293de3836 | 949 | if (ssl->extensions) |
ashleymills | 0:714293de3836 | 950 | length += TLSX_GetSize(ssl->extensions, semaphore, 1); |
ashleymills | 0:714293de3836 | 951 | |
ashleymills | 0:714293de3836 | 952 | if (ssl->ctx && ssl->ctx->extensions) |
ashleymills | 0:714293de3836 | 953 | length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1); |
ashleymills | 0:714293de3836 | 954 | |
ashleymills | 0:714293de3836 | 955 | if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) |
ashleymills | 0:714293de3836 | 956 | length += ssl->suites->hashSigAlgoSz + HELLO_EXT_LEN; |
ashleymills | 0:714293de3836 | 957 | } |
ashleymills | 0:714293de3836 | 958 | |
ashleymills | 0:714293de3836 | 959 | if (length) |
ashleymills | 0:714293de3836 | 960 | length += OPAQUE16_LEN; /* for total length storage */ |
ashleymills | 0:714293de3836 | 961 | |
ashleymills | 0:714293de3836 | 962 | return length; |
ashleymills | 0:714293de3836 | 963 | } |
ashleymills | 0:714293de3836 | 964 | |
ashleymills | 0:714293de3836 | 965 | word16 TLSX_WriteRequest(CYASSL* ssl, byte* output) |
ashleymills | 0:714293de3836 | 966 | { |
ashleymills | 0:714293de3836 | 967 | word16 offset = 0; |
ashleymills | 0:714293de3836 | 968 | |
ashleymills | 0:714293de3836 | 969 | if (ssl && IsTLS(ssl) && output) { |
ashleymills | 0:714293de3836 | 970 | byte semaphore[16] = {0}; |
ashleymills | 0:714293de3836 | 971 | |
ashleymills | 0:714293de3836 | 972 | offset += OPAQUE16_LEN; /* extensions length */ |
ashleymills | 0:714293de3836 | 973 | |
ashleymills | 0:714293de3836 | 974 | if (ssl->extensions) |
ashleymills | 0:714293de3836 | 975 | offset += TLSX_Write(ssl->extensions, output + offset, |
ashleymills | 0:714293de3836 | 976 | semaphore, 1); |
ashleymills | 0:714293de3836 | 977 | |
ashleymills | 0:714293de3836 | 978 | if (ssl->ctx && ssl->ctx->extensions) |
ashleymills | 0:714293de3836 | 979 | offset += TLSX_Write(ssl->ctx->extensions, output + offset, |
ashleymills | 0:714293de3836 | 980 | semaphore, 1); |
ashleymills | 0:714293de3836 | 981 | |
ashleymills | 0:714293de3836 | 982 | if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) |
ashleymills | 0:714293de3836 | 983 | { |
ashleymills | 0:714293de3836 | 984 | int i; |
ashleymills | 0:714293de3836 | 985 | /* extension type */ |
ashleymills | 0:714293de3836 | 986 | c16toa(HELLO_EXT_SIG_ALGO, output + offset); |
ashleymills | 0:714293de3836 | 987 | offset += HELLO_EXT_TYPE_SZ; |
ashleymills | 0:714293de3836 | 988 | |
ashleymills | 0:714293de3836 | 989 | /* extension data length */ |
ashleymills | 0:714293de3836 | 990 | c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, output + offset); |
ashleymills | 0:714293de3836 | 991 | offset += OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 992 | |
ashleymills | 0:714293de3836 | 993 | /* sig algos length */ |
ashleymills | 0:714293de3836 | 994 | c16toa(ssl->suites->hashSigAlgoSz, output + offset); |
ashleymills | 0:714293de3836 | 995 | offset += OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 996 | |
ashleymills | 0:714293de3836 | 997 | /* sig algos */ |
ashleymills | 0:714293de3836 | 998 | for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) |
ashleymills | 0:714293de3836 | 999 | output[offset] = ssl->suites->hashSigAlgo[i]; |
ashleymills | 0:714293de3836 | 1000 | } |
ashleymills | 0:714293de3836 | 1001 | |
ashleymills | 0:714293de3836 | 1002 | if (offset > OPAQUE16_LEN) |
ashleymills | 0:714293de3836 | 1003 | c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ |
ashleymills | 0:714293de3836 | 1004 | } |
ashleymills | 0:714293de3836 | 1005 | |
ashleymills | 0:714293de3836 | 1006 | return offset; |
ashleymills | 0:714293de3836 | 1007 | } |
ashleymills | 0:714293de3836 | 1008 | |
ashleymills | 0:714293de3836 | 1009 | #endif /* NO_CYASSL_CLIENT */ |
ashleymills | 0:714293de3836 | 1010 | |
ashleymills | 0:714293de3836 | 1011 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 1012 | |
ashleymills | 0:714293de3836 | 1013 | word16 TLSX_GetResponseSize(CYASSL* ssl) |
ashleymills | 0:714293de3836 | 1014 | { |
ashleymills | 0:714293de3836 | 1015 | word16 length = 0; |
ashleymills | 0:714293de3836 | 1016 | byte semaphore[16] = {0}; |
ashleymills | 0:714293de3836 | 1017 | |
ashleymills | 0:714293de3836 | 1018 | if (ssl && IsTLS(ssl)) |
ashleymills | 0:714293de3836 | 1019 | length += TLSX_GetSize(ssl->extensions, semaphore, 0); |
ashleymills | 0:714293de3836 | 1020 | |
ashleymills | 0:714293de3836 | 1021 | /* All the response data is set at the ssl object only, so no ctx here. */ |
ashleymills | 0:714293de3836 | 1022 | |
ashleymills | 0:714293de3836 | 1023 | if (length) |
ashleymills | 0:714293de3836 | 1024 | length += OPAQUE16_LEN; /* for total length storage */ |
ashleymills | 0:714293de3836 | 1025 | |
ashleymills | 0:714293de3836 | 1026 | return length; |
ashleymills | 0:714293de3836 | 1027 | } |
ashleymills | 0:714293de3836 | 1028 | |
ashleymills | 0:714293de3836 | 1029 | word16 TLSX_WriteResponse(CYASSL *ssl, byte* output) |
ashleymills | 0:714293de3836 | 1030 | { |
ashleymills | 0:714293de3836 | 1031 | word16 offset = 0; |
ashleymills | 0:714293de3836 | 1032 | |
ashleymills | 0:714293de3836 | 1033 | if (ssl && IsTLS(ssl) && output) { |
ashleymills | 0:714293de3836 | 1034 | byte semaphore[16] = {0}; |
ashleymills | 0:714293de3836 | 1035 | |
ashleymills | 0:714293de3836 | 1036 | offset += OPAQUE16_LEN; /* extensions length */ |
ashleymills | 0:714293de3836 | 1037 | |
ashleymills | 0:714293de3836 | 1038 | offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0); |
ashleymills | 0:714293de3836 | 1039 | |
ashleymills | 0:714293de3836 | 1040 | if (offset > OPAQUE16_LEN) |
ashleymills | 0:714293de3836 | 1041 | c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ |
ashleymills | 0:714293de3836 | 1042 | } |
ashleymills | 0:714293de3836 | 1043 | |
ashleymills | 0:714293de3836 | 1044 | return offset; |
ashleymills | 0:714293de3836 | 1045 | } |
ashleymills | 0:714293de3836 | 1046 | |
ashleymills | 0:714293de3836 | 1047 | #endif /* NO_CYASSL_SERVER */ |
ashleymills | 0:714293de3836 | 1048 | |
ashleymills | 0:714293de3836 | 1049 | int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest, |
ashleymills | 0:714293de3836 | 1050 | Suites *suites) |
ashleymills | 0:714293de3836 | 1051 | { |
ashleymills | 0:714293de3836 | 1052 | int ret = 0; |
ashleymills | 0:714293de3836 | 1053 | word16 offset = 0; |
ashleymills | 0:714293de3836 | 1054 | |
ashleymills | 0:714293de3836 | 1055 | if (!ssl || !input || !suites) |
ashleymills | 0:714293de3836 | 1056 | return BAD_FUNC_ARG; |
ashleymills | 0:714293de3836 | 1057 | |
ashleymills | 0:714293de3836 | 1058 | while (ret == 0 && offset < length) { |
ashleymills | 0:714293de3836 | 1059 | word16 type; |
ashleymills | 0:714293de3836 | 1060 | word16 size; |
ashleymills | 0:714293de3836 | 1061 | |
ashleymills | 0:714293de3836 | 1062 | if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN) |
ashleymills | 0:714293de3836 | 1063 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 1064 | |
ashleymills | 0:714293de3836 | 1065 | ato16(input + offset, &type); |
ashleymills | 0:714293de3836 | 1066 | offset += HELLO_EXT_TYPE_SZ; |
ashleymills | 0:714293de3836 | 1067 | |
ashleymills | 0:714293de3836 | 1068 | ato16(input + offset, &size); |
ashleymills | 0:714293de3836 | 1069 | offset += OPAQUE16_LEN; |
ashleymills | 0:714293de3836 | 1070 | |
ashleymills | 0:714293de3836 | 1071 | if (offset + size > length) |
ashleymills | 0:714293de3836 | 1072 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 1073 | |
ashleymills | 0:714293de3836 | 1074 | switch (type) { |
ashleymills | 0:714293de3836 | 1075 | case SERVER_NAME_INDICATION: |
ashleymills | 0:714293de3836 | 1076 | CYASSL_MSG("SNI extension received"); |
ashleymills | 0:714293de3836 | 1077 | |
ashleymills | 0:714293de3836 | 1078 | ret = SNI_PARSE(ssl, input + offset, size, isRequest); |
ashleymills | 0:714293de3836 | 1079 | break; |
ashleymills | 0:714293de3836 | 1080 | |
ashleymills | 0:714293de3836 | 1081 | case HELLO_EXT_SIG_ALGO: |
ashleymills | 0:714293de3836 | 1082 | if (isRequest) { |
ashleymills | 0:714293de3836 | 1083 | /* do not mess with offset inside the switch! */ |
ashleymills | 0:714293de3836 | 1084 | if (IsAtLeastTLSv1_2(ssl)) { |
ashleymills | 0:714293de3836 | 1085 | ato16(input + offset, &suites->hashSigAlgoSz); |
ashleymills | 0:714293de3836 | 1086 | |
ashleymills | 0:714293de3836 | 1087 | if (suites->hashSigAlgoSz > size - OPAQUE16_LEN) |
ashleymills | 0:714293de3836 | 1088 | return INCOMPLETE_DATA; |
ashleymills | 0:714293de3836 | 1089 | |
ashleymills | 0:714293de3836 | 1090 | XMEMCPY(suites->hashSigAlgo, |
ashleymills | 0:714293de3836 | 1091 | input + offset + OPAQUE16_LEN, |
ashleymills | 0:714293de3836 | 1092 | min(suites->hashSigAlgoSz, |
ashleymills | 0:714293de3836 | 1093 | HELLO_EXT_SIGALGO_MAX)); |
ashleymills | 0:714293de3836 | 1094 | } |
ashleymills | 0:714293de3836 | 1095 | } else { |
ashleymills | 0:714293de3836 | 1096 | CYASSL_MSG("Servers MUST NOT send SIG ALGO extension."); |
ashleymills | 0:714293de3836 | 1097 | } |
ashleymills | 0:714293de3836 | 1098 | |
ashleymills | 0:714293de3836 | 1099 | break; |
ashleymills | 0:714293de3836 | 1100 | } |
ashleymills | 0:714293de3836 | 1101 | |
ashleymills | 0:714293de3836 | 1102 | /* offset should be updated here! */ |
ashleymills | 0:714293de3836 | 1103 | offset += size; |
ashleymills | 0:714293de3836 | 1104 | } |
ashleymills | 0:714293de3836 | 1105 | |
ashleymills | 0:714293de3836 | 1106 | return ret; |
ashleymills | 0:714293de3836 | 1107 | } |
ashleymills | 0:714293de3836 | 1108 | |
ashleymills | 0:714293de3836 | 1109 | /* undefining semaphore macros */ |
ashleymills | 0:714293de3836 | 1110 | #undef IS_OFF |
ashleymills | 0:714293de3836 | 1111 | #undef TURN_ON |
ashleymills | 0:714293de3836 | 1112 | |
ashleymills | 0:714293de3836 | 1113 | #endif /* HAVE_TLS_EXTENSIONS */ |
ashleymills | 0:714293de3836 | 1114 | |
ashleymills | 0:714293de3836 | 1115 | |
ashleymills | 0:714293de3836 | 1116 | #ifndef NO_CYASSL_CLIENT |
ashleymills | 0:714293de3836 | 1117 | |
ashleymills | 0:714293de3836 | 1118 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 1119 | |
ashleymills | 0:714293de3836 | 1120 | CYASSL_METHOD* CyaTLSv1_client_method(void) |
ashleymills | 0:714293de3836 | 1121 | { |
ashleymills | 0:714293de3836 | 1122 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1123 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1124 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1125 | if (method) |
ashleymills | 0:714293de3836 | 1126 | InitSSL_Method(method, MakeTLSv1()); |
ashleymills | 0:714293de3836 | 1127 | return method; |
ashleymills | 0:714293de3836 | 1128 | } |
ashleymills | 0:714293de3836 | 1129 | |
ashleymills | 0:714293de3836 | 1130 | |
ashleymills | 0:714293de3836 | 1131 | CYASSL_METHOD* CyaTLSv1_1_client_method(void) |
ashleymills | 0:714293de3836 | 1132 | { |
ashleymills | 0:714293de3836 | 1133 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1134 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1135 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1136 | if (method) |
ashleymills | 0:714293de3836 | 1137 | InitSSL_Method(method, MakeTLSv1_1()); |
ashleymills | 0:714293de3836 | 1138 | return method; |
ashleymills | 0:714293de3836 | 1139 | } |
ashleymills | 0:714293de3836 | 1140 | |
ashleymills | 0:714293de3836 | 1141 | #endif /* !NO_OLD_TLS */ |
ashleymills | 0:714293de3836 | 1142 | |
ashleymills | 0:714293de3836 | 1143 | #ifndef NO_SHA256 /* can't use without SHA256 */ |
ashleymills | 0:714293de3836 | 1144 | |
ashleymills | 0:714293de3836 | 1145 | CYASSL_METHOD* CyaTLSv1_2_client_method(void) |
ashleymills | 0:714293de3836 | 1146 | { |
ashleymills | 0:714293de3836 | 1147 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1148 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1149 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1150 | if (method) |
ashleymills | 0:714293de3836 | 1151 | InitSSL_Method(method, MakeTLSv1_2()); |
ashleymills | 0:714293de3836 | 1152 | return method; |
ashleymills | 0:714293de3836 | 1153 | } |
ashleymills | 0:714293de3836 | 1154 | |
ashleymills | 0:714293de3836 | 1155 | #endif |
ashleymills | 0:714293de3836 | 1156 | |
ashleymills | 0:714293de3836 | 1157 | |
ashleymills | 0:714293de3836 | 1158 | CYASSL_METHOD* CyaSSLv23_client_method(void) |
ashleymills | 0:714293de3836 | 1159 | { |
ashleymills | 0:714293de3836 | 1160 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1161 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1162 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1163 | if (method) { |
ashleymills | 0:714293de3836 | 1164 | #ifndef NO_SHA256 /* 1.2 requires SHA256 */ |
ashleymills | 0:714293de3836 | 1165 | InitSSL_Method(method, MakeTLSv1_2()); |
ashleymills | 0:714293de3836 | 1166 | #else |
ashleymills | 0:714293de3836 | 1167 | InitSSL_Method(method, MakeTLSv1_1()); |
ashleymills | 0:714293de3836 | 1168 | #endif |
ashleymills | 0:714293de3836 | 1169 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 1170 | method->downgrade = 1; |
ashleymills | 0:714293de3836 | 1171 | #endif |
ashleymills | 0:714293de3836 | 1172 | } |
ashleymills | 0:714293de3836 | 1173 | return method; |
ashleymills | 0:714293de3836 | 1174 | } |
ashleymills | 0:714293de3836 | 1175 | |
ashleymills | 0:714293de3836 | 1176 | |
ashleymills | 0:714293de3836 | 1177 | #endif /* NO_CYASSL_CLIENT */ |
ashleymills | 0:714293de3836 | 1178 | |
ashleymills | 0:714293de3836 | 1179 | |
ashleymills | 0:714293de3836 | 1180 | |
ashleymills | 0:714293de3836 | 1181 | #ifndef NO_CYASSL_SERVER |
ashleymills | 0:714293de3836 | 1182 | |
ashleymills | 0:714293de3836 | 1183 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 1184 | |
ashleymills | 0:714293de3836 | 1185 | CYASSL_METHOD* CyaTLSv1_server_method(void) |
ashleymills | 0:714293de3836 | 1186 | { |
ashleymills | 0:714293de3836 | 1187 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1188 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1189 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1190 | if (method) { |
ashleymills | 0:714293de3836 | 1191 | InitSSL_Method(method, MakeTLSv1()); |
ashleymills | 0:714293de3836 | 1192 | method->side = SERVER_END; |
ashleymills | 0:714293de3836 | 1193 | } |
ashleymills | 0:714293de3836 | 1194 | return method; |
ashleymills | 0:714293de3836 | 1195 | } |
ashleymills | 0:714293de3836 | 1196 | |
ashleymills | 0:714293de3836 | 1197 | |
ashleymills | 0:714293de3836 | 1198 | CYASSL_METHOD* CyaTLSv1_1_server_method(void) |
ashleymills | 0:714293de3836 | 1199 | { |
ashleymills | 0:714293de3836 | 1200 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1201 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1202 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1203 | if (method) { |
ashleymills | 0:714293de3836 | 1204 | InitSSL_Method(method, MakeTLSv1_1()); |
ashleymills | 0:714293de3836 | 1205 | method->side = SERVER_END; |
ashleymills | 0:714293de3836 | 1206 | } |
ashleymills | 0:714293de3836 | 1207 | return method; |
ashleymills | 0:714293de3836 | 1208 | } |
ashleymills | 0:714293de3836 | 1209 | |
ashleymills | 0:714293de3836 | 1210 | #endif /* !NO_OLD_TLS */ |
ashleymills | 0:714293de3836 | 1211 | |
ashleymills | 0:714293de3836 | 1212 | #ifndef NO_SHA256 /* can't use without SHA256 */ |
ashleymills | 0:714293de3836 | 1213 | |
ashleymills | 0:714293de3836 | 1214 | CYASSL_METHOD* CyaTLSv1_2_server_method(void) |
ashleymills | 0:714293de3836 | 1215 | { |
ashleymills | 0:714293de3836 | 1216 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1217 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1218 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1219 | if (method) { |
ashleymills | 0:714293de3836 | 1220 | InitSSL_Method(method, MakeTLSv1_2()); |
ashleymills | 0:714293de3836 | 1221 | method->side = SERVER_END; |
ashleymills | 0:714293de3836 | 1222 | } |
ashleymills | 0:714293de3836 | 1223 | return method; |
ashleymills | 0:714293de3836 | 1224 | } |
ashleymills | 0:714293de3836 | 1225 | |
ashleymills | 0:714293de3836 | 1226 | #endif |
ashleymills | 0:714293de3836 | 1227 | |
ashleymills | 0:714293de3836 | 1228 | |
ashleymills | 0:714293de3836 | 1229 | CYASSL_METHOD* CyaSSLv23_server_method(void) |
ashleymills | 0:714293de3836 | 1230 | { |
ashleymills | 0:714293de3836 | 1231 | CYASSL_METHOD* method = |
ashleymills | 0:714293de3836 | 1232 | (CYASSL_METHOD*) XMALLOC(sizeof(CYASSL_METHOD), 0, |
ashleymills | 0:714293de3836 | 1233 | DYNAMIC_TYPE_METHOD); |
ashleymills | 0:714293de3836 | 1234 | if (method) { |
ashleymills | 0:714293de3836 | 1235 | #ifndef NO_SHA256 /* 1.2 requires SHA256 */ |
ashleymills | 0:714293de3836 | 1236 | InitSSL_Method(method, MakeTLSv1_2()); |
ashleymills | 0:714293de3836 | 1237 | #else |
ashleymills | 0:714293de3836 | 1238 | InitSSL_Method(method, MakeTLSv1_1()); |
ashleymills | 0:714293de3836 | 1239 | #endif |
ashleymills | 0:714293de3836 | 1240 | method->side = SERVER_END; |
ashleymills | 0:714293de3836 | 1241 | #ifndef NO_OLD_TLS |
ashleymills | 0:714293de3836 | 1242 | method->downgrade = 1; |
ashleymills | 0:714293de3836 | 1243 | #endif /* !NO_OLD_TLS */ |
ashleymills | 0:714293de3836 | 1244 | } |
ashleymills | 0:714293de3836 | 1245 | return method; |
ashleymills | 0:714293de3836 | 1246 | } |
ashleymills | 0:714293de3836 | 1247 | |
ashleymills | 0:714293de3836 | 1248 | |
ashleymills | 0:714293de3836 | 1249 | |
ashleymills | 0:714293de3836 | 1250 | #endif /* NO_CYASSL_SERVER */ |
ashleymills | 0:714293de3836 | 1251 | #endif /* NO_TLS */ |
ashleymills | 0:714293de3836 | 1252 |