Subject: Re: [libssh2] #229: static const EVP_CIPHER * make_ctr_evp (size_t keylen) in openssl.c not threadsafe

Re: [libssh2] #229: static const EVP_CIPHER * make_ctr_evp (size_t keylen) in openssl.c not threadsafe

From: libssh2 Trac <trac_at_libssh2.stuge.se>
Date: Thu, 29 Sep 2011 18:38:57 -0000

#229: static const EVP_CIPHER * make_ctr_evp (size_t keylen) in openssl.c
not threadsafe
-----------------------+----------------------
  Reporter: engstrom | Owner: bagder
      Type: defect | Status: assigned
  Priority: normal | Milestone: 1.2.9
 Component: API | Version: 1.3.0
Resolution: | Keywords:
Blocked By: | Blocks:
-----------------------+----------------------

Comment (by engstrom):

 Replying to [comment:6 bagder]:
> Right. Can't we just remove memset()? It serves no purpose...

 the EVP_CIPHER structure contains 13 members and 6 of them (block_size,
 key_len, iv_len, init, do_cipher and cleanup) are being explicitly set.
 The memset() takes care of initializing the other 7 members so it's
 important.

 How about this solution - create three static global structures in
 openssl.c along with a function to initialize those structures (e.g.):

 {{{
 #!c
 static EVP_CIPHER aes_ctr_cipher16;
 static EVP_CIPHER aes_ctr_cipher24;
 static EVP_CIPHER aes_ctr_cipher32;

 void
 _libssh2_init_EVP_aes_ctr(void)
 {
     memset(&aes_ctr_cipher16, 0, sizeof(aes_ctr_cipher16));
     aes_ctr_cipher16.block_size = 16;
     aes_ctr_cipher16.key_len = 16;
     aes_ctr_cipher16.iv_len = 16;
     aes_ctr_cipher16.init = aes_ctr_init;
     aes_ctr_cipher16.do_cipher = aes_ctr_do_cipher;
     aes_ctr_cipher16.cleanup = aes_ctr_cleanup;

     memset(&aes_ctr_cipher24, 0, sizeof(aes_ctr_cipher24));
     aes_ctr_cipher24.block_size = 16;
     aes_ctr_cipher24.key_len = 24;
     aes_ctr_cipher24.iv_len = 16;
     aes_ctr_cipher24.init = aes_ctr_init;
     aes_ctr_cipher24.do_cipher = aes_ctr_do_cipher;
     aes_ctr_cipher24.cleanup = aes_ctr_cleanup;

     memset(&aes_ctr_cipher32, 0, sizeof(aes_ctr_cipher32));
     aes_ctr_cipher32.block_size = 16;
     aes_ctr_cipher32.key_len = 32;
     aes_ctr_cipher32.iv_len = 16;
     aes_ctr_cipher32.init = aes_ctr_init;
     aes_ctr_cipher32.do_cipher = aes_ctr_do_cipher;
     aes_ctr_cipher32.cleanup = aes_ctr_cleanup;
 }
 }}}

 Then change the _libssh2_EVP_aes_XXX_ctr() functions to return the address
 of the appropriate structure:

 {{{
 #!c
 const EVP_CIPHER *
 _libssh2_EVP_aes_128_ctr(void)
 {
     return &aes_ctr_cipher16;
 }

 const EVP_CIPHER *
 _libssh2_EVP_aes_192_ctr(void)
 {
     return &aes_ctr_cipher24;
 }

 const EVP_CIPHER *
 _libssh2_EVP_aes_256_ctr(void)
 {
     return &aes_ctr_cipher32;
 }
 }}}

 Then, in openssl.h you can add the prototype for the init function:

 {{{
 #!c
 void _libssh2_init_EVP_aes_ctr(void);
 }}}

 Then in global.c add the following code so that if OpenSSL is used instead
 of libgcrypt the EVP_CIPHER structures get initialized:

 {{{
 #!c
 static void
 _libssh2_init_cipher_structures(void)
 {
 #ifndef LIBSSH2_LIBGCRYPT /* only need to initialize the cipher structures
 if we build with OpenSSL */
 #include "openssl.h"
  _libssh2_init_EVP_aes_ctr();
 #else
   /* No need to initialize any structures if using libgcrypt */
 #endif
 }
 }}}

 Finally in global.c add the call to _libssh2_init_cipher_structures() in
 the libssh2_init() function which should only be called once and therefore
 won't result in one thread changing the value of a structure member right
 before another thread dereferences that structure member:

 {{{
 #!c
 LIBSSH2_API int
 libssh2_init(int flags)
 {
     if (_libssh2_initialized == 0 && !(flags & LIBSSH2_INIT_NO_CRYPTO)) {
         libssh2_crypto_init();
         _libssh2_init_cipher_structures();
     }

     _libssh2_initialized++;
     _libssh2_init_flags |= flags;

     return 0;
 }
 }}}

-- 
Ticket URL: <http://trac.libssh2.org/ticket/229#comment:8>
libssh2 <http://trac.libssh2.org/>
C library for writing portable SSH2 clients
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2011-09-29