Merge pull request #583 from ejohnstown/pem-keys

Read PEM Keys
pull/584/head
David Garske 2023-09-18 12:05:18 -07:00 committed by GitHub
commit 417388c72a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 12 deletions

View File

@ -1479,7 +1479,8 @@ union wolfSSH_key {
/* Reads a key from the buffer in to out. If the out buffer doesn't exist /* 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 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 to a constant string. Format indicates the format of the key, currently
either SSH format (a public key) or ASN.1 in DER format (a private key). */ either SSH format (a public key) or ASN.1 in DER or PEM format (a
private key). */
int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format, int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
byte** out, word32* outSz, const byte** outType, word32* outTypeSz, byte** out, word32* outSz, const byte** outType, word32* outTypeSz,
void* heap) void* heap)
@ -1533,8 +1534,10 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key), *out, outSz); ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key), *out, outSz);
} }
if (ret != 0) if (ret != 0) {
ret = WS_ERROR; WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
ret = WS_PARSE_E;
}
WFREE(c, heap, DYNTYPE_STRING); WFREE(c, heap, DYNTYPE_STRING);
} }
@ -1548,7 +1551,8 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
} }
else { else {
if (*outSz < inSz) { if (*outSz < inSz) {
return WS_ERROR; WLOG(WS_LOG_DEBUG, "DER private key output size too small");
return WS_BUFFER_E;
} }
newKey = *out; newKey = *out;
} }
@ -1562,8 +1566,52 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
ret = WS_SUCCESS; ret = WS_SUCCESS;
} }
} }
else else if (format == WOLFSSH_FORMAT_PEM) {
ret = WS_ERROR; 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");
}
}
}
else {
WLOG(WS_LOG_DEBUG, "Invalid key format");
ret = WS_BAD_ARGUMENT;
}
return ret; return ret;
} }
@ -1573,8 +1621,9 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
/* Reads a key from the file name into a buffer. If the key starts with the /* Reads a key from the file name into a buffer. If the key starts with the
string "ssh-rsa" or "ecdsa-sha2-nistp256", it is considered an SSH format string "ssh-rsa" or "ecdsa-sha2-nistp256", it is considered an SSH format
public key, otherwise it is considered an ASN.1 private key. The buffer public key, if it has "----BEGIN" it is considered PEM formatted,
is passed to wolfSSH_ReadKey_buffer() for processing. */ otherwise it is considered an ASN.1 private key. The buffer is passed to
wolfSSH_ReadKey_buffer() for processing. */
int wolfSSH_ReadKey_file(const char* name, int wolfSSH_ReadKey_file(const char* name,
byte** out, word32* outSz, const byte** outType, word32* outTypeSz, byte** out, word32* outSz, const byte** outType, word32* outTypeSz,
byte* isPrivate, void* heap) byte* isPrivate, void* heap)
@ -1625,6 +1674,13 @@ int wolfSSH_ReadKey_file(const char* name,
format = WOLFSSH_FORMAT_SSH; format = WOLFSSH_FORMAT_SSH;
in[inSz] = 0; in[inSz] = 0;
} }
else if ((WSTRNSTR((const char*)in, "-----BEGIN ", inSz)
== (const char*)in)
&& (WSTRNSTR((const char*)in, "PRIVATE KEY-----", inSz)
!= NULL)) {
*isPrivate = 1;
format = WOLFSSH_FORMAT_PEM;
}
else { else {
*isPrivate = 1; *isPrivate = 1;
format = WOLFSSH_FORMAT_ASN1; format = WOLFSSH_FORMAT_ASN1;

View File

@ -83,10 +83,12 @@ WOLFSSH_API void wolfSSH_SetHighwaterCb(WOLFSSH_CTX*, word32,
WOLFSSH_API void wolfSSH_SetHighwaterCtx(WOLFSSH*, void*); WOLFSSH_API void wolfSSH_SetHighwaterCtx(WOLFSSH*, void*);
WOLFSSH_API void* wolfSSH_GetHighwaterCtx(WOLFSSH*); WOLFSSH_API void* wolfSSH_GetHighwaterCtx(WOLFSSH*);
WOLFSSH_API int wolfSSH_ReadKey_buffer(const byte*, word32, int, WOLFSSH_API int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
byte**, word32*, const byte**, word32*, void*); byte** out, word32* outSz, const byte** outType, word32* outTypeSz,
WOLFSSH_API int wolfSSH_ReadKey_file(const char*, void* heap);
byte**, word32*, const byte**, word32*, byte*, void*); WOLFSSH_API int wolfSSH_ReadKey_file(const char* name,
byte** out, word32* outSz, const byte** outType, word32* outTypeSz,
byte* isPrivate, void* heap);
#define WS_CHANNEL_ID_SELF 0 #define WS_CHANNEL_ID_SELF 0