mbedtls_ecp_write_key: document and test smaller output buffer

Document and test the current behavior, even if it is weird:

* For Weierstrass keys, the error is MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL,
  not MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL.
* For Weierstrass keys, a smaller output buffer is ok if the output fits.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2024-02-19 13:49:45 +01:00
parent a395bdd066
commit 1c7ff7ea53
3 changed files with 118 additions and 12 deletions

View File

@ -1331,8 +1331,8 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
* \brief This function exports an elliptic curve private key.
*
* \note Note that although this function accepts an output
* buffer that is larger than the key, most key import
* interfaces require the output to be trimmed to the
* buffer that is smaller or larger than the key, most key
* import interfaces require the output to have exactly
* key's nominal length. It is generally simplest to
* pass the key's nominal length as \c buflen, after
* checking that the output buffer is large enough.
@ -1349,13 +1349,18 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
* representation (which is little-endian), padded with
* null bytes at the end to reach \p buflen bytes.
* \param buflen The total length of the buffer in bytes.
* The length of the output is always
* The length of the output is
* (`grp->nbits` + 7) / 8 bytes
* where `grp->nbits` is the private key size in bits.
* For Weierstrass keys, if the output buffer is smaller,
* leading zeros are trimmed to fit if possible. For
* Montgomery keys, the output buffer must always be large
* enough for the nominal length.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key
representation is larger than the available space in \p buf.
* \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or
* #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key
* representation is larger than the available space in \p buf.
* \return Another negative error code on different kinds of failure.
*/
int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,

View File

@ -752,6 +752,42 @@ ECP write key: secp256r1, output longer by 33
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":65:0
ECP write key: secp256r1, output short by 1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":31:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: secp256r1, output_size=1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":1:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: secp256r1, output_size=0
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: secp256r1, top byte = 0, output_size=32
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":32:0
ECP write key: secp256r1, top byte = 0, output_size=31 (fits)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":31:0
ECP write key: secp256r1, top byte = 0, output_size=30 (too small)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":30:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: secp256r1, mostly-0 key, output_size=32
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":32:0
ECP write key: secp256r1, mostly-0 key, output_size=31 (fits)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":31:0
ECP write key: secp256r1, mostly-0 key, output_size=1 (fits)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":1:0
ECP write key: secp384r1, nominal
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":48:0
@ -768,6 +804,18 @@ ECP write key: secp384r1, output longer by 49
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":97:0
ECP write key: secp384r1, output short by 1
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":47:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: secp384r1, output_size=1
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":1:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: secp384r1, output_size=0
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
ECP write key: Curve25519, nominal
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":32:0
@ -784,6 +832,26 @@ ECP write key: Curve25519, output longer by 33
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":65:0
ECP write key: Curve25519, output short by 1
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve25519, output_size=1
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":1:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve25519, output_size=0
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":0:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve25519, mostly-0 key, output_size=32
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"0000000000000000000000000000000000000000000000000000000000000040":32:0
ECP write key: Curve25519, mostly-0 key, output_size=31
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"0000000000000000000000000000000000000000000000000000000000000040":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve448, nominal
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":56:0
@ -800,6 +868,26 @@ ECP write key: Curve448, output longer by 33
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":113:0
ECP write key: Curve448, output short by 1
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve448, output_size=1
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":1:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve448, output_size=0
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":0:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP write key: Curve448, mostly-0 key, output_size=56
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":56:0
ECP write key: Curve448, mostly-0 key, output_size=55
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
ECP mod p192 small (more than 192 bits, less limbs than 2 * 192 bits)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_ECP_NIST_OPTIM
ecp_fast_mod:MBEDTLS_ECP_DP_SECP192R1:"0100000000000103010000000000010201000000000001010100000000000100"

View File

@ -1252,16 +1252,18 @@ void ecp_write_key(int grp_id, data_t *in_key,
if (expected_ret == 0) {
size_t length = (key.grp.nbits + 7) / 8;
TEST_LE_U(length, exported_size);
const unsigned char *key_start = NULL;
const unsigned char *zeros_start = NULL;
switch (mbedtls_ecp_get_type(&key.grp)) {
case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
if ((size_t) exported_size < length) {
length = exported_size;
}
key_start = exported + exported_size - length;
zeros_start = exported;
break;
case MBEDTLS_ECP_TYPE_MONTGOMERY:
TEST_LE_U(length, exported_size);
key_start = exported;
zeros_start = exported + length;
break;
@ -1269,11 +1271,22 @@ void ecp_write_key(int grp_id, data_t *in_key,
TEST_FAIL("Unknown ECP curve type");
break;
}
TEST_MEMORY_COMPARE(in_key->x, in_key->len,
key_start, length);
for (size_t i = 0; i < exported_size - length; i++) {
mbedtls_test_set_step(i);
TEST_EQUAL(zeros_start[i], 0);
if (length < in_key->len) {
/* Shorter output (only possible with Weierstrass keys) */
for (size_t i = 0; i < in_key->len - length; i++) {
mbedtls_test_set_step(i);
TEST_EQUAL(in_key->x[i], 0);
}
TEST_MEMORY_COMPARE(in_key->x + in_key->len - length, length,
key_start, length);
} else {
TEST_MEMORY_COMPARE(in_key->x, in_key->len,
key_start, length);
for (size_t i = 0; i < exported_size - length; i++) {
mbedtls_test_set_step(i);
TEST_EQUAL(zeros_start[i], 0);
}
}
}