Creating a PKCS7 detached signature with providers

53 views
Skip to first unread message

Mad

unread,
Oct 2, 2025, 5:40:13 AMOct 2
to openssl-users

Hello,

This is the first time I've posted on a mailing list, so sorry if the tone isn't correct.

I'm in the process of finalising a project to update OpenSSL 1.1.1 to 3.5.X with the purpose of doing ASN1 decoding and PKCS7 signing where I integrate my own cryptography via providers (digest, cipher, mac, signature, asym_cipher, keymgmt and kdf).

When implementing the detached PKCS7 signature, I tried to use ‘PKCS7_sign’ or ‘CMS_sign(NULL, NULL, NULL, NULL, CMS_PARTIAL|CMS_DETACHED) + CMS_add1_signer(...) + CMS_final(...)’, but the problem was that I systematically came across the ‘EVP_get_digestbyname’ function in the base layers.

If I understand correctly, the ‘EVP_get_digestbyname’ function is incompatible with the OpenSSL 3+ provider system. I wanted to know if there was a trick to make ‘EVP_get_digestbyname’ work or if there is a method that I haven't seen to make a detached signature in DER format.

Thank you for reading and your time.


Matt Caswell

unread,
Oct 2, 2025, 12:13:16 PMOct 2
to Mad, openssl-users
It's not "incompatible" with the provider system - but it is restricted. It only knows about certain built-in digests - but those digests can still come from a provider. Where in the CMS code are you hitting it?

Matt

 

Thank you for reading and your time.


--
You received this message because you are subscribed to the Google Groups "openssl-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openssl-user...@openssl.org.
To view this discussion visit https://groups.google.com/a/openssl.org/d/msgid/openssl-users/e3df5e46-f50d-4dcc-a852-38f2ca2014afn%40openssl.org.

Mad

unread,
Oct 3, 2025, 9:07:09 AMOct 3
to openssl-users, Matt Caswell, openssl-users, Mad

Thank you for your reply and sorry for the length of mine, but I think I need to be exhaustive.

For more detail, I've tried quite a few things to make myself compatible. The executed code looks like this (I don't include error handling so as not to make the code too heavy but I handle each function return correctly):

EVP_MD *md=EVP_MD_fetch(NULL, "SHA256", NULL);
CMS_ContentInfo *pCMS=CMS_sign(NULL, NULL, NULL, NULL, CMS_PARTIAL | CMS_DETACHED);
CMS_add1_signer(pCMS, PX509Cert, pPrivKey, md, CMS_NOATTR);
CMS_final(pCMS, pDataBIOIn, NULL, SMIME_BINARY);

If I don't prepare anything before, when I call ‘CMS_final’ I get the following error "lib(46): ossl_cms_DigestAlgorithm_init_bio(149)‘ which corresponds to ’ERR_raise(ERR_LIB_CMS, CMS_R_UNKOWN_DIGEST_ALGORITHM);".

Of the attempts I have tried, the one that seems the least bad was to add ‘EVP_add_digest(EVP_MD_fetch(NULL, “SHA256”, NULL));’ after initialising my providers. In this case ‘CMS_final’ does not cause an error, but when I retrieve my signature via ‘cbP7Data=id2_CMS_ContentInfo(pCMS, NULL);’ I get ‘cbP7Data==-1’ and the error "lib(13) : asn1_template_ex :reason(222)' which corresponds to 'ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);" but I can't find out which one it corresponds to.
I have the impression that something is missing when calling ‘CMS_final’ but I can't say what.

With regard to the digest providers that I define, I implement PROV_NAMES_SHA1, PROV_NAMES_SHA256, PROV_NAMES_512 and PROV_NAMES_MD5.

Finally, I'm not sure this is very useful but, as I'm in a restricted environment, I had to limit as much as possible the modules compiled with these options when generating my OpenSSL lib (it's not impossible that I removed something too much but I don't know what):

« no-autoalginit no-afalgeng no-aria no-asan no-asm no-async no-autoload-config no-bf no-blake2 no-camellia no-capieng no-cast no-chacha no-cmac no-cmp no-crypto-mdebug-backtrace no-ct no-deprecated no-des no-dgram no-dh no-dsa no-ec no-dynamic-engine no-ec no-ec2m no-ecdh no-ecdsa no-err no-external-tests no-filenames no-fuzz-libfuzzer no-fuzz-afl no-gost no-heartbeats no-hw no-idea no-makedepend no-md2 no-md4 no-mdc2 no-msan no-multiblock no-nextprotoneg no-pinshared no-ocb no-ocsp no-pic no-posix-io no-psk no-poly1305 no-rc2 no-rc4 no-rc5 no-rdrand no-rfc3779 no-rmd160 no-scrypt no-siphash no-sm2 no-sm3 no-sm4 no-srp no-srtp no-sse2 no-ssl no-ssl-trace no-static-engine no-stdio no-tests no-threads no-ts no-ui no-ubsan no-ui-console no-unit-test no-winstore no-whirlpool no-comp no-sctp no-seed no-shared no-ec_nistp_64_gcc_128 no-egd no-dsa no-dso no-dtls no-dtls1 no-dtls1_2 no-legacy no-sock no-tls no-tls1 no-tls1_1 no-tls1_2 no-tls1_3 »

Mad

Mad

unread,
Oct 16, 2025, 8:51:51 AM (9 days ago) Oct 16
to openssl-users, Mad, Matt Caswell, openssl-users

Hello,

I found the source of the problem and the solution, although it's not very elegant and there may be better ways to do it.

My goal is to create a detached PKCS7 signature, so I'm keeping the PKCS7_sign function and I have the following code (simplified, without error handling):

/* Create my own provider */


EVP_MD *md=EVP_MD_fetch(NULL, "SHA256", NULL) ;

/* Modern providers do not have this field, but it is essential for the signature to work. We add it in a dirty way for compatibility. */
md->type=NID_sha256 ;
/* Like PKCS7_sign_ex but lighter */
PKCS7 *pP7=PKCS7_new_ex(NULL, NULL);
PKCS7_set_type(pP7, NID_pkcs7_signed) ;
PKCS7_content_new(pP7, NID_pkcs7_data) ;
/* Adding information */
PKCS7_sign_add_signer(pP7, PX509Cert, pPrivKey, md, PKCS7_NOATTR);
PKCS7_set_detached(pP7, 1) ;
/* Signature */
PKCS7_final(pP7, pDataBIOIn, NULL, PKCS7_BINARY);

 

The problem is caused by this call stack:
EVP_MD_get_type
PKCS7_SIGNER_INFO_set
PKCS7_add_signature
PKCS7_sign_add_signer

Since an OpenSSL 3.0+ provider does not have a “type” field when fetched, the ‘EVP_MD_get_type’ function always returns 0 and corrupts all subsequent processing because "X509_ALGOR_set0(..., OBJ_nid2obj(EVP_MD_get_type(...)), ...)“ does not set the ”digest_alg" field of my PKCS7 structure.

Reply all
Reply to author
Forward
0 new messages