Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scripts/asn1_oid_sum.pl
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,7 @@ sub print_footer {
my @eku_ssh_client_auth = ( 1, 3, 6, 1, 5, 5, 7, 3, 21 );
my @eku_ssh_mscl = ( 1, 3, 6, 1, 4, 1, 311, 20, 2, 2 );
my @eku_ssh_kp_client_auth = ( 1, 3, 6, 1, 5, 2, 3, 4 );
my @eku_ssh_server_auth = ( 1, 3, 6, 1, 5, 5, 7, 3, 22 );

my @ekus = (
{ name => "EKU_ANY", oid => \@eku_any },
Expand All @@ -970,6 +971,7 @@ sub print_footer {
{ name => "EKU_SSH_CLIENT_AUTH", oid => \@eku_ssh_client_auth },
{ name => "EKU_SSH_MSCL", oid => \@eku_ssh_mscl },
{ name => "EKU_SSH_KP_CLIENT_AUTH", oid => \@eku_ssh_kp_client_auth },
{ name => "EKU_SSH_SERVER_AUTH", oid => \@eku_ssh_server_auth },
);

print_sum_enum("ExtKeyUsage", "_OID", \@ekus);
Expand Down
135 changes: 135 additions & 0 deletions tests/api/test_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3547,6 +3547,141 @@ int test_wc_DecodeKeyUsage_decipherOnly(void)
return EXPECT_RESULT();
}

#if defined(WOLFSSL_WOLFSSH) && !defined(NO_ASN) && !defined(NO_CERTS) && \
defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_SHA256)
#define TEST_EXTKEYUSAGE_SSH
#endif

/*
* id-kp-secureShellClient and id-kp-secureShellServer (RFC 6187) are decoded
* into extExtKeyUsageSsh, not extExtKeyUsage. Parse a self-signed P-256 cert
* whose only key purposes are those two and check both bits land.
*/
int test_wc_DecodeExtKeyUsage_ssh(void)
{
EXPECT_DECLS;
#ifdef TEST_EXTKEYUSAGE_SSH
static const unsigned char sshEkuCert[] = {
0x30, 0x82, 0x01, 0x89, 0x30, 0x82, 0x01, 0x2f, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x09, 0x00, 0xc3, 0xf3, 0x13, 0xd2, 0x5f, 0x80, 0x6d, 0xd6,
0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
0x30, 0x31, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x10, 0x30,
0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x73, 0x73, 0x68, 0x2d,
0x65, 0x6b, 0x75, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x39, 0x30,
0x33, 0x30, 0x34, 0x35, 0x34, 0x34, 0x36, 0x5a, 0x18, 0x0f, 0x32, 0x31,
0x32, 0x36, 0x30, 0x38, 0x31, 0x30, 0x30, 0x34, 0x35, 0x34, 0x34, 0x36,
0x5a, 0x30, 0x31, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x10,
0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x73, 0x73, 0x68,
0x2d, 0x65, 0x6b, 0x75, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xfe, 0x1b, 0x76, 0x35, 0xdc,
0x20, 0x18, 0xc2, 0x9c, 0x30, 0x2f, 0xa7, 0x69, 0x7c, 0x9b, 0xe6, 0x9a,
0x70, 0x8f, 0x90, 0x20, 0xa2, 0xbb, 0xbe, 0xa4, 0xef, 0x46, 0xba, 0x87,
0x96, 0xfd, 0xfd, 0x93, 0xee, 0xf5, 0x9f, 0xc9, 0x89, 0x91, 0xaf, 0xf8,
0xa5, 0xd3, 0x00, 0xad, 0x27, 0xc3, 0x65, 0x0d, 0xe2, 0xc3, 0x62, 0x62,
0x9a, 0x31, 0x85, 0x5c, 0xa2, 0xcf, 0x18, 0x4d, 0xd9, 0x03, 0x65, 0xa3,
0x2e, 0x30, 0x2c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16,
0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x15,
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x16, 0x30, 0x0b,
0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x09, 0x48, 0xa1, 0x88, 0x7e, 0x11,
0xa4, 0x70, 0x95, 0x79, 0x4b, 0x61, 0x8f, 0x37, 0xd8, 0x21, 0xa4, 0xe0,
0x4c, 0x63, 0xe6, 0x5e, 0xc2, 0x7b, 0x90, 0x5e, 0xc0, 0x7f, 0xee, 0x72,
0x76, 0x1b, 0x02, 0x21, 0x00, 0xad, 0x2b, 0x74, 0x14, 0xc4, 0x57, 0xbc,
0xbe, 0x46, 0x6b, 0x7f, 0x25, 0x90, 0x79, 0xe0, 0x82, 0xbb, 0x69, 0x43,
0x0b, 0x99, 0xbd, 0x75, 0xd3, 0x4d, 0x8c, 0x8d, 0x2c, 0x9e, 0x50, 0x69,
0x9e
};
DecodedCert cert;

wc_InitDecodedCert(&cert, sshEkuCert, (word32)sizeof(sshEkuCert), NULL);
ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0);
ExpectIntEQ(cert.extExtKeyUsageSet, 1);
ExpectIntEQ(cert.extExtKeyUsage, 0);
ExpectIntEQ(cert.extExtKeyUsageSsh,
EXTKEYUSE_SSH_CLIENT_AUTH | EXTKEYUSE_SSH_SERVER_AUTH);
wc_FreeDecodedCert(&cert);
#endif /* TEST_EXTKEYUSAGE_SSH */
return EXPECT_RESULT();
}

/*
* The OID sum used to identify a KeyPurposeId is a checksum and can collide.
* With the default sum, appending the arc 16256 (encoded as ff 00) to an
* 8 byte OID leaves the sum unchanged, so 1.3.6.1.5.5.7.3.22.16256 sums the
* same as id-kp-secureShellServer and 1.3.6.1.5.5.7.3.1.16256 the same as
* id-kp-serverAuth. With WOLFSSL_OLD_OID_SUM (a byte sum) swapping the last
* two arcs does the same: 1.3.6.1.5.5.7.22.3 and 1.3.6.1.5.5.7.1.3.
* Parse a self-signed P-256 cert with key purposes id-kp-secureShellClient
* plus those four colliding OIDs and check that only the byte-exact OID sets
* a bit.
*/
int test_wc_DecodeExtKeyUsage_ssh_oid_collision(void)
{
EXPECT_DECLS;
#ifdef TEST_EXTKEYUSAGE_SSH
static const unsigned char sshEkuCollideCert[] = {
0x30, 0x82, 0x01, 0xb9, 0x30, 0x82, 0x01, 0x60, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x08, 0x7f, 0x1c, 0x2e, 0x3d, 0x4a, 0x5b, 0x6c, 0x7d, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x18, 0x30, 0x16,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x73, 0x73, 0x68, 0x2d, 0x65,
0x6b, 0x75, 0x2d, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x30, 0x20,
0x17, 0x0d, 0x32, 0x36, 0x30, 0x39, 0x30, 0x33, 0x31, 0x39, 0x33, 0x37,
0x32, 0x33, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, 0x36, 0x30, 0x38, 0x31,
0x30, 0x31, 0x39, 0x33, 0x37, 0x32, 0x33, 0x5a, 0x30, 0x39, 0x31, 0x0b,
0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f,
0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x0f, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x6b, 0x75, 0x2d,
0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06,
0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x68, 0xa5,
0x0e, 0x32, 0xbe, 0x32, 0xad, 0xad, 0xe9, 0x6a, 0xdb, 0x42, 0x0a, 0x96,
0xfc, 0xaa, 0xd6, 0x5c, 0xe2, 0x40, 0x5f, 0x39, 0xfb, 0xc9, 0xce, 0x4a,
0xfe, 0xe0, 0xe8, 0xae, 0x12, 0x9b, 0x1d, 0x56, 0x0c, 0x88, 0x30, 0x7f,
0x8a, 0x7f, 0xd7, 0x94, 0x54, 0x76, 0x9f, 0x73, 0x5c, 0x0f, 0x37, 0x06,
0x66, 0xab, 0xfa, 0xf7, 0x71, 0x3a, 0x11, 0x86, 0x58, 0x3b, 0x85, 0x12,
0x5f, 0x3d, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x3f, 0x06, 0x03, 0x55, 0x1d,
0x25, 0x04, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
0x07, 0x03, 0x15, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
0x16, 0xff, 0x00, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x16,
0x03, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0xff,
0x00, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x03, 0x30,
0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x01, 0xab, 0x08, 0xf9, 0xf0,
0xe5, 0x0e, 0x47, 0x1e, 0x68, 0xb8, 0xce, 0x16, 0x94, 0x2f, 0x8f, 0xfc,
0x6c, 0x95, 0x32, 0xd0, 0x5d, 0x60, 0x54, 0x18, 0xf5, 0x84, 0x67, 0x4f,
0x0c, 0xbd, 0x93, 0x02, 0x20, 0x1c, 0x29, 0x80, 0x00, 0x6f, 0xf6, 0x19,
0x66, 0x25, 0x35, 0x81, 0x38, 0x91, 0x6e, 0xb9, 0xaa, 0x80, 0xb8, 0x7a,
0x3b, 0xab, 0x20, 0x89, 0x1d, 0x04, 0x05, 0x53, 0xa0, 0x5e, 0xf2, 0xe6,
0xa9
};
DecodedCert cert;

wc_InitDecodedCert(&cert, sshEkuCollideCert,
(word32)sizeof(sshEkuCollideCert), NULL);
ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0);
ExpectIntEQ(cert.extExtKeyUsageSet, 1);
/* 1.3.6.1.5.5.7.3.1.16256 and 1.3.6.1.5.5.7.1.3 must not be taken for
* id-kp-serverAuth. */
ExpectIntEQ(cert.extExtKeyUsage, 0);
/* 1.3.6.1.5.5.7.3.22.16256 and 1.3.6.1.5.5.7.22.3 must not be taken for
* id-kp-secureShellServer. */
ExpectIntEQ(cert.extExtKeyUsageSsh, EXTKEYUSE_SSH_CLIENT_AUTH);
wc_FreeDecodedCert(&cert);
#endif /* TEST_EXTKEYUSAGE_SSH */
return EXPECT_RESULT();
}

int test_wc_SignCert_buffer_bounds(void)
{
EXPECT_DECLS;
Expand Down
4 changes: 4 additions & 0 deletions tests/api/test_asn.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ int test_ToTraditional_ex_negative(void);
int test_ToTraditional_ex_mldsa_bad_params(void);
int test_wc_SignCert_buffer_bounds(void);
int test_wc_DecodeKeyUsage_decipherOnly(void);
int test_wc_DecodeExtKeyUsage_ssh(void);
int test_wc_DecodeExtKeyUsage_ssh_oid_collision(void);
int test_wc_AsnDecisionCoverage(void);
int test_wc_AsnFeatureCoverage(void);

Expand Down Expand Up @@ -76,6 +78,8 @@ int test_wc_AsnFeatureCoverage(void);
TEST_DECL_GROUP("asn", test_ToTraditional_ex_mldsa_bad_params), \
TEST_DECL_GROUP("asn", test_wc_SignCert_buffer_bounds), \
TEST_DECL_GROUP("asn", test_wc_DecodeKeyUsage_decipherOnly), \
TEST_DECL_GROUP("asn", test_wc_DecodeExtKeyUsage_ssh), \
TEST_DECL_GROUP("asn", test_wc_DecodeExtKeyUsage_ssh_oid_collision), \
TEST_DECL_GROUP("asn", test_wc_AsnDecisionCoverage), \
TEST_DECL_GROUP("asn", test_wc_AsnFeatureCoverage)

Expand Down
46 changes: 45 additions & 1 deletion wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -5700,6 +5700,8 @@ static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9};
{43, 6, 1, 4, 1, 130, 55, 20, 2, 2};
static const byte extExtKeyUsageSshKpClientAuthOid[] =
{43, 6, 1, 5, 2, 3, 4};
static const byte extExtKeyUsageSshServerAuthOid[] =
EXT_KEY_USAGE_OID_BASE(22);
#endif /* WOLFSSL_WOLFSSH */

#ifdef WOLFSSL_SUBJ_DIR_ATTR
Expand Down Expand Up @@ -7140,6 +7142,10 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz)
oid = extExtKeyUsageSshKpClientAuthOid;
*oidSz = sizeof(extExtKeyUsageSshKpClientAuthOid);
break;
case EKU_SSH_SERVER_AUTH_OID:
oid = extExtKeyUsageSshServerAuthOid;
*oidSz = sizeof(extExtKeyUsageSshServerAuthOid);
break;
#endif /* WOLFSSL_WOLFSSH */
default:
break;
Expand Down Expand Up @@ -21575,8 +21581,30 @@ int DecodeExtKeyUsage(const byte* input, word32 sz,
ret = 0;
}
else if (ret == 0) {
word32 oidSum;
const byte* oidData = NULL;
word32 oidSz = 0;
const byte* checkOid = NULL;
word32 checkOidSz = 0;

oidSum = dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.sum;

/* The OID sum is a checksum and can collide. Only treat the OID as
* a known KeyPurposeId when the encoded bytes match exactly, as
* GetObjectId() does with oidCertKeyUseType. Unknown OIDs must
* still be consumed and counted, so verify here rather than in
* GetASN_Items(). */
GetASN_OIDData(&dataASN[KEYPURPOSEIDASN_IDX_OID], &oidData,
&oidSz);
checkOid = OidFromId(oidSum, oidCertKeyUseType, &checkOidSz);
if ((checkOid == NULL) || (checkOidSz != oidSz) ||
(XMEMCMP(oidData, checkOid, checkOidSz) != 0)) {
WOLFSSL_MSG("\tunrecognized KeyPurposeId");
oidSum = 0;
}

/* Store the bit for the OID. */
switch (dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.sum) {
switch (oidSum) {
case EKU_ANY_OID:
*extExtKeyUsage |= EXTKEYUSE_ANY;
break;
Expand All @@ -21598,6 +21626,22 @@ int DecodeExtKeyUsage(const byte* input, word32 sz,
case EKU_OCSP_SIGN_OID:
*extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN;
break;
#ifdef WOLFSSL_WOLFSSH
case EKU_SSH_CLIENT_AUTH_OID:
*extExtKeyUsageSsh |= EXTKEYUSE_SSH_CLIENT_AUTH;
break;
case EKU_SSH_MSCL_OID:
*extExtKeyUsageSsh |= EXTKEYUSE_SSH_MSCL;
break;
case EKU_SSH_KP_CLIENT_AUTH_OID:
*extExtKeyUsageSsh |= EXTKEYUSE_SSH_KP_CLIENT_AUTH;
break;
case EKU_SSH_SERVER_AUTH_OID:
*extExtKeyUsageSsh |= EXTKEYUSE_SSH_SERVER_AUTH;
break;
#endif /* WOLFSSL_WOLFSSH */
default:
break;
}

#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
Expand Down
3 changes: 3 additions & 0 deletions wolfcrypt/src/asn_orig.c
Original file line number Diff line number Diff line change
Expand Up @@ -3986,6 +3986,9 @@ int DecodeExtKeyUsage(const byte* input, word32 sz,
case EKU_SSH_KP_CLIENT_AUTH_OID:
*extExtKeyUsageSsh |= EXTKEYUSE_SSH_KP_CLIENT_AUTH;
break;
case EKU_SSH_SERVER_AUTH_OID:
*extExtKeyUsageSsh |= EXTKEYUSE_SSH_SERVER_AUTH;
break;
#endif /* WOLFSSL_WOLFSSH */
default:
break;
Expand Down
1 change: 1 addition & 0 deletions wolfssl/wolfcrypt/asn.h
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,7 @@ enum KeyIdType {
#define EXTKEYUSE_SSH_CLIENT_AUTH 0x01
#define EXTKEYUSE_SSH_MSCL 0x02
#define EXTKEYUSE_SSH_KP_CLIENT_AUTH 0x04
#define EXTKEYUSE_SSH_SERVER_AUTH 0x08
#endif /* WOLFSSL_WOLFSSH */

#define WC_NS_SSL_CLIENT 0x80
Expand Down
8 changes: 6 additions & 2 deletions wolfssl/wolfcrypt/oid_sum.h
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,9 @@ enum ExtKeyUsage_Sum {
/* 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02 */
EKU_SSH_MSCL_OID = 264, /* 1.3.6.1.4.1.311.20.2.2 */
/* 0x2b,0x06,0x01,0x05,0x02,0x03,0x04 */
EKU_SSH_KP_CLIENT_AUTH_OID = 64 /* 1.3.6.1.5.2.3.4 */
EKU_SSH_KP_CLIENT_AUTH_OID = 64, /* 1.3.6.1.5.2.3.4 */
/* 0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x16 */
EKU_SSH_SERVER_AUTH_OID = 92 /* 1.3.6.1.5.5.7.3.22 */
#else
/* 0x55,0x1d,0x25,0x00 */
EKU_ANY_OID = 0x00da1daa, /* 2.5.29.37.0 */
Expand All @@ -1348,7 +1350,9 @@ enum ExtKeyUsage_Sum {
/* 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02 */
EKU_SSH_MSCL_OID = 0x103686d7, /* 1.3.6.1.4.1.311.20.2.2 */
/* 0x2b,0x06,0x01,0x05,0x02,0x03,0x04 */
EKU_SSH_KP_CLIENT_AUTH_OID = 0x7a050529 /* 1.3.6.1.5.2.3.4 */
EKU_SSH_KP_CLIENT_AUTH_OID = 0x7a050529, /* 1.3.6.1.5.2.3.4 */
/* 0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x16 */
EKU_SSH_SERVER_AUTH_OID = 0x1302012e /* 1.3.6.1.5.5.7.3.22 */
#endif
};

Expand Down
Loading