wolfssh/examples/client/common.c

1142 lines
40 KiB
C

/* common.c
*
* Copyright (C) 2014-2024 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/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define WOLFSSH_TEST_CLIENT
#include <stdio.h>
#include <wolfssh/ssh.h>
#include <wolfssh/internal.h>
#include <wolfssh/wolfsftp.h>
#include <wolfssh/port.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/coding.h>
#ifdef WOLFSSH_TPM
#include <wolftpm/tpm2_wrap.h>
#include <hal/tpm_io.h>
#endif
#include "examples/client/common.h"
#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) && \
!defined(WOLFSSH_ZEPHYR)
#include <termios.h>
#endif
#ifdef WOLFSSH_CERTS
#include <wolfssl/wolfcrypt/asn.h>
#endif
static byte userPublicKeyBuf[512];
static byte* userPublicKey = userPublicKeyBuf;
static const byte* userPublicKeyType = NULL;
static byte userPassword[256];
static const byte* userPrivateKeyType = NULL;
static word32 userPublicKeySz = 0;
static byte pubKeyLoaded = 0; /* was a public key loaded */
static byte userPrivateKeyBuf[1191]; /* Size equal to hanselPrivateRsaSz. */
static byte* userPrivateKey = userPrivateKeyBuf;
static word32 userPublicKeyTypeSz = 0;
static byte userPrivateKeyAlloc = 0;
static word32 userPrivateKeySz = 0;
static word32 userPrivateKeyTypeSz = 0;
static byte isPrivate = 0;
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
static word32 keyboardResponseCount = 0;
static byte** keyboardResponses;
static word32* keyboardResponseLengths;
#endif
#ifdef WOLFSSH_CERTS
#if 0
/* compiled in for using RSA certificates instead of ECC certificate */
static const byte publicKeyType[] = "x509v3-ssh-rsa";
static const byte privateKeyType[] = "ssh-rsa";
#else
static const byte publicKeyType[] = "x509v3-ecdsa-sha2-nistp256";
#endif
#endif
#ifdef WOLFSSH_TPM
WOLFTPM2_DEV tpmDev;
WOLFTPM2_KEY tpmKey;
#endif /* WOLFSSH_TPM */
#ifndef WOLFSSH_NO_RSA
static const char* hanselPublicRsa =
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGho"
"MNiisWSgUs5HdHcACuHYPi2W6Z1PBFmBWT9odOrGRjoZXJfDDoPi+j8SSfDGsc/hsCmc3G"
"p2yEhUZUEkDhtOXyqjns1ickC9Gh4u80aSVtwHRnJZh9xPhSq5tLOhId4eP61s+a5pwjTj"
"nEhBaIPUJO2C/M0pFnnbZxKgJlX7t1Doy7h5eXxviymOIvaCZKU+x5OopfzM/wFkey0EPW"
"NmzI5y/+pzU5afsdeEWdiQDIQc80H6Pz8fsoFPvYSG+s4/wz0duu7yeeV1Ypoho65Zr+pE"
"nIf7dO0B8EblgWt+ud+JI8wrAhfE4x hansel";
static const byte hanselPrivateRsa[] = {
0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
0xbd, 0x3f, 0x76, 0x45, 0xa3, 0x03, 0xac, 0x38, 0xd5, 0xc7, 0x0f, 0x93,
0x30, 0x5a, 0x20, 0x9c, 0x89, 0x7c, 0xad, 0x05, 0x16, 0x46, 0x86, 0x83,
0x0d, 0x8a, 0x2b, 0x16, 0x4a, 0x05, 0x2c, 0xe4, 0x77, 0x47, 0x70, 0x00,
0xae, 0x1d, 0x83, 0xe2, 0xd9, 0x6e, 0x99, 0xd4, 0xf0, 0x45, 0x98, 0x15,
0x93, 0xf6, 0x87, 0x4e, 0xac, 0x64, 0x63, 0xa1, 0x95, 0xc9, 0x7c, 0x30,
0xe8, 0x3e, 0x2f, 0xa3, 0xf1, 0x24, 0x9f, 0x0c, 0x6b, 0x1c, 0xfe, 0x1b,
0x02, 0x99, 0xcd, 0xc6, 0xa7, 0x6c, 0x84, 0x85, 0x46, 0x54, 0x12, 0x40,
0xe1, 0xb4, 0xe5, 0xf2, 0xaa, 0x39, 0xec, 0xd6, 0x27, 0x24, 0x0b, 0xd1,
0xa1, 0xe2, 0xef, 0x34, 0x69, 0x25, 0x6d, 0xc0, 0x74, 0x67, 0x25, 0x98,
0x7d, 0xc4, 0xf8, 0x52, 0xab, 0x9b, 0x4b, 0x3a, 0x12, 0x1d, 0xe1, 0xe3,
0xfa, 0xd6, 0xcf, 0x9a, 0xe6, 0x9c, 0x23, 0x4e, 0x39, 0xc4, 0x84, 0x16,
0x88, 0x3d, 0x42, 0x4e, 0xd8, 0x2f, 0xcc, 0xd2, 0x91, 0x67, 0x9d, 0xb6,
0x71, 0x2a, 0x02, 0x65, 0x5f, 0xbb, 0x75, 0x0e, 0x8c, 0xbb, 0x87, 0x97,
0x97, 0xc6, 0xf8, 0xb2, 0x98, 0xe2, 0x2f, 0x68, 0x26, 0x4a, 0x53, 0xec,
0x79, 0x3a, 0x8a, 0x5f, 0xcc, 0xcf, 0xf0, 0x16, 0x47, 0xb2, 0xd0, 0x43,
0xd6, 0x36, 0x6c, 0xc8, 0xe7, 0x2f, 0xfe, 0xa7, 0x35, 0x39, 0x69, 0xfb,
0x1d, 0x78, 0x45, 0x9d, 0x89, 0x00, 0xc8, 0x41, 0xcf, 0x34, 0x1f, 0xa3,
0xf3, 0xf1, 0xfb, 0x28, 0x14, 0xfb, 0xd8, 0x48, 0x6f, 0xac, 0xe3, 0xfc,
0x33, 0xd1, 0xdb, 0xae, 0xef, 0x27, 0x9e, 0x57, 0x56, 0x29, 0xa2, 0x1a,
0x3a, 0xe5, 0x9a, 0xfe, 0xa4, 0x49, 0xc8, 0x7f, 0xb7, 0x4e, 0xd0, 0x1f,
0x04, 0x6e, 0x58, 0x16, 0xb7, 0xeb, 0x9d, 0xf8, 0x92, 0x3c, 0xc2, 0xb0,
0x21, 0x7c, 0x4e, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
0x01, 0x00, 0x8d, 0xa4, 0x61, 0x06, 0x2f, 0xc3, 0x40, 0xf4, 0x6c, 0xf4,
0x87, 0x30, 0xb8, 0x00, 0xcc, 0xe5, 0xbc, 0x75, 0x87, 0x1e, 0x06, 0x95,
0x14, 0x7a, 0x23, 0xf9, 0x24, 0xd4, 0x92, 0xe4, 0x1a, 0xbc, 0x88, 0x95,
0xfc, 0x3b, 0x56, 0x16, 0x1b, 0x2e, 0xff, 0x64, 0x2b, 0x58, 0xd7, 0xd8,
0x8e, 0xc2, 0x9f, 0xb2, 0xe5, 0x84, 0xb9, 0xbc, 0x8d, 0x61, 0x54, 0x35,
0xb0, 0x70, 0xfe, 0x72, 0x04, 0xc0, 0x24, 0x6d, 0x2f, 0x69, 0x61, 0x06,
0x1b, 0x1d, 0xe6, 0x2d, 0x6d, 0x79, 0x60, 0xb7, 0xf4, 0xdb, 0xb7, 0x4e,
0x97, 0x36, 0xde, 0x77, 0xc1, 0x9f, 0x85, 0x4e, 0xc3, 0x77, 0x69, 0x66,
0x2e, 0x3e, 0x61, 0x76, 0xf3, 0x67, 0xfb, 0xc6, 0x9a, 0xc5, 0x6f, 0x99,
0xff, 0xe6, 0x89, 0x43, 0x92, 0x44, 0x75, 0xd2, 0x4e, 0x54, 0x91, 0x58,
0xb2, 0x48, 0x2a, 0xe6, 0xfa, 0x0d, 0x4a, 0xca, 0xd4, 0x14, 0x9e, 0xf6,
0x27, 0x67, 0xb7, 0x25, 0x7a, 0x43, 0xbb, 0x2b, 0x67, 0xd1, 0xfe, 0xd1,
0x68, 0x23, 0x06, 0x30, 0x7c, 0xbf, 0x60, 0x49, 0xde, 0xcc, 0x7e, 0x26,
0x5a, 0x3b, 0xfe, 0xa6, 0xa6, 0xe7, 0xa8, 0xdd, 0xac, 0xb9, 0xaf, 0x82,
0x9a, 0x3a, 0x41, 0x7e, 0x61, 0x21, 0x37, 0xa3, 0x08, 0xe4, 0xc4, 0xbc,
0x11, 0xf5, 0x3b, 0x8e, 0x4d, 0x51, 0xf3, 0xbd, 0xda, 0xba, 0xb2, 0xc5,
0xee, 0xfb, 0xcf, 0xdf, 0x83, 0xa1, 0x82, 0x01, 0xe1, 0x51, 0x9d, 0x07,
0x5a, 0x5d, 0xd8, 0xc7, 0x5b, 0x3f, 0x97, 0x13, 0x6a, 0x4d, 0x1e, 0x8d,
0x39, 0xac, 0x40, 0x95, 0x82, 0x6c, 0xa2, 0xa1, 0xcc, 0x8a, 0x9b, 0x21,
0x32, 0x3a, 0x58, 0xcc, 0xe7, 0x2d, 0x1a, 0x79, 0xa4, 0x31, 0x50, 0xb1,
0x4b, 0x76, 0x23, 0x1b, 0xb3, 0x40, 0x3d, 0x3d, 0x72, 0x72, 0x32, 0xec,
0x5f, 0x38, 0xb5, 0x8d, 0xb2, 0x8d, 0x02, 0x81, 0x81, 0x00, 0xed, 0x5a,
0x7e, 0x8e, 0xa1, 0x62, 0x7d, 0x26, 0x5c, 0x78, 0xc4, 0x87, 0x71, 0xc9,
0x41, 0x57, 0x77, 0x94, 0x93, 0x93, 0x26, 0x78, 0xc8, 0xa3, 0x15, 0xbd,
0x59, 0xcb, 0x1b, 0xb4, 0xb2, 0x6b, 0x0f, 0xe7, 0x80, 0xf2, 0xfa, 0xfc,
0x8e, 0x32, 0xa9, 0x1b, 0x1e, 0x7f, 0xe1, 0x26, 0xef, 0x00, 0x25, 0xd8,
0xdd, 0xc9, 0x1a, 0x23, 0x00, 0x26, 0x3b, 0x46, 0x23, 0xc0, 0x50, 0xe7,
0xce, 0x62, 0xb2, 0x36, 0xb2, 0x98, 0x09, 0x16, 0x34, 0x18, 0x9e, 0x46,
0xbc, 0xaf, 0x2c, 0x28, 0x94, 0x2f, 0xe0, 0x5d, 0xc9, 0xb2, 0xc8, 0xfb,
0x5d, 0x13, 0xd5, 0x36, 0xaa, 0x15, 0x0f, 0x89, 0xa5, 0x16, 0x59, 0x5d,
0x22, 0x74, 0xa4, 0x47, 0x5d, 0xfa, 0xfb, 0x0c, 0x5e, 0x80, 0xbf, 0x0f,
0xc2, 0x9c, 0x95, 0x0f, 0xe7, 0xaa, 0x7f, 0x16, 0x1b, 0xd4, 0xdb, 0x38,
0x7d, 0x58, 0x2e, 0x57, 0x78, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xcc, 0x1d,
0x7f, 0x74, 0x36, 0x6d, 0xb4, 0x92, 0x25, 0x62, 0xc5, 0x50, 0xb0, 0x5c,
0xa1, 0xda, 0xf3, 0xb2, 0xfd, 0x1e, 0x98, 0x0d, 0x8b, 0x05, 0x69, 0x60,
0x8e, 0x5e, 0xd2, 0x89, 0x90, 0x4a, 0x0d, 0x46, 0x7e, 0xe2, 0x54, 0x69,
0xae, 0x16, 0xe6, 0xcb, 0xd5, 0xbd, 0x7b, 0x30, 0x2b, 0x7b, 0x5c, 0xee,
0x93, 0x12, 0xcf, 0x63, 0x89, 0x9c, 0x3d, 0xc8, 0x2d, 0xe4, 0x7a, 0x61,
0x09, 0x5e, 0x80, 0xfb, 0x3c, 0x03, 0xb3, 0x73, 0xd6, 0x98, 0xd0, 0x84,
0x0c, 0x59, 0x9f, 0x4e, 0x80, 0xf3, 0x46, 0xed, 0x03, 0x9d, 0xd5, 0xdc,
0x8b, 0xe7, 0xb1, 0xe8, 0xaa, 0x57, 0xdc, 0xd1, 0x41, 0x55, 0x07, 0xc7,
0xdf, 0x67, 0x3c, 0x72, 0x78, 0xb0, 0x60, 0x8f, 0x85, 0xa1, 0x90, 0x99,
0x0c, 0xa5, 0x67, 0xab, 0xf0, 0xb6, 0x74, 0x90, 0x03, 0x55, 0x7b, 0x5e,
0xcc, 0xc5, 0xbf, 0xde, 0xa7, 0x9f, 0x02, 0x81, 0x80, 0x40, 0x81, 0x6e,
0x91, 0xae, 0xd4, 0x88, 0x74, 0xab, 0x7e, 0xfa, 0xd2, 0x60, 0x9f, 0x34,
0x8d, 0xe3, 0xe6, 0xd2, 0x30, 0x94, 0xad, 0x10, 0xc2, 0x19, 0xbf, 0x6b,
0x2e, 0xe2, 0xe9, 0xb9, 0xef, 0x94, 0xd3, 0xf2, 0xdc, 0x96, 0x4f, 0x9b,
0x09, 0xb3, 0xa1, 0xb6, 0x29, 0x44, 0xf4, 0x82, 0xd1, 0xc4, 0x77, 0x6a,
0xd7, 0x23, 0xae, 0x4d, 0x75, 0x16, 0x78, 0xda, 0x70, 0x82, 0xcc, 0x6c,
0xef, 0xaf, 0xc5, 0x63, 0xc6, 0x23, 0xfa, 0x0f, 0xd0, 0x7c, 0xfb, 0x76,
0x7e, 0x18, 0xff, 0x32, 0x3e, 0xcc, 0xb8, 0x50, 0x7f, 0xb1, 0x55, 0x77,
0x17, 0x53, 0xc3, 0xd6, 0x77, 0x80, 0xd0, 0x84, 0xb8, 0x4d, 0x33, 0x1d,
0x91, 0x1b, 0xb0, 0x75, 0x9f, 0x27, 0x29, 0x56, 0x69, 0xa1, 0x03, 0x54,
0x7d, 0x9f, 0x99, 0x41, 0xf9, 0xb9, 0x2e, 0x36, 0x04, 0x24, 0x4b, 0xf6,
0xec, 0xc7, 0x33, 0x68, 0x6b, 0x02, 0x81, 0x80, 0x60, 0x35, 0xcb, 0x3c,
0xd0, 0xe6, 0xf7, 0x05, 0x28, 0x20, 0x1d, 0x57, 0x82, 0x39, 0xb7, 0x85,
0x07, 0xf7, 0xa7, 0x3d, 0xc3, 0x78, 0x26, 0xbe, 0x3f, 0x44, 0x66, 0xf7,
0x25, 0x0f, 0xf8, 0x76, 0x1f, 0x39, 0xca, 0x57, 0x0e, 0x68, 0xdd, 0xc9,
0x27, 0xb2, 0x8e, 0xa6, 0x08, 0xa9, 0xd4, 0xe5, 0x0a, 0x11, 0xde, 0x3b,
0x30, 0x8b, 0xff, 0x72, 0x28, 0xe0, 0xf1, 0x58, 0xcf, 0xa2, 0x6b, 0x93,
0x23, 0x02, 0xc8, 0xf0, 0x09, 0xa7, 0x21, 0x50, 0xd8, 0x80, 0x55, 0x7d,
0xed, 0x0c, 0x48, 0xd5, 0xe2, 0xe9, 0x97, 0x19, 0xcf, 0x93, 0x6c, 0x52,
0xa2, 0xd6, 0x43, 0x6c, 0xb4, 0xc5, 0xe1, 0xa0, 0x9d, 0xd1, 0x45, 0x69,
0x58, 0xe1, 0xb0, 0x27, 0x9a, 0xec, 0x2b, 0x95, 0xd3, 0x1d, 0x81, 0x0b,
0x7a, 0x09, 0x5e, 0xa5, 0xf1, 0xdd, 0x6b, 0xe4, 0xe0, 0x08, 0xf8, 0x46,
0x81, 0xc1, 0x06, 0x8b, 0x02, 0x81, 0x80, 0x00, 0xf6, 0xf2, 0xeb, 0x25,
0xba, 0x78, 0x04, 0xad, 0x0e, 0x0d, 0x2e, 0xa7, 0x69, 0xd6, 0x57, 0xe6,
0x36, 0x32, 0x50, 0xd2, 0xf2, 0xeb, 0xad, 0x31, 0x46, 0x65, 0xc0, 0x07,
0x97, 0x83, 0x6c, 0x66, 0x27, 0x3e, 0x94, 0x2c, 0x05, 0x01, 0x5f, 0x5c,
0xe0, 0x31, 0x30, 0xec, 0x61, 0xd2, 0x74, 0x35, 0xb7, 0x9f, 0x38, 0xe7,
0x8e, 0x67, 0xb1, 0x50, 0x08, 0x68, 0xce, 0xcf, 0xd8, 0xee, 0x88, 0xfd,
0x5d, 0xc4, 0xcd, 0xe2, 0x86, 0x3d, 0x4a, 0x0e, 0x04, 0x7f, 0xee, 0x8a,
0xe8, 0x9b, 0x16, 0xa1, 0xfc, 0x09, 0x82, 0xe2, 0x62, 0x03, 0x3c, 0xe8,
0x25, 0x7f, 0x3c, 0x9a, 0xaa, 0x83, 0xf8, 0xd8, 0x93, 0xd1, 0x54, 0xf9,
0xce, 0xb4, 0xfa, 0x35, 0x36, 0xcc, 0x18, 0x54, 0xaa, 0xf2, 0x90, 0xb7,
0x7c, 0x97, 0x0b, 0x27, 0x2f, 0xae, 0xfc, 0xc3, 0x93, 0xaf, 0x1a, 0x75,
0xec, 0x18, 0xdb
};
static const unsigned int hanselPrivateRsaSz = 1191;
#endif
#ifndef WOLFSSH_NO_ECC
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
static const char* hanselPublicEcc =
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA"
"BBBNkI5JTP6D0lF42tbxX19cE87hztUS6FSDoGvPfiU0CgeNSbI+aFdKIzTP5CQEJSvm25"
"qUzgDtH7oyaQROUnNvk= hansel";
static const byte hanselPrivateEcc[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x03, 0x6e, 0x17, 0xd3, 0xb9,
0xb8, 0xab, 0xc8, 0xf9, 0x1f, 0xf1, 0x2d, 0x44, 0x4c, 0x3b, 0x12, 0xb1,
0xa4, 0x77, 0xd8, 0xed, 0x0e, 0x6a, 0xbe, 0x60, 0xc2, 0xf6, 0x8b, 0xe7,
0xd3, 0x87, 0x83, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xd9, 0x08, 0xe4,
0x94, 0xcf, 0xe8, 0x3d, 0x25, 0x17, 0x8d, 0xad, 0x6f, 0x15, 0xf5, 0xf5,
0xc1, 0x3c, 0xee, 0x1c, 0xed, 0x51, 0x2e, 0x85, 0x48, 0x3a, 0x06, 0xbc,
0xf7, 0xe2, 0x53, 0x40, 0xa0, 0x78, 0xd4, 0x9b, 0x23, 0xe6, 0x85, 0x74,
0xa2, 0x33, 0x4c, 0xfe, 0x42, 0x40, 0x42, 0x52, 0xbe, 0x6d, 0xb9, 0xa9,
0x4c, 0xe0, 0x0e, 0xd1, 0xfb, 0xa3, 0x26, 0x90, 0x44, 0xe5, 0x27, 0x36,
0xf9
};
static const unsigned int hanselPrivateEccSz = 121;
#elif !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
static const char* hanselPublicEcc =
"ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAA"
"CFBAET/BOzBb9Jx9b52VIHFP4g/uk5KceDpz2M+/Ln9WiDjsMfb4NgNCAB+EMNJUX/TNBL"
"FFmqr7c6+zUH+QAo2qstvQDsReyFkETRB2vZD//nCZfcAe0RMtKZmgtQLKXzSlimUjXBM4"
"/zE5lwE05aXADp88h8nuaT/X4bll9cWJlH0fUykA== hansel";
static const byte hanselPrivateEcc[] = {
0x30, 0x81, 0xdc, 0x02, 0x01, 0x01, 0x04, 0x42, 0x01, 0x79, 0x40, 0xb8,
0x33, 0xe5, 0x53, 0x5b, 0x9e, 0xfd, 0xed, 0xbe, 0x7c, 0x68, 0xe4, 0xb6,
0xc3, 0x50, 0x00, 0x0d, 0x39, 0x64, 0x05, 0xf6, 0x5a, 0x5d, 0x41, 0xab,
0xb3, 0xd9, 0xa7, 0xcb, 0x1c, 0x7d, 0x34, 0x46, 0x5c, 0x2d, 0x56, 0x26,
0xa0, 0x6a, 0xc7, 0x3d, 0x4f, 0x78, 0x58, 0x14, 0x66, 0x6c, 0xfc, 0x86,
0x3c, 0x8b, 0x5b, 0x54, 0x29, 0x89, 0x93, 0x48, 0xd9, 0x54, 0x8b, 0xbe,
0x9d, 0x91, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0xa1,
0x81, 0x89, 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x13, 0xfc, 0x13, 0xb3,
0x05, 0xbf, 0x49, 0xc7, 0xd6, 0xf9, 0xd9, 0x52, 0x07, 0x14, 0xfe, 0x20,
0xfe, 0xe9, 0x39, 0x29, 0xc7, 0x83, 0xa7, 0x3d, 0x8c, 0xfb, 0xf2, 0xe7,
0xf5, 0x68, 0x83, 0x8e, 0xc3, 0x1f, 0x6f, 0x83, 0x60, 0x34, 0x20, 0x01,
0xf8, 0x43, 0x0d, 0x25, 0x45, 0xff, 0x4c, 0xd0, 0x4b, 0x14, 0x59, 0xaa,
0xaf, 0xb7, 0x3a, 0xfb, 0x35, 0x07, 0xf9, 0x00, 0x28, 0xda, 0xab, 0x2d,
0xbd, 0x00, 0xec, 0x45, 0xec, 0x85, 0x90, 0x44, 0xd1, 0x07, 0x6b, 0xd9,
0x0f, 0xff, 0xe7, 0x09, 0x97, 0xdc, 0x01, 0xed, 0x11, 0x32, 0xd2, 0x99,
0x9a, 0x0b, 0x50, 0x2c, 0xa5, 0xf3, 0x4a, 0x58, 0xa6, 0x52, 0x35, 0xc1,
0x33, 0x8f, 0xf3, 0x13, 0x99, 0x70, 0x13, 0x4e, 0x5a, 0x5c, 0x00, 0xe9,
0xf3, 0xc8, 0x7c, 0x9e, 0xe6, 0x93, 0xfd, 0x7e, 0x1b, 0x96, 0x5f, 0x5c,
0x58, 0x99, 0x47, 0xd1, 0xf5, 0x32, 0x90
};
static const unsigned int hanselPrivateEccSz = 223;
#else
#error "Enable an ECC Curve or disable ECC."
#endif
#endif
#if defined(WOLFSSH_CERTS)
static int load_der_file(const char* filename, byte** out, word32* outSz,
void* heap)
{
WFILE* file;
byte* in;
word32 inSz;
int ret;
if (filename == NULL || out == NULL || outSz == NULL)
return -1;
ret = WFOPEN(NULL, &file, filename, "rb");
if (ret != 0 || file == WBADFILE)
return -1;
if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) {
WFCLOSE(NULL, file);
return -1;
}
inSz = (word32)WFTELL(NULL, file);
WREWIND(NULL, file);
if (inSz == 0) {
WFCLOSE(NULL, file);
return -1;
}
in = (byte*)WMALLOC(inSz, heap, 0);
if (in == NULL) {
WFCLOSE(NULL, file);
return -1;
}
ret = (int)WFREAD(NULL, in, 1, inSz, file);
if (ret <= 0 || (word32)ret != inSz) {
ret = -1;
WFREE(in, heap, 0);
in = 0;
inSz = 0;
}
else
ret = 0;
*out = in;
*outSz = inSz;
WFCLOSE(NULL, file);
return ret;
}
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME))
static inline void ato32(const byte* c, word32* u32)
{
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
/* when set as true then ignore miss matching IP addresses */
static int IPOverride = 0;
static int ParseRFC6187(const byte* in, word32 inSz, byte** leafOut,
word32* leafOutSz)
{
int ret = WS_SUCCESS;
word32 l = 0, m = 0;
if (inSz < sizeof(word32)) {
printf("inSz %d too small for holding cert name\n", inSz);
return WS_BUFFER_E;
}
/* Skip the name */
ato32(in, &l);
m += l + sizeof(word32);
/* Get the cert count */
if (ret == WS_SUCCESS) {
word32 count;
if (inSz - m < sizeof(word32))
return WS_BUFFER_E;
ato32(in + m, &count);
m += sizeof(word32);
if (ret == WS_SUCCESS && count == 0)
ret = WS_FATAL_ERROR; /* need at least one cert */
}
if (ret == WS_SUCCESS) {
word32 certSz = 0;
if (inSz - m < sizeof(word32))
return WS_BUFFER_E;
ato32(in + m, &certSz);
m += sizeof(word32);
if (ret == WS_SUCCESS) {
/* store leaf cert size to present to user callback */
*leafOutSz = certSz;
*leafOut = (byte*)in + m;
}
if (inSz - m < certSz)
return WS_BUFFER_E;
}
return ret;
}
void ClientIPOverride(int flag)
{
IPOverride = flag;
}
#endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */
#endif /* WOLFSSH_CERTS */
int ClientPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
{
int ret = 0;
#ifdef DEBUG_WOLFSSH
printf("Sample public key check callback\n"
" public key = %p\n"
" public key size = %u\n"
" ctx = %s\n", pubKey, pubKeySz, (const char*)ctx);
#else
(void)pubKey;
(void)pubKeySz;
(void)ctx;
#endif
#ifdef WOLFSSH_CERTS
#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)
/* try to parse the certificate and check it's IP address */
if (pubKeySz > 0) {
DecodedCert dCert;
byte* der = NULL;
word32 derSz = 0;
if (ParseRFC6187(pubKey, pubKeySz, &der, &derSz) == WS_SUCCESS) {
wc_InitDecodedCert(&dCert, der, derSz, NULL);
if (wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
WLOG(WS_LOG_DEBUG, "public key not a cert");
}
else {
int ipMatch = 0;
DNS_entry* current = dCert.altNames;
if (ctx == NULL) {
WLOG(WS_LOG_ERROR, "No host IP set to check against!");
ret = -1;
}
if (ret == 0) {
while (current != NULL) {
if (current->type == ASN_IP_TYPE) {
WLOG(WS_LOG_DEBUG, "host cert alt. name IP : %s",
current->ipString);
WLOG(WS_LOG_DEBUG,
"\texpecting host IP : %s", (char*)ctx);
if (XSTRCMP((const char*)ctx,
current->ipString) == 0) {
WLOG(WS_LOG_DEBUG, "\tmatched!");
ipMatch = 1;
}
}
current = current->next;
}
}
if (ipMatch == 0) {
printf("IP did not match expected IP");
if (!IPOverride) {
printf("\n");
ret = -1;
}
else {
ret = 0;
printf("..overriding\n");
}
}
}
FreeDecodedCert(&dCert);
}
}
#else
WLOG(WS_LOG_DEBUG, "wolfSSL not built with OPENSSL_ALL or WOLFSSL_IP_ALT_NAME");
WLOG(WS_LOG_DEBUG, "\tnot checking IP address from peer's cert");
#endif
#endif
return ret;
}
int ClientUserAuth(byte authType,
WS_UserAuthData* authData,
void* ctx)
{
const char* defaultPassword = (const char*)ctx;
word32 passwordSz = 0;
#if defined(WOLFSSH_TERM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
word32 entry;
#endif
int ret = WOLFSSH_USERAUTH_SUCCESS;
#ifdef DEBUG_WOLFSSH
/* inspect supported types from server */
printf("Server supports:\n");
if (authData->type & WOLFSSH_USERAUTH_PASSWORD) {
printf(" - password\n");
}
if (authData->type & WOLFSSH_USERAUTH_PUBLICKEY) {
printf(" - publickey\n");
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
if (authData->type & WOLFSSH_USERAUTH_KEYBOARD) {
printf(" - keyboard\n");
}
#endif
printf("wolfSSH requesting to use type %d\n", authType);
#endif
/* Wait for request of public key on names known to have one */
if ((authData->type & WOLFSSH_USERAUTH_PUBLICKEY) &&
authData->username != NULL &&
authData->usernameSz > 0) {
/* in the case that the name is hansel or in the case that the user
* passed in a public key file, use public key auth */
if (pubKeyLoaded == 1) {
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
#ifdef WOLFSSH_DEBUG
printf("rejecting password type with %s in favor of pub key\n",
(char*)authData->username);
#endif
return WOLFSSH_USERAUTH_FAILURE;
}
}
}
if (authType == WOLFSSH_USERAUTH_PUBLICKEY) {
WS_UserAuthData_PublicKey* pk = &authData->sf.publicKey;
pk->publicKeyType = userPublicKeyType;
pk->publicKeyTypeSz = userPublicKeyTypeSz;
pk->publicKey = userPublicKey;
pk->publicKeySz = userPublicKeySz;
pk->privateKey = userPrivateKey;
pk->privateKeySz = userPrivateKeySz;
ret = WOLFSSH_USERAUTH_SUCCESS;
}
else if (authType == WOLFSSH_USERAUTH_PASSWORD) {
if (defaultPassword != NULL) {
passwordSz = (word32)strlen(defaultPassword);
memcpy(userPassword, defaultPassword, passwordSz);
}
#ifdef WOLFSSH_TERM
else {
printf("Password: ");
WFFLUSH(stdout);
ClientSetEcho(0);
if (WFGETS((char*)userPassword, sizeof(userPassword), stdin)
== NULL) {
fprintf(stderr, "Getting password failed.\n");
ret = WOLFSSH_USERAUTH_FAILURE;
}
else {
char* c = strpbrk((char*)userPassword, "\r\n");
if (c != NULL)
*c = '\0';
}
passwordSz = (word32)strlen((const char*)userPassword);
ClientSetEcho(1);
#ifdef USE_WINDOWS_API
printf("\r\n");
#endif
WFFLUSH(stdout);
}
#endif
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
authData->sf.password.password = userPassword;
authData->sf.password.passwordSz = passwordSz;
}
}
#if defined(WOLFSSH_TERM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
else if (authType == WOLFSSH_USERAUTH_KEYBOARD) {
if (authData->sf.keyboard.promptName &&
authData->sf.keyboard.promptName[0] != '\0') {
printf("%s\n", authData->sf.keyboard.promptName);
}
if (authData->sf.keyboard.promptInstruction &&
authData->sf.keyboard.promptInstruction[0] != '\0') {
printf("%s\n", authData->sf.keyboard.promptInstruction);
}
keyboardResponseCount = authData->sf.keyboard.promptCount;
keyboardResponses =
(byte**)WMALLOC(sizeof(byte*) * keyboardResponseCount, NULL, 0);
if (keyboardResponses == NULL) {
ret = WS_MEMORY_E;
}
if (ret == WS_SUCCESS) {
authData->sf.keyboard.responses = (byte**)keyboardResponses;
keyboardResponseLengths = (word32*)WMALLOC(
sizeof(word32) * keyboardResponseCount, NULL, 0);
authData->sf.keyboard.responseLengths = keyboardResponseLengths;
}
if (keyboardResponseLengths == NULL) {
ret = WS_MEMORY_E;
}
for (entry = 0; entry < authData->sf.keyboard.promptCount; entry++) {
if (ret == WS_SUCCESS) {
printf("%s", authData->sf.keyboard.prompts[entry]);
if (!authData->sf.keyboard.promptEcho[entry]) {
ClientSetEcho(0);
}
if (WFGETS((char*)userPassword, sizeof(userPassword), stdin)
== NULL) {
fprintf(stderr, "Getting response failed.\n");
ret = WOLFSSH_USERAUTH_FAILURE;
}
else {
char* c = strpbrk((char*)userPassword, "\r\n");
if (c != NULL)
*c = '\0';
}
passwordSz = (word32)strlen((const char*)userPassword);
ClientSetEcho(1);
#ifdef USE_WINDOWS_API
printf("\r\n");
#endif
WFFLUSH(stdout);
authData->sf.keyboard.responses[entry] =
(byte*) WSTRDUP((char*)userPassword, NULL, 0);
authData->sf.keyboard.responseLengths[entry] = passwordSz;
authData->sf.keyboard.responseCount++;
}
}
}
#endif
return ret;
}
#ifdef WOLFSSH_TERM
/* type = 2 : shell / execute command settings
* type = 0 : password
* type = 1 : restore default
* return 0 on success */
int ClientSetEcho(int type)
{
#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32)
static int echoInit = 0;
static struct termios originalTerm;
if (!echoInit) {
if (tcgetattr(STDIN_FILENO, &originalTerm) != 0) {
printf("Couldn't get the original terminal settings.\n");
return -1;
}
echoInit = 1;
}
if (echoInit) {
if (type == 1) {
if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) {
printf("Couldn't restore the terminal settings.\n");
return -1;
}
}
else {
struct termios newTerm;
memcpy(&newTerm, &originalTerm, sizeof(struct termios));
newTerm.c_lflag &= ~ECHO;
if (type == 2) {
newTerm.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE
| ECHOK | ECHONL | NOFLSH | TOSTOP);
/* check macros set for some BSD dependent and not missing on
* QNX flags */
#ifdef ECHOPRT
newTerm.c_lflag &= ~(ECHOPRT);
#endif
#ifdef FLUSHO
newTerm.c_lflag &= ~(FLUSHO);
#endif
#ifdef PENDIN
newTerm.c_lflag &= ~(PENDIN);
#endif
#ifdef EXTPROC
newTerm.c_lflag &= ~(EXTPROC);
#endif
newTerm.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON
| IXOFF | IXANY | IGNBRK | INPCK | PARMRK);
#ifdef IUCLC
newTerm.c_iflag &= ~IUCLC;
#endif
newTerm.c_iflag |= IGNPAR;
newTerm.c_oflag &= ~(OPOST | ONOCR | ONLRET);
#ifdef OUCLC
newTerm.c_oflag &= ~OLCUC;
#endif
newTerm.c_cflag &= ~(CSTOPB | PARENB | PARODD | CLOCAL);
#ifdef CRTSCTS
newTerm.c_cflag &= ~(CRTSCTS);
#endif
}
else {
newTerm.c_lflag |= (ICANON | ECHONL);
}
if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) {
printf("Couldn't turn off echo.\n");
return -1;
}
}
}
#else
static int echoInit = 0;
static DWORD originalTerm;
static CONSOLE_SCREEN_BUFFER_INFO screenOrig;
HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
if (!echoInit) {
if (GetConsoleMode(stdinHandle, &originalTerm) == 0) {
printf("Couldn't get the original terminal settings.\n");
return -1;
}
echoInit = 1;
}
if (type == 1) {
if (SetConsoleMode(stdinHandle, originalTerm) == 0) {
printf("Couldn't restore the terminal settings.\n");
return -1;
}
}
else if (type == 2) {
DWORD newTerm = originalTerm;
newTerm &= ~ENABLE_PROCESSED_INPUT;
newTerm &= ~ENABLE_PROCESSED_OUTPUT;
newTerm &= ~ENABLE_LINE_INPUT;
newTerm &= ~ENABLE_ECHO_INPUT;
newTerm &= ~(ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE);
if (SetConsoleMode(stdinHandle, newTerm) == 0) {
printf("Couldn't turn off echo.\n");
return -1;
}
}
else {
DWORD newTerm = originalTerm;
newTerm &= ~ENABLE_ECHO_INPUT;
if (SetConsoleMode(stdinHandle, newTerm) == 0) {
printf("Couldn't turn off echo.\n");
return -1;
}
}
#endif
return 0;
}
#endif
/* Set certificate to use and public key.
* returns 0 on success */
int ClientUseCert(const char* certName, void* heap)
{
int ret = 0;
if (certName != NULL) {
#ifdef WOLFSSH_CERTS
ret = load_der_file(certName, &userPublicKey, &userPublicKeySz, heap);
if (ret == 0) {
userPublicKeyType = publicKeyType;
userPublicKeyTypeSz = (word32)WSTRLEN((const char*)publicKeyType);
pubKeyLoaded = 1;
}
#else
(void)heap;
fprintf(stderr, "Certificate support not compiled in");
ret = WS_NOT_COMPILED;
#endif
}
return ret;
}
#ifdef WOLFSSH_TPM
static int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
{
int rc = 0;
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
WFILE* fp = NULL;
size_t fileSz = 0;
size_t bytes_read = 0;
byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
int pubAreaSize;
WLOG(WS_LOG_DEBUG, "Entering readKeyBlob()");
WMEMSET(key, 0, sizeof(WOLFTPM2_KEYBLOB));
if (WFOPEN(NULL, &fp, filename, "rb") != 0) {
printf("Failed to open file %s\n", filename);
rc = BUFFER_E; goto exit;
}
if (fp != WBADFILE) {
WFSEEK(NULL, fp, 0, WSEEK_END);
fileSz = WFTELL(NULL, fp);
WREWIND(NULL, fp);
if (fileSz > sizeof(key->priv) + sizeof(key->pub)) {
printf("File size check failed\n");
rc = BUFFER_E; goto exit;
}
printf("Reading %d bytes from %s\n", (int)fileSz, filename);
bytes_read = WFREAD(NULL, &key->pub.size, 1,
sizeof(key->pub.size), fp);
if (bytes_read != sizeof(key->pub.size)) {
printf("Read %zu, expected size marker of %zu bytes\n",
bytes_read, sizeof(key->pub.size));
goto exit;
}
fileSz -= bytes_read;
bytes_read = WFREAD(NULL, pubAreaBuffer, 1,
sizeof(UINT16) + key->pub.size, fp);
if (bytes_read != sizeof(UINT16) + key->pub.size) {
printf("Read %zu, expected public blob %zu bytes\n",
bytes_read, sizeof(UINT16) + key->pub.size);
goto exit;
}
fileSz -= bytes_read; /* Reminder bytes for private key part */
/* Decode the byte stream into a publicArea structure ready for use */
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer,
(word32)sizeof(pubAreaBuffer), &pubAreaSize);
if (rc != 0) return rc;
if (fileSz > 0) {
printf("Reading the private part of the key\n");
bytes_read = WFREAD(NULL, &key->priv, 1, fileSz, fp);
if (bytes_read != fileSz) {
printf("Read %zu, expected private blob %zu bytes\n",
bytes_read, fileSz);
goto exit;
}
rc = 0; /* success */
}
/* sanity check the sizes */
if (pubAreaSize != (key->pub.size + (int)sizeof(key->pub.size)) ||
key->priv.size > sizeof(key->priv.buffer)) {
printf("Struct size check failed (pub %d, priv %d)\n",
key->pub.size, key->priv.size);
rc = BUFFER_E;
}
}
else {
rc = BUFFER_E;
printf("File %s not found!\n", filename);
printf("Key can be generated by running:\n"
" ./examples/keygen/keygen keyblob.bin -rsa -t -pem -eh\n");
}
exit:
if (fp)
WFCLOSE(NULL, fp);
#else
(void)filename;
(void)key;
#endif /* !NO_FILESYSTEM && !NO_WRITE_TEMP_FILES */
WLOG(WS_LOG_DEBUG, "Leaving readKeyBlob(), rc = %d", rc);
return rc;
}
static int wolfSSH_TPM_InitKey(WOLFTPM2_DEV* dev, const char* name,
WOLFTPM2_KEY* pTpmKey, const char* tpmKeyAuth)
{
int rc = 0;
WOLFTPM2_KEY endorse;
WOLFTPM2_KEYBLOB tpmKeyBlob;
WOLFTPM2_SESSION tpmSession;
byte* p = NULL;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_TPM_InitKey()");
/* Initialize the TPM 2.0 device */
if (rc == 0) {
rc = wolfTPM2_Init(dev, TPM2_IoCb, NULL);
if (rc != 0) {
WLOG(WS_LOG_DEBUG,
"TPM 2.0 Device initialization failed, rc: %d", rc);
}
}
/* Create primary endorsement key (EK) */
if (rc == 0) {
rc = wolfTPM2_CreateEK(dev, &endorse, TPM_ALG_RSA);
if (rc != 0) {
WLOG(WS_LOG_DEBUG, "Creating EK failed, rc: %d", rc);
}
}
/* Create and set policy session for EK */
if (rc == 0) {
endorse.handle.policyAuth = 1;
rc = wolfTPM2_CreateAuthSession_EkPolicy(dev, &tpmSession);
if (rc != 0) {
WLOG(WS_LOG_DEBUG,
"Creating EK policy session failed, rc: %d", rc);
}
}
if (rc == 0) {
rc = wolfTPM2_SetAuthSession(dev, 0, &tpmSession, 0);
if (rc != 0) {
WLOG(WS_LOG_DEBUG, "Setting auth session failed, rc: %d", rc);
}
}
/* Load the TPM 2.0 key blob from disk */
if (rc == 0) {
rc = readKeyBlob(name, &tpmKeyBlob);
if (rc != 0) {
WLOG(WS_LOG_DEBUG,
"Reading key blob from disk failed, rc: %d", rc);
}
}
/* Use global auth if provided */
if (rc == 0 && tpmKeyAuth != NULL) {
tpmKeyBlob.handle.auth.size = (word32)XSTRLEN(tpmKeyAuth);
XMEMCPY(tpmKeyBlob.handle.auth.buffer, tpmKeyAuth,
tpmKeyBlob.handle.auth.size);
}
/* Load the public key into the TPM device */
if (rc == 0) {
rc = wolfTPM2_LoadKey(dev, &tpmKeyBlob, &endorse.handle);
if (rc != 0) {
WLOG(WS_LOG_DEBUG, "wolfTPM2_LoadKey failed, rc: %d", rc);
} else {
WLOG(WS_LOG_DEBUG, "Loaded key to 0x%x\n",
(word32)tpmKeyBlob.handle.hndl);
}
}
/* Read the public key and extract the public key as a DER/ASN.1 */
if (rc == 0) {
userPublicKeySz = sizeof(userPublicKeyBuf);
rc = wolfTPM2_ExportPublicKeyBuffer(dev, (WOLFTPM2_KEY*)&tpmKeyBlob,
ENCODING_TYPE_ASN1, userPublicKey, &userPublicKeySz);
if (rc != 0) {
WLOG(WS_LOG_DEBUG, "Exporting TPM key failed, rc: %d", rc);
}
}
/* Read public key from buffer and convert key to OpenSSH format */
if (rc == 0) {
rc = wolfSSH_ReadPublicKey_buffer(userPublicKey, userPublicKeySz,
WOLFSSH_FORMAT_ASN1, &p, &userPublicKeySz, &userPublicKeyType,
&userPublicKeyTypeSz, NULL);
if (rc == 0) {
userPublicKey = p;
} else {
WLOG(WS_LOG_DEBUG, "Reading public key failed, rc: %d", rc);
}
}
/* Copy key info */
if (rc == 0) {
XMEMCPY(&pTpmKey->handle, &tpmKeyBlob.handle, sizeof(pTpmKey->handle));
XMEMCPY(&pTpmKey->pub, &tpmKeyBlob.pub, sizeof(pTpmKey->pub));
wolfTPM2_UnloadHandle(dev, &endorse.handle);
}
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_TPM_InitKey(), rc = %d", rc);
return rc;
}
static void wolfSSH_TPM_Cleanup(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key)
{
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_TPM_Cleanup()");
if (key != NULL) {
wolfTPM2_UnloadHandle(dev, &key->handle);
}
if (dev != NULL) {
wolfTPM2_Cleanup(dev);
}
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_TPM_Cleanup()");
}
/* Set the tpm device and key for the client side */
int ClientSetTpm(WOLFSSH* ssh)
{
if (ssh != NULL) {
wolfSSH_SetTpmDev(ssh, &tpmDev);
wolfSSH_SetTpmKey(ssh, &tpmKey);
}
return 0;
}
#endif /* WOLFSSH_TPM */
/* Reads the private key to use from file name privKeyName.
* returns 0 on success */
int ClientSetPrivateKey(const char* privKeyName, int userEcc,
void* heap, const char* tpmKeyAuth)
{
int ret = 0;
(void)tpmKeyAuth; /* Not used */
if (privKeyName == NULL) {
if (userEcc) {
#ifndef WOLFSSH_NO_ECC
userPrivateKeySz = sizeof(userPrivateKeyBuf);
ret = wolfSSH_ReadKey_buffer(hanselPrivateEcc, hanselPrivateEccSz,
WOLFSSH_FORMAT_ASN1, &userPrivateKey, &userPrivateKeySz,
&userPrivateKeyType, &userPrivateKeyTypeSz, heap);
#endif
}
else {
#ifndef WOLFSSH_NO_RSA
userPrivateKeySz = sizeof(userPrivateKeyBuf);
ret = wolfSSH_ReadKey_buffer(hanselPrivateRsa, hanselPrivateRsaSz,
WOLFSSH_FORMAT_ASN1, &userPrivateKey, &userPrivateKeySz,
&userPrivateKeyType, &userPrivateKeyTypeSz, heap);
#endif
}
isPrivate = 1;
}
else {
#if defined(WOLFSSH_TPM)
/* Protecting the SSH Private Key using a TPM 2.0 device
*
* TPM-backed keys do not require a user buffer, because
* the private key is loaded securely inside the TPM and
* used only from within the TPM for higher security.
*
* Successfully loaded TPM key has a TPM Handle that is
* later passed to wolfSSH for use
*/
WMEMSET(&tpmDev, 0, sizeof(tpmDev));
WMEMSET(&tpmKey, 0, sizeof(tpmKey));
ret = wolfSSH_TPM_InitKey(&tpmDev, privKeyName, &tpmKey, tpmKeyAuth);
#elif !defined(NO_FILESYSTEM)
userPrivateKey = NULL; /* create new buffer based on parsed input */
userPrivateKeyAlloc = 1;
userPrivateKeySz = sizeof(userPrivateKeyBuf);
ret = wolfSSH_ReadKey_file(privKeyName,
(byte**)&userPrivateKey, &userPrivateKeySz,
(const byte**)&userPrivateKeyType, &userPrivateKeyTypeSz,
&isPrivate, heap);
#else
printf("file system not compiled in!\n");
ret = NOT_COMPILED_IN;
#endif /* WOLFSSH_TPM / NO_FILESYSTEM */
}
return ret;
}
/* Set public key to use
* returns 0 on success */
int ClientUsePubKey(const char* pubKeyName, int userEcc, void* heap)
{
int ret = 0;
if (pubKeyName == NULL) {
byte* p = userPublicKey;
userPublicKeySz = sizeof(userPublicKeyBuf);
if (userEcc) {
#ifndef WOLFSSH_NO_ECC
ret = wolfSSH_ReadKey_buffer((const byte*)hanselPublicEcc,
(word32)strlen(hanselPublicEcc), WOLFSSH_FORMAT_SSH,
&p, &userPublicKeySz,
&userPublicKeyType, &userPublicKeyTypeSz, heap);
#endif
}
else {
#ifndef WOLFSSH_NO_RSA
ret = wolfSSH_ReadKey_buffer((const byte*)hanselPublicRsa,
(word32)strlen(hanselPublicRsa), WOLFSSH_FORMAT_SSH,
&p, &userPublicKeySz,
&userPublicKeyType, &userPublicKeyTypeSz, heap);
#endif
}
isPrivate = 1;
}
else {
#ifndef NO_FILESYSTEM
userPublicKey = NULL; /* create new buffer based on parsed input */
ret = wolfSSH_ReadKey_file(pubKeyName,
&userPublicKey, &userPublicKeySz,
(const byte**)&userPublicKeyType, &userPublicKeyTypeSz,
&isPrivate, heap);
#else
printf("file system not compiled in!\n");
ret = NOT_COMPILED_IN;
#endif /* NO_FILESYSTEM */
if (ret == 0) {
pubKeyLoaded = 1;
}
}
return ret;
}
int ClientLoadCA(WOLFSSH_CTX* ctx, const char* caCert)
{
int ret = 0;
/* CA certificate to verify host cert with */
if (caCert) {
#ifdef WOLFSSH_CERTS
byte* der = NULL;
word32 derSz;
ret = load_der_file(caCert, &der, &derSz, ctx->heap);
if (ret == 0) {
if (wolfSSH_CTX_AddRootCert_buffer(ctx, der, derSz,
WOLFSSH_FORMAT_ASN1) != WS_SUCCESS) {
fprintf(stderr, "Couldn't parse in CA certificate.");
ret = WS_PARSE_E;
}
WFREE(der, NULL, 0);
}
#else
(void)ctx;
fprintf(stderr, "Support for certificates not compiled in.");
ret = WS_NOT_COMPILED;
#endif
}
return ret;
}
void ClientFreeBuffers(const char* pubKeyName, const char* privKeyName,
void* heap)
{
#if defined(WOLFSSH_TERM) && defined(WOLFSSH_KEYBOARD_INTERACTIVE)
word32 entry;
#endif
#ifdef WOLFSSH_TPM
wolfSSH_TPM_Cleanup(&tpmDev, &tpmKey);
#endif
if (pubKeyName != NULL && userPublicKey != NULL &&
userPublicKey != userPublicKeyBuf) {
WFREE(userPublicKey, heap, DYNTYPE_PRIVKEY);
}
if (privKeyName != NULL && userPrivateKey != NULL &&
userPrivateKeyAlloc) {
WFREE(userPrivateKey, heap, DYNTYPE_PRIVKEY);
}
#ifdef WOLFSSH_KEYBOARD_INTERACTIVE
for (entry = 0; entry < keyboardResponseCount; entry++) {
WFREE(keyboardResponses[entry], NULL, 0);
}
WFREE(keyboardResponses, NULL, 0);
WFREE(keyboardResponseLengths, NULL, 0);
#endif
}