From 6b83d032a64848a66b60ca54729bcd79493f36ef Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Wed, 23 Sep 2020 10:19:50 +0200 Subject: [PATCH] apps/cms.c: Make -sign and -verify handle binary input Fixes #8940 Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/12959) --- apps/cms.c | 55 ++++++++++++++++++++++++++++--------- test/recipes/80-test_cms.t | 47 +++++++++++++++++++++++++++++-- test/smcont.bin | Bin 0 -> 8000 bytes 3 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 test/smcont.bin diff --git a/apps/cms.c b/apps/cms.c index f40049edac6..64867e37026 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -159,7 +159,7 @@ const OPTIONS cms_options[] = { {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, - {"binary", OPT_BINARY, '-', "Don't translate message to text"}, + {"binary", OPT_BINARY, '-', "Treat input as binary: do not translate to canonical form"}, {"keyid", OPT_KEYID, '-', "Use subject key identifier"}, {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, {"nocerts", OPT_NOCERTS, '-', @@ -227,7 +227,7 @@ const OPTIONS cms_options[] = { {NULL} }; -static CMS_ContentInfo *load_content_info(int informat, BIO *in, BIO **indata, +static CMS_ContentInfo *load_content_info(int informat, BIO *in, int flags, BIO **indata, const char *name, OSSL_LIB_CTX *libctx, const char *propq) @@ -241,7 +241,7 @@ static CMS_ContentInfo *load_content_info(int informat, BIO *in, BIO **indata, } switch (informat) { case FORMAT_SMIME: - ci = SMIME_read_CMS_ex(in, indata, &ret); + ci = SMIME_read_CMS_ex(in, flags, indata, &ret); break; case FORMAT_PEM: ci = PEM_read_bio_CMS(in, &ret, NULL, NULL); @@ -263,6 +263,29 @@ err: return NULL; } +static void warn_binary(const char *file) +{ + BIO *bio; + unsigned char linebuf[1024], *cur, *end; + int len; + + if ((bio = bio_open_default(file, 'r', FORMAT_BINARY)) == NULL) + return; /* cannot give a proper warning since there is an error */ + while ((len = BIO_read(bio, linebuf, sizeof(linebuf))) > 0) { + end = linebuf + len; + for (cur = linebuf; cur < end; cur++) { + if (*cur == '\0' || *cur >= 0x80) { + BIO_printf(bio_err, "Warning: input file '%s' contains %s" + " character; better use -binary option\n", + file, *cur == '\0' ? "NUL" : "8-bit"); + break; + } + } + } + BIO_free(bio); +} + + int cms_main(int argc, char **argv) { CONF *conf = NULL; @@ -452,7 +475,7 @@ int cms_main(int argc, char **argv) OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat)) goto opthelp; } else { - rcms = load_content_info(rctformat, rctin, NULL, "recipient", + rcms = load_content_info(rctformat, rctin, 0, NULL, "recipient", libctx, app_get0_propq()); } break; @@ -784,13 +807,12 @@ int cms_main(int argc, char **argv) if (!(operation & SMIME_SIGNERS)) flags &= ~CMS_DETACHED; - if (!(operation & SMIME_OP)) - if (flags & CMS_BINARY) + if ((flags & CMS_BINARY) != 0) { + if (!(operation & SMIME_OP)) outformat = FORMAT_BINARY; - - if (!(operation & SMIME_IP)) - if (flags & CMS_BINARY) + if (!(operation & SMIME_IP)) informat = FORMAT_BINARY; + } if (operation == SMIME_ENCRYPT) { if (!cipher) { @@ -867,16 +889,22 @@ int cms_main(int argc, char **argv) goto end; } - in = bio_open_default(infile, 'r', informat); + if ((flags & CMS_BINARY) == 0) + warn_binary(infile); + in = bio_open_default(infile, 'r', + (flags & CMS_BINARY) != 0 ? FORMAT_BINARY : informat); if (in == NULL) goto end; if (operation & SMIME_IP) { - cms = load_content_info(informat, in, &indata, "SMIME", libctx, app_get0_propq()); + cms = load_content_info(informat, in, flags, &indata, "SMIME", + libctx, app_get0_propq()); if (cms == NULL) goto end; if (contfile != NULL) { BIO_free(indata); + if ((flags & CMS_BINARY) == 0) + warn_binary(contfile); if ((indata = BIO_new_file(contfile, "rb")) == NULL) { BIO_printf(bio_err, "Can't read content file %s\n", contfile); goto end; @@ -897,13 +925,14 @@ int cms_main(int argc, char **argv) if (rctfile != NULL) { char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r"; + if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) { BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile); goto end; } - rcms = load_content_info(rctformat, rctin, NULL, "recipient", libctx, - app_get0_propq()); + rcms = load_content_info(rctformat, rctin, 0, NULL, "recipient", libctx, + app_get0_propq); if (rcms == NULL) goto end; } diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index a371f21ad8e..0e20b807c89 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -12,7 +12,7 @@ use warnings; use POSIX; use File::Spec::Functions qw/catfile/; -use File::Compare qw/compare_text/; +use File::Compare qw/compare_text compare/; use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/; use OpenSSL::Test::Utils; @@ -50,8 +50,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) $no_rc2 = 1 if disabled("legacy"); -plan tests => - + 10; +plan tests => 11; unless ($no_fips) { @config = ( "-config", srctop_file("test", "fips-and-base.cnf") ); @@ -812,6 +811,48 @@ subtest "CAdES ko tests\n" => sub { } }; +subtest "CMS binary input tests\n" => sub { + my $input = srctop_file("test", "smcont.bin"); + my $signed = "smcont.signed"; + my $verified = "smcont.verified"; + my $cert = srctop_file("test", "certs", "ee-self-signed.pem"); + my $key = srctop_file("test", "certs", "ee-key.pem"); + + plan tests => 11; + + ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", + "-signer", $cert, "-inkey", $key, + "-binary", "-in", $input, "-out", $signed])), + "sign binary input with -binary"); + ok(run(app(["openssl", "cms", "-verify", "-CAfile", $cert, + "-binary", "-in", $signed, "-out", $verified])), + "verify binary input with -binary"); + is(compare($input, $verified), 0, "binary input retained with -binary"); + ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", + "-signer", $cert, "-inkey", $key, + "-in", $input, "-out", $signed])), + "sign binary input without -binary"); + ok(run(app(["openssl", "cms", "-verify", "-CAfile", $cert, + "-in", $signed, "-out", $verified])), + "verify binary input without -binary"); + is(compare($input, $verified), 1, "binary input not retained without -binary"); + ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $cert, "-crlfeol", + "-binary", "-in", $signed, "-out", $verified])), + "verify binary input wrong crlfeol"); + + ok(run(app(["openssl", "cms", "-sign", "-md", "sha256", "-crlfeol", + "-signer", $cert, "-inkey", $key, + "-binary", "-in", $input, "-out", $signed.".crlf"])), + "sign binary input crlfeol"); + ok(run(app(["openssl", "cms", "-verify", "-CAfile", $cert, "-crlfeol", + "-binary", "-in", $signed.".crlf", "-out", $verified.".crlf"])), + "verify binary input crlfeol"); + is(compare($input, $verified.".crlf"), 0); + ok(!run(app(["openssl", "cms", "-verify", "-CAfile", $cert, + "-binary", "-in", $signed.".crlf", "-out", $verified.".crlf"])), + "verify binary input missing crlfeol"); +}; + sub check_availability { my $tnam = shift; diff --git a/test/smcont.bin b/test/smcont.bin new file mode 100644 index 0000000000000000000000000000000000000000..2a5ce10224ce2b98b481273ef8a04cc4557a9e26 GIT binary patch literal 8000 zc-rmO2R{@J0{~!7_TD=?d+)tPX0pp(DeI7NvUm2%*_Z-2nzn6i#Ak4jmRBK;gHx^jJRf*e;~sWn{4=}1y0!xoEIwys7taWruHZv?nRW5$ow&9kPBThH z`?Yujt9)53>m@%oh13Y77OupQZW=U>&=}blq-L^S8^8->oQfP@cu-PgV4h{^fU;8_ z@xDP4xIv+ANGC5)iV(A2=@-i&nWIglw#hLa3 zY`NKdE)g59Pyf4m_e|n!v@l)9t=K#>iSJ#cy8Be!sZ0x2(agEfz$#f)^a+Per{JjN zmjKYsOb&t4Rfbu*M%a&*W@+G#=JHghY@pj7=B5lLFF+XTl9<&t$4V|&${g`<=thLh zga6qC#VI8C)!kX=#9vvLGQ zkf(^mQbEJhVvFBpnzp`U)7)=`l3R3j;;3s4SM1xhH~zwJ2Xb9yjiF*z)_s6#RJsXu**gAdk2k>}P()1XHLc%) z7}1mK;V1j-OuzW7U#b#+Oa725Af5v1ER+tu$;C~CGGzaS1jnO!lmM!}{vDbJI=^M? zd+`2qHQ%kLH@j(?ZYM1KH5Q9Ssdl|lYgqekPb&-@Eo45$Gh1B70~gLH0>BwW^8M^! ze;se$nrzQb5=p$&>Utp!Y`z1((Tb;lrzNsJ57+Jsd^VJ1kqq`(t&1tp7$y6iWxLFks}R7_j~i(=!Xsl4PdA!8XGCnC zgL^(nE7%ciKEvs=?Y@yWkBbsfrZY6)P2^3paGz{fj-XysoLAg$Sdnp)BTc z=}meeQ!=y^kfpP$s+NrkQTHQ01*%^nOeXU(QGI5tX-@I+8$OYQrxfyQAwAd7`S-|W zNr_?G#;W%>ALexUH_wz+yDV`b0i@Pdll%Pg<~hB=X7lOmR#R7R2$_|;Jn^*NS~8}! z+xZAGnp}%D_NXTq@g=G>1fF1B*rDX*h1z#Bl;*=uijGjZOIOlXkZv<}_Mf!=n0NEB z#S_}0u|Jj2hq-(vdF}H14Tc+S5Au`81ZVsCt7KC(ucItx9!X5EhcmGTCepvAnj`Dh z>ObJpp8j#@xBp8yK>N$vHkG=&suxc;(O|`M-nuR9!(r+;?J__}G;2^LW4R$~p+=%_ z8C6!+HYP=z^*d=8-plD~ZEp+0tf+6+k$eMkrcv|TedwR(M%W|*rf^x^&6i(2Avzju z1|4$ZZh8DN+IBmJj*;B>TfF0LiTm*|vsc^pJ$F-1(|gjqf-jE;$7b-eVUuOkoo*Ylx`$U z3GjHvv1Zgq3%tkK6IuzYtN-dkl_?fGU5qEorrZUR0s3mpHfV~IVzuHd+odTUwf&6E z%fr4f{w9hN(4%g``f1fm7Y2WR{$LwBtP7$(Z9=tBNyffqyKb#T&6jO*%97ae3=S`6 zoOX%l)7Ll$)zM|Wp8(0_>?Vw6GWPc+z2S$Gl+p&%;y!OMkbseh7^2_< zT;ZN_*n3y*Ej|+o=M>8dTxao$E&(aG0^YmUnVH_z72APINQYnb*1+oah+ae0@ZF`i zNqYK|u5rD`!3me!KaGab?k!889+ZpyJ`uFodX2qDlw!c+wN#RpwSe0!&0lNlvRIIs zpD3;By59iIIP}#LG4@aG*@xpJsW~C6jfafde$RWZUOSYhLr3OOZ0^=>(DMCg?%lh0 z@7}%te<$Tr%wr=oYHBok&dgWy6pT60$zSwH5kf>!pTA;-%6>qHb_dV9fA+4+uT*ZU zy59xdip8h%R*AiiWg$*nsr<;|)#0-q=z7BeunjF=CV}0)5F&)~gMsh|KQ0a_h8B4a z26>n-Wl;>A_PM?RO2`^E9I}3=-he}Yo_jrpvN4M%x@tek#a;!Tk*fCd573I-J>XDO zsqnf3$av*R4q}bk_e!xoi+iZ+Wh?`5fjNlz$&xp$=x9-2>d2)M;dEHQ4is)Mt2Y{) zO+gc|vBoMKqOL?2G(s>%A1B5^pOe`hPD} z^<19%1|sY^T33!^4wsYz%}G_>4zCFCT(Cx=N_)KOXk0u(;K@;!BU*iC?4SxCCg}~@ zWa@oR)V$LAXtWgRM~*wEZ*c(C@7`>CX_Wbj+Ulzx8rffYHS)6|onp`eYX-5%s5>HSmg&?8_-J$ zjzRs^1NcD5fCASktAw3h!+T3Tf5Y^uX7ld;=+sYhu?9UKtI|@4!i>0`Q+9^lEC9oL z|HAuWtQ|OVS?u+-B<|W<*iOeYmb36=uhN{nz~Hjf=w~tAK*!vnex!x40~aM?{8t`( zrY`w0~e2~xF)su*SUQQi3rXL~(tu2w_w1<9zG zO0-$3Ts&G;5MN_PbMm%Bu>+xp1qXfm_XV@|vqW7n;nMlbccn>FwgBXON&#I=9o`gG zXLQ^ohc5RJaX5qI?Y})Fai@39r)m~J;ai{YO0d*B3c0X8F2U8+=^Xotsi$K6d zBAhE7;SaQoYWa6WU!H1AJ`kTcg4a%PsvC0cwYB+>f8>o2jwSu=zDO4#oIwV)6cToe zVc)wF{`<&F>VRyv9lK+Y7yE_IFwbl>X5&bzk|mB*W0CTB;rVd^pEB>4Ddi#+iN9N^ z-BK?G=;4pYJN>$>$cRFtfigWQ=#AG zm$Ykq)#YuHjqy9)v|Dgn(ZoZw*zB_P22A#<_UOH=*#3&><69azUdW!ni)yH;h(L>% zz>o~Vfu(Dk@SV|2$Rl`1Nq&d^_rhS)-E4%Up&(F}#(7vE1*iMV!6hS5(Gvk=@E~e> z(2o5zoezHQ-aIQCFs06r-*imrN+l#7b&;>){#a^+%IwS;O-sh)`~FZCJ-5@UYQ-P< zyua5y+6Igzg3C_nGRfj4GYMX#fZXd>ll0>z0_weAx)|g5`Sz6!s&APL!}-jSFj}y! zwyBzCr&3swu*^7C;qcf{RZ|q37KBX9K=c;?+=CuJw{bbf`6TI7hxNLb3ZHoJU-GTu zfhYht8==EDG$$c#l{MSFjD0d|4ETak-66}(1`ZhNd58{Hy21i)TRetA;3I)ZG9%`T zJO7;d;s{$cx3}MgX+UG<`9~moUt4zzat5$R5V4h6H=}8dNo<<=jb=pcI#M^mjOdEu zR2N9Cc^_}6+Byim@CI;xsD9{Zj(})=?UiflfR(#I5+Ohvk54tat9pvlHa$L{jOyTa zD(Gk9?HEYYjY6G%HlG;5$|V+$;YM@$u^$dyJ50W?O*4pfHLk26&tyFd8gaDgG|Qvu z<#KS|9VvtI$Tr<3DkVMmDaVZ)Cz=fh=6LBW)}8avk5zt6mhzz%jXAXoZ2bH7T1dUT z>B&&f~CAKVFJga+wsmYdE4{C+^zv8B%z5HQ%ONA=WQ6yglR-x;#9+(;FC33#xY@uj7 zfSNn}k53_USj@nrQSju^EyBK+I{Bh5H;u{t%CSFOM{=$|*?RDZS0`b;OVXh5tXbRf zLBBAN1@_Dk!!gY@yf0+^5JlvBv|<_IHS%=KqZEF2!CR~OGt}HsWX6^g*pFP(iyd&$ z%vifZ7)K7du>x#AT=`VJv$qJnH%XJ;NJ68=yHyfR(haSC)(BI za)Cr-UDC<)c#4tYW$Rl{Tz*qOq6E;jo* zLYM|_gji_W1=@!!v1-?XqZfi3nGdEVj8ED*uGR35YAfUt7r}nFi&3h44xcv9$cz{X cf#jQo6>g2DcWg_F4T+&{=OnD_&u8fW2Q?PhO#lD@ literal 0 Hc-jL100001 -- 2.47.3