add example code for MPLABX use

pull/790/head
Jacob Barthelmeh 2018-04-06 10:13:40 -06:00 committed by JacobBarthelmeh
parent 76e8b9f4ea
commit 48fa1e019e
5 changed files with 1054 additions and 0 deletions

View File

@ -3,6 +3,7 @@
# All paths should be given relative to the root # All paths should be given relative to the root
include ide/winvs/include.am include ide/winvs/include.am
include ide/mplabx/include.am
include ide/CSBENCH/include.am include ide/CSBENCH/include.am
include ide/MQX/include.am include ide/MQX/include.am
include ide/IAR-EWARM/include.am include ide/IAR-EWARM/include.am

View File

@ -0,0 +1,15 @@
This is example code for adding a wolfSSH echoserver to a MPLABX project.
The steps to use the code is as follows:
1) Add wolfssh.c source file to project build.
3) Make sure that current MPLABX project handles setting up TCP stack (see MPLABX examples for this /microchip/harmony/XXX/apps/examples/)
4) Add include path to wolfssh root directory.
5) Add preprocessor macro WOLFSSL_USER_SETTINGS (this is so wolfssl/wolfssh includes user_settings.h) to the project properties.
2) Add include path to user_settings.h to project properties.
4) Add APP_SSH_Tasks() and APP_SSH_Initialize() declarations to app.h header file.
5) Add call to APP_SSH_Initialize() to system_init.c
6) Add call to APP_SSH_Tasks() to system_tasks.c
For the current project this was tested with the heap and stack set to 200,000 each. This was not trimed to see the minumum possible heap and stack usage yet. The TX buffer size used was set to 1024. The example needs to use wolfssl versions that are later than 4/5/2018 (mid v3.14.0) for hardware acceleration and versions v3.14.0 and later for software only.
After building and flashing the board a wolfSSH echoserver will be open on port 22 which can be connected to by using the example client bundled with wolfSSH. ```./examples/client/client -u jill -P upthehill -h 192.168.1.120 -p 22```

View File

@ -0,0 +1,6 @@
# vim:ft=automake
# All paths should be given relative to the root
EXTRA_DIST+= ide/mplabx/README.md
EXTRA_DIST+= ide/mplabx/user_settings.h
EXTRA_DIST+= ide/mplabx/wolfssh.c

View File

@ -0,0 +1,396 @@
/* Example custom user settings for wolfSSL with some wolfSSH settings */
#ifndef WOLFSSL_USER_SETTINGS_H
#define WOLFSSL_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h> /* for size_t */
/* ------------------------------------------------------------------------- */
/* Platform */
/* ------------------------------------------------------------------------- */
#undef WOLFSSL_GENERAL_ALIGNMENT
#define WOLFSSL_GENERAL_ALIGNMENT 4
#undef MICROCHIP_PIC32
#define MICROCHIP_PIC32
#undef MICROCHIP_MPLAB_HARMONY
#define MICROCHIP_MPLAB_HARMONY
#undef MICROCHIP_TCPIP
#define MICROCHIP_TCPIP
#undef WOLFSSL_MICROCHIP_PIC32MZ
#define WOLFSSL_MICROCHIP_PIC32MZ
/* ------------------------------------------------------------------------- */
/* wolfSSH settings */
/* ------------------------------------------------------------------------- */
#define DEFAULT_WINDOW_SZ (16 * 1024)
/* ------------------------------------------------------------------------- */
/* Math Configuration */
/* ------------------------------------------------------------------------- */
#undef USE_FAST_MATH
#define USE_FAST_MATH
#ifdef USE_FAST_MATH
#undef TFM_TIMING_RESISTANT
#define TFM_TIMING_RESISTANT
/* Optimizations */
//#define TFM_MIPS
#endif
/* ------------------------------------------------------------------------- */
/* Crypto */
/* ------------------------------------------------------------------------- */
/* ECC */
#if 1
#undef HAVE_ECC
#define HAVE_ECC
/* Manually define enabled curves */
#undef ECC_USER_CURVES
#define ECC_USER_CURVES
//#define HAVE_ECC192
//#define HAVE_ECC224
#undef NO_ECC256
//#define HAVE_ECC384
//#define HAVE_ECC521
/* Fixed point cache (speeds repeated operations against same private key) */
#undef FP_ECC
//#define FP_ECC
#ifdef FP_ECC
/* Bits / Entries */
#undef FP_ENTRIES
#define FP_ENTRIES 2
#undef FP_LUT
#define FP_LUT 4
#endif
/* Optional ECC calculation method */
/* Note: doubles heap usage, but slightly faster */
#undef ECC_SHAMIR
#define ECC_SHAMIR
/* Reduces heap usage, but slower */
#undef ECC_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT
#ifdef USE_FAST_MATH
/* use reduced size math buffers for ecc points */
#undef ALT_ECC_SIZE
#define ALT_ECC_SIZE
/* Enable TFM optimizations for ECC */
#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
#define TFM_ECC192
#endif
#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
#define TFM_ECC224
#endif
#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
#define TFM_ECC256
#endif
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
#define TFM_ECC384
#endif
#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
#define TFM_ECC521
#endif
#endif
#endif
/* RSA */
#undef NO_RSA
#if 1
#ifdef USE_FAST_MATH
/* Maximum math bits (Max RSA key bits * 2) */
#undef FP_MAX_BITS
#define FP_MAX_BITS 4096
#endif
/* half as much memory but twice as slow */
#undef RSA_LOW_MEM
//#define RSA_LOW_MEM
/* timing resistance */
#undef WC_RSA_BLINDING
#define WC_RSA_BLINDING
#else
#define NO_RSA
#endif
/* AES */
#undef NO_AES
#if 1
#undef HAVE_AES_DECRYPT
#define HAVE_AES_DECRYPT
#undef HAVE_AESGCM
#define HAVE_AESGCM
/* GCM Method: GCM_SMALL, GCM_WORD32 or GCM_TABLE */
#undef GCM_SMALL
#define GCM_SMALL
//#undef HAVE_AESCCM
//#define HAVE_AESCCM
#undef WOLFSSL_AES_COUNTER
#define WOLFSSL_AES_COUNTER
#undef WOLFSSL_AES_DIRECT
#define WOLFSSL_AES_DIRECT
#else
#define NO_AES
#endif
/* DES3 */
#undef NO_DES3
#if 1
#undef WOLFSSL_DES_ECB
#define WOLFSSL_DES_ECB
#else
#define NO_DES3
#endif
/* ChaCha20 / Poly1305 */
#undef HAVE_CHACHA
#undef HAVE_POLY1305
#if 0
#define HAVE_CHACHA
#define HAVE_POLY1305
/* Needed for Poly1305 */
#undef HAVE_ONE_TIME_AUTH
#define HAVE_ONE_TIME_AUTH
#endif
/* Ed25519 / Curve25519 */
#undef HAVE_CURVE25519
#undef HAVE_ED25519
#if 0
#define HAVE_CURVE25519
#define HAVE_ED25519
/* Optionally use small math (less flash usage, but much slower) */
#if 0
#define CURVED25519_SMALL
#endif
#endif
/* ------------------------------------------------------------------------- */
/* Hashing */
/* ------------------------------------------------------------------------- */
/* Sha */
#undef NO_SHA
#if 1
/* 1k smaller, but 25% slower */
//#define USE_SLOW_SHA
#else
#define NO_SHA
#endif
/* Sha256 */
#undef NO_SHA256
#if 1
#else
#define NO_SHA256
#endif
/* Sha512 */
#undef WOLFSSL_SHA512
#if 1
#define WOLFSSL_SHA512
/* Sha384 */
#undef WOLFSSL_SHA384
#if 1
#define WOLFSSL_SHA384
#endif
/* over twice as small, but 50% slower */
//#define USE_SLOW_SHA2
#endif
/* MD5 */
#undef NO_MD5
#if 1
#else
#define NO_MD5
#endif
/* ------------------------------------------------------------------------- */
/* Benchmark / Test */
/* ------------------------------------------------------------------------- */
/* Use reduced benchmark / test sizes */
#undef BENCH_EMBEDDED
#define BENCH_EMBEDDED
#undef USE_CERT_BUFFERS_2048
#define USE_CERT_BUFFERS_2048
#undef USE_CERT_BUFFERS_1024
//#define USE_CERT_BUFFERS_1024
#undef USE_CERT_BUFFERS_256
#define USE_CERT_BUFFERS_256
/* ------------------------------------------------------------------------- */
/* Time */
/* ------------------------------------------------------------------------- */
#if 0
#warning Time/RTC disabled
#undef NO_ASN_TIME
#define NO_ASN_TIME
#endif
/* ------------------------------------------------------------------------- */
/* Debugging */
/* ------------------------------------------------------------------------- */
#undef DEBUG_WOLFSSL
#define DEBUG_WOLFSSL
#undef DEBUG_WOLFSSH
#define DEBUG_WOLFSSH
#ifdef DEBUG_WOLFSSL
/* Use this to measure / print heap usage */
#if 0
#undef USE_WOLFSSL_MEMORY
#define USE_WOLFSSL_MEMORY
#undef WOLFSSL_TRACK_MEMORY
#define WOLFSSL_TRACK_MEMORY
#endif
#else
#undef NO_WOLFSSL_MEMORY
#define NO_WOLFSSL_MEMORY
#undef NO_ERROR_STRINGS
//#define NO_ERROR_STRINGS
#endif
/* ------------------------------------------------------------------------- */
/* Enable Features */
/* ------------------------------------------------------------------------- */
#undef KEEP_PEER_CERT
//#define KEEP_PEER_CERT
#undef HAVE_COMP_KEY
//#define HAVE_COMP_KEY
#undef HAVE_TLS_EXTENSIONS
//#define HAVE_TLS_EXTENSIONS
#undef HAVE_SUPPORTED_CURVES
//#define HAVE_SUPPORTED_CURVES
#undef WOLFSSL_BASE64_ENCODE
//#define WOLFSSL_BASE64_ENCODE
/* TLS Session Cache */
#if 0
#define SMALL_SESSION_CACHE
#else
#define NO_SESSION_CACHE
#endif
/* ------------------------------------------------------------------------- */
/* Disable Features */
/* ------------------------------------------------------------------------- */
#undef NO_WOLFSSL_SERVER
//#define NO_WOLFSSL_SERVER
#undef NO_WOLFSSL_CLIENT
//#define NO_WOLFSSL_CLIENT
#undef NO_CRYPT_TEST
#define NO_CRYPT_TEST
#undef NO_CRYPT_BENCHMARK
#define NO_CRYPT_BENCHMARK
/* In-lining of misc.c functions */
/* If defined, must include wolfcrypt/src/misc.c in build */
/* Slower, but about 1k smaller */
#undef NO_INLINE
//#define NO_INLINE
#undef NO_FILESYSTEM
#define NO_FILESYSTEM
#undef NO_WRITEV
#define NO_WRITEV
#undef NO_MAIN_DRIVER
#define NO_MAIN_DRIVER
#undef NO_DEV_RANDOM
#define NO_DEV_RANDOM
#undef NO_DSA
#define NO_DSA
//#undef NO_DH
//#define NO_DH
#undef NO_RC4
#define NO_RC4
#undef NO_OLD_TLS
#define NO_OLD_TLS
#undef NO_HC128
#define NO_HC128
#undef NO_RABBIT
#define NO_RABBIT
#undef NO_PSK
#define NO_PSK
#undef NO_MD4
#define NO_MD4
#undef NO_PWDBASED
#define NO_PWDBASED
#undef NO_CODING
//#define NO_CODING
#undef SINGLE_THREADED
//#define SINGLE_THREADED
#undef NO_WOLFSSL_DIR
#define NO_WOLFSSL_DIR
#undef WOLFCRYPT_ONLY
#define WOLFCRYPT_ONLY
/* Suppress array-bounds */
#pragma GCC diagnostic ignored "-Warray-bounds"
#ifdef __cplusplus
}
#endif
#endif /* WOLFSSL_USER_SETTINGS_H */

View File

@ -0,0 +1,636 @@
/* wolfssh.c
*
* Copyright (C) 2014-2016 wolfSSL Inc.
*
* This file is part of wolfSSH.
*
* wolfSSH is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
*/
/* Uses portions of code from the wolfssh/examples/echoserver.c example */
#include "app.h"
#include "tcpip/tcpip.h"
#include <wolfssh/ssh.h>
#include <wolfssh/test.h>
#include <wolfssh/certs_test.h>
#include <wolfssh/log.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/coding.h>
#define SERVER_PORT 22
typedef enum
{
APP_SSH_TCPIP_WAIT_INIT,
APP_SSH_TCPIP_WAIT_FOR_IP,
APP_SSH_CTX_INIT,
APP_SSH_USERAUTH_INIT,
APP_SSH_LOADKEY,
APP_SSH_CREATE_SOCKET,
APP_SSH_LISTEN,
APP_SSH_CLEANUP,
APP_SSH_OPERATION,
APP_SSH_ACCEPT,
APP_SSH_ERROR
} APP_SSH_STATES;
typedef struct APP_SSH_DATA
{
APP_SSH_STATES state;
TCP_SOCKET socket;
} APP_SSH_DATA;
APP_SSH_DATA appData;
static WOLFSSH_CTX* ctx;
static WOLFSSH* ssh;
#ifndef EXAMPLE_HIGHWATER_MARK
#define EXAMPLE_HIGHWATER_MARK 0x3FFF8000 /* 1GB - 32kB */
#endif
#ifndef EXAMPLE_BUFFER_SZ
#define EXAMPLE_BUFFER_SZ 4096
#endif
#define SCRATCH_BUFFER_SZ 1200
static INLINE void c32toa(word32 u32, byte* c)
{
c[0] = (u32 >> 24) & 0xff;
c[1] = (u32 >> 16) & 0xff;
c[2] = (u32 >> 8) & 0xff;
c[3] = u32 & 0xff;
}
/* Map user names to passwords */
/* Use arrays for username and p. The password or public key can
* be hashed and the hash stored here. Then I won't need the type. */
typedef struct PwMap {
byte type;
byte username[32];
word32 usernameSz;
byte p[SHA256_DIGEST_SIZE];
struct PwMap* next;
} PwMap;
typedef struct PwMapList {
PwMap* head;
} PwMapList;
PwMapList pwMapList;
static const char echoserverBanner[] = "wolfSSH Example Echo Server\n";
static const char samplePasswordBuffer[] =
"jill:upthehill\n"
"jack:fetchapail\n";
static const char samplePublicKeyEccBuffer[] =
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA"
"BBBNkI5JTP6D0lF42tbxX19cE87hztUS6FSDoGvPfiU0CgeNSbI+aFdKIzTP5CQEJSvm25"
"qUzgDtH7oyaQROUnNvk= hansel\n"
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA"
"BBBKAtH8cqaDbtJFjtviLobHBmjCtG56DMkP6A4M2H9zX2/YCg1h9bYS7WHd9UQDwXO1Hh"
"IZzRYecXh7SG9P4GhRY= gretel\n";
static const char samplePublicKeyRsaBuffer[] =
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGho"
"MNiisWSgUs5HdHcACuHYPi2W6Z1PBFmBWT9odOrGRjoZXJfDDoPi+j8SSfDGsc/hsCmc3G"
"p2yEhUZUEkDhtOXyqjns1ickC9Gh4u80aSVtwHRnJZh9xPhSq5tLOhId4eP61s+a5pwjTj"
"nEhBaIPUJO2C/M0pFnnbZxKgJlX7t1Doy7h5eXxviymOIvaCZKU+x5OopfzM/wFkey0EPW"
"NmzI5y/+pzU5afsdeEWdiQDIQc80H6Pz8fsoFPvYSG+s4/wz0duu7yeeV1Ypoho65Zr+pE"
"nIf7dO0B8EblgWt+ud+JI8wrAhfE4x hansel\n"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqDwRVTRVk/wjPhoo66+Mztrc31KsxDZ"
"+kAV0139PHQ+wsueNpba6jNn5o6mUTEOrxrz0LMsDJOBM7CmG0983kF4gRIihECpQ0rcjO"
"P6BSfbVTE9mfIK5IsUiZGd8SoE9kSV2pJ2FvZeBQENoAxEFk0zZL9tchPS+OCUGbK4SDjz"
"uNZl/30Mczs73N3MBzi6J1oPo7sFlqzB6ecBjK2Kpjus4Y1rYFphJnUxtKvB0s+hoaadru"
"biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI"
"RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n";
static int wsUserAuth(byte authType,
WS_UserAuthData* authData,
void* ctx)
{
PwMapList* list;
PwMap* map;
byte authHash[SHA256_DIGEST_SIZE];
if (ctx == NULL) {
SYS_CONSOLE_MESSAGE("wsUserAuth: ctx not set");
return WOLFSSH_USERAUTH_FAILURE;
}
if (authType != WOLFSSH_USERAUTH_PASSWORD &&
authType != WOLFSSH_USERAUTH_PUBLICKEY) {
return WOLFSSH_USERAUTH_FAILURE;
}
/* Hash the password or public key with its length. */
{
wc_Sha256 sha;
byte flatSz[4];
wc_InitSha256(&sha);
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
c32toa(authData->sf.password.passwordSz, flatSz);
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
wc_Sha256Update(&sha,
authData->sf.password.password,
authData->sf.password.passwordSz);
}
else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) {
c32toa(authData->sf.publicKey.publicKeySz, flatSz);
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
wc_Sha256Update(&sha,
authData->sf.publicKey.publicKey,
authData->sf.publicKey.publicKeySz);
}
wc_Sha256Final(&sha, authHash);
}
list = (PwMapList*)ctx;
map = list->head;
while (map != NULL) {
if (authData->usernameSz == map->usernameSz &&
memcmp(authData->username, map->username, map->usernameSz) == 0) {
if (authData->type == map->type) {
if (memcmp(map->p, authHash, SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
return (authType == WOLFSSH_USERAUTH_PASSWORD ?
WOLFSSH_USERAUTH_INVALID_PASSWORD :
WOLFSSH_USERAUTH_INVALID_PUBLICKEY);
}
}
else {
return WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
}
}
map = map->next;
}
return WOLFSSH_USERAUTH_INVALID_USER;
}
static void PwMapListDelete(PwMapList* list)
{
if (list != NULL) {
PwMap* head = list->head;
while (head != NULL) {
PwMap* cur = head;
head = head->next;
memset(cur, 0, sizeof(PwMap));
free(cur);
}
}
}
static PwMap* PwMapNew(PwMapList* list, byte type, const byte* username,
word32 usernameSz, const byte* p, word32 pSz)
{
PwMap* map;
map = (PwMap*)malloc(sizeof(PwMap));
if (map != NULL) {
Sha256 sha;
byte flatSz[4];
map->type = type;
if (usernameSz >= sizeof(map->username))
usernameSz = sizeof(map->username) - 1;
memcpy(map->username, username, usernameSz + 1);
map->username[usernameSz] = 0;
map->usernameSz = usernameSz;
wc_InitSha256(&sha);
c32toa(pSz, flatSz);
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
wc_Sha256Update(&sha, p, pSz);
wc_Sha256Final(&sha, map->p);
map->next = list->head;
list->head = map;
}
return map;
}
static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list)
{
char* str = (char*)buf;
char* delimiter;
byte* publicKey64;
word32 publicKey64Sz;
byte* username;
word32 usernameSz;
byte publicKey[300];
word32 publicKeySz;
/* Each line of passwd.txt is in the format
* ssh-rsa AAAB3BASE64ENCODEDPUBLICKEYBLOB username\n
* This function modifies the passed-in buffer. */
if (list == NULL)
return -1;
if (buf == NULL || bufSz == 0)
return 0;
while (*str != 0) {
/* Skip the public key type. This example will always be ssh-rsa. */
delimiter = strchr(str, ' ');
str = delimiter + 1;
delimiter = strchr(str, ' ');
publicKey64 = (byte*)str;
*delimiter = 0;
publicKey64Sz = (word32)(delimiter - str);
str = delimiter + 1;
delimiter = strchr(str, '\n');
username = (byte*)str;
*delimiter = 0;
usernameSz = (word32)(delimiter - str);
str = delimiter + 1;
publicKeySz = sizeof(publicKey);
if (Base64_Decode(publicKey64, publicKey64Sz,
publicKey, &publicKeySz) != 0) {
return -1;
}
if (PwMapNew(list, WOLFSSH_USERAUTH_PUBLICKEY,
username, usernameSz,
publicKey, publicKeySz) == NULL ) {
return -1;
}
}
return 0;
}
static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list)
{
char* str = (char*)buf;
char* delimiter;
char* username;
char* password;
/* Each line of passwd.txt is in the format
* username:password\n
* This function modifies the passed-in buffer. */
if (list == NULL)
return -1;
if (buf == NULL || bufSz == 0)
return 0;
while (*str != 0) {
delimiter = strchr(str, ':');
username = str;
*delimiter = 0;
password = delimiter + 1;
str = strchr(password, '\n');
*str = 0;
str++;
if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD,
(byte*)username, (word32)strlen(username),
(byte*)password, (word32)strlen(password)) == NULL ) {
return -1;
}
}
return 0;
}
#ifndef NO_FILESYSTEM
static int load_file(const char* fileName, byte* buf, word32 bufSz)
{
FILE* file;
word32 fileSz;
word32 readSz;
if (fileName == NULL) return 0;
if (WFOPEN(&file, fileName, "rb") != 0)
return 0;
fseek(file, 0, SEEK_END);
fileSz = (word32)ftell(file);
rewind(file);
if (fileSz > bufSz) {
fclose(file);
return 0;
}
readSz = (word32)fread(buf, 1, fileSz, file);
if (readSz < fileSz) {
fclose(file);
return 0;
}
fclose(file);
return fileSz;
}
#endif /* NO_FILESYSTEM */
/* returns buffer size on success */
static int load_key(byte isEcc, byte* buf, word32 bufSz)
{
word32 sz = 0;
#ifndef NO_FILESYSTEM
const char* bufName;
bufName = isEcc ? "./keys/server-key-ecc.der" :
"./keys/server-key-rsa.der" ;
sz = load_file(bufName, buf, SCRATCH_BUFFER_SZ);
#else
/* using buffers instead */
if (isEcc) {
if (sizeof_ecc_key_der_256 > bufSz) {
return 0;
}
WMEMCPY(buf, ecc_key_der_256, sizeof_ecc_key_der_256);
sz = sizeof_ecc_key_der_256;
}
else {
if (sizeof_rsa_key_der_2048 > bufSz) {
return 0;
}
WMEMCPY(buf, (byte*)rsa_key_der_2048, sizeof_rsa_key_der_2048);
sz = sizeof_rsa_key_der_2048;
}
#endif
return sz;
}
static byte find_char(const byte* str, const byte* buf, word32 bufSz)
{
const byte* cur;
while (bufSz) {
cur = str;
while (*cur != '\0') {
if (*cur == *buf)
return *cur;
cur++;
}
buf++;
bufSz--;
}
return 0;
}
#if 0
static void logCb(enum wolfSSH_LogLevel lvl, const char *const msg)
{
if (wolfSSH_LogEnabled()) {
SYS_CONSOLE_PRINT(msg);
SYS_CONSOLE_PRINT("\r\n");
SYS_CONSOLE_Tasks(sysObj.sysConsole0);
}
}
#endif
void APP_SSH_Initialize ( void )
{
appData.state = APP_SSH_CTX_INIT;
wolfSSH_Init();
#if 0
SYS_CONSOLE_PRINT("Turning on wolfSSH debugging\n\r");
wolfSSH_Debugging_ON();
wolfSSH_SetLoggingCb(logCb);
#endif
}
void APP_SSH_Tasks ( void )
{
int useEcc = 0;
switch(appData.state)
{
case APP_SSH_CTX_INIT:
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
if (ctx == NULL) {
SYS_CONSOLE_PRINT("Couldn't allocate SSH CTX data.\r\n");
appData.state = APP_SSH_ERROR;
}
appData.state = APP_SSH_USERAUTH_INIT;
break;
case APP_SSH_USERAUTH_INIT:
wolfSSH_SetUserAuth(ctx, wsUserAuth);
wolfSSH_CTX_SetBanner(ctx, echoserverBanner);
appData.state = APP_SSH_LOADKEY;
break;
case APP_SSH_LOADKEY:
{
const char* bufName;
byte buf[SCRATCH_BUFFER_SZ];
word32 bufSz;
bufSz = load_key(useEcc, buf, SCRATCH_BUFFER_SZ);
if (bufSz == 0) {
SYS_CONSOLE_PRINT("Couldn't load key file.\r\n");
appData.state = APP_SSH_ERROR;
break;
}
if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, buf, bufSz,
WOLFSSH_FORMAT_ASN1) < 0) {
SYS_CONSOLE_PRINT("Couldn't use key buffer.\r\n");
appData.state = APP_SSH_ERROR;
break;
}
bufSz = (word32)strlen(samplePasswordBuffer);
memcpy(buf, samplePasswordBuffer, bufSz);
buf[bufSz] = 0;
LoadPasswordBuffer(buf, bufSz, &pwMapList);
bufName = useEcc ? samplePublicKeyEccBuffer :
samplePublicKeyRsaBuffer;
bufSz = (word32)strlen(bufName);
memcpy(buf, bufName, bufSz);
buf[bufSz] = 0;
LoadPublicKeyBuffer(buf, bufSz, &pwMapList);
}
appData.state = APP_SSH_CREATE_SOCKET;
break;
case APP_SSH_CREATE_SOCKET:
/* Create a socket for listen and accepting connections on */
appData.socket = TCPIP_TCP_ServerOpen(IP_ADDRESS_TYPE_IPV4, SERVER_PORT, 0);
if (!TCPIP_TCP_OptionsSet(appData.socket, TCP_OPTION_NODELAY, (void*)1)) {
SYS_CONSOLE_PRINT("Unable to set no delay with TCP\r\n");
appData.state = APP_SSH_ERROR;
break;
}
appData.state = APP_SSH_LISTEN;
SYS_CONSOLE_PRINT("Waiting for client on to connect on port [%d]\r\n", SERVER_PORT);
break;
case APP_SSH_LISTEN:
if (TCPIP_TCP_IsConnected(appData.socket)) {
SYS_CONSOLE_PRINT("Creating WOLFSSH struct and doing accept\r\n");
ssh = wolfSSH_new(ctx);
if (ssh == NULL) {
SYS_CONSOLE_PRINT("Couldn't allocate SSH data.\r\n");
appData.state = APP_SSH_ERROR;
break;
}
wolfSSH_SetUserAuthCtx(ssh, &pwMapList);
wolfSSH_set_fd(ssh, appData.socket);
appData.state = APP_SSH_ACCEPT;
}
break;
case APP_SSH_ACCEPT:
{
int ret;
if ((ret = wolfSSH_accept(ssh)) == WS_SUCCESS) {
byte msg[] = "Successfully connected to wolfSSH PIC32 echoserver\n\r";
appData.state = APP_SSH_OPERATION;
SYS_CONSOLE_PRINT("wolfSSH accept success!\r\n");
wolfSSH_stream_send(ssh, msg, sizeof(msg));
break;
}
ret = wolfSSH_get_error(ssh);
if (ret != WS_WANT_READ && ret != WS_WANT_WRITE) {
/* connection was closed or error happened */
SYS_CONSOLE_PRINT("Error [%d] with wolfSSH connection. Closing socket.\r\n", ret);
appData.state = APP_SSH_CLEANUP;
}
}
break;
/* echo ssh input (example code from wolfssh/echoserver/echoserver.c) */
case APP_SSH_OPERATION:
{
byte* buf = NULL;
byte* tmpBuf;
int bufSz, backlogSz = 0, rxSz, txSz, stop = 0, txSum;
bufSz = EXAMPLE_BUFFER_SZ + backlogSz;
tmpBuf = (byte*)realloc(buf, bufSz);
if (tmpBuf == NULL)
appData.state = APP_SSH_CLEANUP;
else
buf = tmpBuf;
rxSz = wolfSSH_stream_read(ssh, buf + backlogSz,
EXAMPLE_BUFFER_SZ);
if (rxSz > 0) {
{
/* print out HEX value of received data */
int i;
SYS_CONSOLE_PRINT("wolfSSH server read HEX : \r\n");
for (i = 0; i < rxSz; i++) {
SYS_CONSOLE_PRINT("%02X", buf[backlogSz + i]);
}
SYS_CONSOLE_PRINT("\r\n");
}
backlogSz += rxSz;
txSum = 0;
txSz = 0;
while (backlogSz != txSum && txSz >= 0 && !stop) {
txSz = wolfSSH_stream_send(ssh,
buf + txSum,
backlogSz - txSum);
if (txSz > 0) {
byte c;
const byte matches[] = { 0x03, 0x05, 0x06, 0x00 };
c = find_char(matches, buf + txSum, txSz);
switch (c) {
case 0x03:
appData.state = APP_SSH_CLEANUP;
break;
case 0x06:
if (wolfSSH_TriggerKeyExchange(ssh)
!= WS_SUCCESS)
appData.state = APP_SSH_CLEANUP;
break;
default:
break;
}
txSum += txSz;
}
else if (txSz != WS_REKEYING) {
appData.state = APP_SSH_CLEANUP;
}
}
if (txSum < backlogSz)
memmove(buf, buf + txSum, backlogSz - txSum);
backlogSz -= txSum;
}
free(buf);
}
break;
case APP_SSH_CLEANUP:
SYS_CONSOLE_PRINT("Closing and cleaning up connection\r\n\r\n");
wolfSSH_free(ssh);
WCLOSESOCKET(wolfSSH_get_fd(ssh));
appData.state = APP_SSH_CREATE_SOCKET;
break;
case APP_SSH_ERROR:
{
static int set = 0;
if (!set) {
set = 1;
wolfSSH_CTX_free(ctx);
PwMapListDelete(&pwMapList);
if (wolfSSH_Cleanup() != WS_SUCCESS) {
SYS_CONSOLE_PRINT("wolfSSH Cleanup Error.\r\n");
}
SYS_CONSOLE_PRINT("In error state\r\n");
}
}
break;
default:
SYS_CONSOLE_PRINT("Unknown state!\r\n");
appData.state = APP_SSH_ERROR;
break;
}
}