首页 文章

具有直接呼叫和间接呼叫的Openssl线程安全回调函数注册

提问于
浏览
2

我正在Linux中编写一个C库(比方说,libA),它利用Openssl来执行base64编解码器,哈希等 . 其他一些项目(例如projB)利用libA来做某事,而这些项目本身也调用了Openssl API . 因此,projB以两种方式调用Openssl API:

直接调用Openssl API:projB - > Openssl间接调用Openssl API:projB - > libA - > Openssl

同时,除非在Openssl中注册了至少两个回调函数,否则Openssl不是线程安全的officially announced

void ssl_locking_function(int mode,int n,const char * file,int line)unsigned long ssl_threadid_function()

libA向projB公开以下API:

int InitA(void)int ActionStuff()void DestroyA()

为了确保Openssl的线程安全,有两种解决方案:

#1 . libA在InitA()#2中将回调函数注册到Openssl中 . 在调用libA API之前,projB在初始化时将回调函数注册到Openssl中,而libA不进行回调注册

对于解决方案#1,libA本身是线程安全的,关于调用Openssl API . 但是,projB还必须确保其线程安全性,并且它将采取类似的操作将回调函数注册到Openssl中 .

假设libA注册以下回调函数

void ssl_locking_function_A(int mode,int n,const char * file,int line)unsigned long ssl_threadid_function_A()

和projB注册这些

void ssl_locking_function_B(int mode,int n,const char * file,int line)unsigned long ssl_threadid_function_B()

据我所知,libA的回调函数是在projB之后注册的,最终,projB的回调函数被libA的阴影所掩盖:

projB初始化projB将ssl_locking_function_B()和ssl_threadid_function_B()注册到Openssl projB调用InitA()libA将ssl_locking_function_A()和ssl_threadid_function_A()注册到Openssl projB调用ActionStuff()... projB调用DestroyA()projB uninitialization

我的问题是,哪种解决方案更好,#1还是#2?有没有更好的解决方案?

1 回答

  • 3

    它正式宣布Openssl不是线程安全的,除非在Openssl中注册了至少两个回调函数:

    叉安全和信号安全性更差 . 例如,请参阅Random Fork SafetyLibcrypto Fork Safety .


    为了确保Openssl的线程安全,有两种解决方案:

    我相信还有第三个.... OpenSSL提供了一个名为 OPENSSL_THREADS 的定义 . 如果定义了 OPENSSL_THREADS ,则使用线程支持构建OpenSSL . 请务必包含 <openssl/opensslconf.h> 以获得准确的结果 .

    LibALibB 初始化期间,如果需要,任一库都应安装锁 . 我相信你可以检查 CRYPTO_THREADID_get_callback ,如果它是null,那么你应该初始化锁 . 您还应该包含一个状态变量,以便在关闭时清理资源 .

    实际上,你真的想知道 lock_cslock_cs 的状态 . 那是's where the lock array is held. But its static so you can' t .


    我的问题是,哪种解决方案更好,#1还是#2?有没有更好的解决方案?

    在实践中,您可能会发现这些库没有做任何事情,并且使用库将它留给开发人员(尽管可能有比赛) . RTFM是最好的 .

    最安全的解决方案可能是:(1)如果OpenSSL支持线程,(2)你的库需要线程,(3)没有安装线程锁,那么在初始化期间安装锁 .

相关问题