+ const EVP_MD *dgst)
+{
+ PKCS7_SIGNER_INFO *si = NULL;
+
+ if (dgst == NULL) {
+ int def_nid;
+ if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
+ goto err;
+ dgst = EVP_get_digestbynid(def_nid);
+ if (dgst == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_DEFAULT_DIGEST);
+ goto err;
+ }
+ }
+
+ if ((si = PKCS7_SIGNER_INFO_new()) == NULL)
+ goto err;
+ if (PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst) <= 0)
+ goto err;
+ if (!PKCS7_add_signer(p7, si))
+ goto err;
+ return si;
+ err:
+ PKCS7_SIGNER_INFO_free(si);
+ return NULL;
+}
+
+static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7)
+{
+ if (p7->d.ptr == NULL)
+ return NULL;
+ if (PKCS7_type_is_signed(p7))
+ return p7->d.sign->cert;
+ if (PKCS7_type_is_signedAndEnveloped(p7))
+ return p7->d.signed_and_enveloped->cert;
+ return NULL;
+}
+
+static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7)
+{
+ if (p7->d.ptr == NULL)
+ return NULL;
+ if (PKCS7_type_is_signedAndEnveloped(p7))
+ return p7->d.signed_and_enveloped->recipientinfo;
+ if (PKCS7_type_is_enveloped(p7))
+ return p7->d.enveloped->recipientinfo;
+ return NULL;
+}
+
+/*
+ * Set up the library context into any loaded structure that needs it.
+ * i.e loaded X509 objects.
+ */
+void ossl_pkcs7_resolve_libctx(PKCS7 *p7)
+{
+ int i;
+ const PKCS7_CTX *ctx = ossl_pkcs7_get0_ctx(p7);
+ OSSL_LIB_CTX *libctx = ossl_pkcs7_ctx_get0_libctx(ctx);
+ const char *propq = ossl_pkcs7_ctx_get0_propq(ctx);
+ STACK_OF(PKCS7_RECIP_INFO) *rinfos;
+ STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
+ STACK_OF(X509) *certs;
+
+ if (ctx == NULL || p7->d.ptr == NULL)
+ return;
+
+ rinfos = pkcs7_get_recipient_info(p7);
+ sinfos = PKCS7_get_signer_info(p7);
+ certs = pkcs7_get_signer_certs(p7);
+
+ for (i = 0; i < sk_X509_num(certs); i++)
+ ossl_x509_set0_libctx(sk_X509_value(certs, i), libctx, propq);
+
+ for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) {
+ PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i);
+
+ ossl_x509_set0_libctx(ri->cert, libctx, propq);
+ }
+
+ for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
+ PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+
+ if (si != NULL)
+ si->ctx = ctx;
+ }
+}
+
+const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7)
+{
+ return p7 != NULL ? &p7->ctx : NULL;
+}
+
+void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx)
+{
+ p7->ctx.libctx = ctx;
+}
+
+int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq)
+{
+ if (p7->ctx.propq != NULL) {
+ OPENSSL_free(p7->ctx.propq);
+ p7->ctx.propq = NULL;
+ }
+ if (propq != NULL) {
+ p7->ctx.propq = OPENSSL_strdup(propq);
+ if (p7->ctx.propq == NULL)
+ return 0;
+ }
+ return 1;
+}
+
+int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to)
+{
+ ossl_pkcs7_set0_libctx(to, from->ctx.libctx);
+ if (!ossl_pkcs7_set1_propq(to, from->ctx.propq))
+ return 0;
+
+ ossl_pkcs7_resolve_libctx(to);
+ return 1;
+}
+
+OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx)
+{
+ return ctx != NULL ? ctx->libctx : NULL;
+}
+const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx)
+{
+ return ctx != NULL ? ctx->propq : NULL;
+}
+
+int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
+{
+ if (PKCS7_type_is_digest(p7)) {
+ if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB);
+ return 0;
+ }
+ p7->d.digest->md->parameter->type = V_ASN1_NULL;
+ p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md));
+ return 1;
+ }
+
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
+ return 1;
+}