-
Notifications
You must be signed in to change notification settings - Fork 119
Report a failed PEM decode as WS_PARSE_E, not WS_BAD_FILE_E #1151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -670,6 +670,32 @@ static int load_file(const char* filename, byte** buf, word32* bufSz) | |
| #endif | ||
|
|
||
|
|
||
| #ifdef WOLFSSH_CERTS | ||
|
|
||
| /* PEM shapes that carry a header the sniff accepts but a body no decoder | ||
| * will take, so the failure lands in the decoder rather than the sniff. */ | ||
| static const char badPemCert[] = | ||
| "-----BEGIN CERTIFICATE-----\n" | ||
| "!!!! this is not base64 !!!!\n" | ||
| "-----END CERTIFICATE-----\n"; | ||
| static const char noBodyPemCert[] = "-----BEGIN CERTIFICATE-----\n"; | ||
| /* Under one full base64 group, so the body decodes to nothing rather than | ||
| * failing, and wolfSSL answers 0 for it instead of a negative code. */ | ||
| static const char zeroLenPemCert[] = | ||
| "-----BEGIN CERTIFICATE-----\n" | ||
| "MI\n" | ||
| "-----END CERTIFICATE-----\n"; | ||
|
|
||
| #ifndef WOLFSSH_NO_SERVER | ||
| static const char badPemKey[] = | ||
| "-----BEGIN PRIVATE KEY-----\n" | ||
| "!!!! this is not base64 !!!!\n" | ||
| "-----END PRIVATE KEY-----\n"; | ||
| #endif /* WOLFSSH_NO_SERVER */ | ||
|
|
||
| #endif /* WOLFSSH_CERTS */ | ||
|
|
||
|
|
||
| static void test_wolfSSH_CTX_UseCert_buffer(void) | ||
| { | ||
| #ifdef WOLFSSH_CERTS | ||
|
|
@@ -704,6 +730,18 @@ static void test_wolfSSH_CTX_UseCert_buffer(void) | |
| AssertIntEQ(WS_BAD_FILETYPE_E, | ||
| wolfSSH_CTX_UseCert_buffer(ctx, cert, certSz, 99)); | ||
|
|
||
| /* Content the caller declared PEM but that will not decode is malformed | ||
| * input, not a file that would not read. */ | ||
| AssertIntEQ(WS_PARSE_E, | ||
| wolfSSH_CTX_UseCert_buffer(ctx, (const byte*)badPemCert, | ||
| (word32)WSTRLEN(badPemCert), WOLFSSH_FORMAT_PEM)); | ||
| AssertIntEQ(WS_PARSE_E, | ||
| wolfSSH_CTX_UseCert_buffer(ctx, (const byte*)noBodyPemCert, | ||
| (word32)WSTRLEN(noBodyPemCert), WOLFSSH_FORMAT_PEM)); | ||
| AssertIntEQ(WS_PARSE_E, | ||
| wolfSSH_CTX_UseCert_buffer(ctx, (const byte*)zeroLenPemCert, | ||
| (word32)WSTRLEN(zeroLenPemCert), WOLFSSH_FORMAT_PEM)); | ||
|
|
||
| free(cert); | ||
| cert = NULL; | ||
|
|
||
|
|
@@ -834,6 +872,24 @@ static void test_wolfSSH_ReadCert_buffer(void) | |
| free(cert); | ||
| cert = NULL; | ||
|
|
||
| /* Keeping the header sends these past the sniff and into the decoder, | ||
| * where a body that will not decode is a parse failure. No file was | ||
| * opened on this path, so it must not be reported as a file error. */ | ||
| AssertIntEQ(WS_PARSE_E, wolfSSH_ReadCert_buffer((const byte*)badPemCert, | ||
| (word32)WSTRLEN(badPemCert), | ||
| &out, &outSz, &outType, &outTypeSz, &flavor, NULL)); | ||
| AssertNull(out); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] New out-param assertions in test_wolfSSH_ReadCert_buffer pass vacuously · Weak or missing assertions
Fix: Poison the out params with sentinels before each call, as the existing block at lines 934-946 does. |
||
| AssertIntEQ(outSz, 0); | ||
| AssertNull(outType); | ||
| AssertIntEQ(outTypeSz, 0); | ||
| AssertIntEQ(flavor, WOLFSSH_CERT_FLAVOR_UNKNOWN); | ||
|
|
||
| AssertIntEQ(WS_PARSE_E, wolfSSH_ReadCert_buffer((const byte*)noBodyPemCert, | ||
| (word32)WSTRLEN(noBodyPemCert), | ||
| &out, &outSz, &outType, &outTypeSz, &flavor, NULL)); | ||
| AssertNull(out); | ||
| AssertIntEQ(flavor, WOLFSSH_CERT_FLAVOR_UNKNOWN); | ||
|
|
||
| AssertIntEQ(0, load_file("./keys/server-cert.der", &cert, &certSz)); | ||
| #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 | ||
| AssertIntEQ(WS_SUCCESS, wolfSSH_ReadCert_buffer(cert, certSz, | ||
|
|
@@ -1058,6 +1114,15 @@ static void test_wolfSSH_CTX_AddRootCert_file(void) | |
| /* The cert manager rejects a non-CA in wolfSSL's codes; this path maps. */ | ||
| AssertIntEQ(WS_PARSE_E, | ||
| wolfSSH_CTX_AddRootCert_file(ctx, "./keys/server-key-ecc.der")); | ||
|
|
||
| /* The buffer entry point, tested here because it shares this one's | ||
| * decoder: a PEM body that will not decode is a parse failure. */ | ||
| AssertIntEQ(WS_PARSE_E, | ||
| wolfSSH_CTX_AddRootCert_buffer(ctx, (const byte*)badPemCert, | ||
| (word32)WSTRLEN(badPemCert), WOLFSSH_FORMAT_PEM)); | ||
| AssertIntEQ(WS_PARSE_E, | ||
| wolfSSH_CTX_AddRootCert_buffer(ctx, (const byte*)zeroLenPemCert, | ||
| (word32)WSTRLEN(zeroLenPemCert), WOLFSSH_FORMAT_PEM)); | ||
| #ifdef WOLFSSH_TEST_OSSH_CERT_FILE | ||
| AssertIntEQ(0, writeTmpFile(osshCertPath, osshCertLine, | ||
| WSTRLEN(osshCertLine))); | ||
|
|
@@ -1118,6 +1183,12 @@ static void test_wolfSSH_CTX_UsePrivateKey_buffer_pem(void) | |
| key = NULL; | ||
| #endif /* WOLFSSH_NO_ECDSA */ | ||
|
|
||
| /* A key PEM shares the certificate PEM's decoder, and answers the same | ||
| * way when its body will not decode. */ | ||
| AssertIntEQ(WS_PARSE_E, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] New ret = 0 rejection is unpinned on the private-key arm · Missing edge-case coverage on a function the PR also changed The PR widens Fix: Add a zero-length-body PEM private key fixture (a |
||
| wolfSSH_CTX_UsePrivateKey_buffer(ctx, (const byte*)badPemKey, | ||
| (word32)WSTRLEN(badPemKey), WOLFSSH_FORMAT_PEM)); | ||
|
|
||
| wolfSSH_CTX_free(ctx); | ||
| #endif /* WOLFSSH_CERTS && !WOLFSSH_NO_SERVER */ | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -106,7 +106,10 @@ WOLFSSH_API int wolfSSH_ReadKey_file(const char* name, | |
|
|
||
| #if defined(WOLFSSH_CERTS) || defined(WOLFSSH_OSSH_CERTS) | ||
| /* Decodes a PEM/DER X.509 cert or OpenSSH cert line, detected from content. | ||
| * Caller frees out via heap; on failure every out param is cleared. */ | ||
| * Caller frees out via heap; on failure every out param is cleared. Returns | ||
| * WS_BAD_FILETYPE_E if the content is not a certificate form, and WS_PARSE_E | ||
| * if it is but will not decode. WS_BAD_FILE_E comes only from the _file entry | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⚪ [Info] New ssh.h note misstates when WS_BAD_FILE_E is returned · Incorrect error handling The note says Fix: Extend the note to say a NULL file name also answers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⚪ [Info] New ssh.h return-code contract is contradicted by pinned behaviour · SSH protocol violations The added comment states Fix: Note that a NULL |
||
| * point, and only when the file itself will not read. */ | ||
| WOLFSSH_API int wolfSSH_ReadCert_buffer(const byte* in, word32 inSz, | ||
| byte** out, word32* outSz, const byte** outType, word32* outTypeSz, | ||
| byte* flavor, void* heap); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.