diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2013-12-22 00:35:29 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2013-12-22 00:35:29 +0000 |
commit | cd30f03ac5bf2962f44bd02ae8d88245dff2f12c (patch) | |
tree | 3925364a2099537f881e7a3996acd500b1bfcbbe /crypto/cms/cms_smime.c | |
parent | 20b82b514d81a64f5b240788e5051167456af379 (diff) |
Canonicalise input in CMS_verify.
If content is detached and not binary mode translate the input to
CRLF format. Before this change the input was verified verbatim
which lead to a discrepancy between sign and verify.
Diffstat (limited to 'crypto/cms/cms_smime.c')
-rw-r--r-- | crypto/cms/cms_smime.c | 94 |
1 files changed, 73 insertions, 21 deletions
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 204595b908..8f1aa38ccc 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -60,21 +60,28 @@ #include "cms_lcl.h" #include "asn1_locl.h" -static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) +static BIO *cms_get_text_bio(BIO *out, unsigned int flags) { - unsigned char buf[4096]; - int r = 0, i; - BIO *tmpout = NULL; - + BIO *rbio; if (out == NULL) - tmpout = BIO_new(BIO_s_null()); + rbio = BIO_new(BIO_s_null()); else if (flags & CMS_TEXT) { - tmpout = BIO_new(BIO_s_mem()); - BIO_set_mem_eof_return(tmpout, 0); + rbio = BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(rbio, 0); } else - tmpout = out; + rbio = out; + return rbio; + } + +static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) + { + unsigned char buf[4096]; + int r = 0, i; + BIO *tmpout; + + tmpout = cms_get_text_bio(out, flags); if(!tmpout) { @@ -142,7 +149,7 @@ static void do_free_upto(BIO *f, BIO *upto) BIO_free(f); f = tbio; } - while (f != upto); + while (f && f != upto); } else BIO_free_all(f); @@ -323,7 +330,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, STACK_OF(X509_CRL) *crls = NULL; X509 *signer; int i, scount = 0, ret = 0; - BIO *cmsbio = NULL, *tmpin = NULL; + BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL; if (!dcont && !check_content(cms)) return 0; @@ -406,15 +413,48 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, } else tmpin = dcont; - + /* If not binary mode and detached generate digests by *writing* + * through the BIO. That makes it possible to canonicalise the + * input. + */ + if (!(flags & SMIME_BINARY) && dcont) + { + /* Create output BIO so we can either handle text or to + * ensure included content doesn't override detached content. + */ + tmpout = cms_get_text_bio(out, flags); + if(!tmpout) + { + CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE); + goto err; + } + cmsbio = CMS_dataInit(cms, tmpout); + if (!cmsbio) + goto err; + /* Don't use SMIME_TEXT for verify: it adds headers and + * we want to remove them. + */ + SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT); - cmsbio=CMS_dataInit(cms, tmpin); - if (!cmsbio) - goto err; + if(flags & CMS_TEXT) + { + if (!SMIME_text(tmpout, out)) + { + CMSerr(CMS_F_CMS_VERIFY,CMS_R_SMIME_TEXT_ERROR); + goto err; + } + } + } + else + { + cmsbio=CMS_dataInit(cms, tmpin); + if (!cmsbio) + goto err; - if (!cms_copy_content(out, cmsbio, flags)) - goto err; + if (!cms_copy_content(out, cmsbio, flags)) + goto err; + } if (!(flags & CMS_NO_CONTENT_VERIFY)) { for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) @@ -432,11 +472,23 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, ret = 1; err: - - if (dcont && (tmpin == dcont)) - do_free_upto(cmsbio, dcont); + if (!(flags & SMIME_BINARY) && dcont) + { + do_free_upto(cmsbio, tmpout); + if (tmpin != dcont) + BIO_free(tmpin); + } else - BIO_free_all(cmsbio); + { + + if (dcont && (tmpin == dcont)) + do_free_upto(cmsbio, dcont); + else + BIO_free_all(cmsbio); + } + + if (tmpout && out != tmpout) + BIO_free_all(tmpout); if (cms_certs) sk_X509_pop_free(cms_certs, X509_free); |