Browse Source

Teach more of the ASN.1 code about libctx/propq

Make sure we pass libctx/propq down to all the layers so that objects that
are created during parsing have the right values. Then use this new
capability for PKCS7.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15591)
Matt Caswell 3 years ago
parent
commit
dea2878fac

+ 16 - 4
crypto/asn1/a_d2i_fp.c

@@ -55,7 +55,8 @@ void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
 
 #endif
 
-void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *x,
+                           OSSL_LIB_CTX *libctx, const char *propq)
 {
     BUF_MEM *b = NULL;
     const unsigned char *p;
@@ -69,14 +70,20 @@ void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
         goto err;
 
     p = (const unsigned char *)b->data;
-    ret = ASN1_item_d2i(x, &p, len, it);
+    ret = ASN1_item_d2i_ex(x, &p, len, it, libctx, propq);
  err:
     BUF_MEM_free(b);
     return ret;
 }
 
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+{
+    return ASN1_item_d2i_bio_ex(it, in, x, NULL, NULL);
+}
+
 #ifndef OPENSSL_NO_STDIO
-void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
+                          OSSL_LIB_CTX *libctx, const char *propq)
 {
     BIO *b;
     char *ret;
@@ -86,10 +93,15 @@ void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
         return NULL;
     }
     BIO_set_fp(b, in, BIO_NOCLOSE);
-    ret = ASN1_item_d2i_bio(it, b, x);
+    ret = ASN1_item_d2i_bio_ex(it, b, x, libctx, propq);
     BIO_free(b);
     return ret;
 }
+
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+{
+    return ASN1_item_d2i_fp_ex(it, in, x, NULL, NULL);
+}
 #endif
 
 #define HEADER_SIZE   8

+ 3 - 0
crypto/asn1/asn1_local.h

@@ -89,3 +89,6 @@ int ossl_c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp,
 int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
 
 ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);
+
+int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                 OSSL_LIB_CTX *libctx, const char *propq);

+ 9 - 7
crypto/asn1/asn_mime.c

@@ -130,7 +130,8 @@ int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
     return r;
 }
 
-static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x)
+static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x,
+                                 OSSL_LIB_CTX *libctx, const char *propq)
 {
     BIO *b64;
     ASN1_VALUE *val;
@@ -140,7 +141,7 @@ static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x)
         return 0;
     }
     bio = BIO_push(b64, bio);
-    val = ASN1_item_d2i_bio(it, bio, x);
+    val = ASN1_item_d2i_bio_ex(it, bio, x, libctx, propq);
     if (!val)
         ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
     (void)BIO_flush(bio);
@@ -388,8 +389,9 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
  * opaque this is set to NULL
  */
 
-ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont, const ASN1_ITEM *it,
-                               ASN1_VALUE **x)
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
+                               const ASN1_ITEM *it, ASN1_VALUE **x,
+                               OSSL_LIB_CTX *libctx, const char *propq)
 {
     BIO *asnin;
     STACK_OF(MIME_HEADER) *headers = NULL;
@@ -461,7 +463,7 @@ ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont, const ASN1_ITEM
         }
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         /* Read in ASN1 */
-        if ((val = b64_read_asn1(asnin, it, x)) == NULL) {
+        if ((val = b64_read_asn1(asnin, it, x, libctx, propq)) == NULL) {
             ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
@@ -489,7 +491,7 @@ ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont, const ASN1_ITEM
 
     sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
 
-    if ((val = b64_read_asn1(bio, it, x)) == NULL) {
+    if ((val = b64_read_asn1(bio, it, x, libctx, propq)) == NULL) {
         ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR);
         return NULL;
     }
@@ -498,7 +500,7 @@ ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont, const ASN1_ITEM
 
 ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
 {
-    return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL);
+    return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL, NULL, NULL);
 }
 
 /* Copy text from one BIO to another making the output CRLF at EOL */

+ 66 - 34
crypto/asn1/tasn_dec.c

@@ -28,7 +28,8 @@
 static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                                long len, const ASN1_ITEM *it,
                                int tag, int aclass, char opt, ASN1_TLC *ctx,
-                               int depth);
+                               int depth, OSSL_LIB_CTX *libctx,
+                               const char *propq);
 
 static int asn1_check_eoc(const unsigned char **in, long len);
 static int asn1_find_end(const unsigned char **in, long len, char inf);
@@ -46,11 +47,13 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
 static int asn1_template_ex_d2i(ASN1_VALUE **pval,
                                 const unsigned char **in, long len,
                                 const ASN1_TEMPLATE *tt, char opt,
-                                ASN1_TLC *ctx, int depth);
+                                ASN1_TLC *ctx, int depth, OSSL_LIB_CTX *libctx,
+                                const char *propq);
 static int asn1_template_noexp_d2i(ASN1_VALUE **val,
                                    const unsigned char **in, long len,
                                    const ASN1_TEMPLATE *tt, char opt,
-                                   ASN1_TLC *ctx, int depth);
+                                   ASN1_TLC *ctx, int depth,
+                                   OSSL_LIB_CTX *libctx, const char *propq);
 static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
                                  const unsigned char **in, long len,
                                  const ASN1_ITEM *it,
@@ -101,9 +104,36 @@ unsigned long ASN1_tag2bit(int tag)
  * this will simply be a special case.
  */
 
-ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
-                          const unsigned char **in, long len,
-                          const ASN1_ITEM *it)
+static int asn1_item_ex_d2i_intern(ASN1_VALUE **pval, const unsigned char **in,
+                                   long len, const ASN1_ITEM *it, int tag,
+                                   int aclass, char opt, ASN1_TLC *ctx,
+                                   OSSL_LIB_CTX *libctx, const char *propq)
+{
+    int rv;
+
+    if (pval == NULL || it == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0,
+                             libctx, propq);
+    if (rv <= 0)
+        ASN1_item_ex_free(pval, it);
+    return rv;
+}
+
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+                     const ASN1_ITEM *it,
+                     int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+    return asn1_item_ex_d2i_intern(pval, in, len, it, tag, aclass, opt, ctx,
+                                   NULL, NULL);
+}
+
+ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **pval,
+                             const unsigned char **in, long len,
+                             const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+                             const char *propq)
 {
     ASN1_TLC c;
     ASN1_VALUE *ptmpval = NULL;
@@ -111,25 +141,17 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
     if (pval == NULL)
         pval = &ptmpval;
     asn1_tlc_clear_nc(&c);
-    if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
+    if (asn1_item_ex_d2i_intern(pval, in, len, it, -1, 0, 0, &c, libctx,
+                                propq) > 0)
         return *pval;
     return NULL;
 }
 
-int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
-                     const ASN1_ITEM *it,
-                     int tag, int aclass, char opt, ASN1_TLC *ctx)
+ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
+                          const unsigned char **in, long len,
+                          const ASN1_ITEM *it)
 {
-    int rv;
-
-    if (pval == NULL || it == NULL) {
-        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
-    }
-    rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0);
-    if (rv <= 0)
-        ASN1_item_ex_free(pval, it);
-    return rv;
+    return ASN1_item_d2i_ex(pval, in, len, it, NULL, NULL);
 }
 
 /*
@@ -140,7 +162,8 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
 static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                                long len, const ASN1_ITEM *it,
                                int tag, int aclass, char opt, ASN1_TLC *ctx,
-                               int depth)
+                               int depth, OSSL_LIB_CTX *libctx,
+                               const char *propq)
 {
     const ASN1_TEMPLATE *tt, *errtt = NULL;
     const ASN1_EXTERN_FUNCS *ef;
@@ -188,8 +211,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                           ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
                 goto err;
             }
-            return asn1_template_ex_d2i(pval, in, len,
-                                        it->templates, opt, ctx, depth);
+            return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx,
+                                        depth, libctx, propq);
         }
         return asn1_d2i_ex_primitive(pval, in, len, it,
                                      tag, aclass, opt, ctx);
@@ -235,6 +258,9 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
     case ASN1_ITYPE_EXTERN:
         /* Use new style d2i */
         ef = it->funcs;
+        if (ef->asn1_ex_d2i_ex != NULL)
+            return ef->asn1_ex_d2i_ex(pval, in, len, it, tag, aclass, opt, ctx,
+                                      libctx, propq);
         return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);
 
     case ASN1_ITYPE_CHOICE:
@@ -258,7 +284,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                 ossl_asn1_template_free(pchptr, tt);
                 ossl_asn1_set_choice_selector(pval, -1, it);
             }
-        } else if (!ASN1_item_ex_new(pval, it)) {
+        } else if (!ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) {
             ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         }
@@ -269,7 +295,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             /*
              * We mark field as OPTIONAL so its absence can be recognised.
              */
-            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth);
+            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth,
+                                       libctx, propq);
             /* If field not present, try the next one */
             if (ret == -1)
                 continue;
@@ -335,7 +362,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             goto err;
         }
 
-        if (*pval == NULL && !ASN1_item_ex_new(pval, it)) {
+        if (*pval == NULL
+                && !ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) {
             ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         }
@@ -392,7 +420,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
              */
 
             ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx,
-                                       depth);
+                                       depth, libctx, propq);
             if (!ret) {
                 errtt = seqtt;
                 goto err;
@@ -468,7 +496,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
 static int asn1_template_ex_d2i(ASN1_VALUE **val,
                                 const unsigned char **in, long inlen,
                                 const ASN1_TEMPLATE *tt, char opt,
-                                ASN1_TLC *ctx, int depth)
+                                ASN1_TLC *ctx, int depth,
+                                OSSL_LIB_CTX *libctx, const char *propq)
 {
     int flags, aclass;
     int ret;
@@ -502,7 +531,8 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
             return 0;
         }
         /* We've found the field so it can't be OPTIONAL now */
-        ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth);
+        ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth, libctx,
+                                      propq);
         if (!ret) {
             ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
@@ -525,7 +555,8 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
             }
         }
     } else
-        return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth);
+        return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth,
+                                       libctx, propq);
 
     *in = p;
     return 1;
@@ -537,7 +568,8 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
 static int asn1_template_noexp_d2i(ASN1_VALUE **val,
                                    const unsigned char **in, long len,
                                    const ASN1_TEMPLATE *tt, char opt,
-                                   ASN1_TLC *ctx, int depth)
+                                   ASN1_TLC *ctx, int depth,
+                                   OSSL_LIB_CTX *libctx, const char *propq)
 {
     int flags, aclass;
     int ret;
@@ -618,7 +650,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
             skfield = NULL;
             if (!asn1_item_embed_d2i(&skfield, &p, len,
                                      ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx,
-                                     depth)) {
+                                     depth, libctx, propq)) {
                 ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
                 /* |skfield| may be partially allocated despite failure. */
                 ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item));
@@ -639,7 +671,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
         /* IMPLICIT tagging */
         ret = asn1_item_embed_d2i(val, &p, len,
                                   ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt,
-                                  ctx, depth);
+                                  ctx, depth, libctx, propq);
         if (!ret) {
             ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
@@ -648,7 +680,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
     } else {
         /* Nothing special */
         ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
-                                  -1, 0, opt, ctx, depth);
+                                  -1, 0, opt, ctx, depth, libctx, propq);
         if (!ret) {
             ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;

+ 7 - 0
crypto/asn1/tasn_new.c

@@ -45,6 +45,13 @@ ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
 
 /* Allocate an ASN1 structure */
 
+
+int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                 OSSL_LIB_CTX *libctx, const char *propq)
+{
+    return asn1_item_embed_new(pval, it, 0, libctx, propq);
+}
+
 int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
     return asn1_item_embed_new(pval, it, 0, NULL, NULL);

+ 11 - 2
crypto/pkcs7/pk7_asn1.c

@@ -66,8 +66,16 @@ ASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = {
 PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len)
 {
     PKCS7 *ret;
+    OSSL_LIB_CTX *libctx = NULL;
+    const char *propq = NULL;
 
-    ret = (PKCS7 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (PKCS7_it()));
+    if (a != NULL && *a != NULL) {
+        libctx = (*a)->ctx.libctx;
+        propq = (*a)->ctx.propq;
+    }
+
+    ret = (PKCS7 *)ASN1_item_d2i_ex((ASN1_VALUE **)a, in, len, (PKCS7_it()),
+                                    libctx, propq);
     if (ret != NULL)
         ossl_pkcs7_resolve_libctx(ret);
     return ret;
@@ -85,7 +93,8 @@ PKCS7 *PKCS7_new(void)
 
 PKCS7 *PKCS7_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
 {
-    PKCS7 *pkcs7 = PKCS7_new();
+    PKCS7 *pkcs7 = (PKCS7 *)ASN1_item_new_ex(ASN1_ITEM_rptr(PKCS7), libctx,
+                                             propq);
 
     if (pkcs7 != NULL) {
         pkcs7->ctx.libctx = libctx;

+ 8 - 1
crypto/pkcs7/pk7_mime.c

@@ -49,9 +49,16 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7)
 {
     PKCS7 *ret;
+    OSSL_LIB_CTX *libctx = NULL;
+    const char *propq = NULL;
+
+    if (p7 != NULL && *p7 != NULL) {
+        libctx = (*p7)->ctx.libctx;
+        propq = (*p7)->ctx.propq;
+    }
 
     ret = (PKCS7 *)SMIME_read_ASN1_ex(bio, 0, bcont, ASN1_ITEM_rptr(PKCS7),
-                                      (ASN1_VALUE **)p7);
+                                      (ASN1_VALUE **)p7, libctx, propq);
     if (ret != NULL)
         ossl_pkcs7_resolve_libctx(ret);
     return ret;

+ 17 - 2
crypto/x509/x_all.c

@@ -182,8 +182,15 @@ int i2d_X509_CRL_bio(BIO *bp, const X509_CRL *crl)
 PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
 {
     PKCS7 *ret;
+    OSSL_LIB_CTX *libctx = NULL;
+    const char *propq = NULL;
 
-    ret = ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+    if (p7 != NULL && *p7 != NULL) {
+        libctx = (*p7)->ctx.libctx;
+        propq = (*p7)->ctx.propq;
+    }
+
+    ret = ASN1_item_d2i_fp_ex(ASN1_ITEM_rptr(PKCS7), fp, p7, libctx, propq);
     if (ret != NULL)
         ossl_pkcs7_resolve_libctx(ret);
     return ret;
@@ -198,8 +205,16 @@ int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
 PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
 {
     PKCS7 *ret;
+    OSSL_LIB_CTX *libctx = NULL;
+    const char *propq = NULL;
+
+    if (p7 != NULL && *p7 != NULL) {
+        libctx = (*p7)->ctx.libctx;
+        propq = (*p7)->ctx.propq;
+    }
+
 
-    ret = ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+    ret = ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS7), bp, p7, libctx, propq);
     if (ret != NULL)
         ossl_pkcs7_resolve_libctx(ret);
     return ret;

+ 6 - 2
doc/man3/SMIME_read_ASN1.pod

@@ -10,7 +10,8 @@ SMIME_read_ASN1_ex, SMIME_read_ASN1
  #include <openssl/asn1.h>
 
  ASN1_VALUE *SMIME_read_ASN1_ex(BIO *in, int flags, BIO **bcont,
-                                const ASN1_ITEM *it, ASN1_VALUE **x);
+                                const ASN1_ITEM *it, ASN1_VALUE **x,
+                                OSSL_LIB_CTX *libctx, const char *propq);
  ASN1_VALUE *SMIME_read_ASN1(BIO *in, BIO **bcont, const ASN1_ITEM *it);
 
 =head1 DESCRIPTION
@@ -25,7 +26,10 @@ to be followed by B<CR> and B<LF> characters, else only by an B<LF> character.
 I<x> can be used to optionally supply
 a previously created I<it> ASN1_VALUE object (such as CMS_ContentInfo or PKCS7),
 it can be set to NULL. Valid values that can be used by ASN.1 structure I<it>
-are ASN1_ITEM_rptr(PKCS7) or ASN1_ITEM_rptr(CMS_ContentInfo).
+are ASN1_ITEM_rptr(PKCS7) or ASN1_ITEM_rptr(CMS_ContentInfo). Any algorithm
+fetches that occur during the operation will use the B<OSSL_LIB_CTX> supplied in
+the I<libctx> parameter, and use the property query string I<propq> See
+L<crypto(7)/ALGORITHM FETCHING> for further details about algorithm fetching.
 
 If cleartext signing is used then the content is saved in a memory bio which is
 written to I<*bcont>, otherwise I<*bcont> is set to NULL.

+ 10 - 2
include/openssl/asn1.h.in

@@ -762,6 +762,8 @@ void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x);
                         in, \
                         CHECKED_PPTR_OF(type, x)))
 
+void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
+                          OSSL_LIB_CTX *libctx, const char *propq);
 void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
 int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, const void *x);
 
@@ -784,6 +786,8 @@ void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x);
                           in, \
                           CHECKED_PPTR_OF(type, x)))
 
+void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *pval,
+                           OSSL_LIB_CTX *libctx, const char *propq);
 void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *pval);
 int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x);
 
@@ -846,6 +850,9 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
 ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
                              const char *propq);
 void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
+ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **val, const unsigned char **in,
+                             long len, const ASN1_ITEM *it,
+                             OSSL_LIB_CTX *libctx, const char *propq);
 ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in,
                           long len, const ASN1_ITEM *it);
 int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
@@ -921,8 +928,9 @@ int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
                         STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
                         OSSL_LIB_CTX *libctx, const char *propq);
 ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
-ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont, const ASN1_ITEM *it,
-                               ASN1_VALUE **x);
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
+                               const ASN1_ITEM *it, ASN1_VALUE **x,
+                               OSSL_LIB_CTX *libctx, const char *propq);
 int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
 int SMIME_text(BIO *in, BIO *out);
 

+ 5 - 0
include/openssl/asn1t.h.in

@@ -631,6 +631,10 @@ typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
                         const ASN1_ITEM *it, int tag, int aclass, char opt,
                         ASN1_TLC *ctx);
 
+typedef int ASN1_ex_d2i_ex(ASN1_VALUE **pval, const unsigned char **in, long len,
+                           const ASN1_ITEM *it, int tag, int aclass, char opt,
+                           ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
+                           const char *propq);
 typedef int ASN1_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                         const ASN1_ITEM *it, int tag, int aclass);
 typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
@@ -660,6 +664,7 @@ typedef struct ASN1_EXTERN_FUNCS_st {
     ASN1_ex_i2d *asn1_ex_i2d;
     ASN1_ex_print_func *asn1_ex_print;
     ASN1_ex_new_ex_func *asn1_ex_new_ex;
+    ASN1_ex_d2i_ex *asn1_ex_d2i_ex;
 } ASN1_EXTERN_FUNCS;
 
 typedef struct ASN1_PRIMITIVE_FUNCS_st {

+ 3 - 0
util/libcrypto.num

@@ -5409,3 +5409,6 @@ NCONF_get0_libctx                       ?	3_0_0	EXIST::FUNCTION:
 NCONF_get_section_names                 ?	3_0_0	EXIST::FUNCTION:
 X509_PUBKEY_new_ex                      ?	3_0_0	EXIST::FUNCTION:
 ASN1_item_new_ex                        ?	3_0_0	EXIST::FUNCTION:
+ASN1_item_d2i_fp_ex                     ?	3_0_0	EXIST::FUNCTION:STDIO
+ASN1_item_d2i_bio_ex                    ?	3_0_0	EXIST::FUNCTION:
+ASN1_item_d2i_ex                        ?	3_0_0	EXIST::FUNCTION: