[Pkg-openssl-devel] Bug#670581: Bug#670581: openssl: ntpd segfaults with error 4 in libcrypto.so.0.9.8 on Debian squeeze

Andris Kalnozols andris at hpl.hp.com
Tue May 1 06:54:20 UTC 2012


I believe I found the smoking gun by breaking out the call
to EVP_get_digestbynid(crypto_nid) and testing its return
value:

> --- ntp_crypto.c.orig   2009-12-08 23:36:35.000000000 -0800
> +++ ntp_crypto.c        2012-04-30 22:44:46.094602274 -0700
> @@ -197,6 +197,7 @@
>         )
>  {
>         EVP_MD_CTX ctx;         /* message digest context */
> +       const EVP_MD *type;
>         u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
>         keyid_t keyid;          /* key identifer */
>         u_int32 header[10];     /* data in network byte order */
> @@ -229,7 +230,43 @@
>                 hdlen = 10 * sizeof(u_int32);
>                 break;
>         }
> -       EVP_DigestInit(&ctx, EVP_get_digestbynid(crypto_nid));
> +       if ((type = EVP_get_digestbynid(crypto_nid)) == NULL)
> +               msyslog(LOG_ERR, "EVP_get_digestbynid(KEY_TYPE_MD5) "
> +                                "returned NULL");
> +       EVP_DigestInit(&ctx, type);
>         EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
>         EVP_DigestFinal(&ctx, dgst, &len);
>         memcpy(&keyid, dgst, 4);

Sure enough, this routine returns NULL before the program segfaults.
A web search led me to this:
   > 
http://stackoverflow.com/questions/6762054/evp-get-digestbyname-what-is-this

Indeed, the Debian man page for evp_get_digestbynid(3) has this 
important information:

> EVP_get_digestbyname(), EVP_get_digestbynid() and EVP_get_digestbyobj() return
 > an EVP_MD structure when passed a digest name, a digest NID or an 
ASN1_OBJECT
 > structure respectively. The digest table must be initialized using, 
for example,
 > OpenSSL_add_all_digests() for these functions to work.

My search of the NTP source code for references to
"OpenSSL_add_all_*" showed the following two locations:

libntp/ssl_init.c:
------------------

> #ifdef OPENSSL
> #include "openssl/err.h"
> #include "openssl/rand.h"
>
>
> int ssl_init_done;
>
> void
> ssl_init(void)
> {
>         if (ssl_init_done)
>                 return;
>
>         ERR_load_crypto_strings();
>         OpenSSL_add_all_algorithms();
>
>         ssl_init_done = 1;
> }
>
>
> void
> ssl_check_version(void)
> {
>         INIT_SSL();
> }
> #endif  /* OPENSSL */

include/ntp_stdlib.h:
---------------------

> /* ssl_init.c */
> #ifdef OPENSSL
> extern  void    ssl_init                (void);
> extern  void    ssl_check_version       (void);
> extern  int     ssl_init_done;
> #define INIT_SSL()                              \
>         do {                                    \
>                 if (!ssl_init_done)             \
>                         ssl_init();             \
>         } while (0)
> #else   /* !OPENSSL follows */
> #define INIT_SSL()              do {} while (0)
> #endif

However, I can't find where the ntpd program ever calls ssl_init()
or the INIT_SSL() macro.  So I'm betting that this problem will go
away once I find the proper place to call this important routine.

Perhaps you can keep this ticket open until I can confirm my hunch.
It shouldn't take too long.

Thanks,
Andris







More information about the Pkg-openssl-devel mailing list