error: aggregate ‘HMAC_CTX ctx’ has incomplete type and cannot be defined

error: aggregate ‘HMAC_CTX ctx’ has incomplete type and cannot be defined

我在编译我的应用程序时试图了解出了什么问题,但出现了以下错误:

security.cpp: In member function ‘void Crypt::load()’:
security.cpp:16:21: warning: ‘void OPENSSL_config(const char*)’ is deprecated [-Wdeprecated-declarations]
  OPENSSL_config(NULL);
                     ^
In file included from /usr/local/include/openssl/e_os2.h:13:0,
                 from /usr/local/include/openssl/bio.h:13,
                 from /usr/local/include/openssl/conf.h:13,
                 from security.h:5,
                 from security.cpp:1:
/usr/local/include/openssl/conf.h:91:25: note: declared here
 DEPRECATEDIN_1_1_0(void OPENSSL_config(const char *config_name))
                         ^
security.cpp: In member function ‘void Integrity::get_hmac(uint8_t*, int, uint8_t*, uint64_t)’:
security.cpp:112:11: error: aggregate ‘HMAC_CTX ctx’ has incomplete type and cannot be defined
  HMAC_CTX ctx;
           ^~~
security.cpp:115:2: error: ‘HMAC_CTX_init’ was not declared in this scope
  HMAC_CTX_init(&ctx);
  ^~~~~~~~~~~~~
security.cpp:115:2: note: suggested alternative: ‘HMAC_CTX_new’
  HMAC_CTX_init(&ctx);
  ^~~~~~~~~~~~~
  HMAC_CTX_new
security.cpp:119:2: error: ‘HMAC_CTX_cleanup’ was not declared in this scope
  HMAC_CTX_cleanup(&ctx);
  ^~~~~~~~~~~~~~~~
security.cpp:119:2: note: suggested alternative: ‘HMAC_CTX_get_md’
  HMAC_CTX_cleanup(&ctx);
  ^~~~~~~~~~~~~~~~
  HMAC_CTX_get_md
Makefile:25: recipe for target 'security.o' failed
make: *** [security.o] Error 1

我的 cpp 文件的一些代码部分:

security.cpp:

Crypt g_crypt;
Integrity g_integrity;

Crypt::Crypt() {
        key = (uint8_t *)"01234567890123456789012345678901";
        iv = (uint8_t *)"01234567890123456";
        load();
}

void Crypt::load() {    
        ERR_load_crypto_strings();
        OpenSSL_add_all_algorithms();
        OPENSSL_config(NULL);
}

......
......
......
......
void Integrity::get_hmac(uint8_t *data, int data_len, uint8_t *hmac, uint64_t k_nas_int) {
        HMAC_CTX ctx;
        int res_len;

        HMAC_CTX_init(&ctx);
        HMAC_Init_ex(&ctx, key, strlen((const char*)key), EVP_sha1(), NULL);
        HMAC_Update(&ctx, data, data_len);
        HMAC_Final(&ctx, hmac, (unsigned int*)&res_len);
        HMAC_CTX_cleanup(&ctx);
}

security.h:

#ifndef SECURITY_H
#define SECURITY_H

/* (C) OPENSSL_config */
#include </usr/local/include/openssl/conf.h>

/* (C) EVP_* */
#include </usr/local/include/openssl/evp.h>

/* (C) ERR_* */
#include </usr/local/include/openssl/err.h>

/* (C) HMAC_* */
#include </usr/local/include/openssl/hmac.h>

#include "packet.h"
#include "utils.h"

#define HMAC_ON 1
#define ENC_ON 1

const int HMAC_LEN = 20;

class Crypt {
private:
        uint8_t *key;
        uint8_t *iv;

        void load();
        int enc_data(uint8_t*, int, uint8_t*, uint64_t);
        int dec_data(uint8_t*, int, uint8_t*, uint64_t);
        void handle_crypt_error();

public:
        Crypt();
        void enc(Packet&, uint64_t);
        void dec(Packet&, uint64_t);
        ~Crypt();
};

class Integrity {
private:
        uint8_t *key;

public:
        Integrity();
        void add_hmac(Packet&, uint64_t);
        void get_hmac(uint8_t*, int, uint8_t*, uint64_t);
        void rem_hmac(Packet&, uint8_t*);
        bool hmac_check(Packet&, uint64_t);
        bool cmp_hmacs(uint8_t*, uint8_t*);
        void print_hmac(uint8_t*);
        ~Integrity();
};

extern Crypt g_crypt;
extern Integrity g_integrity;
void encrypt_add_hmac(Packet &pkt);
void decrypt_remove_hmac(Packet &pkt);

现在我已经看到对于 OpenSSL 版本 >1.1.0 有一些建议的更改 但是当我这样做时我得到了 DWARF 错误,尽管我做了

make clean

然后

make

顺便说一下,我的 Makefile(它停止的地方)看起来像这样

G++ = g++ -std=c++0x -std=c++11 -std=gnu++0x -ggdb -O3 -fpermissive -Wno-narrowing
security.o: packet.h security.cpp security.h utils.h
        $(G++) -c -o security.o security.cpp -lcrypto

我会感谢任何建议的解决方案,因为我已经坚持了两天

在 OpenSSL 的最新版本中(我认为从 1.1.0 开始),许多以前声明为 publicly 的结构现在已变为私有并出现在 public 头文件中仅作为不完整类型。因此,您不能在代码中直接使用它们(您只能使用指针)。

因此,您生成 HMAC 的方式略有改变。将 res_len 声明为 unsigned int 以摆脱丑陋的演员表也更有意义:

void Integrity::get_hmac(uint8_t *data, int data_len, uint8_t *hmac, uint64_t k_nas_int) {
        HMAC_CTX *ctx;
        unsigned int res_len;

        ctx = HMAC_CTX_new();
        HMAC_Init_ex(ctx, key, strlen((const char*)key), EVP_sha1(), NULL);
        HMAC_Update(ctx, data, data_len);
        HMAC_Final(ctx, hmac, &res_len);
        HMAC_CTX_free(ctx);
}

文档 here.