mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-05 05:34:41 +02:00
Add checks of public key for ECC and curve25519
This commit is contained in:
@@ -18903,6 +18903,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
|
|||||||
curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
|
curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
|
||||||
if (wc_ecc_import_x963_ex(input + args->idx, length,
|
if (wc_ecc_import_x963_ex(input + args->idx, length,
|
||||||
ssl->peerEccKey, curveId) != 0) {
|
ssl->peerEccKey, curveId) != 0) {
|
||||||
|
#ifdef WOLFSSL_EXTRA_ALERTS
|
||||||
|
SendAlert(ssl, alert_fatal, illegal_parameter);
|
||||||
|
#endif
|
||||||
ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
|
ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26005,6 +26008,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ret = wc_curve25519_check_public(
|
||||||
|
input + args->idx, args->length,
|
||||||
|
EC25519_LITTLE_ENDIAN)) != 0) {
|
||||||
|
#ifdef WOLFSSL_EXTRA_ALERTS
|
||||||
|
if (ret == BUFFER_E)
|
||||||
|
SendAlert(ssl, alert_fatal, decode_error);
|
||||||
|
else if (ret == ECC_OUT_OF_RANGE_E)
|
||||||
|
SendAlert(ssl, alert_fatal, bad_record_mac);
|
||||||
|
else {
|
||||||
|
SendAlert(ssl, alert_fatal,
|
||||||
|
illegal_parameter);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
|
||||||
|
}
|
||||||
|
|
||||||
if (wc_curve25519_import_public_ex(
|
if (wc_curve25519_import_public_ex(
|
||||||
input + args->idx, args->length,
|
input + args->idx, args->length,
|
||||||
ssl->peerX25519Key,
|
ssl->peerX25519Key,
|
||||||
|
12
src/tls.c
12
src/tls.c
@@ -6925,13 +6925,19 @@ static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl,
|
|||||||
WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
|
WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Point is validated by import function. */
|
if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen,
|
||||||
if (wc_curve25519_import_public_ex(keyShareEntry->ke, keyShareEntry->keLen,
|
|
||||||
peerX25519Key,
|
|
||||||
EC25519_LITTLE_ENDIAN) != 0) {
|
EC25519_LITTLE_ENDIAN) != 0) {
|
||||||
ret = ECC_PEERKEY_ERROR;
|
ret = ECC_PEERKEY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (wc_curve25519_import_public_ex(keyShareEntry->ke,
|
||||||
|
keyShareEntry->keLen, peerX25519Key,
|
||||||
|
EC25519_LITTLE_ENDIAN) != 0) {
|
||||||
|
ret = ECC_PEERKEY_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ssl->ecdhCurveOID = ECC_X25519_OID;
|
ssl->ecdhCurveOID = ECC_X25519_OID;
|
||||||
|
|
||||||
|
@@ -257,6 +257,64 @@ int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check the public key value (big or little endian)
|
||||||
|
*
|
||||||
|
* pub Public key bytes.
|
||||||
|
* pubSz Size of public key in bytes.
|
||||||
|
* endian Big-endian or little-endian.
|
||||||
|
* returns BAD_FUNC_ARGS when pub is NULL,
|
||||||
|
* BUFFER_E when size of public key is zero;
|
||||||
|
* ECC_OUT_OF_RANGE_E if the high bit is set;
|
||||||
|
* ECC_BAD_ARG_E if key length is not 32 bytes, public key value is
|
||||||
|
* zero or one; and
|
||||||
|
* 0 otherwise.
|
||||||
|
*/
|
||||||
|
int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian)
|
||||||
|
{
|
||||||
|
word32 i;
|
||||||
|
|
||||||
|
if (pub == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* Check for empty key data */
|
||||||
|
if (pubSz == 0)
|
||||||
|
return BUFFER_E;
|
||||||
|
|
||||||
|
/* Check key length */
|
||||||
|
if (pubSz != CURVE25519_KEYSIZE)
|
||||||
|
return ECC_BAD_ARG_E;
|
||||||
|
|
||||||
|
|
||||||
|
if (endian == EC25519_LITTLE_ENDIAN) {
|
||||||
|
/* Check for value of zero or one */
|
||||||
|
for (i = pubSz - 1; i > 0; i--) {
|
||||||
|
if (pub[i] != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 0 && (pub[0] == 0 || pub[0] == 1))
|
||||||
|
return ECC_BAD_ARG_E;
|
||||||
|
|
||||||
|
/* Check high bit set */
|
||||||
|
if (pub[CURVE25519_KEYSIZE-1] & 0x80)
|
||||||
|
return ECC_OUT_OF_RANGE_E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Check for value of zero or one */
|
||||||
|
for (i = 0; i < pubSz-1; i++) {
|
||||||
|
if (pub[i] != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == pubSz - 1 && (pub[i] == 0 || pub[i] == 1))
|
||||||
|
return ECC_BAD_ARG_E;
|
||||||
|
|
||||||
|
/* Check high bit set */
|
||||||
|
if (pub[0] & 0x80)
|
||||||
|
return ECC_OUT_OF_RANGE_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_CURVE25519_KEY_IMPORT */
|
#endif /* HAVE_CURVE25519_KEY_IMPORT */
|
||||||
|
|
||||||
|
|
||||||
|
@@ -18718,6 +18718,122 @@ static int curve25519_overflow_test(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test the wc_curve25519_check_public API.
|
||||||
|
*
|
||||||
|
* returns 0 on success and -ve on failure.
|
||||||
|
*/
|
||||||
|
static int curve25519_check_public_test(void)
|
||||||
|
{
|
||||||
|
/* Little-endian values that will fail */
|
||||||
|
byte fail_le[][CURVE25519_KEYSIZE] = {
|
||||||
|
{
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* Big-endian values that will fail */
|
||||||
|
byte fail_be[][CURVE25519_KEYSIZE] = {
|
||||||
|
{
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* Good or valid public value */
|
||||||
|
byte good[CURVE25519_KEYSIZE] = {
|
||||||
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Parameter checks */
|
||||||
|
/* NULL pointer */
|
||||||
|
if (wc_curve25519_check_public(NULL, 0, EC25519_LITTLE_ENDIAN) !=
|
||||||
|
BAD_FUNC_ARG) {
|
||||||
|
return -10300;
|
||||||
|
}
|
||||||
|
if (wc_curve25519_check_public(NULL, 0, EC25519_BIG_ENDIAN) !=
|
||||||
|
BAD_FUNC_ARG) {
|
||||||
|
return -10301;
|
||||||
|
}
|
||||||
|
/* Length of 0 treated differntly to other invalid lengths for TLS */
|
||||||
|
if (wc_curve25519_check_public(good, 0, EC25519_LITTLE_ENDIAN) != BUFFER_E)
|
||||||
|
return -10302;
|
||||||
|
if (wc_curve25519_check_public(good, 0, EC25519_BIG_ENDIAN) != BUFFER_E)
|
||||||
|
return -10303;
|
||||||
|
|
||||||
|
/* Length not CURVE25519_KEYSIZE */
|
||||||
|
for (i = 1; i < CURVE25519_KEYSIZE + 2; i++) {
|
||||||
|
if (i == CURVE25519_KEYSIZE)
|
||||||
|
continue;
|
||||||
|
if (wc_curve25519_check_public(good, i, EC25519_LITTLE_ENDIAN) !=
|
||||||
|
ECC_BAD_ARG_E) {
|
||||||
|
return -10310 - i;
|
||||||
|
}
|
||||||
|
if (wc_curve25519_check_public(good, i, EC25519_BIG_ENDIAN) !=
|
||||||
|
ECC_BAD_ARG_E) {
|
||||||
|
return -10350 - i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Little-endian fail cases */
|
||||||
|
for (i = 0; i < (int)(sizeof(fail_le) / sizeof(fail_le)); i++) {
|
||||||
|
if (wc_curve25519_check_public(fail_le[i], CURVE25519_KEYSIZE,
|
||||||
|
EC25519_LITTLE_ENDIAN) == 0) {
|
||||||
|
return -10390 - i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Big-endian fail cases */
|
||||||
|
for (i = 0; i < (int)(sizeof(fail_be) / sizeof(fail_be)); i++) {
|
||||||
|
if (wc_curve25519_check_public(fail_be[i], CURVE25519_KEYSIZE,
|
||||||
|
EC25519_BIG_ENDIAN) == 0) {
|
||||||
|
return -10394 - i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check a valid public value works! */
|
||||||
|
if (wc_curve25519_check_public(good, CURVE25519_KEYSIZE,
|
||||||
|
EC25519_LITTLE_ENDIAN) != 0) {
|
||||||
|
return -10398;
|
||||||
|
}
|
||||||
|
if (wc_curve25519_check_public(good, CURVE25519_KEYSIZE,
|
||||||
|
EC25519_BIG_ENDIAN) != 0) {
|
||||||
|
return -10399;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */
|
#endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */
|
||||||
|
|
||||||
int curve25519_test(void)
|
int curve25519_test(void)
|
||||||
@@ -18895,6 +19011,9 @@ int curve25519_test(void)
|
|||||||
ret = curve25519_overflow_test();
|
ret = curve25519_overflow_test();
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
ret = curve25519_check_public_test();
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
#endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */
|
#endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */
|
||||||
|
|
||||||
/* clean up keys when done */
|
/* clean up keys when done */
|
||||||
|
@@ -128,6 +128,8 @@ int wc_curve25519_import_public(const byte* in, word32 inLen,
|
|||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
|
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
|
||||||
curve25519_key* key, int endian);
|
curve25519_key* key, int endian);
|
||||||
|
WOLFSSL_API
|
||||||
|
int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian);
|
||||||
|
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen);
|
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen);
|
||||||
|
Reference in New Issue
Block a user