@@ -38978,6 +38978,82 @@ static int DecodeOcspRespExtensions(byte* source, word32* ioIndex,
3897838978#endif
3897938979}
3898038980
38981+ #ifdef WOLFSSL_ASN_TEMPLATE
38982+ /* ASN.1 template for OCSP nonce extension.
38983+ * RFC 6960, 4.4.1 - Nonce
38984+ * X.509: RFC 5280, 4.1 - Basic Certificate Fields. (Extension)
38985+ */
38986+ static const ASNItem ocspNonceExtASN[] = {
38987+ /* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
38988+ /* Extension */
38989+ /* EXT */ { 1, ASN_SEQUENCE, 1, 1, 0 },
38990+ /* extnId */
38991+ /* EXT_OID */ {2, ASN_OBJECT_ID, 0, 0, 0 },
38992+ /* critical not encoded. */
38993+ /* extnValue */
38994+ /* EXT_VAL */ {2, ASN_OCTET_STRING, 0, 1, 0 },
38995+ /* nonce */
38996+ /* EXT_NONCE */ {3, ASN_OCTET_STRING, 0, 0, 0 },
38997+ };
38998+ enum {
38999+ OCSPNONCEEXTASN_IDX_SEQ = 0,
39000+ OCSPNONCEEXTASN_IDX_EXT,
39001+ OCSPNONCEEXTASN_IDX_EXT_OID,
39002+ OCSPNONCEEXTASN_IDX_EXT_VAL,
39003+ OCSPNONCEEXTASN_IDX_EXT_NONCE,
39004+ };
39005+
39006+ /* Number of items in ASN.1 template for OCSP nonce extension. */
39007+ #define ocspNonceExtASN_Length (sizeof(ocspNonceExtASN) / sizeof(ASNItem))
39008+ #endif /* WOLFSSL_ASN_TEMPLATE */
39009+
39010+ /* Encode OCSP response extensions (currently only nonce) */
39011+ static int EncodeOcspRespExtensions(OcspResponse* resp, byte* out,
39012+ word32* outSz)
39013+ {
39014+ #ifndef WOLFSSL_ASN_TEMPLATE
39015+ (void)resp;
39016+ (void)output;
39017+ (void)size;
39018+ /* Encoding ocsp responses not supported in legacy ASN parsing */
39019+ return NOT_COMPILED_IN;
39020+ #else
39021+ DECL_ASNSETDATA(dataASN, ocspNonceExtASN_Length);
39022+ int sz = 0;
39023+ int ret = 0;
39024+
39025+ if (resp == NULL || outSz == NULL) {
39026+ return BAD_FUNC_ARG;
39027+ }
39028+
39029+ CALLOC_ASNSETDATA(dataASN, ocspNonceExtASN_Length, ret, resp->heap);
39030+
39031+ if (ret == 0) {
39032+ SetASN_OID(&dataASN[OCSPNONCEEXTASN_IDX_EXT_OID], OCSP_NONCE_OID,
39033+ oidOcspType);
39034+ SetASN_Buffer(&dataASN[OCSPNONCEEXTASN_IDX_EXT_NONCE],
39035+ resp->nonce, resp->nonceSz);
39036+ /* Calculate size of encoding. */
39037+ ret = SizeASN_Items(ocspNonceExtASN, dataASN,
39038+ ocspNonceExtASN_Length, &sz);
39039+ }
39040+ /* Check buffer big enough for encoding if supplied. */
39041+ if (ret == 0 && out != NULL && sz > (int)*outSz) {
39042+ ret = BUFFER_E;
39043+ }
39044+ if (ret == 0 && out != NULL) {
39045+ if (SetASN_Items(ocspNonceExtASN, dataASN, ocspNonceExtASN_Length,
39046+ out) != sz)
39047+ ret = ASN_PARSE_E;
39048+ }
39049+ if (ret == 0)
39050+ *outSz = sz;
39051+
39052+ FREE_ASNSETDATA(dataASN, resp->heap);
39053+ return ret;
39054+ #endif
39055+ }
39056+
3898139057#ifdef WOLFSSL_ASN_TEMPLATE
3898239058/* ASN.1 template for OCSP ResponseData.
3898339059 * RFC 6960, 4.2.1 - ASN.1 Specification of the OCSP Response
@@ -39030,6 +39106,7 @@ static int EncodeResponseData(OcspResponse* resp, byte* out, word32* outSz)
3903039106 int ret = 0;
3903139107 int sz = 0;
3903239108 word32 respListSz = 0;
39109+ word32 respExtSz = 0;
3903339110 OcspEntry* single = NULL;
3903439111
3903539112 if (resp == NULL || outSz == NULL) {
@@ -39076,14 +39153,25 @@ static int EncodeResponseData(OcspResponse* resp, byte* out, word32* outSz)
3907639153 else
3907739154 ret = BAD_FUNC_ARG;
3907839155 }
39156+ if (ret == 0) {
39157+ /* Encode responseExtensions if nonce is present */
39158+ if (resp->nonceSz > 0) {
39159+ ret = EncodeOcspRespExtensions(resp, NULL, &respExtSz);
39160+ if (ret == 0 && respExtSz > 0) {
39161+ SetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_RESPEXT],
39162+ NULL, respExtSz);
39163+ }
39164+ }
39165+ else {
39166+ SetASNItem_NoOutNode(dataASN, ocspRespDataASN,
39167+ OCSPRESPDATAASN_IDX_RESPEXT,
39168+ ocspRespDataASN_Length);
39169+ }
39170+ }
3907939171 if (ret == 0) {
3908039172 SetASN_Int8Bit(&dataASN[OCSPRESPDATAASN_IDX_VER], 0);
3908139173 SetASN_Buffer(&dataASN[OCSPRESPDATAASN_IDX_RESP], NULL,
3908239174 respListSz);
39083- /* TODO add responseExtensions support */
39084- SetASNItem_NoOutNode(dataASN, ocspRespDataASN,
39085- OCSPRESPDATAASN_IDX_RESPEXT,
39086- ocspRespDataASN_Length);
3908739175 /* Calculate size of encoding. */
3908839176 ret = SizeASN_Items(ocspRespDataASN, dataASN, ocspRespDataASN_Length,
3908939177 &sz);
@@ -39109,6 +39197,12 @@ static int EncodeResponseData(OcspResponse* resp, byte* out, word32* outSz)
3910939197 }
3911039198 if (ret == 0 && respListSz != 0)
3911139199 ret = ASN_PARSE_E;
39200+ /* Encode response extensions if buffer was allocated */
39201+ if (ret == 0 && respExtSz > 0) {
39202+ ret = EncodeOcspRespExtensions(resp,
39203+ (byte*)dataASN[OCSPRESPDATAASN_IDX_RESPEXT].data.buffer.data,
39204+ &respExtSz);
39205+ }
3911239206 }
3911339207 if (ret == 0)
3911439208 *outSz = sz;
@@ -40197,35 +40291,6 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap,
4019740291#endif /* WOLFSSL_ASN_TEMPLATE */
4019840292}
4019940293
40200- #ifdef WOLFSSL_ASN_TEMPLATE
40201- /* ASN.1 template for OCSP nonce extension.
40202- * RFC 6960, 4.4.1 - Nonce
40203- * X.509: RFC 5280, 4.1 - Basic Certificate Fields. (Extension)
40204- */
40205- static const ASNItem ocspNonceExtASN[] = {
40206- /* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
40207- /* Extension */
40208- /* EXT */ { 1, ASN_SEQUENCE, 1, 1, 0 },
40209- /* extnId */
40210- /* EXT_OID */ {2, ASN_OBJECT_ID, 0, 0, 0 },
40211- /* critical not encoded. */
40212- /* extnValue */
40213- /* EXT_VAL */ {2, ASN_OCTET_STRING, 0, 1, 0 },
40214- /* nonce */
40215- /* EXT_NONCE */ {3, ASN_OCTET_STRING, 0, 0, 0 },
40216- };
40217- enum {
40218- OCSPNONCEEXTASN_IDX_SEQ = 0,
40219- OCSPNONCEEXTASN_IDX_EXT,
40220- OCSPNONCEEXTASN_IDX_EXT_OID,
40221- OCSPNONCEEXTASN_IDX_EXT_VAL,
40222- OCSPNONCEEXTASN_IDX_EXT_NONCE,
40223- };
40224-
40225- /* Number of items in ASN.1 template for OCSP nonce extension. */
40226- #define ocspNonceExtASN_Length (sizeof(ocspNonceExtASN) / sizeof(ASNItem))
40227- #endif /* WOLFSSL_ASN_TEMPLATE */
40228-
4022940294word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
4023040295{
4023140296 const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
@@ -40526,6 +40591,85 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
4052640591
4052740592#ifdef HAVE_OCSP_RESPONDER
4052840593
40594+ #ifdef WOLFSSL_ASN_TEMPLATE
40595+ /* Decode OCSP request extensions.
40596+ * RFC 6960, 4.1.1 - ASN.1 Specification of the OCSP Request
40597+ *
40598+ * @param [in] source Buffer containing encoded extensions (inside [2]).
40599+ * @param [in] sz Length of buffer in bytes.
40600+ * @param [in, out] req OCSP request object to store nonce.
40601+ * @return 0 on success.
40602+ * @return ASN_PARSE_E when data is malformed.
40603+ */
40604+ static int DecodeOcspReqExtensions(const byte* source, word32 sz,
40605+ OcspRequest* req)
40606+ {
40607+ DECL_ASNGETDATA(dataASN, certExtASN_Length);
40608+ int ret = 0;
40609+ word32 idx = 0;
40610+ word32 maxIdx;
40611+ int seqLen;
40612+
40613+ WOLFSSL_ENTER("DecodeOcspReqExtensions");
40614+
40615+ /* Skip the outer SEQUENCE that wraps all extensions */
40616+ if (GetSequence(source, &idx, &seqLen, sz) < 0) {
40617+ return ASN_PARSE_E;
40618+ }
40619+ maxIdx = idx + (word32)seqLen;
40620+
40621+ CALLOC_ASNGETDATA(dataASN, certExtASN_Length, ret, req->heap);
40622+
40623+ /* Step through all extensions. */
40624+ while ((ret == 0) && (idx < maxIdx)) {
40625+ byte isCrit = 0;
40626+ /* Clear dynamic data, set OID type to expect. */
40627+ XMEMSET(dataASN, 0, sizeof(*dataASN) * certExtASN_Length);
40628+ GetASN_OID(&dataASN[CERTEXTASN_IDX_OID], oidOcspType);
40629+ GetASN_Boolean(&dataASN[CERTEXTASN_IDX_CRIT], &isCrit);
40630+ /* Decode extension. */
40631+ ret = GetASN_Items(certExtASN, dataASN, certExtASN_Length, 0,
40632+ source, &idx, sz);
40633+ if (ret == 0) {
40634+ word32 oid = dataASN[CERTEXTASN_IDX_OID].data.oid.sum;
40635+ int length = (int)dataASN[CERTEXTASN_IDX_VAL].length;
40636+
40637+ if (oid == OCSP_NONCE_OID) {
40638+ /* Extract nonce data - get data inside inner OCTET_STRING */
40639+ ret = GetOctetString(source, &idx, &length, sz);
40640+ if (ret >= 0) {
40641+ ret = 0;
40642+ if (length <= (int)sizeof(req->nonce)) {
40643+ XMEMCPY(req->nonce, source + idx, (size_t)length);
40644+ req->nonceSz = length;
40645+ }
40646+ else {
40647+ /* Nonce too large */
40648+ ret = BUFFER_E;
40649+ }
40650+ }
40651+ }
40652+ else if (isCrit) {
40653+ /* Unknown critical extension - fail */
40654+ ret = ASN_PARSE_E;
40655+ }
40656+ /* Ignore all other extension types. */
40657+
40658+ /* Skip over rest of extension. */
40659+ idx += (word32)length;
40660+ }
40661+ }
40662+
40663+ /* Ensure all extension data was consumed */
40664+ if (ret == 0 && idx != maxIdx) {
40665+ ret = ASN_PARSE_E;
40666+ }
40667+
40668+ FREE_ASNGETDATA(dataASN, req->heap);
40669+ return ret;
40670+ }
40671+ #endif /* WOLFSSL_ASN_TEMPLATE */
40672+
4052940673int DecodeOcspRequest(OcspRequest* req, const byte* input, word32 size)
4053040674{
4053140675#ifndef WOLFSSL_ASN_TEMPLATE
@@ -40572,9 +40716,12 @@ int DecodeOcspRequest(OcspRequest* req, const byte* input, word32 size)
4057240716 ret = ASN_PARSE_E;
4057340717 }
4057440718 if (ret == 0) {
40575- /* Optional extensions not supported yet */
40719+ /* Parse optional extensions */
4057640720 if (dataASN[OCSPREQUESTASN_IDX_TBS_REQEXT].data.ref.data != NULL) {
40577- ret = NOT_COMPILED_IN;
40721+ ret = DecodeOcspReqExtensions(
40722+ dataASN[OCSPREQUESTASN_IDX_TBS_REQEXT].data.ref.data,
40723+ dataASN[OCSPREQUESTASN_IDX_TBS_REQEXT].data.ref.length,
40724+ req);
4057840725 }
4057940726 }
4058040727 if (ret == 0) {
0 commit comments