Mbed-TLS / mbedtls

An open source, portable, easy to use, readable and flexible TLS library, and reference implementation of the PSA Cryptography API. Releases are on a varying cadence, typically around 3 - 6 months between releases.
https://www.trustedfirmware.org/projects/mbed-tls/
Other
5.23k stars 2.56k forks source link

mbedtls_ecp_check_privkey does not properly parse X25519 ECDH private keys #2490

Closed aaronmdjones closed 5 years ago

aaronmdjones commented 5 years ago

Description


Bug

OS:
Linux

mbed TLS build:
Version: 2.16.0 OS version: Gentoo Hardened Configuration:

#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#define MBEDTLS_HAVE_ASM
#define MBEDTLS_HAVE_SSE2
#define MBEDTLS_HAVE_TIME
#define MBEDTLS_HAVE_TIME_DATE
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_CIPHER_MODE_CFB
#define MBEDTLS_CIPHER_MODE_CTR
#define MBEDTLS_CIPHER_MODE_OFB
#define MBEDTLS_CIPHER_MODE_XTS
#define MBEDTLS_CIPHER_PADDING_PKCS7
#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
#define MBEDTLS_CIPHER_PADDING_ZEROS
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
#define MBEDTLS_ECP_DP_CURVE448_ENABLED
#define MBEDTLS_ECP_NIST_OPTIM
#define MBEDTLS_ECDSA_DETERMINISTIC
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
#define MBEDTLS_PK_PARSE_EC_EXTENDED
#define MBEDTLS_ERROR_STRERROR_DUMMY
#define MBEDTLS_GENPRIME
#define MBEDTLS_FS_IO
#define MBEDTLS_PK_RSA_ALT_SUPPORT
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_SELF_TEST
#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
#define MBEDTLS_SSL_FALLBACK_SCSV
#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
#define MBEDTLS_SSL_RENEGOTIATION
#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
#define MBEDTLS_SSL_PROTO_TLS1
#define MBEDTLS_SSL_PROTO_TLS1_1
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_SSL_PROTO_DTLS
#define MBEDTLS_SSL_ALPN
#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
#define MBEDTLS_SSL_SESSION_TICKETS
#define MBEDTLS_SSL_EXPORT_KEYS
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
#define MBEDTLS_SSL_TRUNCATED_HMAC
#define MBEDTLS_VERSION_FEATURES
#define MBEDTLS_X509_CHECK_KEY_USAGE
#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
#define MBEDTLS_AESNI_C
#define MBEDTLS_AES_C
#define MBEDTLS_ARC4_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_BASE64_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_BLOWFISH_C
#define MBEDTLS_CAMELLIA_C
#define MBEDTLS_CCM_C
#define MBEDTLS_CERTS_C
#define MBEDTLS_CHACHA20_C
#define MBEDTLS_CHACHAPOLY_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_DEBUG_C
#define MBEDTLS_DES_C
#define MBEDTLS_DHM_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_ERROR_C
#define MBEDTLS_GCM_C
#define MBEDTLS_HKDF_C
#define MBEDTLS_HMAC_DRBG_C
#define MBEDTLS_MD_C
#define MBEDTLS_MD5_C
#define MBEDTLS_NET_C
#define MBEDTLS_OID_C
#define MBEDTLS_PADLOCK_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_PEM_WRITE_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_PKCS5_C
#define MBEDTLS_PKCS12_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_POLY1305_C
#define MBEDTLS_RIPEMD160_C
#define MBEDTLS_RSA_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_CACHE_C
#define MBEDTLS_SSL_COOKIE_C
#define MBEDTLS_SSL_TICKET_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_TIMING_C
#define MBEDTLS_VERSION_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_CRL_PARSE_C
#define MBEDTLS_X509_CSR_PARSE_C
#define MBEDTLS_X509_CREATE_C
#define MBEDTLS_X509_CRT_WRITE_C
#define MBEDTLS_X509_CSR_WRITE_C
#define MBEDTLS_XTEA_C
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
#if defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif
#include "check_config.h"
#endif /* MBEDTLS_CONFIG_H */

Compiler and options:

# gcc --version
gcc (Gentoo Hardened 8.2.0-r6 p1.7) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.

# portageq envvar CFLAGS
-O2 -pipe -gdwarf-4

Expected behavior
mbedtls_ecp_check_privkey() should return zero when given a properly-generated X25519 private key.

Actual behavior
mbedtls_ecp_check_privkey() fails for X25519 private keys. It also fails with the reference test vectors from the Curve25519 description paper. I also tried the verbatim vectors (unclamped), and I tried reversing the byte arrays, and I tried prepending a 0x00 to the arrays.

Steps to reproduce

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

#include <sodium/core.h>
#include <sodium/crypto_scalarmult_curve25519.h>
#include <sodium/randombytes.h>

#define CURVE25519_KEY_LENGTH 0x20U

static void
printbuf(const char *const restrict desc, const void *const restrict ptr, const size_t len)
{
    const unsigned char *const buf = ptr;

    (void) fprintf(stdout, "%s:", desc);

    for (size_t i = 0; i < len; i++)
    {
        if ((i % 8) == 0)
            (void) fprintf(stdout, "\n\t");

        (void) fprintf(stdout, "0x%02XU, ", (unsigned int) (buf[i] & 0xFFU));
    }

    (void) fprintf(stdout, "\n\n");
    (void) fflush(stdout);
}

static bool __attribute__((__warn_unused_result__))
x25519_keygen(unsigned char pk[const restrict static CURVE25519_KEY_LENGTH],
              unsigned char sk[const restrict static CURVE25519_KEY_LENGTH])
{
    (void) randombytes_buf(sk, CURVE25519_KEY_LENGTH);

    // Clamp the secret key as described in <https://cr.yp.to/ecdh.html>
    sk[0x00U] &= 0xF8U;
    sk[0x1FU] &= 0x7FU;
    sk[0x1FU] |= 0x40U;

    if (crypto_scalarmult_curve25519_base(pk, sk) != 0)
        return false;

    return true;
}

int
main(void)
{
    unsigned char apk[CURVE25519_KEY_LENGTH];
    unsigned char ask[CURVE25519_KEY_LENGTH];
    unsigned char bpk[CURVE25519_KEY_LENGTH];
    unsigned char bsk[CURVE25519_KEY_LENGTH];
    unsigned char ss1[CURVE25519_KEY_LENGTH];
    unsigned char ss2[CURVE25519_KEY_LENGTH];

    if (sodium_init() != 0)
    {
        (void) perror("sodium_init");
        return EXIT_FAILURE;
    }
    if (! x25519_keygen(apk, ask))
    {
        (void) fprintf(stderr, "x25519_keygen() failed\n");
        return EXIT_FAILURE;
    }
    if (! x25519_keygen(bpk, bsk))
    {
        (void) fprintf(stderr, "x25519_keygen() failed\n");
        return EXIT_FAILURE;
    }
    if (crypto_scalarmult_curve25519(ss1, bsk, apk) != 0)
    {
        (void) fprintf(stderr, "crypto_scalarmult_curve25519() failed\n");
        return EXIT_FAILURE;
    }
    if (crypto_scalarmult_curve25519(ss2, ask, bpk) != 0)
    {
        (void) fprintf(stderr, "crypto_scalarmult_curve25519() failed\n");
        return EXIT_FAILURE;
    }
    if (memcmp(ss1, ss2, CURVE25519_KEY_LENGTH) != 0)
    {
        (void) fprintf(stderr, "memcmp(3) mismatch!\n");
        return EXIT_FAILURE;
    }

    (void) printbuf("alice_sk", ask, sizeof ask);
    (void) printbuf("alice_pk", apk, sizeof apk);
    (void) printbuf("bob_sk", bsk, sizeof bsk);
    (void) printbuf("bob_pk", bpk, sizeof bpk);
    (void) printbuf("secret", ss1, sizeof ss1);

    (void) fprintf(stdout, "OK\n");
    return EXIT_SUCCESS;
}
$ clang-9 -Weverything -O0 -gdwarf-4 -pipe sodiumgen.c -o sodiumgen -lsodium
$ ./sodiumgen 

alice_sk:
    0x28U, 0xF8U, 0x0CU, 0x66U, 0x60U, 0xC0U, 0xB6U, 0xF4U, 
    0x4BU, 0xEEU, 0x6BU, 0x67U, 0x3AU, 0xA3U, 0x54U, 0x21U, 
    0x22U, 0x7EU, 0x72U, 0x39U, 0xDAU, 0x25U, 0xD5U, 0x43U, 
    0xDDU, 0xD9U, 0xBAU, 0x85U, 0x9CU, 0xAEU, 0x1AU, 0x55U, 

alice_pk:
    0x75U, 0xAFU, 0x59U, 0xF4U, 0x7BU, 0xCAU, 0x62U, 0xD3U, 
    0x58U, 0xB8U, 0x95U, 0x41U, 0xC9U, 0x95U, 0xF5U, 0x93U, 
    0xB4U, 0x2FU, 0x4FU, 0x81U, 0x06U, 0x3BU, 0x47U, 0x3EU, 
    0x86U, 0xBDU, 0x96U, 0xCFU, 0xCFU, 0xE3U, 0x37U, 0x46U, 

bob_sk:
    0xB8U, 0x90U, 0xF4U, 0xC4U, 0x39U, 0x77U, 0xF6U, 0x2FU, 
    0x9FU, 0xCFU, 0x0FU, 0x28U, 0xAEU, 0x90U, 0xAEU, 0xDBU, 
    0x2DU, 0xE6U, 0x08U, 0xFEU, 0xCAU, 0x4CU, 0xBDU, 0xE4U, 
    0x97U, 0x22U, 0x39U, 0x65U, 0xBEU, 0xF2U, 0x7EU, 0x56U, 

bob_pk:
    0x10U, 0x66U, 0xA0U, 0xD4U, 0x0EU, 0xA3U, 0x62U, 0xBEU, 
    0x2AU, 0x2DU, 0x35U, 0x4CU, 0x91U, 0x33U, 0xF2U, 0x21U, 
    0xF2U, 0xCBU, 0xC2U, 0x6FU, 0x5FU, 0xD1U, 0x54U, 0x1DU, 
    0xF5U, 0xC1U, 0xC2U, 0x88U, 0xA9U, 0x4CU, 0xBEU, 0x39U, 

secret:
    0x2DU, 0xF1U, 0x7EU, 0xF9U, 0x21U, 0x0AU, 0xA7U, 0xD4U, 
    0xA9U, 0x05U, 0x92U, 0x28U, 0x07U, 0x1DU, 0x32U, 0x11U, 
    0xECU, 0x03U, 0xD0U, 0x59U, 0x8AU, 0x1EU, 0x4CU, 0x1CU, 
    0x01U, 0xCBU, 0xCBU, 0x57U, 0xFBU, 0xA5U, 0xADU, 0x4DU, 

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

#include <mbedtls/bignum.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecp.h>

static const unsigned char ecdh_x25519_alice_sk[] = {
    0x28U, 0xF8U, 0x0CU, 0x66U, 0x60U, 0xC0U, 0xB6U, 0xF4U,
    0x4BU, 0xEEU, 0x6BU, 0x67U, 0x3AU, 0xA3U, 0x54U, 0x21U,
    0x22U, 0x7EU, 0x72U, 0x39U, 0xDAU, 0x25U, 0xD5U, 0x43U,
    0xDDU, 0xD9U, 0xBAU, 0x85U, 0x9CU, 0xAEU, 0x1AU, 0x55U,
};

static const unsigned char ecdh_x25519_alice_pk[] = {
    0x75U, 0xAFU, 0x59U, 0xF4U, 0x7BU, 0xCAU, 0x62U, 0xD3U,
    0x58U, 0xB8U, 0x95U, 0x41U, 0xC9U, 0x95U, 0xF5U, 0x93U,
    0xB4U, 0x2FU, 0x4FU, 0x81U, 0x06U, 0x3BU, 0x47U, 0x3EU,
    0x86U, 0xBDU, 0x96U, 0xCFU, 0xCFU, 0xE3U, 0x37U, 0x46U,
};

static const unsigned char ecdh_x25519_bob_sk[] = {
    0xB8U, 0x90U, 0xF4U, 0xC4U, 0x39U, 0x77U, 0xF6U, 0x2FU,
    0x9FU, 0xCFU, 0x0FU, 0x28U, 0xAEU, 0x90U, 0xAEU, 0xDBU,
    0x2DU, 0xE6U, 0x08U, 0xFEU, 0xCAU, 0x4CU, 0xBDU, 0xE4U,
    0x97U, 0x22U, 0x39U, 0x65U, 0xBEU, 0xF2U, 0x7EU, 0x56U,
};

static const unsigned char ecdh_x25519_bob_pk[] = {
    0x10U, 0x66U, 0xA0U, 0xD4U, 0x0EU, 0xA3U, 0x62U, 0xBEU,
    0x2AU, 0x2DU, 0x35U, 0x4CU, 0x91U, 0x33U, 0xF2U, 0x21U,
    0xF2U, 0xCBU, 0xC2U, 0x6FU, 0x5FU, 0xD1U, 0x54U, 0x1DU,
    0xF5U, 0xC1U, 0xC2U, 0x88U, 0xA9U, 0x4CU, 0xBEU, 0x39U,
};

static const unsigned char ecdh_x25519_secret[] = {
    0x2DU, 0xF1U, 0x7EU, 0xF9U, 0x21U, 0x0AU, 0xA7U, 0xD4U,
    0xA9U, 0x05U, 0x92U, 0x28U, 0x07U, 0x1DU, 0x32U, 0x11U,
    0xECU, 0x03U, 0xD0U, 0x59U, 0x8AU, 0x1EU, 0x4CU, 0x1CU,
    0x01U, 0xCBU, 0xCBU, 0x57U, 0xFBU, 0xA5U, 0xADU, 0x4DU,
};

static void
printbuf(const char *const restrict desc, const void *const restrict ptr, const size_t len)
{
    const unsigned char *const buf = ptr;

    (void) fprintf(stdout, "%s:", desc);

    for (size_t i = 0; i < len; i++)
    {
        if ((i % 8) == 0)
            (void) fprintf(stdout, "\n\t");

        (void) fprintf(stdout, "0x%02XU, ", (unsigned int) (buf[i] & 0xFFU));
    }

    (void) fprintf(stdout, "\n\n");
    (void) fflush(stdout);
}

int
main(void)
{
    unsigned char ecdh_x25519_secret_ab[sizeof ecdh_x25519_secret];
    unsigned char ecdh_x25519_secret_ba[sizeof ecdh_x25519_secret];

    mbedtls_ecp_group G;
    mbedtls_ecp_point Qa;
    mbedtls_ecp_point Qb;
    mbedtls_mpi da;
    mbedtls_mpi db;
    mbedtls_mpi za;
    mbedtls_mpi zb;

    int ret;

    (void) mbedtls_ecp_group_init(&G);
    (void) mbedtls_ecp_point_init(&Qa);
    (void) mbedtls_ecp_point_init(&Qb);
    (void) mbedtls_mpi_init(&da);
    (void) mbedtls_mpi_init(&db);
    (void) mbedtls_mpi_init(&za);
    (void) mbedtls_mpi_init(&zb);

    if ((ret = mbedtls_ecp_group_load(&G, MBEDTLS_ECP_DP_CURVE25519)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecp_group_load(G): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_lset(&Qa.Z, 1)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_lset(Qa): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_lset(&Qb.Z, 1)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_lset(Qb): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_read_binary(&Qa.X, ecdh_x25519_alice_pk, sizeof ecdh_x25519_alice_pk)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_read_binary(Qa): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_read_binary(&Qb.X, ecdh_x25519_bob_pk, sizeof ecdh_x25519_bob_pk)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_read_binary(Qb): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_read_binary(&da, ecdh_x25519_alice_sk, sizeof ecdh_x25519_alice_sk)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_read_binary(da): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_read_binary(&db, ecdh_x25519_bob_sk, sizeof ecdh_x25519_bob_sk)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_read_binary(db): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_ecp_check_pubkey(&G, &Qa)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecp_check_pubkey(Qa): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_ecp_check_pubkey(&G, &Qb)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecp_check_pubkey(Qb): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_ecp_check_privkey(&G, &da)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecp_check_privkey(da): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_ecp_check_privkey(&G, &db)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecp_check_privkey(db): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_ecdh_compute_shared(&G, &za, &Qb, &da, NULL, NULL)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecdh_compute_shared(Qb, da): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_ecdh_compute_shared(&G, &zb, &Qa, &db, NULL, NULL)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_ecdh_compute_shared(Qa, db): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_write_binary(&za, ecdh_x25519_secret_ab, sizeof ecdh_x25519_secret_ab)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_write_binary(za): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }
    if ((ret = mbedtls_mpi_write_binary(&zb, ecdh_x25519_secret_ba, sizeof ecdh_x25519_secret_ba)) != 0)
    {
        (void) fprintf(stderr, "mbedtls_mpi_write_binary(zb): -0x%08X\n", (unsigned int) -ret);
        return EXIT_FAILURE;
    }

    (void) printbuf("secret_ab", ecdh_x25519_secret_ab, sizeof ecdh_x25519_secret_ab);
    (void) printbuf("secret_ba", ecdh_x25519_secret_ba, sizeof ecdh_x25519_secret_ba);

    if (memcmp(ecdh_x25519_secret_ab, ecdh_x25519_secret, sizeof ecdh_x25519_secret) != 0)
    {
        (void) fprintf(stderr, "memcmp(3) mismatch!\n");
        return EXIT_FAILURE;
    }
    if (memcmp(ecdh_x25519_secret_ba, ecdh_x25519_secret, sizeof ecdh_x25519_secret) != 0)
    {
        (void) fprintf(stderr, "memcmp(3) mismatch!\n");
        return EXIT_FAILURE;
    }

    (void) fprintf(stdout, "OK\n");
    return EXIT_SUCCESS;
}
$ clang-9 -Weverything -O0 -gdwarf-4 -pipe mbedtest.c -o mbedtest -lmbedcrypto
$ ./mbedtest
mbedtls_ecp_check_privkey(da): -0x00004C80
$ 
ciarmcom commented 5 years ago

ARM Internal Ref: IOTSSL-2797

stepheny commented 5 years ago

This is not a bug. mbedtls_mpi_read_binary and mbedtls_mpi_write_binary read and write in big endian, your sample data is in little endian. Try replace your data const with

static const unsigned char ecdh_x25519_alice_sk[] = {
    0x55U, 0x1AU, 0xAEU, 0x9CU, 0x85U, 0xBAU, 0xD9U, 0xDDU,
    0x43U, 0xD5U, 0x25U, 0xDAU, 0x39U, 0x72U, 0x7EU, 0x22U,
    0x21U, 0x54U, 0xA3U, 0x3AU, 0x67U, 0x6BU, 0xEEU, 0x4BU,
    0xF4U, 0xB6U, 0xC0U, 0x60U, 0x66U, 0x0CU, 0xF8U, 0x28U,
};

static const unsigned char ecdh_x25519_alice_pk[] = {
    0x46U, 0x37U, 0xE3U, 0xCFU, 0xCFU, 0x96U, 0xBDU, 0x86U,
    0x3EU, 0x47U, 0x3BU, 0x06U, 0x81U, 0x4FU, 0x2FU, 0xB4U,
    0x93U, 0xF5U, 0x95U, 0xC9U, 0x41U, 0x95U, 0xB8U, 0x58U,
    0xD3U, 0x62U, 0xCAU, 0x7BU, 0xF4U, 0x59U, 0xAFU, 0x75U,
};

static const unsigned char ecdh_x25519_bob_sk[] = {
    0x56U, 0x7EU, 0xF2U, 0xBEU, 0x65U, 0x39U, 0x22U, 0x97U,
    0xE4U, 0xBDU, 0x4CU, 0xCAU, 0xFEU, 0x08U, 0xE6U, 0x2DU,
    0xDBU, 0xAEU, 0x90U, 0xAEU, 0x28U, 0x0FU, 0xCFU, 0x9FU,
    0x2FU, 0xF6U, 0x77U, 0x39U, 0xC4U, 0xF4U, 0x90U, 0xB8U,
};

static const unsigned char ecdh_x25519_bob_pk[] = {
    0x39U, 0xBEU, 0x4CU, 0xA9U, 0x88U, 0xC2U, 0xC1U, 0xF5U,
    0x1DU, 0x54U, 0xD1U, 0x5FU, 0x6FU, 0xC2U, 0xCBU, 0xF2U,
    0x21U, 0xF2U, 0x33U, 0x91U, 0x4CU, 0x35U, 0x2DU, 0x2AU,
    0xBEU, 0x62U, 0xA3U, 0x0EU, 0xD4U, 0xA0U, 0x66U, 0x10U,
};

static const unsigned char ecdh_x25519_secret[] = {
    0x4DU, 0xADU, 0xA5U, 0xFBU, 0x57U, 0xCBU, 0xCBU, 0x01U,
    0x1CU, 0x4CU, 0x1EU, 0x8AU, 0x59U, 0xD0U, 0x03U, 0xECU,
    0x11U, 0x32U, 0x1DU, 0x07U, 0x28U, 0x92U, 0x05U, 0xA9U,
    0xD4U, 0xA7U, 0x0AU, 0x21U, 0xF9U, 0x7EU, 0xF1U, 0x2DU,
};

you program should work as expected.

aaronmdjones commented 5 years ago

That's strange... I did try reversing the arrays, and it still failed at the same step. I even noted that in my report; but I just tried those arrays above and indeed it works...

Perhaps not enough caffeine was involved.