天天看点

openssl的互斥回调机制

很不幸,openssl的底层实现不是线程安全的,虽然我可以通过我自己实现的锁来安全的在不同的线程中使用同一个 ssl连接,也就是一个ssl指针可以在多个线程中共用,但是我们能看到的最底层也就是这个SSL类型的指针了,这也是我们可以保护的最底层了,再往下的 层次中该如何实现线程互斥呢?大致看了一下openssl的代码,发现在底层加密的时候用到了很多的共享的数据结构或者共享变量,如此一来,虽然比较上层 的SSL指针可以很好的被保护,但是一旦两个线程同时读写而同时调用加密解密函数的话会很显然的用到那些共享变量和共享数据结构,如此一来就很容易出错, 比如我遇到的就是本来要SSL_read出100个字节的数据,可是可能由于SSL_write此时修改了数据结构,我的程序异常崩溃,分析dmp文件发 现是由于s3_read_bytes中将读取数据的长度填充成了0xedffffff,危险啊! 

可是怎么解决这个问题呢?总要有解决的办法啊,是的,有办法,openssl提供了几个接口函数用于设置一些回调函数,在openssl本身它也自带了一 个,在th-lock.c中实现。这两个接口函数是:void CRYPTO_set_locking_callback(void (*func)(int mode,int type, const char *file,int line))设置加锁解锁回调函数;void CRYPTO_set_id_callback(unsigned long (*func)(void))设置得到线程id回调函数。其中我觉得第一个非常有创意,将如何加锁和解锁留给用户自己去实现,这就在库的底层将机制和用户 的策略分离中出来,并且底层可以保持一份平台无关的加密和解密代码,各个不同的操作系统平台可以提供自己实现的加锁和解锁回调函数,并且如果用户只是跑单 线程,那么加锁和解锁会带来很大不必要的开销,于是对共享数据的保护就成了可选的选择了,总之,策略不会污染机制,一切分得很清!对于上面的接口设置的回 调函数,在windows平台就是: 

void win32_locking_callback(int mode, int type, char *file, int line) 

 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1273969

继续阅读