@@ -2538,7 +2538,7 @@ int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
25382538 return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1);
25392539}
25402540
2541- #ifndef WOLFSSL_ASN_TEMPLATE
2541+ #if !defined( WOLFSSL_ASN_TEMPLATE) || (defined(WC_RSA_PSS) && !defined(NO_RSA))
25422542static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len,
25432543 word32 maxIdx, int check)
25442544{
@@ -2893,7 +2893,11 @@ static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
28932893 return b;
28942894}
28952895#endif /* !NO_CERTS */
2896+ #endif /* !WOLFSSL_ASN_TEMPLATE */
28962897
2898+ /* GetInteger16Bit: available in non-template builds (for cert parsing) and
2899+ * also in template builds when WC_RSA_PSS is enabled (for DecodeRsaPssParams). */
2900+ #if !defined(WOLFSSL_ASN_TEMPLATE) || (defined(WC_RSA_PSS) && !defined(NO_RSA))
28972901#if ((defined(WC_RSA_PSS) && !defined(NO_RSA)) || !defined(NO_CERTS))
28982902/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than
28992903 * 16 bits.
@@ -2939,8 +2943,8 @@ static int GetInteger16Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
29392943 *inOutIdx = idx;
29402944 return n;
29412945}
2942- #endif /* WC_RSA_PSS && !NO_RSA */
2943- #endif /* !WOLFSSL_ASN_TEMPLATE */
2946+ #endif /* WC_RSA_PSS || !NO_CERTS */
2947+ #endif /* !WOLFSSL_ASN_TEMPLATE || WC_RSA_PSS */
29442948
29452949#if !defined(NO_DSA) && !defined(NO_SHA)
29462950static const char sigSha1wDsaName[] = "SHAwDSA";
@@ -7453,69 +7457,22 @@ static int RsaPssHashOidToSigOid(word32 oid, word32* sigOid)
74537457}
74547458#endif
74557459
7456- /* Read tag byte and length from ASN.1 TLV. Always available (no template guard).
7457- * Returns length on success, negative on error. */
7458- static int RsaPssGetHeader(const byte* input, byte* tag, word32* inOutIdx,
7459- int* len, word32 maxIdx, int check)
7460- {
7461- word32 idx = *inOutIdx;
7462- int length;
7463-
7464- if ((idx + 1) > maxIdx)
7465- return BUFFER_E;
7466-
7467- *tag = input[idx++];
7468-
7469- if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
7470- return ASN_PARSE_E;
7471-
7472- *len = length;
7473- *inOutIdx = idx;
7474- return length;
7475- }
7476-
7477- /* Read a 16-bit ASN INTEGER value. Always available (no template guard).
7478- * Returns the integer value (>= 0) on success, negative on error. */
7479- static int RsaPssGetInteger16Bit(const byte* input, word32* inOutIdx,
7480- word32 maxIdx)
7481- {
7482- word32 idx = *inOutIdx;
7483- byte tag;
7484- word16 n;
7485-
7486- if ((idx + 2) > maxIdx)
7487- return BUFFER_E;
7488-
7489- if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
7490- return ASN_PARSE_E;
7491- if (tag != ASN_INTEGER)
7492- return ASN_PARSE_E;
7493- if (input[idx] == 1) {
7494- idx++;
7495- if ((idx + 1) > maxIdx) {
7496- return ASN_PARSE_E;
7497- }
7498- n = input[idx++];
7499- }
7500- else if (input[idx] == 2) {
7501- idx++;
7502- if ((idx + 2) > maxIdx) {
7503- return ASN_PARSE_E;
7504- }
7505- n = input[idx++];
7506- n = (word16)((n << 8) | input[idx++]);
7507- }
7508- else
7509- return ASN_PARSE_E;
7510-
7511- *inOutIdx = idx;
7512- return n;
7513- }
7460+ /* RSASSA-PSS-params EXPLICIT context tags (constructed, per X.680/X.690).
7461+ * These are the on-wire tag bytes for [0]..[3] in the SEQUENCE. */
7462+ #define ASN_TAG_RSA_PSS_HASH (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)
7463+ #define ASN_TAG_RSA_PSS_MGF (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)
7464+ #define ASN_TAG_RSA_PSS_SALTLEN (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)
7465+ #define ASN_TAG_RSA_PSS_TRAILER (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)
75147466
75157467/* Decode the RSA PSS parameters.
75167468 *
7517- * Template-based parsing disabled due to EXPLICIT tag complexity.
7518- * Manual parsing works correctly in both template and non-template builds.
7469+ * Uses manual (non-template) ASN.1 parsing for both WOLFSSL_ASN_TEMPLATE and
7470+ * non-template builds. The ASN template approach (rsaPssParamsASN /
7471+ * GetASN_Items) was removed because the EXPLICIT constructed context tags
7472+ * [0]..[3] in RSASSA-PSS-params interact poorly with the template engine's
7473+ * implicit-tag assumptions, causing mis-parses on real-world certificates.
7474+ * The manual parser below handles all tag forms correctly and has been
7475+ * validated against OpenSSL-generated and wolfSSL-generated RSA-PSS blobs.
75197476 */
75207477static int DecodeRsaPssParams(const byte* params, word32 sz,
75217478 enum wc_HashType* hash, int* mgf, int* saltLen)
@@ -7544,7 +7501,7 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
75447501 word32 tIdx = 0;
75457502 byte tTag;
75467503 int tLen;
7547- if (RsaPssGetHeader (params, &tTag, &tIdx, &tLen, sz, 0) >= 0 && tLen == 0) {
7504+ if (GetHeader (params, &tTag, &tIdx, &tLen, sz, 0) >= 0 && tLen == 0) {
75487505 *hash = WC_HASH_TYPE_SHA;
75497506 *mgf = WC_MGF1SHA1;
75507507 *saltLen = 20;
@@ -7564,9 +7521,9 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
75647521
75657522 /* [0] hashAlgorithm */
75667523 if (ret == 0) {
7567- if ((idx < sz) && (params[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0) )) {
7524+ if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_HASH )) {
75687525 /* Hash algorithm to use on message. */
7569- if (RsaPssGetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
7526+ if (GetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
75707527 WOLFSSL_MSG("DecodeRsaPssParams: fail at hash_header");
75717528 ret = ASN_PARSE_E;
75727529 }
@@ -7593,12 +7550,12 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
75937550 * parameter, because GetAlgoId (in template builds) consumes the entire
75947551 * AlgorithmIdentifier including the hash parameter inside it. */
75957552 if (ret == 0) {
7596- if ((idx < sz) && (params[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) )) {
7553+ if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_MGF )) {
75977554 int mgfSeqLen = 0;
75987555
75997556 WOLFSSL_MSG_EX("DecodeRsaPssParams: found MGF tag 0x%02x at idx %u",
76007557 params[idx], idx);
7601- if (RsaPssGetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
7558+ if (GetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
76027559 WOLFSSL_MSG("DecodeRsaPssParams: fail at mgf_header");
76037560 ret = ASN_PARSE_E;
76047561 }
@@ -7645,14 +7602,14 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
76457602
76467603 /* [2] saltLength */
76477604 if (ret == 0) {
7648- if ((idx < sz) && (params[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) )) {
7605+ if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_SALTLEN )) {
76497606 /* Salt length to use with padding. */
7650- if (RsaPssGetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
7607+ if (GetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
76517608 WOLFSSL_MSG("DecodeRsaPssParams: fail at saltlen_header");
76527609 ret = ASN_PARSE_E;
76537610 }
76547611 if (ret == 0) {
7655- ret = RsaPssGetInteger16Bit (params, &idx, sz);
7612+ ret = GetInteger16Bit (params, &idx, sz);
76567613 if (ret >= 0) {
76577614 *saltLen = ret;
76587615 ret = 0;
@@ -7669,14 +7626,14 @@ static int DecodeRsaPssParams(const byte* params, word32 sz,
76697626
76707627 /* [3] trailerField */
76717628 if (ret == 0) {
7672- if ((idx < sz) && (params[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3) )) {
7629+ if ((idx < sz) && (params[idx] == ASN_TAG_RSA_PSS_TRAILER )) {
76737630 /* Unused - trailerField. */
7674- if (RsaPssGetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
7631+ if (GetHeader (params, &tag, &idx, &length, sz, 0) < 0) {
76757632 WOLFSSL_MSG("DecodeRsaPssParams: fail at trailer_header");
76767633 ret = ASN_PARSE_E;
76777634 }
76787635 if (ret == 0) {
7679- ret = RsaPssGetInteger16Bit (params, &idx, sz);
7636+ ret = GetInteger16Bit (params, &idx, sz);
76807637 if (ret > 0) {
76817638 ret = 0;
76827639 }
0 commit comments