diff --git a/doc/dox_comments/header_files/asn.h b/doc/dox_comments/header_files/asn.h index 03bbe38c03..c3aeb50325 100644 --- a/doc/dox_comments/header_files/asn.h +++ b/doc/dox_comments/header_files/asn.h @@ -80,11 +80,16 @@ void FreeAltNames(DNS_entry* altNames, void* heap); \note This API is not public by default. Define WOLFSSL_PUBLIC_ASN to expose APIs marked WOLFSSL_ASN_API. + \note The oid argument passed to the callback is an array of word32 + elements, one per OID arc, so that arcs > 65535 are represented without + truncation. Callbacks must declare their oid parameter as const word32*. + The same applies to wc_SetUnknownExtCallback. + _Example_ \code DecodedCert cert; - int UnknownExtCallback(const byte* oid, word32 oidSz, int crit, + int UnknownExtCallback(const word32* oid, word32 oidSz, int crit, const byte* der, word32 derSz, void* ctx) { // handle unknown extension return 0; @@ -140,16 +145,19 @@ int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap, /*! \ingroup ASN - \brief This function encodes an array of word16 values into an ASN.1 + \brief This function encodes an array of word32 values into an ASN.1 Object Identifier (OID) in DER format. OIDs are used to identify algorithms, extensions, and other objects in certificates and cryptographic protocols. + Each OID arc is a word32, so OIDs containing arcs with values > 65535 are + represented without truncation. + \return 0 On success. \return BAD_FUNC_ARG If in, inSz, or outSz are invalid. \return BUFFER_E If out is not NULL and outSz is too small. - \param in pointer to array of word16 values representing OID components + \param in pointer to array of word32 values representing OID components \param inSz number of components in the OID \param out pointer to buffer to store encoded OID (can be NULL to calculate size) @@ -157,11 +165,11 @@ int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap, _Example_ \code - word16 oid[] = {1, 2, 840, 113549, 1, 1, 11}; // sha256WithRSAEncryption + word32 oid[] = {1, 2, 840, 113549, 1, 1, 11}; // sha256WithRSAEncryption byte encoded[32]; word32 encodedSz = sizeof(encoded); - int ret = wc_EncodeObjectId(oid, sizeof(oid)/sizeof(word16), + int ret = wc_EncodeObjectId(oid, sizeof(oid)/sizeof(*oid), encoded, &encodedSz); if (ret == 0) { // encoded contains DER encoded OID @@ -170,7 +178,7 @@ int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap, \sa wc_BerToDer */ -int wc_EncodeObjectId(const word16* in, word32 inSz, byte* out, +int wc_EncodeObjectId(const word32* in, word32 inSz, byte* out, word32* outSz); /*! diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index bd06ae8e0f..b8d30317d0 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -3953,7 +3953,7 @@ int wc_SetCustomExtension(Cert *cert, int critical, const char *oid, \code int ret = 0; // Unknown extension callback prototype - int myUnknownExtCallback(const word16* oid, word32 oidSz, int crit, + int myUnknownExtCallback(const word32* oid, word32 oidSz, int crit, const unsigned char* der, word32 derSz); // Register it @@ -3967,7 +3967,7 @@ int wc_SetCustomExtension(Cert *cert, int critical, const char *oid, // crit: Whether the extension was mark critical. // der: The der encoding of the content of the extension. // derSz: The size in bytes of the der encoding. - int myCustomExtCallback(const word16* oid, word32 oidSz, int crit, + int myCustomExtCallback(const word32* oid, word32 oidSz, int crit, const unsigned char* der, word32 derSz) { // Logic to parse extension goes here. diff --git a/tests/api/test_asn.c b/tests/api/test_asn.c index 63cbfd365d..8f7b648e5c 100644 --- a/tests/api/test_asn.c +++ b/tests/api/test_asn.c @@ -1624,36 +1624,49 @@ int test_SerialNumber0_RootCA(void) return EXPECT_RESULT(); } -int test_wc_DecodeObjectId(void) + +int test_wc_DecodeObjectId_FIPS16(void) { EXPECT_DECLS; #if !defined(NO_ASN) && \ (defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT)) { - /* OID 1.2.840.113549.1.1.11 (sha256WithRSAEncryption) - * DER encoding: 2a 86 48 86 f7 0d 01 01 0b - * First byte 0x2a = 42 => arc0 = 42/40 = 1, arc1 = 42%40 = 2 - * Remaining arcs: 840, 113549, 1, 1, 11 + word32 i; + static const word16 oid_dot_2[] = { + 2, 100, 4, 6 + }; + + static const byte oid_start_with_2[] = { + 0x81, 0x34, 0x04, 0x06 + }; + + + /* OID 1.3.132.0.6 (secp112r1) + * DER encoding: 2b 81 04 00 06 + * First byte 0x2b = 43 => arc0 = 43/40 = 1, arc1 = 43%40 = 3 + * Remaining arcs: 132 0 6 */ static const byte oid_sha256rsa[] = { - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b + 0x2B, 0x81, 0x04, 0x00, 0x06 + }; + + static const word16 oid_dot_form[] = { + 1U, 3U, 132U, 0U, 6U }; + word16 out[MAX_OID_SZ]; word32 outSz; + word32 trueOutSz = sizeof(oid_dot_form) / sizeof(*oid_dot_form); /* Test 1: Normal decode */ outSz = MAX_OID_SZ; ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa), out, &outSz), 0); - ExpectIntEQ((int)outSz, 7); - ExpectIntEQ(out[0], 1); - ExpectIntEQ(out[1], 2); - ExpectIntEQ(out[2], 840); - ExpectIntEQ(out[3], (word16)113549); /* truncated to word16 */ - ExpectIntEQ(out[4], 1); - ExpectIntEQ(out[5], 1); - ExpectIntEQ(out[6], 11); + ExpectIntEQ((int)outSz, trueOutSz); + for (i = 0; i < ((outSz <= trueOutSz) ? outSz : trueOutSz); i++) { + ExpectIntEQ(out[i], oid_dot_form[i]); + } /* Test 2: NULL args */ outSz = MAX_OID_SZ; @@ -1692,12 +1705,251 @@ int test_wc_DecodeObjectId(void) ExpectIntEQ(DecodeObjectId(oid_sha256rsa, sizeof(oid_sha256rsa), out, &outSz), WC_NO_ERR_TRACE(BUFFER_E)); + + /* Test 7: first Arc is 2 */ + { + word32 trueOutSz2 = sizeof(oid_dot_2) / sizeof(*oid_dot_2); + outSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId(oid_start_with_2, + sizeof(oid_start_with_2), + out, &outSz), 0); + ExpectIntEQ((int)outSz, trueOutSz2); + for (i = 0; i < ((outSz <= trueOutSz2) ? + outSz : trueOutSz2); i++) { + ExpectIntEQ(out[i], oid_dot_2[i]); + } + } + + /* Test 8: an OID with an arc that exceeds word16. Tests that wrong + * but unchangeable behavior is working correctly, + * + * word16 version is used in FIPS build + */ + { + static const byte oid_large_arc[] = { + 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x0d, 0x01, 0x01, 0x0b + }; + static const word16 oid_dot_large_arc[] = { + 1U, 2U, 840U, (word16)113549U, 1U, 1U, 11U + }; + word32 trueOutSz3 = sizeof(oid_dot_large_arc) / sizeof(word16); + + outSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId(oid_large_arc, sizeof(oid_large_arc), + out, &outSz), 0); + ExpectIntEQ((int)outSz, (int)trueOutSz3); + for (i = 0; i < ((outSz <= trueOutSz3) ? outSz : trueOutSz3); i++) { + ExpectIntEQ(out[i], oid_dot_large_arc[i]); + } + #undef LARGE_ARC_EXPECTED + } } #endif /* !NO_ASN && (HAVE_OID_DECODING || WOLFSSL_ASN_PRINT) */ return EXPECT_RESULT(); } +/* Test for word16 FIPS version of function */ +int test_wc_DecodeObjectId_ex(void) +{ + EXPECT_DECLS; + +#if !defined(NO_ASN) && \ + (defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT)) + { + word32 i; + static const word32 oid_dot_2[] = { + 2, 100, 4, 6 + }; + + static const byte oid_start_with_2[] = { + 0x81, 0x34, 0x04, 0x06 + }; + + + /* OID 1.3.132.0.6 (secp112r1) + * DER encoding: 2b 81 04 00 06 + * First byte 0x2b = 43 => arc0 = 43/40 = 1, arc1 = 43%40 = 3 + * Remaining arcs: 132 0 6 + */ + static const byte oid_sha256rsa[] = { + 0x2B, 0x81, 0x04, 0x00, 0x06 + }; + + static const word32 oid_dot_form[] = { + 1U, 3U, 132U, 0U, 6U + }; + + word32 out[MAX_OID_SZ]; + word32 outSz; + + word32 trueOutSz = sizeof(oid_dot_form) / sizeof(word32); + /* Test 1: Normal decode */ + outSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId_ex(oid_sha256rsa, sizeof(oid_sha256rsa), + out, &outSz), 0); + ExpectIntEQ((int)outSz, trueOutSz); + for (i = 0; i < ((outSz <= trueOutSz) ? outSz : trueOutSz); i++) { + ExpectIntEQ(out[i], oid_dot_form[i]); + } + + /* Test 2: NULL args */ + outSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId_ex(NULL, sizeof(oid_sha256rsa), out, &outSz), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(DecodeObjectId_ex(oid_sha256rsa, sizeof(oid_sha256rsa), + out, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Test 3 (Bug 1): outSz=1 must return BUFFER_E, not OOB write. + * The first OID byte decodes into two arcs, so outSz must be >= 2. */ + outSz = 1; + ExpectIntEQ(DecodeObjectId_ex(oid_sha256rsa, sizeof(oid_sha256rsa), + out, &outSz), + WC_NO_ERR_TRACE(BUFFER_E)); + + /* Test 4: outSz=0 must also return BUFFER_E */ + outSz = 0; + ExpectIntEQ(DecodeObjectId_ex(oid_sha256rsa, sizeof(oid_sha256rsa), + out, &outSz), + WC_NO_ERR_TRACE(BUFFER_E)); + + /* Test 5: outSz=2 is enough for a single-byte OID (two arcs) */ + { + static const byte oid_one_byte[] = { 0x2a }; /* 1.2 */ + outSz = 2; + ExpectIntEQ(DecodeObjectId_ex(oid_one_byte, sizeof(oid_one_byte), + out, &outSz), 0); + ExpectIntEQ((int)outSz, 2); + ExpectIntEQ(out[0], 1); + ExpectIntEQ(out[1], 2); + } + + /* Test 6: Buffer too small for later arcs */ + outSz = 3; /* only room for 3 arcs, but OID has 7 */ + ExpectIntEQ(DecodeObjectId_ex(oid_sha256rsa, sizeof(oid_sha256rsa), + out, &outSz), + WC_NO_ERR_TRACE(BUFFER_E)); + + /* Test 7: first Arc is 2 */ + { + word32 trueOutSz2 = sizeof(oid_dot_2) / sizeof(word32); + outSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId_ex(oid_start_with_2, + sizeof(oid_start_with_2), + out, &outSz), 0); + ExpectIntEQ((int)outSz, trueOutSz2); + for (i = 0; i < ((outSz <= trueOutSz2) ? + outSz : trueOutSz2); i++) { + ExpectIntEQ(out[i], oid_dot_2[i]); + } + } + + /* Test 8: an OID with an arc that exceeds word16. + */ + { + static const byte oid_large_arc[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b + }; + static const word32 oid_dot_large_arc[] = { + 1U, 2U, 840U, 113549U, 1U, 1U, 11U + }; + word32 trueOutSz3 = sizeof(oid_dot_large_arc) / sizeof(word32); + + outSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId_ex(oid_large_arc, sizeof(oid_large_arc), + out, &outSz), 0); + ExpectIntEQ((int)outSz, (int)trueOutSz3); + for (i = 0; i < ((outSz <= trueOutSz3) ? outSz : trueOutSz3); i++) { + ExpectIntEQ(out[i], oid_dot_large_arc[i]); + } + #undef LARGE_ARC_EXPECTED + } + } +#endif /* !NO_ASN && (HAVE_OID_DECODING || WOLFSSL_ASN_PRINT) */ + + return EXPECT_RESULT(); +} + +int test_wc_EncodeObjectId(void) +{ + EXPECT_DECLS; +#if defined(HAVE_OID_ENCODING) && !defined(NO_ASN) + { + /* 1.3.132.0.6 (secp112r1) -- every arc fits in word16, so this + * encodes identically in both build configs. */ + static const word32 oid_small[] = { 1U, 3U, 132U, 0U, 6U }; + static const byte oid_small_der[] = { + 0x2b, 0x81, 0x04, 0x00, 0x06 + }; + const word32 oid_small_cnt = sizeof(oid_small) / sizeof(word32); + byte out[MAX_OID_SZ]; + word32 outSz; + word32 i; + + /* Test 1: length-only query (out == NULL) */ + outSz = 0; + ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, NULL, &outSz), + 0); + ExpectIntEQ((int)outSz, (int)sizeof(oid_small_der)); + + /* Test 2: normal encode matches expected DER */ + outSz = sizeof(out); + ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, out, &outSz), 0); + ExpectIntEQ((int)outSz, (int)sizeof(oid_small_der)); + for (i = 0; i < outSz && i < sizeof(oid_small_der); i++) { + ExpectIntEQ(out[i], oid_small_der[i]); + } + + /* Test 3: NULL args */ + outSz = sizeof(out); + ExpectIntEQ(wc_EncodeObjectId(NULL, oid_small_cnt, out, &outSz), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, out, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Test 4: output buffer too small */ + outSz = 1; + ExpectIntEQ(wc_EncodeObjectId(oid_small, oid_small_cnt, out, &outSz), + WC_NO_ERR_TRACE(BUFFER_E)); + + /* Test 5 ): an arc > word16 can only be represented in the + */ + { + static const word32 oid_large[] = { + 1U, 2U, 840U, 113549U, 1U, 1U, 11U + }; + static const byte oid_large_der[] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b + }; + const word32 oid_large_cnt = sizeof(oid_large) / sizeof(word32); + + outSz = sizeof(out); + ExpectIntEQ(wc_EncodeObjectId(oid_large, oid_large_cnt, out, &outSz), + 0); + ExpectIntEQ((int)outSz, (int)sizeof(oid_large_der)); + for (i = 0; i < outSz && i < sizeof(oid_large_der); i++) { + ExpectIntEQ(out[i], oid_large_der[i]); + } + +#if defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT) + { + word32 dec[MAX_OID_SZ]; + word32 decSz = MAX_OID_SZ; + ExpectIntEQ(DecodeObjectId_ex(out, outSz, dec, &decSz), 0); + ExpectIntEQ((int)decSz, (int)oid_large_cnt); + for (i = 0; i < decSz && i < oid_large_cnt; i++) { + ExpectIntEQ(dec[i], oid_large[i]); + } + } +#endif /* HAVE_OID_DECODING || WOLFSSL_ASN_PRINT */ + } + } +#endif /* HAVE_OID_ENCODING && !NO_ASN */ + + return EXPECT_RESULT(); +} + #if defined(HAVE_PKCS8) && !defined(NO_ASN) && \ (defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_PUBLIC_ASN)) && \ diff --git a/tests/api/test_asn.h b/tests/api/test_asn.h index a0c72b2517..bda721f5e4 100644 --- a/tests/api/test_asn.h +++ b/tests/api/test_asn.h @@ -36,7 +36,9 @@ int test_wc_DecodeRsaPssParams(void); int test_SerialNumber0_RootCA(void); int test_DecodeAltNames_length_underflow(void); int test_ParseCert_SM3wSM2_short_pubkey(void); -int test_wc_DecodeObjectId(void); +int test_wc_DecodeObjectId_ex(void); +int test_wc_DecodeObjectId_FIPS16(void); +int test_wc_EncodeObjectId(void); int test_ToTraditional_ex_handcrafted(void); int test_ToTraditional_ex_roundtrip(void); int test_ToTraditional_ex_negative(void); @@ -55,7 +57,9 @@ int test_ToTraditional_ex_mldsa_bad_params(void); TEST_DECL_GROUP("asn", test_SerialNumber0_RootCA), \ TEST_DECL_GROUP("asn", test_DecodeAltNames_length_underflow), \ TEST_DECL_GROUP("asn", test_ParseCert_SM3wSM2_short_pubkey), \ - TEST_DECL_GROUP("asn", test_wc_DecodeObjectId), \ + TEST_DECL_GROUP("asn", test_wc_DecodeObjectId_ex), \ + TEST_DECL_GROUP("asn", test_wc_EncodeObjectId), \ + TEST_DECL_GROUP("asn", test_wc_DecodeObjectId_FIPS16), \ TEST_DECL_GROUP("asn", test_ToTraditional_ex_handcrafted), \ TEST_DECL_GROUP("asn", test_ToTraditional_ex_roundtrip), \ TEST_DECL_GROUP("asn", test_ToTraditional_ex_negative), \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e84d252931..7b8ee7678e 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -7164,12 +7164,106 @@ static int CheckCurve(word32 oid) * @return BAD_FUNC_ARG when in or outSz is NULL. * @return BUFFER_E when buffer too small. */ -int wc_EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz) +int wc_EncodeObjectId(const word32* in, word32 inSz, + byte* out, word32* outSz) { - return EncodeObjectId(in, inSz, out, outSz); + return EncodeObjectId_ex(in, inSz, out, outSz); +} + +int EncodeObjectId_ex(const word32* in, word32 inSz, + byte* out, word32* outSz) +{ + int i, x, len; + word32 d, t; + + /* check args */ + if (in == NULL || outSz == NULL || inSz <= 0) { + return BAD_FUNC_ARG; + } + + /* compute length of encoded OID */ + d = ((word32)in[0] * 40) + in[1]; + len = 0; + for (i = 1; i < (int)inSz; i++) { + x = 0; + t = d; + while (t) { + x++; + t >>= 1; + } + len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0); + + if (i < (int)inSz - 1) { + d = in[i + 1]; + } + } + + if (out) { + /* verify length */ + if ((int)*outSz < len) { + return BUFFER_E; /* buffer provided is not large enough */ + } + + /* calc first byte */ + d = ((word32)in[0] * 40) + in[1]; + + /* encode bytes */ + x = 0; + for (i = 1; i < (int)inSz; i++) { + if (d) { + int y = x, z; + byte mask = 0; + while (d) { + out[x++] = (byte)((d & 0x7F) | mask); + d >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + mask = out[y]; + out[y] = out[z]; + out[z] = mask; + ++y; + --z; + } + } + else { + out[x++] = 0x00; /* zero value */ + } + + /* next word */ + if (i < (int)inSz - 1) { + d = in[i + 1]; + } + } + } + + /* return length */ + *outSz = (word32)len; + + return 0; } -int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz) +/* Encode dotted form of OID into byte array version. + * + * Uses word16 for OIDs and can cause OIDs to be truncated. + * Do not use this for new code unless necessary. (use wc_EncodeObjectId + * or EncodeObjectId_ex) + * We cannot change this function because FIPS code expects + * this signature. + * + * @param [in] in Dotted form of OID. + * @param [in] inSz Count of numbers in dotted form. + * @param [in] out Buffer to hold OID. + * @param [in, out] outSz On in, size of buffer. + * On out, number of bytes in buffer. + * @return 0 on success + * @return BAD_FUNC_ARG when in or outSz is NULL. + * @return BUFFER_E when buffer too small. + */ +int EncodeObjectId(const word16* in, word32 inSz, + byte* out, word32* outSz) { int i, x, len; word32 d, t; @@ -7256,7 +7350,8 @@ int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz) * @return BAD_FUNC_ARG when in or outSz is NULL. * @return BUFFER_E when dotted form buffer too small. */ -int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) +int DecodeObjectId(const byte* in, word32 inSz, + word16* out, word32* outSz) { int x = 0, y = 0; word32 t = 0; @@ -7278,8 +7373,14 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) if ((int)*outSz < 2) { return BUFFER_E; } - out[0] = (word16)(t / 40); - out[1] = (word16)(t % 40); + if (t < 80) { + out[0] = (word16)(t / 40); + out[1] = (word16)(t % 40); + } + else { + out[0] = 2; + out[1] = (word16)(t - 80); + } y = 2; } else { @@ -7299,6 +7400,71 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) return 0; } + +/* Encode dotted form of OID into word32 array version. + * + * Same as DecodeObjectId() but outputs to a word32 array so that OID + * arc values larger than a word16 are not truncated. + * + * @param [in] in Byte array containing OID. + * @param [in] inSz Size of OID in bytes. + * @param [in] out Array to hold dotted form of OID. + * @param [in, out] outSz On in, number of elements in array. + * On out, count of numbers in dotted form. + * @return 0 on success + * @return BAD_FUNC_ARG when in or outSz is NULL. + * @return BUFFER_E when dotted form buffer too small. + */ +int DecodeObjectId_ex(const byte* in, word32 inSz, + word32* out, word32* outSz) +{ + int x = 0, y = 0; + word32 t = 0; + int cnt = 0; + + /* check args */ + if (in == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* decode bytes */ + while (inSz--) { + if (cnt == 4) + return ASN_OBJECT_ID_E; + t = (t << 7) | (in[x] & 0x7F); + cnt++; + if (!(in[x] & 0x80)) { + if (y == 0) { + if ((int)*outSz < 2) { + return BUFFER_E; + } + if (t < 80) { + out[0] = t / 40; + out[1] = t % 40; + } + else { + out[0] = 2; + out[1] = t - 80; + } + y = 2; + } + else { + if (y >= (int)*outSz) { + return BUFFER_E; + } + out[y++] = t; + } + t = 0; /* reset tmp */ + cnt = 0; + } + x++; + } + + /* return length */ + *outSz = (word32)y; + + return 0; +} #endif /* HAVE_OID_DECODING || WOLFSSL_ASN_PRINT */ /* Decode the header of a BER/DER encoded OBJECT ID. @@ -7381,10 +7547,10 @@ static int DumpOID(const byte* oidData, word32 oidSz, word32 oid, #ifdef HAVE_OID_DECODING { - word16 decOid[MAX_OID_SZ]; + word32 decOid[MAX_OID_SZ]; word32 decOidSz = MAX_OID_SZ; /* Decode the OID into dotted form. */ - ret = DecodeObjectId(oidData, oidSz, decOid, &decOidSz); + ret = DecodeObjectId_ex(oidData, oidSz, decOid, &decOidSz); if (ret == 0) { printf(" Decoded (Sz %d): ", decOidSz); for (i=0; idp == NULL) { return BAD_FUNC_ARG; } #ifdef HAVE_OID_ENCODING + /* ecc_oid_t cannot be changed due to it being in the FIPS boundary so we + * have a work around of upsizing its representation*/ + /* Get the size of the encoded OID without having an encoded output */ ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz); if (ret != 0) { return ret; @@ -14335,7 +14503,7 @@ static int GenerateDNSEntryRIDString(DNS_entry* entry, void* heap) int tmpSize = MAX_OID_SZ; word32 oid = 0; word32 idx = 0; - word16 tmpName[MAX_OID_SZ]; + word32 tmpName[MAX_OID_SZ]; char oidName[MAX_OID_SZ]; char* finalName = NULL; @@ -14361,7 +14529,7 @@ static int GenerateDNSEntryRIDString(DNS_entry* entry, void* heap) #endif { /* Decode OBJECT_ID into dotted form array. */ - ret = DecodeObjectId((const byte*)(entry->name),(word32)entry->len, + ret = DecodeObjectId_ex((const byte*)(entry->name),(word32)entry->len, tmpName, (word32*)&tmpSize); if (ret == 0) { @@ -14374,11 +14542,11 @@ static int GenerateDNSEntryRIDString(DNS_entry* entry, void* heap) if (i < tmpSize - 1) { ret = XSNPRINTF(oidName + j, (word32)(MAX_OID_SZ - j), - "%d.", tmpName[i]); + "%u.", tmpName[i]); } else { ret = XSNPRINTF(oidName + j, (word32)(MAX_OID_SZ - j), - "%d", tmpName[i]); + "%u", tmpName[i]); } if (ret >= 0) { @@ -21407,9 +21575,9 @@ static int DecodeCertExtensions(DecodedCert* cert) #ifdef WC_ASN_UNKNOWN_EXT_CB if (isUnknownExt && (cert->unknownExtCallback != NULL || cert->unknownExtCallbackEx != NULL)) { - word16 decOid[MAX_OID_SZ]; + word32 decOid[MAX_OID_SZ]; word32 decOidSz = MAX_OID_SZ; - ret = DecodeObjectId( + ret = DecodeObjectId_ex( dataASN[CERTEXTASN_IDX_OID].data.oid.data, dataASN[CERTEXTASN_IDX_OID].data.oid.length, decOid, &decOidSz); @@ -37632,64 +37800,6 @@ int wc_Asn1_SetOidToNameCb(Asn1* asn1, Asn1OidToNameCb nameCb) return ret; } -/* Encode dotted form of OID into byte array version. - * - * @param [in] in Byte array containing OID. - * @param [in] inSz Size of OID in bytes. - * @param [in] out Array to hold dotted form of OID. - * @param [in, out] outSz On in, number of elements in array. - * On out, count of numbers in dotted form. - * @return 0 on success - * @return BAD_FUNC_ARG when in or outSz is NULL. - * @return BUFFER_E when dotted form buffer too small. - */ -static int EncodedDottedForm(const byte* in, word32 inSz, word32* out, - word32* outSz) -{ - int x = 0, y = 0; - word32 t = 0; - - /* check args */ - if (in == NULL || outSz == NULL) { - return BAD_FUNC_ARG; - } - - if (*outSz < 2) { - return BUFFER_E; - } - - /* decode bytes */ - while (inSz--) { - t = (t << 7) | (in[x] & 0x7F); - if (!(in[x] & 0x80)) { - if (y >= (int)*outSz) { - return BUFFER_E; - } - if (y == 0) { - /* Special case for when first arc is 2 */ - if (t < 80) { - out[0] = t / 40; - out[1] = t % 40; - } - else { - out[0] = 2; - out[1] = t - 80; - } - y = 2; - } - else { - out[y++] = t; - } - t = 0; /* reset tmp */ - } - x++; - } - - /* return length */ - *outSz = (word32)y; - - return 0; -} /* Print OID in dotted form or as hex bytes. * * @param [in] file File pointer to write to. @@ -37703,7 +37813,7 @@ static void PrintObjectIdNum(XFILE file, unsigned char* oid, word32 len) word32 i; /* Decode OBJECT_ID into dotted form array. */ - if (EncodedDottedForm(oid, len, dotted_nums, &num) == 0) { + if (DecodeObjectId_ex(oid, len, dotted_nums, &num) == 0) { /* Print out each number of dotted form. */ for (i = 0; i < num; i++) { XFPRINTF(file, "%d", dotted_nums[i]); diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index 5a3b3cf5fe..d34dade36f 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -1383,7 +1383,7 @@ static int Pkcs11EccSetParams(ecc_key* key, CK_ATTRIBUTE* tmpl, int idx) unsigned char* derParams = tmpl[idx].pValue; #if defined(HAVE_OID_ENCODING) word32 oidSz = ECC_MAX_OID_LEN - 2; - ret = wc_EncodeObjectId(key->dp->oid, key->dp->oidSz, derParams+2, &oidSz); + ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, derParams+2, &oidSz); if (ret != 0) { return ret; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 8c82294d12..45e363420c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1756,13 +1756,12 @@ typedef struct WOLFSSL_AIA_ENTRY { word32 uriSz; /* Length of URI data. */ } WOLFSSL_AIA_ENTRY; #endif /* WOLFSSL_AIA_ENTRY_DEFINED */ - #ifdef WC_ASN_UNKNOWN_EXT_CB -typedef int (*wc_UnknownExtCallback)(const word16* oid, word32 oidSz, int crit, - const unsigned char* der, word32 derSz); -typedef int (*wc_UnknownExtCallbackEx)(const word16* oid, word32 oidSz, - int crit, const unsigned char* der, - word32 derSz, void *ctx); + typedef int (*wc_UnknownExtCallback)(const word32* oid, word32 oidSz, int crit, + const unsigned char* der, word32 derSz); + typedef int (*wc_UnknownExtCallbackEx)(const word32* oid, word32 oidSz, + int crit, const unsigned char* der, + word32 derSz, void *ctx); #endif struct DecodedCert { @@ -2356,6 +2355,7 @@ typedef enum MimeStatus #if defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT) || \ defined(OPENSSL_ALL) #define DecodeObjectId wc_DecodeObjectId + #define DecodeObjectId_ex wc_DecodeObjectId_ex #endif #if defined(WOLFSSL_AKID_NAME) && !defined(GetCAByAKID) /* GetCAByAKID() has two implementations, a full implementation in @@ -2593,15 +2593,21 @@ WOLFSSL_ASN_API int GetASNInt(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL word32 wc_oid_sum(const byte* input, int length); #ifdef HAVE_OID_ENCODING - WOLFSSL_API int wc_EncodeObjectId(const word16* in, word32 inSz, + WOLFSSL_API int wc_EncodeObjectId(const word32* in, word32 inSz, + byte* out, word32* outSz); + WOLFSSL_LOCAL int EncodeObjectId_ex(const word32* in, word32 inSz, byte* out, word32* outSz); + /* Unchangeable due to being called from FIPS code expecting word16 in */ WOLFSSL_LOCAL int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz); #endif #if defined(HAVE_OID_DECODING) || defined(WOLFSSL_ASN_PRINT) || \ defined(OPENSSL_ALL) + /* Unchangeable due to being called from FIPS code expecting word16 out */ WOLFSSL_TEST_VIS int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz); + WOLFSSL_TEST_VIS int DecodeObjectId_ex(const byte* in, word32 inSz, + word32* out, word32* outSz); #endif WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, word32 maxIdx);