由于RSA_generate_key
提供了进度回调,您可以longjmp
退出它来终止函数。通过一些额外的代码,您可以创建一个RSA_generate_key
接受通用测试函数的包装器,该函数可用于检查超时或窗口系统设置的标志。
#include <openssl/rsa.h>
#include <stdbool.h>
#include <setjmp.h>
struct trampoline_ctx {
bool (*testfn)(void *);
void *testfn_arg;
jmp_buf env;
};
static void trampoline(int ignore1, int ignore2, void *arg)
{
struct trampoline_ctx *ctx = arg;
if (!ctx->testfn(ctx->testfn_arg))
longjmp(ctx->env, 1);
}
// like RSA_generate_key, but accepts a test function. If testfn returns
// false, key generation is terminated and NULL is returned.
RSA *
my_generate_key(int num, unsigned long e,
bool (*testfn)(void *), void *testfn_arg)
{
struct trampoline_ctx ctx;
ctx.testfn = testfn;
ctx.testfn_arg = testfn_arg;
if (setjmp(ctx.env))
return NULL;
return RSA_generate_key(num, e, trampoline, &ctx);
}
longjmp
正如C89 和 C99 所要求的那样,这种方法具有惊人的可移植性。它的缺点是,如果您要使用 longjmping 的函数动态分配资源,它可能会泄漏资源。然而,在实践中,如果不经常进行或仅在明确的用户请求下进行,泄漏可能足够小以至于不引人注意。肯定是这种情况,在紧密循环中运行代码并观察进程的资源消耗。
这是上述功能的测试程序:
#include <stdio.h>
#include <sys/time.h>
double now()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + (double) tv.tv_usec / 1e6;
}
struct tt_ctx {
double start;
double limit;
};
bool test_time_limit(void *arg)
{
struct tt_ctx *ctx = arg;
return now() - ctx->start <= ctx->limit;
}
int main(int argc, char **argv)
{
int limit = atoi(argv[1]);
struct tt_ctx ctx;
ctx.start = now();
ctx.limit = limit / 1000.0;
RSA *key = my_generate_key(4096, 65537, test_time_limit, &ctx);
printf("%p\n", key);
return 0;
}
测试程序假定为 POSIX gettimeofday
,但可以轻松转换为系统提供的另一个高分辨率时钟。测试程序如下:
将两段代码附加到文件中并使用-lrsa
. 测试程序将在命令行上以毫秒为单位指定的时间限制内生成一个 4096 位的 RSA 密钥。在所有情况下,它都会打印结果RSA *
指针以指示my_generate_key
其请求是否已完成或已中止。伴随执行的输出time
作为健全性检查以验证是否遵守时间限制:
# try with a 10ms limit
$ time ./a.out 10
(nil) # too short
./a.out 10 0.02s user 0.00s system 85% cpu 0.023 total
# see if 100ms is enough time
$ time ./a.out 100
(nil) # still too short
./a.out 100 0.10s user 0.00s system 97% cpu 0.106 total
# try with 1 whole second:
$ time ./a.out 1000
0x2369010 # success!
./a.out 1000 0.64s user 0.00s system 99% cpu 0.649 total