OpenSSL中的内存泄漏? [英] Memory leak in OpenSSL?

查看:111
本文介绍了OpenSSL中的内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下代码检查签名.为简单起见,公钥,消息和签名在main中初始化.

I use the following code to check a signature. For simplicity public key, message and signature are initialized in main.

#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>

int main(){
    const unsigned char key[] = "-----BEGIN PUBLIC KEY-----\n"
                "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALulMfYFyX1kSm7oUxZyCWWhrBBcWrRA\n"
                "V7LSz1PzMPxoxG3KS8H7PRKFkIk42yM8/vhobmcCmj7UM5572wWch50CAwEAAQ==\n"
                "-----END PUBLIC KEY-----\n";
    unsigned int key_len = sizeof(key);

    const unsigned char data[] = {0x6d,0x65,0x73,0x65,0x0a};
    unsigned int data_len = sizeof(data);

    const unsigned char sig[] = {0xa9,0x29,0x81,0x07,0x8c,0xeb,0xf0,0x1b,0x2a,0x31,0xe5,0x60,0x94,0x8a,0x47,0x94,0x3a,0x8f,0x6b,
                0x4e,0x85,0xb9,0xe7,0xe5,0x4a,0x6c,0x56,0x46,0xd1,0x80,0x15,0x57,0xce,0xcb,0x0a,0x3a,0x67,0x15,0xed,
                0x68,0x03,0x58,0x99,0xa4,0x73,0x61,0xe3,0x30,0x85,0xff,0x89,0x7e,0x32,0xef,0x16,0xec,0x23,0x7f,0x14,
                0xde,0xbf,0x53,0xe0,0x3a};
    unsigned int sig_len = sizeof(sig);


    EVP_PKEY* evp_pubkey = EVP_PKEY_new();
        RSA* rsa_pubkey = NULL;
    EVP_MD_CTX ctx;

    BIO* bufio = BIO_new_mem_buf((void*)key, key_len);
    if(bufio == NULL){  
        fprintf(stderr, "BIO not created.\n");
        EVP_PKEY_free(evp_pubkey);
        BIO_free(bufio);
        return 3;
    }

    evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
    if(evp_pubkey == NULL){ 
        fprintf(stderr, "evp_pubkey not created.\n");
        EVP_PKEY_free(evp_pubkey);
        BIO_free(bufio);
        return 4;
    }

    EVP_MD_CTX_init(&ctx);  

    if (!EVP_VerifyInit(&ctx, EVP_sha256())) {
            fprintf(stderr, "EVP_SignInit: failed.\n");
            EVP_PKEY_free(evp_pubkey);
            BIO_free(bufio);
            return 5;
        }

        if (!EVP_VerifyUpdate(&ctx, data, data_len)) {
                fprintf(stderr, "EVP_SignUpdate: failed.\n");
                EVP_PKEY_free(evp_pubkey);
                BIO_free(bufio);
                return 6;
        }

        if (!EVP_VerifyFinal(&ctx, sig, sig_len, evp_pubkey)) {
            fprintf(stderr, "EVP_VerifyFinal: failed.\n");
            EVP_PKEY_free(evp_pubkey);
            BIO_free(bufio);
            return 7;
        }

        EVP_PKEY_free(evp_pubkey);
        BIO_free(bufio);

        return 0;
}

使用gcc evp.c -lssl -lcrypto编译并在其上运行valgrind --tool=memcheck --leak-check=full ./a.out后,我遇到了一些内存泄漏:

After compiling with gcc evp.c -lssl -lcrypto and running valgrind --tool=memcheck --leak-check=full ./a.out on it I get some memory leaks:

==7492== 56 bytes in 1 blocks are definitely lost in loss record 9 of 12
==7492==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7492==    by 0x4E9AD77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492==    by 0x4F5D459: EVP_PKEY_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492==    by 0x400C4C: main (in a.out)
==7492== 
==7492== 120 bytes in 1 blocks are definitely lost in loss record 10 of 12
==7492==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7492==    by 0x4E9AD77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492==    by 0x4F55678: EVP_DigestInit_ex (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492==    by 0x400D6A: main (in a.out)

我做错什么了吗?

推荐答案

  1. @ iharob 您使用了EVP_MD_CTX_init(),但没有释放使用EVP_MD_CTX_cleanup(&ctx)或-根据您的openssl版本-EVP_MD_CTX_free(&ctx)分配的数据.

    You used EVP_MD_CTX_init() but did not free the data it allocated using EVP_MD_CTX_cleanup(&ctx) or - depending on your openssl version - EVP_MD_CTX_free(&ctx).

    如果您使用调试信息进行编译(在gcc/clang中使用-g),则 valgrind 会向您显示造成泄漏的源代码行.

    And if you compile with debug info (using -g in gcc/clang) valgrind would show you the source code lines responsible for the leaks.

    您也可以使用EVP_MD_CTX_create()代替静态的EVP_MD_CTX.

    You could also use EVP_MD_CTX_create() instead of using a static EVP_MD_CTX.

    这是更新的代码:

    #include <openssl/sha.h>
    #include <openssl/rsa.h>
    #include <openssl/pem.h>
    #include <openssl/evp.h>
    
    int main() {
        const unsigned char key[] =
                "-----BEGIN PUBLIC KEY-----\n"
                "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALulMfYFyX1kSm7oUxZyCWWhrBBcWrRA\n"
                "V7LSz1PzMPxoxG3KS8H7PRKFkIk42yM8/vhobmcCmj7UM5572wWch50CAwEAAQ==\n"
                "-----END PUBLIC KEY-----\n";
        unsigned int key_len = sizeof(key) - 1;
    
        const unsigned char data[] = { 0x6d,0x65,0x73,0x65,0x0a };
        unsigned int data_len = sizeof(data);
    
        const unsigned char sig[] = {
                0xa9,0x29,0x81,0x07,0x8c,0xeb,0xf0,0x1b,0x2a,0x31,0xe5,0x60,
                0x94,0x8a,0x47,0x94,0x3a,0x8f,0x6b,0x4e,0x85,0xb8,0xe7,0xe5,
                0x4a,0x6c,0x56,0x46,0xd1,0x80,0x15,0x57,0xce,0xcb,0x0a,0x3a,
                0x67,0x15,0xed,0x68,0x03,0x58,0x99,0xa4,0x73,0x61,0xe3,0x30,
                0x85,0xff,0x89,0x7e,0x32,0xef,0x16,0xec,0x23,0x7f,0x14,0xde,
                0xbf,0x53,0xe0,0x3a
        };
        unsigned int sig_len = sizeof(sig);
    
        int ret = 0;
    
        EVP_PKEY* evp_pubkey = NULL;
        RSA* rsa_pubkey = NULL;
        EVP_MD_CTX* evp_ctx;
        BIO* bufio = NULL;
    
        if (!(bufio = BIO_new_mem_buf((void*)key, key_len))) {
                fprintf(stderr, "BIO not created.\n");
                ret = 1;
                goto out;
        }
    
        if (!(evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL))) {
                fprintf(stderr, "evp_pubkey not created.\n");
                ret = 2;
                goto out;
        }
    
        if (!(evp_ctx = EVP_MD_CTX_create())) {
                fprintf(stderr, "ctx not created.\n");
                ret = 3;
                goto out;
        }
    
        if (!EVP_VerifyInit(evp_ctx, EVP_sha256())) {
                fprintf(stderr, "EVP_SignInit: failed.\n");
                ret = 4;
                goto out;
        }
    
        if (!EVP_VerifyUpdate(evp_ctx, data, data_len)) {
                fprintf(stderr, "EVP_SignUpdate: failed.\n");
                ret = 5;
                goto out;
        }
    
        if (!EVP_VerifyFinal(evp_ctx, sig, sig_len, evp_pubkey)) {
                fprintf(stderr, "EVP_VerifyFinal: failed.\n");
                ret = 6;
                goto out;
        }
    
    out:
        if (evp_ctx)
                EVP_MD_CTX_destroy(evp_ctx);
    
        if (evp_pubkey)
                EVP_PKEY_free(evp_pubkey);
    
        if (bufio)
                BIO_free(bufio);
    
        return 0;
    }
    

    这篇关于OpenSSL中的内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆