-
-
Notifications
You must be signed in to change notification settings - Fork 11k
Description
After cms = d2i_CMS_bio(bio, NULL), a crash can occur with CMS_verify(cms, NULL, NULL, NULL, NULL, CMS_NO_SIGNER_CERT_VERIFY):
Program terminated with signal SIGSEGV, Segmentation fault.
#0 CMS_SignerInfo_verify (si=0x13199499080) at crypto/cms/cms_sd.c:833
833 fetched_md = EVP_MD_fetch(ctx->libctx, name, ctx->propq);
(gdb) p si->cms_ctx
$1 = (const CMS_CTX *) 0x0
(gdb) bt
#0 CMS_SignerInfo_verify (si=0x13199499080) at crypto/cms/cms_sd.c:833
#1 0x0000012f19e7822b in CMS_verify (cms=<optimized out>, certs=<optimized out>, store=0x0,
dcont=0x0, out=0x0, flags=<optimized out>) at crypto/cms/cms_smime.c:378
The reason for this is that the signer info si doesn't have its cms_ctx set, so ctx is NULL.
This in turn is due to what looks like a logic error on line 41 in d2i_CMS_bio():
Lines 36 to 42 in c305667
| CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms) | |
| { | |
| CMS_ContentInfo *ci; | |
| ci = ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms); | |
| if (ci != NULL && cms != NULL) | |
| cms_resolve_libctx(ci); |
If passed in NULL, or a pointer to NULL, the d2i family of functions will allocate a new struct.
This will have its libctx resolved only if it was passed a pointer to NULL, but not if it was passed NULL.
I think the && cms != NULL part in this conditional should be dropped. Indeed, doing this resolves this crash and the code works as expected from OpenSSL 1.1.1. Of course, I can easily rewrite the code to avoid this problem, but it looks like a bug.
The same problem seems to be present in SMIME_read_CMS_ex (note SMIME_read_CMS just below)
Lines 100 to 101 in c305667
| if (ci != NULL && cms != NULL) | |
| cms_resolve_libctx(ci); |
and in
d2i_CMS_ContentInfo:Lines 37 to 38 in c305667
| if (ci != NULL && a != NULL) | |
| cms_resolve_libctx(ci); |