#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-develReceived on 2011-09-29