mirror of https://github.com/wolfSSL/wolfssh.git
Merge pull request #604 from ejohnstown/wolfssh-client-2
wolfSSH Client with OpenSSH-format Keyspull/554/head
commit
b7aaabc898
|
@ -379,7 +379,7 @@ int ClientSetEcho(int type)
|
|||
newTerm.c_lflag &= ~(ICANON | ECHOE | ECHOK | ECHONL | ISIG);
|
||||
}
|
||||
else {
|
||||
newTerm.c_lflag |= (ICANON | ECHONL);
|
||||
newTerm.c_lflag |= ICANON;
|
||||
}
|
||||
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
|
||||
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTAqdBgCp8bYSq2kQQ48/Ud8Iy6Mjnb
|
||||
/fpB3LfSE/1kx9VaaE4FL3i9Gg2vDV0eLGM3PWksFNPhULxtcYJyjaBjAAAAqJAeleSQHp
|
||||
XkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMCp0GAKnxthKraR
|
||||
BDjz9R3wjLoyOdv9+kHct9IT/WTH1VpoTgUveL0aDa8NXR4sYzc9aSwU0+FQvG1xgnKNoG
|
||||
MAAAAgPrOgktioNqad/wHNC/rt/zVrpNqDnOwg9tNDFMOTwo8AAAANYm9iQGxvY2FsaG9z
|
||||
dAECAw==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
|
@ -0,0 +1 @@
|
|||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMCp0GAKnxthKraRBDjz9R3wjLoyOdv9+kHct9IT/WTH1VpoTgUveL0aDa8NXR4sYzc9aSwU0+FQvG1xgnKNoGM= bob@localhost
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAQEAy2cigZDlpBT+X2MJHAoHnfeFf6+LHm6BDkAT8V9ejHA4dY0Aepb6
|
||||
NbV6u/oYZlueKPeAZ3GNztR9szoL6FSlMvkd9oqvfoxjTGu71T0981ybJelqqGATGtevHU
|
||||
6Jko/I0+lgSQFKWQJ7D3Dj2zlZpIXB2Q7xl/i9kFZgaIqFhUHdWO9JMOwCFwoDrhd8v5xk
|
||||
y1v3OIIZDxiYxVIKbf2J07WbwiSFAxXfiX8TjUBDLFmtqt1AF6LjAyGyaRICXkaGJQ/QJ9
|
||||
sX85h9bkiPlGNAtQGQtNUg3tC9GqOkZ9tCKY1Efh/r0zosOA7ufxg6ymLpq1C4LU/4ENGH
|
||||
kuRPAKvu8wAAA8gztJfmM7SX5gAAAAdzc2gtcnNhAAABAQDLZyKBkOWkFP5fYwkcCged94
|
||||
V/r4seboEOQBPxX16McDh1jQB6lvo1tXq7+hhmW54o94BncY3O1H2zOgvoVKUy+R32iq9+
|
||||
jGNMa7vVPT3zXJsl6WqoYBMa168dTomSj8jT6WBJAUpZAnsPcOPbOVmkhcHZDvGX+L2QVm
|
||||
BoioWFQd1Y70kw7AIXCgOuF3y/nGTLW/c4ghkPGJjFUgpt/YnTtZvCJIUDFd+JfxONQEMs
|
||||
Wa2q3UAXouMDIbJpEgJeRoYlD9An2xfzmH1uSI+UY0C1AZC01SDe0L0ao6Rn20IpjUR+H+
|
||||
vTOiw4Du5/GDrKYumrULgtT/gQ0YeS5E8Aq+7zAAAAAwEAAQAAAQEAvbdBiQXkGyn1pHST
|
||||
/5IfTqia3OCX6td5ChicQUsJvgXBs2rDopQFZmkRxBjd/0K+/0jyfAl/EgZCBBRFHPsuZp
|
||||
/S4ayzSV6aE6J8vMT1bnLWxwKyl7+csjGwRK6HRKtVzsnjI9TPSrw0mc9ax5PzV6/mgZUd
|
||||
o/i+nszh+UASj5mYrBGqMiINspzX6YC+qoUHor3rEJOd9p1aO+N5+1fDKiDnlkM5IO0Qsz
|
||||
GktuwL0fzv9zBnGfnWVJz3CorfP1OW5KCtrDn7BnkQf1eBeVLzq/uoglUjS4DNnVfLA67D
|
||||
O4ZfwtnoW8Gr2R+KdvnypvHnDeY5X51r5PDgL4+7z47pWQAAAIBNFcAzHHE19ISGN8YRHk
|
||||
23/r/3zfvzHU68GSKR1Xj/Y4LSdRTpSm3wBrdQ17f5B4V7RVl2CJvoPekTggnBDQlLJ7fU
|
||||
NU93/nZrY9teYdrNh03buL54VVb5tUM+KN+27zERlTj0/LmYJupN97sZXmlgKsvLbcsnM2
|
||||
i7HuQQaFnsIQAAAIEA5wqFVatT9yovt8pS7rAyYUL/cqc50TZ/5Nwfy5uasRyf1BphHwEW
|
||||
LEimBemVc+VrNwAkt6MFWuloK5ssqb1ubvtRI8Mntd15rRfZtq/foS3J8FJxueXLDWlECy
|
||||
PmVyfVN1Vv4ZeirBy9BTYLiSuxMes+HYks3HucQhxIN1j8SA0AAACBAOFgRjfWXv1/93Jp
|
||||
6CCJ5c98MWP+zu1FbLIlklxPb85osZqlazXHNPPEtblC4z+OqRGMCsv2683anU4ZzcTFIk
|
||||
JS3lzeJ3tdAH4osQ5etKkV4mcdCmeRpjudB9VbaziVhPX02qkPWpM0ckPrgB3hVNUDPz89
|
||||
GtJd3mlhyY5IfFL/AAAADWJvYkBsb2NhbGhvc3QBAgMEBQ==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
|
@ -0,0 +1 @@
|
|||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLZyKBkOWkFP5fYwkcCged94V/r4seboEOQBPxX16McDh1jQB6lvo1tXq7+hhmW54o94BncY3O1H2zOgvoVKUy+R32iq9+jGNMa7vVPT3zXJsl6WqoYBMa168dTomSj8jT6WBJAUpZAnsPcOPbOVmkhcHZDvGX+L2QVmBoioWFQd1Y70kw7AIXCgOuF3y/nGTLW/c4ghkPGJjFUgpt/YnTtZvCJIUDFd+JfxONQEMsWa2q3UAXouMDIbJpEgJeRoYlD9An2xfzmH1uSI+UY0C1AZC01SDe0L0ao6Rn20IpjUR+H+vTOiw4Du5/GDrKYumrULgtT/gQ0YeS5E8Aq+7z bob@localhost
|
|
@ -22,5 +22,6 @@ EXTRA_DIST+= \
|
|||
keys/server-cert.der keys/server-cert.pem \
|
||||
keys/fred-cert.der keys/fred-cert.pem \
|
||||
keys/server-key.pem keys/fred-key.der keys/fred-key.pem \
|
||||
keys/id_ecdsa keys/id_ecdsa.pub keys/id_rsa keys/id_rsa.pub \
|
||||
keys/renewcerts.sh keys/renewcerts.cnf
|
||||
|
||||
|
|
512
src/internal.c
512
src/internal.c
|
@ -137,6 +137,8 @@ Flags:
|
|||
Set when all ECDH algorithms are disabled. Set to disable use of all ECDH
|
||||
algorithms for key agreement. Setting this will force all ECDH key agreement
|
||||
algorithms off.
|
||||
WOLFSSH_KEY_QUANTITY_REQ
|
||||
Number of keys required to be in an OpenSSH-style key wrapper.
|
||||
*/
|
||||
|
||||
static const char sshProtoIdStr[] = "SSH-2.0-wolfSSHv"
|
||||
|
@ -419,6 +421,15 @@ const char* GetErrorString(int err)
|
|||
case WS_MATCH_UA_KEY_ID_E:
|
||||
return "unable to match user auth key type";
|
||||
|
||||
case WS_KEY_AUTH_MAGIC_E:
|
||||
return "key auth magic check error";
|
||||
|
||||
case WS_KEY_CHECK_VAL_E:
|
||||
return "key check value error";
|
||||
|
||||
case WS_KEY_FORMAT_E:
|
||||
return "key format wrong error";
|
||||
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
@ -845,21 +856,51 @@ void SshResourceFree(WOLFSSH* ssh, void* heap)
|
|||
#endif
|
||||
}
|
||||
|
||||
union wolfSSH_key {
|
||||
|
||||
typedef struct WS_KeySignature {
|
||||
byte keySigId;
|
||||
word32 sigSz;
|
||||
const char *name;
|
||||
word32 nameSz;
|
||||
union {
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
RsaKey rsa;
|
||||
struct {
|
||||
RsaKey key;
|
||||
} rsa;
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_ECDSA
|
||||
ecc_key ecc;
|
||||
struct {
|
||||
ecc_key key;
|
||||
} ecc;
|
||||
#endif
|
||||
};
|
||||
} ks;
|
||||
} WS_KeySignature;
|
||||
|
||||
|
||||
static void wolfSSH_KEY_clean(WS_KeySignature* key)
|
||||
{
|
||||
if (key != NULL) {
|
||||
if (key->keySigId == ID_SSH_RSA) {
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
wc_FreeRsaKey(&key->ks.rsa.key);
|
||||
#endif
|
||||
}
|
||||
else if (key->keySigId == ID_ECDSA_SHA2_NISTP256 ||
|
||||
key->keySigId == ID_ECDSA_SHA2_NISTP384 ||
|
||||
key->keySigId == ID_ECDSA_SHA2_NISTP521) {
|
||||
#ifndef WOLFSSH_NO_ECDSA
|
||||
wc_ecc_free(&key->ks.ecc.key);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Identifies the flavor of a key, RSA or ECDSA, and returns the key type ID.
|
||||
* The process is to decode the key as if it was RSA and if that fails try
|
||||
* to load it as if ECDSA. Both public and private keys can be decoded.
|
||||
* For RSA keys, the key format is described as "ssh-rsa".
|
||||
* Identifies the flavor of an ASN.1 key, RSA or ECDSA, and returns the key
|
||||
* type ID. The process is to decode the key as if it was RSA and if that
|
||||
* fails try to load it as if ECDSA. Both public and private keys can be
|
||||
* decoded. For RSA keys, the key format is described as "ssh-rsa".
|
||||
*
|
||||
* @param in key to identify
|
||||
* @param inSz size of key
|
||||
|
@ -867,88 +908,369 @@ union wolfSSH_key {
|
|||
* @param heap heap to use for memory allocation
|
||||
* @return keyId as int, WS_MEMORY_E, WS_UNIMPLEMENTED_E
|
||||
*/
|
||||
int IdentifyKey(const byte* in, word32 inSz, int isPrivate, void* heap)
|
||||
int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap)
|
||||
{
|
||||
union wolfSSH_key *key = NULL;
|
||||
int keyId = ID_UNKNOWN;
|
||||
WS_KeySignature *key = NULL;
|
||||
word32 idx;
|
||||
int ret;
|
||||
int dynType = isPrivate ? DYNTYPE_PRIVKEY : DYNTYPE_PUBKEY;
|
||||
WOLFSSH_UNUSED(dynType);
|
||||
|
||||
key = (union wolfSSH_key*)WMALLOC(sizeof(union wolfSSH_key), heap, dynType);
|
||||
key = (WS_KeySignature*)WMALLOC(sizeof(WS_KeySignature), heap, dynType);
|
||||
|
||||
if (key == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
else {
|
||||
WMEMSET(key, 0, sizeof(*key));
|
||||
key->keySigId = ID_UNKNOWN;
|
||||
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
if (key != NULL) {
|
||||
/* Check RSA key */
|
||||
if (keyId == ID_UNKNOWN) {
|
||||
if (key->keySigId == ID_UNKNOWN) {
|
||||
idx = 0;
|
||||
ret = wc_InitRsaKey(&key->rsa, NULL);
|
||||
ret = wc_InitRsaKey(&key->ks.rsa.key, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
if (isPrivate) {
|
||||
ret = wc_RsaPrivateKeyDecode(in, &idx, &key->rsa, inSz);
|
||||
ret = wc_RsaPrivateKeyDecode(in, &idx,
|
||||
&key->ks.rsa.key, inSz);
|
||||
}
|
||||
else {
|
||||
ret = wc_RsaPublicKeyDecode(in, &idx, &key->rsa, inSz);
|
||||
ret = wc_RsaPublicKeyDecode(in, &idx,
|
||||
&key->ks.rsa.key, inSz);
|
||||
}
|
||||
|
||||
/* If decode was successful, this is an RSA key. */
|
||||
if (ret == 0) {
|
||||
keyId = ID_SSH_RSA;
|
||||
key->keySigId = ID_SSH_RSA;
|
||||
}
|
||||
}
|
||||
|
||||
wc_FreeRsaKey(&key->rsa);
|
||||
wc_FreeRsaKey(&key->ks.rsa.key);
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSH_NO_RSA */
|
||||
#ifndef WOLFSSH_NO_ECDSA
|
||||
if (key != NULL) {
|
||||
/* Check ECDSA key */
|
||||
if (keyId == ID_UNKNOWN) {
|
||||
if (key->keySigId == ID_UNKNOWN) {
|
||||
idx = 0;
|
||||
ret = wc_ecc_init_ex(&key->ecc, heap, INVALID_DEVID);
|
||||
ret = wc_ecc_init_ex(&key->ks.ecc.key, heap, INVALID_DEVID);
|
||||
|
||||
if (ret == 0) {
|
||||
if (isPrivate) {
|
||||
ret = wc_EccPrivateKeyDecode(in, &idx, &key->ecc, inSz);
|
||||
ret = wc_EccPrivateKeyDecode(in, &idx,
|
||||
&key->ks.ecc.key, inSz);
|
||||
}
|
||||
else {
|
||||
ret = wc_EccPublicKeyDecode(in, &idx, &key->ecc, inSz);
|
||||
ret = wc_EccPublicKeyDecode(in, &idx,
|
||||
&key->ks.ecc.key, inSz);
|
||||
}
|
||||
|
||||
/* If decode was successful, this is an ECDSA key. */
|
||||
if (ret == 0) {
|
||||
switch (wc_ecc_get_curve_id(key->ecc.idx)) {
|
||||
switch (wc_ecc_get_curve_id(key->ks.ecc.key.idx)) {
|
||||
case ECC_SECP256R1:
|
||||
keyId = ID_ECDSA_SHA2_NISTP256;
|
||||
key->keySigId = ID_ECDSA_SHA2_NISTP256;
|
||||
break;
|
||||
case ECC_SECP384R1:
|
||||
keyId = ID_ECDSA_SHA2_NISTP384;
|
||||
key->keySigId = ID_ECDSA_SHA2_NISTP384;
|
||||
break;
|
||||
case ECC_SECP521R1:
|
||||
keyId = ID_ECDSA_SHA2_NISTP521;
|
||||
key->keySigId = ID_ECDSA_SHA2_NISTP521;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wc_ecc_free(&key->ecc);
|
||||
wc_ecc_free(&key->ks.ecc.key);
|
||||
}
|
||||
#endif /* WOLFSSH_NO_ECDSA */
|
||||
|
||||
if (key->keySigId == ID_UNKNOWN) {
|
||||
ret = WS_UNIMPLEMENTED_E;
|
||||
}
|
||||
else {
|
||||
ret = key->keySigId;
|
||||
}
|
||||
|
||||
WFREE(key, heap, dynType);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Utility function to read an Mpint from the stream directly into a mp_int.
|
||||
*/
|
||||
static INLINE int GetMpintToMp(mp_int* mp,
|
||||
const byte* buf, word32 len, word32* idx)
|
||||
{
|
||||
const byte* val = NULL;
|
||||
word32 valSz = 0;
|
||||
int ret;
|
||||
|
||||
ret = GetMpint(&valSz, &val, buf, len, idx);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = mp_read_unsigned_bin(mp, val, valSz);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For the given RSA key, calculate p^-1 and q^-1. wolfCrypt's RSA
|
||||
* code expects them, but the OpenSSH format key doesn't store them.
|
||||
* TODO: Add a RSA read function to wolfCrypt to handle this condition.
|
||||
*/
|
||||
static INLINE int CalcRsaInverses(RsaKey* key)
|
||||
{
|
||||
mp_int m;
|
||||
int ret;
|
||||
|
||||
ret = mp_init(&m);
|
||||
if (ret == MP_OKAY) {
|
||||
ret = mp_sub_d(&key->p, 1, &m);
|
||||
if (ret == MP_OKAY)
|
||||
ret = mp_mod(&key->d, &m, &key->dP);
|
||||
if (ret == MP_OKAY)
|
||||
ret = mp_sub_d(&key->q, 1, &m);
|
||||
if (ret == MP_OKAY)
|
||||
ret = mp_mod(&key->d, &m, &key->dQ);
|
||||
mp_forcezero(&m);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Utility for GetOpenSshKey() to read in RSA keys.
|
||||
*/
|
||||
static int GetOpenSshKeyRsa(RsaKey* key,
|
||||
const byte* buf, word32 len, word32* idx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wc_InitRsaKey(key, NULL);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpintToMp(&key->n, buf, len, idx);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpintToMp(&key->e, buf, len, idx);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpintToMp(&key->d, buf, len, idx);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpintToMp(&key->u, buf, len, idx);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpintToMp(&key->p, buf, len, idx);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpintToMp(&key->q, buf, len, idx);
|
||||
|
||||
/* Calculate dP and dQ for wolfCrypt. */
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = CalcRsaInverses(key);
|
||||
|
||||
if (ret != WS_SUCCESS)
|
||||
ret = WS_RSA_E;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Utility for GetOpenSshKey() to read in ECDSA keys.
|
||||
*/
|
||||
static int GetOpenSshKeyEcc(ecc_key* key,
|
||||
const byte* buf, word32 len, word32* idx)
|
||||
{
|
||||
const byte *name = NULL, *priv = NULL, *pub = NULL;
|
||||
word32 nameSz = 0, privSz = 0, pubSz = 0;
|
||||
int ret;
|
||||
|
||||
ret = wc_ecc_init(key);
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetStringRef(&nameSz, &name, buf, len, idx); /* curve name */
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetStringRef(&pubSz, &pub, buf, len, idx); /* Q */
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetMpint(&privSz, &priv, buf, len, idx); /* d */
|
||||
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz,
|
||||
key, ECC_CURVE_DEF);
|
||||
|
||||
if (ret != WS_SUCCESS)
|
||||
ret = WS_ECC_E;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decodes an OpenSSH format key.
|
||||
*/
|
||||
static int GetOpenSshKey(WS_KeySignature *key,
|
||||
const byte* buf, word32 len, word32* idx)
|
||||
{
|
||||
const char AuthMagic[] = "openssh-key-v1";
|
||||
const byte* str = NULL;
|
||||
word32 keyCount = 0, strSz, i;
|
||||
int ret = WS_SUCCESS;
|
||||
|
||||
if (WSTRCMP(AuthMagic, (const char*)buf) != 0) {
|
||||
ret = WS_KEY_AUTH_MAGIC_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
*idx += (word32)WSTRLEN(AuthMagic) + 1;
|
||||
ret = GetSkip(buf, len, idx); /* ciphername */
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetSkip(buf, len, idx); /* kdfname */
|
||||
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetSkip(buf, len, idx); /* kdfoptions */
|
||||
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetUint32(&keyCount, buf, len, idx); /* key count */
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (keyCount != WOLFSSH_KEY_QUANTITY_REQ) {
|
||||
ret = WS_KEY_FORMAT_E;
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSH_NO_ECDSA */
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
strSz = 0;
|
||||
ret = GetStringRef(&strSz, &str, buf, len, idx);
|
||||
/* public buf */
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
strSz = 0;
|
||||
ret = GetStringRef(&strSz, &str, buf, len, idx);
|
||||
/* list of private keys */
|
||||
|
||||
/* If there isn't a private key, the key file is bad. */
|
||||
if (ret == WS_SUCCESS && strSz == 0) {
|
||||
ret = WS_KEY_FORMAT_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
const byte* subStr = NULL;
|
||||
word32 subStrSz = 0, subIdx = 0, check1 = 0, check2 = ~0;
|
||||
byte keyId;
|
||||
|
||||
idx = 0;
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetUint32(&check1, str, strSz, &subIdx); /* checkint 1 */
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetUint32(&check2, str, strSz, &subIdx); /* checkint 2 */
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (check1 != check2) {
|
||||
ret = WS_KEY_CHECK_VAL_E;
|
||||
}
|
||||
}
|
||||
if (ret == WS_SUCCESS) {
|
||||
for (i = 0; i < keyCount; i++) {
|
||||
ret = GetStringRef(&subStrSz, &subStr,
|
||||
str, strSz, &subIdx);
|
||||
if (ret == WS_SUCCESS) {
|
||||
keyId = NameToId((const char*)subStr, subStrSz);
|
||||
key->keySigId = keyId;
|
||||
}
|
||||
if (ret == WS_SUCCESS) {
|
||||
switch (keyId) {
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
case ID_SSH_RSA:
|
||||
ret = GetOpenSshKeyRsa(&key->ks.rsa.key,
|
||||
str, strSz, &subIdx);
|
||||
break;
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_ECDSA
|
||||
case ID_ECDSA_SHA2_NISTP256:
|
||||
ret = GetOpenSshKeyEcc(&key->ks.ecc.key,
|
||||
str, strSz, &subIdx);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = WS_UNIMPLEMENTED_E;
|
||||
break;
|
||||
}
|
||||
if (ret == WS_SUCCESS)
|
||||
ret = GetSkip(str, strSz, &subIdx);
|
||||
/* key comment */
|
||||
}
|
||||
}
|
||||
/* Padding: Add increasing digits to pad to the nearest
|
||||
* block size. Default block size is 8, but depends on
|
||||
* the encryption algo. The private key chunk's length,
|
||||
* and the length of the comment delimit the end of the
|
||||
* encrypted blob. No added padding required. */
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (strSz % MIN_BLOCK_SZ == 0) {
|
||||
if (strSz > subIdx) {
|
||||
/* The padding starts at 1. */
|
||||
check2 = strSz - subIdx;
|
||||
for (check1 = 1;
|
||||
check1 <= check2;
|
||||
check1++, subIdx++) {
|
||||
if (check1 != str[subIdx]) {
|
||||
/* Bad pad value. */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Identifies the flavor of an OpenSSH key, RSA or ECDSA, and returns the
|
||||
* key type ID. The process is to decode the key extracting the identifiers,
|
||||
* and try to decode the key as the type indicated type. For RSA keys, the
|
||||
* key format is described as "ssh-rsa".
|
||||
*
|
||||
* @param in key to identify
|
||||
* @param inSz size of key
|
||||
* @param heap heap to use for memory allocation
|
||||
* @return keyId as int, WS_MEMORY_E, WS_UNIMPLEMENTED_E,
|
||||
* WS_INVALID_ALGO_ID
|
||||
*/
|
||||
int IdentifyOpenSshKey(const byte* in, word32 inSz, void* heap)
|
||||
{
|
||||
WS_KeySignature *key = NULL;
|
||||
word32 idx = 0;
|
||||
int ret;
|
||||
|
||||
key = (WS_KeySignature*)WMALLOC(sizeof(WS_KeySignature),
|
||||
heap, DYNTYPE_PRIVKEY);
|
||||
|
||||
if (key == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
else if (keyId == ID_UNKNOWN) {
|
||||
ret = WS_UNIMPLEMENTED_E;
|
||||
}
|
||||
else {
|
||||
ret = keyId;
|
||||
WMEMSET(key, 0, sizeof(*key));
|
||||
key->keySigId = ID_NONE;
|
||||
|
||||
ret = GetOpenSshKey(key, in, inSz, &idx);
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = key->keySigId;
|
||||
}
|
||||
else if (key->keySigId == ID_UNKNOWN) {
|
||||
ret = WS_UNIMPLEMENTED_E;
|
||||
}
|
||||
|
||||
wolfSSH_KEY_clean(key);
|
||||
WFREE(key, heap, DYNTYPE_PRIVKEY);
|
||||
}
|
||||
WFREE(key, heap, dynType);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -958,7 +1280,7 @@ int IdentifyKey(const byte* in, word32 inSz, int isPrivate, void* heap)
|
|||
/*
|
||||
* Identifies the flavor of an X.509 certificate, RSA or ECDSA, and returns
|
||||
* the key type ID. The process is to decode the certificate and pass the
|
||||
* public key to IdentifyKey.
|
||||
* public key to IdentifyAsn1Key.
|
||||
*
|
||||
* @param in certificate to identify
|
||||
* @param inSz size of certificate
|
||||
|
@ -1005,7 +1327,7 @@ static int IdentifyCert(const byte* in, word32 inSz, void* heap)
|
|||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = IdentifyKey(key, keySz, 0, heap);
|
||||
ret = IdentifyAsn1Key(key, keySz, 0, heap);
|
||||
}
|
||||
|
||||
WFREE(key, heap, DYNTYPE_PUBKEY);
|
||||
|
@ -1288,9 +1610,12 @@ int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx,
|
|||
if (ctx == NULL || in == NULL || inSz == 0)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
if (format != WOLFSSH_FORMAT_ASN1 && format != WOLFSSH_FORMAT_PEM &&
|
||||
format != WOLFSSH_FORMAT_RAW)
|
||||
if (format != WOLFSSH_FORMAT_ASN1
|
||||
&& format != WOLFSSH_FORMAT_PEM
|
||||
&& format != WOLFSSH_FORMAT_RAW
|
||||
&& format != WOLFSSH_FORMAT_OPENSSH) {
|
||||
return WS_BAD_FILETYPE_E;
|
||||
}
|
||||
|
||||
if (type == BUFTYPE_CA) {
|
||||
dynamicType = DYNTYPE_CA;
|
||||
|
@ -1341,7 +1666,7 @@ int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx,
|
|||
/* Maybe decrypt */
|
||||
|
||||
if (type == BUFTYPE_PRIVKEY) {
|
||||
ret = IdentifyKey(der, derSz, 1, ctx->heap);
|
||||
ret = IdentifyAsn1Key(der, derSz, 1, ctx->heap);
|
||||
if (ret < 0) {
|
||||
WFREE(der, heap, dynamicType);
|
||||
return ret;
|
||||
|
@ -1713,6 +2038,11 @@ static const NameIdPair NameIdMap[] = {
|
|||
|
||||
/* Ext Info IDs */
|
||||
{ ID_EXTINFO_SERVER_SIG_ALGS, "server-sig-algs" },
|
||||
|
||||
/* Curve Name IDs */
|
||||
{ ID_CURVE_NISTP256, "nistp256" },
|
||||
{ ID_CURVE_NISTP384, "nistp384" },
|
||||
{ ID_CURVE_NISTP521, "nistp521" },
|
||||
};
|
||||
|
||||
|
||||
|
@ -2397,6 +2727,26 @@ int GetSize(word32* v, const byte* buf, word32 len, word32* idx)
|
|||
}
|
||||
|
||||
|
||||
int GetSkip(const byte* buf, word32 len, word32* idx)
|
||||
{
|
||||
int result;
|
||||
word32 sz;
|
||||
|
||||
result = GetUint32(&sz, buf, len, idx);
|
||||
|
||||
if (result == WS_SUCCESS) {
|
||||
result = WS_BUFFER_E;
|
||||
|
||||
if (*idx < len && sz <= len - *idx) {
|
||||
*idx += sz;
|
||||
result = WS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Gets the size of the mpint, and puts the pointer to the start of
|
||||
* buf's number into *mpint. This function does not copy. */
|
||||
int GetMpint(word32* mpintSz, const byte** mpint,
|
||||
|
@ -8814,7 +9164,7 @@ static int SendKexGetSigningKey(WOLFSSH* ssh,
|
|||
sigKeyBlock_ptr->sk.ecc.primeName =
|
||||
PrimeNameForId(ssh->handshake->pubKeyId);
|
||||
sigKeyBlock_ptr->sk.ecc.primeNameSz =
|
||||
(word32)strlen(sigKeyBlock_ptr->sk.ecc.primeName);
|
||||
(word32)WSTRLEN(sigKeyBlock_ptr->sk.ecc.primeName);
|
||||
|
||||
/* Decode the user-configured ECDSA private key. */
|
||||
sigKeyBlock_ptr->sk.ecc.qSz =
|
||||
|
@ -9104,7 +9454,7 @@ int SendKexDhReply(WOLFSSH* ssh)
|
|||
sigKeyBlock_ptr->pubKeyName =
|
||||
IdToName(SigTypeForId(sigKeyBlock_ptr->pubKeyId));
|
||||
sigKeyBlock_ptr->pubKeyNameSz =
|
||||
(word32)strlen(sigKeyBlock_ptr->pubKeyName);
|
||||
(word32)WSTRLEN(sigKeyBlock_ptr->pubKeyName);
|
||||
sigKeyBlock_ptr->pubKeyFmtId = sigKeyBlock_ptr->pubKeyId;
|
||||
if (sigKeyBlock_ptr->pubKeyId == ID_RSA_SHA2_256
|
||||
|| sigKeyBlock_ptr->pubKeyId == ID_RSA_SHA2_512) {
|
||||
|
@ -9113,7 +9463,7 @@ int SendKexDhReply(WOLFSSH* ssh)
|
|||
sigKeyBlock_ptr->pubKeyFmtName =
|
||||
IdToName(sigKeyBlock_ptr->pubKeyFmtId);
|
||||
sigKeyBlock_ptr->pubKeyFmtNameSz =
|
||||
(word32)strlen(sigKeyBlock_ptr->pubKeyFmtName);
|
||||
(word32)WSTRLEN(sigKeyBlock_ptr->pubKeyFmtName);
|
||||
|
||||
switch (ssh->handshake->kexId) {
|
||||
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256
|
||||
|
@ -10556,40 +10906,6 @@ int SendExtInfo(WOLFSSH* ssh)
|
|||
}
|
||||
|
||||
|
||||
typedef struct WS_KeySignature {
|
||||
byte keySigId;
|
||||
word32 sigSz;
|
||||
const char *name;
|
||||
word32 nameSz;
|
||||
union {
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
struct {
|
||||
RsaKey key;
|
||||
byte e[256];
|
||||
word32 eSz;
|
||||
byte ePad;
|
||||
byte n[256];
|
||||
word32 nSz;
|
||||
byte nPad;
|
||||
} rsa;
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_ECDSA
|
||||
struct {
|
||||
ecc_key key;
|
||||
word32 keyBlobSz;
|
||||
const char *keyBlobName;
|
||||
word32 keyBlobNameSz;
|
||||
byte q[256];
|
||||
word32 qSz;
|
||||
byte qPad;
|
||||
const char *primeName;
|
||||
word32 primeNameSz;
|
||||
} ecc;
|
||||
#endif
|
||||
} ks;
|
||||
} WS_KeySignature;
|
||||
|
||||
|
||||
/* Updates the payload size, and maybe loads keys. */
|
||||
static int PrepareUserAuthRequestPassword(WOLFSSH* ssh, word32* payloadSz,
|
||||
const WS_UserAuthData* authData)
|
||||
|
@ -10647,15 +10963,24 @@ static int PrepareUserAuthRequestRsa(WOLFSSH* ssh, word32* payloadSz,
|
|||
if (ret == WS_SUCCESS) {
|
||||
word32 idx = 0;
|
||||
#ifdef WOLFSSH_AGENT
|
||||
if (ssh->agentEnabled)
|
||||
if (ssh->agentEnabled) {
|
||||
ret = wc_RsaPublicKeyDecode(authData->sf.publicKey.publicKey,
|
||||
&idx, &keySig->ks.rsa.key,
|
||||
authData->sf.publicKey.publicKeySz);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = wc_RsaPrivateKeyDecode(authData->sf.publicKey.privateKey,
|
||||
&idx, &keySig->ks.rsa.key,
|
||||
authData->sf.publicKey.privateKeySz);
|
||||
if (ret != 0) {
|
||||
idx = 0;
|
||||
ret = GetOpenSshKey(keySig,
|
||||
authData->sf.publicKey.privateKey,
|
||||
authData->sf.publicKey.privateKeySz, &idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
|
@ -11037,9 +11362,17 @@ static int PrepareUserAuthRequestEcc(WOLFSSH* ssh, word32* payloadSz,
|
|||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = wc_EccPrivateKeyDecode(authData->sf.publicKey.privateKey,
|
||||
&idx, &keySig->ks.ecc.key,
|
||||
authData->sf.publicKey.privateKeySz);
|
||||
if (ret != 0) {
|
||||
idx = 0;
|
||||
ret = GetOpenSshKey(keySig,
|
||||
authData->sf.publicKey.privateKey,
|
||||
authData->sf.publicKey.privateKeySz, &idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
|
@ -11719,23 +12052,6 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh,
|
|||
}
|
||||
|
||||
|
||||
static void CleanupUserAuthRequestPublicKey(WS_KeySignature* keySig)
|
||||
{
|
||||
if (keySig != NULL) {
|
||||
if (keySig->keySigId == ID_SSH_RSA) {
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
wc_FreeRsaKey(&keySig->ks.rsa.key);
|
||||
#endif
|
||||
}
|
||||
else if (keySig->keySigId == ID_ECDSA_SHA2_NISTP256 ||
|
||||
keySig->keySigId == ID_ECDSA_SHA2_NISTP384 ||
|
||||
keySig->keySigId == ID_ECDSA_SHA2_NISTP521) {
|
||||
#ifndef WOLFSSH_NO_ECDSA
|
||||
wc_ecc_free(&keySig->ks.ecc.key);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -11885,7 +12201,7 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig)
|
|||
}
|
||||
|
||||
if (authId == ID_USERAUTH_PUBLICKEY)
|
||||
CleanupUserAuthRequestPublicKey(keySig_ptr);
|
||||
wolfSSH_KEY_clean(keySig_ptr);
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = wolfSSH_SendPacket(ssh);
|
||||
|
@ -13491,7 +13807,6 @@ int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
|
|||
#endif /* WOLFSSH_SFTP || WOLFSSH_SCP */
|
||||
|
||||
|
||||
#ifdef DEBUG_WOLFSSH
|
||||
|
||||
#define LINE_WIDTH 16
|
||||
void DumpOctetString(const byte* input, word32 inputSz)
|
||||
|
@ -13527,7 +13842,6 @@ void DumpOctetString(const byte* input, word32 inputSz)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
|
||||
|
|
377
src/ssh.c
377
src/ssh.c
|
@ -1323,7 +1323,6 @@ void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH* ssh)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_TERM
|
||||
|
||||
#if defined(WOLFSSH_TERM) && !defined(NO_FILESYSTEM)
|
||||
/* Used to resize terminal window with shell connections
|
||||
|
@ -1361,8 +1360,6 @@ void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx)
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Used to set the channel request type sent in wolfSSH connect. The default
|
||||
* type set is shell if this function is not called.
|
||||
|
@ -1489,6 +1486,251 @@ union wolfSSH_key {
|
|||
#endif
|
||||
};
|
||||
|
||||
static const char* PrivBeginOpenSSH = "-----BEGIN OPENSSH PRIVATE KEY-----";
|
||||
static const char* PrivEndOpenSSH = "-----END OPENSSH PRIVATE KEY-----";
|
||||
static const char* PrivBeginPrefix = "-----BEGIN ";
|
||||
/* static const char* PrivEndPrefix = "-----END "; */
|
||||
static const char* PrivSuffix = " PRIVATE KEY-----";
|
||||
|
||||
|
||||
static int DoSshPubKey(const byte* in, word32 inSz, byte** out,
|
||||
word32* outSz, const byte** outType, word32* outTypeSz,
|
||||
void* heap)
|
||||
{
|
||||
byte* newKey = NULL;
|
||||
char* c;
|
||||
char* last;
|
||||
char* type = NULL;
|
||||
char* key = NULL;
|
||||
int ret = WS_SUCCESS;
|
||||
word32 newKeySz, typeSz;
|
||||
|
||||
WOLFSSH_UNUSED(inSz);
|
||||
WOLFSSH_UNUSED(heap);
|
||||
|
||||
/*
|
||||
SSH format is:
|
||||
type AAAABASE64ENCODEDKEYDATA comment
|
||||
*/
|
||||
c = WSTRDUP((const char*)in, heap, DYNTYPE_STRING);
|
||||
if (c != NULL) {
|
||||
type = WSTRTOK(c, " \n", &last);
|
||||
key = WSTRTOK(NULL, " \n", &last);
|
||||
}
|
||||
else {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (type == NULL || key == NULL) {
|
||||
ret = WS_PARSE_E;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
typeSz = (word32)WSTRLEN(type);
|
||||
/* set size based on sanity check in wolfSSL base64 decode
|
||||
* function */
|
||||
newKeySz = ((word32)WSTRLEN(key) * 3 + 3) / 4;
|
||||
if (*out == NULL) {
|
||||
newKey = (byte*)WMALLOC(newKeySz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*outSz < newKeySz) {
|
||||
WLOG(WS_LOG_DEBUG, "PEM private key output size too small");
|
||||
ret = WS_BUFFER_E;
|
||||
}
|
||||
else {
|
||||
newKey = *out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key),
|
||||
newKey, &newKeySz);
|
||||
|
||||
if (ret == 0) {
|
||||
*out = newKey;
|
||||
*outSz = newKeySz;
|
||||
*outType = (const byte *)IdToName(NameToId(type, typeSz));
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
|
||||
if (*out == NULL) {
|
||||
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
|
||||
}
|
||||
ret = WS_PARSE_E;
|
||||
}
|
||||
}
|
||||
|
||||
WFREE(c, heap, DYNTYPE_STRING);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int DoAsn1Key(const byte* in, word32 inSz, byte** out,
|
||||
word32* outSz, const byte** outType, word32* outTypeSz,
|
||||
void* heap)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
byte* newKey = NULL;
|
||||
|
||||
WOLFSSH_UNUSED(heap);
|
||||
|
||||
if (*out == NULL) {
|
||||
newKey = (byte*)WMALLOC(inSz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "DER private key output size too small");
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
newKey = *out;
|
||||
}
|
||||
|
||||
ret = IdentifyAsn1Key(in, inSz, 1, heap);
|
||||
|
||||
if (ret > 0) {
|
||||
*out = newKey;
|
||||
*outSz = inSz;
|
||||
WMEMCPY(newKey, in, inSz);
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "unable to identify key");
|
||||
if (*out == NULL) {
|
||||
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int DoPemKey(const byte* in, word32 inSz, byte** out,
|
||||
word32* outSz, const byte** outType, word32* outTypeSz,
|
||||
void* heap)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
byte* newKey = NULL;
|
||||
word32 newKeySz = inSz; /* binary will be smaller than PEM */
|
||||
|
||||
WOLFSSH_UNUSED(heap);
|
||||
|
||||
if (*out == NULL) {
|
||||
newKey = (byte*)WMALLOC(inSz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "PEM private key output size too small");
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
newKey = *out;
|
||||
}
|
||||
|
||||
/* If it is PEM, convert to ASN1 then process. */
|
||||
ret = wc_KeyPemToDer(in, inSz, newKey, newKeySz, NULL);
|
||||
if (ret > 0) {
|
||||
newKeySz = (word32)ret;
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
|
||||
ret = WS_PARSE_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = IdentifyAsn1Key(newKey, newKeySz, 1, heap);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
*out = newKey;
|
||||
*outSz = newKeySz;
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "unable to identify key");
|
||||
if (*out == NULL) {
|
||||
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int DoOpenSshKey(const byte* in, word32 inSz, byte** out,
|
||||
word32* outSz, const byte** outType, word32* outTypeSz,
|
||||
void* heap)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
byte* newKey = NULL;
|
||||
word32 newKeySz = inSz; /* binary will be smaller than PEM */
|
||||
|
||||
if (*out == NULL) {
|
||||
newKey = (byte*)WMALLOC(newKeySz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "PEM private key output size too small");
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
newKey = *out;
|
||||
}
|
||||
|
||||
in += WSTRLEN(PrivBeginOpenSSH);
|
||||
inSz -= (word32)(WSTRLEN(PrivBeginOpenSSH) + WSTRLEN(PrivEndOpenSSH) + 2);
|
||||
|
||||
ret = Base64_Decode((byte*)in, inSz, newKey, &newKeySz);
|
||||
if (ret == 0) {
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
|
||||
ret = WS_PARSE_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = IdentifyOpenSshKey(newKey, newKeySz, heap);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
*out = newKey;
|
||||
*outSz = newKeySz;
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "unable to identify key");
|
||||
if (*out == NULL) {
|
||||
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Reads a key from the buffer in to out. If the out buffer doesn't exist
|
||||
it is created. The type of key is stored in outType. It'll be a pointer
|
||||
to a constant string. Format indicates the format of the key, currently
|
||||
|
@ -1499,127 +1741,22 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
|
|||
void* heap)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
byte* newKey = NULL;
|
||||
|
||||
WOLFSSH_UNUSED(heap);
|
||||
|
||||
if (in == NULL || inSz == 0 || out == NULL || outSz == NULL ||
|
||||
outType == NULL || outTypeSz == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
if (format == WOLFSSH_FORMAT_SSH) {
|
||||
char* c;
|
||||
char* last;
|
||||
char* type = NULL;
|
||||
char* key = NULL;
|
||||
|
||||
/*
|
||||
SSH format is:
|
||||
type AAAABASE64ENCODEDKEYDATA comment
|
||||
*/
|
||||
c = WSTRDUP((const char*)in, heap, DYNTYPE_STRING);
|
||||
type = WSTRTOK(c, " \n", &last);
|
||||
key = WSTRTOK(NULL, " \n", &last);
|
||||
|
||||
if (type != NULL && key != NULL) {
|
||||
const char* name;
|
||||
word32 typeSz;
|
||||
byte nameId;
|
||||
|
||||
typeSz = (word32)WSTRLEN(type);
|
||||
|
||||
nameId = NameToId(type, typeSz);
|
||||
name = IdToName(nameId);
|
||||
*outType = (const byte*)name;
|
||||
*outTypeSz = typeSz;
|
||||
|
||||
if (*out == NULL) {
|
||||
/* set size based on sanity check in wolfSSL base64 decode
|
||||
* function */
|
||||
*outSz = ((word32)WSTRLEN(key) * 3 + 3) / 4;
|
||||
newKey = (byte*)WMALLOC(*outSz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
*out = newKey;
|
||||
}
|
||||
|
||||
ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key), *out, outSz);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
|
||||
ret = WS_PARSE_E;
|
||||
}
|
||||
|
||||
WFREE(c, heap, DYNTYPE_STRING);
|
||||
ret = DoSshPubKey(in, inSz, out, outSz, outType, outTypeSz, heap);
|
||||
}
|
||||
else if (format == WOLFSSH_FORMAT_ASN1) {
|
||||
if (*out == NULL) {
|
||||
newKey = (byte*)WMALLOC(inSz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
*out = newKey;
|
||||
}
|
||||
else {
|
||||
if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "DER private key output size too small");
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
newKey = *out;
|
||||
}
|
||||
*outSz = inSz;
|
||||
WMEMCPY(newKey, in, inSz);
|
||||
|
||||
ret = IdentifyKey(in, inSz, 1, heap);
|
||||
if (ret > 0) {
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
ret = DoAsn1Key(in, inSz, out, outSz, outType, outTypeSz, heap);
|
||||
}
|
||||
else if (format == WOLFSSH_FORMAT_PEM) {
|
||||
word32 newKeySz = inSz; /* binary will be smaller than PEM */
|
||||
|
||||
if (*out == NULL) {
|
||||
newKey = (byte*)WMALLOC(newKeySz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
*out = newKey;
|
||||
}
|
||||
else {
|
||||
if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "PEM private key output size too small");
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
newKey = *out;
|
||||
}
|
||||
|
||||
/* If it is PEM, convert to ASN1 then process. */
|
||||
ret = wc_KeyPemToDer(in, inSz, newKey, newKeySz, NULL);
|
||||
if (ret > 0) {
|
||||
newKeySz = (word32)ret;
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
|
||||
ret = WS_PARSE_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = IdentifyKey(newKey, newKeySz, 1, heap);
|
||||
if (ret > 0) {
|
||||
*outSz = newKeySz;
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "unable to identify key");
|
||||
}
|
||||
}
|
||||
ret = DoPemKey(in, inSz, out, outSz, outType, outTypeSz, heap);
|
||||
}
|
||||
else if (format == WOLFSSH_FORMAT_OPENSSH) {
|
||||
ret = DoOpenSshKey(in, inSz, out, outSz, outType, outTypeSz, heap);
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Invalid key format");
|
||||
|
@ -1687,9 +1824,17 @@ int wolfSSH_ReadKey_file(const char* name,
|
|||
format = WOLFSSH_FORMAT_SSH;
|
||||
in[inSz] = 0;
|
||||
}
|
||||
else if ((WSTRNSTR((const char*)in, "-----BEGIN ", inSz)
|
||||
#if 0
|
||||
else if (WSTRNSTR((const char*)in, PrivBeginOpenSSH, inSz) != NULL &&
|
||||
WSTRNSTR((const char*)in, PrivEndOpenSSH, inSz) != NULL) {
|
||||
#endif
|
||||
else if (WSTRNSTR((const char*)in, PrivBeginOpenSSH, inSz) != NULL) {
|
||||
*isPrivate = 1;
|
||||
format = WOLFSSH_FORMAT_OPENSSH;
|
||||
}
|
||||
else if ((WSTRNSTR((const char*)in, PrivBeginPrefix, inSz)
|
||||
== (const char*)in)
|
||||
&& (WSTRNSTR((const char*)in, "PRIVATE KEY-----", inSz)
|
||||
&& (WSTRNSTR((const char*)in, PrivSuffix, inSz)
|
||||
!= NULL)) {
|
||||
*isPrivate = 1;
|
||||
format = WOLFSSH_FORMAT_PEM;
|
||||
|
|
198
tests/api.c
198
tests/api.c
|
@ -602,6 +602,203 @@ static void test_wolfSSH_CertMan(void)
|
|||
}
|
||||
|
||||
|
||||
#define KEY_BUF_SZ 2048
|
||||
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
|
||||
const char id_rsa[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"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\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
const char id_rsa_pub[] =
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLZyKBkOWkFP5fYwkcCged94V/r4seboEO"
|
||||
"QBPxX16McDh1jQB6lvo1tXq7+hhmW54o94BncY3O1H2zOgvoVKUy+R32iq9+jGNMa7vVPT3z"
|
||||
"XJsl6WqoYBMa168dTomSj8jT6WBJAUpZAnsPcOPbOVmkhcHZDvGX+L2QVmBoioWFQd1Y70kw"
|
||||
"7AIXCgOuF3y/nGTLW/c4ghkPGJjFUgpt/YnTtZvCJIUDFd+JfxONQEMsWa2q3UAXouMDIbJp"
|
||||
"EgJeRoYlD9An2xfzmH1uSI+UY0C1AZC01SDe0L0ao6Rn20IpjUR+H+vTOiw4Du5/GDrKYumr"
|
||||
"ULgtT/gQ0YeS5E8Aq+7z bob@localhost\n";
|
||||
|
||||
#endif /* WOLFSSH_NO_RSA */
|
||||
|
||||
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
|
||||
|
||||
const char id_ecdsa[] =
|
||||
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\n"
|
||||
"1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTAqdBgCp8bYSq2kQQ48/Ud8Iy6Mjnb\n"
|
||||
"/fpB3LfSE/1kx9VaaE4FL3i9Gg2vDV0eLGM3PWksFNPhULxtcYJyjaBjAAAAqJAeleSQHp\n"
|
||||
"XkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMCp0GAKnxthKraR\n"
|
||||
"BDjz9R3wjLoyOdv9+kHct9IT/WTH1VpoTgUveL0aDa8NXR4sYzc9aSwU0+FQvG1xgnKNoG\n"
|
||||
"MAAAAgPrOgktioNqad/wHNC/rt/zVrpNqDnOwg9tNDFMOTwo8AAAANYm9iQGxvY2FsaG9z\n"
|
||||
"dAECAw==\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n";
|
||||
|
||||
const char id_ecdsa_pub[] =
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABB"
|
||||
"BMCp0GAKnxthKraRBDjz9R3wjLoyOdv9+kHct9IT/WTH1VpoTgUveL0aDa8NXR4sYzc9aSwU"
|
||||
"0+FQvG1xgnKNoGM= bob@localhost\n";
|
||||
|
||||
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP256 */
|
||||
|
||||
static void test_wolfSSH_ReadKey(void)
|
||||
{
|
||||
#if !defined(WOLFSSH_NO_RSA) || !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
|
||||
byte *key, *keyCheck, *derKey;
|
||||
const byte* keyType;
|
||||
word32 keySz, keyTypeSz, derKeySz;
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
|
||||
/* OpenSSH Format, ssh-rsa, private, need alloc */
|
||||
key = NULL;
|
||||
keySz = 0;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = wolfSSH_ReadKey_buffer((const byte*)id_rsa, (word32)WSTRLEN(id_rsa),
|
||||
WOLFSSH_FORMAT_OPENSSH, &key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertNotNull(key);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ssh-rsa");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ssh-rsa"));
|
||||
WFREE(key, NULL, DYNTYPE_FILE);
|
||||
|
||||
/* SSL PEM Format, ssh-rsa, private, need alloc */
|
||||
derKey = NULL;
|
||||
derKeySz = 0;
|
||||
key = NULL;
|
||||
keySz = 0;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = ConvertHexToBin(serverKeyRsaDer, &derKey, &derKeySz,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
AssertIntEQ(ret, 0);
|
||||
ret = wolfSSH_ReadKey_buffer(derKey, derKeySz, WOLFSSH_FORMAT_ASN1,
|
||||
&key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertNotNull(key);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ssh-rsa");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ssh-rsa"));
|
||||
WFREE(key, NULL, DYNTYPE_FILE);
|
||||
WFREE(derKey, NULL, 0);
|
||||
|
||||
/* OpenSSH Format, ssh-rsa, public, need alloc */
|
||||
key = NULL;
|
||||
keySz = 0;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = wolfSSH_ReadKey_buffer((const byte*)id_rsa_pub,
|
||||
(word32)WSTRLEN(id_rsa_pub), WOLFSSH_FORMAT_SSH,
|
||||
&key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertNotNull(key);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ssh-rsa");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ssh-rsa"));
|
||||
WFREE(key, NULL, DYNTYPE_FILE);
|
||||
|
||||
/* OpenSSH Format, ssh-rsa, private, no alloc */
|
||||
keyCheck = (byte*)WMALLOC(KEY_BUF_SZ, NULL, DYNTYPE_FILE);
|
||||
AssertNotNull(keyCheck);
|
||||
key = keyCheck;
|
||||
keySz = KEY_BUF_SZ;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = wolfSSH_ReadKey_buffer((const byte*)id_rsa, (word32)WSTRLEN(id_rsa),
|
||||
WOLFSSH_FORMAT_OPENSSH, &key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertTrue(key == keyCheck);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ssh-rsa");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ssh-rsa"));
|
||||
WFREE(keyCheck, NULL, DYNTYPE_FILE);
|
||||
|
||||
#endif /* WOLFSSH_NO_RSA */
|
||||
|
||||
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
|
||||
|
||||
/* OpenSSH Format, ecdsa-sha2-nistp256, private, need alloc */
|
||||
key = NULL;
|
||||
keySz = 0;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = wolfSSH_ReadKey_buffer((const byte*)id_ecdsa,
|
||||
(word32)WSTRLEN(id_ecdsa), WOLFSSH_FORMAT_OPENSSH,
|
||||
&key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertNotNull(key);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ecdsa-sha2-nistp256");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ecdsa-sha2-nistp256"));
|
||||
WFREE(key, NULL, DYNTYPE_FILE);
|
||||
|
||||
/* SSL DER Format, ecdsa-sha2-nistp256, private, need alloc */
|
||||
derKey = NULL;
|
||||
derKeySz = 0;
|
||||
key = NULL;
|
||||
keySz = 0;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = ConvertHexToBin(serverKeyEccDer, &derKey, &derKeySz,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
ret = wolfSSH_ReadKey_buffer(derKey, derKeySz, WOLFSSH_FORMAT_ASN1,
|
||||
&key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertNotNull(key);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ecdsa-sha2-nistp256");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ecdsa-sha2-nistp256"));
|
||||
WFREE(key, NULL, DYNTYPE_FILE);
|
||||
WFREE(derKey, NULL, 0);
|
||||
|
||||
/* OpenSSH Format, ecdsa-sha2-nistp256, public, need alloc */
|
||||
key = NULL;
|
||||
keySz = 0;
|
||||
keyType = NULL;
|
||||
keyTypeSz = 0;
|
||||
ret = wolfSSH_ReadKey_buffer((const byte*)id_ecdsa_pub,
|
||||
(word32)WSTRLEN(id_ecdsa_pub), WOLFSSH_FORMAT_SSH,
|
||||
&key, &keySz, &keyType, &keyTypeSz, NULL);
|
||||
AssertIntEQ(ret, WS_SUCCESS);
|
||||
AssertNotNull(key);
|
||||
AssertIntGT(keySz, 0);
|
||||
AssertStrEQ(keyType, "ecdsa-sha2-nistp256");
|
||||
AssertIntEQ(keyTypeSz, (word32)WSTRLEN("ecdsa-sha2-nistp256"));
|
||||
WFREE(key, NULL, DYNTYPE_FILE);
|
||||
|
||||
#endif /* WOLFSSH_NO_ECDSA_SHA2_NISTP256 */
|
||||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSH_SCP
|
||||
|
||||
static int my_ScpRecv(WOLFSSH* ssh, int state, const char* basePath,
|
||||
|
@ -1125,6 +1322,7 @@ int wolfSSH_ApiTest(int argc, char** argv)
|
|||
test_wolfSSH_CTX_UsePrivateKey_buffer();
|
||||
test_wolfSSH_CTX_UseCert_buffer();
|
||||
test_wolfSSH_CertMan();
|
||||
test_wolfSSH_ReadKey();
|
||||
|
||||
/* SCP tests */
|
||||
test_wolfSSH_SCP_CB();
|
||||
|
|
|
@ -128,8 +128,11 @@ enum WS_ErrorCodes {
|
|||
WS_CERT_KEY_SIZE_E = -1087, /* Key size error */
|
||||
WS_CTX_KEY_COUNT_E = -1088, /* Adding too many private keys */
|
||||
WS_MATCH_UA_KEY_ID_E = -1089, /* Match user auth key key fail */
|
||||
WS_KEY_AUTH_MAGIC_E = -1090, /* OpenSSH key auth magic check fail */
|
||||
WS_KEY_CHECK_VAL_E = -1091, /* OpenSSH key check value fail */
|
||||
WS_KEY_FORMAT_E = -1092, /* OpenSSH key format fail */
|
||||
|
||||
WS_LAST_E = -1089 /* Update this to indicate last error */
|
||||
WS_LAST_E = -1092 /* Update this to indicate last error */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -347,6 +347,10 @@ enum {
|
|||
|
||||
ID_EXTINFO_SERVER_SIG_ALGS,
|
||||
|
||||
ID_CURVE_NISTP256,
|
||||
ID_CURVE_NISTP384,
|
||||
ID_CURVE_NISTP521,
|
||||
|
||||
ID_UNKNOWN
|
||||
};
|
||||
|
||||
|
@ -420,6 +424,9 @@ enum {
|
|||
#ifndef WOLFSSH_MAX_PUB_KEY_ALGO
|
||||
#define WOLFSSH_MAX_PUB_KEY_ALGO (WOLFSSH_MAX_PVT_KEYS + 2)
|
||||
#endif
|
||||
#ifndef WOLFSSH_KEY_QUANTITY_REQ
|
||||
#define WOLFSSH_KEY_QUANTITY_REQ 1
|
||||
#endif
|
||||
|
||||
WOLFSSH_LOCAL byte NameToId(const char*, word32);
|
||||
WOLFSSH_LOCAL const char* IdToName(byte);
|
||||
|
@ -855,8 +862,9 @@ WOLFSSH_LOCAL void ChannelDelete(WOLFSSH_CHANNEL*, void*);
|
|||
WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelFind(WOLFSSH*, word32, byte);
|
||||
WOLFSSH_LOCAL int ChannelRemove(WOLFSSH*, word32, byte);
|
||||
WOLFSSH_LOCAL int ChannelPutData(WOLFSSH_CHANNEL*, byte*, word32);
|
||||
WOLFSSH_LOCAL int IdentifyKey(const byte* in, word32 inSz,
|
||||
WOLFSSH_LOCAL int IdentifyAsn1Key(const byte* in, word32 inSz,
|
||||
int isPrivate, void* heap);
|
||||
WOLFSSH_LOCAL int IdentifyOpenSshKey(const byte* in, word32 inSz, void* heap);
|
||||
WOLFSSH_LOCAL int wolfSSH_ProcessBuffer(WOLFSSH_CTX*,
|
||||
const byte*, word32,
|
||||
int, int);
|
||||
|
@ -869,6 +877,7 @@ WOLFSSH_LOCAL int GetUint32(word32* v,
|
|||
const byte* buf, word32 len, word32* idx);
|
||||
WOLFSSH_LOCAL int GetSize(word32* v,
|
||||
const byte* buf, word32 len, word32* idx);
|
||||
WOLFSSH_LOCAL int GetSkip(const byte* buf, word32 len, word32* idx);
|
||||
WOLFSSH_LOCAL int GetMpint(word32* mpintSz, const byte** mpint,
|
||||
const byte* buf, word32 len, word32* idx);
|
||||
WOLFSSH_LOCAL int GetString(char* s, word32* sSz,
|
||||
|
|
|
@ -1390,7 +1390,7 @@ extern "C" {
|
|||
|
||||
|
||||
#ifndef WOLFSSH_UNUSED
|
||||
#define WOLFSSH_UNUSED(arg) (void)(arg);
|
||||
#define WOLFSSH_UNUSED(arg) (void)(arg)
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -311,6 +311,7 @@ enum WS_FormatTypes {
|
|||
WOLFSSH_FORMAT_PEM,
|
||||
WOLFSSH_FORMAT_RAW,
|
||||
WOLFSSH_FORMAT_SSH,
|
||||
WOLFSSH_FORMAT_OPENSSH
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue