-1

我正在为OpenThread堆栈通过 CoAP 实现 EST(安全传输注册)客户端。为此,我想使用 mbedTLS 编写 CSR(证书签名请求),它是作为第三方软件的堆栈的一部分。我现在的问题是,当我构建代码时(我在 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 */

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

这是我在 common-switch 文件中编辑的内容:

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

和她我添加的配置:

开放线程/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”。

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

谢谢。

4

1 回答 1

0

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

看来您也使用 X509,如果您缺少与mbedx509*X509*的符号链接,请添加libmbedx509.a-lmbedx509(并且可以使用选项来指定路径)-L

于 2019-06-26T15:50:08.160 回答