ssh

Dependents:   OS

Committer:
sPymbed
Date:
Mon Nov 25 14:24:05 2019 +0000
Revision:
0:c4152c628df5
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sPymbed 0:c4152c628df5 1 /* internal.c
sPymbed 0:c4152c628df5 2 *
sPymbed 0:c4152c628df5 3 * Copyright (C) 2014-2016 wolfSSL Inc.
sPymbed 0:c4152c628df5 4 *
sPymbed 0:c4152c628df5 5 * This file is part of wolfSSH.
sPymbed 0:c4152c628df5 6 *
sPymbed 0:c4152c628df5 7 * wolfSSH is free software; you can redistribute it and/or modify
sPymbed 0:c4152c628df5 8 * it under the terms of the GNU General Public License as published by
sPymbed 0:c4152c628df5 9 * the Free Software Foundation; either version 3 of the License, or
sPymbed 0:c4152c628df5 10 * (at your option) any later version.
sPymbed 0:c4152c628df5 11 *
sPymbed 0:c4152c628df5 12 * wolfSSH is distributed in the hope that it will be useful,
sPymbed 0:c4152c628df5 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sPymbed 0:c4152c628df5 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
sPymbed 0:c4152c628df5 15 * GNU General Public License for more details.
sPymbed 0:c4152c628df5 16 *
sPymbed 0:c4152c628df5 17 * You should have received a copy of the GNU General Public License
sPymbed 0:c4152c628df5 18 * along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
sPymbed 0:c4152c628df5 19 */
sPymbed 0:c4152c628df5 20
sPymbed 0:c4152c628df5 21
sPymbed 0:c4152c628df5 22 /*
sPymbed 0:c4152c628df5 23 * The internal module contains the private data and functions. The public
sPymbed 0:c4152c628df5 24 * API calls into this module to do the work of processing the connections.
sPymbed 0:c4152c628df5 25 */
sPymbed 0:c4152c628df5 26
sPymbed 0:c4152c628df5 27
sPymbed 0:c4152c628df5 28 #ifdef HAVE_CONFIG_H
sPymbed 0:c4152c628df5 29 #include <config.h>
sPymbed 0:c4152c628df5 30 #endif
sPymbed 0:c4152c628df5 31
sPymbed 0:c4152c628df5 32 #include <wolfssh/ssh.h>
sPymbed 0:c4152c628df5 33 #include <wolfssh/internal.h>
sPymbed 0:c4152c628df5 34 #include <wolfssh/log.h>
sPymbed 0:c4152c628df5 35 #include <wolfcrypt/asn.h>
sPymbed 0:c4152c628df5 36 #include <wolfcrypt/dh.h>
sPymbed 0:c4152c628df5 37 #include <wolfcrypt/rsa.h>
sPymbed 0:c4152c628df5 38 #include <wolfcrypt/ecc.h>
sPymbed 0:c4152c628df5 39 #include <wolfcrypt/hmac.h>
sPymbed 0:c4152c628df5 40 #include <wolfcrypt/integer.h>
sPymbed 0:c4152c628df5 41 #include <wolfcrypt/signature.h>
sPymbed 0:c4152c628df5 42
sPymbed 0:c4152c628df5 43 //#include "esp_log.h"
sPymbed 0:c4152c628df5 44 //#include "esp_system.h"
sPymbed 0:c4152c628df5 45
sPymbed 0:c4152c628df5 46 #ifdef NO_INLINE
sPymbed 0:c4152c628df5 47 #include <wolfssh/misc.h>
sPymbed 0:c4152c628df5 48 #else
sPymbed 0:c4152c628df5 49 #define WOLFSSH_MISC_INCLUDED
sPymbed 0:c4152c628df5 50 #include "src/misc.c"
sPymbed 0:c4152c628df5 51 #endif
sPymbed 0:c4152c628df5 52
sPymbed 0:c4152c628df5 53
sPymbed 0:c4152c628df5 54 static const char sshProtoIdStr[] = "SSH-2.0-wolfSSHv"
sPymbed 0:c4152c628df5 55 LIBWOLFSSH_VERSION_STRING
sPymbed 0:c4152c628df5 56 "\r\n";
sPymbed 0:c4152c628df5 57 #ifndef WOLFSSH_DEFAULT_GEXDH_MIN
sPymbed 0:c4152c628df5 58 #define WOLFSSH_DEFAULT_GEXDH_MIN 1024
sPymbed 0:c4152c628df5 59 #endif
sPymbed 0:c4152c628df5 60 #ifndef WOLFSSH_DEFAULT_GEXDH_PREFERRED
sPymbed 0:c4152c628df5 61 #define WOLFSSH_DEFAULT_GEXDH_PREFERRED 3072
sPymbed 0:c4152c628df5 62 #endif
sPymbed 0:c4152c628df5 63 #ifndef WOLFSSH_DEFAULT_GEXDH_MAX
sPymbed 0:c4152c628df5 64 #define WOLFSSH_DEFAULT_GEXDH_MAX 8192
sPymbed 0:c4152c628df5 65 #endif
sPymbed 0:c4152c628df5 66
sPymbed 0:c4152c628df5 67
sPymbed 0:c4152c628df5 68 const char* GetErrorString(int err)
sPymbed 0:c4152c628df5 69 {
sPymbed 0:c4152c628df5 70 (void)err;
sPymbed 0:c4152c628df5 71
sPymbed 0:c4152c628df5 72 #ifdef NO_WOLFSSH_STRINGS
sPymbed 0:c4152c628df5 73 return "No wolfSSH strings available";
sPymbed 0:c4152c628df5 74 #else
sPymbed 0:c4152c628df5 75 switch (err) {
sPymbed 0:c4152c628df5 76 case WS_SUCCESS:
sPymbed 0:c4152c628df5 77 return "function success";
sPymbed 0:c4152c628df5 78
sPymbed 0:c4152c628df5 79 case WS_FATAL_ERROR:
sPymbed 0:c4152c628df5 80 return "general function failure";
sPymbed 0:c4152c628df5 81
sPymbed 0:c4152c628df5 82 case WS_BAD_ARGUMENT:
sPymbed 0:c4152c628df5 83 return "bad function argument";
sPymbed 0:c4152c628df5 84
sPymbed 0:c4152c628df5 85 case WS_MEMORY_E:
sPymbed 0:c4152c628df5 86 return "memory allocation failure";
sPymbed 0:c4152c628df5 87
sPymbed 0:c4152c628df5 88 case WS_BUFFER_E:
sPymbed 0:c4152c628df5 89 return "input/output buffer size error";
sPymbed 0:c4152c628df5 90
sPymbed 0:c4152c628df5 91 case WS_PARSE_E:
sPymbed 0:c4152c628df5 92 return "general parsing error";
sPymbed 0:c4152c628df5 93
sPymbed 0:c4152c628df5 94 case WS_NOT_COMPILED:
sPymbed 0:c4152c628df5 95 return "feature not compiled in";
sPymbed 0:c4152c628df5 96
sPymbed 0:c4152c628df5 97 case WS_OVERFLOW_E:
sPymbed 0:c4152c628df5 98 return "would overflow if continued failure";
sPymbed 0:c4152c628df5 99
sPymbed 0:c4152c628df5 100 case WS_BAD_USAGE:
sPymbed 0:c4152c628df5 101 return "bad example usage";
sPymbed 0:c4152c628df5 102
sPymbed 0:c4152c628df5 103 case WS_SOCKET_ERROR_E:
sPymbed 0:c4152c628df5 104 return "socket error";
sPymbed 0:c4152c628df5 105
sPymbed 0:c4152c628df5 106 case WS_WANT_READ:
sPymbed 0:c4152c628df5 107 return "I/O callback would read block error";
sPymbed 0:c4152c628df5 108
sPymbed 0:c4152c628df5 109 case WS_WANT_WRITE:
sPymbed 0:c4152c628df5 110 return "I/O callback would write block error";
sPymbed 0:c4152c628df5 111
sPymbed 0:c4152c628df5 112 case WS_RECV_OVERFLOW_E:
sPymbed 0:c4152c628df5 113 return "receive buffer overflow";
sPymbed 0:c4152c628df5 114
sPymbed 0:c4152c628df5 115 case WS_VERSION_E:
sPymbed 0:c4152c628df5 116 return "peer version unsupported";
sPymbed 0:c4152c628df5 117
sPymbed 0:c4152c628df5 118 case WS_SEND_OOB_READ_E:
sPymbed 0:c4152c628df5 119 return "attempted to read buffer out of bounds";
sPymbed 0:c4152c628df5 120
sPymbed 0:c4152c628df5 121 case WS_INPUT_CASE_E:
sPymbed 0:c4152c628df5 122 return "bad process input state, programming error";
sPymbed 0:c4152c628df5 123
sPymbed 0:c4152c628df5 124 case WS_BAD_FILETYPE_E:
sPymbed 0:c4152c628df5 125 return "bad filetype";
sPymbed 0:c4152c628df5 126
sPymbed 0:c4152c628df5 127 case WS_UNIMPLEMENTED_E:
sPymbed 0:c4152c628df5 128 return "feature not implemented";
sPymbed 0:c4152c628df5 129
sPymbed 0:c4152c628df5 130 case WS_RSA_E:
sPymbed 0:c4152c628df5 131 return "RSA buffer error";
sPymbed 0:c4152c628df5 132
sPymbed 0:c4152c628df5 133 case WS_BAD_FILE_E:
sPymbed 0:c4152c628df5 134 return "bad file";
sPymbed 0:c4152c628df5 135
sPymbed 0:c4152c628df5 136 case WS_DECRYPT_E:
sPymbed 0:c4152c628df5 137 return "decrypt error";
sPymbed 0:c4152c628df5 138
sPymbed 0:c4152c628df5 139 case WS_ENCRYPT_E:
sPymbed 0:c4152c628df5 140 return "encrypt error";
sPymbed 0:c4152c628df5 141
sPymbed 0:c4152c628df5 142 case WS_VERIFY_MAC_E:
sPymbed 0:c4152c628df5 143 return "verify mac error";
sPymbed 0:c4152c628df5 144
sPymbed 0:c4152c628df5 145 case WS_CREATE_MAC_E:
sPymbed 0:c4152c628df5 146 return "verify mac error";
sPymbed 0:c4152c628df5 147
sPymbed 0:c4152c628df5 148 case WS_RESOURCE_E:
sPymbed 0:c4152c628df5 149 return "insufficient resources for new channel";
sPymbed 0:c4152c628df5 150
sPymbed 0:c4152c628df5 151 case WS_INVALID_CHANTYPE:
sPymbed 0:c4152c628df5 152 return "peer requested invalid channel type";
sPymbed 0:c4152c628df5 153
sPymbed 0:c4152c628df5 154 case WS_INVALID_CHANID:
sPymbed 0:c4152c628df5 155 return "peer requested invalid channel id";
sPymbed 0:c4152c628df5 156
sPymbed 0:c4152c628df5 157 case WS_INVALID_USERNAME:
sPymbed 0:c4152c628df5 158 return "invalid user name";
sPymbed 0:c4152c628df5 159
sPymbed 0:c4152c628df5 160 case WS_CRYPTO_FAILED:
sPymbed 0:c4152c628df5 161 return "crypto action failed";
sPymbed 0:c4152c628df5 162
sPymbed 0:c4152c628df5 163 case WS_INVALID_STATE_E:
sPymbed 0:c4152c628df5 164 return "invalid state";
sPymbed 0:c4152c628df5 165
sPymbed 0:c4152c628df5 166 case WS_REKEYING:
sPymbed 0:c4152c628df5 167 return "rekeying with peer";
sPymbed 0:c4152c628df5 168
sPymbed 0:c4152c628df5 169 case WS_INVALID_PRIME_CURVE:
sPymbed 0:c4152c628df5 170 return "invalid prime curve in ecc";
sPymbed 0:c4152c628df5 171
sPymbed 0:c4152c628df5 172 case WS_ECC_E:
sPymbed 0:c4152c628df5 173 return "ECDSA buffer error";
sPymbed 0:c4152c628df5 174
sPymbed 0:c4152c628df5 175 case WS_CHANOPEN_FAILED:
sPymbed 0:c4152c628df5 176 return "peer returned channel open failure";
sPymbed 0:c4152c628df5 177
sPymbed 0:c4152c628df5 178 case WS_CHANNEL_CLOSED:
sPymbed 0:c4152c628df5 179 return "channel closed";
sPymbed 0:c4152c628df5 180
sPymbed 0:c4152c628df5 181 default:
sPymbed 0:c4152c628df5 182 return "Unknown error code";
sPymbed 0:c4152c628df5 183 }
sPymbed 0:c4152c628df5 184 #endif
sPymbed 0:c4152c628df5 185 }
sPymbed 0:c4152c628df5 186
sPymbed 0:c4152c628df5 187
sPymbed 0:c4152c628df5 188 static int wsHighwater(byte dir, void* ctx)
sPymbed 0:c4152c628df5 189 {
sPymbed 0:c4152c628df5 190 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 191
sPymbed 0:c4152c628df5 192 (void)dir;
sPymbed 0:c4152c628df5 193
sPymbed 0:c4152c628df5 194 if (ctx) {
sPymbed 0:c4152c628df5 195 WOLFSSH* ssh = (WOLFSSH*)ctx;
sPymbed 0:c4152c628df5 196
sPymbed 0:c4152c628df5 197 WLOG(WS_LOG_DEBUG, "HIGHWATER MARK: (%u) %s",
sPymbed 0:c4152c628df5 198 wolfSSH_GetHighwater(ssh),
sPymbed 0:c4152c628df5 199 (dir == WOLFSSH_HWSIDE_RECEIVE) ? "receive" : "transmit");
sPymbed 0:c4152c628df5 200
sPymbed 0:c4152c628df5 201 ret = wolfSSH_TriggerKeyExchange(ssh);
sPymbed 0:c4152c628df5 202 }
sPymbed 0:c4152c628df5 203
sPymbed 0:c4152c628df5 204 return ret;
sPymbed 0:c4152c628df5 205 }
sPymbed 0:c4152c628df5 206
sPymbed 0:c4152c628df5 207
sPymbed 0:c4152c628df5 208 static INLINE void HighwaterCheck(WOLFSSH* ssh, byte side)
sPymbed 0:c4152c628df5 209 {
sPymbed 0:c4152c628df5 210 if (!ssh->highwaterFlag && ssh->highwaterMark &&
sPymbed 0:c4152c628df5 211 (ssh->txCount >= ssh->highwaterMark ||
sPymbed 0:c4152c628df5 212 ssh->rxCount >= ssh->highwaterMark)) {
sPymbed 0:c4152c628df5 213
sPymbed 0:c4152c628df5 214 WLOG(WS_LOG_DEBUG, "%s over high water mark",
sPymbed 0:c4152c628df5 215 (side == WOLFSSH_HWSIDE_TRANSMIT) ? "Transmit" : "Receive");
sPymbed 0:c4152c628df5 216
sPymbed 0:c4152c628df5 217 ssh->highwaterFlag = 1;
sPymbed 0:c4152c628df5 218
sPymbed 0:c4152c628df5 219 if (ssh->ctx->highwaterCb)
sPymbed 0:c4152c628df5 220 ssh->ctx->highwaterCb(side, ssh->highwaterCtx);
sPymbed 0:c4152c628df5 221 }
sPymbed 0:c4152c628df5 222 }
sPymbed 0:c4152c628df5 223
sPymbed 0:c4152c628df5 224
sPymbed 0:c4152c628df5 225 static HandshakeInfo* HandshakeInfoNew(void* heap)
sPymbed 0:c4152c628df5 226 {
sPymbed 0:c4152c628df5 227 HandshakeInfo* newHs;
sPymbed 0:c4152c628df5 228
sPymbed 0:c4152c628df5 229 WLOG(WS_LOG_DEBUG, "Entering HandshakeInfoNew()");
sPymbed 0:c4152c628df5 230 newHs = (HandshakeInfo*)WMALLOC(sizeof(HandshakeInfo),
sPymbed 0:c4152c628df5 231 heap, DYNTYPE_HS);
sPymbed 0:c4152c628df5 232 if (newHs != NULL) {
sPymbed 0:c4152c628df5 233 WMEMSET(newHs, 0, sizeof(HandshakeInfo));
sPymbed 0:c4152c628df5 234 newHs->kexId = ID_NONE;
sPymbed 0:c4152c628df5 235 newHs->pubKeyId = ID_NONE;
sPymbed 0:c4152c628df5 236 newHs->encryptId = ID_NONE;
sPymbed 0:c4152c628df5 237 newHs->macId = ID_NONE;
sPymbed 0:c4152c628df5 238 newHs->blockSz = MIN_BLOCK_SZ;
sPymbed 0:c4152c628df5 239 newHs->hashId = WC_HASH_TYPE_NONE;
sPymbed 0:c4152c628df5 240 newHs->dhGexMinSz = WOLFSSH_DEFAULT_GEXDH_MIN;
sPymbed 0:c4152c628df5 241 newHs->dhGexPreferredSz = WOLFSSH_DEFAULT_GEXDH_PREFERRED;
sPymbed 0:c4152c628df5 242 newHs->dhGexMaxSz = WOLFSSH_DEFAULT_GEXDH_MAX;
sPymbed 0:c4152c628df5 243 }
sPymbed 0:c4152c628df5 244
sPymbed 0:c4152c628df5 245 return newHs;
sPymbed 0:c4152c628df5 246 }
sPymbed 0:c4152c628df5 247
sPymbed 0:c4152c628df5 248 void ForceZero(const void* mem, word32 length){
sPymbed 0:c4152c628df5 249 }
sPymbed 0:c4152c628df5 250
sPymbed 0:c4152c628df5 251 static void HandshakeInfoFree(HandshakeInfo* hs, void* heap)
sPymbed 0:c4152c628df5 252 {
sPymbed 0:c4152c628df5 253 (void)heap;
sPymbed 0:c4152c628df5 254
sPymbed 0:c4152c628df5 255 WLOG(WS_LOG_DEBUG, "Entering HandshakeInfoFree()");
sPymbed 0:c4152c628df5 256 if (hs) {
sPymbed 0:c4152c628df5 257 WFREE(hs->kexInit, heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 258 WFREE(hs->primeGroup, heap, DYNTYPE_MPINT);
sPymbed 0:c4152c628df5 259 WFREE(hs->generator, heap, DYNTYPE_MPINT);
sPymbed 0:c4152c628df5 260 ForceZero(hs, sizeof(HandshakeInfo));
sPymbed 0:c4152c628df5 261 WFREE(hs, heap, DYNTYPE_HS);
sPymbed 0:c4152c628df5 262 }
sPymbed 0:c4152c628df5 263 }
sPymbed 0:c4152c628df5 264
sPymbed 0:c4152c628df5 265
sPymbed 0:c4152c628df5 266 #ifdef DEBUG_WOLFSSH
sPymbed 0:c4152c628df5 267
sPymbed 0:c4152c628df5 268 static const char cannedBanner[] =
sPymbed 0:c4152c628df5 269 "CANNED BANNER\r\n"
sPymbed 0:c4152c628df5 270 "This server is an example test server. "
sPymbed 0:c4152c628df5 271 "It should have its own banner, but\r\n"
sPymbed 0:c4152c628df5 272 "it is currently using a canned one in "
sPymbed 0:c4152c628df5 273 "the library. Be happy or not.\r\n";
sPymbed 0:c4152c628df5 274 static const word32 cannedBannerSz = sizeof(cannedBanner) - 1;
sPymbed 0:c4152c628df5 275
sPymbed 0:c4152c628df5 276 #endif /* DEBUG_WOLFSSH */
sPymbed 0:c4152c628df5 277
sPymbed 0:c4152c628df5 278
sPymbed 0:c4152c628df5 279 WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap)
sPymbed 0:c4152c628df5 280 {
sPymbed 0:c4152c628df5 281 WLOG(WS_LOG_DEBUG, "Entering CtxInit()");
sPymbed 0:c4152c628df5 282
sPymbed 0:c4152c628df5 283 if (ctx == NULL)
sPymbed 0:c4152c628df5 284 return ctx;
sPymbed 0:c4152c628df5 285
sPymbed 0:c4152c628df5 286 WMEMSET(ctx, 0, sizeof(WOLFSSH_CTX));
sPymbed 0:c4152c628df5 287
sPymbed 0:c4152c628df5 288 if (heap)
sPymbed 0:c4152c628df5 289 ctx->heap = heap;
sPymbed 0:c4152c628df5 290
sPymbed 0:c4152c628df5 291 ctx->side = side;
sPymbed 0:c4152c628df5 292 #ifndef WOLFSSH_USER_IO
sPymbed 0:c4152c628df5 293 ctx->ioRecvCb = wsEmbedRecv;
sPymbed 0:c4152c628df5 294 ctx->ioSendCb = wsEmbedSend;
sPymbed 0:c4152c628df5 295 #endif /* WOLFSSH_USER_IO */
sPymbed 0:c4152c628df5 296 ctx->highwaterMark = DEFAULT_HIGHWATER_MARK;
sPymbed 0:c4152c628df5 297 ctx->highwaterCb = wsHighwater;
sPymbed 0:c4152c628df5 298 #ifdef DEBUG_WOLFSSH
sPymbed 0:c4152c628df5 299 ctx->banner = cannedBanner;
sPymbed 0:c4152c628df5 300 ctx->bannerSz = cannedBannerSz;
sPymbed 0:c4152c628df5 301 #endif /* DEBUG_WOLFSSH */
sPymbed 0:c4152c628df5 302
sPymbed 0:c4152c628df5 303 return ctx;
sPymbed 0:c4152c628df5 304 }
sPymbed 0:c4152c628df5 305
sPymbed 0:c4152c628df5 306
sPymbed 0:c4152c628df5 307 void CtxResourceFree(WOLFSSH_CTX* ctx)
sPymbed 0:c4152c628df5 308 {
sPymbed 0:c4152c628df5 309 WLOG(WS_LOG_DEBUG, "Entering CtxResourceFree()");
sPymbed 0:c4152c628df5 310
sPymbed 0:c4152c628df5 311 if (ctx->privateKey) {
sPymbed 0:c4152c628df5 312 ForceZero(ctx->privateKey, ctx->privateKeySz);
sPymbed 0:c4152c628df5 313 WFREE(ctx->privateKey, ctx->heap, DYNTYPE_PRIVKEY);
sPymbed 0:c4152c628df5 314 }
sPymbed 0:c4152c628df5 315 }
sPymbed 0:c4152c628df5 316
sPymbed 0:c4152c628df5 317
sPymbed 0:c4152c628df5 318 WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
sPymbed 0:c4152c628df5 319 {
sPymbed 0:c4152c628df5 320 HandshakeInfo* handshake;
sPymbed 0:c4152c628df5 321 RNG* rng;
sPymbed 0:c4152c628df5 322 void* heap;
sPymbed 0:c4152c628df5 323
sPymbed 0:c4152c628df5 324 WLOG(WS_LOG_DEBUG, "Entering SshInit()");
sPymbed 0:c4152c628df5 325 //ESP_LOGI("WOLFSSH", "SshInit()");
sPymbed 0:c4152c628df5 326
sPymbed 0:c4152c628df5 327 if (ssh == NULL || ctx == NULL)
sPymbed 0:c4152c628df5 328 return ssh;
sPymbed 0:c4152c628df5 329 heap = ctx->heap;
sPymbed 0:c4152c628df5 330 //ESP_LOGI("WOLFSSH", "heap=ctx->heap");
sPymbed 0:c4152c628df5 331
sPymbed 0:c4152c628df5 332 handshake = HandshakeInfoNew(heap);
sPymbed 0:c4152c628df5 333 //ESP_LOGI("WOLFSSH", "HandshakeInfoNew(heap) OK");
sPymbed 0:c4152c628df5 334 rng = (RNG*)WMALLOC(sizeof(RNG), heap, DYNTYPE_RNG);
sPymbed 0:c4152c628df5 335 //ESP_LOGI("WOLFSSH", "malloc RNG OK");
sPymbed 0:c4152c628df5 336
sPymbed 0:c4152c628df5 337 //if(handshake == NULL) ESP_LOGE("WOLFSSH", "handshake is NULL");
sPymbed 0:c4152c628df5 338 //if(rng == NULL) ESP_LOGE("WOLFSSH", "rng is NULL");
sPymbed 0:c4152c628df5 339
sPymbed 0:c4152c628df5 340
sPymbed 0:c4152c628df5 341 //ESP_LOGI("WOLFSSH", "wc_InitRng(rng), free heap:%d", esp_get_free_heap_size());
sPymbed 0:c4152c628df5 342
sPymbed 0:c4152c628df5 343 int wc_InitRng_result = wc_InitRng(rng);
sPymbed 0:c4152c628df5 344
sPymbed 0:c4152c628df5 345 if (handshake == NULL || rng == NULL || wc_InitRng_result != 0) {
sPymbed 0:c4152c628df5 346 //ESP_LOGE("WOLFSSH", "Cannot allocate memory, wc_InitRng_result ret=%d", wc_InitRng_result);
sPymbed 0:c4152c628df5 347 WLOG(WS_LOG_DEBUG, "SshInit: Cannot allocate memory.\n");
sPymbed 0:c4152c628df5 348 WFREE(handshake, heap, DYNTYPE_HS);
sPymbed 0:c4152c628df5 349 WFREE(rng, heap, DYNTYPE_RNG);
sPymbed 0:c4152c628df5 350 wolfSSH_free(ssh);
sPymbed 0:c4152c628df5 351 return NULL;
sPymbed 0:c4152c628df5 352 }
sPymbed 0:c4152c628df5 353
sPymbed 0:c4152c628df5 354 WMEMSET(ssh, 0, sizeof(WOLFSSH)); /* default init to zeros */
sPymbed 0:c4152c628df5 355 //ESP_LOGI("WOLFSSH", "memset WOLFSSH");
sPymbed 0:c4152c628df5 356
sPymbed 0:c4152c628df5 357 ssh->ctx = ctx;
sPymbed 0:c4152c628df5 358 ssh->error = WS_SUCCESS;
sPymbed 0:c4152c628df5 359 ssh->rfd = -1; /* set to invalid */
sPymbed 0:c4152c628df5 360 ssh->wfd = -1; /* set to invalid */
sPymbed 0:c4152c628df5 361 ssh->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */
sPymbed 0:c4152c628df5 362 ssh->ioWriteCtx = &ssh->wfd; /* set */
sPymbed 0:c4152c628df5 363 ssh->highwaterMark = ctx->highwaterMark;
sPymbed 0:c4152c628df5 364 ssh->highwaterCtx = (void*)ssh;
sPymbed 0:c4152c628df5 365 ssh->acceptState = ACCEPT_BEGIN;
sPymbed 0:c4152c628df5 366 ssh->clientState = CLIENT_BEGIN;
sPymbed 0:c4152c628df5 367 ssh->isKeying = 1;
sPymbed 0:c4152c628df5 368 ssh->nextChannel = DEFAULT_NEXT_CHANNEL;
sPymbed 0:c4152c628df5 369 ssh->blockSz = MIN_BLOCK_SZ;
sPymbed 0:c4152c628df5 370 ssh->encryptId = ID_NONE;
sPymbed 0:c4152c628df5 371 ssh->macId = ID_NONE;
sPymbed 0:c4152c628df5 372 ssh->peerBlockSz = MIN_BLOCK_SZ;
sPymbed 0:c4152c628df5 373 ssh->rng = rng;
sPymbed 0:c4152c628df5 374 ssh->kSz = sizeof(ssh->k);
sPymbed 0:c4152c628df5 375 ssh->handshake = handshake;
sPymbed 0:c4152c628df5 376
sPymbed 0:c4152c628df5 377 //ESP_LOGI("WOLFSSH", "BufferInit...");
sPymbed 0:c4152c628df5 378 if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS ||
sPymbed 0:c4152c628df5 379 BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS) {
sPymbed 0:c4152c628df5 380
sPymbed 0:c4152c628df5 381 wolfSSH_free(ssh);
sPymbed 0:c4152c628df5 382 ssh = NULL;
sPymbed 0:c4152c628df5 383 }
sPymbed 0:c4152c628df5 384 //ESP_LOGI("WOLFSSH", "BufferInit OK");
sPymbed 0:c4152c628df5 385
sPymbed 0:c4152c628df5 386 return ssh;
sPymbed 0:c4152c628df5 387 }
sPymbed 0:c4152c628df5 388
sPymbed 0:c4152c628df5 389 void SshResourceFree(WOLFSSH* ssh, void* heap)
sPymbed 0:c4152c628df5 390 {
sPymbed 0:c4152c628df5 391 /* when ssh holds resources, free here */
sPymbed 0:c4152c628df5 392 (void)heap;
sPymbed 0:c4152c628df5 393
sPymbed 0:c4152c628df5 394 WLOG(WS_LOG_DEBUG, "Entering sshResourceFree()");
sPymbed 0:c4152c628df5 395
sPymbed 0:c4152c628df5 396 ShrinkBuffer(&ssh->inputBuffer, 1);
sPymbed 0:c4152c628df5 397 ShrinkBuffer(&ssh->outputBuffer, 1);
sPymbed 0:c4152c628df5 398 ForceZero(ssh->k, ssh->kSz);
sPymbed 0:c4152c628df5 399 HandshakeInfoFree(ssh->handshake, heap);
sPymbed 0:c4152c628df5 400 ForceZero(&ssh->keys, sizeof(Keys));
sPymbed 0:c4152c628df5 401 ForceZero(&ssh->peerKeys, sizeof(Keys));
sPymbed 0:c4152c628df5 402 if (ssh->rng) {
sPymbed 0:c4152c628df5 403 wc_FreeRng(ssh->rng);
sPymbed 0:c4152c628df5 404 WFREE(ssh->rng, heap, DYNTYPE_RNG);
sPymbed 0:c4152c628df5 405 }
sPymbed 0:c4152c628df5 406 if (ssh->userName) {
sPymbed 0:c4152c628df5 407 WFREE(ssh->userName, heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 408 }
sPymbed 0:c4152c628df5 409 if (ssh->peerProtoId) {
sPymbed 0:c4152c628df5 410 WFREE(ssh->peerProtoId, heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 411 }
sPymbed 0:c4152c628df5 412 if (ssh->channelList) {
sPymbed 0:c4152c628df5 413 WOLFSSH_CHANNEL* cur = ssh->channelList;
sPymbed 0:c4152c628df5 414 WOLFSSH_CHANNEL* next;
sPymbed 0:c4152c628df5 415 while (cur) {
sPymbed 0:c4152c628df5 416 next = cur->next;
sPymbed 0:c4152c628df5 417 ChannelDelete(cur, heap);
sPymbed 0:c4152c628df5 418 cur = next;
sPymbed 0:c4152c628df5 419 }
sPymbed 0:c4152c628df5 420 }
sPymbed 0:c4152c628df5 421 }
sPymbed 0:c4152c628df5 422
sPymbed 0:c4152c628df5 423
sPymbed 0:c4152c628df5 424 int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx,
sPymbed 0:c4152c628df5 425 const byte* in, word32 inSz,
sPymbed 0:c4152c628df5 426 int format, int type)
sPymbed 0:c4152c628df5 427 {
sPymbed 0:c4152c628df5 428 int dynamicType;
sPymbed 0:c4152c628df5 429 void* heap;
sPymbed 0:c4152c628df5 430 byte* der;
sPymbed 0:c4152c628df5 431 word32 derSz;
sPymbed 0:c4152c628df5 432
sPymbed 0:c4152c628df5 433 if (ctx == NULL || in == NULL || inSz == 0)
sPymbed 0:c4152c628df5 434 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 435
sPymbed 0:c4152c628df5 436 if (format != WOLFSSH_FORMAT_ASN1 && format != WOLFSSH_FORMAT_PEM &&
sPymbed 0:c4152c628df5 437 format != WOLFSSH_FORMAT_RAW)
sPymbed 0:c4152c628df5 438 return WS_BAD_FILETYPE_E;
sPymbed 0:c4152c628df5 439
sPymbed 0:c4152c628df5 440 if (type == BUFTYPE_CA)
sPymbed 0:c4152c628df5 441 dynamicType = DYNTYPE_CA;
sPymbed 0:c4152c628df5 442 else if (type == BUFTYPE_CERT)
sPymbed 0:c4152c628df5 443 dynamicType = DYNTYPE_CERT;
sPymbed 0:c4152c628df5 444 else if (type == BUFTYPE_PRIVKEY)
sPymbed 0:c4152c628df5 445 dynamicType = DYNTYPE_PRIVKEY;
sPymbed 0:c4152c628df5 446 else
sPymbed 0:c4152c628df5 447 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 448
sPymbed 0:c4152c628df5 449 heap = ctx->heap;
sPymbed 0:c4152c628df5 450
sPymbed 0:c4152c628df5 451 if (format == WOLFSSH_FORMAT_PEM)
sPymbed 0:c4152c628df5 452 return WS_UNIMPLEMENTED_E;
sPymbed 0:c4152c628df5 453 else {
sPymbed 0:c4152c628df5 454 /* format is ASN1 or RAW */
sPymbed 0:c4152c628df5 455 der = (byte*)WMALLOC(inSz, heap, dynamicType);
sPymbed 0:c4152c628df5 456 if (der == NULL)
sPymbed 0:c4152c628df5 457 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 458 WMEMCPY(der, in, inSz);
sPymbed 0:c4152c628df5 459 derSz = inSz;
sPymbed 0:c4152c628df5 460 }
sPymbed 0:c4152c628df5 461
sPymbed 0:c4152c628df5 462 /* Maybe decrypt */
sPymbed 0:c4152c628df5 463
sPymbed 0:c4152c628df5 464 if (type == BUFTYPE_PRIVKEY) {
sPymbed 0:c4152c628df5 465 if (ctx->privateKey)
sPymbed 0:c4152c628df5 466 WFREE(ctx->privateKey, heap, dynamicType);
sPymbed 0:c4152c628df5 467 ctx->privateKey = der;
sPymbed 0:c4152c628df5 468 ctx->privateKeySz = derSz;
sPymbed 0:c4152c628df5 469 }
sPymbed 0:c4152c628df5 470 else {
sPymbed 0:c4152c628df5 471 WFREE(der, heap, dynamicType);
sPymbed 0:c4152c628df5 472 return WS_UNIMPLEMENTED_E;
sPymbed 0:c4152c628df5 473 }
sPymbed 0:c4152c628df5 474
sPymbed 0:c4152c628df5 475 if (type == BUFTYPE_PRIVKEY && format != WOLFSSH_FORMAT_RAW) {
sPymbed 0:c4152c628df5 476 /* Check RSA key */
sPymbed 0:c4152c628df5 477 union {
sPymbed 0:c4152c628df5 478 RsaKey rsa;
sPymbed 0:c4152c628df5 479 ecc_key ecc;
sPymbed 0:c4152c628df5 480 } key;
sPymbed 0:c4152c628df5 481 word32 scratch = 0;
sPymbed 0:c4152c628df5 482 int ret;
sPymbed 0:c4152c628df5 483
sPymbed 0:c4152c628df5 484 if (wc_InitRsaKey(&key.rsa, NULL) < 0)
sPymbed 0:c4152c628df5 485 return WS_RSA_E;
sPymbed 0:c4152c628df5 486
sPymbed 0:c4152c628df5 487 ret = wc_RsaPrivateKeyDecode(der, &scratch, &key.rsa, derSz);
sPymbed 0:c4152c628df5 488 wc_FreeRsaKey(&key.rsa);
sPymbed 0:c4152c628df5 489
sPymbed 0:c4152c628df5 490 if (ret < 0) {
sPymbed 0:c4152c628df5 491 /* Couldn't decode as RSA key. Try decoding as ECC key. */
sPymbed 0:c4152c628df5 492 scratch = 0;
sPymbed 0:c4152c628df5 493 if (wc_ecc_init_ex(&key.ecc, ctx->heap, INVALID_DEVID) != 0)
sPymbed 0:c4152c628df5 494 return WS_ECC_E;
sPymbed 0:c4152c628df5 495
sPymbed 0:c4152c628df5 496 ret = wc_EccPrivateKeyDecode(ctx->privateKey, &scratch,
sPymbed 0:c4152c628df5 497 &key.ecc, ctx->privateKeySz);
sPymbed 0:c4152c628df5 498 if (ret == 0) {
sPymbed 0:c4152c628df5 499 int curveId = wc_ecc_get_curve_id(key.ecc.idx);
sPymbed 0:c4152c628df5 500 if (curveId == ECC_SECP256R1 ||
sPymbed 0:c4152c628df5 501 curveId == ECC_SECP384R1 ||
sPymbed 0:c4152c628df5 502 curveId == ECC_SECP521R1) {
sPymbed 0:c4152c628df5 503
sPymbed 0:c4152c628df5 504 ctx->useEcc = curveId;
sPymbed 0:c4152c628df5 505 }
sPymbed 0:c4152c628df5 506 else
sPymbed 0:c4152c628df5 507 ret = WS_BAD_FILE_E;
sPymbed 0:c4152c628df5 508 }
sPymbed 0:c4152c628df5 509 wc_ecc_free(&key.ecc);
sPymbed 0:c4152c628df5 510
sPymbed 0:c4152c628df5 511 if (ret != 0)
sPymbed 0:c4152c628df5 512 return WS_BAD_FILE_E;
sPymbed 0:c4152c628df5 513 }
sPymbed 0:c4152c628df5 514 }
sPymbed 0:c4152c628df5 515
sPymbed 0:c4152c628df5 516 return WS_SUCCESS;
sPymbed 0:c4152c628df5 517 }
sPymbed 0:c4152c628df5 518
sPymbed 0:c4152c628df5 519 void c32toa(word32 u32, byte* c){
sPymbed 0:c4152c628df5 520 }
sPymbed 0:c4152c628df5 521
sPymbed 0:c4152c628df5 522 int GenerateKey(byte hashId, byte keyId,
sPymbed 0:c4152c628df5 523 byte* key, word32 keySz,
sPymbed 0:c4152c628df5 524 const byte* k, word32 kSz,
sPymbed 0:c4152c628df5 525 const byte* h, word32 hSz,
sPymbed 0:c4152c628df5 526 const byte* sessionId, word32 sessionIdSz)
sPymbed 0:c4152c628df5 527 {
sPymbed 0:c4152c628df5 528 word32 blocks, remainder;
sPymbed 0:c4152c628df5 529 wc_HashAlg hash;
sPymbed 0:c4152c628df5 530 byte kPad = 0;
sPymbed 0:c4152c628df5 531 byte pad = 0;
sPymbed 0:c4152c628df5 532 byte kSzFlat[LENGTH_SZ];
sPymbed 0:c4152c628df5 533 int digestSz;
sPymbed 0:c4152c628df5 534 int ret;
sPymbed 0:c4152c628df5 535
sPymbed 0:c4152c628df5 536 if (key == NULL || keySz == 0 ||
sPymbed 0:c4152c628df5 537 k == NULL || kSz == 0 ||
sPymbed 0:c4152c628df5 538 h == NULL || hSz == 0 ||
sPymbed 0:c4152c628df5 539 sessionId == NULL || sessionIdSz == 0) {
sPymbed 0:c4152c628df5 540
sPymbed 0:c4152c628df5 541 WLOG(WS_LOG_DEBUG, "GK: bad argument");
sPymbed 0:c4152c628df5 542 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 543 }
sPymbed 0:c4152c628df5 544
sPymbed 0:c4152c628df5 545 digestSz = wc_HashGetDigestSize(hashId);
sPymbed 0:c4152c628df5 546 if (digestSz == 0) {
sPymbed 0:c4152c628df5 547 WLOG(WS_LOG_DEBUG, "GK: bad hash ID");
sPymbed 0:c4152c628df5 548 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 549 }
sPymbed 0:c4152c628df5 550
sPymbed 0:c4152c628df5 551 if (k[0] & 0x80) kPad = 1;
sPymbed 0:c4152c628df5 552 c32toa(kSz + kPad, kSzFlat);
sPymbed 0:c4152c628df5 553
sPymbed 0:c4152c628df5 554 blocks = keySz / digestSz;
sPymbed 0:c4152c628df5 555 remainder = keySz % digestSz;
sPymbed 0:c4152c628df5 556
sPymbed 0:c4152c628df5 557 ret = wc_HashInit(&hash, hashId);
sPymbed 0:c4152c628df5 558 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 559 ret = wc_HashUpdate(&hash, hashId, kSzFlat, LENGTH_SZ);
sPymbed 0:c4152c628df5 560 if (ret == WS_SUCCESS && kPad)
sPymbed 0:c4152c628df5 561 ret = wc_HashUpdate(&hash, hashId, &pad, 1);
sPymbed 0:c4152c628df5 562 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 563 ret = wc_HashUpdate(&hash, hashId, k, kSz);
sPymbed 0:c4152c628df5 564 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 565 ret = wc_HashUpdate(&hash, hashId, h, hSz);
sPymbed 0:c4152c628df5 566 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 567 ret = wc_HashUpdate(&hash, hashId, &keyId, sizeof(keyId));
sPymbed 0:c4152c628df5 568 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 569 ret = wc_HashUpdate(&hash, hashId, sessionId, sessionIdSz);
sPymbed 0:c4152c628df5 570
sPymbed 0:c4152c628df5 571 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 572 if (blocks == 0) {
sPymbed 0:c4152c628df5 573 if (remainder > 0) {
sPymbed 0:c4152c628df5 574 byte lastBlock[WC_MAX_DIGEST_SIZE];
sPymbed 0:c4152c628df5 575 ret = wc_HashFinal(&hash, hashId, lastBlock);
sPymbed 0:c4152c628df5 576 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 577 WMEMCPY(key, lastBlock, remainder);
sPymbed 0:c4152c628df5 578 }
sPymbed 0:c4152c628df5 579 }
sPymbed 0:c4152c628df5 580 else {
sPymbed 0:c4152c628df5 581 word32 runningKeySz, curBlock;
sPymbed 0:c4152c628df5 582
sPymbed 0:c4152c628df5 583 runningKeySz = digestSz;
sPymbed 0:c4152c628df5 584 ret = wc_HashFinal(&hash, hashId, key);
sPymbed 0:c4152c628df5 585
sPymbed 0:c4152c628df5 586 for (curBlock = 1; curBlock < blocks; curBlock++) {
sPymbed 0:c4152c628df5 587 ret = wc_HashInit(&hash, hashId);
sPymbed 0:c4152c628df5 588 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 589 ret = wc_HashUpdate(&hash, hashId, kSzFlat, LENGTH_SZ);
sPymbed 0:c4152c628df5 590 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 591 if (kPad)
sPymbed 0:c4152c628df5 592 ret = wc_HashUpdate(&hash, hashId, &pad, 1);
sPymbed 0:c4152c628df5 593 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 594 ret = wc_HashUpdate(&hash, hashId, k, kSz);
sPymbed 0:c4152c628df5 595 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 596 ret = wc_HashUpdate(&hash, hashId, h, hSz);
sPymbed 0:c4152c628df5 597 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 598 ret = wc_HashUpdate(&hash, hashId, key, runningKeySz);
sPymbed 0:c4152c628df5 599 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 600 ret = wc_HashFinal(&hash, hashId, key + runningKeySz);
sPymbed 0:c4152c628df5 601 if (ret != WS_SUCCESS) break;
sPymbed 0:c4152c628df5 602 runningKeySz += digestSz;
sPymbed 0:c4152c628df5 603 }
sPymbed 0:c4152c628df5 604
sPymbed 0:c4152c628df5 605 if (remainder > 0) {
sPymbed 0:c4152c628df5 606 byte lastBlock[WC_MAX_DIGEST_SIZE];
sPymbed 0:c4152c628df5 607 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 608 ret = wc_HashInit(&hash, hashId);
sPymbed 0:c4152c628df5 609 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 610 ret = wc_HashUpdate(&hash, hashId, kSzFlat, LENGTH_SZ);
sPymbed 0:c4152c628df5 611 if (ret == WS_SUCCESS && kPad)
sPymbed 0:c4152c628df5 612 ret = wc_HashUpdate(&hash, hashId, &pad, 1);
sPymbed 0:c4152c628df5 613 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 614 ret = wc_HashUpdate(&hash, hashId, k, kSz);
sPymbed 0:c4152c628df5 615 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 616 ret = wc_HashUpdate(&hash, hashId, h, hSz);
sPymbed 0:c4152c628df5 617 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 618 ret = wc_HashUpdate(&hash, hashId, key, runningKeySz);
sPymbed 0:c4152c628df5 619 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 620 ret = wc_HashFinal(&hash, hashId, lastBlock);
sPymbed 0:c4152c628df5 621 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 622 WMEMCPY(key + runningKeySz, lastBlock, remainder);
sPymbed 0:c4152c628df5 623 }
sPymbed 0:c4152c628df5 624 }
sPymbed 0:c4152c628df5 625 }
sPymbed 0:c4152c628df5 626
sPymbed 0:c4152c628df5 627 if (ret != WS_SUCCESS)
sPymbed 0:c4152c628df5 628 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 629
sPymbed 0:c4152c628df5 630 return ret;
sPymbed 0:c4152c628df5 631 }
sPymbed 0:c4152c628df5 632
sPymbed 0:c4152c628df5 633
sPymbed 0:c4152c628df5 634 static int GenerateKeys(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 635 {
sPymbed 0:c4152c628df5 636 Keys* cK;
sPymbed 0:c4152c628df5 637 Keys* sK;
sPymbed 0:c4152c628df5 638 byte hashId;
sPymbed 0:c4152c628df5 639 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 640
sPymbed 0:c4152c628df5 641 if (ssh == NULL)
sPymbed 0:c4152c628df5 642 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 643 else {
sPymbed 0:c4152c628df5 644 if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {
sPymbed 0:c4152c628df5 645 cK = &ssh->handshake->peerKeys;
sPymbed 0:c4152c628df5 646 sK = &ssh->handshake->keys;
sPymbed 0:c4152c628df5 647 }
sPymbed 0:c4152c628df5 648 else {
sPymbed 0:c4152c628df5 649 cK = &ssh->handshake->keys;
sPymbed 0:c4152c628df5 650 sK = &ssh->handshake->peerKeys;
sPymbed 0:c4152c628df5 651 }
sPymbed 0:c4152c628df5 652 hashId = ssh->handshake->hashId;
sPymbed 0:c4152c628df5 653 }
sPymbed 0:c4152c628df5 654
sPymbed 0:c4152c628df5 655 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 656 ret = GenerateKey(hashId, 'A',
sPymbed 0:c4152c628df5 657 cK->iv, cK->ivSz,
sPymbed 0:c4152c628df5 658 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
sPymbed 0:c4152c628df5 659 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 660 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 661 ret = GenerateKey(hashId, 'B',
sPymbed 0:c4152c628df5 662 sK->iv, sK->ivSz,
sPymbed 0:c4152c628df5 663 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
sPymbed 0:c4152c628df5 664 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 665 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 666 ret = GenerateKey(hashId, 'C',
sPymbed 0:c4152c628df5 667 cK->encKey, cK->encKeySz,
sPymbed 0:c4152c628df5 668 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
sPymbed 0:c4152c628df5 669 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 670 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 671 ret = GenerateKey(hashId, 'D',
sPymbed 0:c4152c628df5 672 sK->encKey, sK->encKeySz,
sPymbed 0:c4152c628df5 673 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
sPymbed 0:c4152c628df5 674 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 675 if (!ssh->handshake->aeadMode) {
sPymbed 0:c4152c628df5 676 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 677 ret = GenerateKey(hashId, 'E',
sPymbed 0:c4152c628df5 678 cK->macKey, cK->macKeySz,
sPymbed 0:c4152c628df5 679 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
sPymbed 0:c4152c628df5 680 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 681 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 682 ret = GenerateKey(hashId, 'F',
sPymbed 0:c4152c628df5 683 sK->macKey, sK->macKeySz,
sPymbed 0:c4152c628df5 684 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
sPymbed 0:c4152c628df5 685 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 686 }
sPymbed 0:c4152c628df5 687 #ifdef SHOW_SECRETS
sPymbed 0:c4152c628df5 688 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 689 printf("\n** Showing Secrets **\nK:\n");
sPymbed 0:c4152c628df5 690 DumpOctetString(ssh->k, ssh->kSz);
sPymbed 0:c4152c628df5 691 printf("H:\n");
sPymbed 0:c4152c628df5 692 DumpOctetString(ssh->h, ssh->hSz);
sPymbed 0:c4152c628df5 693 printf("Session ID:\n");
sPymbed 0:c4152c628df5 694 DumpOctetString(ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 695 printf("A:\n");
sPymbed 0:c4152c628df5 696 DumpOctetString(cK->iv, cK->ivSz);
sPymbed 0:c4152c628df5 697 printf("B:\n");
sPymbed 0:c4152c628df5 698 DumpOctetString(sK->iv, sK->ivSz);
sPymbed 0:c4152c628df5 699 printf("C:\n");
sPymbed 0:c4152c628df5 700 DumpOctetString(cK->encKey, cK->encKeySz);
sPymbed 0:c4152c628df5 701 printf("D:\n");
sPymbed 0:c4152c628df5 702 DumpOctetString(sK->encKey, sK->encKeySz);
sPymbed 0:c4152c628df5 703 printf("E:\n");
sPymbed 0:c4152c628df5 704 DumpOctetString(cK->macKey, cK->macKeySz);
sPymbed 0:c4152c628df5 705 printf("F:\n");
sPymbed 0:c4152c628df5 706 DumpOctetString(sK->macKey, sK->macKeySz);
sPymbed 0:c4152c628df5 707 printf("\n");
sPymbed 0:c4152c628df5 708 }
sPymbed 0:c4152c628df5 709 #endif /* SHOW_SECRETS */
sPymbed 0:c4152c628df5 710
sPymbed 0:c4152c628df5 711 return ret;
sPymbed 0:c4152c628df5 712 }
sPymbed 0:c4152c628df5 713
sPymbed 0:c4152c628df5 714
sPymbed 0:c4152c628df5 715 typedef struct {
sPymbed 0:c4152c628df5 716 byte id;
sPymbed 0:c4152c628df5 717 const char* name;
sPymbed 0:c4152c628df5 718 } NameIdPair;
sPymbed 0:c4152c628df5 719
sPymbed 0:c4152c628df5 720
sPymbed 0:c4152c628df5 721 static const NameIdPair NameIdMap[] = {
sPymbed 0:c4152c628df5 722 { ID_NONE, "none" },
sPymbed 0:c4152c628df5 723
sPymbed 0:c4152c628df5 724 /* Encryption IDs */
sPymbed 0:c4152c628df5 725 { ID_AES128_CBC, "aes128-cbc" },
sPymbed 0:c4152c628df5 726 { ID_AES128_GCM, "aes128-gcm@openssh.com" },
sPymbed 0:c4152c628df5 727
sPymbed 0:c4152c628df5 728 /* Integrity IDs */
sPymbed 0:c4152c628df5 729 { ID_HMAC_SHA1, "hmac-sha1" },
sPymbed 0:c4152c628df5 730 { ID_HMAC_SHA1_96, "hmac-sha1-96" },
sPymbed 0:c4152c628df5 731 { ID_HMAC_SHA2_256, "hmac-sha2-256" },
sPymbed 0:c4152c628df5 732
sPymbed 0:c4152c628df5 733 /* Key Exchange IDs */
sPymbed 0:c4152c628df5 734 { ID_DH_GROUP1_SHA1, "diffie-hellman-group1-sha1" },
sPymbed 0:c4152c628df5 735 { ID_DH_GROUP14_SHA1, "diffie-hellman-group14-sha1" },
sPymbed 0:c4152c628df5 736 { ID_DH_GEX_SHA256, "diffie-hellman-group-exchange-sha256" },
sPymbed 0:c4152c628df5 737 { ID_ECDH_SHA2_NISTP256, "ecdh-sha2-nistp256" },
sPymbed 0:c4152c628df5 738 { ID_ECDH_SHA2_NISTP384, "ecdh-sha2-nistp384" },
sPymbed 0:c4152c628df5 739 { ID_ECDH_SHA2_NISTP521, "ecdh-sha2-nistp521" },
sPymbed 0:c4152c628df5 740
sPymbed 0:c4152c628df5 741 /* Public Key IDs */
sPymbed 0:c4152c628df5 742 { ID_SSH_RSA, "ssh-rsa" },
sPymbed 0:c4152c628df5 743 { ID_ECDSA_SHA2_NISTP256, "ecdsa-sha2-nistp256" },
sPymbed 0:c4152c628df5 744 { ID_ECDSA_SHA2_NISTP384, "ecdsa-sha2-nistp384" },
sPymbed 0:c4152c628df5 745 { ID_ECDSA_SHA2_NISTP521, "ecdsa-sha2-nistp521" },
sPymbed 0:c4152c628df5 746
sPymbed 0:c4152c628df5 747 /* Service IDs */
sPymbed 0:c4152c628df5 748 { ID_SERVICE_USERAUTH, "ssh-userauth" },
sPymbed 0:c4152c628df5 749 { ID_SERVICE_CONNECTION, "ssh-connection" },
sPymbed 0:c4152c628df5 750
sPymbed 0:c4152c628df5 751 /* UserAuth IDs */
sPymbed 0:c4152c628df5 752 { ID_USERAUTH_PASSWORD, "password" },
sPymbed 0:c4152c628df5 753 { ID_USERAUTH_PUBLICKEY, "publickey" },
sPymbed 0:c4152c628df5 754
sPymbed 0:c4152c628df5 755 /* Channel Type IDs */
sPymbed 0:c4152c628df5 756 { ID_CHANTYPE_SESSION, "session" }
sPymbed 0:c4152c628df5 757 };
sPymbed 0:c4152c628df5 758
sPymbed 0:c4152c628df5 759
sPymbed 0:c4152c628df5 760 byte NameToId(const char* name, word32 nameSz)
sPymbed 0:c4152c628df5 761 {
sPymbed 0:c4152c628df5 762 byte id = ID_UNKNOWN;
sPymbed 0:c4152c628df5 763 word32 i;
sPymbed 0:c4152c628df5 764
sPymbed 0:c4152c628df5 765 for (i = 0; i < (sizeof(NameIdMap)/sizeof(NameIdPair)); i++) {
sPymbed 0:c4152c628df5 766 if (nameSz == WSTRLEN(NameIdMap[i].name) &&
sPymbed 0:c4152c628df5 767 WSTRNCMP(name, NameIdMap[i].name, nameSz) == 0) {
sPymbed 0:c4152c628df5 768
sPymbed 0:c4152c628df5 769 id = NameIdMap[i].id;
sPymbed 0:c4152c628df5 770 break;
sPymbed 0:c4152c628df5 771 }
sPymbed 0:c4152c628df5 772 }
sPymbed 0:c4152c628df5 773
sPymbed 0:c4152c628df5 774 return id;
sPymbed 0:c4152c628df5 775 }
sPymbed 0:c4152c628df5 776
sPymbed 0:c4152c628df5 777
sPymbed 0:c4152c628df5 778 const char* IdToName(byte id)
sPymbed 0:c4152c628df5 779 {
sPymbed 0:c4152c628df5 780 const char* name = "unknown";
sPymbed 0:c4152c628df5 781 word32 i;
sPymbed 0:c4152c628df5 782
sPymbed 0:c4152c628df5 783 for (i = 0; i < (sizeof(NameIdMap)/sizeof(NameIdPair)); i++) {
sPymbed 0:c4152c628df5 784 if (NameIdMap[i].id == id) {
sPymbed 0:c4152c628df5 785 name = NameIdMap[i].name;
sPymbed 0:c4152c628df5 786 break;
sPymbed 0:c4152c628df5 787 }
sPymbed 0:c4152c628df5 788 }
sPymbed 0:c4152c628df5 789
sPymbed 0:c4152c628df5 790 return name;
sPymbed 0:c4152c628df5 791 }
sPymbed 0:c4152c628df5 792
sPymbed 0:c4152c628df5 793
sPymbed 0:c4152c628df5 794 WOLFSSH_CHANNEL* ChannelNew(WOLFSSH* ssh, byte channelType,
sPymbed 0:c4152c628df5 795 word32 initialWindowSz, word32 maxPacketSz)
sPymbed 0:c4152c628df5 796 {
sPymbed 0:c4152c628df5 797 WOLFSSH_CHANNEL* newChannel = NULL;
sPymbed 0:c4152c628df5 798
sPymbed 0:c4152c628df5 799 WLOG(WS_LOG_DEBUG, "Entering ChannelNew()");
sPymbed 0:c4152c628df5 800 if (ssh == NULL || ssh->ctx == NULL) {
sPymbed 0:c4152c628df5 801 WLOG(WS_LOG_DEBUG, "Trying to create new channel without ssh or ctx");
sPymbed 0:c4152c628df5 802 }
sPymbed 0:c4152c628df5 803 else {
sPymbed 0:c4152c628df5 804 void* heap = ssh->ctx->heap;
sPymbed 0:c4152c628df5 805
sPymbed 0:c4152c628df5 806 newChannel = (WOLFSSH_CHANNEL*)WMALLOC(sizeof(WOLFSSH_CHANNEL),
sPymbed 0:c4152c628df5 807 heap, DYNTYPE_CHANNEL);
sPymbed 0:c4152c628df5 808 if (newChannel != NULL)
sPymbed 0:c4152c628df5 809 {
sPymbed 0:c4152c628df5 810 byte* buffer;
sPymbed 0:c4152c628df5 811
sPymbed 0:c4152c628df5 812 buffer = (byte*)WMALLOC(initialWindowSz, heap, DYNTYPE_BUFFER);
sPymbed 0:c4152c628df5 813 if (buffer != NULL) {
sPymbed 0:c4152c628df5 814 WMEMSET(newChannel, 0, sizeof(WOLFSSH_CHANNEL));
sPymbed 0:c4152c628df5 815 newChannel->channelType = channelType;
sPymbed 0:c4152c628df5 816 newChannel->channel = ssh->nextChannel++;
sPymbed 0:c4152c628df5 817 newChannel->windowSz = initialWindowSz;
sPymbed 0:c4152c628df5 818 newChannel->maxPacketSz = maxPacketSz;
sPymbed 0:c4152c628df5 819 /*
sPymbed 0:c4152c628df5 820 * In the context of the channel input buffer, the buffer is
sPymbed 0:c4152c628df5 821 * a fixed size. The property length will be the insert point
sPymbed 0:c4152c628df5 822 * for new received data. The property idx will be the pull
sPymbed 0:c4152c628df5 823 * point for the data.
sPymbed 0:c4152c628df5 824 */
sPymbed 0:c4152c628df5 825 newChannel->inputBuffer.heap = heap;
sPymbed 0:c4152c628df5 826 newChannel->inputBuffer.buffer = buffer;
sPymbed 0:c4152c628df5 827 newChannel->inputBuffer.bufferSz = initialWindowSz;
sPymbed 0:c4152c628df5 828 newChannel->inputBuffer.dynamicFlag = 1;
sPymbed 0:c4152c628df5 829 }
sPymbed 0:c4152c628df5 830 else {
sPymbed 0:c4152c628df5 831 WLOG(WS_LOG_DEBUG, "Unable to allocate new channel's buffer");
sPymbed 0:c4152c628df5 832 WFREE(newChannel, heap, DYNTYPE_CHANNEL);
sPymbed 0:c4152c628df5 833 newChannel = NULL;
sPymbed 0:c4152c628df5 834 }
sPymbed 0:c4152c628df5 835 }
sPymbed 0:c4152c628df5 836 else {
sPymbed 0:c4152c628df5 837 WLOG(WS_LOG_DEBUG, "Unable to allocate new channel");
sPymbed 0:c4152c628df5 838 }
sPymbed 0:c4152c628df5 839 }
sPymbed 0:c4152c628df5 840
sPymbed 0:c4152c628df5 841 WLOG(WS_LOG_INFO, "Leaving ChannelNew(), ret = %p", newChannel);
sPymbed 0:c4152c628df5 842
sPymbed 0:c4152c628df5 843 return newChannel;
sPymbed 0:c4152c628df5 844 }
sPymbed 0:c4152c628df5 845
sPymbed 0:c4152c628df5 846
sPymbed 0:c4152c628df5 847 void ChannelDelete(WOLFSSH_CHANNEL* channel, void* heap)
sPymbed 0:c4152c628df5 848 {
sPymbed 0:c4152c628df5 849 (void)heap;
sPymbed 0:c4152c628df5 850
sPymbed 0:c4152c628df5 851 if (channel) {
sPymbed 0:c4152c628df5 852 WFREE(channel->inputBuffer.buffer,
sPymbed 0:c4152c628df5 853 channel->inputBuffer.heap, DYNTYPE_BUFFER);
sPymbed 0:c4152c628df5 854 WFREE(channel, heap, DYNTYPE_CHANNEL);
sPymbed 0:c4152c628df5 855 }
sPymbed 0:c4152c628df5 856 }
sPymbed 0:c4152c628df5 857
sPymbed 0:c4152c628df5 858
sPymbed 0:c4152c628df5 859 #define FIND_SELF 0
sPymbed 0:c4152c628df5 860 #define FIND_PEER 1
sPymbed 0:c4152c628df5 861
sPymbed 0:c4152c628df5 862 WOLFSSH_CHANNEL* ChannelFind(WOLFSSH* ssh, word32 channel, byte peer)
sPymbed 0:c4152c628df5 863 {
sPymbed 0:c4152c628df5 864 WOLFSSH_CHANNEL* findChannel = NULL;
sPymbed 0:c4152c628df5 865
sPymbed 0:c4152c628df5 866 WLOG(WS_LOG_DEBUG, "Entering ChannelFind()");
sPymbed 0:c4152c628df5 867
sPymbed 0:c4152c628df5 868 if (ssh == NULL) {
sPymbed 0:c4152c628df5 869 WLOG(WS_LOG_DEBUG, "Null ssh, not looking for channel");
sPymbed 0:c4152c628df5 870 }
sPymbed 0:c4152c628df5 871 else {
sPymbed 0:c4152c628df5 872 WOLFSSH_CHANNEL* list = ssh->channelList;
sPymbed 0:c4152c628df5 873 word32 listSz = ssh->channelListSz;
sPymbed 0:c4152c628df5 874
sPymbed 0:c4152c628df5 875 while (list && listSz) {
sPymbed 0:c4152c628df5 876 if (channel == ((peer == FIND_PEER) ?
sPymbed 0:c4152c628df5 877 list->peerChannel : list->channel)) {
sPymbed 0:c4152c628df5 878 findChannel = list;
sPymbed 0:c4152c628df5 879 break;
sPymbed 0:c4152c628df5 880 }
sPymbed 0:c4152c628df5 881 list = list->next;
sPymbed 0:c4152c628df5 882 listSz--;
sPymbed 0:c4152c628df5 883 }
sPymbed 0:c4152c628df5 884 }
sPymbed 0:c4152c628df5 885
sPymbed 0:c4152c628df5 886 WLOG(WS_LOG_DEBUG, "Leaving ChannelFind(): %p", findChannel);
sPymbed 0:c4152c628df5 887
sPymbed 0:c4152c628df5 888 return findChannel;
sPymbed 0:c4152c628df5 889 }
sPymbed 0:c4152c628df5 890
sPymbed 0:c4152c628df5 891
sPymbed 0:c4152c628df5 892 int ChannelUpdate(WOLFSSH_CHANNEL* channel, word32 peerChannelId,
sPymbed 0:c4152c628df5 893 word32 peerInitialWindowSz, word32 peerMaxPacketSz)
sPymbed 0:c4152c628df5 894 {
sPymbed 0:c4152c628df5 895 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 896
sPymbed 0:c4152c628df5 897 if (channel == NULL)
sPymbed 0:c4152c628df5 898 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 899 else {
sPymbed 0:c4152c628df5 900 channel->peerChannel = peerChannelId;
sPymbed 0:c4152c628df5 901 channel->peerWindowSz = peerInitialWindowSz;
sPymbed 0:c4152c628df5 902 channel->peerMaxPacketSz = peerMaxPacketSz;
sPymbed 0:c4152c628df5 903 }
sPymbed 0:c4152c628df5 904
sPymbed 0:c4152c628df5 905 return ret;
sPymbed 0:c4152c628df5 906 }
sPymbed 0:c4152c628df5 907
sPymbed 0:c4152c628df5 908
sPymbed 0:c4152c628df5 909 static int ChannelAppend(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
sPymbed 0:c4152c628df5 910 {
sPymbed 0:c4152c628df5 911 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 912
sPymbed 0:c4152c628df5 913 WLOG(WS_LOG_DEBUG, "Entering ChannelAppend()");
sPymbed 0:c4152c628df5 914
sPymbed 0:c4152c628df5 915 if (ssh == NULL || channel == NULL)
sPymbed 0:c4152c628df5 916 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 917
sPymbed 0:c4152c628df5 918 if (ssh->channelList == NULL) {
sPymbed 0:c4152c628df5 919 ssh->channelList = channel;
sPymbed 0:c4152c628df5 920 ssh->channelListSz = 1;
sPymbed 0:c4152c628df5 921 }
sPymbed 0:c4152c628df5 922 else {
sPymbed 0:c4152c628df5 923 WOLFSSH_CHANNEL* cur = ssh->channelList;
sPymbed 0:c4152c628df5 924 while (cur->next != NULL)
sPymbed 0:c4152c628df5 925 cur = cur->next;
sPymbed 0:c4152c628df5 926 cur->next = channel;
sPymbed 0:c4152c628df5 927 ssh->channelListSz++;
sPymbed 0:c4152c628df5 928 }
sPymbed 0:c4152c628df5 929
sPymbed 0:c4152c628df5 930 WLOG(WS_LOG_DEBUG, "Leaving ChannelAppend(), ret = %d", ret);
sPymbed 0:c4152c628df5 931 return ret;
sPymbed 0:c4152c628df5 932 }
sPymbed 0:c4152c628df5 933
sPymbed 0:c4152c628df5 934
sPymbed 0:c4152c628df5 935 int ChannelRemove(WOLFSSH* ssh, word32 channel, byte peer)
sPymbed 0:c4152c628df5 936 {
sPymbed 0:c4152c628df5 937 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 938 WOLFSSH_CHANNEL* list;
sPymbed 0:c4152c628df5 939
sPymbed 0:c4152c628df5 940 WLOG(WS_LOG_DEBUG, "Entering ChannelRemove()");
sPymbed 0:c4152c628df5 941
sPymbed 0:c4152c628df5 942 if (ssh == NULL)
sPymbed 0:c4152c628df5 943 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 944
sPymbed 0:c4152c628df5 945 list = ssh->channelList;
sPymbed 0:c4152c628df5 946 if (list == NULL)
sPymbed 0:c4152c628df5 947 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 948
sPymbed 0:c4152c628df5 949 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 950 WOLFSSH_CHANNEL* prev = NULL;
sPymbed 0:c4152c628df5 951 word32 listSz = ssh->channelListSz;
sPymbed 0:c4152c628df5 952
sPymbed 0:c4152c628df5 953 while (list && listSz) {
sPymbed 0:c4152c628df5 954 if (channel == ((peer == FIND_PEER) ?
sPymbed 0:c4152c628df5 955 list->peerChannel : list->channel)) {
sPymbed 0:c4152c628df5 956 if (prev == NULL)
sPymbed 0:c4152c628df5 957 ssh->channelList = list->next;
sPymbed 0:c4152c628df5 958 else
sPymbed 0:c4152c628df5 959 prev->next = list->next;
sPymbed 0:c4152c628df5 960 ChannelDelete(list, ssh->ctx->heap);
sPymbed 0:c4152c628df5 961 ssh->channelListSz--;
sPymbed 0:c4152c628df5 962
sPymbed 0:c4152c628df5 963 break;
sPymbed 0:c4152c628df5 964 }
sPymbed 0:c4152c628df5 965 prev = list;
sPymbed 0:c4152c628df5 966 list = list->next;
sPymbed 0:c4152c628df5 967 listSz--;
sPymbed 0:c4152c628df5 968 }
sPymbed 0:c4152c628df5 969
sPymbed 0:c4152c628df5 970 if (listSz == 0)
sPymbed 0:c4152c628df5 971 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 972 }
sPymbed 0:c4152c628df5 973
sPymbed 0:c4152c628df5 974 WLOG(WS_LOG_DEBUG, "Leaving ChannelRemove(), ret = %d", ret);
sPymbed 0:c4152c628df5 975 return ret;
sPymbed 0:c4152c628df5 976 }
sPymbed 0:c4152c628df5 977
sPymbed 0:c4152c628df5 978
sPymbed 0:c4152c628df5 979 int ChannelPutData(WOLFSSH_CHANNEL* channel, byte* data, word32 dataSz)
sPymbed 0:c4152c628df5 980 {
sPymbed 0:c4152c628df5 981 Buffer* inBuf;
sPymbed 0:c4152c628df5 982
sPymbed 0:c4152c628df5 983 WLOG(WS_LOG_DEBUG, "Entering ChannelPutData()");
sPymbed 0:c4152c628df5 984
sPymbed 0:c4152c628df5 985 if (channel == NULL || data == NULL)
sPymbed 0:c4152c628df5 986 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 987
sPymbed 0:c4152c628df5 988 inBuf = &channel->inputBuffer;
sPymbed 0:c4152c628df5 989
sPymbed 0:c4152c628df5 990 if (inBuf->length < inBuf->bufferSz &&
sPymbed 0:c4152c628df5 991 inBuf->length + dataSz <= inBuf->bufferSz) {
sPymbed 0:c4152c628df5 992
sPymbed 0:c4152c628df5 993 WMEMCPY(inBuf->buffer + inBuf->length, data, dataSz);
sPymbed 0:c4152c628df5 994 inBuf->length += dataSz;
sPymbed 0:c4152c628df5 995
sPymbed 0:c4152c628df5 996 WLOG(WS_LOG_INFO, " dataSz = %u", dataSz);
sPymbed 0:c4152c628df5 997 WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
sPymbed 0:c4152c628df5 998 channel->windowSz -= dataSz;
sPymbed 0:c4152c628df5 999 WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
sPymbed 0:c4152c628df5 1000 }
sPymbed 0:c4152c628df5 1001 else {
sPymbed 0:c4152c628df5 1002 return WS_RECV_OVERFLOW_E;
sPymbed 0:c4152c628df5 1003 }
sPymbed 0:c4152c628df5 1004
sPymbed 0:c4152c628df5 1005 return WS_SUCCESS;
sPymbed 0:c4152c628df5 1006 }
sPymbed 0:c4152c628df5 1007
sPymbed 0:c4152c628df5 1008
sPymbed 0:c4152c628df5 1009 int BufferInit(Buffer* buffer, word32 size, void* heap)
sPymbed 0:c4152c628df5 1010 {
sPymbed 0:c4152c628df5 1011 if (buffer == NULL)
sPymbed 0:c4152c628df5 1012 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 1013
sPymbed 0:c4152c628df5 1014 if (size <= STATIC_BUFFER_LEN)
sPymbed 0:c4152c628df5 1015 size = STATIC_BUFFER_LEN;
sPymbed 0:c4152c628df5 1016
sPymbed 0:c4152c628df5 1017 WMEMSET(buffer, 0, sizeof(Buffer));
sPymbed 0:c4152c628df5 1018 buffer->heap = heap;
sPymbed 0:c4152c628df5 1019 buffer->bufferSz = size;
sPymbed 0:c4152c628df5 1020 if (size > STATIC_BUFFER_LEN) {
sPymbed 0:c4152c628df5 1021 buffer->buffer = (byte*)WMALLOC(size, heap, DYNTYPE_BUFFER);
sPymbed 0:c4152c628df5 1022 if (buffer->buffer == NULL)
sPymbed 0:c4152c628df5 1023 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 1024 buffer->dynamicFlag = 1;
sPymbed 0:c4152c628df5 1025 }
sPymbed 0:c4152c628df5 1026 else
sPymbed 0:c4152c628df5 1027 buffer->buffer = buffer->staticBuffer;
sPymbed 0:c4152c628df5 1028
sPymbed 0:c4152c628df5 1029 return WS_SUCCESS;
sPymbed 0:c4152c628df5 1030 }
sPymbed 0:c4152c628df5 1031
sPymbed 0:c4152c628df5 1032
sPymbed 0:c4152c628df5 1033 int GrowBuffer(Buffer* buf, word32 sz, word32 usedSz)
sPymbed 0:c4152c628df5 1034 {
sPymbed 0:c4152c628df5 1035 #if 0
sPymbed 0:c4152c628df5 1036 WLOG(WS_LOG_DEBUG, "GB: buf = %p", buf);
sPymbed 0:c4152c628df5 1037 WLOG(WS_LOG_DEBUG, "GB: sz = %d", sz);
sPymbed 0:c4152c628df5 1038 WLOG(WS_LOG_DEBUG, "GB: usedSz = %d", usedSz);
sPymbed 0:c4152c628df5 1039 #endif
sPymbed 0:c4152c628df5 1040 /* New buffer will end up being sz+usedSz long
sPymbed 0:c4152c628df5 1041 * empty space at the head of the buffer will be compressed */
sPymbed 0:c4152c628df5 1042 if (buf != NULL) {
sPymbed 0:c4152c628df5 1043 word32 newSz = sz + usedSz;
sPymbed 0:c4152c628df5 1044 /*WLOG(WS_LOG_DEBUG, "GB: newSz = %d", newSz);*/
sPymbed 0:c4152c628df5 1045
sPymbed 0:c4152c628df5 1046 if (newSz > buf->bufferSz) {
sPymbed 0:c4152c628df5 1047 byte* newBuffer = (byte*)WMALLOC(newSz,
sPymbed 0:c4152c628df5 1048 buf->heap, DYNTYPE_BUFFER);
sPymbed 0:c4152c628df5 1049
sPymbed 0:c4152c628df5 1050 if (newBuffer == NULL)
sPymbed 0:c4152c628df5 1051 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 1052
sPymbed 0:c4152c628df5 1053 /*WLOG(WS_LOG_DEBUG, "GB: resizing buffer");*/
sPymbed 0:c4152c628df5 1054 if (buf->length > 0)
sPymbed 0:c4152c628df5 1055 WMEMCPY(newBuffer, buf->buffer + buf->idx, usedSz);
sPymbed 0:c4152c628df5 1056
sPymbed 0:c4152c628df5 1057 if (!buf->dynamicFlag)
sPymbed 0:c4152c628df5 1058 buf->dynamicFlag = 1;
sPymbed 0:c4152c628df5 1059 else
sPymbed 0:c4152c628df5 1060 WFREE(buf->buffer, buf->heap, DYNTYPE_BUFFER);
sPymbed 0:c4152c628df5 1061
sPymbed 0:c4152c628df5 1062 buf->buffer = newBuffer;
sPymbed 0:c4152c628df5 1063 buf->bufferSz = newSz;
sPymbed 0:c4152c628df5 1064 buf->length = usedSz;
sPymbed 0:c4152c628df5 1065 buf->idx = 0;
sPymbed 0:c4152c628df5 1066 }
sPymbed 0:c4152c628df5 1067 }
sPymbed 0:c4152c628df5 1068
sPymbed 0:c4152c628df5 1069 return WS_SUCCESS;
sPymbed 0:c4152c628df5 1070 }
sPymbed 0:c4152c628df5 1071
sPymbed 0:c4152c628df5 1072
sPymbed 0:c4152c628df5 1073 void ShrinkBuffer(Buffer* buf, int forcedFree)
sPymbed 0:c4152c628df5 1074 {
sPymbed 0:c4152c628df5 1075 WLOG(WS_LOG_DEBUG, "Entering ShrinkBuffer()");
sPymbed 0:c4152c628df5 1076
sPymbed 0:c4152c628df5 1077 if (buf != NULL) {
sPymbed 0:c4152c628df5 1078 word32 usedSz = buf->length - buf->idx;
sPymbed 0:c4152c628df5 1079
sPymbed 0:c4152c628df5 1080 WLOG(WS_LOG_DEBUG, "SB: usedSz = %u, forcedFree = %u",
sPymbed 0:c4152c628df5 1081 usedSz, forcedFree);
sPymbed 0:c4152c628df5 1082
sPymbed 0:c4152c628df5 1083 if (!forcedFree && usedSz > STATIC_BUFFER_LEN)
sPymbed 0:c4152c628df5 1084 return;
sPymbed 0:c4152c628df5 1085
sPymbed 0:c4152c628df5 1086 if (!forcedFree && usedSz) {
sPymbed 0:c4152c628df5 1087 WLOG(WS_LOG_DEBUG, "SB: shifting down");
sPymbed 0:c4152c628df5 1088 WMEMCPY(buf->staticBuffer, buf->buffer + buf->idx, usedSz);
sPymbed 0:c4152c628df5 1089 }
sPymbed 0:c4152c628df5 1090
sPymbed 0:c4152c628df5 1091 if (buf->dynamicFlag) {
sPymbed 0:c4152c628df5 1092 WLOG(WS_LOG_DEBUG, "SB: releasing dynamic buffer");
sPymbed 0:c4152c628df5 1093 WFREE(buf->buffer, buf->heap, DYNTYPE_BUFFER);
sPymbed 0:c4152c628df5 1094 }
sPymbed 0:c4152c628df5 1095 buf->dynamicFlag = 0;
sPymbed 0:c4152c628df5 1096 buf->buffer = buf->staticBuffer;
sPymbed 0:c4152c628df5 1097 buf->bufferSz = STATIC_BUFFER_LEN;
sPymbed 0:c4152c628df5 1098 buf->length = forcedFree ? 0 : usedSz;
sPymbed 0:c4152c628df5 1099 buf->idx = 0;
sPymbed 0:c4152c628df5 1100 }
sPymbed 0:c4152c628df5 1101
sPymbed 0:c4152c628df5 1102 WLOG(WS_LOG_DEBUG, "Leaving ShrinkBuffer()");
sPymbed 0:c4152c628df5 1103 }
sPymbed 0:c4152c628df5 1104
sPymbed 0:c4152c628df5 1105
sPymbed 0:c4152c628df5 1106 static int Receive(WOLFSSH* ssh, byte* buf, word32 sz)
sPymbed 0:c4152c628df5 1107 {
sPymbed 0:c4152c628df5 1108 int recvd;
sPymbed 0:c4152c628df5 1109
sPymbed 0:c4152c628df5 1110 if (ssh->ctx->ioRecvCb == NULL) {
sPymbed 0:c4152c628df5 1111 WLOG(WS_LOG_DEBUG, "Your IO Recv callback is null, please set");
sPymbed 0:c4152c628df5 1112 return -1;
sPymbed 0:c4152c628df5 1113 }
sPymbed 0:c4152c628df5 1114
sPymbed 0:c4152c628df5 1115 retry:
sPymbed 0:c4152c628df5 1116 recvd = ssh->ctx->ioRecvCb(ssh, buf, sz, ssh->ioReadCtx);
sPymbed 0:c4152c628df5 1117 WLOG(WS_LOG_DEBUG, "Receive: recvd = %d", recvd);
sPymbed 0:c4152c628df5 1118 if (recvd < 0)
sPymbed 0:c4152c628df5 1119 switch (recvd) {
sPymbed 0:c4152c628df5 1120 case WS_CBIO_ERR_GENERAL: /* general/unknown error */
sPymbed 0:c4152c628df5 1121 return -1;
sPymbed 0:c4152c628df5 1122
sPymbed 0:c4152c628df5 1123 case WS_CBIO_ERR_WANT_READ: /* want read, would block */
sPymbed 0:c4152c628df5 1124 return WS_WANT_READ;
sPymbed 0:c4152c628df5 1125
sPymbed 0:c4152c628df5 1126 case WS_CBIO_ERR_CONN_RST: /* connection reset */
sPymbed 0:c4152c628df5 1127 ssh->connReset = 1;
sPymbed 0:c4152c628df5 1128 return -1;
sPymbed 0:c4152c628df5 1129
sPymbed 0:c4152c628df5 1130 case WS_CBIO_ERR_ISR: /* interrupt */
sPymbed 0:c4152c628df5 1131 goto retry;
sPymbed 0:c4152c628df5 1132
sPymbed 0:c4152c628df5 1133 case WS_CBIO_ERR_CONN_CLOSE: /* peer closed connection */
sPymbed 0:c4152c628df5 1134 ssh->isClosed = 1;
sPymbed 0:c4152c628df5 1135 return -1;
sPymbed 0:c4152c628df5 1136
sPymbed 0:c4152c628df5 1137 case WS_CBIO_ERR_TIMEOUT:
sPymbed 0:c4152c628df5 1138 return -1;
sPymbed 0:c4152c628df5 1139
sPymbed 0:c4152c628df5 1140 default:
sPymbed 0:c4152c628df5 1141 return recvd;
sPymbed 0:c4152c628df5 1142 }
sPymbed 0:c4152c628df5 1143
sPymbed 0:c4152c628df5 1144 return recvd;
sPymbed 0:c4152c628df5 1145 }
sPymbed 0:c4152c628df5 1146
sPymbed 0:c4152c628df5 1147
sPymbed 0:c4152c628df5 1148 static int GetInputText(WOLFSSH* ssh, byte** pEol)
sPymbed 0:c4152c628df5 1149 {
sPymbed 0:c4152c628df5 1150 int gotLine = 0;
sPymbed 0:c4152c628df5 1151 int inSz = 255;
sPymbed 0:c4152c628df5 1152 int in;
sPymbed 0:c4152c628df5 1153 char *eol;
sPymbed 0:c4152c628df5 1154
sPymbed 0:c4152c628df5 1155 if (GrowBuffer(&ssh->inputBuffer, inSz, 0) < 0)
sPymbed 0:c4152c628df5 1156 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 1157
sPymbed 0:c4152c628df5 1158 do {
sPymbed 0:c4152c628df5 1159 in = Receive(ssh,
sPymbed 0:c4152c628df5 1160 ssh->inputBuffer.buffer + ssh->inputBuffer.length, inSz);
sPymbed 0:c4152c628df5 1161
sPymbed 0:c4152c628df5 1162 if (in == -1)
sPymbed 0:c4152c628df5 1163 return WS_SOCKET_ERROR_E;
sPymbed 0:c4152c628df5 1164
sPymbed 0:c4152c628df5 1165 if (in == WS_WANT_READ)
sPymbed 0:c4152c628df5 1166 return WS_WANT_READ;
sPymbed 0:c4152c628df5 1167
sPymbed 0:c4152c628df5 1168 if (in > inSz)
sPymbed 0:c4152c628df5 1169 return WS_RECV_OVERFLOW_E;
sPymbed 0:c4152c628df5 1170
sPymbed 0:c4152c628df5 1171 ssh->inputBuffer.length += in;
sPymbed 0:c4152c628df5 1172 inSz -= in;
sPymbed 0:c4152c628df5 1173
sPymbed 0:c4152c628df5 1174 eol = WSTRNSTR((const char*)ssh->inputBuffer.buffer, "\r\n",
sPymbed 0:c4152c628df5 1175 ssh->inputBuffer.length);
sPymbed 0:c4152c628df5 1176
sPymbed 0:c4152c628df5 1177 if (eol)
sPymbed 0:c4152c628df5 1178 gotLine = 1;
sPymbed 0:c4152c628df5 1179
sPymbed 0:c4152c628df5 1180 } while (!gotLine && inSz);
sPymbed 0:c4152c628df5 1181
sPymbed 0:c4152c628df5 1182 if (pEol)
sPymbed 0:c4152c628df5 1183 *pEol = (byte*)eol;
sPymbed 0:c4152c628df5 1184
sPymbed 0:c4152c628df5 1185 return (gotLine ? WS_SUCCESS : WS_VERSION_E);
sPymbed 0:c4152c628df5 1186 }
sPymbed 0:c4152c628df5 1187
sPymbed 0:c4152c628df5 1188
sPymbed 0:c4152c628df5 1189 static int SendBuffered(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 1190 {
sPymbed 0:c4152c628df5 1191 WLOG(WS_LOG_DEBUG, "Entering SendBuffered()");
sPymbed 0:c4152c628df5 1192
sPymbed 0:c4152c628df5 1193 if (ssh->ctx->ioSendCb == NULL) {
sPymbed 0:c4152c628df5 1194 WLOG(WS_LOG_DEBUG, "Your IO Send callback is null, please set");
sPymbed 0:c4152c628df5 1195 return WS_SOCKET_ERROR_E;
sPymbed 0:c4152c628df5 1196 }
sPymbed 0:c4152c628df5 1197
sPymbed 0:c4152c628df5 1198 while (ssh->outputBuffer.length > 0) {
sPymbed 0:c4152c628df5 1199 int sent = ssh->ctx->ioSendCb(ssh,
sPymbed 0:c4152c628df5 1200 ssh->outputBuffer.buffer + ssh->outputBuffer.idx,
sPymbed 0:c4152c628df5 1201 ssh->outputBuffer.length, ssh->ioReadCtx);
sPymbed 0:c4152c628df5 1202
sPymbed 0:c4152c628df5 1203 if (sent < 0) {
sPymbed 0:c4152c628df5 1204 switch (sent) {
sPymbed 0:c4152c628df5 1205 case WS_CBIO_ERR_WANT_WRITE: /* want write, would block */
sPymbed 0:c4152c628df5 1206 return WS_WANT_WRITE;
sPymbed 0:c4152c628df5 1207
sPymbed 0:c4152c628df5 1208 case WS_CBIO_ERR_CONN_RST: /* connection reset */
sPymbed 0:c4152c628df5 1209 ssh->connReset = 1;
sPymbed 0:c4152c628df5 1210 break;
sPymbed 0:c4152c628df5 1211
sPymbed 0:c4152c628df5 1212 case WS_CBIO_ERR_CONN_CLOSE: /* peer closed connection */
sPymbed 0:c4152c628df5 1213 ssh->isClosed = 1;
sPymbed 0:c4152c628df5 1214 break;
sPymbed 0:c4152c628df5 1215 }
sPymbed 0:c4152c628df5 1216 return WS_SOCKET_ERROR_E;
sPymbed 0:c4152c628df5 1217 }
sPymbed 0:c4152c628df5 1218
sPymbed 0:c4152c628df5 1219 if ((word32)sent > ssh->outputBuffer.length) {
sPymbed 0:c4152c628df5 1220 WLOG(WS_LOG_DEBUG, "SendBuffered() out of bounds read");
sPymbed 0:c4152c628df5 1221 return WS_SEND_OOB_READ_E;
sPymbed 0:c4152c628df5 1222 }
sPymbed 0:c4152c628df5 1223
sPymbed 0:c4152c628df5 1224 ssh->outputBuffer.idx += sent;
sPymbed 0:c4152c628df5 1225 ssh->outputBuffer.length -= sent;
sPymbed 0:c4152c628df5 1226 }
sPymbed 0:c4152c628df5 1227
sPymbed 0:c4152c628df5 1228 ssh->outputBuffer.idx = 0;
sPymbed 0:c4152c628df5 1229
sPymbed 0:c4152c628df5 1230 WLOG(WS_LOG_DEBUG, "SB: Shrinking output buffer");
sPymbed 0:c4152c628df5 1231 ShrinkBuffer(&ssh->outputBuffer, 0);
sPymbed 0:c4152c628df5 1232
sPymbed 0:c4152c628df5 1233 HighwaterCheck(ssh, WOLFSSH_HWSIDE_TRANSMIT);
sPymbed 0:c4152c628df5 1234
sPymbed 0:c4152c628df5 1235 return WS_SUCCESS;
sPymbed 0:c4152c628df5 1236 }
sPymbed 0:c4152c628df5 1237
sPymbed 0:c4152c628df5 1238
sPymbed 0:c4152c628df5 1239 static int GetInputData(WOLFSSH* ssh, word32 size)
sPymbed 0:c4152c628df5 1240 {
sPymbed 0:c4152c628df5 1241 int in;
sPymbed 0:c4152c628df5 1242 int inSz;
sPymbed 0:c4152c628df5 1243 int maxLength;
sPymbed 0:c4152c628df5 1244 int usedLength;
sPymbed 0:c4152c628df5 1245
sPymbed 0:c4152c628df5 1246 /* check max input length */
sPymbed 0:c4152c628df5 1247 usedLength = ssh->inputBuffer.length - ssh->inputBuffer.idx;
sPymbed 0:c4152c628df5 1248 maxLength = ssh->inputBuffer.bufferSz - usedLength;
sPymbed 0:c4152c628df5 1249 inSz = (int)(size - usedLength); /* from last partial read */
sPymbed 0:c4152c628df5 1250 #if 0
sPymbed 0:c4152c628df5 1251 WLOG(WS_LOG_DEBUG, "GID: size = %u", size);
sPymbed 0:c4152c628df5 1252 WLOG(WS_LOG_DEBUG, "GID: usedLength = %d", usedLength);
sPymbed 0:c4152c628df5 1253 WLOG(WS_LOG_DEBUG, "GID: maxLength = %d", maxLength);
sPymbed 0:c4152c628df5 1254 WLOG(WS_LOG_DEBUG, "GID: inSz = %d", inSz);
sPymbed 0:c4152c628df5 1255 #endif
sPymbed 0:c4152c628df5 1256 /*
sPymbed 0:c4152c628df5 1257 * usedLength - how much untouched data is in the buffer
sPymbed 0:c4152c628df5 1258 * maxLength - how much empty space is in the buffer
sPymbed 0:c4152c628df5 1259 * inSz - difference between requested data and empty space in the buffer
sPymbed 0:c4152c628df5 1260 * how much more we need to allocate
sPymbed 0:c4152c628df5 1261 */
sPymbed 0:c4152c628df5 1262
sPymbed 0:c4152c628df5 1263 if (inSz <= 0)
sPymbed 0:c4152c628df5 1264 return WS_SUCCESS;
sPymbed 0:c4152c628df5 1265
sPymbed 0:c4152c628df5 1266 /*
sPymbed 0:c4152c628df5 1267 * If we need more space than there is left in the buffer grow buffer.
sPymbed 0:c4152c628df5 1268 * Growing the buffer also compresses empty space at the head of the
sPymbed 0:c4152c628df5 1269 * buffer and resets idx to 0.
sPymbed 0:c4152c628df5 1270 */
sPymbed 0:c4152c628df5 1271 if (inSz > maxLength) {
sPymbed 0:c4152c628df5 1272 if (GrowBuffer(&ssh->inputBuffer, size, usedLength) < 0)
sPymbed 0:c4152c628df5 1273 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 1274 }
sPymbed 0:c4152c628df5 1275
sPymbed 0:c4152c628df5 1276 /* Put buffer data at start if not there */
sPymbed 0:c4152c628df5 1277 /* Compress the buffer if needed, i.e. buffer idx is non-zero */
sPymbed 0:c4152c628df5 1278 if (usedLength > 0 && ssh->inputBuffer.idx != 0) {
sPymbed 0:c4152c628df5 1279 WMEMMOVE(ssh->inputBuffer.buffer,
sPymbed 0:c4152c628df5 1280 ssh->inputBuffer.buffer + ssh->inputBuffer.idx,
sPymbed 0:c4152c628df5 1281 usedLength);
sPymbed 0:c4152c628df5 1282 }
sPymbed 0:c4152c628df5 1283
sPymbed 0:c4152c628df5 1284 /* remove processed data */
sPymbed 0:c4152c628df5 1285 ssh->inputBuffer.idx = 0;
sPymbed 0:c4152c628df5 1286 ssh->inputBuffer.length = usedLength;
sPymbed 0:c4152c628df5 1287
sPymbed 0:c4152c628df5 1288 /* read data from network */
sPymbed 0:c4152c628df5 1289 do {
sPymbed 0:c4152c628df5 1290 in = Receive(ssh,
sPymbed 0:c4152c628df5 1291 ssh->inputBuffer.buffer + ssh->inputBuffer.length, inSz);
sPymbed 0:c4152c628df5 1292 if (in == -1) {
sPymbed 0:c4152c628df5 1293 //ESP_LOGE("WOLFSSH", "GetInputData: WS_SOCKET_ERROR_E");
sPymbed 0:c4152c628df5 1294 return WS_SOCKET_ERROR_E;
sPymbed 0:c4152c628df5 1295 }
sPymbed 0:c4152c628df5 1296
sPymbed 0:c4152c628df5 1297 if (in == WS_WANT_READ) {
sPymbed 0:c4152c628df5 1298 //ESP_LOGE("WOLFSSH", "GetInputData: WS_WANT_READ");
sPymbed 0:c4152c628df5 1299 return WS_WANT_READ;
sPymbed 0:c4152c628df5 1300 }
sPymbed 0:c4152c628df5 1301
sPymbed 0:c4152c628df5 1302 if (in > inSz) {
sPymbed 0:c4152c628df5 1303 //ESP_LOGE("WOLFSSH", "GetInputData: WS_RECV_OVERFLOW_E");
sPymbed 0:c4152c628df5 1304 return WS_RECV_OVERFLOW_E;
sPymbed 0:c4152c628df5 1305 }
sPymbed 0:c4152c628df5 1306
sPymbed 0:c4152c628df5 1307 ssh->inputBuffer.length += in;
sPymbed 0:c4152c628df5 1308 inSz -= in;
sPymbed 0:c4152c628df5 1309
sPymbed 0:c4152c628df5 1310 } while (ssh->inputBuffer.length < size);
sPymbed 0:c4152c628df5 1311
sPymbed 0:c4152c628df5 1312 return 0;
sPymbed 0:c4152c628df5 1313 }
sPymbed 0:c4152c628df5 1314
sPymbed 0:c4152c628df5 1315
sPymbed 0:c4152c628df5 1316 static int GetBoolean(byte* v, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 1317 {
sPymbed 0:c4152c628df5 1318 int result = WS_BUFFER_E;
sPymbed 0:c4152c628df5 1319
sPymbed 0:c4152c628df5 1320 if (*idx < len) {
sPymbed 0:c4152c628df5 1321 *v = buf[*idx];
sPymbed 0:c4152c628df5 1322 *idx += BOOLEAN_SZ;
sPymbed 0:c4152c628df5 1323 result = WS_SUCCESS;
sPymbed 0:c4152c628df5 1324 }
sPymbed 0:c4152c628df5 1325
sPymbed 0:c4152c628df5 1326 return result;
sPymbed 0:c4152c628df5 1327 }
sPymbed 0:c4152c628df5 1328
sPymbed 0:c4152c628df5 1329 void ato32(const byte* c, word32 * u32){}
sPymbed 0:c4152c628df5 1330
sPymbed 0:c4152c628df5 1331 static int GetUint32(word32* v, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 1332 {
sPymbed 0:c4152c628df5 1333 int result = WS_BUFFER_E;
sPymbed 0:c4152c628df5 1334
sPymbed 0:c4152c628df5 1335 if (*idx < len && *idx + UINT32_SZ <= len) {
sPymbed 0:c4152c628df5 1336 ato32(buf + *idx, v);
sPymbed 0:c4152c628df5 1337 *idx += UINT32_SZ;
sPymbed 0:c4152c628df5 1338 result = WS_SUCCESS;
sPymbed 0:c4152c628df5 1339 }
sPymbed 0:c4152c628df5 1340
sPymbed 0:c4152c628df5 1341 return result;
sPymbed 0:c4152c628df5 1342 }
sPymbed 0:c4152c628df5 1343
sPymbed 0:c4152c628df5 1344
sPymbed 0:c4152c628df5 1345 /* Gets the size of the mpint, and puts the pointer to the start of
sPymbed 0:c4152c628df5 1346 * buf's number into *mpint. This function does not copy. */
sPymbed 0:c4152c628df5 1347 static int GetMpint(word32* mpintSz, byte** mpint,
sPymbed 0:c4152c628df5 1348 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 1349 {
sPymbed 0:c4152c628df5 1350 int result;
sPymbed 0:c4152c628df5 1351
sPymbed 0:c4152c628df5 1352 result = GetUint32(mpintSz, buf, len, idx);
sPymbed 0:c4152c628df5 1353
sPymbed 0:c4152c628df5 1354 if (result == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1355 result = WS_BUFFER_E;
sPymbed 0:c4152c628df5 1356
sPymbed 0:c4152c628df5 1357 if (*idx < len && *idx + *mpintSz <= len) {
sPymbed 0:c4152c628df5 1358 *mpint = buf + *idx;
sPymbed 0:c4152c628df5 1359 *idx += *mpintSz;
sPymbed 0:c4152c628df5 1360 result = WS_SUCCESS;
sPymbed 0:c4152c628df5 1361 }
sPymbed 0:c4152c628df5 1362 }
sPymbed 0:c4152c628df5 1363
sPymbed 0:c4152c628df5 1364 return result;
sPymbed 0:c4152c628df5 1365 }
sPymbed 0:c4152c628df5 1366
sPymbed 0:c4152c628df5 1367
sPymbed 0:c4152c628df5 1368 /* Gets the size of a string, copies it as much of it as will fit in
sPymbed 0:c4152c628df5 1369 * the provided buffer, and terminates it with a NULL. */
sPymbed 0:c4152c628df5 1370 static int GetString(char* s, word32* sSz,
sPymbed 0:c4152c628df5 1371 byte* buf, word32 len, word32 *idx)
sPymbed 0:c4152c628df5 1372 {
sPymbed 0:c4152c628df5 1373 int result;
sPymbed 0:c4152c628df5 1374 word32 strSz;
sPymbed 0:c4152c628df5 1375
sPymbed 0:c4152c628df5 1376 result = GetUint32(&strSz, buf, len, idx);
sPymbed 0:c4152c628df5 1377
sPymbed 0:c4152c628df5 1378 if (result == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1379 result = WS_BUFFER_E;
sPymbed 0:c4152c628df5 1380 if (*idx < len && *idx + strSz <= len) {
sPymbed 0:c4152c628df5 1381 *sSz = (strSz >= *sSz) ? *sSz : strSz;
sPymbed 0:c4152c628df5 1382 WMEMCPY(s, buf + *idx, *sSz);
sPymbed 0:c4152c628df5 1383 *idx += strSz;
sPymbed 0:c4152c628df5 1384 s[*sSz] = 0;
sPymbed 0:c4152c628df5 1385 result = WS_SUCCESS;
sPymbed 0:c4152c628df5 1386 }
sPymbed 0:c4152c628df5 1387 }
sPymbed 0:c4152c628df5 1388
sPymbed 0:c4152c628df5 1389 return result;
sPymbed 0:c4152c628df5 1390 }
sPymbed 0:c4152c628df5 1391
sPymbed 0:c4152c628df5 1392
sPymbed 0:c4152c628df5 1393 static int GetNameList(byte* idList, word32* idListSz,
sPymbed 0:c4152c628df5 1394 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 1395 {
sPymbed 0:c4152c628df5 1396 byte idListIdx;
sPymbed 0:c4152c628df5 1397 word32 nameListSz, nameListIdx;
sPymbed 0:c4152c628df5 1398 word32 begin;
sPymbed 0:c4152c628df5 1399 byte* name;
sPymbed 0:c4152c628df5 1400 word32 nameSz;
sPymbed 0:c4152c628df5 1401 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 1402
sPymbed 0:c4152c628df5 1403 WLOG(WS_LOG_DEBUG, "Entering GetNameList()");
sPymbed 0:c4152c628df5 1404
sPymbed 0:c4152c628df5 1405 if (idList == NULL || idListSz == NULL ||
sPymbed 0:c4152c628df5 1406 buf == NULL || len == 0 || idx == NULL) {
sPymbed 0:c4152c628df5 1407
sPymbed 0:c4152c628df5 1408 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 1409 }
sPymbed 0:c4152c628df5 1410
sPymbed 0:c4152c628df5 1411 /*
sPymbed 0:c4152c628df5 1412 * This iterates across a name list and finds names that end in either the
sPymbed 0:c4152c628df5 1413 * comma delimeter or with the end of the list.
sPymbed 0:c4152c628df5 1414 */
sPymbed 0:c4152c628df5 1415
sPymbed 0:c4152c628df5 1416 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1417 begin = *idx;
sPymbed 0:c4152c628df5 1418 if (begin >= len || begin + 4 >= len)
sPymbed 0:c4152c628df5 1419 ret = WS_BUFFER_E;
sPymbed 0:c4152c628df5 1420 }
sPymbed 0:c4152c628df5 1421
sPymbed 0:c4152c628df5 1422 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1423 ret = GetUint32(&nameListSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1424
sPymbed 0:c4152c628df5 1425 /* The strings we want are now in the bounds of the message, and the
sPymbed 0:c4152c628df5 1426 * length of the list. Find the commas, or end of list, and then decode
sPymbed 0:c4152c628df5 1427 * the values. */
sPymbed 0:c4152c628df5 1428 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1429 name = buf + begin;
sPymbed 0:c4152c628df5 1430 nameSz = 0;
sPymbed 0:c4152c628df5 1431 nameListIdx = 0;
sPymbed 0:c4152c628df5 1432 idListIdx = 0;
sPymbed 0:c4152c628df5 1433
sPymbed 0:c4152c628df5 1434 while (nameListIdx < nameListSz) {
sPymbed 0:c4152c628df5 1435 nameListIdx++;
sPymbed 0:c4152c628df5 1436
sPymbed 0:c4152c628df5 1437 if (nameListIdx == nameListSz)
sPymbed 0:c4152c628df5 1438 nameSz++;
sPymbed 0:c4152c628df5 1439
sPymbed 0:c4152c628df5 1440 if (nameListIdx == nameListSz || name[nameSz] == ',') {
sPymbed 0:c4152c628df5 1441 byte id;
sPymbed 0:c4152c628df5 1442
sPymbed 0:c4152c628df5 1443 id = NameToId((char*)name, nameSz);
sPymbed 0:c4152c628df5 1444 {
sPymbed 0:c4152c628df5 1445 const char* displayName = IdToName(id);
sPymbed 0:c4152c628df5 1446 if (displayName) {
sPymbed 0:c4152c628df5 1447 WLOG(WS_LOG_DEBUG, "DNL: name ID = %s", displayName);
sPymbed 0:c4152c628df5 1448 }
sPymbed 0:c4152c628df5 1449 }
sPymbed 0:c4152c628df5 1450 if (id != ID_UNKNOWN)
sPymbed 0:c4152c628df5 1451 idList[idListIdx++] = id;
sPymbed 0:c4152c628df5 1452
sPymbed 0:c4152c628df5 1453 name += 1 + nameSz;
sPymbed 0:c4152c628df5 1454 nameSz = 0;
sPymbed 0:c4152c628df5 1455 }
sPymbed 0:c4152c628df5 1456 else
sPymbed 0:c4152c628df5 1457 nameSz++;
sPymbed 0:c4152c628df5 1458 }
sPymbed 0:c4152c628df5 1459
sPymbed 0:c4152c628df5 1460 begin += nameListSz;
sPymbed 0:c4152c628df5 1461 *idListSz = idListIdx;
sPymbed 0:c4152c628df5 1462 *idx = begin;
sPymbed 0:c4152c628df5 1463 }
sPymbed 0:c4152c628df5 1464
sPymbed 0:c4152c628df5 1465 WLOG(WS_LOG_DEBUG, "Leaving GetNameList(), ret = %d", ret);
sPymbed 0:c4152c628df5 1466 return ret;
sPymbed 0:c4152c628df5 1467 }
sPymbed 0:c4152c628df5 1468
sPymbed 0:c4152c628df5 1469
sPymbed 0:c4152c628df5 1470 static const byte cannedEncAlgo[] = {ID_AES128_GCM, ID_AES128_CBC};
sPymbed 0:c4152c628df5 1471 static const byte cannedMacAlgo[] = {ID_HMAC_SHA2_256, ID_HMAC_SHA1_96,
sPymbed 0:c4152c628df5 1472 ID_HMAC_SHA1};
sPymbed 0:c4152c628df5 1473 static const byte cannedKeyAlgoRsa[] = {ID_SSH_RSA};
sPymbed 0:c4152c628df5 1474 static const byte cannedKeyAlgoEcc256[] = {ID_ECDSA_SHA2_NISTP256};
sPymbed 0:c4152c628df5 1475 static const byte cannedKeyAlgoEcc384[] = {ID_ECDSA_SHA2_NISTP384};
sPymbed 0:c4152c628df5 1476 static const byte cannedKeyAlgoEcc521[] = {ID_ECDSA_SHA2_NISTP521};
sPymbed 0:c4152c628df5 1477 static const byte cannedKexAlgo[] = {ID_ECDH_SHA2_NISTP256,
sPymbed 0:c4152c628df5 1478 ID_DH_GEX_SHA256,
sPymbed 0:c4152c628df5 1479 ID_DH_GROUP14_SHA1,
sPymbed 0:c4152c628df5 1480 ID_DH_GROUP1_SHA1};
sPymbed 0:c4152c628df5 1481
sPymbed 0:c4152c628df5 1482 static const word32 cannedEncAlgoSz = sizeof(cannedEncAlgo);
sPymbed 0:c4152c628df5 1483 static const word32 cannedMacAlgoSz = sizeof(cannedMacAlgo);
sPymbed 0:c4152c628df5 1484 static const word32 cannedKeyAlgoRsaSz = sizeof(cannedKeyAlgoRsa);
sPymbed 0:c4152c628df5 1485 static const word32 cannedKeyAlgoEcc256Sz = sizeof(cannedKeyAlgoEcc256);
sPymbed 0:c4152c628df5 1486 static const word32 cannedKeyAlgoEcc384Sz = sizeof(cannedKeyAlgoEcc384);
sPymbed 0:c4152c628df5 1487 static const word32 cannedKeyAlgoEcc521Sz = sizeof(cannedKeyAlgoEcc521);
sPymbed 0:c4152c628df5 1488 static const word32 cannedKexAlgoSz = sizeof(cannedKexAlgo);
sPymbed 0:c4152c628df5 1489
sPymbed 0:c4152c628df5 1490
sPymbed 0:c4152c628df5 1491 static byte MatchIdLists(const byte* left, word32 leftSz,
sPymbed 0:c4152c628df5 1492 const byte* right, word32 rightSz)
sPymbed 0:c4152c628df5 1493 {
sPymbed 0:c4152c628df5 1494 word32 i, j;
sPymbed 0:c4152c628df5 1495
sPymbed 0:c4152c628df5 1496 if (left != NULL && leftSz > 0 && right != NULL && rightSz > 0) {
sPymbed 0:c4152c628df5 1497 for (i = 0; i < leftSz; i++) {
sPymbed 0:c4152c628df5 1498 for (j = 0; j < rightSz; j++) {
sPymbed 0:c4152c628df5 1499 if (left[i] == right[j]) {
sPymbed 0:c4152c628df5 1500 #if 0
sPymbed 0:c4152c628df5 1501 WLOG(WS_LOG_DEBUG, "MID: matched %s", IdToName(left[i]));
sPymbed 0:c4152c628df5 1502 #endif
sPymbed 0:c4152c628df5 1503 return left[i];
sPymbed 0:c4152c628df5 1504 }
sPymbed 0:c4152c628df5 1505 }
sPymbed 0:c4152c628df5 1506 }
sPymbed 0:c4152c628df5 1507 }
sPymbed 0:c4152c628df5 1508
sPymbed 0:c4152c628df5 1509 return ID_UNKNOWN;
sPymbed 0:c4152c628df5 1510 }
sPymbed 0:c4152c628df5 1511
sPymbed 0:c4152c628df5 1512
sPymbed 0:c4152c628df5 1513 static INLINE byte BlockSzForId(byte id)
sPymbed 0:c4152c628df5 1514 {
sPymbed 0:c4152c628df5 1515 switch (id) {
sPymbed 0:c4152c628df5 1516 case ID_AES128_CBC:
sPymbed 0:c4152c628df5 1517 case ID_AES128_GCM:
sPymbed 0:c4152c628df5 1518 return AES_BLOCK_SIZE;
sPymbed 0:c4152c628df5 1519 default:
sPymbed 0:c4152c628df5 1520 return 0;
sPymbed 0:c4152c628df5 1521 }
sPymbed 0:c4152c628df5 1522 }
sPymbed 0:c4152c628df5 1523
sPymbed 0:c4152c628df5 1524
sPymbed 0:c4152c628df5 1525 static INLINE byte MacSzForId(byte id)
sPymbed 0:c4152c628df5 1526 {
sPymbed 0:c4152c628df5 1527 switch (id) {
sPymbed 0:c4152c628df5 1528 case ID_HMAC_SHA1:
sPymbed 0:c4152c628df5 1529 return SHA_DIGEST_SIZE;
sPymbed 0:c4152c628df5 1530 case ID_HMAC_SHA1_96:
sPymbed 0:c4152c628df5 1531 return SHA1_96_SZ;
sPymbed 0:c4152c628df5 1532 case ID_HMAC_SHA2_256:
sPymbed 0:c4152c628df5 1533 return SHA256_DIGEST_SIZE;
sPymbed 0:c4152c628df5 1534 default:
sPymbed 0:c4152c628df5 1535 return 0;
sPymbed 0:c4152c628df5 1536 }
sPymbed 0:c4152c628df5 1537 }
sPymbed 0:c4152c628df5 1538
sPymbed 0:c4152c628df5 1539
sPymbed 0:c4152c628df5 1540 static INLINE byte KeySzForId(byte id)
sPymbed 0:c4152c628df5 1541 {
sPymbed 0:c4152c628df5 1542 switch (id) {
sPymbed 0:c4152c628df5 1543 case ID_HMAC_SHA1:
sPymbed 0:c4152c628df5 1544 case ID_HMAC_SHA1_96:
sPymbed 0:c4152c628df5 1545 return SHA_DIGEST_SIZE;
sPymbed 0:c4152c628df5 1546 case ID_HMAC_SHA2_256:
sPymbed 0:c4152c628df5 1547 return SHA256_DIGEST_SIZE;
sPymbed 0:c4152c628df5 1548 case ID_AES128_CBC:
sPymbed 0:c4152c628df5 1549 case ID_AES128_GCM:
sPymbed 0:c4152c628df5 1550 return AES_BLOCK_SIZE;
sPymbed 0:c4152c628df5 1551 default:
sPymbed 0:c4152c628df5 1552 return 0;
sPymbed 0:c4152c628df5 1553 }
sPymbed 0:c4152c628df5 1554 }
sPymbed 0:c4152c628df5 1555
sPymbed 0:c4152c628df5 1556
sPymbed 0:c4152c628df5 1557 static INLINE byte HashForId(byte id)
sPymbed 0:c4152c628df5 1558 {
sPymbed 0:c4152c628df5 1559 switch (id) {
sPymbed 0:c4152c628df5 1560 case ID_DH_GROUP1_SHA1:
sPymbed 0:c4152c628df5 1561 case ID_DH_GROUP14_SHA1:
sPymbed 0:c4152c628df5 1562 case ID_SSH_RSA:
sPymbed 0:c4152c628df5 1563 return WC_HASH_TYPE_SHA;
sPymbed 0:c4152c628df5 1564 case ID_DH_GEX_SHA256:
sPymbed 0:c4152c628df5 1565 case ID_ECDH_SHA2_NISTP256:
sPymbed 0:c4152c628df5 1566 case ID_ECDSA_SHA2_NISTP256:
sPymbed 0:c4152c628df5 1567 return WC_HASH_TYPE_SHA256;
sPymbed 0:c4152c628df5 1568 case ID_ECDH_SHA2_NISTP384:
sPymbed 0:c4152c628df5 1569 case ID_ECDSA_SHA2_NISTP384:
sPymbed 0:c4152c628df5 1570 return WC_HASH_TYPE_SHA384;
sPymbed 0:c4152c628df5 1571 case ID_ECDH_SHA2_NISTP521:
sPymbed 0:c4152c628df5 1572 case ID_ECDSA_SHA2_NISTP521:
sPymbed 0:c4152c628df5 1573 return WC_HASH_TYPE_SHA512;
sPymbed 0:c4152c628df5 1574 default:
sPymbed 0:c4152c628df5 1575 return WC_HASH_TYPE_NONE;
sPymbed 0:c4152c628df5 1576 }
sPymbed 0:c4152c628df5 1577 }
sPymbed 0:c4152c628df5 1578
sPymbed 0:c4152c628df5 1579
sPymbed 0:c4152c628df5 1580 static INLINE int wcPrimeForId(byte id)
sPymbed 0:c4152c628df5 1581 {
sPymbed 0:c4152c628df5 1582 switch (id) {
sPymbed 0:c4152c628df5 1583 case ID_ECDH_SHA2_NISTP256:
sPymbed 0:c4152c628df5 1584 case ID_ECDSA_SHA2_NISTP256:
sPymbed 0:c4152c628df5 1585 return ECC_SECP256R1;
sPymbed 0:c4152c628df5 1586 case ID_ECDH_SHA2_NISTP384:
sPymbed 0:c4152c628df5 1587 case ID_ECDSA_SHA2_NISTP384:
sPymbed 0:c4152c628df5 1588 return ECC_SECP384R1;
sPymbed 0:c4152c628df5 1589 case ID_ECDH_SHA2_NISTP521:
sPymbed 0:c4152c628df5 1590 case ID_ECDSA_SHA2_NISTP521:
sPymbed 0:c4152c628df5 1591 return ECC_SECP521R1;
sPymbed 0:c4152c628df5 1592 default:
sPymbed 0:c4152c628df5 1593 return ECC_CURVE_INVALID;
sPymbed 0:c4152c628df5 1594 }
sPymbed 0:c4152c628df5 1595 }
sPymbed 0:c4152c628df5 1596 static INLINE const char *PrimeNameForId(byte id)
sPymbed 0:c4152c628df5 1597 {
sPymbed 0:c4152c628df5 1598 switch (id) {
sPymbed 0:c4152c628df5 1599 case ID_ECDH_SHA2_NISTP256:
sPymbed 0:c4152c628df5 1600 case ID_ECDSA_SHA2_NISTP256:
sPymbed 0:c4152c628df5 1601 return "nistp256";
sPymbed 0:c4152c628df5 1602 case ID_ECDH_SHA2_NISTP384:
sPymbed 0:c4152c628df5 1603 case ID_ECDSA_SHA2_NISTP384:
sPymbed 0:c4152c628df5 1604 return "nistp384";
sPymbed 0:c4152c628df5 1605 case ID_ECDH_SHA2_NISTP521:
sPymbed 0:c4152c628df5 1606 case ID_ECDSA_SHA2_NISTP521:
sPymbed 0:c4152c628df5 1607 return "nistp521";
sPymbed 0:c4152c628df5 1608 default:
sPymbed 0:c4152c628df5 1609 return "unknown";
sPymbed 0:c4152c628df5 1610 }
sPymbed 0:c4152c628df5 1611 }
sPymbed 0:c4152c628df5 1612
sPymbed 0:c4152c628df5 1613
sPymbed 0:c4152c628df5 1614 static INLINE byte AeadModeForId(byte id)
sPymbed 0:c4152c628df5 1615 {
sPymbed 0:c4152c628df5 1616 return (id == ID_AES128_GCM);
sPymbed 0:c4152c628df5 1617 }
sPymbed 0:c4152c628df5 1618
sPymbed 0:c4152c628df5 1619
sPymbed 0:c4152c628df5 1620 static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 1621 {
sPymbed 0:c4152c628df5 1622 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 1623 byte algoId;
sPymbed 0:c4152c628df5 1624 byte list[6];
sPymbed 0:c4152c628df5 1625 word32 listSz;
sPymbed 0:c4152c628df5 1626 word32 skipSz;
sPymbed 0:c4152c628df5 1627 word32 begin;
sPymbed 0:c4152c628df5 1628
sPymbed 0:c4152c628df5 1629 WLOG(WS_LOG_DEBUG, "Entering DoKexInit()");
sPymbed 0:c4152c628df5 1630
sPymbed 0:c4152c628df5 1631 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 1632 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 1633
sPymbed 0:c4152c628df5 1634 /*
sPymbed 0:c4152c628df5 1635 * I don't need to save what the client sends here. I should decode
sPymbed 0:c4152c628df5 1636 * each list into a local array of IDs, and pick the one the peer is
sPymbed 0:c4152c628df5 1637 * using that's on my known list, or verify that the one the peer can
sPymbed 0:c4152c628df5 1638 * support the other direction is on my known list. All I need to do
sPymbed 0:c4152c628df5 1639 * is save the actual values.
sPymbed 0:c4152c628df5 1640 */
sPymbed 0:c4152c628df5 1641
sPymbed 0:c4152c628df5 1642 if (ssh->handshake == NULL) {
sPymbed 0:c4152c628df5 1643 ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);
sPymbed 0:c4152c628df5 1644 if (ssh->handshake == NULL) {
sPymbed 0:c4152c628df5 1645 WLOG(WS_LOG_DEBUG, "Couldn't allocate handshake info");
sPymbed 0:c4152c628df5 1646 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 1647 }
sPymbed 0:c4152c628df5 1648 }
sPymbed 0:c4152c628df5 1649
sPymbed 0:c4152c628df5 1650 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1651 begin = *idx;
sPymbed 0:c4152c628df5 1652
sPymbed 0:c4152c628df5 1653 /* Check that the cookie exists inside the message */
sPymbed 0:c4152c628df5 1654 if (begin + COOKIE_SZ > len) {
sPymbed 0:c4152c628df5 1655 /* error, out of bounds */
sPymbed 0:c4152c628df5 1656 ret = WS_PARSE_E;
sPymbed 0:c4152c628df5 1657 }
sPymbed 0:c4152c628df5 1658 else {
sPymbed 0:c4152c628df5 1659 /* Move past the cookie. */
sPymbed 0:c4152c628df5 1660 begin += COOKIE_SZ;
sPymbed 0:c4152c628df5 1661 }
sPymbed 0:c4152c628df5 1662 }
sPymbed 0:c4152c628df5 1663
sPymbed 0:c4152c628df5 1664 /* KEX Algorithms */
sPymbed 0:c4152c628df5 1665 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1666 WLOG(WS_LOG_DEBUG, "DKI: KEX Algorithms");
sPymbed 0:c4152c628df5 1667 listSz = 2;
sPymbed 0:c4152c628df5 1668 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1669 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1670 algoId = MatchIdLists(list, listSz, cannedKexAlgo, cannedKexAlgoSz);
sPymbed 0:c4152c628df5 1671 if (algoId == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1672 WLOG(WS_LOG_DEBUG, "Unable to negotiate KEX Algo");
sPymbed 0:c4152c628df5 1673 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1674 }
sPymbed 0:c4152c628df5 1675 else {
sPymbed 0:c4152c628df5 1676 ssh->handshake->kexId = algoId;
sPymbed 0:c4152c628df5 1677 ssh->handshake->hashId = HashForId(algoId);
sPymbed 0:c4152c628df5 1678 }
sPymbed 0:c4152c628df5 1679 }
sPymbed 0:c4152c628df5 1680 }
sPymbed 0:c4152c628df5 1681
sPymbed 0:c4152c628df5 1682 /* Server Host Key Algorithms */
sPymbed 0:c4152c628df5 1683 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1684 WLOG(WS_LOG_DEBUG, "DKI: Server Host Key Algorithms");
sPymbed 0:c4152c628df5 1685 listSz = 1;
sPymbed 0:c4152c628df5 1686 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1687 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1688 const byte *cannedKeyAlgo;
sPymbed 0:c4152c628df5 1689 word32 cannedKeyAlgoSz;
sPymbed 0:c4152c628df5 1690
sPymbed 0:c4152c628df5 1691 switch (ssh->ctx->useEcc) {
sPymbed 0:c4152c628df5 1692 case ECC_SECP256R1:
sPymbed 0:c4152c628df5 1693 cannedKeyAlgo = cannedKeyAlgoEcc256;
sPymbed 0:c4152c628df5 1694 cannedKeyAlgoSz = cannedKeyAlgoEcc256Sz;
sPymbed 0:c4152c628df5 1695 break;
sPymbed 0:c4152c628df5 1696 case ECC_SECP384R1:
sPymbed 0:c4152c628df5 1697 cannedKeyAlgo = cannedKeyAlgoEcc384;
sPymbed 0:c4152c628df5 1698 cannedKeyAlgoSz = cannedKeyAlgoEcc384Sz;
sPymbed 0:c4152c628df5 1699 break;
sPymbed 0:c4152c628df5 1700 case ECC_SECP521R1:
sPymbed 0:c4152c628df5 1701 cannedKeyAlgo = cannedKeyAlgoEcc521;
sPymbed 0:c4152c628df5 1702 cannedKeyAlgoSz = cannedKeyAlgoEcc521Sz;
sPymbed 0:c4152c628df5 1703 break;
sPymbed 0:c4152c628df5 1704 default:
sPymbed 0:c4152c628df5 1705 cannedKeyAlgo = cannedKeyAlgoRsa;
sPymbed 0:c4152c628df5 1706 cannedKeyAlgoSz = cannedKeyAlgoRsaSz;
sPymbed 0:c4152c628df5 1707 }
sPymbed 0:c4152c628df5 1708 algoId = MatchIdLists(list, listSz,
sPymbed 0:c4152c628df5 1709 cannedKeyAlgo, cannedKeyAlgoSz);
sPymbed 0:c4152c628df5 1710 if (algoId == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1711 WLOG(WS_LOG_DEBUG, "Unable to negotiate Server Host Key Algo");
sPymbed 0:c4152c628df5 1712 return WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1713 }
sPymbed 0:c4152c628df5 1714 else
sPymbed 0:c4152c628df5 1715 ssh->handshake->pubKeyId = algoId;
sPymbed 0:c4152c628df5 1716 }
sPymbed 0:c4152c628df5 1717 }
sPymbed 0:c4152c628df5 1718
sPymbed 0:c4152c628df5 1719 /* Enc Algorithms - Client to Server */
sPymbed 0:c4152c628df5 1720 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1721 WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Client to Server");
sPymbed 0:c4152c628df5 1722 listSz = 3;
sPymbed 0:c4152c628df5 1723 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1724 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1725 algoId = MatchIdLists(list, listSz, cannedEncAlgo, cannedEncAlgoSz);
sPymbed 0:c4152c628df5 1726 if (algoId == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1727 WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo C2S");
sPymbed 0:c4152c628df5 1728 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1729 }
sPymbed 0:c4152c628df5 1730 }
sPymbed 0:c4152c628df5 1731 }
sPymbed 0:c4152c628df5 1732
sPymbed 0:c4152c628df5 1733 /* Enc Algorithms - Server to Client */
sPymbed 0:c4152c628df5 1734 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1735 WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Server to Client");
sPymbed 0:c4152c628df5 1736 listSz = 3;
sPymbed 0:c4152c628df5 1737 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1738 if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1739 WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
sPymbed 0:c4152c628df5 1740 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1741 }
sPymbed 0:c4152c628df5 1742 else {
sPymbed 0:c4152c628df5 1743 ssh->handshake->encryptId = algoId;
sPymbed 0:c4152c628df5 1744 ssh->handshake->aeadMode = AeadModeForId(algoId);
sPymbed 0:c4152c628df5 1745 ssh->handshake->blockSz = BlockSzForId(algoId);
sPymbed 0:c4152c628df5 1746 ssh->handshake->keys.encKeySz =
sPymbed 0:c4152c628df5 1747 ssh->handshake->peerKeys.encKeySz =
sPymbed 0:c4152c628df5 1748 KeySzForId(algoId);
sPymbed 0:c4152c628df5 1749 if (!ssh->handshake->aeadMode) {
sPymbed 0:c4152c628df5 1750 ssh->handshake->keys.ivSz =
sPymbed 0:c4152c628df5 1751 ssh->handshake->peerKeys.ivSz =
sPymbed 0:c4152c628df5 1752 ssh->handshake->blockSz;
sPymbed 0:c4152c628df5 1753 }
sPymbed 0:c4152c628df5 1754 else {
sPymbed 0:c4152c628df5 1755 ssh->handshake->keys.ivSz =
sPymbed 0:c4152c628df5 1756 ssh->handshake->peerKeys.ivSz =
sPymbed 0:c4152c628df5 1757 AEAD_NONCE_SZ;
sPymbed 0:c4152c628df5 1758 ssh->handshake->macSz = ssh->handshake->blockSz;
sPymbed 0:c4152c628df5 1759 }
sPymbed 0:c4152c628df5 1760 }
sPymbed 0:c4152c628df5 1761 }
sPymbed 0:c4152c628df5 1762
sPymbed 0:c4152c628df5 1763 /* MAC Algorithms - Client to Server */
sPymbed 0:c4152c628df5 1764 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1765 WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Client to Server");
sPymbed 0:c4152c628df5 1766 listSz = 2;
sPymbed 0:c4152c628df5 1767 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1768 if (ret == WS_SUCCESS && !ssh->aeadMode) {
sPymbed 0:c4152c628df5 1769 algoId = MatchIdLists(list, listSz, cannedMacAlgo, cannedMacAlgoSz);
sPymbed 0:c4152c628df5 1770 if (algoId == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1771 WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
sPymbed 0:c4152c628df5 1772 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1773 }
sPymbed 0:c4152c628df5 1774 }
sPymbed 0:c4152c628df5 1775 }
sPymbed 0:c4152c628df5 1776
sPymbed 0:c4152c628df5 1777 /* MAC Algorithms - Server to Client */
sPymbed 0:c4152c628df5 1778 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1779 WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Server to Client");
sPymbed 0:c4152c628df5 1780 listSz = 2;
sPymbed 0:c4152c628df5 1781 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1782 if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) {
sPymbed 0:c4152c628df5 1783 if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1784 WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
sPymbed 0:c4152c628df5 1785 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1786 }
sPymbed 0:c4152c628df5 1787 else {
sPymbed 0:c4152c628df5 1788 ssh->handshake->macId = algoId;
sPymbed 0:c4152c628df5 1789 ssh->handshake->macSz = MacSzForId(algoId);
sPymbed 0:c4152c628df5 1790 ssh->handshake->keys.macKeySz =
sPymbed 0:c4152c628df5 1791 ssh->handshake->peerKeys.macKeySz =
sPymbed 0:c4152c628df5 1792 KeySzForId(algoId);
sPymbed 0:c4152c628df5 1793 }
sPymbed 0:c4152c628df5 1794 }
sPymbed 0:c4152c628df5 1795 }
sPymbed 0:c4152c628df5 1796
sPymbed 0:c4152c628df5 1797 /* Compression Algorithms - Client to Server */
sPymbed 0:c4152c628df5 1798 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1799 /* The compression algorithm lists should have none as a value. */
sPymbed 0:c4152c628df5 1800 algoId = ID_NONE;
sPymbed 0:c4152c628df5 1801
sPymbed 0:c4152c628df5 1802 WLOG(WS_LOG_DEBUG, "DKI: Compression Algorithms - Client to Server");
sPymbed 0:c4152c628df5 1803 listSz = 1;
sPymbed 0:c4152c628df5 1804 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1805 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1806 if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1807 WLOG(WS_LOG_DEBUG, "Unable to negotiate Compression Algo C2S");
sPymbed 0:c4152c628df5 1808 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1809 }
sPymbed 0:c4152c628df5 1810 }
sPymbed 0:c4152c628df5 1811 }
sPymbed 0:c4152c628df5 1812
sPymbed 0:c4152c628df5 1813 /* Compression Algorithms - Server to Client */
sPymbed 0:c4152c628df5 1814 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1815 WLOG(WS_LOG_DEBUG, "DKI: Compression Algorithms - Server to Client");
sPymbed 0:c4152c628df5 1816 listSz = 1;
sPymbed 0:c4152c628df5 1817 ret = GetNameList(list, &listSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1818 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1819 if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
sPymbed 0:c4152c628df5 1820 WLOG(WS_LOG_DEBUG, "Unable to negotiate Compression Algo S2C");
sPymbed 0:c4152c628df5 1821 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 1822 }
sPymbed 0:c4152c628df5 1823 }
sPymbed 0:c4152c628df5 1824 }
sPymbed 0:c4152c628df5 1825
sPymbed 0:c4152c628df5 1826 /* Languages - Client to Server, skip */
sPymbed 0:c4152c628df5 1827 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1828 WLOG(WS_LOG_DEBUG, "DKI: Languages - Client to Server");
sPymbed 0:c4152c628df5 1829 ret = GetUint32(&skipSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1830 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1831 begin += skipSz;
sPymbed 0:c4152c628df5 1832 }
sPymbed 0:c4152c628df5 1833
sPymbed 0:c4152c628df5 1834 /* Languages - Server to Client, skip */
sPymbed 0:c4152c628df5 1835 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1836 WLOG(WS_LOG_DEBUG, "DKI: Languages - Server to Client");
sPymbed 0:c4152c628df5 1837 ret = GetUint32(&skipSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1838 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1839 begin += skipSz;
sPymbed 0:c4152c628df5 1840 }
sPymbed 0:c4152c628df5 1841
sPymbed 0:c4152c628df5 1842 /* First KEX Packet Follows */
sPymbed 0:c4152c628df5 1843 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1844 WLOG(WS_LOG_DEBUG, "DKI: KEX Packet Follows");
sPymbed 0:c4152c628df5 1845 ret = GetBoolean(&ssh->handshake->kexPacketFollows, buf, len, &begin);
sPymbed 0:c4152c628df5 1846 }
sPymbed 0:c4152c628df5 1847
sPymbed 0:c4152c628df5 1848 /* Skip the "for future use" length. */
sPymbed 0:c4152c628df5 1849 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1850 WLOG(WS_LOG_DEBUG, "DKI: For Future Use");
sPymbed 0:c4152c628df5 1851 ret = GetUint32(&skipSz, buf, len, &begin);
sPymbed 0:c4152c628df5 1852 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1853 begin += skipSz;
sPymbed 0:c4152c628df5 1854 }
sPymbed 0:c4152c628df5 1855
sPymbed 0:c4152c628df5 1856 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1857 byte scratchLen[LENGTH_SZ];
sPymbed 0:c4152c628df5 1858 word32 strSz;
sPymbed 0:c4152c628df5 1859
sPymbed 0:c4152c628df5 1860 if (!ssh->isKeying) {
sPymbed 0:c4152c628df5 1861 WLOG(WS_LOG_DEBUG, "Keying initiated");
sPymbed 0:c4152c628df5 1862 ret = SendKexInit(ssh);
sPymbed 0:c4152c628df5 1863 }
sPymbed 0:c4152c628df5 1864
sPymbed 0:c4152c628df5 1865 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1866 ret = wc_HashInit(&ssh->handshake->hash, ssh->handshake->hashId);
sPymbed 0:c4152c628df5 1867
sPymbed 0:c4152c628df5 1868 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1869 if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)
sPymbed 0:c4152c628df5 1870 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 1871 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1872 ssh->peerProtoId, ssh->peerProtoIdSz);
sPymbed 0:c4152c628df5 1873 }
sPymbed 0:c4152c628df5 1874
sPymbed 0:c4152c628df5 1875 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1876 strSz = (word32)WSTRLEN(sshProtoIdStr) - SSH_PROTO_EOL_SZ;
sPymbed 0:c4152c628df5 1877 c32toa(strSz, scratchLen);
sPymbed 0:c4152c628df5 1878 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1879 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 1880 }
sPymbed 0:c4152c628df5 1881
sPymbed 0:c4152c628df5 1882 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1883 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1884 (const byte*)sshProtoIdStr, strSz);
sPymbed 0:c4152c628df5 1885
sPymbed 0:c4152c628df5 1886 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1887 if (ssh->ctx->side == WOLFSSH_ENDPOINT_CLIENT) {
sPymbed 0:c4152c628df5 1888 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 1889 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1890 ssh->peerProtoId, ssh->peerProtoIdSz);
sPymbed 0:c4152c628df5 1891 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1892 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 1893 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1894 ssh->handshake->kexInit,
sPymbed 0:c4152c628df5 1895 ssh->handshake->kexInitSz);
sPymbed 0:c4152c628df5 1896 }
sPymbed 0:c4152c628df5 1897 }
sPymbed 0:c4152c628df5 1898
sPymbed 0:c4152c628df5 1899 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1900 c32toa(len + 1, scratchLen);
sPymbed 0:c4152c628df5 1901 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1902 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 1903 }
sPymbed 0:c4152c628df5 1904
sPymbed 0:c4152c628df5 1905 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1906 scratchLen[0] = MSGID_KEXINIT;
sPymbed 0:c4152c628df5 1907 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1908 scratchLen, MSG_ID_SZ);
sPymbed 0:c4152c628df5 1909 }
sPymbed 0:c4152c628df5 1910
sPymbed 0:c4152c628df5 1911 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 1912 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1913 buf, len);
sPymbed 0:c4152c628df5 1914
sPymbed 0:c4152c628df5 1915 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1916 if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)
sPymbed 0:c4152c628df5 1917 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 1918 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 1919 ssh->handshake->kexInit,
sPymbed 0:c4152c628df5 1920 ssh->handshake->kexInitSz);
sPymbed 0:c4152c628df5 1921 }
sPymbed 0:c4152c628df5 1922
sPymbed 0:c4152c628df5 1923 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 1924 *idx = begin;
sPymbed 0:c4152c628df5 1925 if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)
sPymbed 0:c4152c628df5 1926 ssh->clientState = CLIENT_KEXINIT_DONE;
sPymbed 0:c4152c628df5 1927 else
sPymbed 0:c4152c628df5 1928 ssh->serverState = SERVER_KEXINIT_DONE;
sPymbed 0:c4152c628df5 1929 }
sPymbed 0:c4152c628df5 1930 }
sPymbed 0:c4152c628df5 1931
sPymbed 0:c4152c628df5 1932 WLOG(WS_LOG_DEBUG, "Leaving DoKexInit(), ret = %d", ret);
sPymbed 0:c4152c628df5 1933 return ret;
sPymbed 0:c4152c628df5 1934 }
sPymbed 0:c4152c628df5 1935
sPymbed 0:c4152c628df5 1936
sPymbed 0:c4152c628df5 1937 static const byte dhGenerator[] = { 2 };
sPymbed 0:c4152c628df5 1938 static const byte dhPrimeGroup1[] = {
sPymbed 0:c4152c628df5 1939 /* SSH DH Group 1 (Oakley Group 2, 1024-bit MODP Group, RFC 2409) */
sPymbed 0:c4152c628df5 1940 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
sPymbed 0:c4152c628df5 1941 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
sPymbed 0:c4152c628df5 1942 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
sPymbed 0:c4152c628df5 1943 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
sPymbed 0:c4152c628df5 1944 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
sPymbed 0:c4152c628df5 1945 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
sPymbed 0:c4152c628df5 1946 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
sPymbed 0:c4152c628df5 1947 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
sPymbed 0:c4152c628df5 1948 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
sPymbed 0:c4152c628df5 1949 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
sPymbed 0:c4152c628df5 1950 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
sPymbed 0:c4152c628df5 1951 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
sPymbed 0:c4152c628df5 1952 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
sPymbed 0:c4152c628df5 1953 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
sPymbed 0:c4152c628df5 1954 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
sPymbed 0:c4152c628df5 1955 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
sPymbed 0:c4152c628df5 1956 };
sPymbed 0:c4152c628df5 1957 static const byte dhPrimeGroup14[] = {
sPymbed 0:c4152c628df5 1958 /* SSH DH Group 14 (Oakley Group 14, 2048-bit MODP Group, RFC 3526) */
sPymbed 0:c4152c628df5 1959 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
sPymbed 0:c4152c628df5 1960 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
sPymbed 0:c4152c628df5 1961 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
sPymbed 0:c4152c628df5 1962 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
sPymbed 0:c4152c628df5 1963 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
sPymbed 0:c4152c628df5 1964 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
sPymbed 0:c4152c628df5 1965 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
sPymbed 0:c4152c628df5 1966 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
sPymbed 0:c4152c628df5 1967 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
sPymbed 0:c4152c628df5 1968 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
sPymbed 0:c4152c628df5 1969 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
sPymbed 0:c4152c628df5 1970 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
sPymbed 0:c4152c628df5 1971 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
sPymbed 0:c4152c628df5 1972 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
sPymbed 0:c4152c628df5 1973 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
sPymbed 0:c4152c628df5 1974 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
sPymbed 0:c4152c628df5 1975 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
sPymbed 0:c4152c628df5 1976 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
sPymbed 0:c4152c628df5 1977 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
sPymbed 0:c4152c628df5 1978 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
sPymbed 0:c4152c628df5 1979 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
sPymbed 0:c4152c628df5 1980 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
sPymbed 0:c4152c628df5 1981 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
sPymbed 0:c4152c628df5 1982 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
sPymbed 0:c4152c628df5 1983 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
sPymbed 0:c4152c628df5 1984 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
sPymbed 0:c4152c628df5 1985 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
sPymbed 0:c4152c628df5 1986 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
sPymbed 0:c4152c628df5 1987 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
sPymbed 0:c4152c628df5 1988 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
sPymbed 0:c4152c628df5 1989 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
sPymbed 0:c4152c628df5 1990 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
sPymbed 0:c4152c628df5 1991 };
sPymbed 0:c4152c628df5 1992
sPymbed 0:c4152c628df5 1993 static const word32 dhGeneratorSz = sizeof(dhGenerator);
sPymbed 0:c4152c628df5 1994 static const word32 dhPrimeGroup1Sz = sizeof(dhPrimeGroup1);
sPymbed 0:c4152c628df5 1995 static const word32 dhPrimeGroup14Sz = sizeof(dhPrimeGroup14);
sPymbed 0:c4152c628df5 1996
sPymbed 0:c4152c628df5 1997
sPymbed 0:c4152c628df5 1998 static int DoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 1999 {
sPymbed 0:c4152c628df5 2000 /* First get the length of the MP_INT, and then add in the hash of the
sPymbed 0:c4152c628df5 2001 * mp_int value of e as it appears in the packet. After that, decode e
sPymbed 0:c4152c628df5 2002 * into an mp_int struct for the DH calculation by wolfCrypt.
sPymbed 0:c4152c628df5 2003 *
sPymbed 0:c4152c628df5 2004 * This function also works as MSGID_KEXECDH_INIT (30). That message
sPymbed 0:c4152c628df5 2005 * has the same format as MSGID_KEXDH_INIT, except it is the ECDH Q value
sPymbed 0:c4152c628df5 2006 * in the message isn't of the DH e value. Treat the Q as e. */
sPymbed 0:c4152c628df5 2007 /* DYNTYPE_DH */
sPymbed 0:c4152c628df5 2008
sPymbed 0:c4152c628df5 2009 byte* e;
sPymbed 0:c4152c628df5 2010 word32 eSz;
sPymbed 0:c4152c628df5 2011 word32 begin;
sPymbed 0:c4152c628df5 2012 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2013
sPymbed 0:c4152c628df5 2014 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 2015 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2016
sPymbed 0:c4152c628df5 2017 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2018 begin = *idx;
sPymbed 0:c4152c628df5 2019 ret = GetUint32(&eSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2020 }
sPymbed 0:c4152c628df5 2021
sPymbed 0:c4152c628df5 2022 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2023 e = buf + begin;
sPymbed 0:c4152c628df5 2024 begin += eSz;
sPymbed 0:c4152c628df5 2025
sPymbed 0:c4152c628df5 2026 if (eSz <= sizeof(ssh->handshake->e)) {
sPymbed 0:c4152c628df5 2027 WMEMCPY(ssh->handshake->e, e, eSz);
sPymbed 0:c4152c628df5 2028 ssh->handshake->eSz = eSz;
sPymbed 0:c4152c628df5 2029 }
sPymbed 0:c4152c628df5 2030
sPymbed 0:c4152c628df5 2031 ssh->clientState = CLIENT_KEXDH_INIT_DONE;
sPymbed 0:c4152c628df5 2032 *idx = begin;
sPymbed 0:c4152c628df5 2033
sPymbed 0:c4152c628df5 2034 //ESP_LOGI("WOLFSSH", "Sending KexDH Reply to client");
sPymbed 0:c4152c628df5 2035 ret = SendKexDhReply(ssh);
sPymbed 0:c4152c628df5 2036 }
sPymbed 0:c4152c628df5 2037
sPymbed 0:c4152c628df5 2038 return ret;
sPymbed 0:c4152c628df5 2039 }
sPymbed 0:c4152c628df5 2040
sPymbed 0:c4152c628df5 2041
sPymbed 0:c4152c628df5 2042 static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2043 {
sPymbed 0:c4152c628df5 2044 byte* pubKey;
sPymbed 0:c4152c628df5 2045 word32 pubKeySz;
sPymbed 0:c4152c628df5 2046 byte* f;
sPymbed 0:c4152c628df5 2047 word32 fSz;
sPymbed 0:c4152c628df5 2048 byte* sig;
sPymbed 0:c4152c628df5 2049 word32 sigSz;
sPymbed 0:c4152c628df5 2050 word32 scratch;
sPymbed 0:c4152c628df5 2051 byte scratchLen[LENGTH_SZ];
sPymbed 0:c4152c628df5 2052 word32 kPad = 0;
sPymbed 0:c4152c628df5 2053 struct {
sPymbed 0:c4152c628df5 2054 byte useRsa;
sPymbed 0:c4152c628df5 2055 word32 keySz;
sPymbed 0:c4152c628df5 2056 union {
sPymbed 0:c4152c628df5 2057 struct {
sPymbed 0:c4152c628df5 2058 RsaKey key;
sPymbed 0:c4152c628df5 2059 } rsa;
sPymbed 0:c4152c628df5 2060 struct {
sPymbed 0:c4152c628df5 2061 ecc_key key;
sPymbed 0:c4152c628df5 2062 } ecc;
sPymbed 0:c4152c628df5 2063 } sk;
sPymbed 0:c4152c628df5 2064 } sigKeyBlock;
sPymbed 0:c4152c628df5 2065 word32 begin;
sPymbed 0:c4152c628df5 2066 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2067
sPymbed 0:c4152c628df5 2068 WLOG(WS_LOG_DEBUG, "Entering DoKexDhReply()");
sPymbed 0:c4152c628df5 2069
sPymbed 0:c4152c628df5 2070 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 2071 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2072
sPymbed 0:c4152c628df5 2073 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2074 begin = *idx;
sPymbed 0:c4152c628df5 2075 pubKey = buf + begin;
sPymbed 0:c4152c628df5 2076 ret = GetUint32(&pubKeySz, buf, len, &begin);
sPymbed 0:c4152c628df5 2077 }
sPymbed 0:c4152c628df5 2078
sPymbed 0:c4152c628df5 2079 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2080 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2081 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2082 pubKey, pubKeySz + LENGTH_SZ);
sPymbed 0:c4152c628df5 2083
sPymbed 0:c4152c628df5 2084 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2085 pubKey = buf + begin;
sPymbed 0:c4152c628df5 2086 begin += pubKeySz;
sPymbed 0:c4152c628df5 2087 }
sPymbed 0:c4152c628df5 2088
sPymbed 0:c4152c628df5 2089 /* If using DH-GEX include the GEX specific values. */
sPymbed 0:c4152c628df5 2090 if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {
sPymbed 0:c4152c628df5 2091 byte primeGroupPad = 0, generatorPad = 0;
sPymbed 0:c4152c628df5 2092
sPymbed 0:c4152c628df5 2093 /* Hash in the client's requested minimum key size. */
sPymbed 0:c4152c628df5 2094 if (ret == 0) {
sPymbed 0:c4152c628df5 2095 c32toa(ssh->handshake->dhGexMinSz, scratchLen);
sPymbed 0:c4152c628df5 2096 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2097 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2098 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2099 }
sPymbed 0:c4152c628df5 2100 /* Hash in the client's requested preferred key size. */
sPymbed 0:c4152c628df5 2101 if (ret == 0) {
sPymbed 0:c4152c628df5 2102 c32toa(ssh->handshake->dhGexPreferredSz, scratchLen);
sPymbed 0:c4152c628df5 2103 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2104 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2105 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2106 }
sPymbed 0:c4152c628df5 2107 /* Hash in the client's requested maximum key size. */
sPymbed 0:c4152c628df5 2108 if (ret == 0) {
sPymbed 0:c4152c628df5 2109 c32toa(ssh->handshake->dhGexMaxSz, scratchLen);
sPymbed 0:c4152c628df5 2110 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2111 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2112 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2113 }
sPymbed 0:c4152c628df5 2114 /* Add a pad byte if the mpint has the MSB set. */
sPymbed 0:c4152c628df5 2115 if (ret == 0) {
sPymbed 0:c4152c628df5 2116 if (ssh->handshake->primeGroup[0] & 0x80)
sPymbed 0:c4152c628df5 2117 primeGroupPad = 1;
sPymbed 0:c4152c628df5 2118
sPymbed 0:c4152c628df5 2119 /* Hash in the length of the GEX prime group. */
sPymbed 0:c4152c628df5 2120 c32toa(ssh->handshake->primeGroupSz + primeGroupPad,
sPymbed 0:c4152c628df5 2121 scratchLen);
sPymbed 0:c4152c628df5 2122 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2123 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2124 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2125 }
sPymbed 0:c4152c628df5 2126 /* Hash in the pad byte for the GEX prime group. */
sPymbed 0:c4152c628df5 2127 if (ret == 0) {
sPymbed 0:c4152c628df5 2128 if (primeGroupPad) {
sPymbed 0:c4152c628df5 2129 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 2130 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2131 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2132 scratchLen, 1);
sPymbed 0:c4152c628df5 2133 }
sPymbed 0:c4152c628df5 2134 }
sPymbed 0:c4152c628df5 2135 /* Hash in the GEX prime group. */
sPymbed 0:c4152c628df5 2136 if (ret == 0)
sPymbed 0:c4152c628df5 2137 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2138 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2139 ssh->handshake->primeGroup,
sPymbed 0:c4152c628df5 2140 ssh->handshake->primeGroupSz);
sPymbed 0:c4152c628df5 2141 /* Add a pad byte if the mpint has the MSB set. */
sPymbed 0:c4152c628df5 2142 if (ret == 0) {
sPymbed 0:c4152c628df5 2143 if (ssh->handshake->generator[0] & 0x80)
sPymbed 0:c4152c628df5 2144 generatorPad = 1;
sPymbed 0:c4152c628df5 2145
sPymbed 0:c4152c628df5 2146 /* Hash in the length of the GEX generator. */
sPymbed 0:c4152c628df5 2147 c32toa(ssh->handshake->generatorSz + generatorPad, scratchLen);
sPymbed 0:c4152c628df5 2148 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2149 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2150 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2151 }
sPymbed 0:c4152c628df5 2152 /* Hash in the pad byte for the GEX generator. */
sPymbed 0:c4152c628df5 2153 if (ret == 0) {
sPymbed 0:c4152c628df5 2154 if (generatorPad) {
sPymbed 0:c4152c628df5 2155 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 2156 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2157 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2158 scratchLen, 1);
sPymbed 0:c4152c628df5 2159 }
sPymbed 0:c4152c628df5 2160 }
sPymbed 0:c4152c628df5 2161 /* Hash in the GEX generator. */
sPymbed 0:c4152c628df5 2162 if (ret == 0)
sPymbed 0:c4152c628df5 2163 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2164 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2165 ssh->handshake->generator,
sPymbed 0:c4152c628df5 2166 ssh->handshake->generatorSz);
sPymbed 0:c4152c628df5 2167 }
sPymbed 0:c4152c628df5 2168
sPymbed 0:c4152c628df5 2169 /* Hash in the size of the client's DH e-value (ECDH Q-value). */
sPymbed 0:c4152c628df5 2170 if (ret == 0) {
sPymbed 0:c4152c628df5 2171 c32toa(ssh->handshake->eSz, scratchLen);
sPymbed 0:c4152c628df5 2172 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2173 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2174 }
sPymbed 0:c4152c628df5 2175 /* Hash in the client's DH e-value (ECDH Q-value). */
sPymbed 0:c4152c628df5 2176 if (ret == 0)
sPymbed 0:c4152c628df5 2177 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2178 ssh->handshake->e, ssh->handshake->eSz);
sPymbed 0:c4152c628df5 2179
sPymbed 0:c4152c628df5 2180 /* Get and hash in the server's DH f-value (ECDH Q-value) */
sPymbed 0:c4152c628df5 2181 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2182 f = buf + begin;
sPymbed 0:c4152c628df5 2183 ret = GetUint32(&fSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2184 }
sPymbed 0:c4152c628df5 2185
sPymbed 0:c4152c628df5 2186 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2187 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2188 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2189 f, fSz + LENGTH_SZ);
sPymbed 0:c4152c628df5 2190
sPymbed 0:c4152c628df5 2191 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2192 f = buf + begin;
sPymbed 0:c4152c628df5 2193 begin += fSz;
sPymbed 0:c4152c628df5 2194 ret = GetUint32(&sigSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2195 }
sPymbed 0:c4152c628df5 2196
sPymbed 0:c4152c628df5 2197 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2198 sig = buf + begin;
sPymbed 0:c4152c628df5 2199 begin += sigSz;
sPymbed 0:c4152c628df5 2200 *idx = begin;
sPymbed 0:c4152c628df5 2201
sPymbed 0:c4152c628df5 2202 /* Load in the server's public signing key */
sPymbed 0:c4152c628df5 2203 sigKeyBlock.useRsa = ssh->handshake->pubKeyId == ID_SSH_RSA;
sPymbed 0:c4152c628df5 2204
sPymbed 0:c4152c628df5 2205 if (sigKeyBlock.useRsa) {
sPymbed 0:c4152c628df5 2206 byte* e;
sPymbed 0:c4152c628df5 2207 word32 eSz;
sPymbed 0:c4152c628df5 2208 byte* n;
sPymbed 0:c4152c628df5 2209 word32 nSz;
sPymbed 0:c4152c628df5 2210 word32 pubKeyIdx = 0;
sPymbed 0:c4152c628df5 2211
sPymbed 0:c4152c628df5 2212 ret = wc_InitRsaKey(&sigKeyBlock.sk.rsa.key, ssh->ctx->heap);
sPymbed 0:c4152c628df5 2213 if (ret != 0)
sPymbed 0:c4152c628df5 2214 ret = WS_RSA_E;
sPymbed 0:c4152c628df5 2215 if (ret == 0)
sPymbed 0:c4152c628df5 2216 ret = GetUint32(&scratch, pubKey, pubKeySz, &pubKeyIdx);
sPymbed 0:c4152c628df5 2217 /* This is the algo name. */
sPymbed 0:c4152c628df5 2218 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2219 pubKeyIdx += scratch;
sPymbed 0:c4152c628df5 2220 ret = GetUint32(&eSz, pubKey, pubKeySz, &pubKeyIdx);
sPymbed 0:c4152c628df5 2221 }
sPymbed 0:c4152c628df5 2222 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2223 e = pubKey + pubKeyIdx;
sPymbed 0:c4152c628df5 2224 pubKeyIdx += eSz;
sPymbed 0:c4152c628df5 2225 ret = GetUint32(&nSz, pubKey, pubKeySz, &pubKeyIdx);
sPymbed 0:c4152c628df5 2226 }
sPymbed 0:c4152c628df5 2227 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2228 n = pubKey + pubKeyIdx;
sPymbed 0:c4152c628df5 2229 ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz,
sPymbed 0:c4152c628df5 2230 &sigKeyBlock.sk.rsa.key);
sPymbed 0:c4152c628df5 2231 }
sPymbed 0:c4152c628df5 2232
sPymbed 0:c4152c628df5 2233 if (ret == 0)
sPymbed 0:c4152c628df5 2234 sigKeyBlock.keySz = sizeof(sigKeyBlock.sk.rsa.key);
sPymbed 0:c4152c628df5 2235 else
sPymbed 0:c4152c628df5 2236 ret = WS_RSA_E;
sPymbed 0:c4152c628df5 2237 }
sPymbed 0:c4152c628df5 2238 else {
sPymbed 0:c4152c628df5 2239 ret = wc_ecc_init_ex(&sigKeyBlock.sk.ecc.key, ssh->ctx->heap,
sPymbed 0:c4152c628df5 2240 INVALID_DEVID);
sPymbed 0:c4152c628df5 2241 if (ret == 0)
sPymbed 0:c4152c628df5 2242 ret = wc_ecc_import_x963(pubKey, pubKeySz,
sPymbed 0:c4152c628df5 2243 &sigKeyBlock.sk.ecc.key);
sPymbed 0:c4152c628df5 2244 if (ret == 0)
sPymbed 0:c4152c628df5 2245 sigKeyBlock.keySz = sizeof(sigKeyBlock.sk.ecc.key);
sPymbed 0:c4152c628df5 2246 else
sPymbed 0:c4152c628df5 2247 ret = WS_ECC_E;
sPymbed 0:c4152c628df5 2248 }
sPymbed 0:c4152c628df5 2249
sPymbed 0:c4152c628df5 2250 /* Generate and hash in the shared secret */
sPymbed 0:c4152c628df5 2251 if (ret == 0) {
sPymbed 0:c4152c628df5 2252 if (!ssh->handshake->useEcc) {
sPymbed 0:c4152c628df5 2253 ret = wc_DhAgree(&ssh->handshake->privKey.dh,
sPymbed 0:c4152c628df5 2254 ssh->k, &ssh->kSz,
sPymbed 0:c4152c628df5 2255 ssh->handshake->x, ssh->handshake->xSz,
sPymbed 0:c4152c628df5 2256 f, fSz);
sPymbed 0:c4152c628df5 2257 ForceZero(ssh->handshake->x, ssh->handshake->xSz);
sPymbed 0:c4152c628df5 2258 wc_FreeDhKey(&ssh->handshake->privKey.dh);
sPymbed 0:c4152c628df5 2259 }
sPymbed 0:c4152c628df5 2260 else {
sPymbed 0:c4152c628df5 2261 ecc_key key;
sPymbed 0:c4152c628df5 2262 ret = wc_ecc_init(&key);
sPymbed 0:c4152c628df5 2263 if (ret == 0)
sPymbed 0:c4152c628df5 2264 ret = wc_ecc_import_x963(f, fSz, &key);
sPymbed 0:c4152c628df5 2265 if (ret == 0)
sPymbed 0:c4152c628df5 2266 ret = wc_ecc_shared_secret(&ssh->handshake->privKey.ecc,
sPymbed 0:c4152c628df5 2267 &key, ssh->k, &ssh->kSz);
sPymbed 0:c4152c628df5 2268 wc_ecc_free(&key);
sPymbed 0:c4152c628df5 2269 wc_ecc_free(&ssh->handshake->privKey.ecc);
sPymbed 0:c4152c628df5 2270 }
sPymbed 0:c4152c628df5 2271 }
sPymbed 0:c4152c628df5 2272
sPymbed 0:c4152c628df5 2273 /* Hash in the shared secret K. */
sPymbed 0:c4152c628df5 2274 if (ret == 0) {
sPymbed 0:c4152c628df5 2275 kPad = (ssh->k[0] & 0x80) ? 1 : 0;
sPymbed 0:c4152c628df5 2276 c32toa(ssh->kSz + kPad, scratchLen);
sPymbed 0:c4152c628df5 2277 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2278 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 2279 }
sPymbed 0:c4152c628df5 2280 if (ret == 0) {
sPymbed 0:c4152c628df5 2281 if (kPad) {
sPymbed 0:c4152c628df5 2282 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 2283 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2284 ssh->handshake->hashId, scratchLen, 1);
sPymbed 0:c4152c628df5 2285 }
sPymbed 0:c4152c628df5 2286 }
sPymbed 0:c4152c628df5 2287 if (ret == 0)
sPymbed 0:c4152c628df5 2288 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 2289 ssh->k, ssh->kSz);
sPymbed 0:c4152c628df5 2290
sPymbed 0:c4152c628df5 2291 /* Save the exchange hash value H, and session ID. */
sPymbed 0:c4152c628df5 2292 if (ret == 0)
sPymbed 0:c4152c628df5 2293 ret = wc_HashFinal(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 2294 ssh->handshake->hashId, ssh->h);
sPymbed 0:c4152c628df5 2295 if (ret == 0) {
sPymbed 0:c4152c628df5 2296 ssh->hSz = wc_HashGetDigestSize(ssh->handshake->hashId);
sPymbed 0:c4152c628df5 2297 if (ssh->sessionIdSz == 0) {
sPymbed 0:c4152c628df5 2298 WMEMCPY(ssh->sessionId, ssh->h, ssh->hSz);
sPymbed 0:c4152c628df5 2299 ssh->sessionIdSz = ssh->hSz;
sPymbed 0:c4152c628df5 2300 }
sPymbed 0:c4152c628df5 2301 }
sPymbed 0:c4152c628df5 2302
sPymbed 0:c4152c628df5 2303 if (ret != WS_SUCCESS)
sPymbed 0:c4152c628df5 2304 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 2305 }
sPymbed 0:c4152c628df5 2306
sPymbed 0:c4152c628df5 2307 /* Verify h with the server's public key. */
sPymbed 0:c4152c628df5 2308 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2309 /* Skip past the sig name. Check it, though. Other SSH implementations
sPymbed 0:c4152c628df5 2310 * do the verify based on the name, despite what was agreed upon. XXX*/
sPymbed 0:c4152c628df5 2311 begin = 0;
sPymbed 0:c4152c628df5 2312 ret = GetUint32(&scratch, sig, sigSz, &begin);
sPymbed 0:c4152c628df5 2313 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2314 begin += scratch;
sPymbed 0:c4152c628df5 2315 ret = GetUint32(&scratch, sig, sigSz, &begin);
sPymbed 0:c4152c628df5 2316 }
sPymbed 0:c4152c628df5 2317 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2318 sig = sig + begin;
sPymbed 0:c4152c628df5 2319 sigSz = scratch;
sPymbed 0:c4152c628df5 2320
sPymbed 0:c4152c628df5 2321 ret = wc_SignatureVerify(HashForId(ssh->handshake->pubKeyId),
sPymbed 0:c4152c628df5 2322 sigKeyBlock.useRsa ?
sPymbed 0:c4152c628df5 2323 WC_SIGNATURE_TYPE_RSA_W_ENC :
sPymbed 0:c4152c628df5 2324 WC_SIGNATURE_TYPE_ECC,
sPymbed 0:c4152c628df5 2325 ssh->h, ssh->hSz, sig, sigSz,
sPymbed 0:c4152c628df5 2326 &sigKeyBlock.sk, sigKeyBlock.keySz);
sPymbed 0:c4152c628df5 2327 if (ret != 0) {
sPymbed 0:c4152c628df5 2328 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 2329 "DoKexDhReply: Signature Verify fail (%d)", ret);
sPymbed 0:c4152c628df5 2330 ret = sigKeyBlock.useRsa ? WS_RSA_E : WS_ECC_E;
sPymbed 0:c4152c628df5 2331 }
sPymbed 0:c4152c628df5 2332 }
sPymbed 0:c4152c628df5 2333 }
sPymbed 0:c4152c628df5 2334
sPymbed 0:c4152c628df5 2335 if (sigKeyBlock.useRsa)
sPymbed 0:c4152c628df5 2336 wc_FreeRsaKey(&sigKeyBlock.sk.rsa.key);
sPymbed 0:c4152c628df5 2337 else
sPymbed 0:c4152c628df5 2338 wc_ecc_free(&sigKeyBlock.sk.ecc.key);
sPymbed 0:c4152c628df5 2339
sPymbed 0:c4152c628df5 2340 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2341 ret = GenerateKeys(ssh);
sPymbed 0:c4152c628df5 2342
sPymbed 0:c4152c628df5 2343 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2344 ret = SendNewKeys(ssh);
sPymbed 0:c4152c628df5 2345
sPymbed 0:c4152c628df5 2346 WLOG(WS_LOG_DEBUG, "Leaving DoKexDhReply(), ret = %d", ret);
sPymbed 0:c4152c628df5 2347 return ret;
sPymbed 0:c4152c628df5 2348 }
sPymbed 0:c4152c628df5 2349
sPymbed 0:c4152c628df5 2350
sPymbed 0:c4152c628df5 2351 static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2352 {
sPymbed 0:c4152c628df5 2353 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2354
sPymbed 0:c4152c628df5 2355 (void)buf;
sPymbed 0:c4152c628df5 2356 (void)len;
sPymbed 0:c4152c628df5 2357 (void)idx;
sPymbed 0:c4152c628df5 2358
sPymbed 0:c4152c628df5 2359 if (ssh == NULL)
sPymbed 0:c4152c628df5 2360 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2361
sPymbed 0:c4152c628df5 2362 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2363 ssh->peerEncryptId = ssh->handshake->encryptId;
sPymbed 0:c4152c628df5 2364 ssh->peerMacId = ssh->handshake->macId;
sPymbed 0:c4152c628df5 2365 ssh->peerBlockSz = ssh->handshake->blockSz;
sPymbed 0:c4152c628df5 2366 ssh->peerMacSz = ssh->handshake->macSz;
sPymbed 0:c4152c628df5 2367 ssh->peerAeadMode = ssh->handshake->aeadMode;
sPymbed 0:c4152c628df5 2368 WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));
sPymbed 0:c4152c628df5 2369
sPymbed 0:c4152c628df5 2370 switch (ssh->peerEncryptId) {
sPymbed 0:c4152c628df5 2371 case ID_NONE:
sPymbed 0:c4152c628df5 2372 WLOG(WS_LOG_DEBUG, "DNK: peer using cipher none");
sPymbed 0:c4152c628df5 2373 //ESP_LOGI("WOLFSSH", "DNK: peer using cipher none");
sPymbed 0:c4152c628df5 2374 break;
sPymbed 0:c4152c628df5 2375
sPymbed 0:c4152c628df5 2376 case ID_AES128_CBC:
sPymbed 0:c4152c628df5 2377 WLOG(WS_LOG_DEBUG, "DNK: peer using cipher aes128-cbc");
sPymbed 0:c4152c628df5 2378 ret = wc_AesSetKey(&ssh->decryptCipher.aes,
sPymbed 0:c4152c628df5 2379 ssh->peerKeys.encKey, ssh->peerKeys.encKeySz,
sPymbed 0:c4152c628df5 2380 ssh->peerKeys.iv, AES_DECRYPTION);
sPymbed 0:c4152c628df5 2381 //ESP_LOGI("WOLFSSH", "DNK: peer using cipher aes128-cbc");
sPymbed 0:c4152c628df5 2382 break;
sPymbed 0:c4152c628df5 2383
sPymbed 0:c4152c628df5 2384 case ID_AES128_GCM:
sPymbed 0:c4152c628df5 2385 WLOG(WS_LOG_DEBUG, "DNK: peer using cipher aes128-gcm");
sPymbed 0:c4152c628df5 2386 ret = wc_AesGcmSetKey(&ssh->decryptCipher.aes,
sPymbed 0:c4152c628df5 2387 ssh->peerKeys.encKey,
sPymbed 0:c4152c628df5 2388 ssh->peerKeys.encKeySz);
sPymbed 0:c4152c628df5 2389 //ESP_LOGI("WOLFSSH", "DNK: peer using cipher aes128-gcm");
sPymbed 0:c4152c628df5 2390 break;
sPymbed 0:c4152c628df5 2391
sPymbed 0:c4152c628df5 2392 default:
sPymbed 0:c4152c628df5 2393 WLOG(WS_LOG_DEBUG, "DNK: peer using cipher invalid");
sPymbed 0:c4152c628df5 2394 //ESP_LOGI("WOLFSSH", "DNK: peer using cipher invalid");
sPymbed 0:c4152c628df5 2395 break;
sPymbed 0:c4152c628df5 2396 }
sPymbed 0:c4152c628df5 2397
sPymbed 0:c4152c628df5 2398 if (ret == 0)
sPymbed 0:c4152c628df5 2399 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2400 else
sPymbed 0:c4152c628df5 2401 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 2402 }
sPymbed 0:c4152c628df5 2403
sPymbed 0:c4152c628df5 2404 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2405 ssh->rxCount = 0;
sPymbed 0:c4152c628df5 2406 ssh->highwaterFlag = 0;
sPymbed 0:c4152c628df5 2407 ssh->isKeying = 0;
sPymbed 0:c4152c628df5 2408 HandshakeInfoFree(ssh->handshake, ssh->ctx->heap);
sPymbed 0:c4152c628df5 2409 ssh->handshake = NULL;
sPymbed 0:c4152c628df5 2410 WLOG(WS_LOG_DEBUG, "Keying completed");
sPymbed 0:c4152c628df5 2411 //ESP_LOGI("WOLFSSH", "Keying completed");
sPymbed 0:c4152c628df5 2412 }
sPymbed 0:c4152c628df5 2413
sPymbed 0:c4152c628df5 2414 return ret;
sPymbed 0:c4152c628df5 2415 }
sPymbed 0:c4152c628df5 2416
sPymbed 0:c4152c628df5 2417
sPymbed 0:c4152c628df5 2418 static int DoKexDhGexRequest(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 2419 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2420 {
sPymbed 0:c4152c628df5 2421 word32 begin;
sPymbed 0:c4152c628df5 2422 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2423
sPymbed 0:c4152c628df5 2424 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 2425 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2426
sPymbed 0:c4152c628df5 2427 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2428 begin = *idx;
sPymbed 0:c4152c628df5 2429 ret = GetUint32(&ssh->handshake->dhGexMinSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2430 }
sPymbed 0:c4152c628df5 2431
sPymbed 0:c4152c628df5 2432 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2433 ret = GetUint32(&ssh->handshake->dhGexPreferredSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2434 }
sPymbed 0:c4152c628df5 2435
sPymbed 0:c4152c628df5 2436 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2437 ret = GetUint32(&ssh->handshake->dhGexMaxSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2438 }
sPymbed 0:c4152c628df5 2439
sPymbed 0:c4152c628df5 2440 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2441 WLOG(WS_LOG_INFO, " min = %u, preferred = %u, max = %u",
sPymbed 0:c4152c628df5 2442 ssh->handshake->dhGexMinSz,
sPymbed 0:c4152c628df5 2443 ssh->handshake->dhGexPreferredSz,
sPymbed 0:c4152c628df5 2444 ssh->handshake->dhGexMaxSz);
sPymbed 0:c4152c628df5 2445 *idx = begin;
sPymbed 0:c4152c628df5 2446 ret = SendKexDhGexGroup(ssh);
sPymbed 0:c4152c628df5 2447 }
sPymbed 0:c4152c628df5 2448
sPymbed 0:c4152c628df5 2449 return ret;
sPymbed 0:c4152c628df5 2450 }
sPymbed 0:c4152c628df5 2451
sPymbed 0:c4152c628df5 2452
sPymbed 0:c4152c628df5 2453 static int DoKexDhGexGroup(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 2454 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2455 {
sPymbed 0:c4152c628df5 2456 byte* primeGroup = NULL;
sPymbed 0:c4152c628df5 2457 word32 primeGroupSz;
sPymbed 0:c4152c628df5 2458 byte* generator = NULL;
sPymbed 0:c4152c628df5 2459 word32 generatorSz;
sPymbed 0:c4152c628df5 2460 word32 begin;
sPymbed 0:c4152c628df5 2461 int ret = WS_UNIMPLEMENTED_E;
sPymbed 0:c4152c628df5 2462
sPymbed 0:c4152c628df5 2463 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 2464 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2465
sPymbed 0:c4152c628df5 2466 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2467 begin = *idx;
sPymbed 0:c4152c628df5 2468 ret = GetMpint(&primeGroupSz, &primeGroup, buf, len, &begin);
sPymbed 0:c4152c628df5 2469 }
sPymbed 0:c4152c628df5 2470
sPymbed 0:c4152c628df5 2471 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2472 ret = GetMpint(&generatorSz, &generator, buf, len, &begin);
sPymbed 0:c4152c628df5 2473
sPymbed 0:c4152c628df5 2474 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2475 ssh->handshake->primeGroup =
sPymbed 0:c4152c628df5 2476 (byte*)WMALLOC(primeGroupSz + UINT32_SZ,
sPymbed 0:c4152c628df5 2477 ssh->ctx->heap, DYNTYPE_MPINT);
sPymbed 0:c4152c628df5 2478 if (ssh->handshake->primeGroup == NULL)
sPymbed 0:c4152c628df5 2479 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 2480 }
sPymbed 0:c4152c628df5 2481
sPymbed 0:c4152c628df5 2482 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2483 ssh->handshake->generator =
sPymbed 0:c4152c628df5 2484 (byte*)WMALLOC(generatorSz + UINT32_SZ,
sPymbed 0:c4152c628df5 2485 ssh->ctx->heap, DYNTYPE_MPINT);
sPymbed 0:c4152c628df5 2486 if (ssh->handshake->generator == NULL) {
sPymbed 0:c4152c628df5 2487 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 2488 WFREE(ssh->handshake->primeGroup, ssh->ctx->heap, DYNTYPE_MPINT);
sPymbed 0:c4152c628df5 2489 ssh->handshake->primeGroup = NULL;
sPymbed 0:c4152c628df5 2490 }
sPymbed 0:c4152c628df5 2491 }
sPymbed 0:c4152c628df5 2492
sPymbed 0:c4152c628df5 2493 if (WS_SUCCESS) {
sPymbed 0:c4152c628df5 2494 c32toa(primeGroupSz, ssh->handshake->primeGroup);
sPymbed 0:c4152c628df5 2495 WMEMCPY(ssh->handshake->primeGroup + UINT32_SZ,
sPymbed 0:c4152c628df5 2496 primeGroup, primeGroupSz);
sPymbed 0:c4152c628df5 2497 ssh->handshake->primeGroupSz = primeGroupSz;
sPymbed 0:c4152c628df5 2498 c32toa(generatorSz, ssh->handshake->generator);
sPymbed 0:c4152c628df5 2499 WMEMCPY(ssh->handshake->generator + UINT32_SZ,
sPymbed 0:c4152c628df5 2500 generator, generatorSz);
sPymbed 0:c4152c628df5 2501 ssh->handshake->generatorSz = generatorSz;
sPymbed 0:c4152c628df5 2502
sPymbed 0:c4152c628df5 2503 *idx = begin;
sPymbed 0:c4152c628df5 2504 ret = SendKexDhInit(ssh);
sPymbed 0:c4152c628df5 2505 }
sPymbed 0:c4152c628df5 2506
sPymbed 0:c4152c628df5 2507 return ret;
sPymbed 0:c4152c628df5 2508 }
sPymbed 0:c4152c628df5 2509
sPymbed 0:c4152c628df5 2510
sPymbed 0:c4152c628df5 2511 static int DoIgnore(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2512 {
sPymbed 0:c4152c628df5 2513 word32 dataSz;
sPymbed 0:c4152c628df5 2514 word32 begin = *idx;
sPymbed 0:c4152c628df5 2515
sPymbed 0:c4152c628df5 2516 (void)ssh;
sPymbed 0:c4152c628df5 2517 (void)len;
sPymbed 0:c4152c628df5 2518
sPymbed 0:c4152c628df5 2519 ato32(buf + begin, &dataSz);
sPymbed 0:c4152c628df5 2520 begin += LENGTH_SZ + dataSz;
sPymbed 0:c4152c628df5 2521
sPymbed 0:c4152c628df5 2522 *idx = begin;
sPymbed 0:c4152c628df5 2523
sPymbed 0:c4152c628df5 2524 return WS_SUCCESS;
sPymbed 0:c4152c628df5 2525 }
sPymbed 0:c4152c628df5 2526
sPymbed 0:c4152c628df5 2527
sPymbed 0:c4152c628df5 2528 static int DoDebug(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2529 {
sPymbed 0:c4152c628df5 2530 byte alwaysDisplay;
sPymbed 0:c4152c628df5 2531 char* msg = NULL;
sPymbed 0:c4152c628df5 2532 char* lang = NULL;
sPymbed 0:c4152c628df5 2533 word32 strSz;
sPymbed 0:c4152c628df5 2534 word32 begin = *idx;
sPymbed 0:c4152c628df5 2535
sPymbed 0:c4152c628df5 2536 (void)ssh;
sPymbed 0:c4152c628df5 2537 (void)len;
sPymbed 0:c4152c628df5 2538
sPymbed 0:c4152c628df5 2539 alwaysDisplay = buf[begin++];
sPymbed 0:c4152c628df5 2540
sPymbed 0:c4152c628df5 2541 ato32(buf + begin, &strSz);
sPymbed 0:c4152c628df5 2542 begin += LENGTH_SZ;
sPymbed 0:c4152c628df5 2543 if (strSz > 0) {
sPymbed 0:c4152c628df5 2544 msg = (char*)WMALLOC(strSz + 1, ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 2545 if (msg != NULL) {
sPymbed 0:c4152c628df5 2546 WMEMCPY(msg, buf + begin, strSz);
sPymbed 0:c4152c628df5 2547 msg[strSz] = 0;
sPymbed 0:c4152c628df5 2548 }
sPymbed 0:c4152c628df5 2549 else {
sPymbed 0:c4152c628df5 2550 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 2551 }
sPymbed 0:c4152c628df5 2552 begin += strSz;
sPymbed 0:c4152c628df5 2553 }
sPymbed 0:c4152c628df5 2554
sPymbed 0:c4152c628df5 2555 ato32(buf + begin, &strSz);
sPymbed 0:c4152c628df5 2556 begin += LENGTH_SZ;
sPymbed 0:c4152c628df5 2557 if (strSz > 0) {
sPymbed 0:c4152c628df5 2558 lang = (char*)WMALLOC(strSz + 1, ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 2559 if (lang != NULL) {
sPymbed 0:c4152c628df5 2560 WMEMCPY(lang, buf + begin, strSz);
sPymbed 0:c4152c628df5 2561 lang[strSz] = 0;
sPymbed 0:c4152c628df5 2562 }
sPymbed 0:c4152c628df5 2563 else {
sPymbed 0:c4152c628df5 2564 WFREE(msg, ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 2565 return WS_MEMORY_E;
sPymbed 0:c4152c628df5 2566 }
sPymbed 0:c4152c628df5 2567 begin += strSz;
sPymbed 0:c4152c628df5 2568 }
sPymbed 0:c4152c628df5 2569
sPymbed 0:c4152c628df5 2570 if (alwaysDisplay) {
sPymbed 0:c4152c628df5 2571 WLOG(WS_LOG_DEBUG, "DEBUG MSG (%s): %s",
sPymbed 0:c4152c628df5 2572 (lang == NULL) ? "none" : lang,
sPymbed 0:c4152c628df5 2573 (msg == NULL) ? "no message" : msg);
sPymbed 0:c4152c628df5 2574 }
sPymbed 0:c4152c628df5 2575
sPymbed 0:c4152c628df5 2576 *idx = begin;
sPymbed 0:c4152c628df5 2577
sPymbed 0:c4152c628df5 2578 WFREE(msg, ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 2579 WFREE(lang, ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 2580
sPymbed 0:c4152c628df5 2581 return WS_SUCCESS;
sPymbed 0:c4152c628df5 2582 }
sPymbed 0:c4152c628df5 2583
sPymbed 0:c4152c628df5 2584
sPymbed 0:c4152c628df5 2585 static int DoUnimplemented(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 2586 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2587 {
sPymbed 0:c4152c628df5 2588 word32 seq;
sPymbed 0:c4152c628df5 2589 word32 begin = *idx;
sPymbed 0:c4152c628df5 2590
sPymbed 0:c4152c628df5 2591 (void)ssh;
sPymbed 0:c4152c628df5 2592 (void)len;
sPymbed 0:c4152c628df5 2593
sPymbed 0:c4152c628df5 2594 ato32(buf + begin, &seq);
sPymbed 0:c4152c628df5 2595 begin += UINT32_SZ;
sPymbed 0:c4152c628df5 2596
sPymbed 0:c4152c628df5 2597 WLOG(WS_LOG_DEBUG, "UNIMPLEMENTED: seq %u", seq);
sPymbed 0:c4152c628df5 2598
sPymbed 0:c4152c628df5 2599 *idx = begin;
sPymbed 0:c4152c628df5 2600
sPymbed 0:c4152c628df5 2601 return WS_SUCCESS;
sPymbed 0:c4152c628df5 2602 }
sPymbed 0:c4152c628df5 2603
sPymbed 0:c4152c628df5 2604
sPymbed 0:c4152c628df5 2605 static int DoDisconnect(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2606 {
sPymbed 0:c4152c628df5 2607 word32 reason;
sPymbed 0:c4152c628df5 2608 const char* reasonStr;
sPymbed 0:c4152c628df5 2609 word32 begin = *idx;
sPymbed 0:c4152c628df5 2610
sPymbed 0:c4152c628df5 2611 (void)ssh;
sPymbed 0:c4152c628df5 2612 (void)len;
sPymbed 0:c4152c628df5 2613 (void)reasonStr;
sPymbed 0:c4152c628df5 2614
sPymbed 0:c4152c628df5 2615 ato32(buf + begin, &reason);
sPymbed 0:c4152c628df5 2616 begin += UINT32_SZ;
sPymbed 0:c4152c628df5 2617
sPymbed 0:c4152c628df5 2618 #ifdef NO_WOLFSSH_STRINGS
sPymbed 0:c4152c628df5 2619 WLOG(WS_LOG_DEBUG, "DISCONNECT: (%u)", reason);
sPymbed 0:c4152c628df5 2620 #elif defined(DEBUG_WOLFSSH)
sPymbed 0:c4152c628df5 2621 switch (reason) {
sPymbed 0:c4152c628df5 2622 case WOLFSSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT:
sPymbed 0:c4152c628df5 2623 reasonStr = "host not allowed to connect"; break;
sPymbed 0:c4152c628df5 2624 case WOLFSSH_DISCONNECT_PROTOCOL_ERROR:
sPymbed 0:c4152c628df5 2625 reasonStr = "protocol error"; break;
sPymbed 0:c4152c628df5 2626 case WOLFSSH_DISCONNECT_KEY_EXCHANGE_FAILED:
sPymbed 0:c4152c628df5 2627 reasonStr = "key exchange failed"; break;
sPymbed 0:c4152c628df5 2628 case WOLFSSH_DISCONNECT_RESERVED:
sPymbed 0:c4152c628df5 2629 reasonStr = "reserved"; break;
sPymbed 0:c4152c628df5 2630 case WOLFSSH_DISCONNECT_MAC_ERROR:
sPymbed 0:c4152c628df5 2631 reasonStr = "mac error"; break;
sPymbed 0:c4152c628df5 2632 case WOLFSSH_DISCONNECT_COMPRESSION_ERROR:
sPymbed 0:c4152c628df5 2633 reasonStr = "compression error"; break;
sPymbed 0:c4152c628df5 2634 case WOLFSSH_DISCONNECT_SERVICE_NOT_AVAILABLE:
sPymbed 0:c4152c628df5 2635 reasonStr = "service not available"; break;
sPymbed 0:c4152c628df5 2636 case WOLFSSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED:
sPymbed 0:c4152c628df5 2637 reasonStr = "protocol version not supported"; break;
sPymbed 0:c4152c628df5 2638 case WOLFSSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE:
sPymbed 0:c4152c628df5 2639 reasonStr = "host key not verifiable"; break;
sPymbed 0:c4152c628df5 2640 case WOLFSSH_DISCONNECT_CONNECTION_LOST:
sPymbed 0:c4152c628df5 2641 reasonStr = "connection lost"; break;
sPymbed 0:c4152c628df5 2642 case WOLFSSH_DISCONNECT_BY_APPLICATION:
sPymbed 0:c4152c628df5 2643 reasonStr = "disconnect by application"; break;
sPymbed 0:c4152c628df5 2644 case WOLFSSH_DISCONNECT_TOO_MANY_CONNECTIONS:
sPymbed 0:c4152c628df5 2645 reasonStr = "too many connections"; break;
sPymbed 0:c4152c628df5 2646 case WOLFSSH_DISCONNECT_AUTH_CANCELLED_BY_USER:
sPymbed 0:c4152c628df5 2647 reasonStr = "auth cancelled by user"; break;
sPymbed 0:c4152c628df5 2648 case WOLFSSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE:
sPymbed 0:c4152c628df5 2649 reasonStr = "no more auth methods available"; break;
sPymbed 0:c4152c628df5 2650 case WOLFSSH_DISCONNECT_ILLEGAL_USER_NAME:
sPymbed 0:c4152c628df5 2651 reasonStr = "illegal user name"; break;
sPymbed 0:c4152c628df5 2652 default:
sPymbed 0:c4152c628df5 2653 reasonStr = "unknown reason";
sPymbed 0:c4152c628df5 2654 }
sPymbed 0:c4152c628df5 2655 WLOG(WS_LOG_DEBUG, "DISCONNECT: (%u) %s", reason, reasonStr);
sPymbed 0:c4152c628df5 2656 #endif
sPymbed 0:c4152c628df5 2657
sPymbed 0:c4152c628df5 2658 *idx = begin;
sPymbed 0:c4152c628df5 2659
sPymbed 0:c4152c628df5 2660 return WS_SUCCESS;
sPymbed 0:c4152c628df5 2661 }
sPymbed 0:c4152c628df5 2662
sPymbed 0:c4152c628df5 2663
sPymbed 0:c4152c628df5 2664 static int DoServiceRequest(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 2665 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2666 {
sPymbed 0:c4152c628df5 2667 word32 begin = *idx;
sPymbed 0:c4152c628df5 2668 word32 nameSz;
sPymbed 0:c4152c628df5 2669 char serviceName[32];
sPymbed 0:c4152c628df5 2670
sPymbed 0:c4152c628df5 2671 (void)len;
sPymbed 0:c4152c628df5 2672
sPymbed 0:c4152c628df5 2673 ato32(buf + begin, &nameSz);
sPymbed 0:c4152c628df5 2674 begin += LENGTH_SZ;
sPymbed 0:c4152c628df5 2675
sPymbed 0:c4152c628df5 2676 WMEMCPY(serviceName, buf + begin, nameSz);
sPymbed 0:c4152c628df5 2677 begin += nameSz;
sPymbed 0:c4152c628df5 2678 serviceName[nameSz] = 0;
sPymbed 0:c4152c628df5 2679
sPymbed 0:c4152c628df5 2680 *idx = begin;
sPymbed 0:c4152c628df5 2681
sPymbed 0:c4152c628df5 2682 WLOG(WS_LOG_DEBUG, "Requesting service: %s", serviceName);
sPymbed 0:c4152c628df5 2683 ssh->clientState = CLIENT_USERAUTH_REQUEST_DONE;
sPymbed 0:c4152c628df5 2684
sPymbed 0:c4152c628df5 2685 return WS_SUCCESS;
sPymbed 0:c4152c628df5 2686 }
sPymbed 0:c4152c628df5 2687
sPymbed 0:c4152c628df5 2688
sPymbed 0:c4152c628df5 2689 static int DoServiceAccept(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 2690 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2691 {
sPymbed 0:c4152c628df5 2692 word32 begin = *idx;
sPymbed 0:c4152c628df5 2693 word32 nameSz;
sPymbed 0:c4152c628df5 2694 char serviceName[32];
sPymbed 0:c4152c628df5 2695
sPymbed 0:c4152c628df5 2696 (void)len;
sPymbed 0:c4152c628df5 2697
sPymbed 0:c4152c628df5 2698 ato32(buf + begin, &nameSz);
sPymbed 0:c4152c628df5 2699 begin += LENGTH_SZ;
sPymbed 0:c4152c628df5 2700
sPymbed 0:c4152c628df5 2701 WMEMCPY(serviceName, buf + begin, nameSz);
sPymbed 0:c4152c628df5 2702 begin += nameSz;
sPymbed 0:c4152c628df5 2703 serviceName[nameSz] = 0;
sPymbed 0:c4152c628df5 2704
sPymbed 0:c4152c628df5 2705 *idx = begin;
sPymbed 0:c4152c628df5 2706
sPymbed 0:c4152c628df5 2707 WLOG(WS_LOG_DEBUG, "Accepted service: %s", serviceName);
sPymbed 0:c4152c628df5 2708 ssh->serverState = SERVER_USERAUTH_REQUEST_DONE;
sPymbed 0:c4152c628df5 2709
sPymbed 0:c4152c628df5 2710 return WS_SUCCESS;
sPymbed 0:c4152c628df5 2711 }
sPymbed 0:c4152c628df5 2712
sPymbed 0:c4152c628df5 2713
sPymbed 0:c4152c628df5 2714 /* Utility for DoUserAuthRequest() */
sPymbed 0:c4152c628df5 2715 static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData,
sPymbed 0:c4152c628df5 2716 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 2717 {
sPymbed 0:c4152c628df5 2718 word32 begin;
sPymbed 0:c4152c628df5 2719 WS_UserAuthData_Password* pw;
sPymbed 0:c4152c628df5 2720 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2721
sPymbed 0:c4152c628df5 2722 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPassword()");
sPymbed 0:c4152c628df5 2723
sPymbed 0:c4152c628df5 2724 if (ssh == NULL || authData == NULL ||
sPymbed 0:c4152c628df5 2725 buf == NULL || len == 0 || idx == NULL) {
sPymbed 0:c4152c628df5 2726
sPymbed 0:c4152c628df5 2727 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2728 }
sPymbed 0:c4152c628df5 2729
sPymbed 0:c4152c628df5 2730 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2731 begin = *idx;
sPymbed 0:c4152c628df5 2732 pw = &authData->sf.password;
sPymbed 0:c4152c628df5 2733 authData->type = WOLFSSH_USERAUTH_PASSWORD;
sPymbed 0:c4152c628df5 2734 ret = GetBoolean(&pw->hasNewPassword, buf, len, &begin);
sPymbed 0:c4152c628df5 2735 }
sPymbed 0:c4152c628df5 2736
sPymbed 0:c4152c628df5 2737 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2738 ret = GetUint32(&pw->passwordSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2739
sPymbed 0:c4152c628df5 2740 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2741 pw->password = buf + begin;
sPymbed 0:c4152c628df5 2742 begin += pw->passwordSz;
sPymbed 0:c4152c628df5 2743
sPymbed 0:c4152c628df5 2744 if (pw->hasNewPassword) {
sPymbed 0:c4152c628df5 2745 /* Skip the password change. Maybe error out since we aren't
sPymbed 0:c4152c628df5 2746 * supporting password changes at this time. */
sPymbed 0:c4152c628df5 2747 ret = GetUint32(&pw->newPasswordSz, buf, len, &begin);
sPymbed 0:c4152c628df5 2748 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2749 pw->newPassword = buf + begin;
sPymbed 0:c4152c628df5 2750 begin += pw->newPasswordSz;
sPymbed 0:c4152c628df5 2751 }
sPymbed 0:c4152c628df5 2752 }
sPymbed 0:c4152c628df5 2753 else {
sPymbed 0:c4152c628df5 2754 pw->newPassword = NULL;
sPymbed 0:c4152c628df5 2755 pw->newPasswordSz = 0;
sPymbed 0:c4152c628df5 2756 }
sPymbed 0:c4152c628df5 2757
sPymbed 0:c4152c628df5 2758 if (ssh->ctx->userAuthCb != NULL) {
sPymbed 0:c4152c628df5 2759 WLOG(WS_LOG_DEBUG, "DUARPW: Calling the userauth callback");
sPymbed 0:c4152c628df5 2760 ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD,
sPymbed 0:c4152c628df5 2761 authData, ssh->userAuthCtx);
sPymbed 0:c4152c628df5 2762 if (ret == WOLFSSH_USERAUTH_SUCCESS) {
sPymbed 0:c4152c628df5 2763 WLOG(WS_LOG_DEBUG, "DUARPW: password check successful");
sPymbed 0:c4152c628df5 2764 ssh->clientState = CLIENT_USERAUTH_DONE;
sPymbed 0:c4152c628df5 2765 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2766 }
sPymbed 0:c4152c628df5 2767 else {
sPymbed 0:c4152c628df5 2768 WLOG(WS_LOG_DEBUG, "DUARPW: password check failed");
sPymbed 0:c4152c628df5 2769 ret = SendUserAuthFailure(ssh, 0);
sPymbed 0:c4152c628df5 2770 }
sPymbed 0:c4152c628df5 2771 }
sPymbed 0:c4152c628df5 2772 else {
sPymbed 0:c4152c628df5 2773 WLOG(WS_LOG_DEBUG, "DUARPW: No user auth callback");
sPymbed 0:c4152c628df5 2774 ret = SendUserAuthFailure(ssh, 0);
sPymbed 0:c4152c628df5 2775 }
sPymbed 0:c4152c628df5 2776 }
sPymbed 0:c4152c628df5 2777
sPymbed 0:c4152c628df5 2778 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2779 *idx = begin;
sPymbed 0:c4152c628df5 2780
sPymbed 0:c4152c628df5 2781 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPassword(), ret = %d", ret);
sPymbed 0:c4152c628df5 2782 return ret;
sPymbed 0:c4152c628df5 2783 }
sPymbed 0:c4152c628df5 2784
sPymbed 0:c4152c628df5 2785 int ConstantCompare(byte encDigest[], byte checkDigest[],
sPymbed 0:c4152c628df5 2786 word32 encDigestSz){
sPymbed 0:c4152c628df5 2787 return 0;
sPymbed 0:c4152c628df5 2788 }
sPymbed 0:c4152c628df5 2789
sPymbed 0:c4152c628df5 2790
sPymbed 0:c4152c628df5 2791 /* Utility for DoUserAuthRequestPublicKey() */
sPymbed 0:c4152c628df5 2792 /* returns negative for error, positive is size of digest. */
sPymbed 0:c4152c628df5 2793 static int DoUserAuthRequestRsa(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
sPymbed 0:c4152c628df5 2794 byte hashId, byte* digest, word32 digestSz)
sPymbed 0:c4152c628df5 2795 {
sPymbed 0:c4152c628df5 2796 RsaKey key;
sPymbed 0:c4152c628df5 2797 byte checkDigest[MAX_ENCODED_SIG_SZ];
sPymbed 0:c4152c628df5 2798 int checkDigestSz;
sPymbed 0:c4152c628df5 2799 byte* publicKeyType;
sPymbed 0:c4152c628df5 2800 word32 publicKeyTypeSz = 0;
sPymbed 0:c4152c628df5 2801 byte* n;
sPymbed 0:c4152c628df5 2802 word32 nSz = 0;
sPymbed 0:c4152c628df5 2803 byte* e;
sPymbed 0:c4152c628df5 2804 word32 eSz = 0;
sPymbed 0:c4152c628df5 2805 word32 i = 0;
sPymbed 0:c4152c628df5 2806 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2807
sPymbed 0:c4152c628df5 2808 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestRsa()");
sPymbed 0:c4152c628df5 2809
sPymbed 0:c4152c628df5 2810 if (ssh == NULL || pk == NULL || digest == NULL || digestSz == 0)
sPymbed 0:c4152c628df5 2811 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2812
sPymbed 0:c4152c628df5 2813 /* First check that the public key's type matches the one we are
sPymbed 0:c4152c628df5 2814 * expecting. */
sPymbed 0:c4152c628df5 2815 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2816 ret = GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2817
sPymbed 0:c4152c628df5 2818 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2819 publicKeyType = pk->publicKey + i;
sPymbed 0:c4152c628df5 2820 i += publicKeyTypeSz;
sPymbed 0:c4152c628df5 2821 if (publicKeyTypeSz != pk->publicKeyTypeSz &&
sPymbed 0:c4152c628df5 2822 WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) {
sPymbed 0:c4152c628df5 2823
sPymbed 0:c4152c628df5 2824 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 2825 "Public Key's type does not match public key type");
sPymbed 0:c4152c628df5 2826 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 2827 }
sPymbed 0:c4152c628df5 2828 }
sPymbed 0:c4152c628df5 2829
sPymbed 0:c4152c628df5 2830 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2831 ret = GetUint32(&eSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2832
sPymbed 0:c4152c628df5 2833 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2834 e = pk->publicKey + i;
sPymbed 0:c4152c628df5 2835 i += eSz;
sPymbed 0:c4152c628df5 2836 ret = GetUint32(&nSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2837 }
sPymbed 0:c4152c628df5 2838
sPymbed 0:c4152c628df5 2839 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2840 n = pk->publicKey + i;
sPymbed 0:c4152c628df5 2841
sPymbed 0:c4152c628df5 2842 ret = wc_InitRsaKey(&key, ssh->ctx->heap);
sPymbed 0:c4152c628df5 2843 if (ret == 0)
sPymbed 0:c4152c628df5 2844 ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, &key);
sPymbed 0:c4152c628df5 2845 if (ret != 0) {
sPymbed 0:c4152c628df5 2846 WLOG(WS_LOG_DEBUG, "Could not decode public key");
sPymbed 0:c4152c628df5 2847 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 2848 }
sPymbed 0:c4152c628df5 2849 }
sPymbed 0:c4152c628df5 2850
sPymbed 0:c4152c628df5 2851 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2852 i = 0;
sPymbed 0:c4152c628df5 2853 /* First check that the signature's public key type matches the one
sPymbed 0:c4152c628df5 2854 * we are expecting. */
sPymbed 0:c4152c628df5 2855 ret = GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2856 }
sPymbed 0:c4152c628df5 2857
sPymbed 0:c4152c628df5 2858 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2859 publicKeyType = pk->publicKey + i;
sPymbed 0:c4152c628df5 2860 i += publicKeyTypeSz;
sPymbed 0:c4152c628df5 2861
sPymbed 0:c4152c628df5 2862 if (publicKeyTypeSz != pk->publicKeyTypeSz &&
sPymbed 0:c4152c628df5 2863 WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) {
sPymbed 0:c4152c628df5 2864
sPymbed 0:c4152c628df5 2865 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 2866 "Signature's type does not match public key type");
sPymbed 0:c4152c628df5 2867 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 2868 }
sPymbed 0:c4152c628df5 2869 }
sPymbed 0:c4152c628df5 2870
sPymbed 0:c4152c628df5 2871 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2872 ret = GetUint32(&nSz, pk->signature, pk->signatureSz, &i);
sPymbed 0:c4152c628df5 2873
sPymbed 0:c4152c628df5 2874 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2875 n = pk->signature + i;
sPymbed 0:c4152c628df5 2876 checkDigestSz = wc_RsaSSL_Verify(n, nSz, checkDigest,
sPymbed 0:c4152c628df5 2877 sizeof(checkDigest), &key);
sPymbed 0:c4152c628df5 2878 if (checkDigestSz <= 0) {
sPymbed 0:c4152c628df5 2879 WLOG(WS_LOG_DEBUG, "Could not verify signature");
sPymbed 0:c4152c628df5 2880 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 2881 }
sPymbed 0:c4152c628df5 2882 }
sPymbed 0:c4152c628df5 2883
sPymbed 0:c4152c628df5 2884 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2885 byte encDigest[MAX_ENCODED_SIG_SZ];
sPymbed 0:c4152c628df5 2886 word32 encDigestSz;
sPymbed 0:c4152c628df5 2887 volatile int compare;
sPymbed 0:c4152c628df5 2888 volatile int sizeCompare;
sPymbed 0:c4152c628df5 2889
sPymbed 0:c4152c628df5 2890 encDigestSz = wc_EncodeSignature(encDigest, digest,
sPymbed 0:c4152c628df5 2891 wc_HashGetDigestSize(hashId),
sPymbed 0:c4152c628df5 2892 wc_HashGetOID(hashId));
sPymbed 0:c4152c628df5 2893
sPymbed 0:c4152c628df5 2894 compare = ConstantCompare(encDigest, checkDigest,
sPymbed 0:c4152c628df5 2895 encDigestSz);
sPymbed 0:c4152c628df5 2896 sizeCompare = encDigestSz != (word32)checkDigestSz;
sPymbed 0:c4152c628df5 2897
sPymbed 0:c4152c628df5 2898 if ((compare | sizeCompare) == 0)
sPymbed 0:c4152c628df5 2899 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2900 else
sPymbed 0:c4152c628df5 2901 ret = WS_RSA_E;
sPymbed 0:c4152c628df5 2902 }
sPymbed 0:c4152c628df5 2903
sPymbed 0:c4152c628df5 2904 wc_FreeRsaKey(&key);
sPymbed 0:c4152c628df5 2905
sPymbed 0:c4152c628df5 2906 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestRsa(), ret = %d", ret);
sPymbed 0:c4152c628df5 2907 return ret;
sPymbed 0:c4152c628df5 2908 }
sPymbed 0:c4152c628df5 2909
sPymbed 0:c4152c628df5 2910
sPymbed 0:c4152c628df5 2911 /* Utility for DoUserAuthRequestPublicKey() */
sPymbed 0:c4152c628df5 2912 /* returns negative for error, positive is size of digest. */
sPymbed 0:c4152c628df5 2913 static int DoUserAuthRequestEcc(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
sPymbed 0:c4152c628df5 2914 byte hashId, byte* digest, word32 digestSz)
sPymbed 0:c4152c628df5 2915 {
sPymbed 0:c4152c628df5 2916 ecc_key key;
sPymbed 0:c4152c628df5 2917 byte* publicKeyType;
sPymbed 0:c4152c628df5 2918 word32 publicKeyTypeSz = 0;
sPymbed 0:c4152c628df5 2919 byte* curveName;
sPymbed 0:c4152c628df5 2920 word32 curveNameSz = 0;
sPymbed 0:c4152c628df5 2921 mp_int r, s;
sPymbed 0:c4152c628df5 2922 byte* q;
sPymbed 0:c4152c628df5 2923 word32 sz, qSz;
sPymbed 0:c4152c628df5 2924 word32 i = 0;
sPymbed 0:c4152c628df5 2925 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 2926
sPymbed 0:c4152c628df5 2927 (void)hashId;
sPymbed 0:c4152c628df5 2928
sPymbed 0:c4152c628df5 2929 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestRsa()");
sPymbed 0:c4152c628df5 2930
sPymbed 0:c4152c628df5 2931 if (ssh == NULL || pk == NULL || digest == NULL || digestSz == 0)
sPymbed 0:c4152c628df5 2932 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 2933
sPymbed 0:c4152c628df5 2934 /* First check that the public key's type matches the one we are
sPymbed 0:c4152c628df5 2935 * expecting. */
sPymbed 0:c4152c628df5 2936 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2937 ret = GetUint32(&publicKeyTypeSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2938
sPymbed 0:c4152c628df5 2939 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2940 publicKeyType = pk->publicKey + i;
sPymbed 0:c4152c628df5 2941 i += publicKeyTypeSz;
sPymbed 0:c4152c628df5 2942 if (publicKeyTypeSz != pk->publicKeyTypeSz &&
sPymbed 0:c4152c628df5 2943 WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) {
sPymbed 0:c4152c628df5 2944
sPymbed 0:c4152c628df5 2945 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 2946 "Public Key's type does not match public key type");
sPymbed 0:c4152c628df5 2947 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 2948 }
sPymbed 0:c4152c628df5 2949 }
sPymbed 0:c4152c628df5 2950
sPymbed 0:c4152c628df5 2951 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 2952 ret = GetUint32(&curveNameSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2953
sPymbed 0:c4152c628df5 2954 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2955 curveName = pk->publicKey + i;
sPymbed 0:c4152c628df5 2956 (void)curveName; /* Not used at the moment, hush the compiler. */
sPymbed 0:c4152c628df5 2957 i += curveNameSz;
sPymbed 0:c4152c628df5 2958 ret = GetUint32(&qSz, pk->publicKey, pk->publicKeySz, &i);
sPymbed 0:c4152c628df5 2959 }
sPymbed 0:c4152c628df5 2960
sPymbed 0:c4152c628df5 2961 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2962 q = pk->publicKey + i;
sPymbed 0:c4152c628df5 2963 i += qSz;
sPymbed 0:c4152c628df5 2964 ret = wc_ecc_init_ex(&key, ssh->ctx->heap, INVALID_DEVID);
sPymbed 0:c4152c628df5 2965 }
sPymbed 0:c4152c628df5 2966
sPymbed 0:c4152c628df5 2967 if (ret == 0)
sPymbed 0:c4152c628df5 2968 ret = wc_ecc_import_x963(q, qSz, &key);
sPymbed 0:c4152c628df5 2969
sPymbed 0:c4152c628df5 2970 if (ret != 0) {
sPymbed 0:c4152c628df5 2971 WLOG(WS_LOG_DEBUG, "Could not decode public key");
sPymbed 0:c4152c628df5 2972 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 2973 }
sPymbed 0:c4152c628df5 2974
sPymbed 0:c4152c628df5 2975 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2976 i = 0;
sPymbed 0:c4152c628df5 2977 /* First check that the signature's public key type matches the one
sPymbed 0:c4152c628df5 2978 * we are expecting. */
sPymbed 0:c4152c628df5 2979 ret = GetUint32(&publicKeyTypeSz, pk->signature, pk->signatureSz, &i);
sPymbed 0:c4152c628df5 2980 }
sPymbed 0:c4152c628df5 2981
sPymbed 0:c4152c628df5 2982 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2983 publicKeyType = pk->signature + i;
sPymbed 0:c4152c628df5 2984 i += publicKeyTypeSz;
sPymbed 0:c4152c628df5 2985
sPymbed 0:c4152c628df5 2986 if (publicKeyTypeSz != pk->publicKeyTypeSz &&
sPymbed 0:c4152c628df5 2987 WMEMCMP(publicKeyType, pk->publicKeyType, publicKeyTypeSz) != 0) {
sPymbed 0:c4152c628df5 2988
sPymbed 0:c4152c628df5 2989 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 2990 "Signature's type does not match public key type");
sPymbed 0:c4152c628df5 2991 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 2992 }
sPymbed 0:c4152c628df5 2993 }
sPymbed 0:c4152c628df5 2994
sPymbed 0:c4152c628df5 2995 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 2996 /* Get the size of the signature blob. */
sPymbed 0:c4152c628df5 2997 ret = GetUint32(&sz, pk->signature, pk->signatureSz, &i);
sPymbed 0:c4152c628df5 2998 }
sPymbed 0:c4152c628df5 2999
sPymbed 0:c4152c628df5 3000 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3001 /* Get R and S. */
sPymbed 0:c4152c628df5 3002 ret = GetUint32(&sz, pk->signature, pk->signatureSz, &i);
sPymbed 0:c4152c628df5 3003 }
sPymbed 0:c4152c628df5 3004
sPymbed 0:c4152c628df5 3005 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3006 ret = mp_read_unsigned_bin(&r, pk->signature + i, sz);
sPymbed 0:c4152c628df5 3007 if (ret != 0)
sPymbed 0:c4152c628df5 3008 ret = WS_PARSE_E;
sPymbed 0:c4152c628df5 3009 else
sPymbed 0:c4152c628df5 3010 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3011 }
sPymbed 0:c4152c628df5 3012
sPymbed 0:c4152c628df5 3013 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3014 i += sz;
sPymbed 0:c4152c628df5 3015 ret = GetUint32(&sz, pk->signature, pk->signatureSz, &i);
sPymbed 0:c4152c628df5 3016 }
sPymbed 0:c4152c628df5 3017
sPymbed 0:c4152c628df5 3018 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3019 ret = mp_read_unsigned_bin(&s, pk->signature + i, sz);
sPymbed 0:c4152c628df5 3020 if (ret != 0)
sPymbed 0:c4152c628df5 3021 ret = WS_PARSE_E;
sPymbed 0:c4152c628df5 3022 else
sPymbed 0:c4152c628df5 3023 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3024 }
sPymbed 0:c4152c628df5 3025
sPymbed 0:c4152c628df5 3026 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3027 int status = 0;
sPymbed 0:c4152c628df5 3028
sPymbed 0:c4152c628df5 3029 ret = wc_ecc_verify_hash_ex(&r, &s, digest, digestSz, &status, &key);
sPymbed 0:c4152c628df5 3030 if (ret != 0) {
sPymbed 0:c4152c628df5 3031 WLOG(WS_LOG_DEBUG, "Could not verify signature");
sPymbed 0:c4152c628df5 3032 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 3033 }
sPymbed 0:c4152c628df5 3034 else
sPymbed 0:c4152c628df5 3035 ret = status ? WS_SUCCESS : WS_ECC_E;
sPymbed 0:c4152c628df5 3036 }
sPymbed 0:c4152c628df5 3037
sPymbed 0:c4152c628df5 3038 mp_clear(&r);
sPymbed 0:c4152c628df5 3039 mp_clear(&s);
sPymbed 0:c4152c628df5 3040 wc_ecc_free(&key);
sPymbed 0:c4152c628df5 3041
sPymbed 0:c4152c628df5 3042 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestEcc(), ret = %d", ret);
sPymbed 0:c4152c628df5 3043 return ret;
sPymbed 0:c4152c628df5 3044 }
sPymbed 0:c4152c628df5 3045
sPymbed 0:c4152c628df5 3046
sPymbed 0:c4152c628df5 3047 /* Utility for DoUserAuthRequest() */
sPymbed 0:c4152c628df5 3048 static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
sPymbed 0:c4152c628df5 3049 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3050 {
sPymbed 0:c4152c628df5 3051 word32 begin;
sPymbed 0:c4152c628df5 3052 WS_UserAuthData_PublicKey* pk;
sPymbed 0:c4152c628df5 3053 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3054 int authFailure = 0;
sPymbed 0:c4152c628df5 3055
sPymbed 0:c4152c628df5 3056 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPublicKey()");
sPymbed 0:c4152c628df5 3057
sPymbed 0:c4152c628df5 3058 if (ssh == NULL || authData == NULL ||
sPymbed 0:c4152c628df5 3059 buf == NULL || len == 0 || idx == NULL) {
sPymbed 0:c4152c628df5 3060
sPymbed 0:c4152c628df5 3061 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3062 }
sPymbed 0:c4152c628df5 3063
sPymbed 0:c4152c628df5 3064 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3065 begin = *idx;
sPymbed 0:c4152c628df5 3066 pk = &authData->sf.publicKey;
sPymbed 0:c4152c628df5 3067 authData->type = WOLFSSH_USERAUTH_PUBLICKEY;
sPymbed 0:c4152c628df5 3068 ret = GetBoolean(&pk->hasSignature, buf, len, &begin);
sPymbed 0:c4152c628df5 3069 }
sPymbed 0:c4152c628df5 3070
sPymbed 0:c4152c628df5 3071 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3072 ret = GetUint32(&pk->publicKeyTypeSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3073
sPymbed 0:c4152c628df5 3074 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3075 pk->publicKeyType = buf + begin;
sPymbed 0:c4152c628df5 3076 begin += pk->publicKeyTypeSz;
sPymbed 0:c4152c628df5 3077 ret = GetUint32(&pk->publicKeySz, buf, len, &begin);
sPymbed 0:c4152c628df5 3078 }
sPymbed 0:c4152c628df5 3079
sPymbed 0:c4152c628df5 3080 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3081 pk->publicKey = buf + begin;
sPymbed 0:c4152c628df5 3082 begin += pk->publicKeySz;
sPymbed 0:c4152c628df5 3083
sPymbed 0:c4152c628df5 3084 if (pk->hasSignature) {
sPymbed 0:c4152c628df5 3085 ret = GetUint32(&pk->signatureSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3086 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3087 pk->signature = buf + begin;
sPymbed 0:c4152c628df5 3088 begin += pk->signatureSz;
sPymbed 0:c4152c628df5 3089 }
sPymbed 0:c4152c628df5 3090 }
sPymbed 0:c4152c628df5 3091 else {
sPymbed 0:c4152c628df5 3092 pk->signature = NULL;
sPymbed 0:c4152c628df5 3093 pk->signatureSz = 0;
sPymbed 0:c4152c628df5 3094 }
sPymbed 0:c4152c628df5 3095
sPymbed 0:c4152c628df5 3096 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3097 *idx = begin;
sPymbed 0:c4152c628df5 3098
sPymbed 0:c4152c628df5 3099 if (ssh->ctx->userAuthCb != NULL) {
sPymbed 0:c4152c628df5 3100 WLOG(WS_LOG_DEBUG, "DUARPK: Calling the userauth callback");
sPymbed 0:c4152c628df5 3101 ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY,
sPymbed 0:c4152c628df5 3102 authData, ssh->userAuthCtx);
sPymbed 0:c4152c628df5 3103 WLOG(WS_LOG_DEBUG, "DUARPK: callback result = %d", ret);
sPymbed 0:c4152c628df5 3104 if (ret == WOLFSSH_USERAUTH_SUCCESS)
sPymbed 0:c4152c628df5 3105 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3106 else {
sPymbed 0:c4152c628df5 3107 ret = SendUserAuthFailure(ssh, 0);
sPymbed 0:c4152c628df5 3108 authFailure = 1;
sPymbed 0:c4152c628df5 3109 }
sPymbed 0:c4152c628df5 3110 }
sPymbed 0:c4152c628df5 3111 else {
sPymbed 0:c4152c628df5 3112 WLOG(WS_LOG_DEBUG, "DUARPK: no userauth callback set");
sPymbed 0:c4152c628df5 3113 ret = SendUserAuthFailure(ssh, 0);
sPymbed 0:c4152c628df5 3114 authFailure = 1;
sPymbed 0:c4152c628df5 3115 }
sPymbed 0:c4152c628df5 3116 }
sPymbed 0:c4152c628df5 3117 }
sPymbed 0:c4152c628df5 3118
sPymbed 0:c4152c628df5 3119 if (ret == WS_SUCCESS && !authFailure) {
sPymbed 0:c4152c628df5 3120 if (pk->signature == NULL) {
sPymbed 0:c4152c628df5 3121 WLOG(WS_LOG_DEBUG, "DUARPK: Send the PK OK");
sPymbed 0:c4152c628df5 3122 ret = SendUserAuthPkOk(ssh, pk->publicKeyType, pk->publicKeyTypeSz,
sPymbed 0:c4152c628df5 3123 pk->publicKey, pk->publicKeySz);
sPymbed 0:c4152c628df5 3124 }
sPymbed 0:c4152c628df5 3125 else {
sPymbed 0:c4152c628df5 3126 wc_HashAlg hash;
sPymbed 0:c4152c628df5 3127 byte digest[WC_MAX_DIGEST_SIZE];
sPymbed 0:c4152c628df5 3128 word32 digestSz;
sPymbed 0:c4152c628df5 3129 byte hashId = WC_HASH_TYPE_SHA;
sPymbed 0:c4152c628df5 3130 byte pkTypeId;
sPymbed 0:c4152c628df5 3131
sPymbed 0:c4152c628df5 3132 pkTypeId = NameToId((char*)pk->publicKeyType,
sPymbed 0:c4152c628df5 3133 pk->publicKeyTypeSz);
sPymbed 0:c4152c628df5 3134 if (pkTypeId == ID_UNKNOWN)
sPymbed 0:c4152c628df5 3135 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 3136
sPymbed 0:c4152c628df5 3137 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3138 hashId = HashForId(pkTypeId);
sPymbed 0:c4152c628df5 3139 WMEMSET(digest, 0, sizeof(digest));
sPymbed 0:c4152c628df5 3140 digestSz = wc_HashGetDigestSize(hashId);
sPymbed 0:c4152c628df5 3141 ret = wc_HashInit(&hash, hashId);
sPymbed 0:c4152c628df5 3142 }
sPymbed 0:c4152c628df5 3143
sPymbed 0:c4152c628df5 3144 if (ret == 0) {
sPymbed 0:c4152c628df5 3145 c32toa(ssh->sessionIdSz, digest);
sPymbed 0:c4152c628df5 3146 ret = wc_HashUpdate(&hash, hashId, digest, UINT32_SZ);
sPymbed 0:c4152c628df5 3147 }
sPymbed 0:c4152c628df5 3148
sPymbed 0:c4152c628df5 3149 if (ret == 0)
sPymbed 0:c4152c628df5 3150 ret = wc_HashUpdate(&hash, hashId,
sPymbed 0:c4152c628df5 3151 ssh->sessionId, ssh->sessionIdSz);
sPymbed 0:c4152c628df5 3152
sPymbed 0:c4152c628df5 3153 if (ret == 0) {
sPymbed 0:c4152c628df5 3154 digest[0] = MSGID_USERAUTH_REQUEST;
sPymbed 0:c4152c628df5 3155 ret = wc_HashUpdate(&hash, hashId, digest, MSG_ID_SZ);
sPymbed 0:c4152c628df5 3156 }
sPymbed 0:c4152c628df5 3157
sPymbed 0:c4152c628df5 3158 /* The rest of the fields in the signature are already
sPymbed 0:c4152c628df5 3159 * in the buffer. Just need to account for the sizes. */
sPymbed 0:c4152c628df5 3160 if (ret == 0)
sPymbed 0:c4152c628df5 3161 ret = wc_HashUpdate(&hash, hashId, pk->dataToSign,
sPymbed 0:c4152c628df5 3162 authData->usernameSz +
sPymbed 0:c4152c628df5 3163 authData->serviceNameSz +
sPymbed 0:c4152c628df5 3164 authData->authNameSz + BOOLEAN_SZ +
sPymbed 0:c4152c628df5 3165 pk->publicKeyTypeSz + pk->publicKeySz +
sPymbed 0:c4152c628df5 3166 (UINT32_SZ * 5));
sPymbed 0:c4152c628df5 3167 if (ret == 0) {
sPymbed 0:c4152c628df5 3168 ret = wc_HashFinal(&hash, hashId, digest);
sPymbed 0:c4152c628df5 3169
sPymbed 0:c4152c628df5 3170 if (ret != 0)
sPymbed 0:c4152c628df5 3171 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 3172 else
sPymbed 0:c4152c628df5 3173 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3174 }
sPymbed 0:c4152c628df5 3175
sPymbed 0:c4152c628df5 3176 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3177 if (pkTypeId == ID_SSH_RSA)
sPymbed 0:c4152c628df5 3178 ret = DoUserAuthRequestRsa(ssh, pk,
sPymbed 0:c4152c628df5 3179 hashId, digest, digestSz);
sPymbed 0:c4152c628df5 3180 else if (pkTypeId == ID_ECDSA_SHA2_NISTP256 ||
sPymbed 0:c4152c628df5 3181 pkTypeId == ID_ECDSA_SHA2_NISTP384 ||
sPymbed 0:c4152c628df5 3182 pkTypeId == ID_ECDSA_SHA2_NISTP521)
sPymbed 0:c4152c628df5 3183 ret = DoUserAuthRequestEcc(ssh, pk,
sPymbed 0:c4152c628df5 3184 hashId, digest, digestSz);
sPymbed 0:c4152c628df5 3185 }
sPymbed 0:c4152c628df5 3186
sPymbed 0:c4152c628df5 3187 if (ret != WS_SUCCESS) {
sPymbed 0:c4152c628df5 3188 WLOG(WS_LOG_DEBUG, "DUARPK: signature compare failure");
sPymbed 0:c4152c628df5 3189 ret = SendUserAuthFailure(ssh, 0);
sPymbed 0:c4152c628df5 3190 }
sPymbed 0:c4152c628df5 3191 else {
sPymbed 0:c4152c628df5 3192 ssh->clientState = CLIENT_USERAUTH_DONE;
sPymbed 0:c4152c628df5 3193 }
sPymbed 0:c4152c628df5 3194 }
sPymbed 0:c4152c628df5 3195 }
sPymbed 0:c4152c628df5 3196
sPymbed 0:c4152c628df5 3197 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPublicKey(), ret = %d", ret);
sPymbed 0:c4152c628df5 3198 return ret;
sPymbed 0:c4152c628df5 3199 }
sPymbed 0:c4152c628df5 3200
sPymbed 0:c4152c628df5 3201
sPymbed 0:c4152c628df5 3202 static int DoUserAuthRequest(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3203 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3204 {
sPymbed 0:c4152c628df5 3205 word32 begin;
sPymbed 0:c4152c628df5 3206 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3207 byte authNameId;
sPymbed 0:c4152c628df5 3208 WS_UserAuthData authData;
sPymbed 0:c4152c628df5 3209
sPymbed 0:c4152c628df5 3210 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequest()");
sPymbed 0:c4152c628df5 3211
sPymbed 0:c4152c628df5 3212 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3213 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3214
sPymbed 0:c4152c628df5 3215 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3216 begin = *idx;
sPymbed 0:c4152c628df5 3217 WMEMSET(&authData, 0, sizeof(authData));
sPymbed 0:c4152c628df5 3218 ret = GetUint32(&authData.usernameSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3219 }
sPymbed 0:c4152c628df5 3220
sPymbed 0:c4152c628df5 3221 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3222 authData.username = buf + begin;
sPymbed 0:c4152c628df5 3223 begin += authData.usernameSz;
sPymbed 0:c4152c628df5 3224
sPymbed 0:c4152c628df5 3225 ret = GetUint32(&authData.serviceNameSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3226 }
sPymbed 0:c4152c628df5 3227
sPymbed 0:c4152c628df5 3228 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3229 authData.serviceName = buf + begin;
sPymbed 0:c4152c628df5 3230 begin += authData.serviceNameSz;
sPymbed 0:c4152c628df5 3231
sPymbed 0:c4152c628df5 3232 ret = GetUint32(&authData.authNameSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3233 }
sPymbed 0:c4152c628df5 3234
sPymbed 0:c4152c628df5 3235 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3236 authData.authName = buf + begin;
sPymbed 0:c4152c628df5 3237 begin += authData.authNameSz;
sPymbed 0:c4152c628df5 3238 authNameId = NameToId((char*)authData.authName, authData.authNameSz);
sPymbed 0:c4152c628df5 3239
sPymbed 0:c4152c628df5 3240 if (authNameId == ID_USERAUTH_PASSWORD)
sPymbed 0:c4152c628df5 3241 ret = DoUserAuthRequestPassword(ssh, &authData, buf, len, &begin);
sPymbed 0:c4152c628df5 3242 else if (authNameId == ID_USERAUTH_PUBLICKEY) {
sPymbed 0:c4152c628df5 3243 authData.sf.publicKey.dataToSign = buf + *idx;
sPymbed 0:c4152c628df5 3244 ret = DoUserAuthRequestPublicKey(ssh, &authData, buf, len, &begin);
sPymbed 0:c4152c628df5 3245 }
sPymbed 0:c4152c628df5 3246 #ifdef WOLFSSH_ALLOW_USERAUTH_NONE
sPymbed 0:c4152c628df5 3247 else if (authNameId == ID_NONE) {
sPymbed 0:c4152c628df5 3248 ssh->clientState = CLIENT_USERAUTH_DONE;
sPymbed 0:c4152c628df5 3249 }
sPymbed 0:c4152c628df5 3250 #endif
sPymbed 0:c4152c628df5 3251 else {
sPymbed 0:c4152c628df5 3252 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 3253 "invalid userauth type: %s", IdToName(authNameId));
sPymbed 0:c4152c628df5 3254 ret = SendUserAuthFailure(ssh, 0);
sPymbed 0:c4152c628df5 3255 }
sPymbed 0:c4152c628df5 3256
sPymbed 0:c4152c628df5 3257 *idx = begin;
sPymbed 0:c4152c628df5 3258 }
sPymbed 0:c4152c628df5 3259
sPymbed 0:c4152c628df5 3260 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 3261 return ret;
sPymbed 0:c4152c628df5 3262 }
sPymbed 0:c4152c628df5 3263
sPymbed 0:c4152c628df5 3264
sPymbed 0:c4152c628df5 3265 static int DoUserAuthFailure(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3266 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3267 {
sPymbed 0:c4152c628df5 3268 byte authList[3]; /* Should only ever be password, publickey, hostname */
sPymbed 0:c4152c628df5 3269 word32 authListSz;
sPymbed 0:c4152c628df5 3270 byte partialSuccess;
sPymbed 0:c4152c628df5 3271 byte authId = ID_USERAUTH_PASSWORD;
sPymbed 0:c4152c628df5 3272 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3273
sPymbed 0:c4152c628df5 3274 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthFailure()");
sPymbed 0:c4152c628df5 3275
sPymbed 0:c4152c628df5 3276 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3277 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3278
sPymbed 0:c4152c628df5 3279 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3280 ret = GetNameList(authList, &authListSz, buf, len, idx);
sPymbed 0:c4152c628df5 3281
sPymbed 0:c4152c628df5 3282 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3283 ret = GetBoolean(&partialSuccess, buf, len, idx);
sPymbed 0:c4152c628df5 3284
sPymbed 0:c4152c628df5 3285 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3286 ret = SendUserAuthRequest(ssh, authId);
sPymbed 0:c4152c628df5 3287
sPymbed 0:c4152c628df5 3288 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthFailure(), ret = %d", ret);
sPymbed 0:c4152c628df5 3289 return ret;
sPymbed 0:c4152c628df5 3290 }
sPymbed 0:c4152c628df5 3291
sPymbed 0:c4152c628df5 3292
sPymbed 0:c4152c628df5 3293 static int DoUserAuthSuccess(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3294 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3295 {
sPymbed 0:c4152c628df5 3296 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3297
sPymbed 0:c4152c628df5 3298 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthSuccess()");
sPymbed 0:c4152c628df5 3299
sPymbed 0:c4152c628df5 3300 /* This message does not have any payload. len should be 0. */
sPymbed 0:c4152c628df5 3301 if (ssh == NULL || buf == NULL || len != 0 || idx == NULL)
sPymbed 0:c4152c628df5 3302 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3303
sPymbed 0:c4152c628df5 3304 ssh->serverState = SERVER_USERAUTH_ACCEPT_DONE;
sPymbed 0:c4152c628df5 3305
sPymbed 0:c4152c628df5 3306 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthSuccess(), ret = %d", ret);
sPymbed 0:c4152c628df5 3307 return ret;
sPymbed 0:c4152c628df5 3308 }
sPymbed 0:c4152c628df5 3309
sPymbed 0:c4152c628df5 3310
sPymbed 0:c4152c628df5 3311 static int DoUserAuthBanner(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3312 {
sPymbed 0:c4152c628df5 3313 word32 begin;
sPymbed 0:c4152c628df5 3314 char banner[80];
sPymbed 0:c4152c628df5 3315 word32 bannerSz = sizeof(banner);
sPymbed 0:c4152c628df5 3316 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3317
sPymbed 0:c4152c628df5 3318 WLOG(WS_LOG_DEBUG, "Entering DoUserAuthBanner()");
sPymbed 0:c4152c628df5 3319
sPymbed 0:c4152c628df5 3320 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3321 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3322
sPymbed 0:c4152c628df5 3323 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3324 begin = *idx;
sPymbed 0:c4152c628df5 3325 ret = GetString(banner, &bannerSz, buf, len, idx);
sPymbed 0:c4152c628df5 3326 }
sPymbed 0:c4152c628df5 3327
sPymbed 0:c4152c628df5 3328 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3329 ret = GetUint32(&bannerSz, buf, len, idx);
sPymbed 0:c4152c628df5 3330
sPymbed 0:c4152c628df5 3331 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3332 begin += bannerSz;
sPymbed 0:c4152c628df5 3333 if (ssh->ctx->showBanner) {
sPymbed 0:c4152c628df5 3334 WLOG(WS_LOG_INFO, "%s", banner);
sPymbed 0:c4152c628df5 3335 }
sPymbed 0:c4152c628df5 3336 }
sPymbed 0:c4152c628df5 3337
sPymbed 0:c4152c628df5 3338 WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthBanner(), ret = %d", ret);
sPymbed 0:c4152c628df5 3339 return ret;
sPymbed 0:c4152c628df5 3340 }
sPymbed 0:c4152c628df5 3341
sPymbed 0:c4152c628df5 3342
sPymbed 0:c4152c628df5 3343 static int DoGlobalRequest(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3344 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3345 {
sPymbed 0:c4152c628df5 3346 word32 begin;
sPymbed 0:c4152c628df5 3347 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3348 char name[80];
sPymbed 0:c4152c628df5 3349 word32 nameSz = sizeof(name);
sPymbed 0:c4152c628df5 3350 byte wantReply = 0;
sPymbed 0:c4152c628df5 3351
sPymbed 0:c4152c628df5 3352 WLOG(WS_LOG_DEBUG, "Entering DoGlobalRequest()");
sPymbed 0:c4152c628df5 3353
sPymbed 0:c4152c628df5 3354 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3355 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3356
sPymbed 0:c4152c628df5 3357 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3358 begin = *idx;
sPymbed 0:c4152c628df5 3359 ret = GetString(name, &nameSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3360 }
sPymbed 0:c4152c628df5 3361
sPymbed 0:c4152c628df5 3362 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3363 WLOG(WS_LOG_DEBUG, "DGR: request name = %s", name);
sPymbed 0:c4152c628df5 3364 ret = GetBoolean(&wantReply, buf, len, &begin);
sPymbed 0:c4152c628df5 3365 }
sPymbed 0:c4152c628df5 3366
sPymbed 0:c4152c628df5 3367 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3368 *idx += len;
sPymbed 0:c4152c628df5 3369
sPymbed 0:c4152c628df5 3370 if (wantReply)
sPymbed 0:c4152c628df5 3371 ret = SendRequestSuccess(ssh, 0);
sPymbed 0:c4152c628df5 3372 }
sPymbed 0:c4152c628df5 3373
sPymbed 0:c4152c628df5 3374 WLOG(WS_LOG_DEBUG, "Leaving DoGlobalRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 3375 return ret;
sPymbed 0:c4152c628df5 3376 }
sPymbed 0:c4152c628df5 3377
sPymbed 0:c4152c628df5 3378
sPymbed 0:c4152c628df5 3379 static int DoChannelOpen(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3380 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3381 {
sPymbed 0:c4152c628df5 3382 word32 begin = *idx;
sPymbed 0:c4152c628df5 3383 word32 typeSz;
sPymbed 0:c4152c628df5 3384 char type[32];
sPymbed 0:c4152c628df5 3385 byte typeId = ID_UNKNOWN;
sPymbed 0:c4152c628df5 3386 word32 peerChannelId;
sPymbed 0:c4152c628df5 3387 word32 peerInitialWindowSz;
sPymbed 0:c4152c628df5 3388 word32 peerMaxPacketSz;
sPymbed 0:c4152c628df5 3389 int ret;
sPymbed 0:c4152c628df5 3390 WOLFSSH_CHANNEL* newChannel;
sPymbed 0:c4152c628df5 3391
sPymbed 0:c4152c628df5 3392 WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()");
sPymbed 0:c4152c628df5 3393 //ESP_LOGI("WOLFSSH", "Entering DoChannelOpen()");
sPymbed 0:c4152c628df5 3394
sPymbed 0:c4152c628df5 3395 typeSz = sizeof(type);
sPymbed 0:c4152c628df5 3396 ret = GetString(type, &typeSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3397
sPymbed 0:c4152c628df5 3398 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3399 ret = GetUint32(&peerChannelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3400
sPymbed 0:c4152c628df5 3401 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3402 ret = GetUint32(&peerInitialWindowSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3403
sPymbed 0:c4152c628df5 3404 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3405 ret = GetUint32(&peerMaxPacketSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3406
sPymbed 0:c4152c628df5 3407 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3408 *idx = begin;
sPymbed 0:c4152c628df5 3409
sPymbed 0:c4152c628df5 3410 WLOG(WS_LOG_INFO, " type = %s", type);
sPymbed 0:c4152c628df5 3411 WLOG(WS_LOG_INFO, " peerChannelId = %u", peerChannelId);
sPymbed 0:c4152c628df5 3412 WLOG(WS_LOG_INFO, " peerInitialWindowSz = %u", peerInitialWindowSz);
sPymbed 0:c4152c628df5 3413 WLOG(WS_LOG_INFO, " peerMaxPacketSz = %u", peerMaxPacketSz);
sPymbed 0:c4152c628df5 3414
sPymbed 0:c4152c628df5 3415 //ESP_LOGI("WOLFSSH", "DoChannelOpen type = %s", type);
sPymbed 0:c4152c628df5 3416 //ESP_LOGI("WOLFSSH", "DoChannelOpen peerChId = %u", peerChannelId);
sPymbed 0:c4152c628df5 3417 //ESP_LOGI("WOLFSSH", "DoChannelOpen peerInitWndSz = %u", peerInitialWindowSz);
sPymbed 0:c4152c628df5 3418 //ESP_LOGI("WOLFSSH", "DoChannelOpen peerMaxPktSz = %u", peerMaxPacketSz);
sPymbed 0:c4152c628df5 3419
sPymbed 0:c4152c628df5 3420 typeId = NameToId(type, typeSz);
sPymbed 0:c4152c628df5 3421 if (typeId != ID_CHANTYPE_SESSION)
sPymbed 0:c4152c628df5 3422 ret = WS_INVALID_CHANTYPE;
sPymbed 0:c4152c628df5 3423 //ESP_LOGI("WOLFSSH", "DoChannelOpen ret = %d", ret);
sPymbed 0:c4152c628df5 3424 }
sPymbed 0:c4152c628df5 3425
sPymbed 0:c4152c628df5 3426 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3427 newChannel = ChannelNew(ssh, typeId,
sPymbed 0:c4152c628df5 3428 DEFAULT_WINDOW_SZ, DEFAULT_MAX_PACKET_SZ);
sPymbed 0:c4152c628df5 3429 //ESP_LOGI("WOLFSSH", "DoChannelOpen newCh = %p", newChannel);
sPymbed 0:c4152c628df5 3430 if (newChannel == NULL)
sPymbed 0:c4152c628df5 3431 ret = WS_RESOURCE_E;
sPymbed 0:c4152c628df5 3432 else {
sPymbed 0:c4152c628df5 3433 ChannelUpdate(newChannel, peerChannelId,
sPymbed 0:c4152c628df5 3434 peerInitialWindowSz, peerMaxPacketSz);
sPymbed 0:c4152c628df5 3435 //ESP_LOGI("WOLFSSH", "DoChannelOpen ChUpdate");
sPymbed 0:c4152c628df5 3436 if (ssh->channelListSz == 0)
sPymbed 0:c4152c628df5 3437 ssh->defaultPeerChannelId = peerChannelId;
sPymbed 0:c4152c628df5 3438 ChannelAppend(ssh, newChannel);
sPymbed 0:c4152c628df5 3439
sPymbed 0:c4152c628df5 3440 ssh->clientState = CLIENT_DONE;
sPymbed 0:c4152c628df5 3441 }
sPymbed 0:c4152c628df5 3442 }
sPymbed 0:c4152c628df5 3443
sPymbed 0:c4152c628df5 3444 WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpen(), ret = %d", ret);
sPymbed 0:c4152c628df5 3445 //ESP_LOGI("WOLFSSH", "Leaving DoChannelOpen(), ret = %d", ret);
sPymbed 0:c4152c628df5 3446 return ret;
sPymbed 0:c4152c628df5 3447 }
sPymbed 0:c4152c628df5 3448
sPymbed 0:c4152c628df5 3449
sPymbed 0:c4152c628df5 3450 static int DoChannelOpenConf(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3451 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3452 {
sPymbed 0:c4152c628df5 3453 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 3454 word32 begin, channelId, peerChannelId,
sPymbed 0:c4152c628df5 3455 peerInitialWindowSz, peerMaxPacketSz;
sPymbed 0:c4152c628df5 3456 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3457
sPymbed 0:c4152c628df5 3458 WLOG(WS_LOG_DEBUG, "Entering DoChannelOpenConf()");
sPymbed 0:c4152c628df5 3459
sPymbed 0:c4152c628df5 3460 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3461 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3462
sPymbed 0:c4152c628df5 3463 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3464 begin = *idx;
sPymbed 0:c4152c628df5 3465 ret = GetUint32(&channelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3466 }
sPymbed 0:c4152c628df5 3467
sPymbed 0:c4152c628df5 3468 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3469 ret = GetUint32(&peerChannelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3470
sPymbed 0:c4152c628df5 3471 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3472 ret = GetUint32(&peerInitialWindowSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3473
sPymbed 0:c4152c628df5 3474 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3475 ret = GetUint32(&peerMaxPacketSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3476
sPymbed 0:c4152c628df5 3477 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3478 WLOG(WS_LOG_INFO, " channelId = %u", channelId);
sPymbed 0:c4152c628df5 3479 WLOG(WS_LOG_INFO, " peerChannelId = %u", peerChannelId);
sPymbed 0:c4152c628df5 3480 WLOG(WS_LOG_INFO, " peerInitialWindowSz = %u", peerInitialWindowSz);
sPymbed 0:c4152c628df5 3481 WLOG(WS_LOG_INFO, " peerMaxPacketSz = %u", peerMaxPacketSz);
sPymbed 0:c4152c628df5 3482
sPymbed 0:c4152c628df5 3483 channel = ChannelFind(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 3484 if (channel == NULL)
sPymbed 0:c4152c628df5 3485 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 3486 }
sPymbed 0:c4152c628df5 3487
sPymbed 0:c4152c628df5 3488 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3489 ret = ChannelUpdate(channel, peerChannelId,
sPymbed 0:c4152c628df5 3490 peerInitialWindowSz, peerMaxPacketSz);
sPymbed 0:c4152c628df5 3491
sPymbed 0:c4152c628df5 3492 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3493 ssh->serverState = SERVER_CHANNEL_OPEN_DONE;
sPymbed 0:c4152c628df5 3494
sPymbed 0:c4152c628df5 3495 WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpenConf(), ret = %d", ret);
sPymbed 0:c4152c628df5 3496 return ret;
sPymbed 0:c4152c628df5 3497 }
sPymbed 0:c4152c628df5 3498
sPymbed 0:c4152c628df5 3499
sPymbed 0:c4152c628df5 3500 static int DoChannelOpenFail(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3501 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3502 {
sPymbed 0:c4152c628df5 3503 char desc[80];
sPymbed 0:c4152c628df5 3504 word32 begin, channelId, reasonId, descSz, langSz;
sPymbed 0:c4152c628df5 3505 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3506
sPymbed 0:c4152c628df5 3507 WLOG(WS_LOG_DEBUG, "Entering DoChannelOpenFail()");
sPymbed 0:c4152c628df5 3508
sPymbed 0:c4152c628df5 3509 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3510 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3511
sPymbed 0:c4152c628df5 3512 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3513 begin = *idx;
sPymbed 0:c4152c628df5 3514 ret = GetUint32(&channelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3515 }
sPymbed 0:c4152c628df5 3516
sPymbed 0:c4152c628df5 3517 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3518 ret = GetUint32(&reasonId, buf, len, &begin);
sPymbed 0:c4152c628df5 3519
sPymbed 0:c4152c628df5 3520 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3521 descSz = sizeof(desc);
sPymbed 0:c4152c628df5 3522 ret = GetString(desc, &descSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3523 }
sPymbed 0:c4152c628df5 3524
sPymbed 0:c4152c628df5 3525 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3526 ret = GetUint32(&langSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3527
sPymbed 0:c4152c628df5 3528 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3529 *idx = begin + langSz;
sPymbed 0:c4152c628df5 3530
sPymbed 0:c4152c628df5 3531 WLOG(WS_LOG_INFO, "channel open failure reason code: %u", reasonId);
sPymbed 0:c4152c628df5 3532 if (descSz > 0) {
sPymbed 0:c4152c628df5 3533 WLOG(WS_LOG_INFO, "description: %s", desc);
sPymbed 0:c4152c628df5 3534 }
sPymbed 0:c4152c628df5 3535
sPymbed 0:c4152c628df5 3536 ret = ChannelRemove(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 3537 }
sPymbed 0:c4152c628df5 3538
sPymbed 0:c4152c628df5 3539 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3540 ret = WS_CHANOPEN_FAILED;
sPymbed 0:c4152c628df5 3541
sPymbed 0:c4152c628df5 3542 WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpenFail(), ret = %d", ret);
sPymbed 0:c4152c628df5 3543 return ret;
sPymbed 0:c4152c628df5 3544 }
sPymbed 0:c4152c628df5 3545
sPymbed 0:c4152c628df5 3546
sPymbed 0:c4152c628df5 3547 static int DoChannelClose(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3548 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3549 {
sPymbed 0:c4152c628df5 3550 WOLFSSH_CHANNEL* channel = NULL;
sPymbed 0:c4152c628df5 3551 word32 begin = *idx;
sPymbed 0:c4152c628df5 3552 word32 channelId;
sPymbed 0:c4152c628df5 3553 int ret;
sPymbed 0:c4152c628df5 3554
sPymbed 0:c4152c628df5 3555 WLOG(WS_LOG_DEBUG, "Entering DoChannelClose()");
sPymbed 0:c4152c628df5 3556
sPymbed 0:c4152c628df5 3557 ret = GetUint32(&channelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3558
sPymbed 0:c4152c628df5 3559 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3560 *idx = begin;
sPymbed 0:c4152c628df5 3561
sPymbed 0:c4152c628df5 3562 channel = ChannelFind(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 3563 if (channel == NULL)
sPymbed 0:c4152c628df5 3564 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 3565 }
sPymbed 0:c4152c628df5 3566
sPymbed 0:c4152c628df5 3567 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3568 ret = SendChannelClose(ssh, channelId);
sPymbed 0:c4152c628df5 3569
sPymbed 0:c4152c628df5 3570 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3571 ret = ChannelRemove(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 3572
sPymbed 0:c4152c628df5 3573 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3574 ret = WS_CHANNEL_CLOSED;
sPymbed 0:c4152c628df5 3575
sPymbed 0:c4152c628df5 3576 WLOG(WS_LOG_DEBUG, "Leaving DoChannelClose(), ret = %d", ret);
sPymbed 0:c4152c628df5 3577 return ret;
sPymbed 0:c4152c628df5 3578 }
sPymbed 0:c4152c628df5 3579
sPymbed 0:c4152c628df5 3580
sPymbed 0:c4152c628df5 3581 static int DoChannelRequest(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3582 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3583 {
sPymbed 0:c4152c628df5 3584 word32 begin = *idx;
sPymbed 0:c4152c628df5 3585 word32 channelId;
sPymbed 0:c4152c628df5 3586 word32 typeSz;
sPymbed 0:c4152c628df5 3587 char type[32];
sPymbed 0:c4152c628df5 3588 byte wantReply;
sPymbed 0:c4152c628df5 3589 int ret;
sPymbed 0:c4152c628df5 3590
sPymbed 0:c4152c628df5 3591 WLOG(WS_LOG_DEBUG, "Entering DoChannelRequest()");
sPymbed 0:c4152c628df5 3592
sPymbed 0:c4152c628df5 3593 ret = GetUint32(&channelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3594
sPymbed 0:c4152c628df5 3595 typeSz = sizeof(type);
sPymbed 0:c4152c628df5 3596 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3597 ret = GetString(type, &typeSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3598
sPymbed 0:c4152c628df5 3599 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3600 ret = GetBoolean(&wantReply, buf, len, &begin);
sPymbed 0:c4152c628df5 3601
sPymbed 0:c4152c628df5 3602 if (ret != WS_SUCCESS) {
sPymbed 0:c4152c628df5 3603 WLOG(WS_LOG_DEBUG, "Leaving DoChannelRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 3604 return ret;
sPymbed 0:c4152c628df5 3605 }
sPymbed 0:c4152c628df5 3606
sPymbed 0:c4152c628df5 3607 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3608 WLOG(WS_LOG_DEBUG, " channelId = %u", channelId);
sPymbed 0:c4152c628df5 3609 WLOG(WS_LOG_DEBUG, " type = %s", type);
sPymbed 0:c4152c628df5 3610 WLOG(WS_LOG_DEBUG, " wantReply = %u", wantReply);
sPymbed 0:c4152c628df5 3611
sPymbed 0:c4152c628df5 3612 if (WSTRNCMP(type, "pty-req", typeSz) == 0) {
sPymbed 0:c4152c628df5 3613 char term[32];
sPymbed 0:c4152c628df5 3614 word32 termSz;
sPymbed 0:c4152c628df5 3615 word32 widthChar, heightRows, widthPixels, heightPixels;
sPymbed 0:c4152c628df5 3616 word32 modesSz;
sPymbed 0:c4152c628df5 3617
sPymbed 0:c4152c628df5 3618 termSz = sizeof(term);
sPymbed 0:c4152c628df5 3619 ret = GetString(term, &termSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3620 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3621 ret = GetUint32(&widthChar, buf, len, &begin);
sPymbed 0:c4152c628df5 3622 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3623 ret = GetUint32(&heightRows, buf, len, &begin);
sPymbed 0:c4152c628df5 3624 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3625 ret = GetUint32(&widthPixels, buf, len, &begin);
sPymbed 0:c4152c628df5 3626 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3627 ret = GetUint32(&heightPixels, buf, len, &begin);
sPymbed 0:c4152c628df5 3628 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3629 ret = GetUint32(&modesSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3630
sPymbed 0:c4152c628df5 3631 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3632 WLOG(WS_LOG_DEBUG, " term = %s", term);
sPymbed 0:c4152c628df5 3633 WLOG(WS_LOG_DEBUG, " widthChar = %u", widthChar);
sPymbed 0:c4152c628df5 3634 WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows);
sPymbed 0:c4152c628df5 3635 WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels);
sPymbed 0:c4152c628df5 3636 WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels);
sPymbed 0:c4152c628df5 3637 WLOG(WS_LOG_DEBUG, " modes = %u", (modesSz - 1) / 5);
sPymbed 0:c4152c628df5 3638 }
sPymbed 0:c4152c628df5 3639 }
sPymbed 0:c4152c628df5 3640 else if (WSTRNCMP(type, "env", typeSz) == 0) {
sPymbed 0:c4152c628df5 3641 char name[32];
sPymbed 0:c4152c628df5 3642 word32 nameSz;
sPymbed 0:c4152c628df5 3643 char value[32];
sPymbed 0:c4152c628df5 3644 word32 valueSz;
sPymbed 0:c4152c628df5 3645
sPymbed 0:c4152c628df5 3646 nameSz = sizeof(name);
sPymbed 0:c4152c628df5 3647 valueSz = sizeof(value);
sPymbed 0:c4152c628df5 3648 ret = GetString(name, &nameSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3649 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3650 ret = GetString(value, &valueSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3651
sPymbed 0:c4152c628df5 3652 WLOG(WS_LOG_DEBUG, " %s = %s", name, value);
sPymbed 0:c4152c628df5 3653 }
sPymbed 0:c4152c628df5 3654 }
sPymbed 0:c4152c628df5 3655
sPymbed 0:c4152c628df5 3656 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3657 *idx = len;
sPymbed 0:c4152c628df5 3658
sPymbed 0:c4152c628df5 3659 if (wantReply) {
sPymbed 0:c4152c628df5 3660 int replyRet;
sPymbed 0:c4152c628df5 3661
sPymbed 0:c4152c628df5 3662 replyRet = SendChannelSuccess(ssh, channelId, (ret == WS_SUCCESS));
sPymbed 0:c4152c628df5 3663 if (replyRet != WS_SUCCESS)
sPymbed 0:c4152c628df5 3664 ret = replyRet;
sPymbed 0:c4152c628df5 3665 }
sPymbed 0:c4152c628df5 3666
sPymbed 0:c4152c628df5 3667 WLOG(WS_LOG_DEBUG, "Leaving DoChannelRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 3668 return ret;
sPymbed 0:c4152c628df5 3669 }
sPymbed 0:c4152c628df5 3670
sPymbed 0:c4152c628df5 3671
sPymbed 0:c4152c628df5 3672 static int DoChannelSuccess(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3673 {
sPymbed 0:c4152c628df5 3674 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3675
sPymbed 0:c4152c628df5 3676 WLOG(WS_LOG_DEBUG, "Entering DoChannelSuccess()");
sPymbed 0:c4152c628df5 3677
sPymbed 0:c4152c628df5 3678 if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
sPymbed 0:c4152c628df5 3679 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3680
sPymbed 0:c4152c628df5 3681 ssh->serverState = SERVER_DONE;
sPymbed 0:c4152c628df5 3682
sPymbed 0:c4152c628df5 3683 WLOG(WS_LOG_DEBUG, "Leaving DoChannelSuccess(), ret = %d", ret);
sPymbed 0:c4152c628df5 3684 return ret;
sPymbed 0:c4152c628df5 3685 }
sPymbed 0:c4152c628df5 3686
sPymbed 0:c4152c628df5 3687
sPymbed 0:c4152c628df5 3688 static int DoChannelFailure(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3689 {
sPymbed 0:c4152c628df5 3690 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3691
sPymbed 0:c4152c628df5 3692 WLOG(WS_LOG_DEBUG, "Entering DoChannelFailure()");
sPymbed 0:c4152c628df5 3693
sPymbed 0:c4152c628df5 3694 if (ssh == NULL || buf == NULL || len != 0 || idx == NULL)
sPymbed 0:c4152c628df5 3695 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 3696
sPymbed 0:c4152c628df5 3697 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3698 ret = WS_CHANOPEN_FAILED;
sPymbed 0:c4152c628df5 3699 WLOG(WS_LOG_DEBUG, "Leaving DoChannelFailure(), ret = %d", ret);
sPymbed 0:c4152c628df5 3700 return ret;
sPymbed 0:c4152c628df5 3701 }
sPymbed 0:c4152c628df5 3702
sPymbed 0:c4152c628df5 3703
sPymbed 0:c4152c628df5 3704 static int DoChannelWindowAdjust(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3705 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3706 {
sPymbed 0:c4152c628df5 3707 WOLFSSH_CHANNEL* channel = NULL;
sPymbed 0:c4152c628df5 3708 word32 begin = *idx;
sPymbed 0:c4152c628df5 3709 word32 channelId, bytesToAdd;
sPymbed 0:c4152c628df5 3710 int ret;
sPymbed 0:c4152c628df5 3711
sPymbed 0:c4152c628df5 3712 WLOG(WS_LOG_DEBUG, "Entering DoChannelWindowAdjust()");
sPymbed 0:c4152c628df5 3713
sPymbed 0:c4152c628df5 3714 ret = GetUint32(&channelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3715 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3716 ret = GetUint32(&bytesToAdd, buf, len, &begin);
sPymbed 0:c4152c628df5 3717
sPymbed 0:c4152c628df5 3718 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3719 *idx = begin;
sPymbed 0:c4152c628df5 3720
sPymbed 0:c4152c628df5 3721 channel = ChannelFind(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 3722 if (channel == NULL)
sPymbed 0:c4152c628df5 3723 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 3724 else {
sPymbed 0:c4152c628df5 3725 WLOG(WS_LOG_INFO, " channelId = %u", channelId);
sPymbed 0:c4152c628df5 3726 WLOG(WS_LOG_INFO, " bytesToAdd = %u", bytesToAdd);
sPymbed 0:c4152c628df5 3727 WLOG(WS_LOG_INFO, " peerWindowSz = %u",
sPymbed 0:c4152c628df5 3728 channel->peerWindowSz);
sPymbed 0:c4152c628df5 3729
sPymbed 0:c4152c628df5 3730 channel->peerWindowSz += bytesToAdd;
sPymbed 0:c4152c628df5 3731
sPymbed 0:c4152c628df5 3732 WLOG(WS_LOG_INFO, " update peerWindowSz = %u",
sPymbed 0:c4152c628df5 3733 channel->peerWindowSz);
sPymbed 0:c4152c628df5 3734
sPymbed 0:c4152c628df5 3735 }
sPymbed 0:c4152c628df5 3736 }
sPymbed 0:c4152c628df5 3737
sPymbed 0:c4152c628df5 3738 WLOG(WS_LOG_DEBUG, "Leaving DoChannelWindowAdjust(), ret = %d", ret);
sPymbed 0:c4152c628df5 3739 return ret;
sPymbed 0:c4152c628df5 3740 }
sPymbed 0:c4152c628df5 3741
sPymbed 0:c4152c628df5 3742
sPymbed 0:c4152c628df5 3743 static int DoChannelData(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 3744 byte* buf, word32 len, word32* idx)
sPymbed 0:c4152c628df5 3745 {
sPymbed 0:c4152c628df5 3746 WOLFSSH_CHANNEL* channel = NULL;
sPymbed 0:c4152c628df5 3747 word32 begin = *idx;
sPymbed 0:c4152c628df5 3748 word32 dataSz = 0;
sPymbed 0:c4152c628df5 3749 word32 channelId;
sPymbed 0:c4152c628df5 3750 int ret;
sPymbed 0:c4152c628df5 3751
sPymbed 0:c4152c628df5 3752 WLOG(WS_LOG_DEBUG, "Entering DoChannelData()");
sPymbed 0:c4152c628df5 3753
sPymbed 0:c4152c628df5 3754 ret = GetUint32(&channelId, buf, len, &begin);
sPymbed 0:c4152c628df5 3755 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 3756 ret = GetUint32(&dataSz, buf, len, &begin);
sPymbed 0:c4152c628df5 3757
sPymbed 0:c4152c628df5 3758 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3759 *idx = begin + dataSz;
sPymbed 0:c4152c628df5 3760
sPymbed 0:c4152c628df5 3761 channel = ChannelFind(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 3762 if (channel == NULL)
sPymbed 0:c4152c628df5 3763 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 3764 else
sPymbed 0:c4152c628df5 3765 ret = ChannelPutData(channel, buf + begin, dataSz);
sPymbed 0:c4152c628df5 3766 }
sPymbed 0:c4152c628df5 3767
sPymbed 0:c4152c628df5 3768 WLOG(WS_LOG_DEBUG, "Leaving DoChannelData(), ret = %d", ret);
sPymbed 0:c4152c628df5 3769 return ret;
sPymbed 0:c4152c628df5 3770 }
sPymbed 0:c4152c628df5 3771
sPymbed 0:c4152c628df5 3772
sPymbed 0:c4152c628df5 3773 static int DoPacket(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 3774 {
sPymbed 0:c4152c628df5 3775 byte* buf = (byte*)ssh->inputBuffer.buffer;
sPymbed 0:c4152c628df5 3776 word32 idx = ssh->inputBuffer.idx;
sPymbed 0:c4152c628df5 3777 word32 len = ssh->inputBuffer.length;
sPymbed 0:c4152c628df5 3778 word32 payloadSz;
sPymbed 0:c4152c628df5 3779 byte padSz;
sPymbed 0:c4152c628df5 3780 byte msg;
sPymbed 0:c4152c628df5 3781 word32 payloadIdx = 0;
sPymbed 0:c4152c628df5 3782 int ret;
sPymbed 0:c4152c628df5 3783
sPymbed 0:c4152c628df5 3784 //ESP_LOGI("WOLFSSH", "DoPacket sequence number: %d", ssh->peerSeq);
sPymbed 0:c4152c628df5 3785 WLOG(WS_LOG_DEBUG, "DoPacket sequence number: %d", ssh->peerSeq);
sPymbed 0:c4152c628df5 3786
sPymbed 0:c4152c628df5 3787 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 3788 padSz = buf[idx++];
sPymbed 0:c4152c628df5 3789 payloadSz = ssh->curSz - PAD_LENGTH_SZ - padSz - MSG_ID_SZ;
sPymbed 0:c4152c628df5 3790
sPymbed 0:c4152c628df5 3791 msg = buf[idx++];
sPymbed 0:c4152c628df5 3792 /* At this point, payload starts at "buf + idx". */
sPymbed 0:c4152c628df5 3793
sPymbed 0:c4152c628df5 3794 switch (msg) {
sPymbed 0:c4152c628df5 3795
sPymbed 0:c4152c628df5 3796 case MSGID_DISCONNECT:
sPymbed 0:c4152c628df5 3797 //ESP_LOGI("WOLFSSH", "Decoding MSGID_DISCONNECT");
sPymbed 0:c4152c628df5 3798 WLOG(WS_LOG_DEBUG, "Decoding MSGID_DISCONNECT");
sPymbed 0:c4152c628df5 3799 ret = DoDisconnect(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3800 break;
sPymbed 0:c4152c628df5 3801
sPymbed 0:c4152c628df5 3802 case MSGID_IGNORE:
sPymbed 0:c4152c628df5 3803 //ESP_LOGI("WOLFSSH", "Decoding MSGID_IGNORE");
sPymbed 0:c4152c628df5 3804 WLOG(WS_LOG_DEBUG, "Decoding MSGID_IGNORE");
sPymbed 0:c4152c628df5 3805 ret = DoIgnore(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3806 break;
sPymbed 0:c4152c628df5 3807
sPymbed 0:c4152c628df5 3808 case MSGID_UNIMPLEMENTED:
sPymbed 0:c4152c628df5 3809 //ESP_LOGI("WOLFSSH", "Decoding MSGID_UNIMPLEMENTED");
sPymbed 0:c4152c628df5 3810 WLOG(WS_LOG_DEBUG, "Decoding MSGID_UNIMPLEMENTED");
sPymbed 0:c4152c628df5 3811 ret = DoUnimplemented(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3812 break;
sPymbed 0:c4152c628df5 3813
sPymbed 0:c4152c628df5 3814 case MSGID_DEBUG:
sPymbed 0:c4152c628df5 3815 //ESP_LOGI("WOLFSSH", "Decoding MSGID_DEBUG");
sPymbed 0:c4152c628df5 3816 WLOG(WS_LOG_DEBUG, "Decoding MSGID_DEBUG");
sPymbed 0:c4152c628df5 3817 ret = DoDebug(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3818 break;
sPymbed 0:c4152c628df5 3819
sPymbed 0:c4152c628df5 3820 case MSGID_KEXINIT:
sPymbed 0:c4152c628df5 3821 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXINIT");
sPymbed 0:c4152c628df5 3822 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXINIT");
sPymbed 0:c4152c628df5 3823 ret = DoKexInit(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3824 break;
sPymbed 0:c4152c628df5 3825
sPymbed 0:c4152c628df5 3826 case MSGID_NEWKEYS:
sPymbed 0:c4152c628df5 3827 //ESP_LOGI("WOLFSSH", "Decoding MSGID_NEWKEYS");
sPymbed 0:c4152c628df5 3828 WLOG(WS_LOG_DEBUG, "Decoding MSGID_NEWKEYS");
sPymbed 0:c4152c628df5 3829 ret = DoNewKeys(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3830 break;
sPymbed 0:c4152c628df5 3831
sPymbed 0:c4152c628df5 3832 case MSGID_KEXDH_INIT:
sPymbed 0:c4152c628df5 3833 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXDH_INIT");
sPymbed 0:c4152c628df5 3834 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT");
sPymbed 0:c4152c628df5 3835 ret = DoKexDhInit(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3836 break;
sPymbed 0:c4152c628df5 3837
sPymbed 0:c4152c628df5 3838 case MSGID_KEXDH_REPLY:
sPymbed 0:c4152c628df5 3839 if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {
sPymbed 0:c4152c628df5 3840 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXDH_GEX_GROUP");
sPymbed 0:c4152c628df5 3841 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_GEX_GROUP");
sPymbed 0:c4152c628df5 3842 ret = DoKexDhGexGroup(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3843 }
sPymbed 0:c4152c628df5 3844 else {
sPymbed 0:c4152c628df5 3845 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXDH_REPLY");
sPymbed 0:c4152c628df5 3846 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_REPLY");
sPymbed 0:c4152c628df5 3847 ret = DoKexDhReply(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3848 }
sPymbed 0:c4152c628df5 3849 break;
sPymbed 0:c4152c628df5 3850
sPymbed 0:c4152c628df5 3851 case MSGID_KEXDH_GEX_REQUEST:
sPymbed 0:c4152c628df5 3852 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXDH_GEX_REQUEST");
sPymbed 0:c4152c628df5 3853 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_GEX_REQUEST");
sPymbed 0:c4152c628df5 3854 ret = DoKexDhGexRequest(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3855 break;
sPymbed 0:c4152c628df5 3856
sPymbed 0:c4152c628df5 3857 case MSGID_KEXDH_GEX_INIT:
sPymbed 0:c4152c628df5 3858 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXDH_GEX_INIT");
sPymbed 0:c4152c628df5 3859 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_GEX_INIT");
sPymbed 0:c4152c628df5 3860 ret = DoKexDhInit(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3861 break;
sPymbed 0:c4152c628df5 3862
sPymbed 0:c4152c628df5 3863 case MSGID_KEXDH_GEX_REPLY:
sPymbed 0:c4152c628df5 3864 //ESP_LOGI("WOLFSSH", "Decoding MSGID_KEXDH_GEX_INIT");
sPymbed 0:c4152c628df5 3865 WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_GEX_INIT");
sPymbed 0:c4152c628df5 3866 ret = DoKexDhReply(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3867 break;
sPymbed 0:c4152c628df5 3868
sPymbed 0:c4152c628df5 3869 case MSGID_SERVICE_REQUEST:
sPymbed 0:c4152c628df5 3870 //ESP_LOGI("WOLFSSH", "Decoding MSGID_SERVICE_REQUEST");
sPymbed 0:c4152c628df5 3871 WLOG(WS_LOG_DEBUG, "Decoding MSGID_SERVICE_REQUEST");
sPymbed 0:c4152c628df5 3872 ret = DoServiceRequest(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3873 break;
sPymbed 0:c4152c628df5 3874
sPymbed 0:c4152c628df5 3875 case MSGID_SERVICE_ACCEPT:
sPymbed 0:c4152c628df5 3876 //ESP_LOGI("WOLFSSH", "Decoding MSGID_SERVER_ACCEPT");
sPymbed 0:c4152c628df5 3877 WLOG(WS_LOG_DEBUG, "Decoding MSGID_SERVER_ACCEPT");
sPymbed 0:c4152c628df5 3878 ret = DoServiceAccept(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3879 break;
sPymbed 0:c4152c628df5 3880
sPymbed 0:c4152c628df5 3881 case MSGID_USERAUTH_REQUEST:
sPymbed 0:c4152c628df5 3882 //ESP_LOGI("WOLFSSH", "Decoding MSGID_USERAUTH_REQUEST");
sPymbed 0:c4152c628df5 3883 WLOG(WS_LOG_DEBUG, "Decoding MSGID_USERAUTH_REQUEST");
sPymbed 0:c4152c628df5 3884 ret = DoUserAuthRequest(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3885 break;
sPymbed 0:c4152c628df5 3886
sPymbed 0:c4152c628df5 3887 case MSGID_USERAUTH_FAILURE:
sPymbed 0:c4152c628df5 3888 //ESP_LOGI("WOLFSSH", "Decoding MSGID_USERAUTH_FAILURE");
sPymbed 0:c4152c628df5 3889 WLOG(WS_LOG_DEBUG, "Decoding MSGID_USERAUTH_FAILURE");
sPymbed 0:c4152c628df5 3890 ret = DoUserAuthFailure(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3891 break;
sPymbed 0:c4152c628df5 3892
sPymbed 0:c4152c628df5 3893 case MSGID_USERAUTH_SUCCESS:
sPymbed 0:c4152c628df5 3894 //ESP_LOGI("WOLFSSH", "Decoding MSGID_USERAUTH_SUCCESS");
sPymbed 0:c4152c628df5 3895 WLOG(WS_LOG_DEBUG, "Decoding MSGID_USERAUTH_SUCCESS");
sPymbed 0:c4152c628df5 3896 ret = DoUserAuthSuccess(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3897 break;
sPymbed 0:c4152c628df5 3898
sPymbed 0:c4152c628df5 3899 case MSGID_USERAUTH_BANNER:
sPymbed 0:c4152c628df5 3900 //ESP_LOGI("WOLFSSH", "Decoding MSGID_USERAUTH_BANNER");
sPymbed 0:c4152c628df5 3901 WLOG(WS_LOG_DEBUG, "Decoding MSGID_USERAUTH_BANNER");
sPymbed 0:c4152c628df5 3902 ret = DoUserAuthBanner(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3903 break;
sPymbed 0:c4152c628df5 3904
sPymbed 0:c4152c628df5 3905 case MSGID_GLOBAL_REQUEST:
sPymbed 0:c4152c628df5 3906 //ESP_LOGI("WOLFSSH", "Decoding MSGID_GLOBAL_REQUEST");
sPymbed 0:c4152c628df5 3907 WLOG(WS_LOG_DEBUG, "Decoding MSGID_GLOBAL_REQUEST");
sPymbed 0:c4152c628df5 3908 ret = DoGlobalRequest(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3909 break;
sPymbed 0:c4152c628df5 3910
sPymbed 0:c4152c628df5 3911 case MSGID_CHANNEL_OPEN:
sPymbed 0:c4152c628df5 3912 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_OPEN");
sPymbed 0:c4152c628df5 3913 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_OPEN");
sPymbed 0:c4152c628df5 3914 ret = DoChannelOpen(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3915 break;
sPymbed 0:c4152c628df5 3916
sPymbed 0:c4152c628df5 3917 case MSGID_CHANNEL_OPEN_CONF:
sPymbed 0:c4152c628df5 3918 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_OPEN_CONF");
sPymbed 0:c4152c628df5 3919 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_OPEN_CONF");
sPymbed 0:c4152c628df5 3920 ret = DoChannelOpenConf(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3921 break;
sPymbed 0:c4152c628df5 3922
sPymbed 0:c4152c628df5 3923 case MSGID_CHANNEL_OPEN_FAIL:
sPymbed 0:c4152c628df5 3924 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_OPEN_FAIL");
sPymbed 0:c4152c628df5 3925 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_OPEN_FAIL");
sPymbed 0:c4152c628df5 3926 ret = DoChannelOpenFail(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3927 break;
sPymbed 0:c4152c628df5 3928
sPymbed 0:c4152c628df5 3929 case MSGID_CHANNEL_WINDOW_ADJUST:
sPymbed 0:c4152c628df5 3930 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_WINDOW_ADJUST");
sPymbed 0:c4152c628df5 3931 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_WINDOW_ADJUST");
sPymbed 0:c4152c628df5 3932 ret = DoChannelWindowAdjust(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3933 break;
sPymbed 0:c4152c628df5 3934
sPymbed 0:c4152c628df5 3935 case MSGID_CHANNEL_DATA:
sPymbed 0:c4152c628df5 3936 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_DATA");
sPymbed 0:c4152c628df5 3937 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_DATA");
sPymbed 0:c4152c628df5 3938 ret = DoChannelData(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3939 break;
sPymbed 0:c4152c628df5 3940
sPymbed 0:c4152c628df5 3941 case MSGID_CHANNEL_EOF:
sPymbed 0:c4152c628df5 3942 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_EOF");
sPymbed 0:c4152c628df5 3943 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_EOF");
sPymbed 0:c4152c628df5 3944 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 3945 break;
sPymbed 0:c4152c628df5 3946
sPymbed 0:c4152c628df5 3947 case MSGID_CHANNEL_CLOSE:
sPymbed 0:c4152c628df5 3948 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_CLOSE");
sPymbed 0:c4152c628df5 3949 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_CLOSE");
sPymbed 0:c4152c628df5 3950 ret = DoChannelClose(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3951 break;
sPymbed 0:c4152c628df5 3952
sPymbed 0:c4152c628df5 3953 case MSGID_CHANNEL_REQUEST:
sPymbed 0:c4152c628df5 3954 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_REQUEST");
sPymbed 0:c4152c628df5 3955 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_REQUEST");
sPymbed 0:c4152c628df5 3956 ret = DoChannelRequest(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3957 break;
sPymbed 0:c4152c628df5 3958
sPymbed 0:c4152c628df5 3959 case MSGID_CHANNEL_SUCCESS:
sPymbed 0:c4152c628df5 3960 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_SUCCESS");
sPymbed 0:c4152c628df5 3961 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_SUCCESS");
sPymbed 0:c4152c628df5 3962 ret = DoChannelSuccess(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3963 break;
sPymbed 0:c4152c628df5 3964
sPymbed 0:c4152c628df5 3965 case MSGID_CHANNEL_FAILURE:
sPymbed 0:c4152c628df5 3966 //ESP_LOGI("WOLFSSH", "Decoding MSGID_CHANNEL_FAILURE");
sPymbed 0:c4152c628df5 3967 WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_FAILURE");
sPymbed 0:c4152c628df5 3968 ret = DoChannelFailure(ssh, buf + idx, payloadSz, &payloadIdx);
sPymbed 0:c4152c628df5 3969 break;
sPymbed 0:c4152c628df5 3970
sPymbed 0:c4152c628df5 3971 default:
sPymbed 0:c4152c628df5 3972 //ESP_LOGI("WOLFSSH", "Unimplemented message ID (%d)", msg);
sPymbed 0:c4152c628df5 3973 WLOG(WS_LOG_DEBUG, "Unimplemented message ID (%d)", msg);
sPymbed 0:c4152c628df5 3974 #ifdef SHOW_UNIMPLEMENTED
sPymbed 0:c4152c628df5 3975 DumpOctetString(buf + idx, payloadSz);
sPymbed 0:c4152c628df5 3976 #endif
sPymbed 0:c4152c628df5 3977 ret = SendUnimplemented(ssh);
sPymbed 0:c4152c628df5 3978 }
sPymbed 0:c4152c628df5 3979
sPymbed 0:c4152c628df5 3980 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3981 idx += payloadIdx;
sPymbed 0:c4152c628df5 3982
sPymbed 0:c4152c628df5 3983 if (idx + padSz > len) {
sPymbed 0:c4152c628df5 3984 WLOG(WS_LOG_DEBUG, "Not enough data in buffer for pad.");
sPymbed 0:c4152c628df5 3985 ret = WS_BUFFER_E;
sPymbed 0:c4152c628df5 3986 }
sPymbed 0:c4152c628df5 3987 }
sPymbed 0:c4152c628df5 3988
sPymbed 0:c4152c628df5 3989 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 3990 idx += padSz;
sPymbed 0:c4152c628df5 3991 ssh->inputBuffer.idx = idx;
sPymbed 0:c4152c628df5 3992 ssh->peerSeq++;
sPymbed 0:c4152c628df5 3993 }
sPymbed 0:c4152c628df5 3994
sPymbed 0:c4152c628df5 3995 return ret;
sPymbed 0:c4152c628df5 3996 }
sPymbed 0:c4152c628df5 3997
sPymbed 0:c4152c628df5 3998
sPymbed 0:c4152c628df5 3999 static INLINE int Encrypt(WOLFSSH* ssh, byte* cipher, const byte* input,
sPymbed 0:c4152c628df5 4000 word16 sz)
sPymbed 0:c4152c628df5 4001 {
sPymbed 0:c4152c628df5 4002 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4003
sPymbed 0:c4152c628df5 4004 if (ssh == NULL || cipher == NULL || input == NULL || sz == 0)
sPymbed 0:c4152c628df5 4005 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4006
sPymbed 0:c4152c628df5 4007 WLOG(WS_LOG_DEBUG, "Encrypt %s", IdToName(ssh->encryptId));
sPymbed 0:c4152c628df5 4008
sPymbed 0:c4152c628df5 4009 switch (ssh->encryptId) {
sPymbed 0:c4152c628df5 4010 case ID_NONE:
sPymbed 0:c4152c628df5 4011 break;
sPymbed 0:c4152c628df5 4012
sPymbed 0:c4152c628df5 4013 case ID_AES128_CBC:
sPymbed 0:c4152c628df5 4014 if (wc_AesCbcEncrypt(&ssh->encryptCipher.aes,
sPymbed 0:c4152c628df5 4015 cipher, input, sz) < 0) {
sPymbed 0:c4152c628df5 4016
sPymbed 0:c4152c628df5 4017 ret = WS_ENCRYPT_E;
sPymbed 0:c4152c628df5 4018 }
sPymbed 0:c4152c628df5 4019 break;
sPymbed 0:c4152c628df5 4020
sPymbed 0:c4152c628df5 4021 default:
sPymbed 0:c4152c628df5 4022 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 4023 }
sPymbed 0:c4152c628df5 4024
sPymbed 0:c4152c628df5 4025 ssh->txCount += sz;
sPymbed 0:c4152c628df5 4026
sPymbed 0:c4152c628df5 4027 return ret;
sPymbed 0:c4152c628df5 4028 }
sPymbed 0:c4152c628df5 4029
sPymbed 0:c4152c628df5 4030
sPymbed 0:c4152c628df5 4031 static INLINE int Decrypt(WOLFSSH* ssh, byte* plain, const byte* input,
sPymbed 0:c4152c628df5 4032 word16 sz)
sPymbed 0:c4152c628df5 4033 {
sPymbed 0:c4152c628df5 4034 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4035
sPymbed 0:c4152c628df5 4036 if (ssh == NULL || plain == NULL || input == NULL || sz == 0)
sPymbed 0:c4152c628df5 4037 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4038
sPymbed 0:c4152c628df5 4039 WLOG(WS_LOG_DEBUG, "Decrypt %s", IdToName(ssh->peerEncryptId));
sPymbed 0:c4152c628df5 4040
sPymbed 0:c4152c628df5 4041 switch (ssh->peerEncryptId) {
sPymbed 0:c4152c628df5 4042 case ID_NONE:
sPymbed 0:c4152c628df5 4043 break;
sPymbed 0:c4152c628df5 4044
sPymbed 0:c4152c628df5 4045 case ID_AES128_CBC:
sPymbed 0:c4152c628df5 4046 if (wc_AesCbcDecrypt(&ssh->decryptCipher.aes,
sPymbed 0:c4152c628df5 4047 plain, input, sz) < 0) {
sPymbed 0:c4152c628df5 4048
sPymbed 0:c4152c628df5 4049 ret = WS_DECRYPT_E;
sPymbed 0:c4152c628df5 4050 }
sPymbed 0:c4152c628df5 4051 break;
sPymbed 0:c4152c628df5 4052
sPymbed 0:c4152c628df5 4053 default:
sPymbed 0:c4152c628df5 4054 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 4055 }
sPymbed 0:c4152c628df5 4056
sPymbed 0:c4152c628df5 4057 ssh->rxCount += sz;
sPymbed 0:c4152c628df5 4058 HighwaterCheck(ssh, WOLFSSH_HWSIDE_RECEIVE);
sPymbed 0:c4152c628df5 4059
sPymbed 0:c4152c628df5 4060 return ret;
sPymbed 0:c4152c628df5 4061 }
sPymbed 0:c4152c628df5 4062
sPymbed 0:c4152c628df5 4063
sPymbed 0:c4152c628df5 4064 static INLINE int CreateMac(WOLFSSH* ssh, const byte* in, word32 inSz,
sPymbed 0:c4152c628df5 4065 byte* mac)
sPymbed 0:c4152c628df5 4066 {
sPymbed 0:c4152c628df5 4067 byte flatSeq[LENGTH_SZ];
sPymbed 0:c4152c628df5 4068 int ret;
sPymbed 0:c4152c628df5 4069
sPymbed 0:c4152c628df5 4070 c32toa(ssh->seq, flatSeq);
sPymbed 0:c4152c628df5 4071
sPymbed 0:c4152c628df5 4072 WLOG(WS_LOG_DEBUG, "CreateMac %s", IdToName(ssh->macId));
sPymbed 0:c4152c628df5 4073
sPymbed 0:c4152c628df5 4074 /* Need to MAC the sequence number and the unencrypted packet */
sPymbed 0:c4152c628df5 4075 switch (ssh->macId) {
sPymbed 0:c4152c628df5 4076 case ID_NONE:
sPymbed 0:c4152c628df5 4077 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4078 break;
sPymbed 0:c4152c628df5 4079
sPymbed 0:c4152c628df5 4080 case ID_HMAC_SHA1_96:
sPymbed 0:c4152c628df5 4081 {
sPymbed 0:c4152c628df5 4082 Hmac hmac;
sPymbed 0:c4152c628df5 4083 byte digest[SHA_DIGEST_SIZE];
sPymbed 0:c4152c628df5 4084
sPymbed 0:c4152c628df5 4085 ret = wc_HmacSetKey(&hmac, SHA,
sPymbed 0:c4152c628df5 4086 ssh->keys.macKey, ssh->keys.macKeySz);
sPymbed 0:c4152c628df5 4087 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4088 ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
sPymbed 0:c4152c628df5 4089 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4090 ret = wc_HmacUpdate(&hmac, in, inSz);
sPymbed 0:c4152c628df5 4091 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4092 ret = wc_HmacFinal(&hmac, digest);
sPymbed 0:c4152c628df5 4093 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4094 WMEMCPY(mac, digest, SHA1_96_SZ);
sPymbed 0:c4152c628df5 4095 }
sPymbed 0:c4152c628df5 4096 break;
sPymbed 0:c4152c628df5 4097
sPymbed 0:c4152c628df5 4098 case ID_HMAC_SHA1:
sPymbed 0:c4152c628df5 4099 {
sPymbed 0:c4152c628df5 4100 Hmac hmac;
sPymbed 0:c4152c628df5 4101
sPymbed 0:c4152c628df5 4102 ret = wc_HmacSetKey(&hmac, SHA,
sPymbed 0:c4152c628df5 4103 ssh->keys.macKey, ssh->keys.macKeySz);
sPymbed 0:c4152c628df5 4104 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4105 ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
sPymbed 0:c4152c628df5 4106 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4107 ret = wc_HmacUpdate(&hmac, in, inSz);
sPymbed 0:c4152c628df5 4108 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4109 ret = wc_HmacFinal(&hmac, mac);
sPymbed 0:c4152c628df5 4110 }
sPymbed 0:c4152c628df5 4111 break;
sPymbed 0:c4152c628df5 4112
sPymbed 0:c4152c628df5 4113 case ID_HMAC_SHA2_256:
sPymbed 0:c4152c628df5 4114 {
sPymbed 0:c4152c628df5 4115 Hmac hmac;
sPymbed 0:c4152c628df5 4116
sPymbed 0:c4152c628df5 4117 ret = wc_HmacSetKey(&hmac, SHA256,
sPymbed 0:c4152c628df5 4118 ssh->keys.macKey,
sPymbed 0:c4152c628df5 4119 ssh->keys.macKeySz);
sPymbed 0:c4152c628df5 4120 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4121 ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
sPymbed 0:c4152c628df5 4122 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4123 ret = wc_HmacUpdate(&hmac, in, inSz);
sPymbed 0:c4152c628df5 4124 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4125 ret = wc_HmacFinal(&hmac, mac);
sPymbed 0:c4152c628df5 4126 }
sPymbed 0:c4152c628df5 4127 break;
sPymbed 0:c4152c628df5 4128
sPymbed 0:c4152c628df5 4129 default:
sPymbed 0:c4152c628df5 4130 WLOG(WS_LOG_DEBUG, "Invalid Mac ID");
sPymbed 0:c4152c628df5 4131 ret = WS_FATAL_ERROR;
sPymbed 0:c4152c628df5 4132 }
sPymbed 0:c4152c628df5 4133
sPymbed 0:c4152c628df5 4134 return ret;
sPymbed 0:c4152c628df5 4135 }
sPymbed 0:c4152c628df5 4136
sPymbed 0:c4152c628df5 4137
sPymbed 0:c4152c628df5 4138 static INLINE int VerifyMac(WOLFSSH* ssh, const byte* in, word32 inSz,
sPymbed 0:c4152c628df5 4139 const byte* mac)
sPymbed 0:c4152c628df5 4140 {
sPymbed 0:c4152c628df5 4141 int ret;
sPymbed 0:c4152c628df5 4142 byte flatSeq[LENGTH_SZ];
sPymbed 0:c4152c628df5 4143 byte checkMac[MAX_HMAC_SZ];
sPymbed 0:c4152c628df5 4144 Hmac hmac;
sPymbed 0:c4152c628df5 4145
sPymbed 0:c4152c628df5 4146 c32toa(ssh->peerSeq, flatSeq);
sPymbed 0:c4152c628df5 4147
sPymbed 0:c4152c628df5 4148 WLOG(WS_LOG_DEBUG, "VerifyMac %s", IdToName(ssh->peerMacId));
sPymbed 0:c4152c628df5 4149 WLOG(WS_LOG_DEBUG, "VM: inSz = %u", inSz);
sPymbed 0:c4152c628df5 4150 WLOG(WS_LOG_DEBUG, "VM: seq = %u", ssh->peerSeq);
sPymbed 0:c4152c628df5 4151 WLOG(WS_LOG_DEBUG, "VM: keyLen = %u", ssh->peerKeys.macKeySz);
sPymbed 0:c4152c628df5 4152
sPymbed 0:c4152c628df5 4153 WMEMSET(checkMac, 0, sizeof(checkMac));
sPymbed 0:c4152c628df5 4154
sPymbed 0:c4152c628df5 4155 switch (ssh->peerMacId) {
sPymbed 0:c4152c628df5 4156 case ID_NONE:
sPymbed 0:c4152c628df5 4157 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4158 break;
sPymbed 0:c4152c628df5 4159
sPymbed 0:c4152c628df5 4160 case ID_HMAC_SHA1:
sPymbed 0:c4152c628df5 4161 case ID_HMAC_SHA1_96:
sPymbed 0:c4152c628df5 4162 ret = wc_HmacSetKey(&hmac, SHA,
sPymbed 0:c4152c628df5 4163 ssh->peerKeys.macKey, ssh->peerKeys.macKeySz);
sPymbed 0:c4152c628df5 4164 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4165 ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
sPymbed 0:c4152c628df5 4166 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4167 ret = wc_HmacUpdate(&hmac, in, inSz);
sPymbed 0:c4152c628df5 4168 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4169 ret = wc_HmacFinal(&hmac, checkMac);
sPymbed 0:c4152c628df5 4170 if (ConstantCompare(checkMac, mac, ssh->peerMacSz) != 0)
sPymbed 0:c4152c628df5 4171 ret = WS_VERIFY_MAC_E;
sPymbed 0:c4152c628df5 4172 break;
sPymbed 0:c4152c628df5 4173
sPymbed 0:c4152c628df5 4174 case ID_HMAC_SHA2_256:
sPymbed 0:c4152c628df5 4175 ret = wc_HmacSetKey(&hmac, SHA256,
sPymbed 0:c4152c628df5 4176 ssh->peerKeys.macKey, ssh->peerKeys.macKeySz);
sPymbed 0:c4152c628df5 4177 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4178 ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
sPymbed 0:c4152c628df5 4179 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4180 ret = wc_HmacUpdate(&hmac, in, inSz);
sPymbed 0:c4152c628df5 4181 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4182 ret = wc_HmacFinal(&hmac, checkMac);
sPymbed 0:c4152c628df5 4183 if (ConstantCompare(checkMac, mac, ssh->peerMacSz) != 0)
sPymbed 0:c4152c628df5 4184 ret = WS_VERIFY_MAC_E;
sPymbed 0:c4152c628df5 4185 break;
sPymbed 0:c4152c628df5 4186
sPymbed 0:c4152c628df5 4187 default:
sPymbed 0:c4152c628df5 4188 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 4189 }
sPymbed 0:c4152c628df5 4190
sPymbed 0:c4152c628df5 4191 return ret;
sPymbed 0:c4152c628df5 4192 }
sPymbed 0:c4152c628df5 4193
sPymbed 0:c4152c628df5 4194
sPymbed 0:c4152c628df5 4195 static INLINE void AeadIncrementExpIv(byte* iv)
sPymbed 0:c4152c628df5 4196 {
sPymbed 0:c4152c628df5 4197 int i;
sPymbed 0:c4152c628df5 4198
sPymbed 0:c4152c628df5 4199 iv += AEAD_IMP_IV_SZ;
sPymbed 0:c4152c628df5 4200
sPymbed 0:c4152c628df5 4201 for (i = AEAD_EXP_IV_SZ-1; i >= 0; i--) {
sPymbed 0:c4152c628df5 4202 if (++iv[i]) return;
sPymbed 0:c4152c628df5 4203 }
sPymbed 0:c4152c628df5 4204 }
sPymbed 0:c4152c628df5 4205
sPymbed 0:c4152c628df5 4206
sPymbed 0:c4152c628df5 4207 static INLINE int EncryptAead(WOLFSSH* ssh, byte* cipher,
sPymbed 0:c4152c628df5 4208 const byte* input, word16 sz,
sPymbed 0:c4152c628df5 4209 byte* authTag, const byte* auth,
sPymbed 0:c4152c628df5 4210 word16 authSz)
sPymbed 0:c4152c628df5 4211 {
sPymbed 0:c4152c628df5 4212 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4213
sPymbed 0:c4152c628df5 4214 if (ssh == NULL || cipher == NULL || input == NULL || sz == 0 ||
sPymbed 0:c4152c628df5 4215 authTag == NULL || auth == NULL || authSz == 0)
sPymbed 0:c4152c628df5 4216 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4217
sPymbed 0:c4152c628df5 4218 WLOG(WS_LOG_DEBUG, "EncryptAead %s", IdToName(ssh->encryptId));
sPymbed 0:c4152c628df5 4219
sPymbed 0:c4152c628df5 4220 if (ssh->encryptId == ID_AES128_GCM) {
sPymbed 0:c4152c628df5 4221 ret = wc_AesGcmEncrypt(&ssh->encryptCipher.aes, cipher, input, sz,
sPymbed 0:c4152c628df5 4222 ssh->keys.iv, ssh->keys.ivSz,
sPymbed 0:c4152c628df5 4223 authTag, ssh->macSz, auth, authSz);
sPymbed 0:c4152c628df5 4224 }
sPymbed 0:c4152c628df5 4225 else
sPymbed 0:c4152c628df5 4226 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 4227
sPymbed 0:c4152c628df5 4228 AeadIncrementExpIv(ssh->keys.iv);
sPymbed 0:c4152c628df5 4229 ssh->txCount += sz;
sPymbed 0:c4152c628df5 4230
sPymbed 0:c4152c628df5 4231 return ret;
sPymbed 0:c4152c628df5 4232 }
sPymbed 0:c4152c628df5 4233
sPymbed 0:c4152c628df5 4234
sPymbed 0:c4152c628df5 4235 static INLINE int DecryptAead(WOLFSSH* ssh, byte* plain,
sPymbed 0:c4152c628df5 4236 const byte* input, word16 sz,
sPymbed 0:c4152c628df5 4237 const byte* authTag, const byte* auth,
sPymbed 0:c4152c628df5 4238 word16 authSz)
sPymbed 0:c4152c628df5 4239 {
sPymbed 0:c4152c628df5 4240 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4241
sPymbed 0:c4152c628df5 4242 if (ssh == NULL || plain == NULL || input == NULL || sz == 0 ||
sPymbed 0:c4152c628df5 4243 authTag == NULL || auth == NULL || authSz == 0)
sPymbed 0:c4152c628df5 4244 return WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4245
sPymbed 0:c4152c628df5 4246 WLOG(WS_LOG_DEBUG, "DecryptAead %s", IdToName(ssh->peerEncryptId));
sPymbed 0:c4152c628df5 4247
sPymbed 0:c4152c628df5 4248 if (ssh->peerEncryptId == ID_AES128_GCM) {
sPymbed 0:c4152c628df5 4249 ret = wc_AesGcmDecrypt(&ssh->decryptCipher.aes, plain, input, sz,
sPymbed 0:c4152c628df5 4250 ssh->peerKeys.iv, ssh->peerKeys.ivSz,
sPymbed 0:c4152c628df5 4251 authTag, ssh->peerMacSz, auth, authSz);
sPymbed 0:c4152c628df5 4252 }
sPymbed 0:c4152c628df5 4253 else
sPymbed 0:c4152c628df5 4254 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 4255
sPymbed 0:c4152c628df5 4256 AeadIncrementExpIv(ssh->peerKeys.iv);
sPymbed 0:c4152c628df5 4257 ssh->rxCount += sz;
sPymbed 0:c4152c628df5 4258 HighwaterCheck(ssh, WOLFSSH_HWSIDE_RECEIVE);
sPymbed 0:c4152c628df5 4259
sPymbed 0:c4152c628df5 4260 return ret;
sPymbed 0:c4152c628df5 4261 }
sPymbed 0:c4152c628df5 4262
sPymbed 0:c4152c628df5 4263
sPymbed 0:c4152c628df5 4264 int DoReceive(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 4265 {
sPymbed 0:c4152c628df5 4266 int ret = WS_FATAL_ERROR;
sPymbed 0:c4152c628df5 4267 int verifyResult;
sPymbed 0:c4152c628df5 4268 word32 readSz;
sPymbed 0:c4152c628df5 4269 byte peerBlockSz = ssh->peerBlockSz;
sPymbed 0:c4152c628df5 4270 byte peerMacSz = ssh->peerMacSz;
sPymbed 0:c4152c628df5 4271 byte aeadMode = ssh->peerAeadMode;
sPymbed 0:c4152c628df5 4272
sPymbed 0:c4152c628df5 4273 for (;;) {
sPymbed 0:c4152c628df5 4274 switch (ssh->processReplyState) {
sPymbed 0:c4152c628df5 4275 case PROCESS_INIT:
sPymbed 0:c4152c628df5 4276 readSz = peerBlockSz;
sPymbed 0:c4152c628df5 4277 //ESP_LOGI("WOLFSSH", "DoReceive: PROCESS_INT");
sPymbed 0:c4152c628df5 4278 WLOG(WS_LOG_DEBUG, "PR1: size = %u", readSz);
sPymbed 0:c4152c628df5 4279 //ESP_LOGI("WOLFSSH", "PR1: size = %u", readSz);
sPymbed 0:c4152c628df5 4280 if ((ret = GetInputData(ssh, readSz)) < 0) {
sPymbed 0:c4152c628df5 4281 return ret;
sPymbed 0:c4152c628df5 4282 }
sPymbed 0:c4152c628df5 4283 ssh->processReplyState = PROCESS_PACKET_LENGTH;
sPymbed 0:c4152c628df5 4284
sPymbed 0:c4152c628df5 4285 if (!aeadMode) {
sPymbed 0:c4152c628df5 4286 /* Decrypt first block if encrypted */
sPymbed 0:c4152c628df5 4287 ret = Decrypt(ssh,
sPymbed 0:c4152c628df5 4288 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4289 ssh->inputBuffer.idx,
sPymbed 0:c4152c628df5 4290 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4291 ssh->inputBuffer.idx,
sPymbed 0:c4152c628df5 4292 readSz);
sPymbed 0:c4152c628df5 4293 if (ret != WS_SUCCESS) {
sPymbed 0:c4152c628df5 4294 //ESP_LOGI("WOLFSSH", "PR: First decrypt fail");
sPymbed 0:c4152c628df5 4295 WLOG(WS_LOG_DEBUG, "PR: First decrypt fail");
sPymbed 0:c4152c628df5 4296 return ret;
sPymbed 0:c4152c628df5 4297 }
sPymbed 0:c4152c628df5 4298 }
sPymbed 0:c4152c628df5 4299 //ESP_LOGI("WOLFSSH", "DoReceive: PROCESS_INT DONE");
sPymbed 0:c4152c628df5 4300 FALL_THROUGH;
sPymbed 0:c4152c628df5 4301
sPymbed 0:c4152c628df5 4302 case PROCESS_PACKET_LENGTH:
sPymbed 0:c4152c628df5 4303 //ESP_LOGI("WOLFSSH", "DoReceive: PROCESS_PACKET_LENGTH");
sPymbed 0:c4152c628df5 4304 /* Peek at the packet_length field. */
sPymbed 0:c4152c628df5 4305 ato32(ssh->inputBuffer.buffer + ssh->inputBuffer.idx,
sPymbed 0:c4152c628df5 4306 &ssh->curSz);
sPymbed 0:c4152c628df5 4307 ssh->processReplyState = PROCESS_PACKET_FINISH;
sPymbed 0:c4152c628df5 4308 FALL_THROUGH;
sPymbed 0:c4152c628df5 4309
sPymbed 0:c4152c628df5 4310 case PROCESS_PACKET_FINISH:
sPymbed 0:c4152c628df5 4311 //ESP_LOGI("WOLFSSH", "DoReceive: PROCESS_PACKET_FINISH");
sPymbed 0:c4152c628df5 4312 readSz = ssh->curSz + LENGTH_SZ + peerMacSz;
sPymbed 0:c4152c628df5 4313 WLOG(WS_LOG_DEBUG, "PR2: size = %u", readSz);
sPymbed 0:c4152c628df5 4314 if (readSz > 0) {
sPymbed 0:c4152c628df5 4315 if ((ret = GetInputData(ssh, readSz)) < 0) {
sPymbed 0:c4152c628df5 4316 return ret;
sPymbed 0:c4152c628df5 4317 }
sPymbed 0:c4152c628df5 4318
sPymbed 0:c4152c628df5 4319 if (!aeadMode) {
sPymbed 0:c4152c628df5 4320 if (ssh->curSz + LENGTH_SZ - peerBlockSz > 0) {
sPymbed 0:c4152c628df5 4321 ret = Decrypt(ssh,
sPymbed 0:c4152c628df5 4322 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4323 ssh->inputBuffer.idx + peerBlockSz,
sPymbed 0:c4152c628df5 4324 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4325 ssh->inputBuffer.idx + peerBlockSz,
sPymbed 0:c4152c628df5 4326 ssh->curSz + LENGTH_SZ - peerBlockSz);
sPymbed 0:c4152c628df5 4327 }
sPymbed 0:c4152c628df5 4328 else {
sPymbed 0:c4152c628df5 4329 WLOG(WS_LOG_INFO,
sPymbed 0:c4152c628df5 4330 "Not trying to decrypt short message.");
sPymbed 0:c4152c628df5 4331 }
sPymbed 0:c4152c628df5 4332
sPymbed 0:c4152c628df5 4333 /* Verify the buffer is big enough for the data and mac.
sPymbed 0:c4152c628df5 4334 * Even if the decrypt step fails, verify the MAC anyway.
sPymbed 0:c4152c628df5 4335 * This keeps consistent timing. */
sPymbed 0:c4152c628df5 4336 verifyResult = VerifyMac(ssh,
sPymbed 0:c4152c628df5 4337 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4338 ssh->inputBuffer.idx,
sPymbed 0:c4152c628df5 4339 ssh->curSz + LENGTH_SZ,
sPymbed 0:c4152c628df5 4340 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4341 ssh->inputBuffer.idx +
sPymbed 0:c4152c628df5 4342 LENGTH_SZ + ssh->curSz);
sPymbed 0:c4152c628df5 4343 if (ret != WS_SUCCESS) {
sPymbed 0:c4152c628df5 4344 WLOG(WS_LOG_DEBUG, "PR: Decrypt fail");
sPymbed 0:c4152c628df5 4345 return ret;
sPymbed 0:c4152c628df5 4346 }
sPymbed 0:c4152c628df5 4347 if (verifyResult != WS_SUCCESS) {
sPymbed 0:c4152c628df5 4348 WLOG(WS_LOG_DEBUG, "PR: VerifyMac fail");
sPymbed 0:c4152c628df5 4349 return ret;
sPymbed 0:c4152c628df5 4350 }
sPymbed 0:c4152c628df5 4351 }
sPymbed 0:c4152c628df5 4352 else {
sPymbed 0:c4152c628df5 4353 ret = DecryptAead(ssh,
sPymbed 0:c4152c628df5 4354 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4355 ssh->inputBuffer.idx +
sPymbed 0:c4152c628df5 4356 LENGTH_SZ,
sPymbed 0:c4152c628df5 4357 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4358 ssh->inputBuffer.idx +
sPymbed 0:c4152c628df5 4359 LENGTH_SZ,
sPymbed 0:c4152c628df5 4360 ssh->curSz,
sPymbed 0:c4152c628df5 4361 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4362 ssh->inputBuffer.idx +
sPymbed 0:c4152c628df5 4363 ssh->curSz + LENGTH_SZ,
sPymbed 0:c4152c628df5 4364 ssh->inputBuffer.buffer +
sPymbed 0:c4152c628df5 4365 ssh->inputBuffer.idx,
sPymbed 0:c4152c628df5 4366 LENGTH_SZ);
sPymbed 0:c4152c628df5 4367
sPymbed 0:c4152c628df5 4368 if (ret != WS_SUCCESS) {
sPymbed 0:c4152c628df5 4369 WLOG(WS_LOG_DEBUG, "PR: DecryptAead fail");
sPymbed 0:c4152c628df5 4370 return ret;
sPymbed 0:c4152c628df5 4371 }
sPymbed 0:c4152c628df5 4372 }
sPymbed 0:c4152c628df5 4373 }
sPymbed 0:c4152c628df5 4374 ssh->processReplyState = PROCESS_PACKET;
sPymbed 0:c4152c628df5 4375 FALL_THROUGH;
sPymbed 0:c4152c628df5 4376
sPymbed 0:c4152c628df5 4377 case PROCESS_PACKET:
sPymbed 0:c4152c628df5 4378 //ESP_LOGI("WOLFSSH", "DoReceive: PROCESS_PACKET");
sPymbed 0:c4152c628df5 4379 if ( (ret = DoPacket(ssh)) < 0) {
sPymbed 0:c4152c628df5 4380 return ret;
sPymbed 0:c4152c628df5 4381 }
sPymbed 0:c4152c628df5 4382 WLOG(WS_LOG_DEBUG, "PR3: peerMacSz = %u", peerMacSz);
sPymbed 0:c4152c628df5 4383 ssh->inputBuffer.idx += peerMacSz;
sPymbed 0:c4152c628df5 4384 break;
sPymbed 0:c4152c628df5 4385
sPymbed 0:c4152c628df5 4386 default:
sPymbed 0:c4152c628df5 4387 //ESP_LOGI("WOLFSSH", "DoReceive: Bad input state!!");
sPymbed 0:c4152c628df5 4388 WLOG(WS_LOG_DEBUG, "Bad process input state, program error");
sPymbed 0:c4152c628df5 4389 return WS_INPUT_CASE_E;
sPymbed 0:c4152c628df5 4390 }
sPymbed 0:c4152c628df5 4391 WLOG(WS_LOG_DEBUG, "PR4: Shrinking input buffer");
sPymbed 0:c4152c628df5 4392 //ESP_LOGI("WOLFSSH", "PR4: Shrinking input buffer");
sPymbed 0:c4152c628df5 4393 ShrinkBuffer(&ssh->inputBuffer, 1);
sPymbed 0:c4152c628df5 4394 ssh->processReplyState = PROCESS_INIT;
sPymbed 0:c4152c628df5 4395
sPymbed 0:c4152c628df5 4396 WLOG(WS_LOG_DEBUG, "PR5: txCount = %u, rxCount = %u",
sPymbed 0:c4152c628df5 4397 ssh->txCount, ssh->rxCount);
sPymbed 0:c4152c628df5 4398 //ESP_LOGI("WOLFSSH", "PR5: txCount = %u, rxCount = %u", ssh->txCount, ssh->rxCount);
sPymbed 0:c4152c628df5 4399
sPymbed 0:c4152c628df5 4400 return WS_SUCCESS;
sPymbed 0:c4152c628df5 4401 }
sPymbed 0:c4152c628df5 4402 }
sPymbed 0:c4152c628df5 4403
sPymbed 0:c4152c628df5 4404
sPymbed 0:c4152c628df5 4405 int DoProtoId(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 4406 {
sPymbed 0:c4152c628df5 4407 int ret;
sPymbed 0:c4152c628df5 4408 word32 idSz;
sPymbed 0:c4152c628df5 4409 byte* eol;
sPymbed 0:c4152c628df5 4410
sPymbed 0:c4152c628df5 4411 if ( (ret = GetInputText(ssh, &eol)) < 0) {
sPymbed 0:c4152c628df5 4412 WLOG(WS_LOG_DEBUG, "get input text failed");
sPymbed 0:c4152c628df5 4413 return ret;
sPymbed 0:c4152c628df5 4414 }
sPymbed 0:c4152c628df5 4415
sPymbed 0:c4152c628df5 4416 if (eol == NULL) {
sPymbed 0:c4152c628df5 4417 WLOG(WS_LOG_DEBUG, "invalid EOL");
sPymbed 0:c4152c628df5 4418 return WS_VERSION_E;
sPymbed 0:c4152c628df5 4419 }
sPymbed 0:c4152c628df5 4420
sPymbed 0:c4152c628df5 4421 if (WSTRNCASECMP((char*)ssh->inputBuffer.buffer,
sPymbed 0:c4152c628df5 4422 sshProtoIdStr, SSH_PROTO_SZ) == 0) {
sPymbed 0:c4152c628df5 4423
sPymbed 0:c4152c628df5 4424 if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)
sPymbed 0:c4152c628df5 4425 ssh->clientState = CLIENT_VERSION_DONE;
sPymbed 0:c4152c628df5 4426 else
sPymbed 0:c4152c628df5 4427 ssh->serverState = SERVER_VERSION_DONE;
sPymbed 0:c4152c628df5 4428 }
sPymbed 0:c4152c628df5 4429 else {
sPymbed 0:c4152c628df5 4430 WLOG(WS_LOG_DEBUG, "SSH version mismatch");
sPymbed 0:c4152c628df5 4431 return WS_VERSION_E;
sPymbed 0:c4152c628df5 4432 }
sPymbed 0:c4152c628df5 4433
sPymbed 0:c4152c628df5 4434 *eol = 0;
sPymbed 0:c4152c628df5 4435
sPymbed 0:c4152c628df5 4436 idSz = (word32)WSTRLEN((char*)ssh->inputBuffer.buffer);
sPymbed 0:c4152c628df5 4437
sPymbed 0:c4152c628df5 4438 /* Store the proto ID for later use. It is used in keying and rekeying. */
sPymbed 0:c4152c628df5 4439 ssh->peerProtoId = (byte*)WMALLOC(idSz + LENGTH_SZ,
sPymbed 0:c4152c628df5 4440 ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 4441 if (ssh->peerProtoId == NULL)
sPymbed 0:c4152c628df5 4442 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 4443 else {
sPymbed 0:c4152c628df5 4444 c32toa(idSz, ssh->peerProtoId);
sPymbed 0:c4152c628df5 4445 WMEMCPY(ssh->peerProtoId + LENGTH_SZ, ssh->inputBuffer.buffer, idSz);
sPymbed 0:c4152c628df5 4446 ssh->peerProtoIdSz = idSz + LENGTH_SZ;
sPymbed 0:c4152c628df5 4447 }
sPymbed 0:c4152c628df5 4448
sPymbed 0:c4152c628df5 4449 ssh->inputBuffer.idx += idSz + SSH_PROTO_EOL_SZ;
sPymbed 0:c4152c628df5 4450 ShrinkBuffer(&ssh->inputBuffer, 0);
sPymbed 0:c4152c628df5 4451
sPymbed 0:c4152c628df5 4452 return ret;
sPymbed 0:c4152c628df5 4453 }
sPymbed 0:c4152c628df5 4454
sPymbed 0:c4152c628df5 4455
sPymbed 0:c4152c628df5 4456 int SendProtoId(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 4457 {
sPymbed 0:c4152c628df5 4458 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4459 word32 sshProtoIdStrSz;
sPymbed 0:c4152c628df5 4460
sPymbed 0:c4152c628df5 4461 if (ssh == NULL)
sPymbed 0:c4152c628df5 4462 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4463
sPymbed 0:c4152c628df5 4464 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4465 WLOG(WS_LOG_DEBUG, "%s", sshProtoIdStr);
sPymbed 0:c4152c628df5 4466 sshProtoIdStrSz = (word32)WSTRLEN(sshProtoIdStr);
sPymbed 0:c4152c628df5 4467 ret = GrowBuffer(&ssh->outputBuffer, sshProtoIdStrSz, 0);
sPymbed 0:c4152c628df5 4468 }
sPymbed 0:c4152c628df5 4469
sPymbed 0:c4152c628df5 4470 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4471 WMEMCPY(ssh->outputBuffer.buffer, sshProtoIdStr, sshProtoIdStrSz);
sPymbed 0:c4152c628df5 4472 ssh->outputBuffer.length = sshProtoIdStrSz;
sPymbed 0:c4152c628df5 4473 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 4474 }
sPymbed 0:c4152c628df5 4475
sPymbed 0:c4152c628df5 4476 return ret;
sPymbed 0:c4152c628df5 4477 }
sPymbed 0:c4152c628df5 4478
sPymbed 0:c4152c628df5 4479
sPymbed 0:c4152c628df5 4480 static int PreparePacket(WOLFSSH* ssh, word32 payloadSz)
sPymbed 0:c4152c628df5 4481 {
sPymbed 0:c4152c628df5 4482 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4483 byte* output;
sPymbed 0:c4152c628df5 4484 word32 outputSz;
sPymbed 0:c4152c628df5 4485 word32 packetSz;
sPymbed 0:c4152c628df5 4486 word32 usedSz;
sPymbed 0:c4152c628df5 4487 byte paddingSz;
sPymbed 0:c4152c628df5 4488
sPymbed 0:c4152c628df5 4489 if (ssh == NULL)
sPymbed 0:c4152c628df5 4490 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4491
sPymbed 0:c4152c628df5 4492 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4493 /* Minimum value for paddingSz is 4. */
sPymbed 0:c4152c628df5 4494 paddingSz = ssh->blockSz -
sPymbed 0:c4152c628df5 4495 ((ssh->aeadMode ? 0 : LENGTH_SZ) +
sPymbed 0:c4152c628df5 4496 PAD_LENGTH_SZ + payloadSz) % ssh->blockSz;
sPymbed 0:c4152c628df5 4497 if (paddingSz < MIN_PAD_LENGTH)
sPymbed 0:c4152c628df5 4498 paddingSz += ssh->blockSz;
sPymbed 0:c4152c628df5 4499 ssh->paddingSz = paddingSz;
sPymbed 0:c4152c628df5 4500 packetSz = PAD_LENGTH_SZ + payloadSz + paddingSz;
sPymbed 0:c4152c628df5 4501 outputSz = LENGTH_SZ + packetSz + ssh->macSz;
sPymbed 0:c4152c628df5 4502 usedSz = ssh->outputBuffer.length - ssh->outputBuffer.idx;
sPymbed 0:c4152c628df5 4503
sPymbed 0:c4152c628df5 4504 ret = GrowBuffer(&ssh->outputBuffer, outputSz, usedSz);
sPymbed 0:c4152c628df5 4505 }
sPymbed 0:c4152c628df5 4506
sPymbed 0:c4152c628df5 4507 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4508 ssh->packetStartIdx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 4509 output = ssh->outputBuffer.buffer + ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 4510
sPymbed 0:c4152c628df5 4511 /* fill in the packetSz, paddingSz */
sPymbed 0:c4152c628df5 4512 c32toa(packetSz, output);
sPymbed 0:c4152c628df5 4513 output[LENGTH_SZ] = paddingSz;
sPymbed 0:c4152c628df5 4514
sPymbed 0:c4152c628df5 4515 ssh->outputBuffer.length += LENGTH_SZ + PAD_LENGTH_SZ;
sPymbed 0:c4152c628df5 4516 }
sPymbed 0:c4152c628df5 4517
sPymbed 0:c4152c628df5 4518 return ret;
sPymbed 0:c4152c628df5 4519 }
sPymbed 0:c4152c628df5 4520
sPymbed 0:c4152c628df5 4521
sPymbed 0:c4152c628df5 4522 static int BundlePacket(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 4523 {
sPymbed 0:c4152c628df5 4524 byte* output;
sPymbed 0:c4152c628df5 4525 word32 idx;
sPymbed 0:c4152c628df5 4526 byte paddingSz;
sPymbed 0:c4152c628df5 4527 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4528
sPymbed 0:c4152c628df5 4529 if (ssh == NULL)
sPymbed 0:c4152c628df5 4530 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4531
sPymbed 0:c4152c628df5 4532 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4533 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 4534 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 4535 paddingSz = ssh->paddingSz;
sPymbed 0:c4152c628df5 4536
sPymbed 0:c4152c628df5 4537 /* Add the padding */
sPymbed 0:c4152c628df5 4538 WLOG(WS_LOG_DEBUG, "BP: paddingSz = %u", paddingSz);
sPymbed 0:c4152c628df5 4539 if (ssh->encryptId == ID_NONE)
sPymbed 0:c4152c628df5 4540 WMEMSET(output + idx, 0, paddingSz);
sPymbed 0:c4152c628df5 4541 else if (wc_RNG_GenerateBlock(ssh->rng, output + idx, paddingSz) < 0)
sPymbed 0:c4152c628df5 4542 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 4543 }
sPymbed 0:c4152c628df5 4544
sPymbed 0:c4152c628df5 4545 if (!ssh->aeadMode) {
sPymbed 0:c4152c628df5 4546 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4547 idx += paddingSz;
sPymbed 0:c4152c628df5 4548 ret = CreateMac(ssh, ssh->outputBuffer.buffer + ssh->packetStartIdx,
sPymbed 0:c4152c628df5 4549 ssh->outputBuffer.length -
sPymbed 0:c4152c628df5 4550 ssh->packetStartIdx + paddingSz,
sPymbed 0:c4152c628df5 4551 output + idx);
sPymbed 0:c4152c628df5 4552 }
sPymbed 0:c4152c628df5 4553 else {
sPymbed 0:c4152c628df5 4554 WLOG(WS_LOG_DEBUG, "BP: failed to add padding");
sPymbed 0:c4152c628df5 4555 }
sPymbed 0:c4152c628df5 4556
sPymbed 0:c4152c628df5 4557 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4558 idx += ssh->macSz;
sPymbed 0:c4152c628df5 4559 ret = Encrypt(ssh,
sPymbed 0:c4152c628df5 4560 ssh->outputBuffer.buffer + ssh->packetStartIdx,
sPymbed 0:c4152c628df5 4561 ssh->outputBuffer.buffer + ssh->packetStartIdx,
sPymbed 0:c4152c628df5 4562 ssh->outputBuffer.length -
sPymbed 0:c4152c628df5 4563 ssh->packetStartIdx + paddingSz);
sPymbed 0:c4152c628df5 4564 }
sPymbed 0:c4152c628df5 4565 else {
sPymbed 0:c4152c628df5 4566 WLOG(WS_LOG_DEBUG, "BP: failed to generate mac");
sPymbed 0:c4152c628df5 4567 }
sPymbed 0:c4152c628df5 4568 }
sPymbed 0:c4152c628df5 4569 else {
sPymbed 0:c4152c628df5 4570 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4571 idx += paddingSz;
sPymbed 0:c4152c628df5 4572 ret = EncryptAead(ssh,
sPymbed 0:c4152c628df5 4573 ssh->outputBuffer.buffer +
sPymbed 0:c4152c628df5 4574 ssh->packetStartIdx + LENGTH_SZ,
sPymbed 0:c4152c628df5 4575 ssh->outputBuffer.buffer +
sPymbed 0:c4152c628df5 4576 ssh->packetStartIdx + LENGTH_SZ,
sPymbed 0:c4152c628df5 4577 ssh->outputBuffer.length -
sPymbed 0:c4152c628df5 4578 ssh->packetStartIdx + paddingSz -
sPymbed 0:c4152c628df5 4579 LENGTH_SZ,
sPymbed 0:c4152c628df5 4580 output + idx,
sPymbed 0:c4152c628df5 4581 ssh->outputBuffer.buffer +
sPymbed 0:c4152c628df5 4582 ssh->packetStartIdx,
sPymbed 0:c4152c628df5 4583 LENGTH_SZ);
sPymbed 0:c4152c628df5 4584 idx += ssh->macSz;
sPymbed 0:c4152c628df5 4585 }
sPymbed 0:c4152c628df5 4586 }
sPymbed 0:c4152c628df5 4587
sPymbed 0:c4152c628df5 4588 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4589 ssh->seq++;
sPymbed 0:c4152c628df5 4590 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 4591 }
sPymbed 0:c4152c628df5 4592 else {
sPymbed 0:c4152c628df5 4593 WLOG(WS_LOG_DEBUG, "BP: failed to encrypt buffer");
sPymbed 0:c4152c628df5 4594 }
sPymbed 0:c4152c628df5 4595
sPymbed 0:c4152c628df5 4596 return ret;
sPymbed 0:c4152c628df5 4597 }
sPymbed 0:c4152c628df5 4598
sPymbed 0:c4152c628df5 4599
sPymbed 0:c4152c628df5 4600 static INLINE void CopyNameList(byte* buf, word32* idx,
sPymbed 0:c4152c628df5 4601 const char* src, word32 srcSz)
sPymbed 0:c4152c628df5 4602 {
sPymbed 0:c4152c628df5 4603 word32 begin = *idx;
sPymbed 0:c4152c628df5 4604
sPymbed 0:c4152c628df5 4605 c32toa(srcSz, buf + begin);
sPymbed 0:c4152c628df5 4606 begin += LENGTH_SZ;
sPymbed 0:c4152c628df5 4607 WMEMCPY(buf + begin, src, srcSz);
sPymbed 0:c4152c628df5 4608 begin += srcSz;
sPymbed 0:c4152c628df5 4609
sPymbed 0:c4152c628df5 4610 *idx = begin;
sPymbed 0:c4152c628df5 4611 }
sPymbed 0:c4152c628df5 4612
sPymbed 0:c4152c628df5 4613
sPymbed 0:c4152c628df5 4614 static const char cannedEncAlgoNames[] = "aes128-gcm@openssh.com,aes128-cbc";
sPymbed 0:c4152c628df5 4615 static const char cannedMacAlgoNames[] = "hmac-sha2-256,hmac-sha1-96,"
sPymbed 0:c4152c628df5 4616 "hmac-sha1";
sPymbed 0:c4152c628df5 4617 static const char cannedKeyAlgoRsaNames[] = "ssh-rsa";
sPymbed 0:c4152c628df5 4618 static const char cannedKeyAlgoEcc256Names[] = "ecdsa-sha2-nistp256";
sPymbed 0:c4152c628df5 4619 static const char cannedKeyAlgoEcc384Names[] = "ecdsa-sha2-nistp384";
sPymbed 0:c4152c628df5 4620 static const char cannedKeyAlgoEcc521Names[] = "ecdsa-sha2-nistp521";
sPymbed 0:c4152c628df5 4621 static const char cannedKexAlgoNames[] = "ecdh-sha2-nistp256,"
sPymbed 0:c4152c628df5 4622 "diffie-hellman-group-exchange-sha256,"
sPymbed 0:c4152c628df5 4623 "diffie-hellman-group14-sha1,"
sPymbed 0:c4152c628df5 4624 "diffie-hellman-group1-sha1";
sPymbed 0:c4152c628df5 4625 static const char cannedNoneNames[] = "none";
sPymbed 0:c4152c628df5 4626
sPymbed 0:c4152c628df5 4627 static const word32 cannedEncAlgoNamesSz = sizeof(cannedEncAlgoNames) - 1;
sPymbed 0:c4152c628df5 4628 static const word32 cannedMacAlgoNamesSz = sizeof(cannedMacAlgoNames) - 1;
sPymbed 0:c4152c628df5 4629 static const word32 cannedKeyAlgoRsaNamesSz = sizeof(cannedKeyAlgoRsaNames) - 1;
sPymbed 0:c4152c628df5 4630 static const word32 cannedKeyAlgoEcc256NamesSz =
sPymbed 0:c4152c628df5 4631 sizeof(cannedKeyAlgoEcc256Names) - 1;
sPymbed 0:c4152c628df5 4632 static const word32 cannedKeyAlgoEcc384NamesSz =
sPymbed 0:c4152c628df5 4633 sizeof(cannedKeyAlgoEcc384Names) - 1;
sPymbed 0:c4152c628df5 4634 static const word32 cannedKeyAlgoEcc521NamesSz =
sPymbed 0:c4152c628df5 4635 sizeof(cannedKeyAlgoEcc521Names) - 1;
sPymbed 0:c4152c628df5 4636 static const word32 cannedKexAlgoNamesSz = sizeof(cannedKexAlgoNames) - 1;
sPymbed 0:c4152c628df5 4637 static const word32 cannedNoneNamesSz = sizeof(cannedNoneNames) - 1;
sPymbed 0:c4152c628df5 4638
sPymbed 0:c4152c628df5 4639
sPymbed 0:c4152c628df5 4640 int SendKexInit(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 4641 {
sPymbed 0:c4152c628df5 4642 byte* output;
sPymbed 0:c4152c628df5 4643 byte* payload;
sPymbed 0:c4152c628df5 4644 word32 idx = 0;
sPymbed 0:c4152c628df5 4645 word32 payloadSz;
sPymbed 0:c4152c628df5 4646 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4647 const char* cannedKeyAlgoNames;
sPymbed 0:c4152c628df5 4648 word32 cannedKeyAlgoNamesSz;
sPymbed 0:c4152c628df5 4649
sPymbed 0:c4152c628df5 4650 WLOG(WS_LOG_DEBUG, "Entering SendKexInit()");
sPymbed 0:c4152c628df5 4651
sPymbed 0:c4152c628df5 4652 if (ssh == NULL)
sPymbed 0:c4152c628df5 4653 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 4654
sPymbed 0:c4152c628df5 4655 ssh->isKeying = 1;
sPymbed 0:c4152c628df5 4656 if (ssh->handshake == NULL) {
sPymbed 0:c4152c628df5 4657 ssh->handshake = HandshakeInfoNew(ssh->ctx->heap);
sPymbed 0:c4152c628df5 4658 if (ssh->handshake == NULL) {
sPymbed 0:c4152c628df5 4659 WLOG(WS_LOG_DEBUG, "Couldn't allocate handshake info");
sPymbed 0:c4152c628df5 4660 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 4661 }
sPymbed 0:c4152c628df5 4662 }
sPymbed 0:c4152c628df5 4663
sPymbed 0:c4152c628df5 4664 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4665 switch (ssh->ctx->useEcc) {
sPymbed 0:c4152c628df5 4666 case ECC_SECP256R1:
sPymbed 0:c4152c628df5 4667 cannedKeyAlgoNames = cannedKeyAlgoEcc256Names;
sPymbed 0:c4152c628df5 4668 cannedKeyAlgoNamesSz = cannedKeyAlgoEcc256NamesSz;
sPymbed 0:c4152c628df5 4669 break;
sPymbed 0:c4152c628df5 4670 case ECC_SECP384R1:
sPymbed 0:c4152c628df5 4671 cannedKeyAlgoNames = cannedKeyAlgoEcc384Names;
sPymbed 0:c4152c628df5 4672 cannedKeyAlgoNamesSz = cannedKeyAlgoEcc384NamesSz;
sPymbed 0:c4152c628df5 4673 break;
sPymbed 0:c4152c628df5 4674 case ECC_SECP521R1:
sPymbed 0:c4152c628df5 4675 cannedKeyAlgoNames = cannedKeyAlgoEcc521Names;
sPymbed 0:c4152c628df5 4676 cannedKeyAlgoNamesSz = cannedKeyAlgoEcc521NamesSz;
sPymbed 0:c4152c628df5 4677 break;
sPymbed 0:c4152c628df5 4678 default:
sPymbed 0:c4152c628df5 4679 cannedKeyAlgoNames = cannedKeyAlgoRsaNames;
sPymbed 0:c4152c628df5 4680 cannedKeyAlgoNamesSz = cannedKeyAlgoRsaNamesSz;
sPymbed 0:c4152c628df5 4681 }
sPymbed 0:c4152c628df5 4682 payloadSz = MSG_ID_SZ + COOKIE_SZ + (LENGTH_SZ * 11) + BOOLEAN_SZ +
sPymbed 0:c4152c628df5 4683 cannedKexAlgoNamesSz + cannedKeyAlgoNamesSz +
sPymbed 0:c4152c628df5 4684 (cannedEncAlgoNamesSz * 2) +
sPymbed 0:c4152c628df5 4685 (cannedMacAlgoNamesSz * 2) +
sPymbed 0:c4152c628df5 4686 (cannedNoneNamesSz * 2);
sPymbed 0:c4152c628df5 4687 ret = PreparePacket(ssh, payloadSz);
sPymbed 0:c4152c628df5 4688 }
sPymbed 0:c4152c628df5 4689
sPymbed 0:c4152c628df5 4690 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4691 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 4692 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 4693 payload = output + idx;
sPymbed 0:c4152c628df5 4694
sPymbed 0:c4152c628df5 4695 output[idx++] = MSGID_KEXINIT;
sPymbed 0:c4152c628df5 4696
sPymbed 0:c4152c628df5 4697 ret = wc_RNG_GenerateBlock(ssh->rng, output + idx, COOKIE_SZ);
sPymbed 0:c4152c628df5 4698 }
sPymbed 0:c4152c628df5 4699
sPymbed 0:c4152c628df5 4700 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4701 byte* buf;
sPymbed 0:c4152c628df5 4702 word32 bufSz = payloadSz + LENGTH_SZ;
sPymbed 0:c4152c628df5 4703
sPymbed 0:c4152c628df5 4704 idx += COOKIE_SZ;
sPymbed 0:c4152c628df5 4705
sPymbed 0:c4152c628df5 4706 CopyNameList(output, &idx, cannedKexAlgoNames, cannedKexAlgoNamesSz);
sPymbed 0:c4152c628df5 4707 CopyNameList(output, &idx, cannedKeyAlgoNames, cannedKeyAlgoNamesSz);
sPymbed 0:c4152c628df5 4708 CopyNameList(output, &idx, cannedEncAlgoNames, cannedEncAlgoNamesSz);
sPymbed 0:c4152c628df5 4709 CopyNameList(output, &idx, cannedEncAlgoNames, cannedEncAlgoNamesSz);
sPymbed 0:c4152c628df5 4710 CopyNameList(output, &idx, cannedMacAlgoNames, cannedMacAlgoNamesSz);
sPymbed 0:c4152c628df5 4711 CopyNameList(output, &idx, cannedMacAlgoNames, cannedMacAlgoNamesSz);
sPymbed 0:c4152c628df5 4712 CopyNameList(output, &idx, cannedNoneNames, cannedNoneNamesSz);
sPymbed 0:c4152c628df5 4713 CopyNameList(output, &idx, cannedNoneNames, cannedNoneNamesSz);
sPymbed 0:c4152c628df5 4714 c32toa(0, output + idx); /* Languages - Client To Server (0) */
sPymbed 0:c4152c628df5 4715 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 4716 c32toa(0, output + idx); /* Languages - Server To Client (0) */
sPymbed 0:c4152c628df5 4717 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 4718 output[idx++] = 0; /* First KEX packet follows (false) */
sPymbed 0:c4152c628df5 4719 c32toa(0, output + idx); /* Reserved (0) */
sPymbed 0:c4152c628df5 4720 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 4721
sPymbed 0:c4152c628df5 4722 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 4723
sPymbed 0:c4152c628df5 4724 buf = (byte*)WMALLOC(bufSz, ssh->ctx->heap, DYNTYPE_STRING);
sPymbed 0:c4152c628df5 4725 if (buf == NULL) {
sPymbed 0:c4152c628df5 4726 WLOG(WS_LOG_DEBUG, "Cannot allocate storage for KEX Init msg");
sPymbed 0:c4152c628df5 4727 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 4728 }
sPymbed 0:c4152c628df5 4729 else {
sPymbed 0:c4152c628df5 4730 c32toa(payloadSz, buf);
sPymbed 0:c4152c628df5 4731 WMEMCPY(buf + LENGTH_SZ, payload, payloadSz);
sPymbed 0:c4152c628df5 4732 ssh->handshake->kexInit = buf;
sPymbed 0:c4152c628df5 4733 ssh->handshake->kexInitSz = bufSz;
sPymbed 0:c4152c628df5 4734 }
sPymbed 0:c4152c628df5 4735 }
sPymbed 0:c4152c628df5 4736
sPymbed 0:c4152c628df5 4737 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4738 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 4739
sPymbed 0:c4152c628df5 4740 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 4741 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 4742
sPymbed 0:c4152c628df5 4743 WLOG(WS_LOG_DEBUG, "Leaving SendKexInit(), ret = %d", ret);
sPymbed 0:c4152c628df5 4744 return ret;
sPymbed 0:c4152c628df5 4745 }
sPymbed 0:c4152c628df5 4746
sPymbed 0:c4152c628df5 4747
sPymbed 0:c4152c628df5 4748 /* SendKexDhReply()
sPymbed 0:c4152c628df5 4749 * It is also the funciton used for MSGID_KEXECDH_REPLY. The parameters
sPymbed 0:c4152c628df5 4750 * are analogous between the two messages. Where MSGID_KEXDH_REPLY has
sPymbed 0:c4152c628df5 4751 * server's public host key (K_S), f, and the signature of H;
sPymbed 0:c4152c628df5 4752 * MSGID_KEXECDH_REPLY has K_S, the server'e ephemeral public key (Q_S),
sPymbed 0:c4152c628df5 4753 * and the signature of H. This also applies to the GEX version of this.
sPymbed 0:c4152c628df5 4754 * H is calculated the same for KEXDH and KEXECDH, and has some exceptions
sPymbed 0:c4152c628df5 4755 * for GEXDH. */
sPymbed 0:c4152c628df5 4756 int SendKexDhReply(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 4757 {
sPymbed 0:c4152c628df5 4758 /* This function and DoKexDhReply() are unwieldy and in need of refactoring. */
sPymbed 0:c4152c628df5 4759 const byte* primeGroup = dhPrimeGroup14;
sPymbed 0:c4152c628df5 4760 word32 primeGroupSz = dhPrimeGroup14Sz;
sPymbed 0:c4152c628df5 4761 const byte* generator = dhGenerator;
sPymbed 0:c4152c628df5 4762 word32 generatorSz = dhGeneratorSz;
sPymbed 0:c4152c628df5 4763
sPymbed 0:c4152c628df5 4764 byte useEcc = 0;
sPymbed 0:c4152c628df5 4765 byte f[257];
sPymbed 0:c4152c628df5 4766 word32 fSz = sizeof(f);
sPymbed 0:c4152c628df5 4767 byte fPad = 0;
sPymbed 0:c4152c628df5 4768 byte kPad = 0;
sPymbed 0:c4152c628df5 4769
sPymbed 0:c4152c628df5 4770 struct {
sPymbed 0:c4152c628df5 4771 byte useRsa;
sPymbed 0:c4152c628df5 4772 word32 sz;
sPymbed 0:c4152c628df5 4773 const char *name;
sPymbed 0:c4152c628df5 4774 word32 nameSz;
sPymbed 0:c4152c628df5 4775 union {
sPymbed 0:c4152c628df5 4776 struct {
sPymbed 0:c4152c628df5 4777 RsaKey key;
sPymbed 0:c4152c628df5 4778 byte e[257];
sPymbed 0:c4152c628df5 4779 word32 eSz;
sPymbed 0:c4152c628df5 4780 byte ePad;
sPymbed 0:c4152c628df5 4781 byte n[257];
sPymbed 0:c4152c628df5 4782 word32 nSz;
sPymbed 0:c4152c628df5 4783 byte nPad;
sPymbed 0:c4152c628df5 4784 } rsa;
sPymbed 0:c4152c628df5 4785 struct {
sPymbed 0:c4152c628df5 4786 ecc_key key;
sPymbed 0:c4152c628df5 4787 word32 keyBlobSz;
sPymbed 0:c4152c628df5 4788 const char *keyBlobName;
sPymbed 0:c4152c628df5 4789 word32 keyBlobNameSz;
sPymbed 0:c4152c628df5 4790 byte q[257];
sPymbed 0:c4152c628df5 4791 word32 qSz;
sPymbed 0:c4152c628df5 4792 byte qPad;
sPymbed 0:c4152c628df5 4793 const char *primeName;
sPymbed 0:c4152c628df5 4794 word32 primeNameSz;
sPymbed 0:c4152c628df5 4795 } ecc;
sPymbed 0:c4152c628df5 4796 } sk;
sPymbed 0:c4152c628df5 4797 } sigKeyBlock;
sPymbed 0:c4152c628df5 4798
sPymbed 0:c4152c628df5 4799 byte sig[512];
sPymbed 0:c4152c628df5 4800 word32 sigSz = sizeof(sig);
sPymbed 0:c4152c628df5 4801 word32 sigBlockSz;
sPymbed 0:c4152c628df5 4802
sPymbed 0:c4152c628df5 4803 word32 payloadSz;
sPymbed 0:c4152c628df5 4804 byte scratchLen[LENGTH_SZ];
sPymbed 0:c4152c628df5 4805 word32 scratch = 0;
sPymbed 0:c4152c628df5 4806 byte* output;
sPymbed 0:c4152c628df5 4807 word32 idx;
sPymbed 0:c4152c628df5 4808 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 4809 byte msgId = MSGID_KEXDH_REPLY;
sPymbed 0:c4152c628df5 4810
sPymbed 0:c4152c628df5 4811 WLOG(WS_LOG_DEBUG, "Entering SendKexDhReply()");
sPymbed 0:c4152c628df5 4812 //ESP_LOGI("WOLFSSH", "Entering SendKexDhReply()");
sPymbed 0:c4152c628df5 4813
sPymbed 0:c4152c628df5 4814 sigKeyBlock.useRsa = ssh->handshake->pubKeyId == ID_SSH_RSA;
sPymbed 0:c4152c628df5 4815 sigKeyBlock.name = IdToName(ssh->handshake->pubKeyId);
sPymbed 0:c4152c628df5 4816 sigKeyBlock.nameSz = (word32)strlen(sigKeyBlock.name);
sPymbed 0:c4152c628df5 4817
sPymbed 0:c4152c628df5 4818 switch (ssh->handshake->kexId) {
sPymbed 0:c4152c628df5 4819 case ID_DH_GROUP1_SHA1:
sPymbed 0:c4152c628df5 4820 //ESP_LOGI("WOLFSSH", "KexID: ID_DH_GROUP1_SHA1");
sPymbed 0:c4152c628df5 4821 primeGroup = dhPrimeGroup1;
sPymbed 0:c4152c628df5 4822 primeGroupSz = dhPrimeGroup1Sz;
sPymbed 0:c4152c628df5 4823 break;
sPymbed 0:c4152c628df5 4824
sPymbed 0:c4152c628df5 4825 case ID_DH_GROUP14_SHA1:
sPymbed 0:c4152c628df5 4826 //ESP_LOGI("WOLFSSH", "KexID: ID_DH_GROUP14_SHA1 (default)");
sPymbed 0:c4152c628df5 4827 /* This is the default case. */
sPymbed 0:c4152c628df5 4828 break;
sPymbed 0:c4152c628df5 4829
sPymbed 0:c4152c628df5 4830 case ID_DH_GEX_SHA256:
sPymbed 0:c4152c628df5 4831 //ESP_LOGI("WOLFSSH", "KexID: ID_DH_GEX_SHA256");
sPymbed 0:c4152c628df5 4832 msgId = MSGID_KEXDH_GEX_REPLY;
sPymbed 0:c4152c628df5 4833 break;
sPymbed 0:c4152c628df5 4834
sPymbed 0:c4152c628df5 4835 case ID_ECDH_SHA2_NISTP256:
sPymbed 0:c4152c628df5 4836 case ID_ECDH_SHA2_NISTP384:
sPymbed 0:c4152c628df5 4837 case ID_ECDH_SHA2_NISTP521:
sPymbed 0:c4152c628df5 4838 //ESP_LOGI("WOLFSSH", "KexID: ID_ECDH_SHA2_NISTP256/384/521");
sPymbed 0:c4152c628df5 4839 useEcc = 1;
sPymbed 0:c4152c628df5 4840 msgId = MSGID_KEXDH_REPLY;
sPymbed 0:c4152c628df5 4841 break;
sPymbed 0:c4152c628df5 4842
sPymbed 0:c4152c628df5 4843 default:
sPymbed 0:c4152c628df5 4844 //ESP_LOGI("WOLFSSH", "KexID: INVALID");
sPymbed 0:c4152c628df5 4845 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 4846 }
sPymbed 0:c4152c628df5 4847
sPymbed 0:c4152c628df5 4848 /* At this point, the exchange hash, H, includes items V_C, V_S, I_C,
sPymbed 0:c4152c628df5 4849 * and I_S. Next add K_S, the server's public host key. K_S will
sPymbed 0:c4152c628df5 4850 * either be RSA or ECDSA public key blob. */
sPymbed 0:c4152c628df5 4851 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 4852 if (sigKeyBlock.useRsa) {
sPymbed 0:c4152c628df5 4853 //ESP_LOGI("WOLFSSH", "KeyBlock: RSA");
sPymbed 0:c4152c628df5 4854 /* Decode the user-configured RSA private key. */
sPymbed 0:c4152c628df5 4855 sigKeyBlock.sk.rsa.eSz = sizeof(sigKeyBlock.sk.rsa.e);
sPymbed 0:c4152c628df5 4856 sigKeyBlock.sk.rsa.nSz = sizeof(sigKeyBlock.sk.rsa.n);
sPymbed 0:c4152c628df5 4857 //ESP_LOGI("WOLFSSH", "wc_InitRsaKey");
sPymbed 0:c4152c628df5 4858 ret = wc_InitRsaKey(&sigKeyBlock.sk.rsa.key, ssh->ctx->heap);
sPymbed 0:c4152c628df5 4859 //ESP_LOGI("WOLFSSH", "wc_InitRsaKey ret=%d", ret);
sPymbed 0:c4152c628df5 4860 if (ret == 0)
sPymbed 0:c4152c628df5 4861 ret = wc_RsaPrivateKeyDecode(ssh->ctx->privateKey, &scratch,
sPymbed 0:c4152c628df5 4862 &sigKeyBlock.sk.rsa.key,
sPymbed 0:c4152c628df5 4863 (int)ssh->ctx->privateKeySz);
sPymbed 0:c4152c628df5 4864 //ESP_LOGI("WOLFSSH", "RSAPrivKey: %p (%d)", ssh->ctx->privateKey, (int)ssh->ctx->privateKeySz);
sPymbed 0:c4152c628df5 4865 //ESP_LOGI("WOLFSSH", "wc_RsaPrivateKeyDecode ret=%d", ret);
sPymbed 0:c4152c628df5 4866 /* Flatten the public key into mpint values for the hash. */
sPymbed 0:c4152c628df5 4867 if (ret == 0)
sPymbed 0:c4152c628df5 4868 ret = wc_RsaFlattenPublicKey(&sigKeyBlock.sk.rsa.key,
sPymbed 0:c4152c628df5 4869 sigKeyBlock.sk.rsa.e,
sPymbed 0:c4152c628df5 4870 &sigKeyBlock.sk.rsa.eSz,
sPymbed 0:c4152c628df5 4871 sigKeyBlock.sk.rsa.n,
sPymbed 0:c4152c628df5 4872 &sigKeyBlock.sk.rsa.nSz);
sPymbed 0:c4152c628df5 4873 //ESP_LOGI("WOLFSSH", "wc_RsaFlattenPublicKey ret=%d", ret);
sPymbed 0:c4152c628df5 4874 if (ret == 0) {
sPymbed 0:c4152c628df5 4875 /* Add a pad byte if the mpint has the MSB set. */
sPymbed 0:c4152c628df5 4876 sigKeyBlock.sk.rsa.ePad = (sigKeyBlock.sk.rsa.e[0] & 0x80) ?
sPymbed 0:c4152c628df5 4877 1 : 0;
sPymbed 0:c4152c628df5 4878 sigKeyBlock.sk.rsa.nPad = (sigKeyBlock.sk.rsa.n[0] & 0x80) ?
sPymbed 0:c4152c628df5 4879 1 : 0;
sPymbed 0:c4152c628df5 4880 sigKeyBlock.sz = (LENGTH_SZ * 3) + sigKeyBlock.nameSz +
sPymbed 0:c4152c628df5 4881 sigKeyBlock.sk.rsa.eSz +
sPymbed 0:c4152c628df5 4882 sigKeyBlock.sk.rsa.ePad +
sPymbed 0:c4152c628df5 4883 sigKeyBlock.sk.rsa.nSz +
sPymbed 0:c4152c628df5 4884 sigKeyBlock.sk.rsa.nPad;
sPymbed 0:c4152c628df5 4885 c32toa(sigKeyBlock.sz, scratchLen);
sPymbed 0:c4152c628df5 4886 /* Hash in the length of the public key block. */
sPymbed 0:c4152c628df5 4887 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4888 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4889 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 4890 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4891 }
sPymbed 0:c4152c628df5 4892 /* Hash in the length of the key type string. */
sPymbed 0:c4152c628df5 4893 if (ret == 0) {
sPymbed 0:c4152c628df5 4894 c32toa(sigKeyBlock.nameSz, scratchLen);
sPymbed 0:c4152c628df5 4895 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4896 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4897 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 4898 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4899 }
sPymbed 0:c4152c628df5 4900 /* Hash in the key type string. */
sPymbed 0:c4152c628df5 4901 if (ret == 0)
sPymbed 0:c4152c628df5 4902 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4903 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4904 (byte*)sigKeyBlock.name,
sPymbed 0:c4152c628df5 4905 sigKeyBlock.nameSz);
sPymbed 0:c4152c628df5 4906 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4907 /* Hash in the length of the RSA public key E value. */
sPymbed 0:c4152c628df5 4908 if (ret == 0) {
sPymbed 0:c4152c628df5 4909 c32toa(sigKeyBlock.sk.rsa.eSz + sigKeyBlock.sk.rsa.ePad,
sPymbed 0:c4152c628df5 4910 scratchLen);
sPymbed 0:c4152c628df5 4911 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4912 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4913 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 4914 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4915 }
sPymbed 0:c4152c628df5 4916 /* Hash in the pad byte for the RSA public key E value. */
sPymbed 0:c4152c628df5 4917 if (ret == 0) {
sPymbed 0:c4152c628df5 4918 if (sigKeyBlock.sk.rsa.ePad) {
sPymbed 0:c4152c628df5 4919 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 4920 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4921 ssh->handshake->hashId, scratchLen, 1);
sPymbed 0:c4152c628df5 4922 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4923 }
sPymbed 0:c4152c628df5 4924 }
sPymbed 0:c4152c628df5 4925 /* Hash in the RSA public key E value. */
sPymbed 0:c4152c628df5 4926 if (ret == 0)
sPymbed 0:c4152c628df5 4927 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4928 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4929 sigKeyBlock.sk.rsa.e,
sPymbed 0:c4152c628df5 4930 sigKeyBlock.sk.rsa.eSz);
sPymbed 0:c4152c628df5 4931 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4932 /* Hash in the length of the RSA public key N value. */
sPymbed 0:c4152c628df5 4933 if (ret == 0) {
sPymbed 0:c4152c628df5 4934 c32toa(sigKeyBlock.sk.rsa.nSz + sigKeyBlock.sk.rsa.nPad,
sPymbed 0:c4152c628df5 4935 scratchLen);
sPymbed 0:c4152c628df5 4936 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4937 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4938 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 4939 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4940 }
sPymbed 0:c4152c628df5 4941 /* Hash in the pad byte for the RSA public key N value. */
sPymbed 0:c4152c628df5 4942 if (ret == 0) {
sPymbed 0:c4152c628df5 4943 if (sigKeyBlock.sk.rsa.nPad) {
sPymbed 0:c4152c628df5 4944 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 4945 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4946 ssh->handshake->hashId, scratchLen, 1);
sPymbed 0:c4152c628df5 4947 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4948 }
sPymbed 0:c4152c628df5 4949 }
sPymbed 0:c4152c628df5 4950 /* Hash in the RSA public key N value. */
sPymbed 0:c4152c628df5 4951 if (ret == 0)
sPymbed 0:c4152c628df5 4952 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4953 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4954 sigKeyBlock.sk.rsa.n,
sPymbed 0:c4152c628df5 4955 sigKeyBlock.sk.rsa.nSz);
sPymbed 0:c4152c628df5 4956 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 4957 }
sPymbed 0:c4152c628df5 4958 else {
sPymbed 0:c4152c628df5 4959 //ESP_LOGI("WOLFSSH", "KeyBlock: Non-RSA");
sPymbed 0:c4152c628df5 4960 sigKeyBlock.sk.ecc.primeName =
sPymbed 0:c4152c628df5 4961 PrimeNameForId(ssh->handshake->pubKeyId);
sPymbed 0:c4152c628df5 4962 sigKeyBlock.sk.ecc.primeNameSz =
sPymbed 0:c4152c628df5 4963 (word32)strlen(sigKeyBlock.sk.ecc.primeName);
sPymbed 0:c4152c628df5 4964
sPymbed 0:c4152c628df5 4965 /* Decode the user-configured ECDSA private key. */
sPymbed 0:c4152c628df5 4966 sigKeyBlock.sk.ecc.qSz = sizeof(sigKeyBlock.sk.ecc.q);
sPymbed 0:c4152c628df5 4967 ret = wc_ecc_init_ex(&sigKeyBlock.sk.ecc.key, ssh->ctx->heap,
sPymbed 0:c4152c628df5 4968 INVALID_DEVID);
sPymbed 0:c4152c628df5 4969 scratch = 0;
sPymbed 0:c4152c628df5 4970 if (ret == 0)
sPymbed 0:c4152c628df5 4971 ret = wc_EccPrivateKeyDecode(ssh->ctx->privateKey, &scratch,
sPymbed 0:c4152c628df5 4972 &sigKeyBlock.sk.ecc.key,
sPymbed 0:c4152c628df5 4973 ssh->ctx->privateKeySz);
sPymbed 0:c4152c628df5 4974 /* Flatten the public key into x963 value for the exchange hash. */
sPymbed 0:c4152c628df5 4975 if (ret == 0)
sPymbed 0:c4152c628df5 4976 ret = wc_ecc_export_x963(&sigKeyBlock.sk.ecc.key,
sPymbed 0:c4152c628df5 4977 sigKeyBlock.sk.ecc.q,
sPymbed 0:c4152c628df5 4978 &sigKeyBlock.sk.ecc.qSz);
sPymbed 0:c4152c628df5 4979 /* Hash in the length of the public key block. */
sPymbed 0:c4152c628df5 4980 if (ret == 0) {
sPymbed 0:c4152c628df5 4981 sigKeyBlock.sz = (LENGTH_SZ * 3) +
sPymbed 0:c4152c628df5 4982 sigKeyBlock.nameSz +
sPymbed 0:c4152c628df5 4983 sigKeyBlock.sk.ecc.primeNameSz +
sPymbed 0:c4152c628df5 4984 sigKeyBlock.sk.ecc.qSz;
sPymbed 0:c4152c628df5 4985 c32toa(sigKeyBlock.sz, scratchLen);
sPymbed 0:c4152c628df5 4986 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4987 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4988 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 4989 }
sPymbed 0:c4152c628df5 4990 /* Hash in the length of the key type string. */
sPymbed 0:c4152c628df5 4991 if (ret == 0) {
sPymbed 0:c4152c628df5 4992 c32toa(sigKeyBlock.nameSz, scratchLen);
sPymbed 0:c4152c628df5 4993 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 4994 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 4995 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 4996 }
sPymbed 0:c4152c628df5 4997 /* Hash in the key type string. */
sPymbed 0:c4152c628df5 4998 if (ret == 0)
sPymbed 0:c4152c628df5 4999 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5000 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5001 (byte*)sigKeyBlock.name,
sPymbed 0:c4152c628df5 5002 sigKeyBlock.nameSz);
sPymbed 0:c4152c628df5 5003 /* Hash in the length of the name of the prime. */
sPymbed 0:c4152c628df5 5004 if (ret == 0) {
sPymbed 0:c4152c628df5 5005 c32toa(sigKeyBlock.sk.ecc.primeNameSz, scratchLen);
sPymbed 0:c4152c628df5 5006 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5007 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5008 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5009 }
sPymbed 0:c4152c628df5 5010 /* Hash in the name of the prime. */
sPymbed 0:c4152c628df5 5011 if (ret == 0)
sPymbed 0:c4152c628df5 5012 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5013 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5014 (const byte*)sigKeyBlock.sk.ecc.primeName,
sPymbed 0:c4152c628df5 5015 sigKeyBlock.sk.ecc.primeNameSz);
sPymbed 0:c4152c628df5 5016 /* Hash in the length of the public key. */
sPymbed 0:c4152c628df5 5017 if (ret == 0) {
sPymbed 0:c4152c628df5 5018 c32toa(sigKeyBlock.sk.ecc.qSz, scratchLen);
sPymbed 0:c4152c628df5 5019 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5020 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5021 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5022 }
sPymbed 0:c4152c628df5 5023 /* Hash in the public key. */
sPymbed 0:c4152c628df5 5024 if (ret == 0)
sPymbed 0:c4152c628df5 5025 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5026 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5027 sigKeyBlock.sk.ecc.q,
sPymbed 0:c4152c628df5 5028 sigKeyBlock.sk.ecc.qSz);
sPymbed 0:c4152c628df5 5029 }
sPymbed 0:c4152c628df5 5030
sPymbed 0:c4152c628df5 5031 /* If using DH-GEX include the GEX specific values. */
sPymbed 0:c4152c628df5 5032 if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {
sPymbed 0:c4152c628df5 5033 byte primeGroupPad = 0, generatorPad = 0;
sPymbed 0:c4152c628df5 5034
sPymbed 0:c4152c628df5 5035 /* Hash in the client's requested minimum key size. */
sPymbed 0:c4152c628df5 5036 if (ret == 0) {
sPymbed 0:c4152c628df5 5037 c32toa(ssh->handshake->dhGexMinSz, scratchLen);
sPymbed 0:c4152c628df5 5038 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5039 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5040 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5041 }
sPymbed 0:c4152c628df5 5042 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(dhGexMinSz) ret=%d", ret);
sPymbed 0:c4152c628df5 5043 /* Hash in the client's requested preferred key size. */
sPymbed 0:c4152c628df5 5044 if (ret == 0) {
sPymbed 0:c4152c628df5 5045 c32toa(ssh->handshake->dhGexPreferredSz, scratchLen);
sPymbed 0:c4152c628df5 5046 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5047 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5048 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5049 }
sPymbed 0:c4152c628df5 5050 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(dhGexPreferredSz) ret=%d", ret);
sPymbed 0:c4152c628df5 5051 /* Hash in the client's requested maximum key size. */
sPymbed 0:c4152c628df5 5052 if (ret == 0) {
sPymbed 0:c4152c628df5 5053 c32toa(ssh->handshake->dhGexMaxSz, scratchLen);
sPymbed 0:c4152c628df5 5054 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5055 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5056 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5057 }
sPymbed 0:c4152c628df5 5058 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(dhGexMaxSz) ret=%d", ret);
sPymbed 0:c4152c628df5 5059 /* Add a pad byte if the mpint has the MSB set. */
sPymbed 0:c4152c628df5 5060 if (ret == 0) {
sPymbed 0:c4152c628df5 5061 if (primeGroup[0] & 0x80)
sPymbed 0:c4152c628df5 5062 primeGroupPad = 1;
sPymbed 0:c4152c628df5 5063
sPymbed 0:c4152c628df5 5064 /* Hash in the length of the GEX prime group. */
sPymbed 0:c4152c628df5 5065 c32toa(primeGroupSz + primeGroupPad, scratchLen);
sPymbed 0:c4152c628df5 5066 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5067 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5068 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5069 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(primeGroupSz + primeGroupPad) ret=%d", ret);
sPymbed 0:c4152c628df5 5070 }
sPymbed 0:c4152c628df5 5071 /* Hash in the pad byte for the GEX prime group. */
sPymbed 0:c4152c628df5 5072 if (ret == 0) {
sPymbed 0:c4152c628df5 5073 if (primeGroupPad) {
sPymbed 0:c4152c628df5 5074 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 5075 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5076 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5077 scratchLen, 1);
sPymbed 0:c4152c628df5 5078 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(primeGroupPad) ret=%d", ret);
sPymbed 0:c4152c628df5 5079 }
sPymbed 0:c4152c628df5 5080 }
sPymbed 0:c4152c628df5 5081 /* Hash in the GEX prime group. */
sPymbed 0:c4152c628df5 5082 if (ret == 0)
sPymbed 0:c4152c628df5 5083 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5084 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5085 primeGroup, primeGroupSz);
sPymbed 0:c4152c628df5 5086 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(hasn in gex prime grp) ret=%d", ret);
sPymbed 0:c4152c628df5 5087 /* Add a pad byte if the mpint has the MSB set. */
sPymbed 0:c4152c628df5 5088 if (ret == 0) {
sPymbed 0:c4152c628df5 5089 if (generator[0] & 0x80)
sPymbed 0:c4152c628df5 5090 generatorPad = 1;
sPymbed 0:c4152c628df5 5091
sPymbed 0:c4152c628df5 5092 /* Hash in the length of the GEX generator. */
sPymbed 0:c4152c628df5 5093 c32toa(generatorSz + generatorPad, scratchLen);
sPymbed 0:c4152c628df5 5094 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5095 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5096 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5097 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(add pad byte) ret=%d", ret);
sPymbed 0:c4152c628df5 5098 }
sPymbed 0:c4152c628df5 5099 /* Hash in the pad byte for the GEX generator. */
sPymbed 0:c4152c628df5 5100 if (ret == 0) {
sPymbed 0:c4152c628df5 5101 if (generatorPad) {
sPymbed 0:c4152c628df5 5102 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 5103 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5104 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5105 scratchLen, 1);
sPymbed 0:c4152c628df5 5106 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(hash in the pad byte for gex gen) ret=%d", ret);
sPymbed 0:c4152c628df5 5107 }
sPymbed 0:c4152c628df5 5108 }
sPymbed 0:c4152c628df5 5109 /* Hash in the GEX generator. */
sPymbed 0:c4152c628df5 5110 if (ret == 0)
sPymbed 0:c4152c628df5 5111 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5112 ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5113 generator, generatorSz);
sPymbed 0:c4152c628df5 5114 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(hash in the gex gen) ret=%d", ret);
sPymbed 0:c4152c628df5 5115 }
sPymbed 0:c4152c628df5 5116
sPymbed 0:c4152c628df5 5117 /* Hash in the size of the client's DH e-value (ECDH Q-value). */
sPymbed 0:c4152c628df5 5118 if (ret == 0) {
sPymbed 0:c4152c628df5 5119 c32toa(ssh->handshake->eSz, scratchLen);
sPymbed 0:c4152c628df5 5120 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5121 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5122 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(client DH e-val size) ret=%d", ret);
sPymbed 0:c4152c628df5 5123 }
sPymbed 0:c4152c628df5 5124 /* Hash in the client's DH e-value (ECDH Q-value). */
sPymbed 0:c4152c628df5 5125 if (ret == 0)
sPymbed 0:c4152c628df5 5126 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5127 ssh->handshake->e, ssh->handshake->eSz);
sPymbed 0:c4152c628df5 5128 //ESP_LOGI("WOLFSSH", "wc_HashUpdate(client DH e-val) ret=%d", ret);
sPymbed 0:c4152c628df5 5129
sPymbed 0:c4152c628df5 5130 /* Make the server's DH f-value and the shared secret K. */
sPymbed 0:c4152c628df5 5131 /* Or make the server's ECDH private value, and the shared secret K. */
sPymbed 0:c4152c628df5 5132 if (ret == 0) {
sPymbed 0:c4152c628df5 5133 if (!useEcc) {
sPymbed 0:c4152c628df5 5134 DhKey privKey;
sPymbed 0:c4152c628df5 5135 byte y[256];
sPymbed 0:c4152c628df5 5136 word32 ySz = sizeof(y);
sPymbed 0:c4152c628df5 5137
sPymbed 0:c4152c628df5 5138 ret = wc_InitDhKey(&privKey);
sPymbed 0:c4152c628df5 5139 //ESP_LOGI("WOLFSSH", "wc_InitDhKey ret=%d", ret);
sPymbed 0:c4152c628df5 5140 if (ret == 0)
sPymbed 0:c4152c628df5 5141 ret = wc_DhSetKey(&privKey, primeGroup, primeGroupSz,
sPymbed 0:c4152c628df5 5142 generator, generatorSz);
sPymbed 0:c4152c628df5 5143 //ESP_LOGI("WOLFSSH", "wc_DhSetKey ret=%d", ret);
sPymbed 0:c4152c628df5 5144 if (ret == 0)
sPymbed 0:c4152c628df5 5145 ret = wc_DhGenerateKeyPair(&privKey, ssh->rng,
sPymbed 0:c4152c628df5 5146 y, &ySz, f, &fSz);
sPymbed 0:c4152c628df5 5147 //ESP_LOGI("WOLFSSH", "wc_DhGenerateKeyPair ret=%d", ret);
sPymbed 0:c4152c628df5 5148 if (ret == 0)
sPymbed 0:c4152c628df5 5149 ret = wc_DhAgree(&privKey, ssh->k, &ssh->kSz, y, ySz,
sPymbed 0:c4152c628df5 5150 ssh->handshake->e, ssh->handshake->eSz);
sPymbed 0:c4152c628df5 5151 //ESP_LOGI("WOLFSSH", "wc_DhAgree ret=%d", ret);
sPymbed 0:c4152c628df5 5152 ForceZero(y, ySz);
sPymbed 0:c4152c628df5 5153 wc_FreeDhKey(&privKey);
sPymbed 0:c4152c628df5 5154 }
sPymbed 0:c4152c628df5 5155 else {
sPymbed 0:c4152c628df5 5156 ecc_key pubKey;
sPymbed 0:c4152c628df5 5157 ecc_key privKey;
sPymbed 0:c4152c628df5 5158 int primeId = wcPrimeForId(ssh->handshake->kexId);
sPymbed 0:c4152c628df5 5159
sPymbed 0:c4152c628df5 5160 if (primeId == ECC_CURVE_INVALID)
sPymbed 0:c4152c628df5 5161 ret = WS_INVALID_PRIME_CURVE;
sPymbed 0:c4152c628df5 5162
sPymbed 0:c4152c628df5 5163 if (ret == 0)
sPymbed 0:c4152c628df5 5164 ret = wc_ecc_init_ex(&pubKey, ssh->ctx->heap,
sPymbed 0:c4152c628df5 5165 INVALID_DEVID);
sPymbed 0:c4152c628df5 5166 if (ret == 0)
sPymbed 0:c4152c628df5 5167 ret = wc_ecc_init_ex(&privKey, ssh->ctx->heap,
sPymbed 0:c4152c628df5 5168 INVALID_DEVID);
sPymbed 0:c4152c628df5 5169
sPymbed 0:c4152c628df5 5170 if (ret == 0)
sPymbed 0:c4152c628df5 5171 ret = wc_ecc_import_x963_ex(ssh->handshake->e,
sPymbed 0:c4152c628df5 5172 ssh->handshake->eSz,
sPymbed 0:c4152c628df5 5173 &pubKey, primeId);
sPymbed 0:c4152c628df5 5174
sPymbed 0:c4152c628df5 5175 if (ret == 0)
sPymbed 0:c4152c628df5 5176 ret = wc_ecc_make_key_ex(ssh->rng,
sPymbed 0:c4152c628df5 5177 wc_ecc_get_curve_size_from_id(primeId),
sPymbed 0:c4152c628df5 5178 &privKey, primeId);
sPymbed 0:c4152c628df5 5179 if (ret == 0)
sPymbed 0:c4152c628df5 5180 ret = wc_ecc_export_x963(&privKey, f, &fSz);
sPymbed 0:c4152c628df5 5181 if (ret == 0)
sPymbed 0:c4152c628df5 5182 ret = wc_ecc_shared_secret(&privKey, &pubKey,
sPymbed 0:c4152c628df5 5183 ssh->k, &ssh->kSz);
sPymbed 0:c4152c628df5 5184 wc_ecc_free(&privKey);
sPymbed 0:c4152c628df5 5185 wc_ecc_free(&pubKey);
sPymbed 0:c4152c628df5 5186 }
sPymbed 0:c4152c628df5 5187 }
sPymbed 0:c4152c628df5 5188
sPymbed 0:c4152c628df5 5189 /* Hash in the server's DH f-value. */
sPymbed 0:c4152c628df5 5190 if (ret == 0) {
sPymbed 0:c4152c628df5 5191 fPad = (f[0] & 0x80) ? 1 : 0;
sPymbed 0:c4152c628df5 5192 c32toa(fSz + fPad, scratchLen);
sPymbed 0:c4152c628df5 5193 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5194 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5195 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5196 }
sPymbed 0:c4152c628df5 5197 if (ret == 0) {
sPymbed 0:c4152c628df5 5198 if (fPad) {
sPymbed 0:c4152c628df5 5199 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 5200 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5201 ssh->handshake->hashId, scratchLen, 1);
sPymbed 0:c4152c628df5 5202 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5203 }
sPymbed 0:c4152c628df5 5204 }
sPymbed 0:c4152c628df5 5205 if (ret == 0)
sPymbed 0:c4152c628df5 5206 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5207 ssh->handshake->hashId, f, fSz);
sPymbed 0:c4152c628df5 5208 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5209
sPymbed 0:c4152c628df5 5210 /* Hash in the shared secret K. */
sPymbed 0:c4152c628df5 5211 if (ret == 0) {
sPymbed 0:c4152c628df5 5212 kPad = (ssh->k[0] & 0x80) ? 1 : 0;
sPymbed 0:c4152c628df5 5213 c32toa(ssh->kSz + kPad, scratchLen);
sPymbed 0:c4152c628df5 5214 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5215 scratchLen, LENGTH_SZ);
sPymbed 0:c4152c628df5 5216 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5217 }
sPymbed 0:c4152c628df5 5218 if (ret == 0) {
sPymbed 0:c4152c628df5 5219 if (kPad) {
sPymbed 0:c4152c628df5 5220 scratchLen[0] = 0;
sPymbed 0:c4152c628df5 5221 ret = wc_HashUpdate(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5222 ssh->handshake->hashId, scratchLen, 1);
sPymbed 0:c4152c628df5 5223 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5224 }
sPymbed 0:c4152c628df5 5225 }
sPymbed 0:c4152c628df5 5226 if (ret == 0)
sPymbed 0:c4152c628df5 5227 ret = wc_HashUpdate(&ssh->handshake->hash, ssh->handshake->hashId,
sPymbed 0:c4152c628df5 5228 ssh->k, ssh->kSz);
sPymbed 0:c4152c628df5 5229 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5230
sPymbed 0:c4152c628df5 5231 /* Save the exchange hash value H, and session ID. */
sPymbed 0:c4152c628df5 5232 if (ret == 0)
sPymbed 0:c4152c628df5 5233 ret = wc_HashFinal(&ssh->handshake->hash,
sPymbed 0:c4152c628df5 5234 ssh->handshake->hashId, ssh->h);
sPymbed 0:c4152c628df5 5235 //ESP_LOGI("WOLFSSH", "wc_HashUpdate ret=%d", ret);
sPymbed 0:c4152c628df5 5236 if (ret == 0) {
sPymbed 0:c4152c628df5 5237 ssh->hSz = wc_HashGetDigestSize(ssh->handshake->hashId);
sPymbed 0:c4152c628df5 5238 if (ssh->sessionIdSz == 0) {
sPymbed 0:c4152c628df5 5239 WMEMCPY(ssh->sessionId, ssh->h, ssh->hSz);
sPymbed 0:c4152c628df5 5240 ssh->sessionIdSz = ssh->hSz;
sPymbed 0:c4152c628df5 5241 }
sPymbed 0:c4152c628df5 5242 }
sPymbed 0:c4152c628df5 5243
sPymbed 0:c4152c628df5 5244 if (ret != WS_SUCCESS)
sPymbed 0:c4152c628df5 5245 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 5246 //ESP_LOGI("WOLFSSH", "overall ret ret=%d", ret);
sPymbed 0:c4152c628df5 5247 }
sPymbed 0:c4152c628df5 5248
sPymbed 0:c4152c628df5 5249 /* Sign h with the server's private key. */
sPymbed 0:c4152c628df5 5250 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5251 wc_HashAlg digestHash;
sPymbed 0:c4152c628df5 5252 byte digest[WC_MAX_DIGEST_SIZE];
sPymbed 0:c4152c628df5 5253 byte sigHashId;
sPymbed 0:c4152c628df5 5254
sPymbed 0:c4152c628df5 5255 sigHashId = HashForId(ssh->handshake->pubKeyId);
sPymbed 0:c4152c628df5 5256
sPymbed 0:c4152c628df5 5257 ret = wc_HashInit(&digestHash, sigHashId);
sPymbed 0:c4152c628df5 5258 if (ret == 0)
sPymbed 0:c4152c628df5 5259 ret = wc_HashUpdate(&digestHash, sigHashId, ssh->h, ssh->hSz);
sPymbed 0:c4152c628df5 5260 if (ret == 0)
sPymbed 0:c4152c628df5 5261 ret = wc_HashFinal(&digestHash, sigHashId, digest);
sPymbed 0:c4152c628df5 5262 if (ret != 0)
sPymbed 0:c4152c628df5 5263 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 5264
sPymbed 0:c4152c628df5 5265 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5266 if (sigKeyBlock.useRsa) {
sPymbed 0:c4152c628df5 5267 byte encSig[MAX_ENCODED_SIG_SZ];
sPymbed 0:c4152c628df5 5268 word32 encSigSz;
sPymbed 0:c4152c628df5 5269
sPymbed 0:c4152c628df5 5270 encSigSz = wc_EncodeSignature(encSig, digest,
sPymbed 0:c4152c628df5 5271 wc_HashGetDigestSize(sigHashId),
sPymbed 0:c4152c628df5 5272 wc_HashGetOID(sigHashId));
sPymbed 0:c4152c628df5 5273 if (encSigSz <= 0) {
sPymbed 0:c4152c628df5 5274 WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad Encode Sig");
sPymbed 0:c4152c628df5 5275 ret = WS_CRYPTO_FAILED;
sPymbed 0:c4152c628df5 5276 }
sPymbed 0:c4152c628df5 5277 else {
sPymbed 0:c4152c628df5 5278 WLOG(WS_LOG_INFO, "Signing hash with RSA.");
sPymbed 0:c4152c628df5 5279 sigSz = wc_RsaSSL_Sign(encSig, encSigSz, sig, sizeof(sig),
sPymbed 0:c4152c628df5 5280 &sigKeyBlock.sk.rsa.key, ssh->rng);
sPymbed 0:c4152c628df5 5281 if (sigSz <= 0) {
sPymbed 0:c4152c628df5 5282 WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad RSA Sign");
sPymbed 0:c4152c628df5 5283 ret = WS_RSA_E;
sPymbed 0:c4152c628df5 5284 }
sPymbed 0:c4152c628df5 5285 }
sPymbed 0:c4152c628df5 5286 }
sPymbed 0:c4152c628df5 5287 else {
sPymbed 0:c4152c628df5 5288 WLOG(WS_LOG_INFO, "Signing hash with ECDSA.");
sPymbed 0:c4152c628df5 5289 sigSz = sizeof(sig);
sPymbed 0:c4152c628df5 5290 ret = wc_ecc_sign_hash(digest, wc_HashGetDigestSize(sigHashId),
sPymbed 0:c4152c628df5 5291 sig, &sigSz,
sPymbed 0:c4152c628df5 5292 ssh->rng, &sigKeyBlock.sk.ecc.key);
sPymbed 0:c4152c628df5 5293 if (ret != MP_OKAY) {
sPymbed 0:c4152c628df5 5294 WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad ECDSA Sign");
sPymbed 0:c4152c628df5 5295 ret = WS_ECC_E;
sPymbed 0:c4152c628df5 5296 }
sPymbed 0:c4152c628df5 5297 else {
sPymbed 0:c4152c628df5 5298 byte r[257];
sPymbed 0:c4152c628df5 5299 word32 rSz = sizeof(r);
sPymbed 0:c4152c628df5 5300 byte rPad;
sPymbed 0:c4152c628df5 5301 byte s[257];
sPymbed 0:c4152c628df5 5302 word32 sSz = sizeof(s);
sPymbed 0:c4152c628df5 5303 byte sPad;
sPymbed 0:c4152c628df5 5304
sPymbed 0:c4152c628df5 5305 ret = wc_ecc_sig_to_rs(sig, sigSz, r, &rSz, s, &sSz);
sPymbed 0:c4152c628df5 5306 if (ret == 0) {
sPymbed 0:c4152c628df5 5307 idx = 0;
sPymbed 0:c4152c628df5 5308 rPad = (r[0] & 0x80) ? 1 : 0;
sPymbed 0:c4152c628df5 5309 sPad = (s[0] & 0x80) ? 1 : 0;
sPymbed 0:c4152c628df5 5310 sigSz = (LENGTH_SZ * 2) + rSz + rPad + sSz + sPad;
sPymbed 0:c4152c628df5 5311
sPymbed 0:c4152c628df5 5312 c32toa(rSz + rPad, sig + idx);
sPymbed 0:c4152c628df5 5313 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5314 if (rPad)
sPymbed 0:c4152c628df5 5315 sig[idx++] = 0;
sPymbed 0:c4152c628df5 5316 WMEMCPY(sig + idx, r, rSz);
sPymbed 0:c4152c628df5 5317 idx += rSz;
sPymbed 0:c4152c628df5 5318 c32toa(sSz + sPad, sig + idx);
sPymbed 0:c4152c628df5 5319 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5320 if (sPad)
sPymbed 0:c4152c628df5 5321 sig[idx++] = 0;
sPymbed 0:c4152c628df5 5322 WMEMCPY(sig + idx, s, sSz);
sPymbed 0:c4152c628df5 5323 }
sPymbed 0:c4152c628df5 5324 }
sPymbed 0:c4152c628df5 5325 }
sPymbed 0:c4152c628df5 5326 }
sPymbed 0:c4152c628df5 5327 }
sPymbed 0:c4152c628df5 5328
sPymbed 0:c4152c628df5 5329 //ESP_LOGI("WOLFSSH", "Here??? %d", ret);
sPymbed 0:c4152c628df5 5330
sPymbed 0:c4152c628df5 5331 if (sigKeyBlock.useRsa)
sPymbed 0:c4152c628df5 5332 wc_FreeRsaKey(&sigKeyBlock.sk.rsa.key);
sPymbed 0:c4152c628df5 5333 else
sPymbed 0:c4152c628df5 5334 wc_ecc_free(&sigKeyBlock.sk.ecc.key);
sPymbed 0:c4152c628df5 5335
sPymbed 0:c4152c628df5 5336 sigBlockSz = (LENGTH_SZ * 2) + sigKeyBlock.nameSz + sigSz;
sPymbed 0:c4152c628df5 5337
sPymbed 0:c4152c628df5 5338 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5339 ret = GenerateKeys(ssh);
sPymbed 0:c4152c628df5 5340
sPymbed 0:c4152c628df5 5341 /* Get the buffer, copy the packet data, once f is laid into the buffer,
sPymbed 0:c4152c628df5 5342 * add it to the hash and then add K. */
sPymbed 0:c4152c628df5 5343 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5344 payloadSz = MSG_ID_SZ + (LENGTH_SZ * 3) +
sPymbed 0:c4152c628df5 5345 sigKeyBlock.sz + fSz + fPad + sigBlockSz;
sPymbed 0:c4152c628df5 5346 ret = PreparePacket(ssh, payloadSz);
sPymbed 0:c4152c628df5 5347 }
sPymbed 0:c4152c628df5 5348
sPymbed 0:c4152c628df5 5349 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5350 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5351 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5352
sPymbed 0:c4152c628df5 5353 output[idx++] = msgId;
sPymbed 0:c4152c628df5 5354
sPymbed 0:c4152c628df5 5355 /* Copy the rsaKeyBlock into the buffer. */
sPymbed 0:c4152c628df5 5356 c32toa(sigKeyBlock.sz, output + idx);
sPymbed 0:c4152c628df5 5357 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5358 c32toa(sigKeyBlock.nameSz, output + idx);
sPymbed 0:c4152c628df5 5359 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5360 WMEMCPY(output + idx, sigKeyBlock.name, sigKeyBlock.nameSz);
sPymbed 0:c4152c628df5 5361 idx += sigKeyBlock.nameSz;
sPymbed 0:c4152c628df5 5362 if (sigKeyBlock.useRsa) {
sPymbed 0:c4152c628df5 5363 c32toa(sigKeyBlock.sk.rsa.eSz + sigKeyBlock.sk.rsa.ePad,
sPymbed 0:c4152c628df5 5364 output + idx);
sPymbed 0:c4152c628df5 5365 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5366 if (sigKeyBlock.sk.rsa.ePad) output[idx++] = 0;
sPymbed 0:c4152c628df5 5367 WMEMCPY(output + idx, sigKeyBlock.sk.rsa.e, sigKeyBlock.sk.rsa.eSz);
sPymbed 0:c4152c628df5 5368 idx += sigKeyBlock.sk.rsa.eSz;
sPymbed 0:c4152c628df5 5369 c32toa(sigKeyBlock.sk.rsa.nSz + sigKeyBlock.sk.rsa.nPad,
sPymbed 0:c4152c628df5 5370 output + idx);
sPymbed 0:c4152c628df5 5371 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5372 if (sigKeyBlock.sk.rsa.nPad) output[idx++] = 0;
sPymbed 0:c4152c628df5 5373 WMEMCPY(output + idx, sigKeyBlock.sk.rsa.n, sigKeyBlock.sk.rsa.nSz);
sPymbed 0:c4152c628df5 5374 idx += sigKeyBlock.sk.rsa.nSz;
sPymbed 0:c4152c628df5 5375 }
sPymbed 0:c4152c628df5 5376 else {
sPymbed 0:c4152c628df5 5377 c32toa(sigKeyBlock.sk.ecc.primeNameSz, output + idx);
sPymbed 0:c4152c628df5 5378 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5379 WMEMCPY(output + idx, sigKeyBlock.sk.ecc.primeName,
sPymbed 0:c4152c628df5 5380 sigKeyBlock.sk.ecc.primeNameSz);
sPymbed 0:c4152c628df5 5381 idx += sigKeyBlock.sk.ecc.primeNameSz;
sPymbed 0:c4152c628df5 5382 c32toa(sigKeyBlock.sk.ecc.qSz, output + idx);
sPymbed 0:c4152c628df5 5383 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5384 WMEMCPY(output + idx, sigKeyBlock.sk.ecc.q,
sPymbed 0:c4152c628df5 5385 sigKeyBlock.sk.ecc.qSz);
sPymbed 0:c4152c628df5 5386 idx += sigKeyBlock.sk.ecc.qSz;
sPymbed 0:c4152c628df5 5387 }
sPymbed 0:c4152c628df5 5388
sPymbed 0:c4152c628df5 5389 /* Copy the server's public key. F for DE, or Q_S for ECDH. */
sPymbed 0:c4152c628df5 5390 c32toa(fSz + fPad, output + idx);
sPymbed 0:c4152c628df5 5391 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5392 if (fPad) output[idx++] = 0;
sPymbed 0:c4152c628df5 5393 WMEMCPY(output + idx, f, fSz);
sPymbed 0:c4152c628df5 5394 idx += fSz;
sPymbed 0:c4152c628df5 5395
sPymbed 0:c4152c628df5 5396 /* Copy the signature of the exchange hash. */
sPymbed 0:c4152c628df5 5397 c32toa(sigBlockSz, output + idx);
sPymbed 0:c4152c628df5 5398 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5399 c32toa(sigKeyBlock.nameSz, output + idx);
sPymbed 0:c4152c628df5 5400 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5401 WMEMCPY(output + idx, sigKeyBlock.name, sigKeyBlock.nameSz);
sPymbed 0:c4152c628df5 5402 idx += sigKeyBlock.nameSz;
sPymbed 0:c4152c628df5 5403 c32toa(sigSz, output + idx);
sPymbed 0:c4152c628df5 5404 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5405 WMEMCPY(output + idx, sig, sigSz);
sPymbed 0:c4152c628df5 5406 idx += sigSz;
sPymbed 0:c4152c628df5 5407
sPymbed 0:c4152c628df5 5408 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5409
sPymbed 0:c4152c628df5 5410 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5411 }
sPymbed 0:c4152c628df5 5412
sPymbed 0:c4152c628df5 5413 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5414 ret = SendNewKeys(ssh);
sPymbed 0:c4152c628df5 5415
sPymbed 0:c4152c628df5 5416 WLOG(WS_LOG_DEBUG, "Leaving SendKexDhReply(), ret = %d", ret);
sPymbed 0:c4152c628df5 5417 return ret;
sPymbed 0:c4152c628df5 5418 }
sPymbed 0:c4152c628df5 5419
sPymbed 0:c4152c628df5 5420
sPymbed 0:c4152c628df5 5421 int SendNewKeys(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 5422 {
sPymbed 0:c4152c628df5 5423 byte* output;
sPymbed 0:c4152c628df5 5424 word32 idx = 0;
sPymbed 0:c4152c628df5 5425 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5426
sPymbed 0:c4152c628df5 5427 WLOG(WS_LOG_DEBUG, "Entering SendNewKeys()");
sPymbed 0:c4152c628df5 5428 if (ssh == NULL)
sPymbed 0:c4152c628df5 5429 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5430
sPymbed 0:c4152c628df5 5431 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5432 ret = PreparePacket(ssh, MSG_ID_SZ);
sPymbed 0:c4152c628df5 5433
sPymbed 0:c4152c628df5 5434 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5435 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5436 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5437
sPymbed 0:c4152c628df5 5438 output[idx++] = MSGID_NEWKEYS;
sPymbed 0:c4152c628df5 5439
sPymbed 0:c4152c628df5 5440 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5441
sPymbed 0:c4152c628df5 5442 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5443 }
sPymbed 0:c4152c628df5 5444
sPymbed 0:c4152c628df5 5445 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5446 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5447
sPymbed 0:c4152c628df5 5448 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5449 ssh->blockSz = ssh->handshake->blockSz;
sPymbed 0:c4152c628df5 5450 ssh->encryptId = ssh->handshake->encryptId;
sPymbed 0:c4152c628df5 5451 ssh->macSz = ssh->handshake->macSz;
sPymbed 0:c4152c628df5 5452 ssh->macId = ssh->handshake->macId;
sPymbed 0:c4152c628df5 5453 ssh->aeadMode = ssh->handshake->aeadMode;
sPymbed 0:c4152c628df5 5454 WMEMCPY(&ssh->keys, &ssh->handshake->keys, sizeof(Keys));
sPymbed 0:c4152c628df5 5455
sPymbed 0:c4152c628df5 5456 switch (ssh->encryptId) {
sPymbed 0:c4152c628df5 5457 case ID_NONE:
sPymbed 0:c4152c628df5 5458 WLOG(WS_LOG_DEBUG, "SNK: using cipher none");
sPymbed 0:c4152c628df5 5459 break;
sPymbed 0:c4152c628df5 5460
sPymbed 0:c4152c628df5 5461 case ID_AES128_CBC:
sPymbed 0:c4152c628df5 5462 WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-cbc");
sPymbed 0:c4152c628df5 5463 ret = wc_AesSetKey(&ssh->encryptCipher.aes,
sPymbed 0:c4152c628df5 5464 ssh->keys.encKey, ssh->keys.encKeySz,
sPymbed 0:c4152c628df5 5465 ssh->keys.iv, AES_ENCRYPTION);
sPymbed 0:c4152c628df5 5466 break;
sPymbed 0:c4152c628df5 5467
sPymbed 0:c4152c628df5 5468 case ID_AES128_GCM:
sPymbed 0:c4152c628df5 5469 WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-gcm");
sPymbed 0:c4152c628df5 5470 ret = wc_AesGcmSetKey(&ssh->encryptCipher.aes,
sPymbed 0:c4152c628df5 5471 ssh->keys.encKey, ssh->keys.encKeySz);
sPymbed 0:c4152c628df5 5472 break;
sPymbed 0:c4152c628df5 5473
sPymbed 0:c4152c628df5 5474 default:
sPymbed 0:c4152c628df5 5475 WLOG(WS_LOG_DEBUG, "SNK: using cipher invalid");
sPymbed 0:c4152c628df5 5476 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 5477 }
sPymbed 0:c4152c628df5 5478 }
sPymbed 0:c4152c628df5 5479
sPymbed 0:c4152c628df5 5480 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5481 ssh->txCount = 0;
sPymbed 0:c4152c628df5 5482 }
sPymbed 0:c4152c628df5 5483
sPymbed 0:c4152c628df5 5484 WLOG(WS_LOG_DEBUG, "Leaving SendNewKeys(), ret = %d", ret);
sPymbed 0:c4152c628df5 5485 return ret;
sPymbed 0:c4152c628df5 5486 }
sPymbed 0:c4152c628df5 5487
sPymbed 0:c4152c628df5 5488
sPymbed 0:c4152c628df5 5489 int SendKexDhGexRequest(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 5490 {
sPymbed 0:c4152c628df5 5491 byte* output;
sPymbed 0:c4152c628df5 5492 word32 idx = 0;
sPymbed 0:c4152c628df5 5493 word32 payloadSz;
sPymbed 0:c4152c628df5 5494 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5495
sPymbed 0:c4152c628df5 5496 WLOG(WS_LOG_DEBUG, "Entering SendKexDhGexRequest()");
sPymbed 0:c4152c628df5 5497 if (ssh == NULL)
sPymbed 0:c4152c628df5 5498 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5499
sPymbed 0:c4152c628df5 5500 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5501 payloadSz = MSG_ID_SZ + (UINT32_SZ * 3);
sPymbed 0:c4152c628df5 5502 ret = PreparePacket(ssh, payloadSz);
sPymbed 0:c4152c628df5 5503 }
sPymbed 0:c4152c628df5 5504
sPymbed 0:c4152c628df5 5505 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5506 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5507 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5508
sPymbed 0:c4152c628df5 5509 output[idx++] = MSGID_KEXDH_GEX_REQUEST;
sPymbed 0:c4152c628df5 5510
sPymbed 0:c4152c628df5 5511 c32toa(ssh->handshake->dhGexMinSz, output + idx);
sPymbed 0:c4152c628df5 5512 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 5513 c32toa(ssh->handshake->dhGexPreferredSz, output + idx);
sPymbed 0:c4152c628df5 5514 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 5515 c32toa(ssh->handshake->dhGexMaxSz, output + idx);
sPymbed 0:c4152c628df5 5516 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 5517
sPymbed 0:c4152c628df5 5518 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5519
sPymbed 0:c4152c628df5 5520 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5521 }
sPymbed 0:c4152c628df5 5522
sPymbed 0:c4152c628df5 5523 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5524 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5525
sPymbed 0:c4152c628df5 5526 WLOG(WS_LOG_DEBUG, "Leaving SendKexDhGexRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 5527 return ret;
sPymbed 0:c4152c628df5 5528 }
sPymbed 0:c4152c628df5 5529
sPymbed 0:c4152c628df5 5530
sPymbed 0:c4152c628df5 5531 int SendKexDhGexGroup(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 5532 {
sPymbed 0:c4152c628df5 5533 byte* output;
sPymbed 0:c4152c628df5 5534 word32 idx = 0;
sPymbed 0:c4152c628df5 5535 word32 payloadSz;
sPymbed 0:c4152c628df5 5536 const byte* primeGroup = dhPrimeGroup14;
sPymbed 0:c4152c628df5 5537 word32 primeGroupSz = dhPrimeGroup14Sz;
sPymbed 0:c4152c628df5 5538 const byte* generator = dhGenerator;
sPymbed 0:c4152c628df5 5539 word32 generatorSz = dhGeneratorSz;
sPymbed 0:c4152c628df5 5540 byte primePad = 0;
sPymbed 0:c4152c628df5 5541 byte generatorPad = 0;
sPymbed 0:c4152c628df5 5542 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5543
sPymbed 0:c4152c628df5 5544 WLOG(WS_LOG_DEBUG, "Entering SendKexDhGexGroup()");
sPymbed 0:c4152c628df5 5545 if (ssh == NULL)
sPymbed 0:c4152c628df5 5546 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5547
sPymbed 0:c4152c628df5 5548 if (primeGroup[0] & 0x80)
sPymbed 0:c4152c628df5 5549 primePad = 1;
sPymbed 0:c4152c628df5 5550
sPymbed 0:c4152c628df5 5551 if (generator[0] & 0x80)
sPymbed 0:c4152c628df5 5552 generatorPad = 1;
sPymbed 0:c4152c628df5 5553
sPymbed 0:c4152c628df5 5554 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5555 payloadSz = MSG_ID_SZ + (LENGTH_SZ * 2) +
sPymbed 0:c4152c628df5 5556 primeGroupSz + primePad +
sPymbed 0:c4152c628df5 5557 generatorSz + generatorPad;
sPymbed 0:c4152c628df5 5558 ret = PreparePacket(ssh, payloadSz);
sPymbed 0:c4152c628df5 5559 }
sPymbed 0:c4152c628df5 5560
sPymbed 0:c4152c628df5 5561 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5562 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5563 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5564
sPymbed 0:c4152c628df5 5565 output[idx++] = MSGID_KEXDH_GEX_GROUP;
sPymbed 0:c4152c628df5 5566
sPymbed 0:c4152c628df5 5567 c32toa(primeGroupSz + primePad, output + idx);
sPymbed 0:c4152c628df5 5568 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5569
sPymbed 0:c4152c628df5 5570 if (primePad) {
sPymbed 0:c4152c628df5 5571 output[idx] = 0;
sPymbed 0:c4152c628df5 5572 idx += 1;
sPymbed 0:c4152c628df5 5573 }
sPymbed 0:c4152c628df5 5574
sPymbed 0:c4152c628df5 5575 WMEMCPY(output + idx, primeGroup, primeGroupSz);
sPymbed 0:c4152c628df5 5576 idx += primeGroupSz;
sPymbed 0:c4152c628df5 5577
sPymbed 0:c4152c628df5 5578 c32toa(generatorSz + generatorPad, output + idx);
sPymbed 0:c4152c628df5 5579 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5580
sPymbed 0:c4152c628df5 5581 if (generatorPad) {
sPymbed 0:c4152c628df5 5582 output[idx] = 0;
sPymbed 0:c4152c628df5 5583 idx += 1;
sPymbed 0:c4152c628df5 5584 }
sPymbed 0:c4152c628df5 5585
sPymbed 0:c4152c628df5 5586 WMEMCPY(output + idx, generator, generatorSz);
sPymbed 0:c4152c628df5 5587 idx += generatorSz;
sPymbed 0:c4152c628df5 5588
sPymbed 0:c4152c628df5 5589 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5590
sPymbed 0:c4152c628df5 5591 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5592 }
sPymbed 0:c4152c628df5 5593
sPymbed 0:c4152c628df5 5594 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5595 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5596
sPymbed 0:c4152c628df5 5597 WLOG(WS_LOG_DEBUG, "Leaving SendKexDhGexGroup(), ret = %d", ret);
sPymbed 0:c4152c628df5 5598 return ret;
sPymbed 0:c4152c628df5 5599 }
sPymbed 0:c4152c628df5 5600
sPymbed 0:c4152c628df5 5601
sPymbed 0:c4152c628df5 5602 int SendKexDhInit(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 5603 {
sPymbed 0:c4152c628df5 5604 byte* output;
sPymbed 0:c4152c628df5 5605 word32 idx = 0;
sPymbed 0:c4152c628df5 5606 word32 payloadSz;
sPymbed 0:c4152c628df5 5607 const byte* primeGroup = dhPrimeGroup14;
sPymbed 0:c4152c628df5 5608 word32 primeGroupSz = dhPrimeGroup14Sz;
sPymbed 0:c4152c628df5 5609 const byte* generator = dhGenerator;
sPymbed 0:c4152c628df5 5610 word32 generatorSz = dhGeneratorSz;
sPymbed 0:c4152c628df5 5611 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5612 byte msgId = MSGID_KEXDH_INIT;
sPymbed 0:c4152c628df5 5613 byte e[256];
sPymbed 0:c4152c628df5 5614 word32 eSz = sizeof(e);
sPymbed 0:c4152c628df5 5615 byte ePad = 0;
sPymbed 0:c4152c628df5 5616
sPymbed 0:c4152c628df5 5617 WLOG(WS_LOG_DEBUG, "Entering SendKexDhInit()");
sPymbed 0:c4152c628df5 5618
sPymbed 0:c4152c628df5 5619 switch (ssh->handshake->kexId) {
sPymbed 0:c4152c628df5 5620 case ID_DH_GROUP1_SHA1:
sPymbed 0:c4152c628df5 5621 primeGroup = dhPrimeGroup1;
sPymbed 0:c4152c628df5 5622 primeGroupSz = dhPrimeGroup1Sz;
sPymbed 0:c4152c628df5 5623 break;
sPymbed 0:c4152c628df5 5624
sPymbed 0:c4152c628df5 5625 case ID_DH_GROUP14_SHA1:
sPymbed 0:c4152c628df5 5626 /* This is the default case. */
sPymbed 0:c4152c628df5 5627 break;
sPymbed 0:c4152c628df5 5628
sPymbed 0:c4152c628df5 5629 case ID_DH_GEX_SHA256:
sPymbed 0:c4152c628df5 5630 primeGroup = ssh->handshake->primeGroup;
sPymbed 0:c4152c628df5 5631 primeGroupSz = ssh->handshake->primeGroupSz;
sPymbed 0:c4152c628df5 5632 generator = ssh->handshake->generator;
sPymbed 0:c4152c628df5 5633 generatorSz = ssh->handshake->generatorSz;
sPymbed 0:c4152c628df5 5634 msgId = MSGID_KEXDH_GEX_INIT;
sPymbed 0:c4152c628df5 5635 break;
sPymbed 0:c4152c628df5 5636
sPymbed 0:c4152c628df5 5637 case ID_ECDH_SHA2_NISTP256:
sPymbed 0:c4152c628df5 5638 case ID_ECDH_SHA2_NISTP384:
sPymbed 0:c4152c628df5 5639 case ID_ECDH_SHA2_NISTP521:
sPymbed 0:c4152c628df5 5640 ssh->handshake->useEcc = 1;
sPymbed 0:c4152c628df5 5641 msgId = MSGID_KEXECDH_INIT;
sPymbed 0:c4152c628df5 5642 break;
sPymbed 0:c4152c628df5 5643
sPymbed 0:c4152c628df5 5644 default:
sPymbed 0:c4152c628df5 5645 WLOG(WS_LOG_DEBUG, "Invalid algo: %u", ssh->handshake->kexId);
sPymbed 0:c4152c628df5 5646 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 5647 }
sPymbed 0:c4152c628df5 5648
sPymbed 0:c4152c628df5 5649
sPymbed 0:c4152c628df5 5650 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5651 if (!ssh->handshake->useEcc) {
sPymbed 0:c4152c628df5 5652 DhKey* privKey = &ssh->handshake->privKey.dh;
sPymbed 0:c4152c628df5 5653
sPymbed 0:c4152c628df5 5654 ret = wc_InitDhKey(privKey);
sPymbed 0:c4152c628df5 5655 if (ret == 0)
sPymbed 0:c4152c628df5 5656 ret = wc_DhSetKey(privKey, primeGroup, primeGroupSz,
sPymbed 0:c4152c628df5 5657 generator, generatorSz);
sPymbed 0:c4152c628df5 5658 if (ret == 0)
sPymbed 0:c4152c628df5 5659 ret = wc_DhGenerateKeyPair(privKey, ssh->rng,
sPymbed 0:c4152c628df5 5660 ssh->handshake->x,
sPymbed 0:c4152c628df5 5661 &ssh->handshake->xSz,
sPymbed 0:c4152c628df5 5662 e, &eSz);
sPymbed 0:c4152c628df5 5663 }
sPymbed 0:c4152c628df5 5664 else {
sPymbed 0:c4152c628df5 5665 ecc_key* privKey = &ssh->handshake->privKey.ecc;
sPymbed 0:c4152c628df5 5666 int primeId = wcPrimeForId(ssh->handshake->kexId);
sPymbed 0:c4152c628df5 5667
sPymbed 0:c4152c628df5 5668 if (primeId == ECC_CURVE_INVALID)
sPymbed 0:c4152c628df5 5669 ret = WS_INVALID_PRIME_CURVE;
sPymbed 0:c4152c628df5 5670
sPymbed 0:c4152c628df5 5671 if (ret == 0)
sPymbed 0:c4152c628df5 5672 ret = wc_ecc_init_ex(privKey, ssh->ctx->heap,
sPymbed 0:c4152c628df5 5673 INVALID_DEVID);
sPymbed 0:c4152c628df5 5674
sPymbed 0:c4152c628df5 5675 if (ret == 0)
sPymbed 0:c4152c628df5 5676 ret = wc_ecc_make_key_ex(ssh->rng,
sPymbed 0:c4152c628df5 5677 wc_ecc_get_curve_size_from_id(primeId),
sPymbed 0:c4152c628df5 5678 privKey, primeId);
sPymbed 0:c4152c628df5 5679 if (ret == 0)
sPymbed 0:c4152c628df5 5680 ret = wc_ecc_export_x963(privKey, e, &eSz);
sPymbed 0:c4152c628df5 5681 }
sPymbed 0:c4152c628df5 5682
sPymbed 0:c4152c628df5 5683 if (ret == 0)
sPymbed 0:c4152c628df5 5684 ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5685 }
sPymbed 0:c4152c628df5 5686
sPymbed 0:c4152c628df5 5687 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5688 if (e[0] & 0x80) {
sPymbed 0:c4152c628df5 5689 ePad = 1;
sPymbed 0:c4152c628df5 5690 ssh->handshake->e[0] = 0;
sPymbed 0:c4152c628df5 5691 }
sPymbed 0:c4152c628df5 5692 WMEMCPY(ssh->handshake->e + ePad, e, eSz);
sPymbed 0:c4152c628df5 5693 ssh->handshake->eSz = eSz + ePad;
sPymbed 0:c4152c628df5 5694
sPymbed 0:c4152c628df5 5695 payloadSz = MSG_ID_SZ + LENGTH_SZ + eSz + ePad;
sPymbed 0:c4152c628df5 5696 ret = PreparePacket(ssh, payloadSz);
sPymbed 0:c4152c628df5 5697 }
sPymbed 0:c4152c628df5 5698
sPymbed 0:c4152c628df5 5699 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5700 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5701 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5702
sPymbed 0:c4152c628df5 5703 output[idx++] = msgId;
sPymbed 0:c4152c628df5 5704
sPymbed 0:c4152c628df5 5705 c32toa(eSz + ePad, output + idx);
sPymbed 0:c4152c628df5 5706 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5707
sPymbed 0:c4152c628df5 5708 if (ePad) {
sPymbed 0:c4152c628df5 5709 output[idx] = 0;
sPymbed 0:c4152c628df5 5710 idx += 1;
sPymbed 0:c4152c628df5 5711 }
sPymbed 0:c4152c628df5 5712
sPymbed 0:c4152c628df5 5713 WMEMCPY(output + idx, e, eSz);
sPymbed 0:c4152c628df5 5714 idx += eSz;
sPymbed 0:c4152c628df5 5715
sPymbed 0:c4152c628df5 5716 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5717
sPymbed 0:c4152c628df5 5718 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5719 }
sPymbed 0:c4152c628df5 5720
sPymbed 0:c4152c628df5 5721 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5722 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5723
sPymbed 0:c4152c628df5 5724 WLOG(WS_LOG_DEBUG, "Leaving SendKexDhInit(), ret = %d", ret);
sPymbed 0:c4152c628df5 5725 return ret;
sPymbed 0:c4152c628df5 5726 }
sPymbed 0:c4152c628df5 5727
sPymbed 0:c4152c628df5 5728
sPymbed 0:c4152c628df5 5729 int SendUnimplemented(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 5730 {
sPymbed 0:c4152c628df5 5731 byte* output;
sPymbed 0:c4152c628df5 5732 word32 idx = 0;
sPymbed 0:c4152c628df5 5733 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5734
sPymbed 0:c4152c628df5 5735 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 5736 "Entering SendUnimplemented(), peerSeq = %u", ssh->peerSeq);
sPymbed 0:c4152c628df5 5737
sPymbed 0:c4152c628df5 5738 if (ssh == NULL)
sPymbed 0:c4152c628df5 5739 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5740
sPymbed 0:c4152c628df5 5741 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5742 ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ);
sPymbed 0:c4152c628df5 5743
sPymbed 0:c4152c628df5 5744 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5745 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5746 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5747
sPymbed 0:c4152c628df5 5748 output[idx++] = MSGID_UNIMPLEMENTED;
sPymbed 0:c4152c628df5 5749 c32toa(ssh->peerSeq, output + idx);
sPymbed 0:c4152c628df5 5750 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 5751
sPymbed 0:c4152c628df5 5752 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5753
sPymbed 0:c4152c628df5 5754 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5755 }
sPymbed 0:c4152c628df5 5756
sPymbed 0:c4152c628df5 5757 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5758 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5759
sPymbed 0:c4152c628df5 5760 WLOG(WS_LOG_DEBUG, "Leaving SendUnimplemented(), ret = %d", ret);
sPymbed 0:c4152c628df5 5761 return ret;
sPymbed 0:c4152c628df5 5762 }
sPymbed 0:c4152c628df5 5763
sPymbed 0:c4152c628df5 5764
sPymbed 0:c4152c628df5 5765 int SendDisconnect(WOLFSSH* ssh, word32 reason)
sPymbed 0:c4152c628df5 5766 {
sPymbed 0:c4152c628df5 5767 byte* output;
sPymbed 0:c4152c628df5 5768 word32 idx = 0;
sPymbed 0:c4152c628df5 5769 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5770
sPymbed 0:c4152c628df5 5771 if (ssh == NULL)
sPymbed 0:c4152c628df5 5772 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5773
sPymbed 0:c4152c628df5 5774 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5775 ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + (LENGTH_SZ * 2));
sPymbed 0:c4152c628df5 5776
sPymbed 0:c4152c628df5 5777 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5778 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5779 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5780
sPymbed 0:c4152c628df5 5781 output[idx++] = MSGID_DISCONNECT;
sPymbed 0:c4152c628df5 5782 c32toa(reason, output + idx);
sPymbed 0:c4152c628df5 5783 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 5784 c32toa(0, output + idx);
sPymbed 0:c4152c628df5 5785 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5786 c32toa(0, output + idx);
sPymbed 0:c4152c628df5 5787 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5788
sPymbed 0:c4152c628df5 5789 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5790
sPymbed 0:c4152c628df5 5791 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5792 }
sPymbed 0:c4152c628df5 5793
sPymbed 0:c4152c628df5 5794 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5795 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5796
sPymbed 0:c4152c628df5 5797 return ret;
sPymbed 0:c4152c628df5 5798 }
sPymbed 0:c4152c628df5 5799
sPymbed 0:c4152c628df5 5800
sPymbed 0:c4152c628df5 5801 int SendIgnore(WOLFSSH* ssh, const unsigned char* data, word32 dataSz)
sPymbed 0:c4152c628df5 5802 {
sPymbed 0:c4152c628df5 5803 byte* output;
sPymbed 0:c4152c628df5 5804 word32 idx = 0;
sPymbed 0:c4152c628df5 5805 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5806
sPymbed 0:c4152c628df5 5807 if (ssh == NULL || (data == NULL && dataSz > 0))
sPymbed 0:c4152c628df5 5808 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5809
sPymbed 0:c4152c628df5 5810 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5811 ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + dataSz);
sPymbed 0:c4152c628df5 5812
sPymbed 0:c4152c628df5 5813 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5814 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5815 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5816
sPymbed 0:c4152c628df5 5817 output[idx++] = MSGID_IGNORE;
sPymbed 0:c4152c628df5 5818 c32toa(dataSz, output + idx);
sPymbed 0:c4152c628df5 5819 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5820 if (dataSz > 0) {
sPymbed 0:c4152c628df5 5821 WMEMCPY(output + idx, data, dataSz);
sPymbed 0:c4152c628df5 5822 idx += dataSz;
sPymbed 0:c4152c628df5 5823 }
sPymbed 0:c4152c628df5 5824
sPymbed 0:c4152c628df5 5825 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5826
sPymbed 0:c4152c628df5 5827 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5828 }
sPymbed 0:c4152c628df5 5829
sPymbed 0:c4152c628df5 5830 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5831 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5832
sPymbed 0:c4152c628df5 5833 return ret;
sPymbed 0:c4152c628df5 5834 }
sPymbed 0:c4152c628df5 5835
sPymbed 0:c4152c628df5 5836
sPymbed 0:c4152c628df5 5837 static const char cannedLangTag[] = "en-us";
sPymbed 0:c4152c628df5 5838 static const word32 cannedLangTagSz = sizeof(cannedLangTag) - 1;
sPymbed 0:c4152c628df5 5839
sPymbed 0:c4152c628df5 5840
sPymbed 0:c4152c628df5 5841 int SendDebug(WOLFSSH* ssh, byte alwaysDisplay, const char* msg)
sPymbed 0:c4152c628df5 5842 {
sPymbed 0:c4152c628df5 5843 word32 msgSz;
sPymbed 0:c4152c628df5 5844 byte* output;
sPymbed 0:c4152c628df5 5845 word32 idx = 0;
sPymbed 0:c4152c628df5 5846 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5847
sPymbed 0:c4152c628df5 5848 if (ssh == NULL)
sPymbed 0:c4152c628df5 5849 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5850
sPymbed 0:c4152c628df5 5851 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5852 msgSz = (msg != NULL) ? (word32)WSTRLEN(msg) : 0;
sPymbed 0:c4152c628df5 5853
sPymbed 0:c4152c628df5 5854 ret = PreparePacket(ssh,
sPymbed 0:c4152c628df5 5855 MSG_ID_SZ + BOOLEAN_SZ + (LENGTH_SZ * 2) +
sPymbed 0:c4152c628df5 5856 msgSz + cannedLangTagSz);
sPymbed 0:c4152c628df5 5857 }
sPymbed 0:c4152c628df5 5858
sPymbed 0:c4152c628df5 5859 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5860 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5861 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5862
sPymbed 0:c4152c628df5 5863 output[idx++] = MSGID_DEBUG;
sPymbed 0:c4152c628df5 5864 output[idx++] = (alwaysDisplay != 0);
sPymbed 0:c4152c628df5 5865 c32toa(msgSz, output + idx);
sPymbed 0:c4152c628df5 5866 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5867 if (msgSz > 0) {
sPymbed 0:c4152c628df5 5868 WMEMCPY(output + idx, msg, msgSz);
sPymbed 0:c4152c628df5 5869 idx += msgSz;
sPymbed 0:c4152c628df5 5870 }
sPymbed 0:c4152c628df5 5871 c32toa(cannedLangTagSz, output + idx);
sPymbed 0:c4152c628df5 5872 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5873 WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz);
sPymbed 0:c4152c628df5 5874 idx += cannedLangTagSz;
sPymbed 0:c4152c628df5 5875
sPymbed 0:c4152c628df5 5876 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5877
sPymbed 0:c4152c628df5 5878 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5879 }
sPymbed 0:c4152c628df5 5880
sPymbed 0:c4152c628df5 5881 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5882 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5883
sPymbed 0:c4152c628df5 5884 return ret;
sPymbed 0:c4152c628df5 5885 }
sPymbed 0:c4152c628df5 5886
sPymbed 0:c4152c628df5 5887
sPymbed 0:c4152c628df5 5888 int SendServiceRequest(WOLFSSH* ssh, byte serviceId)
sPymbed 0:c4152c628df5 5889 {
sPymbed 0:c4152c628df5 5890 const char* serviceName;
sPymbed 0:c4152c628df5 5891 word32 serviceNameSz;
sPymbed 0:c4152c628df5 5892 byte* output;
sPymbed 0:c4152c628df5 5893 word32 idx;
sPymbed 0:c4152c628df5 5894 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5895
sPymbed 0:c4152c628df5 5896 WLOG(WS_LOG_DEBUG, "Entering SendServiceRequest()");
sPymbed 0:c4152c628df5 5897
sPymbed 0:c4152c628df5 5898 if (ssh == NULL)
sPymbed 0:c4152c628df5 5899 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5900
sPymbed 0:c4152c628df5 5901 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5902 serviceName = IdToName(serviceId);
sPymbed 0:c4152c628df5 5903 serviceNameSz = (word32)WSTRLEN(serviceName);
sPymbed 0:c4152c628df5 5904
sPymbed 0:c4152c628df5 5905 ret = PreparePacket(ssh,
sPymbed 0:c4152c628df5 5906 MSG_ID_SZ + LENGTH_SZ + serviceNameSz);
sPymbed 0:c4152c628df5 5907 }
sPymbed 0:c4152c628df5 5908
sPymbed 0:c4152c628df5 5909 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5910 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5911 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5912
sPymbed 0:c4152c628df5 5913 output[idx++] = MSGID_SERVICE_REQUEST;
sPymbed 0:c4152c628df5 5914 c32toa(serviceNameSz, output + idx);
sPymbed 0:c4152c628df5 5915 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5916 WMEMCPY(output + idx, serviceName, serviceNameSz);
sPymbed 0:c4152c628df5 5917 idx += serviceNameSz;
sPymbed 0:c4152c628df5 5918
sPymbed 0:c4152c628df5 5919 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5920 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5921 }
sPymbed 0:c4152c628df5 5922
sPymbed 0:c4152c628df5 5923 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5924 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 5925
sPymbed 0:c4152c628df5 5926 WLOG(WS_LOG_DEBUG, "Leaving SendServiceRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 5927 return ret;
sPymbed 0:c4152c628df5 5928 }
sPymbed 0:c4152c628df5 5929
sPymbed 0:c4152c628df5 5930
sPymbed 0:c4152c628df5 5931 int SendServiceAccept(WOLFSSH* ssh, byte serviceId)
sPymbed 0:c4152c628df5 5932 {
sPymbed 0:c4152c628df5 5933 const char* serviceName;
sPymbed 0:c4152c628df5 5934 word32 serviceNameSz;
sPymbed 0:c4152c628df5 5935 byte* output;
sPymbed 0:c4152c628df5 5936 word32 idx;
sPymbed 0:c4152c628df5 5937 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5938
sPymbed 0:c4152c628df5 5939 if (ssh == NULL)
sPymbed 0:c4152c628df5 5940 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5941
sPymbed 0:c4152c628df5 5942 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5943 serviceName = IdToName(serviceId);
sPymbed 0:c4152c628df5 5944 serviceNameSz = (word32)WSTRLEN(serviceName);
sPymbed 0:c4152c628df5 5945 ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + serviceNameSz);
sPymbed 0:c4152c628df5 5946 }
sPymbed 0:c4152c628df5 5947
sPymbed 0:c4152c628df5 5948 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5949 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 5950 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 5951
sPymbed 0:c4152c628df5 5952 output[idx++] = MSGID_SERVICE_ACCEPT;
sPymbed 0:c4152c628df5 5953 c32toa(serviceNameSz, output + idx);
sPymbed 0:c4152c628df5 5954 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 5955 WMEMCPY(output + idx, serviceName, serviceNameSz);
sPymbed 0:c4152c628df5 5956 idx += serviceNameSz;
sPymbed 0:c4152c628df5 5957
sPymbed 0:c4152c628df5 5958 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 5959
sPymbed 0:c4152c628df5 5960 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 5961 }
sPymbed 0:c4152c628df5 5962
sPymbed 0:c4152c628df5 5963 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 5964 ret = SendUserAuthBanner(ssh);
sPymbed 0:c4152c628df5 5965
sPymbed 0:c4152c628df5 5966 return ret;
sPymbed 0:c4152c628df5 5967 }
sPymbed 0:c4152c628df5 5968
sPymbed 0:c4152c628df5 5969
sPymbed 0:c4152c628df5 5970 static const char cannedAuths[] = "publickey,password";
sPymbed 0:c4152c628df5 5971 static const word32 cannedAuthsSz = sizeof(cannedAuths) - 1;
sPymbed 0:c4152c628df5 5972
sPymbed 0:c4152c628df5 5973
sPymbed 0:c4152c628df5 5974 int SendUserAuthRequest(WOLFSSH* ssh, byte authId)
sPymbed 0:c4152c628df5 5975 {
sPymbed 0:c4152c628df5 5976 byte* output;
sPymbed 0:c4152c628df5 5977 word32 idx;
sPymbed 0:c4152c628df5 5978 const char* authName;
sPymbed 0:c4152c628df5 5979 word32 authNameSz;
sPymbed 0:c4152c628df5 5980 const char* serviceName;
sPymbed 0:c4152c628df5 5981 word32 serviceNameSz;
sPymbed 0:c4152c628df5 5982 word32 payloadSz;
sPymbed 0:c4152c628df5 5983 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 5984 WS_UserAuthData authData;
sPymbed 0:c4152c628df5 5985
sPymbed 0:c4152c628df5 5986 WLOG(WS_LOG_DEBUG, "Entering SendUserAuthRequest()");
sPymbed 0:c4152c628df5 5987
sPymbed 0:c4152c628df5 5988 if (ssh == NULL)
sPymbed 0:c4152c628df5 5989 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 5990
sPymbed 0:c4152c628df5 5991 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 5992 if (authId == ID_USERAUTH_PASSWORD && ssh->ctx->userAuthCb != NULL) {
sPymbed 0:c4152c628df5 5993 WLOG(WS_LOG_DEBUG, "SUARPW: Calling the userauth callback");
sPymbed 0:c4152c628df5 5994 ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD,
sPymbed 0:c4152c628df5 5995 &authData, ssh->userAuthCtx);
sPymbed 0:c4152c628df5 5996 if (ret != WOLFSSH_USERAUTH_SUCCESS) {
sPymbed 0:c4152c628df5 5997 WLOG(WS_LOG_DEBUG, "SUARPW: Couldn't get password");
sPymbed 0:c4152c628df5 5998 ret = WS_FATAL_ERROR;
sPymbed 0:c4152c628df5 5999 }
sPymbed 0:c4152c628df5 6000 }
sPymbed 0:c4152c628df5 6001 }
sPymbed 0:c4152c628df5 6002
sPymbed 0:c4152c628df5 6003 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6004 serviceName = IdToName(ID_SERVICE_CONNECTION);
sPymbed 0:c4152c628df5 6005 serviceNameSz = (word32)WSTRLEN(serviceName);
sPymbed 0:c4152c628df5 6006 authName = IdToName(authId);
sPymbed 0:c4152c628df5 6007 authNameSz = (word32)WSTRLEN(authName);
sPymbed 0:c4152c628df5 6008
sPymbed 0:c4152c628df5 6009 payloadSz = MSG_ID_SZ + (LENGTH_SZ * 3) +
sPymbed 0:c4152c628df5 6010 ssh->userNameSz + serviceNameSz + authNameSz;
sPymbed 0:c4152c628df5 6011
sPymbed 0:c4152c628df5 6012 if (authId == ID_USERAUTH_PASSWORD) {
sPymbed 0:c4152c628df5 6013 payloadSz += BOOLEAN_SZ + LENGTH_SZ +
sPymbed 0:c4152c628df5 6014 authData.sf.password.passwordSz;
sPymbed 0:c4152c628df5 6015 }
sPymbed 0:c4152c628df5 6016 else if (authId != ID_NONE)
sPymbed 0:c4152c628df5 6017 ret = WS_INVALID_ALGO_ID;
sPymbed 0:c4152c628df5 6018 }
sPymbed 0:c4152c628df5 6019
sPymbed 0:c4152c628df5 6020 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6021 ret = PreparePacket(ssh, payloadSz);
sPymbed 0:c4152c628df5 6022
sPymbed 0:c4152c628df5 6023 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6024 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6025 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6026
sPymbed 0:c4152c628df5 6027 output[idx++] = MSGID_USERAUTH_REQUEST;
sPymbed 0:c4152c628df5 6028 c32toa(ssh->userNameSz, output + idx);
sPymbed 0:c4152c628df5 6029 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6030 WMEMCPY(output + idx, ssh->userName, ssh->userNameSz);
sPymbed 0:c4152c628df5 6031 idx += ssh->userNameSz;
sPymbed 0:c4152c628df5 6032
sPymbed 0:c4152c628df5 6033 c32toa(serviceNameSz, output + idx);
sPymbed 0:c4152c628df5 6034 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6035 WMEMCPY(output + idx, serviceName, serviceNameSz);
sPymbed 0:c4152c628df5 6036 idx += serviceNameSz;
sPymbed 0:c4152c628df5 6037
sPymbed 0:c4152c628df5 6038 c32toa(authNameSz, output + idx);
sPymbed 0:c4152c628df5 6039 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6040 WMEMCPY(output + idx, authName, authNameSz);
sPymbed 0:c4152c628df5 6041 idx += authNameSz;
sPymbed 0:c4152c628df5 6042
sPymbed 0:c4152c628df5 6043 if (authId == ID_USERAUTH_PASSWORD) {
sPymbed 0:c4152c628df5 6044 output[idx++] = 0; /* Boolean "FALSE" for password change */
sPymbed 0:c4152c628df5 6045 c32toa(authData.sf.password.passwordSz, output + idx);
sPymbed 0:c4152c628df5 6046 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6047 WMEMCPY(output + idx, authData.sf.password.password,
sPymbed 0:c4152c628df5 6048 authData.sf.password.passwordSz);
sPymbed 0:c4152c628df5 6049 idx += authData.sf.password.passwordSz;
sPymbed 0:c4152c628df5 6050 }
sPymbed 0:c4152c628df5 6051
sPymbed 0:c4152c628df5 6052 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6053
sPymbed 0:c4152c628df5 6054 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6055 }
sPymbed 0:c4152c628df5 6056
sPymbed 0:c4152c628df5 6057 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6058 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6059
sPymbed 0:c4152c628df5 6060 WLOG(WS_LOG_DEBUG, "Leaving SendUserAuthRequest(), ret = %d", ret);
sPymbed 0:c4152c628df5 6061 return ret;
sPymbed 0:c4152c628df5 6062 }
sPymbed 0:c4152c628df5 6063
sPymbed 0:c4152c628df5 6064
sPymbed 0:c4152c628df5 6065 int SendUserAuthFailure(WOLFSSH* ssh, byte partialSuccess)
sPymbed 0:c4152c628df5 6066 {
sPymbed 0:c4152c628df5 6067 byte* output;
sPymbed 0:c4152c628df5 6068 word32 idx;
sPymbed 0:c4152c628df5 6069 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6070
sPymbed 0:c4152c628df5 6071 WLOG(WS_LOG_DEBUG, "Entering SendUserAuthFailure()");
sPymbed 0:c4152c628df5 6072
sPymbed 0:c4152c628df5 6073 if (ssh == NULL)
sPymbed 0:c4152c628df5 6074 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6075
sPymbed 0:c4152c628df5 6076 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6077 ret = PreparePacket(ssh,
sPymbed 0:c4152c628df5 6078 MSG_ID_SZ + LENGTH_SZ +
sPymbed 0:c4152c628df5 6079 cannedAuthsSz + BOOLEAN_SZ);
sPymbed 0:c4152c628df5 6080
sPymbed 0:c4152c628df5 6081 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6082 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6083 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6084
sPymbed 0:c4152c628df5 6085 output[idx++] = MSGID_USERAUTH_FAILURE;
sPymbed 0:c4152c628df5 6086 c32toa(cannedAuthsSz, output + idx);
sPymbed 0:c4152c628df5 6087 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6088 WMEMCPY(output + idx, cannedAuths, cannedAuthsSz);
sPymbed 0:c4152c628df5 6089 idx += cannedAuthsSz;
sPymbed 0:c4152c628df5 6090 output[idx++] = (partialSuccess != 0);
sPymbed 0:c4152c628df5 6091
sPymbed 0:c4152c628df5 6092 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6093
sPymbed 0:c4152c628df5 6094 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6095 }
sPymbed 0:c4152c628df5 6096
sPymbed 0:c4152c628df5 6097 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6098 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6099
sPymbed 0:c4152c628df5 6100 return ret;
sPymbed 0:c4152c628df5 6101 }
sPymbed 0:c4152c628df5 6102
sPymbed 0:c4152c628df5 6103
sPymbed 0:c4152c628df5 6104 int SendUserAuthSuccess(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 6105 {
sPymbed 0:c4152c628df5 6106 byte* output;
sPymbed 0:c4152c628df5 6107 word32 idx;
sPymbed 0:c4152c628df5 6108 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6109
sPymbed 0:c4152c628df5 6110 if (ssh == NULL)
sPymbed 0:c4152c628df5 6111 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6112
sPymbed 0:c4152c628df5 6113 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6114 ret = PreparePacket(ssh, MSG_ID_SZ);
sPymbed 0:c4152c628df5 6115
sPymbed 0:c4152c628df5 6116 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6117 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6118 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6119
sPymbed 0:c4152c628df5 6120 output[idx++] = MSGID_USERAUTH_SUCCESS;
sPymbed 0:c4152c628df5 6121
sPymbed 0:c4152c628df5 6122 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6123
sPymbed 0:c4152c628df5 6124 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6125 }
sPymbed 0:c4152c628df5 6126
sPymbed 0:c4152c628df5 6127 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6128 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6129
sPymbed 0:c4152c628df5 6130 return ret;
sPymbed 0:c4152c628df5 6131 }
sPymbed 0:c4152c628df5 6132
sPymbed 0:c4152c628df5 6133
sPymbed 0:c4152c628df5 6134 int SendUserAuthPkOk(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 6135 const byte* algoName, word32 algoNameSz,
sPymbed 0:c4152c628df5 6136 const byte* publicKey, word32 publicKeySz)
sPymbed 0:c4152c628df5 6137 {
sPymbed 0:c4152c628df5 6138 byte* output;
sPymbed 0:c4152c628df5 6139 word32 idx;
sPymbed 0:c4152c628df5 6140 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6141
sPymbed 0:c4152c628df5 6142 if (ssh == NULL ||
sPymbed 0:c4152c628df5 6143 algoName == NULL || algoNameSz == 0 ||
sPymbed 0:c4152c628df5 6144 publicKey == NULL || publicKeySz == 0) {
sPymbed 0:c4152c628df5 6145
sPymbed 0:c4152c628df5 6146 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6147 }
sPymbed 0:c4152c628df5 6148
sPymbed 0:c4152c628df5 6149 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6150 ret = PreparePacket(ssh, MSG_ID_SZ + (LENGTH_SZ * 2) +
sPymbed 0:c4152c628df5 6151 algoNameSz + publicKeySz);
sPymbed 0:c4152c628df5 6152
sPymbed 0:c4152c628df5 6153 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6154 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6155 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6156
sPymbed 0:c4152c628df5 6157 output[idx++] = MSGID_USERAUTH_PK_OK;
sPymbed 0:c4152c628df5 6158 c32toa(algoNameSz, output + idx);
sPymbed 0:c4152c628df5 6159 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6160 WMEMCPY(output + idx, algoName, algoNameSz);
sPymbed 0:c4152c628df5 6161 idx += algoNameSz;
sPymbed 0:c4152c628df5 6162 c32toa(publicKeySz, output + idx);
sPymbed 0:c4152c628df5 6163 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6164 WMEMCPY(output + idx, publicKey, publicKeySz);
sPymbed 0:c4152c628df5 6165 idx += publicKeySz;
sPymbed 0:c4152c628df5 6166
sPymbed 0:c4152c628df5 6167 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6168
sPymbed 0:c4152c628df5 6169 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6170 }
sPymbed 0:c4152c628df5 6171
sPymbed 0:c4152c628df5 6172 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6173 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6174
sPymbed 0:c4152c628df5 6175 return ret;
sPymbed 0:c4152c628df5 6176 }
sPymbed 0:c4152c628df5 6177
sPymbed 0:c4152c628df5 6178
sPymbed 0:c4152c628df5 6179 int SendUserAuthBanner(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 6180 {
sPymbed 0:c4152c628df5 6181 byte* output;
sPymbed 0:c4152c628df5 6182 word32 idx;
sPymbed 0:c4152c628df5 6183 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6184 const char* banner;
sPymbed 0:c4152c628df5 6185 word32 bannerSz = 0;
sPymbed 0:c4152c628df5 6186
sPymbed 0:c4152c628df5 6187 if (ssh == NULL)
sPymbed 0:c4152c628df5 6188 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6189
sPymbed 0:c4152c628df5 6190 if (ssh->ctx->banner != NULL && ssh->ctx->bannerSz > 0) {
sPymbed 0:c4152c628df5 6191 banner = ssh->ctx->banner;
sPymbed 0:c4152c628df5 6192 bannerSz = ssh->ctx->bannerSz;
sPymbed 0:c4152c628df5 6193 }
sPymbed 0:c4152c628df5 6194
sPymbed 0:c4152c628df5 6195 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6196 ret = PreparePacket(ssh, MSG_ID_SZ + (LENGTH_SZ * 2) +
sPymbed 0:c4152c628df5 6197 bannerSz + cannedLangTagSz);
sPymbed 0:c4152c628df5 6198
sPymbed 0:c4152c628df5 6199 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6200 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6201 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6202
sPymbed 0:c4152c628df5 6203 output[idx++] = MSGID_USERAUTH_BANNER;
sPymbed 0:c4152c628df5 6204 c32toa(bannerSz, output + idx);
sPymbed 0:c4152c628df5 6205 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6206 if (bannerSz > 0)
sPymbed 0:c4152c628df5 6207 WMEMCPY(output + idx, banner, bannerSz);
sPymbed 0:c4152c628df5 6208 idx += bannerSz;
sPymbed 0:c4152c628df5 6209 c32toa(cannedLangTagSz, output + idx);
sPymbed 0:c4152c628df5 6210 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6211 WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz);
sPymbed 0:c4152c628df5 6212 idx += cannedLangTagSz;
sPymbed 0:c4152c628df5 6213
sPymbed 0:c4152c628df5 6214 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6215
sPymbed 0:c4152c628df5 6216 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6217 }
sPymbed 0:c4152c628df5 6218
sPymbed 0:c4152c628df5 6219 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6220 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6221
sPymbed 0:c4152c628df5 6222 return ret;
sPymbed 0:c4152c628df5 6223 }
sPymbed 0:c4152c628df5 6224
sPymbed 0:c4152c628df5 6225
sPymbed 0:c4152c628df5 6226 int SendRequestSuccess(WOLFSSH* ssh, int success)
sPymbed 0:c4152c628df5 6227 {
sPymbed 0:c4152c628df5 6228 byte* output;
sPymbed 0:c4152c628df5 6229 word32 idx;
sPymbed 0:c4152c628df5 6230 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6231
sPymbed 0:c4152c628df5 6232 WLOG(WS_LOG_DEBUG, "Entering SendRequestSuccess(), %s",
sPymbed 0:c4152c628df5 6233 success ? "Success" : "Failure");
sPymbed 0:c4152c628df5 6234
sPymbed 0:c4152c628df5 6235 if (ssh == NULL)
sPymbed 0:c4152c628df5 6236 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6237
sPymbed 0:c4152c628df5 6238 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6239 ret = PreparePacket(ssh, MSG_ID_SZ);
sPymbed 0:c4152c628df5 6240
sPymbed 0:c4152c628df5 6241 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6242 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6243 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6244
sPymbed 0:c4152c628df5 6245 output[idx++] = success ?
sPymbed 0:c4152c628df5 6246 MSGID_REQUEST_SUCCESS : MSGID_REQUEST_FAILURE;
sPymbed 0:c4152c628df5 6247
sPymbed 0:c4152c628df5 6248 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6249
sPymbed 0:c4152c628df5 6250 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6251 }
sPymbed 0:c4152c628df5 6252
sPymbed 0:c4152c628df5 6253 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6254 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6255
sPymbed 0:c4152c628df5 6256 WLOG(WS_LOG_DEBUG, "Leaving SendRequestSuccess(), ret = %d", ret);
sPymbed 0:c4152c628df5 6257 return ret;
sPymbed 0:c4152c628df5 6258 }
sPymbed 0:c4152c628df5 6259
sPymbed 0:c4152c628df5 6260
sPymbed 0:c4152c628df5 6261 int SendChannelOpenSession(WOLFSSH* ssh,
sPymbed 0:c4152c628df5 6262 word32 initialWindowSz, word32 maxPacketSz)
sPymbed 0:c4152c628df5 6263 {
sPymbed 0:c4152c628df5 6264 WOLFSSH_CHANNEL* newChannel;
sPymbed 0:c4152c628df5 6265 byte* output;
sPymbed 0:c4152c628df5 6266 const char* channelType;
sPymbed 0:c4152c628df5 6267 word32 channelTypeSz, channelId, idx;
sPymbed 0:c4152c628df5 6268 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6269
sPymbed 0:c4152c628df5 6270 WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenSession()");
sPymbed 0:c4152c628df5 6271
sPymbed 0:c4152c628df5 6272 if (ssh == NULL)
sPymbed 0:c4152c628df5 6273 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6274
sPymbed 0:c4152c628df5 6275 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6276 channelId = ssh->nextChannel;
sPymbed 0:c4152c628df5 6277 newChannel = ChannelNew(ssh, ID_CHANTYPE_SESSION,
sPymbed 0:c4152c628df5 6278 initialWindowSz, maxPacketSz);
sPymbed 0:c4152c628df5 6279 if (newChannel == NULL)
sPymbed 0:c4152c628df5 6280 ret = WS_MEMORY_E;
sPymbed 0:c4152c628df5 6281
sPymbed 0:c4152c628df5 6282 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6283 ret = ChannelAppend(ssh, newChannel);
sPymbed 0:c4152c628df5 6284 }
sPymbed 0:c4152c628df5 6285
sPymbed 0:c4152c628df5 6286 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6287 channelType = IdToName(ID_CHANTYPE_SESSION);
sPymbed 0:c4152c628df5 6288 channelTypeSz = (word32)WSTRLEN(channelType);
sPymbed 0:c4152c628df5 6289
sPymbed 0:c4152c628df5 6290 ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + channelTypeSz +
sPymbed 0:c4152c628df5 6291 (UINT32_SZ * 3));
sPymbed 0:c4152c628df5 6292 }
sPymbed 0:c4152c628df5 6293
sPymbed 0:c4152c628df5 6294 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6295 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6296 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6297
sPymbed 0:c4152c628df5 6298 output[idx++] = MSGID_CHANNEL_OPEN;
sPymbed 0:c4152c628df5 6299 c32toa(channelTypeSz, output + idx);
sPymbed 0:c4152c628df5 6300 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6301 WMEMCPY(output + idx, channelType, channelTypeSz);
sPymbed 0:c4152c628df5 6302 idx += channelTypeSz;
sPymbed 0:c4152c628df5 6303 c32toa(channelId, output + idx);
sPymbed 0:c4152c628df5 6304 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6305 c32toa(initialWindowSz, output + idx);
sPymbed 0:c4152c628df5 6306 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6307 c32toa(maxPacketSz, output + idx);
sPymbed 0:c4152c628df5 6308 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6309
sPymbed 0:c4152c628df5 6310 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6311
sPymbed 0:c4152c628df5 6312 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6313 }
sPymbed 0:c4152c628df5 6314
sPymbed 0:c4152c628df5 6315 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6316 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6317
sPymbed 0:c4152c628df5 6318 WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenSession(), ret = %d", ret);
sPymbed 0:c4152c628df5 6319 return ret;
sPymbed 0:c4152c628df5 6320 }
sPymbed 0:c4152c628df5 6321
sPymbed 0:c4152c628df5 6322
sPymbed 0:c4152c628df5 6323 int SendChannelOpenConf(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 6324 {
sPymbed 0:c4152c628df5 6325 byte* output;
sPymbed 0:c4152c628df5 6326 word32 idx;
sPymbed 0:c4152c628df5 6327 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6328 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6329
sPymbed 0:c4152c628df5 6330 WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenConf()");
sPymbed 0:c4152c628df5 6331
sPymbed 0:c4152c628df5 6332 if (ssh == NULL)
sPymbed 0:c4152c628df5 6333 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6334
sPymbed 0:c4152c628df5 6335 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6336 channel = ChannelFind(ssh, ssh->defaultPeerChannelId, FIND_PEER);
sPymbed 0:c4152c628df5 6337 if (channel == NULL)
sPymbed 0:c4152c628df5 6338 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6339 }
sPymbed 0:c4152c628df5 6340
sPymbed 0:c4152c628df5 6341 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6342 ret = PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 4));
sPymbed 0:c4152c628df5 6343
sPymbed 0:c4152c628df5 6344 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6345 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6346 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6347
sPymbed 0:c4152c628df5 6348 output[idx++] = MSGID_CHANNEL_OPEN_CONF;
sPymbed 0:c4152c628df5 6349 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6350 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6351 c32toa(channel->channel, output + idx);
sPymbed 0:c4152c628df5 6352 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6353 c32toa(channel->windowSz, output + idx);
sPymbed 0:c4152c628df5 6354 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6355 c32toa(channel->maxPacketSz, output + idx);
sPymbed 0:c4152c628df5 6356 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6357
sPymbed 0:c4152c628df5 6358 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6359
sPymbed 0:c4152c628df5 6360 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6361 }
sPymbed 0:c4152c628df5 6362
sPymbed 0:c4152c628df5 6363 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6364 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6365
sPymbed 0:c4152c628df5 6366 WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenConf(), ret = %d", ret);
sPymbed 0:c4152c628df5 6367 return ret;
sPymbed 0:c4152c628df5 6368 }
sPymbed 0:c4152c628df5 6369
sPymbed 0:c4152c628df5 6370
sPymbed 0:c4152c628df5 6371 int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId)
sPymbed 0:c4152c628df5 6372 {
sPymbed 0:c4152c628df5 6373 byte* output;
sPymbed 0:c4152c628df5 6374 word32 idx;
sPymbed 0:c4152c628df5 6375 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6376 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6377
sPymbed 0:c4152c628df5 6378 WLOG(WS_LOG_DEBUG, "Entering SendChannelEof()");
sPymbed 0:c4152c628df5 6379
sPymbed 0:c4152c628df5 6380 if (ssh == NULL)
sPymbed 0:c4152c628df5 6381 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6382
sPymbed 0:c4152c628df5 6383 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6384 channel = ChannelFind(ssh, peerChannelId, FIND_PEER);
sPymbed 0:c4152c628df5 6385 if (channel == NULL)
sPymbed 0:c4152c628df5 6386 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6387 }
sPymbed 0:c4152c628df5 6388
sPymbed 0:c4152c628df5 6389 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6390 ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ);
sPymbed 0:c4152c628df5 6391
sPymbed 0:c4152c628df5 6392 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6393 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6394 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6395
sPymbed 0:c4152c628df5 6396 output[idx++] = MSGID_CHANNEL_EOF;
sPymbed 0:c4152c628df5 6397 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6398 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6399
sPymbed 0:c4152c628df5 6400 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6401
sPymbed 0:c4152c628df5 6402 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6403 }
sPymbed 0:c4152c628df5 6404
sPymbed 0:c4152c628df5 6405 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6406 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6407
sPymbed 0:c4152c628df5 6408 WLOG(WS_LOG_DEBUG, "Leaving SendChannelEof(), ret = %d", ret);
sPymbed 0:c4152c628df5 6409 return ret;
sPymbed 0:c4152c628df5 6410 }
sPymbed 0:c4152c628df5 6411
sPymbed 0:c4152c628df5 6412
sPymbed 0:c4152c628df5 6413 int SendChannelClose(WOLFSSH* ssh, word32 peerChannelId)
sPymbed 0:c4152c628df5 6414 {
sPymbed 0:c4152c628df5 6415 byte* output;
sPymbed 0:c4152c628df5 6416 word32 idx;
sPymbed 0:c4152c628df5 6417 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6418 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6419
sPymbed 0:c4152c628df5 6420 WLOG(WS_LOG_DEBUG, "Entering SendChannelClose()");
sPymbed 0:c4152c628df5 6421
sPymbed 0:c4152c628df5 6422 if (ssh == NULL)
sPymbed 0:c4152c628df5 6423 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6424
sPymbed 0:c4152c628df5 6425 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6426 channel = ChannelFind(ssh, peerChannelId, FIND_PEER);
sPymbed 0:c4152c628df5 6427 if (channel == NULL)
sPymbed 0:c4152c628df5 6428 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6429 }
sPymbed 0:c4152c628df5 6430
sPymbed 0:c4152c628df5 6431 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6432 ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ);
sPymbed 0:c4152c628df5 6433
sPymbed 0:c4152c628df5 6434 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6435 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6436 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6437
sPymbed 0:c4152c628df5 6438 output[idx++] = MSGID_CHANNEL_CLOSE;
sPymbed 0:c4152c628df5 6439 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6440 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6441
sPymbed 0:c4152c628df5 6442 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6443
sPymbed 0:c4152c628df5 6444 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6445 }
sPymbed 0:c4152c628df5 6446
sPymbed 0:c4152c628df5 6447 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6448 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6449
sPymbed 0:c4152c628df5 6450 WLOG(WS_LOG_DEBUG, "Leaving SendChannelClose(), ret = %d", ret);
sPymbed 0:c4152c628df5 6451 return ret;
sPymbed 0:c4152c628df5 6452 }
sPymbed 0:c4152c628df5 6453
sPymbed 0:c4152c628df5 6454 word32 min(word32 a, word32 b){
sPymbed 0:c4152c628df5 6455 return 0;
sPymbed 0:c4152c628df5 6456 }
sPymbed 0:c4152c628df5 6457
sPymbed 0:c4152c628df5 6458 int SendChannelData(WOLFSSH* ssh, word32 peerChannel,
sPymbed 0:c4152c628df5 6459 byte* data, word32 dataSz)
sPymbed 0:c4152c628df5 6460 {
sPymbed 0:c4152c628df5 6461 byte* output;
sPymbed 0:c4152c628df5 6462 word32 idx;
sPymbed 0:c4152c628df5 6463 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6464 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6465
sPymbed 0:c4152c628df5 6466 WLOG(WS_LOG_DEBUG, "Entering SendChannelData()");
sPymbed 0:c4152c628df5 6467
sPymbed 0:c4152c628df5 6468 if (ssh == NULL)
sPymbed 0:c4152c628df5 6469 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6470
sPymbed 0:c4152c628df5 6471 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6472 if (ssh->isKeying)
sPymbed 0:c4152c628df5 6473 ret = WS_REKEYING;
sPymbed 0:c4152c628df5 6474 }
sPymbed 0:c4152c628df5 6475
sPymbed 0:c4152c628df5 6476 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6477 channel = ChannelFind(ssh, peerChannel, FIND_PEER);
sPymbed 0:c4152c628df5 6478 if (channel == NULL) {
sPymbed 0:c4152c628df5 6479 WLOG(WS_LOG_DEBUG, "Invalid peer channel");
sPymbed 0:c4152c628df5 6480 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6481 }
sPymbed 0:c4152c628df5 6482 }
sPymbed 0:c4152c628df5 6483
sPymbed 0:c4152c628df5 6484 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6485 word32 bound = min(channel->peerWindowSz, channel->peerMaxPacketSz);
sPymbed 0:c4152c628df5 6486
sPymbed 0:c4152c628df5 6487 if (dataSz > bound) {
sPymbed 0:c4152c628df5 6488 WLOG(WS_LOG_DEBUG,
sPymbed 0:c4152c628df5 6489 "Trying to send %u, client will only accept %u, limiting",
sPymbed 0:c4152c628df5 6490 dataSz, bound);
sPymbed 0:c4152c628df5 6491 dataSz = bound;
sPymbed 0:c4152c628df5 6492 }
sPymbed 0:c4152c628df5 6493
sPymbed 0:c4152c628df5 6494 ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ + dataSz);
sPymbed 0:c4152c628df5 6495 }
sPymbed 0:c4152c628df5 6496
sPymbed 0:c4152c628df5 6497 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6498 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6499 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6500
sPymbed 0:c4152c628df5 6501 output[idx++] = MSGID_CHANNEL_DATA;
sPymbed 0:c4152c628df5 6502 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6503 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6504 c32toa(dataSz, output + idx);
sPymbed 0:c4152c628df5 6505 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6506 WMEMCPY(output + idx, data, dataSz);
sPymbed 0:c4152c628df5 6507 idx += dataSz;
sPymbed 0:c4152c628df5 6508
sPymbed 0:c4152c628df5 6509 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6510
sPymbed 0:c4152c628df5 6511 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6512 }
sPymbed 0:c4152c628df5 6513
sPymbed 0:c4152c628df5 6514 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6515 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6516
sPymbed 0:c4152c628df5 6517 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6518 WLOG(WS_LOG_INFO, " dataSz = %u", dataSz);
sPymbed 0:c4152c628df5 6519 WLOG(WS_LOG_INFO, " peerWindowSz = %u", channel->peerWindowSz);
sPymbed 0:c4152c628df5 6520 channel->peerWindowSz -= dataSz;
sPymbed 0:c4152c628df5 6521 WLOG(WS_LOG_INFO, " update peerWindowSz = %u", channel->peerWindowSz);
sPymbed 0:c4152c628df5 6522 ret = dataSz;
sPymbed 0:c4152c628df5 6523 }
sPymbed 0:c4152c628df5 6524
sPymbed 0:c4152c628df5 6525 WLOG(WS_LOG_DEBUG, "Leaving SendChannelData(), ret = %d", ret);
sPymbed 0:c4152c628df5 6526 return ret;
sPymbed 0:c4152c628df5 6527 }
sPymbed 0:c4152c628df5 6528
sPymbed 0:c4152c628df5 6529
sPymbed 0:c4152c628df5 6530 int SendChannelWindowAdjust(WOLFSSH* ssh, word32 peerChannel,
sPymbed 0:c4152c628df5 6531 word32 bytesToAdd)
sPymbed 0:c4152c628df5 6532 {
sPymbed 0:c4152c628df5 6533 byte* output;
sPymbed 0:c4152c628df5 6534 word32 idx;
sPymbed 0:c4152c628df5 6535 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6536 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6537
sPymbed 0:c4152c628df5 6538 WLOG(WS_LOG_DEBUG, "Entering SendChannelWindowAdjust()");
sPymbed 0:c4152c628df5 6539
sPymbed 0:c4152c628df5 6540 if (ssh == NULL)
sPymbed 0:c4152c628df5 6541 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6542
sPymbed 0:c4152c628df5 6543 channel = ChannelFind(ssh, peerChannel, FIND_PEER);
sPymbed 0:c4152c628df5 6544 if (channel == NULL) {
sPymbed 0:c4152c628df5 6545 WLOG(WS_LOG_DEBUG, "Invalid peer channel");
sPymbed 0:c4152c628df5 6546 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6547 }
sPymbed 0:c4152c628df5 6548 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6549 ret = PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 2));
sPymbed 0:c4152c628df5 6550
sPymbed 0:c4152c628df5 6551 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6552 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6553 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6554
sPymbed 0:c4152c628df5 6555 output[idx++] = MSGID_CHANNEL_WINDOW_ADJUST;
sPymbed 0:c4152c628df5 6556 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6557 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6558 c32toa(bytesToAdd, output + idx);
sPymbed 0:c4152c628df5 6559 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6560
sPymbed 0:c4152c628df5 6561 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6562
sPymbed 0:c4152c628df5 6563 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6564 }
sPymbed 0:c4152c628df5 6565
sPymbed 0:c4152c628df5 6566 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6567 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6568
sPymbed 0:c4152c628df5 6569 WLOG(WS_LOG_DEBUG, "Leaving SendChannelWindowAdjust(), ret = %d", ret);
sPymbed 0:c4152c628df5 6570 return ret;
sPymbed 0:c4152c628df5 6571 }
sPymbed 0:c4152c628df5 6572
sPymbed 0:c4152c628df5 6573
sPymbed 0:c4152c628df5 6574 static const char cannedShellName[] = "shell";
sPymbed 0:c4152c628df5 6575 static const word32 cannedShellNameSz = sizeof(cannedShellName) - 1;
sPymbed 0:c4152c628df5 6576
sPymbed 0:c4152c628df5 6577
sPymbed 0:c4152c628df5 6578 int SendChannelRequestShell(WOLFSSH* ssh)
sPymbed 0:c4152c628df5 6579 {
sPymbed 0:c4152c628df5 6580 byte* output;
sPymbed 0:c4152c628df5 6581 word32 idx;
sPymbed 0:c4152c628df5 6582 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6583 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6584
sPymbed 0:c4152c628df5 6585 WLOG(WS_LOG_DEBUG, "Entering SendChannelRequestShell()");
sPymbed 0:c4152c628df5 6586
sPymbed 0:c4152c628df5 6587 if (ssh == NULL)
sPymbed 0:c4152c628df5 6588 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6589
sPymbed 0:c4152c628df5 6590 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6591 channel = ChannelFind(ssh, ssh->defaultPeerChannelId, FIND_PEER);
sPymbed 0:c4152c628df5 6592 if (channel == NULL)
sPymbed 0:c4152c628df5 6593 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6594 }
sPymbed 0:c4152c628df5 6595
sPymbed 0:c4152c628df5 6596 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6597 ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ +
sPymbed 0:c4152c628df5 6598 cannedShellNameSz + BOOLEAN_SZ);
sPymbed 0:c4152c628df5 6599
sPymbed 0:c4152c628df5 6600 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6601 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6602 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6603
sPymbed 0:c4152c628df5 6604 output[idx++] = MSGID_CHANNEL_REQUEST;
sPymbed 0:c4152c628df5 6605 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6606 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6607 c32toa(cannedShellNameSz, output + idx);
sPymbed 0:c4152c628df5 6608 idx += LENGTH_SZ;
sPymbed 0:c4152c628df5 6609 WMEMCPY(output + idx, cannedShellName, cannedShellNameSz);
sPymbed 0:c4152c628df5 6610 idx += cannedShellNameSz;
sPymbed 0:c4152c628df5 6611 output[idx++] = 1;
sPymbed 0:c4152c628df5 6612
sPymbed 0:c4152c628df5 6613 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6614
sPymbed 0:c4152c628df5 6615 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6616 }
sPymbed 0:c4152c628df5 6617
sPymbed 0:c4152c628df5 6618 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6619 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6620
sPymbed 0:c4152c628df5 6621 WLOG(WS_LOG_DEBUG, "Leaving SendChannelRequestShell(), ret = %d", ret);
sPymbed 0:c4152c628df5 6622 return ret;
sPymbed 0:c4152c628df5 6623 }
sPymbed 0:c4152c628df5 6624
sPymbed 0:c4152c628df5 6625
sPymbed 0:c4152c628df5 6626 int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success)
sPymbed 0:c4152c628df5 6627 {
sPymbed 0:c4152c628df5 6628 byte* output;
sPymbed 0:c4152c628df5 6629 word32 idx;
sPymbed 0:c4152c628df5 6630 int ret = WS_SUCCESS;
sPymbed 0:c4152c628df5 6631 WOLFSSH_CHANNEL* channel;
sPymbed 0:c4152c628df5 6632
sPymbed 0:c4152c628df5 6633 WLOG(WS_LOG_DEBUG, "Entering SendChannelSuccess(), %s",
sPymbed 0:c4152c628df5 6634 success ? "Success" : "Failure");
sPymbed 0:c4152c628df5 6635
sPymbed 0:c4152c628df5 6636 if (ssh == NULL)
sPymbed 0:c4152c628df5 6637 ret = WS_BAD_ARGUMENT;
sPymbed 0:c4152c628df5 6638
sPymbed 0:c4152c628df5 6639 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6640 channel = ChannelFind(ssh, channelId, FIND_SELF);
sPymbed 0:c4152c628df5 6641 if (channel == NULL) {
sPymbed 0:c4152c628df5 6642 WLOG(WS_LOG_DEBUG, "Invalid channel");
sPymbed 0:c4152c628df5 6643 ret = WS_INVALID_CHANID;
sPymbed 0:c4152c628df5 6644 }
sPymbed 0:c4152c628df5 6645 }
sPymbed 0:c4152c628df5 6646
sPymbed 0:c4152c628df5 6647 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6648 ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ);
sPymbed 0:c4152c628df5 6649
sPymbed 0:c4152c628df5 6650 if (ret == WS_SUCCESS) {
sPymbed 0:c4152c628df5 6651 output = ssh->outputBuffer.buffer;
sPymbed 0:c4152c628df5 6652 idx = ssh->outputBuffer.length;
sPymbed 0:c4152c628df5 6653
sPymbed 0:c4152c628df5 6654 output[idx++] = success ?
sPymbed 0:c4152c628df5 6655 MSGID_CHANNEL_SUCCESS : MSGID_CHANNEL_FAILURE;
sPymbed 0:c4152c628df5 6656 c32toa(channel->peerChannel, output + idx);
sPymbed 0:c4152c628df5 6657 idx += UINT32_SZ;
sPymbed 0:c4152c628df5 6658
sPymbed 0:c4152c628df5 6659 ssh->outputBuffer.length = idx;
sPymbed 0:c4152c628df5 6660
sPymbed 0:c4152c628df5 6661 ret = BundlePacket(ssh);
sPymbed 0:c4152c628df5 6662 }
sPymbed 0:c4152c628df5 6663
sPymbed 0:c4152c628df5 6664 if (ret == WS_SUCCESS)
sPymbed 0:c4152c628df5 6665 ret = SendBuffered(ssh);
sPymbed 0:c4152c628df5 6666
sPymbed 0:c4152c628df5 6667 WLOG(WS_LOG_DEBUG, "Leaving SendChannelSuccess(), ret = %d", ret);
sPymbed 0:c4152c628df5 6668 return ret;
sPymbed 0:c4152c628df5 6669 }
sPymbed 0:c4152c628df5 6670
sPymbed 0:c4152c628df5 6671
sPymbed 0:c4152c628df5 6672 #ifdef DEBUG_WOLFSSH
sPymbed 0:c4152c628df5 6673
sPymbed 0:c4152c628df5 6674 #define LINE_WIDTH 16
sPymbed 0:c4152c628df5 6675 void DumpOctetString(const byte* input, word32 inputSz)
sPymbed 0:c4152c628df5 6676 {
sPymbed 0:c4152c628df5 6677 int rows = inputSz / LINE_WIDTH;
sPymbed 0:c4152c628df5 6678 int remainder = inputSz % LINE_WIDTH;
sPymbed 0:c4152c628df5 6679 int i,j;
sPymbed 0:c4152c628df5 6680
sPymbed 0:c4152c628df5 6681 for (i = 0; i < rows; i++) {
sPymbed 0:c4152c628df5 6682 printf("%04X: ", i * LINE_WIDTH);
sPymbed 0:c4152c628df5 6683 for (j = 0; j < LINE_WIDTH; j++) {
sPymbed 0:c4152c628df5 6684 printf("%02X ", input[i * LINE_WIDTH + j]);
sPymbed 0:c4152c628df5 6685 }
sPymbed 0:c4152c628df5 6686 printf("\n");
sPymbed 0:c4152c628df5 6687 }
sPymbed 0:c4152c628df5 6688 if (remainder) {
sPymbed 0:c4152c628df5 6689 printf("%04X: ", i * LINE_WIDTH);
sPymbed 0:c4152c628df5 6690 for (j = 0; j < remainder; j++) {
sPymbed 0:c4152c628df5 6691 printf("%02X ", input[i * LINE_WIDTH + j]);
sPymbed 0:c4152c628df5 6692 }
sPymbed 0:c4152c628df5 6693 printf("\n");
sPymbed 0:c4152c628df5 6694 }
sPymbed 0:c4152c628df5 6695 }
sPymbed 0:c4152c628df5 6696
sPymbed 0:c4152c628df5 6697 #endif