(抱歉,这很冗长)我正在尝试将 OpenSSL 支持添加到用 Objective C for OS X 10.6(Snow Leopard)编写的 Cocoa 应用程序中。为了简化问题,我有一个小型包装类,它包含各种 BIO 和密码上下文结构,AETOpenSSLWrapper。如下所示
。H
@interface AETOpenSSLWrapper: public NSObject
{
BIO *writeBIO,encBIO;
EVP_CIPHER_CTX *ctx;
unsigned char *readWriteBuff;
}
@property (readwrite,assign) BIO *writeBIO,*encBIO;
@property (readwrite,assign) EVP_CIPHER_CTX *ctx;
@property (readwrite,assign) unsigned char *readWriteBuff;
-(id)init;
...
-(void)dealloc;
@end
.m
@implementation AETOpenSSLWrapper
@synthesize writeBIO,encBIO,ctx,readWriteBuff;
-(id)init
{
self=[super init];
if(self)
{
writeBIO=BIO_new(BIO_s_file());
encBIO=...
ctx=...
buff=...
(error handling omitted)
}
return self;
}
@end
然后各种实用方法链接 BIO,写入输出 BIO,刷新等,特别是一个 -(void)pushEncryptingBIO 链接加密过滤器 BIO(已使用密钥、盐和初始向量初始化)
-(void)pushEncryptingBIO
{
writeBIO=BIO_push(encBIO,writeBIO);
}
最后是我的 dealloc 例程。这是直接从openssl-1.0.1c 发行版提供的enc程序中提取的
-(void)dealloc
{
if(readWriteBuff!=NULL)
OPENSSL_free(readWriteBuff);
if(writeBIO!=NULL)
BIO_free_all(writeBIO);
if(encBIO!=NULL) <----------- this looks wrong
BIO_free(encBIO); <---+
[super dealloc];
}
等效代码位于加密输入缓冲区的循环之前以及 openssl 源代码树中 apps/enc.c 中的 MAIN() 例程的末尾:
第 657 - 658 行
if (benc != NULL)
wbio=BIO_push(benc,wbio);
和第 682 - 688 行
end:
ERR_print_errors(bio_err);
if (strbuf != NULL) OPENSSL_free(strbuf);
if (buff != NULL) OPENSSL_free(buff);
if (in != NULL) BIO_free(in);
if (out != NULL) BIO_free_all(out);
if (benc != NULL) BIO_free(benc); <--- are we sure about this?
问题是(最后):由于 BIO 被推送到链上,该调用BIO_free(benc)
(或在我的代码中)是否应该存在,该链被释放?查看 的实现,它只是沿着 BIO 链运行,递减 ref 计数并在执行过程中释放,并且不会将指针清空。这看起来一定是一个错误,但显然我不愿意假设 SSL 维护人员错过了这一点,而我没有。如果我留下电话,我偶尔会遇到崩溃(十分之一),如果我不这样做,我不会,但我不想要泄漏。这是在 Apple 事件处理程序中,因此调试更加复杂。有什么建议么?BIO_free(encBIO)
writeBIO/out
BIO_free_all
BIO_free_all
BIO_free(encBIO)