在mbedtls中使用openthread时,如何解决“未定义的引用”错误?

时间:2019-06-26 15:30:08

标签: c++ mbedtls openthread

我正在为OpenThread堆栈通过CoAP实现EST(安全传输注册)-客户端的实现。为此,我想使用mbedTLS编写CSR(证书签名请求),mbedTLS作为第三方软件是堆栈的一部分。我现在的问题是,在构建代码时(我在Ubuntu 18.04.2 LTS计算机上使用GCC),我从链接器中收到一些“未定义的引用”错误。

由于有多个功能会发生错误,因此我仅提供一个示例代码。这是我的源文件:

openthread / src / core / crypto / ecp.cpp:

#include "ecp.hpp"

#include <mbedtls/ctr_drbg.h>
#include <mbedtls/ecp.h>
#include <mbedtls/pk.h>

#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/random.hpp"

#include "openthread/entropy.h"
#include "openthread/random_crypto.h"

namespace ot {
namespace Crypto {

#if OPENTHREAD_ENABLE_EST_CLIENT && OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE

otError Ecp::KeyPairGeneration(const uint8_t *aPersonalSeed,
                               uint32_t       aPersonalSeedLength,
                               uint8_t *      aPrivateKey,
                               uint32_t *     aPrivateKeyLength,
                               uint8_t *      aPublicKey,
                               uint32_t *     aPublicKeyLength)
{
    otError error = OT_ERROR_NONE;
    mbedtls_pk_context keypair;

    OT_UNUSED_VARIABLE(aPersonalSeed);
    OT_UNUSED_VARIABLE(aPersonalSeedLength);

    mbedtls_pk_init(&keypair);

    // Generate keypair
    VerifyOrExit(mbedtls_pk_setup(&keypair, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)),
                 error = OT_ERROR_FAILED);

    VerifyOrExit(mbedtls_ecp_group_load(&mbedtls_pk_ec(keypair)->grp, MBEDTLS_ECP_DP_SECP256R1) == 0,
                 error = OT_ERROR_FAILED);

    VerifyOrExit(mbedtls_ecp_gen_keypair(&mbedtls_pk_ec(keypair)->grp, &mbedtls_pk_ec(keypair)->d,
                                         &mbedtls_pk_ec(keypair)->Q, mbedtls_ctr_drbg_random,
                                         Random::Crypto::MbedTlsContextGet()) == 0,
                 error = OT_ERROR_FAILED);

    VerifyOrExit(mbedtls_pk_write_pubkey_pem(&keypair, (unsigned char*)aPublicKey,
                                             *aPublicKeyLength) == 0,
                 error = OT_ERROR_INVALID_ARGS);

    VerifyOrExit(mbedtls_pk_write_key_pem(&keypair, (unsigned char*)aPrivateKey,
                                          *aPrivateKeyLength) == 0,
                 error = OT_ERROR_INVALID_ARGS);

exit:
    mbedtls_pk_free(&keypair);

    return error;
}

#endif // OPENTHREAD_ENABLE_EST_CLIENT

} // namespace Crypto
} // namespace ot

我的头文件:

openthread / src / core / crypto / ecp.hpp


#ifndef ECP_HPP_
#define ECP_HPP_

#include "openthread-core-config.h"

#include <stdint.h>
#include <stdlib.h>

#include <openthread/error.h>

namespace ot {
namespace Crypto {

/**
 * @addtogroup core-security
 *
 * @{
 *
 */

/**
 * This class implements elliptic curve key generation.
 *
 */
class Ecp
{
public:
    /**
     * This method generate a Elliptic Curve key pair.
     *
     * @param[in]       aPersonalSeed       An additional seed for the entropy. Can be NULL.
     * @param[in]       aPersonalSeedLengh  The length of the @p aPersonalSeed.
     * @param[out]      aPrivateKey         An output buffer where the private key should be stored.
     * @param[inout]    aPrivateKeyLength   The length of the @p aPrivateKey buffer.
     * @param[out]      aPublicKey          An output buffer where the private key should be stored.
     * @param[inout]    aPublicKeyLength    The length of the @p aPublicKey buffer.
     *
     * @retval  OT_ERROR_NONE       EC key pairs has been created successfully.
     *          OT_ERROR_NO_BUFS    Key buffers are too small or mbedtls heap too small.
     */
    static otError KeyPairGeneration(const uint8_t *aPersonalSeed,
                                     uint32_t       aPersonalSeedLength,
                                     uint8_t *      aPrivateKey,
                                     uint32_t *     aPrivateKeyLength,
                                     uint8_t *      aPublicKey,
                                     uint32_t *     aPublicKeyLength);
};

/**
 * @}
 *
 */

} // namespace Crypto
} // namespace ot

#endif // ECP_HPP_

导致错误的函数在此处为mbedtls_pk_write_pubkey_pem和mbedtls_pk_write_key_pem。

这也是控制台输出的一部分:

Making all in apps
Making all in cli
  CC       ot_cli_ftd-main.o
  CC       ot_cli_mtd-main.o
  CCLD     ot-cli-ftd
  CCLD     ot-cli-mtd
/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: ../../../src/core/libopenthread-mtd.a(libopenthread_mtd_a-ecp.o): in function `ot::Crypto::Ecp::KeyPairGeneration(unsigned char const*, unsigned long, unsigned char*, unsigned long*, unsigned char*, unsigned long*)':
/home/scnm/eclipse-workspace/openthread/examples/../src/core/crypto/ecp.cpp:79: undefined reference to `mbedtls_pk_write_pubkey_pem'
/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: /home/scnm/eclipse-workspace/openthread/examples/../src/core/crypto/ecp.cpp:83: undefined reference to `mbedtls_pk_write_key_pem'
collect2: error: ld returned 1 exit status
Makefile:1249: recipe for target 'ot-cli-mtd' failed
make[5]: *** [ot-cli-mtd] Error 1

我首先想到的是,因为我缺少一些#define才能实际使用这些功能,但是我将其与其他使用mbedtls的OpenThread代码进行了比较,但我看不出我做错了什么。据我了解,我必须修改“ openthread / third_party / mbedtls / mbedtls-config.h”文件,以便构建这些功能,这就是我所做的:

#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H

#include <stdio.h>
#include <stdlib.h>

#include <openthread/config.h>
#include <openthread/platform/logging.h>
#include <openthread/platform/memory.h>

#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf

#define MBEDTLS_AES_C
#define MBEDTLS_AES_ROM_TABLES
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_CCM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CMAC_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_ECJPAKE_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_NIST_OPTIM
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_HAVE_ASM
#define MBEDTLS_HMAC_DRBG_C
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
#define MBEDTLS_MD_C
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA256_SMALLER
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
#define MBEDTLS_SSL_EXPORT_KEYS
#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_SSL_PROTO_DTLS
#define MBEDTLS_SSL_TLS_C

#if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER || OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
#define MBEDTLS_SSL_COOKIE_C
#define MBEDTLS_SSL_SRV_C
#endif

#if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#if OPENTHREAD_ENABLE_EST_CLIENT
#define MBEDTLS_PEM_WRITE_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_X509_CSR_WRITE_C
#define MBEDTLS_X509_CREATE_C
#endif
#endif

#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_OID_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#endif

#if OPENTHREAD_ENABLE_ECDSA
#define MBEDTLS_BASE64_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_OID_C
#define MBEDTLS_PEM_PARSE_C
#endif

#define MBEDTLS_MPI_WINDOW_SIZE            1 /**< Maximum windows size used. */
#define MBEDTLS_MPI_MAX_SIZE              32 /**< Maximum number of bytes for usable MPIs. */
#define MBEDTLS_ECP_MAX_BITS             256 /**< Maximum bit size of groups */
#define MBEDTLS_ECP_WINDOW_SIZE            2 /**< Maximum window size used */
#define MBEDTLS_ECP_FIXED_POINT_OPTIM      0 /**< Enable fixed-point speed-up */
#define MBEDTLS_ENTROPY_MAX_SOURCES        1 /**< Maximum number of sources supported */

#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
#define MBEDTLS_PLATFORM_STD_CALLOC      otPlatCAlloc /**< Default allocator to use, can be undefined */
#define MBEDTLS_PLATFORM_STD_FREE        otPlatFree /**< Default free to use, can be undefined */
#else
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
#endif

#if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
#define MBEDTLS_SSL_MAX_CONTENT_LEN      900 /**< Maxium fragment length in bytes */
#else
#define MBEDTLS_SSL_MAX_CONTENT_LEN      768 /**< Maxium fragment length in bytes */
#endif

#define MBEDTLS_SSL_CIPHERSUITES         MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8

#if defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif

#if defined(MBEDTLS_ECP_ALT) && !defined(MBEDTLS_ECP_RESTARTABLE)
typedef void mbedtls_ecp_restart_ctx;
#endif

#include "mbedtls/check_config.h"

#endif /* MBEDTLS_CONFIG_H */

它解决了我以前遇到的“未在此范围内定义”错误,但是现在我遇到了上述错误。

这是我在通用开关文件中编辑的内容:

openthread / examples / common-switches.mk

ECDSA               ?= 0
// my code begin
EST_CLIENT          ?= 0
// my code end
JAM_DETECTION       ?= 0
ifeq ($(ECDSA),1)
configure_OPTIONS              += --enable-ecdsa
endif

// my code begin
ifeq ($(EST_CLIENT),1)
configure_OPTIONS              += --enable-est-client --enable-application-coap-secure
endif
// my code end

ifeq ($(JAM_DETECTION),1)
configure_OPTIONS              += --enable-jam-detection
endif

和她我要配置的内容:

openthread / configure.ac

#
# EST Client
#

AC_ARG_ENABLE(est_client,
    [AS_HELP_STRING([--enable-est-client],[Enable EST client support @<:@default=no@:>@.])],
    [
        case "${enableval}" in

        no|yes)
            enable_est_client=${enableval}
            ;;

        *)
            AC_MSG_ERROR([Invalid value ${enable_est_client} for --enable-est-client])
            ;;
        esac
    ],
    [enable_est_client=no])

if test "$enable_est_client" = "yes"; then
    OPENTHREAD_ENABLE_EST_CLIENT=1
else
    OPENTHREAD_ENABLE_EST_CLIENT=0
fi

AC_SUBST(OPENTHREAD_ENABLE_EST_CLIENT)
AM_CONDITIONAL([OPENTHREAD_ENABLE_EST_CLIENT], [test "${enable_est_client}" = "yes"])
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_EST_CLIENT],[${OPENTHREAD_ENABLE_EST_CLIENT}],[Define to 1 if you want to enable EST Client])
  OpenThread DNS Client support             : ${enable_dns_client}
// my code begin
  OpenThread EST Client support             : ${enable_est_client}
// my code end
  OpenThread SNTP Client support            : ${enable_sntp_client}

我还编辑了makefile:

openthread / src / core / Makefile.am

    crypto/ecdsa.hpp                  \
    crypto/ecp.hpp                    \
    crypto/hmac_sha256.hpp            \
    crypto/ecdsa.cpp                  \
    crypto/ecp.cpp                    \
    crypto/hmac_sha256.cpp            \

我的构建命令是“ make -f examples / Makefile-nrf52840 EST_CLIENT = 1”。

我认为这个问题一旦解决,我就可以自己解决其他问题,因为问题的根源似乎是相同的。

谢谢。

1 个答案:

答案 0 :(得分:0)

您在链接期间出错,未定义符号mbedtls_pk_write_pubkey_pem,这意味着您错过了指定定义它的库的权限。在网络上浏览似乎需要链接 mbedcrypto ,因此添加 libmbedcrypto.a -lmbedcrypto (并且可以使用选项{ {1}}指定路径)

如果您缺少与 mbedx509 的符号-L链接,似乎还使用X509,因此添加 libmbedx509.a -lmbedx509 < / em>(并且可以使用选项*X509*指定路径)