Re: [External] : Re: BIO_read() crash

2022-12-06 Thread Tomas Mraz
On Mon, 2022-12-05 at 16:14 -0800, Benjamin Kaduk via openssl-users
wrote:
> On Mon, Dec 05, 2022 at 11:31:18AM -0800, Thomas Dwyer III wrote:
> > Why does EVP_get_digestbyname("md4") return non-NULL if the legacy
> > provider
> > isn't loaded? Similarly, why does it return non-NULL for "md5"
> > after doing
> > EVP_set_default_properties(NULL, "fips=yes")? This seems
> > unintuitive. Legacy
> > code that does not know about EVP_MD_fetch() checks the return
> > value of
> > EVP_get_digestbyname(). Isn't that where the error should be
> > detected? Why
> > let it get all the way to BIO_set_md() (or EVP_DigestInit() or
> > whatever)
> > before the error is detected?
> 
> To do so would introduce a time-of-check/time-of-use race, as the set
> of
> providers available may change in the intervening period.

Not just that. IMO the primary motivation was to keep the digests (and
similarly ciphers) returned by the EVP_md4() (and similar) or
EVP_get_digestbyname() calls still constant. I.e., they would not
change based on the providers involved, etc. This implied the implicit
fetching done inside the EVP_DigestInit() and similar init routines.

As any correct code required checking result of EVP_DigestInit() and
thus also the result of BIO_set_md(), it was the least of all evils in
how to implement these legacy EVP_MD functions returning constant
EVP_MDs.
-- 
Tomáš Mráz, OpenSSL



Re: [External] : Re: BIO_read() crash

2022-12-05 Thread Benjamin Kaduk via openssl-users
On Mon, Dec 05, 2022 at 11:31:18AM -0800, Thomas Dwyer III wrote:
> Why does EVP_get_digestbyname("md4") return non-NULL if the legacy provider
> isn't loaded? Similarly, why does it return non-NULL for "md5" after doing
> EVP_set_default_properties(NULL, "fips=yes")? This seems unintuitive. Legacy
> code that does not know about EVP_MD_fetch() checks the return value of
> EVP_get_digestbyname(). Isn't that where the error should be detected? Why
> let it get all the way to BIO_set_md() (or EVP_DigestInit() or whatever)
> before the error is detected?

To do so would introduce a time-of-check/time-of-use race, as the set of
providers available may change in the intervening period.

-Ben


Re: [External] : Re: BIO_read() crash

2022-12-05 Thread Thomas Dwyer III
Why does EVP_get_digestbyname("md4") return non-NULL if the legacy 
provider isn't loaded? Similarly, why does it return non-NULL for "md5" 
after doing EVP_set_default_properties(NULL, "fips=yes")? This seems 
unintuitive. Legacy code that does not know about EVP_MD_fetch() checks 
the return value of EVP_get_digestbyname(). Isn't that where the error 
should be detected? Why let it get all the way to BIO_set_md() (or 
EVP_DigestInit() or whatever) before the error is detected?



Tom.III


||
On 12/5/22 02:24, Tomas Mraz wrote:

Hi,

there is an error in your code - see my comment below.


On Mon, 2022-12-05 at 08:45 +, Zhongyan Wang wrote:
...

     md = EVP_get_digestbyname(dgst);
     if (!md) {
     printf("Error EVP_get_digestbyname %s\n", dgst);
     goto err_exit;
     }
  
     in = BIO_new_file(datain, "rb");

     if (!in) {
     printf("Error BIO_new_file %s\n", datain);
     goto err_exit;
     }
  
     out = BIO_new(BIO_s_mem());

     if (!out) {
     printf("Error BIO_new out\n");
     goto err_exit;
     }
  
     rbio = in;
  
     bmd = BIO_new(BIO_f_md());

     if (!bmd){
     printf("Error BIO_new bmd\n");
     goto err_exit;
     }
  
     BIO_set_md(bmd, md);

You do not check the return value here. This call will return <= 0
return value in case the legacy provider is not loaded.





Re: BIO_read() crash

2022-12-05 Thread Tomas Mraz
Hi,

there is an error in your code - see my comment below.


On Mon, 2022-12-05 at 08:45 +, Zhongyan Wang wrote:
...
>     md = EVP_get_digestbyname(dgst);
>     if (!md) {
>     printf("Error EVP_get_digestbyname %s\n", dgst);
>     goto err_exit;
>     }
>  
>     in = BIO_new_file(datain, "rb");
>     if (!in) {
>     printf("Error BIO_new_file %s\n", datain);
>     goto err_exit;
>     }
>  
>     out = BIO_new(BIO_s_mem());
>     if (!out) {
>     printf("Error BIO_new out\n");
>     goto err_exit;
>     }
>  
>     rbio = in;
>  
>     bmd = BIO_new(BIO_f_md());
>     if (!bmd){
>     printf("Error BIO_new bmd\n");
>     goto err_exit;
>     }
>  
>     BIO_set_md(bmd, md);

You do not check the return value here. This call will return <= 0
return value in case the legacy provider is not loaded.



-- 
Tomáš Mráz, OpenSSL



BIO_read() crash

2022-12-05 Thread Zhongyan Wang
Hi team,
I find a segment fault in BIO_read() on openssl 3.0 about calculate digest with 
BIO using md4 algorithm.
This is my test code, put it in a.c, build & run, it will crash.
If don't load legacy provider:

  1.  Set dgst  = "md4", EVP_get_digestbyname(dgst) won't return NULL, but a 
non-NULL object. If use EVP_MD_fetch(NULL, dgst, NULL) instead, it will return 
NULL.
  2.  When call BIO_read(), this program crashes.
If load legacy provider, this program works ok.



#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main() {
EVP_MD *md = NULL;
const char *datain = "a.c";
const int BUF_SIZE = 8192;
char *buff = NULL;
char *ptr = NULL;
const char *dgst = "md4";
int ret = 0, len = 0, i = 0;
BIO *in = NULL, *out = NULL, *bmd = NULL, *rbio = NULL, *err;

if ((err = BIO_new(BIO_s_file())) != NULL)
BIO_set_fp(err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);

md = EVP_get_digestbyname(dgst);
if (!md) {
printf("Error EVP_get_digestbyname %s\n", dgst);
goto err_exit;
}

in = BIO_new_file(datain, "rb");
if (!in) {
printf("Error BIO_new_file %s\n", datain);
goto err_exit;
}

out = BIO_new(BIO_s_mem());
if (!out) {
printf("Error BIO_new out\n");
goto err_exit;
}

rbio = in;

bmd = BIO_new(BIO_f_md());
if (!bmd){
printf("Error BIO_new bmd\n");
goto err_exit;
}

BIO_set_md(bmd, md);

rbio = BIO_push(bmd, rbio);

buff = (char *)malloc(BUF_SIZE);
if (!buff) {
printf("Error malloc\n");
goto err_exit;
}

for (;;) {
ret = BIO_read(rbio, buff, BUF_SIZE); /* this call will segment fault */
if (ret <= 0) break;
}

len = BIO_gets(rbio, buff, BUF_SIZE);

len = BIO_write(out, buff, len);

if (!BIO_flush(out)) {
printf("Error BIO_flush\n");
goto err_exit;
}

len = BIO_get_mem_data(out, );
printf("digest success, len=%d\n", len);
for (i = 0; i < len; i++)
printf("%d ", ptr[i]);
printf("\n");

err_exit:
ERR_print_errors(err);
if (in)
BIO_free(in);
if (out)
BIO_free_all(out);
if (err)
BIO_free(err);
if (bmd)
BIO_free(bmd);
if (buff)
free(buff);
if (md)
EVP_MD_free(md);
ERR_clear_error();
return 0;
}
-


Rocket Software, Inc. and subsidiaries ? 77 Fourth Avenue, Waltham MA 02451 ? 
Main Office Toll Free Number: +1 855.577.4323
Contact Customer Support: 
https://my.rocketsoftware.com/RocketCommunity/RCEmailSupport
Unsubscribe from Marketing Messages/Manage Your Subscription Preferences - 
http://www.rocketsoftware.com/manage-your-email-preferences
Privacy Policy - http://www.rocketsoftware.com/company/legal/privacy-policy


This communication and any attachments may contain confidential information of 
Rocket Software, Inc. All unauthorized use, disclosure or distribution is 
prohibited. If you are not the intended recipient, please notify Rocket 
Software immediately and destroy all copies of this communication. Thank you.