Skip to content

Commit 7f523bf

Browse files
authored
Merge pull request #8845 from gilles-peskine-arm/ecp-write-doc-3.6
Document ECP write functions
2 parents 09e6fb4 + 7511d4a commit 7f523bf

File tree

4 files changed

+251
-7
lines changed

4 files changed

+251
-7
lines changed

include/mbedtls/ecp.h

+38-6
Original file line numberDiff line numberDiff line change
@@ -1330,17 +1330,41 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
13301330
/**
13311331
* \brief This function exports an elliptic curve private key.
13321332
*
1333+
* \note Note that although this function accepts an output
1334+
* buffer that is smaller or larger than the key, most key
1335+
* import interfaces require the output to have exactly
1336+
* key's nominal length. It is generally simplest to
1337+
* pass the key's nominal length as \c buflen, after
1338+
* checking that the output buffer is large enough.
1339+
* See the description of the \p buflen parameter for
1340+
* how to calculate the nominal length.
1341+
*
1342+
* \note If the private key was not set in \p key,
1343+
* the output is unspecified. Future versions
1344+
* may return an error in that case.
1345+
*
13331346
* \param key The private key.
13341347
* \param buf The output buffer for containing the binary representation
1335-
* of the key. (Big endian integer for Weierstrass curves, byte
1336-
* string for Montgomery curves.)
1348+
* of the key.
1349+
* For Weierstrass curves, this is the big-endian
1350+
* representation, padded with null bytes at the beginning
1351+
* to reach \p buflen bytes.
1352+
* For Montgomery curves, this is the standard byte string
1353+
* representation (which is little-endian), padded with
1354+
* null bytes at the end to reach \p buflen bytes.
13371355
* \param buflen The total length of the buffer in bytes.
1356+
* The length of the output is
1357+
* (`grp->nbits` + 7) / 8 bytes
1358+
* where `grp->nbits` is the private key size in bits.
1359+
* For Weierstrass keys, if the output buffer is smaller,
1360+
* leading zeros are trimmed to fit if possible. For
1361+
* Montgomery keys, the output buffer must always be large
1362+
* enough for the nominal length.
13381363
*
13391364
* \return \c 0 on success.
1340-
* \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key
1341-
representation is larger than the available space in \p buf.
1342-
* \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for
1343-
* the group is not implemented.
1365+
* \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or
1366+
* #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key
1367+
* representation is larger than the available space in \p buf.
13441368
* \return Another negative error code on different kinds of failure.
13451369
*/
13461370
int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
@@ -1349,6 +1373,10 @@ int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
13491373
/**
13501374
* \brief This function exports an elliptic curve public key.
13511375
*
1376+
* \note If the public key was not set in \p key,
1377+
* the output is unspecified. Future versions
1378+
* may return an error in that case.
1379+
*
13521380
* \param key The public key.
13531381
* \param format The point format. This must be either
13541382
* #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.
@@ -1431,6 +1459,10 @@ mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id(
14311459
* Each of the output parameters can be a null pointer
14321460
* if you do not need that parameter.
14331461
*
1462+
* \note If the private key or the public key was not set in \p key,
1463+
* the corresponding output is unspecified. Future versions
1464+
* may return an error in that case.
1465+
*
14341466
* \param key The key pair to export from.
14351467
* \param grp Slot for exported ECP group.
14361468
* It must either be null or point to an initialized ECP group.

library/ecp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3305,7 +3305,7 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
33053305
int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
33063306
unsigned char *buf, size_t buflen)
33073307
{
3308-
int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
3308+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
33093309

33103310
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
33113311
if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {

tests/suites/test_suite_ecp.data

+152
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,158 @@ ECP read key #24 (Curve25519 RFC, OK)
736736
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
737737
mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE25519:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":0:1
738738

739+
ECP write key: secp256r1, nominal
740+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
741+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":32:0
742+
743+
ECP write key: secp256r1, output longer by 1
744+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
745+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":33:0
746+
747+
ECP write key: secp256r1, output longer by 32
748+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
749+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":64:0
750+
751+
ECP write key: secp256r1, output longer by 33
752+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
753+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":65:0
754+
755+
ECP write key: secp256r1, output short by 1
756+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
757+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":31:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
758+
759+
ECP write key: secp256r1, output_size=1
760+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
761+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":1:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
762+
763+
ECP write key: secp256r1, output_size=0
764+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
765+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
766+
767+
ECP write key: secp256r1, top byte = 0, output_size=32
768+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
769+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":32:0
770+
771+
ECP write key: secp256r1, top byte = 0, output_size=31 (fits)
772+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
773+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":31:0
774+
775+
ECP write key: secp256r1, top byte = 0, output_size=30 (too small)
776+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
777+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":30:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
778+
779+
ECP write key: secp256r1, mostly-0 key, output_size=32
780+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
781+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":32:0
782+
783+
ECP write key: secp256r1, mostly-0 key, output_size=31 (fits)
784+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
785+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":31:0
786+
787+
ECP write key: secp256r1, mostly-0 key, output_size=1 (fits)
788+
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
789+
ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":1:0
790+
791+
ECP write key: secp384r1, nominal
792+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
793+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":48:0
794+
795+
ECP write key: secp384r1, output longer by 1
796+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
797+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":49:0
798+
799+
ECP write key: secp384r1, output longer by 48
800+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
801+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":96:0
802+
803+
ECP write key: secp384r1, output longer by 49
804+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
805+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":97:0
806+
807+
ECP write key: secp384r1, output short by 1
808+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
809+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":47:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
810+
811+
ECP write key: secp384r1, output_size=1
812+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
813+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":1:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
814+
815+
ECP write key: secp384r1, output_size=0
816+
depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
817+
ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
818+
819+
ECP write key: Curve25519, nominal
820+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
821+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":32:0
822+
823+
ECP write key: Curve25519, output longer by 1
824+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
825+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":33:0
826+
827+
ECP write key: Curve25519, output longer by 32
828+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
829+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":64:0
830+
831+
ECP write key: Curve25519, output longer by 33
832+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
833+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":65:0
834+
835+
ECP write key: Curve25519, output short by 1
836+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
837+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
838+
839+
ECP write key: Curve25519, output_size=1
840+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
841+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":1:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
842+
843+
ECP write key: Curve25519, output_size=0
844+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
845+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":0:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
846+
847+
ECP write key: Curve25519, mostly-0 key, output_size=32
848+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
849+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"0000000000000000000000000000000000000000000000000000000000000040":32:0
850+
851+
ECP write key: Curve25519, mostly-0 key, output_size=31
852+
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
853+
ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"0000000000000000000000000000000000000000000000000000000000000040":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
854+
855+
ECP write key: Curve448, nominal
856+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
857+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":56:0
858+
859+
ECP write key: Curve448, output longer by 1
860+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
861+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":57:0
862+
863+
ECP write key: Curve448, output longer by 32
864+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
865+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":112:0
866+
867+
ECP write key: Curve448, output longer by 33
868+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
869+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":113:0
870+
871+
ECP write key: Curve448, output short by 1
872+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
873+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
874+
875+
ECP write key: Curve448, output_size=1
876+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
877+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":1:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
878+
879+
ECP write key: Curve448, output_size=0
880+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
881+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":0:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
882+
883+
ECP write key: Curve448, mostly-0 key, output_size=56
884+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
885+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":56:0
886+
887+
ECP write key: Curve448, mostly-0 key, output_size=55
888+
depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
889+
ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
890+
739891
ECP mod p192 small (more than 192 bits, less limbs than 2 * 192 bits)
740892
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_ECP_NIST_OPTIM
741893
ecp_fast_mod:MBEDTLS_ECP_DP_SECP192R1:"0100000000000103010000000000010201000000000001010100000000000100"

tests/suites/test_suite_ecp.function

+60
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,66 @@ exit:
12361236
}
12371237
/* END_CASE */
12381238

1239+
/* BEGIN_CASE */
1240+
void ecp_write_key(int grp_id, data_t *in_key,
1241+
int exported_size, int expected_ret)
1242+
{
1243+
mbedtls_ecp_keypair key;
1244+
mbedtls_ecp_keypair_init(&key);
1245+
unsigned char *exported = NULL;
1246+
1247+
TEST_EQUAL(mbedtls_ecp_read_key(grp_id, &key, in_key->x, in_key->len), 0);
1248+
1249+
TEST_CALLOC(exported, exported_size);
1250+
TEST_EQUAL(mbedtls_ecp_write_key(&key, exported, exported_size),
1251+
expected_ret);
1252+
1253+
if (expected_ret == 0) {
1254+
size_t length = (key.grp.nbits + 7) / 8;
1255+
const unsigned char *key_start = NULL;
1256+
const unsigned char *zeros_start = NULL;
1257+
switch (mbedtls_ecp_get_type(&key.grp)) {
1258+
case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
1259+
if ((size_t) exported_size < length) {
1260+
length = exported_size;
1261+
}
1262+
key_start = exported + exported_size - length;
1263+
zeros_start = exported;
1264+
break;
1265+
case MBEDTLS_ECP_TYPE_MONTGOMERY:
1266+
TEST_LE_U(length, exported_size);
1267+
key_start = exported;
1268+
zeros_start = exported + length;
1269+
break;
1270+
default:
1271+
TEST_FAIL("Unknown ECP curve type");
1272+
break;
1273+
}
1274+
1275+
if (length < in_key->len) {
1276+
/* Shorter output (only possible with Weierstrass keys) */
1277+
for (size_t i = 0; i < in_key->len - length; i++) {
1278+
mbedtls_test_set_step(i);
1279+
TEST_EQUAL(in_key->x[i], 0);
1280+
}
1281+
TEST_MEMORY_COMPARE(in_key->x + in_key->len - length, length,
1282+
key_start, length);
1283+
} else {
1284+
TEST_MEMORY_COMPARE(in_key->x, in_key->len,
1285+
key_start, length);
1286+
for (size_t i = 0; i < exported_size - length; i++) {
1287+
mbedtls_test_set_step(i);
1288+
TEST_EQUAL(zeros_start[i], 0);
1289+
}
1290+
}
1291+
}
1292+
1293+
exit:
1294+
mbedtls_ecp_keypair_free(&key);
1295+
mbedtls_free(exported);
1296+
}
1297+
/* END_CASE */
1298+
12391299
/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_ECP_MONTGOMERY_ENABLED:MBEDTLS_ECP_LIGHT */
12401300
void genkey_mx_known_answer(int bits, data_t *seed, data_t *expected)
12411301
{

0 commit comments

Comments
 (0)