Skip to content

Commit

Permalink
[cryptotest] Add P-384 targets to cryptotest.
Browse files Browse the repository at this point in the history
These were initially excluded because we didn't support P-384 in cryptolib yet,
but now that P-384 support is present we should test it.

Verified locally that the ECDH and ECDSA targets pass on FPGA.

Signed-off-by: Jade Philipoom <[email protected]>
  • Loading branch information
jadephilipoom committed Dec 4, 2024
1 parent 7e22215 commit 777277f
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 22 deletions.
23 changes: 9 additions & 14 deletions sw/device/tests/crypto/cryptotest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ ECDSA_TESTVECTOR_TARGETS = [
"p256_sha512",
"p256_sha3_256",
"p256_sha3_512",
# TODO uncomment when cryptolib supports ECDSA with P-384
# "p384_sha384",
# "p384_sha512",
# "p384_sha3_384",
# "p384_sha3_512",
"p384_sha384",
"p384_sha512",
"p384_sha3_384",
"p384_sha3_512",
]
] + [
"//sw/host/cryptotest/testvectors/data:nist_cavp_ecdsa_fips_186_4_sig_ver_json",
Expand All @@ -51,13 +50,10 @@ ECDSA_TESTVECTOR_TARGETS = [
"p256_sha3_256",
"p256_sha3_384",
"p256_sha3_512",
# TODO uncomment when cryptolib supports ECDSA with P-384
# "p384_sha256",
# "p384_sha384",
# "p384_sha512",
# "p384_sha3_256",
# "p384_sha3_384",
# "p384_sha3_512",
"p384_sha384",
"p384_sha512",
"p384_sha3_384",
"p384_sha3_512",
]
]

Expand All @@ -78,8 +74,7 @@ ECDH_TESTVECTOR_TARGETS = [
"//sw/host/cryptotest/testvectors/data:wycheproof_ecdh_{}".format(mode)
for mode in [
"p256",
# TODO uncomment when ECDH supports P-384
# "p384",
"p384",
]
] + [
"//sw/host/cryptotest/testvectors/data:nist_cavp_ecdh_sp_800_56a_json",
Expand Down
44 changes: 36 additions & 8 deletions sw/device/tests/crypto/cryptotest/firmware/ecdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/base/status.h"
#include "sw/device/lib/crypto/impl/ecc/p256.h"
#include "sw/device/lib/crypto/impl/ecc/p384.h"
#include "sw/device/lib/crypto/impl/integrity.h"
#include "sw/device/lib/crypto/impl/keyblob.h"
#include "sw/device/lib/crypto/include/datatypes.h"
Expand All @@ -15,6 +16,7 @@
#include "sw/device/tests/crypto/cryptotest/json/ecdh_commands.h"

static const int P256_KEY_BYTES = 32;
static const int P384_KEY_BYTES = 48;

status_t handle_ecdh(ujson_t *uj) {
// Declare ECDH parameter ujson deserializer types
Expand All @@ -32,6 +34,9 @@ status_t handle_ecdh(ujson_t *uj) {
otcrypto_ecc_curve_type_t curve_type;
otcrypto_unblinded_key_t public_key;
p256_point_t pub_p256;
p384_point_t pub_p384;
p256_masked_scalar_t private_key_masked_p256;
p384_masked_scalar_t private_key_masked_p384;

otcrypto_key_config_t key_config = {
.version = kOtcryptoLibVersion1,
Expand All @@ -43,7 +48,7 @@ status_t handle_ecdh(ujson_t *uj) {
uint32_t *private_key_masked_raw;
uint32_t private_keyblob_length;
switch (uj_curve) {
case kCryptotestEcdhCurveP256:
case kCryptotestEcdhCurveP256: {
curve_type = kOtcryptoEccCurveTypeNistP256;
memset(pub_p256.x, 0, kP256CoordWords * 4);
memcpy(pub_p256.x, uj_qx.coordinate, uj_qx.coordinate_len);
Expand All @@ -54,14 +59,37 @@ status_t handle_ecdh(ujson_t *uj) {
public_key.key = (uint32_t *)&pub_p256;
key_config.key_length = P256_KEY_BYTES;
shared_key_words = P256_KEY_BYTES / sizeof(uint32_t);
p256_masked_scalar_t private_key_masked;
memset(private_key_masked.share0, 0, kP256MaskedScalarShareBytes);
memcpy(private_key_masked.share0, uj_private_key.d0, kP256ScalarBytes);
memset(private_key_masked.share1, 0, kP256MaskedScalarShareBytes);
memcpy(private_key_masked.share1, uj_private_key.d1, kP256ScalarBytes);
private_key_masked_raw = (uint32_t *)&private_key_masked;
private_keyblob_length = sizeof(private_key_masked);
memset(private_key_masked_p256.share0, 0, kP256MaskedScalarShareBytes);
memcpy(private_key_masked_p256.share0, uj_private_key.d0,
kP256ScalarBytes);
memset(private_key_masked_p256.share1, 0, kP256MaskedScalarShareBytes);
memcpy(private_key_masked_p256.share1, uj_private_key.d1,
kP256ScalarBytes);
private_key_masked_raw = (uint32_t *)&private_key_masked_p256;
private_keyblob_length = sizeof(private_key_masked_p256);
break;
}
case kCryptotestEcdhCurveP384: {
curve_type = kOtcryptoEccCurveTypeNistP384;
memset(pub_p384.x, 0, kP384CoordWords * 4);
memcpy(pub_p384.x, uj_qx.coordinate, uj_qx.coordinate_len);
memset(pub_p384.y, 0, kP384CoordWords * 4);
memcpy(pub_p384.y, uj_qy.coordinate, uj_qy.coordinate_len);
public_key.key_mode = kOtcryptoKeyModeEcdh;
public_key.key_length = sizeof(p384_point_t);
public_key.key = (uint32_t *)&pub_p384;
key_config.key_length = P384_KEY_BYTES;
shared_key_words = P384_KEY_BYTES / sizeof(uint32_t);
memset(private_key_masked_p384.share0, 0, kP384MaskedScalarShareBytes);
memcpy(private_key_masked_p384.share0, uj_private_key.d0,
kP384ScalarBytes);
memset(private_key_masked_p384.share1, 0, kP384MaskedScalarShareBytes);
memcpy(private_key_masked_p384.share1, uj_private_key.d1,
kP384ScalarBytes);
private_key_masked_raw = (uint32_t *)&private_key_masked_p384;
private_keyblob_length = sizeof(private_key_masked_p384);
break;
}
default:
LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
return INVALID_ARGUMENT();
Expand Down
114 changes: 114 additions & 0 deletions sw/device/tests/crypto/cryptotest/firmware/ecdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/base/status.h"
#include "sw/device/lib/crypto/impl/ecc/p256.h"
#include "sw/device/lib/crypto/impl/ecc/p384.h"
#include "sw/device/lib/crypto/impl/integrity.h"
#include "sw/device/lib/crypto/impl/keyblob.h"
#include "sw/device/lib/crypto/include/datatypes.h"
Expand All @@ -18,6 +19,8 @@
enum {
/* Number of bytes in a P-256 private key. */
kP256PrivateKeyBytes = 256 / 8,
/* Number of bytes in a P-384 private key. */
kP384PrivateKeyBytes = 384 / 8,
};

static const otcrypto_key_config_t kP256PrivateKeyConfig = {
Expand All @@ -28,6 +31,14 @@ static const otcrypto_key_config_t kP256PrivateKeyConfig = {
.security_level = kOtcryptoKeySecurityLevelLow,
};

static const otcrypto_key_config_t kP384PrivateKeyConfig = {
.version = kOtcryptoLibVersion1,
.key_mode = kOtcryptoKeyModeEcdsa,
.key_length = kP384PrivateKeyBytes,
.hw_backed = kHardenedBoolFalse,
.security_level = kOtcryptoKeySecurityLevelLow,
};

int set_nist_p256_params(
cryptotest_ecdsa_coordinate_t uj_qx, cryptotest_ecdsa_coordinate_t uj_qy,
cryptotest_ecdsa_signature_t uj_signature,
Expand Down Expand Up @@ -81,6 +92,59 @@ int set_nist_p256_params(
return true;
}

int set_nist_p384_params(
cryptotest_ecdsa_coordinate_t uj_qx, cryptotest_ecdsa_coordinate_t uj_qy,
cryptotest_ecdsa_signature_t uj_signature,
otcrypto_ecc_curve_type_t *curve_type, otcrypto_unblinded_key_t *public_key,
p384_ecdsa_signature_t *signature_p384, p384_point_t *pub_p384,
otcrypto_word32_buf_t *signature_mut, size_t *digest_len) {
*curve_type = kOtcryptoEccCurveTypeNistP384;
if (uj_qx.coordinate_len > kP384CoordBytes) {
LOG_ERROR(
"Coordinate value qx too large for P384 (have = %d bytes, max = %d "
"bytes)",
uj_qx.coordinate_len, kP384CoordBytes);
return false;
}
if (uj_qy.coordinate_len > kP384CoordBytes) {
LOG_ERROR(
"Coordinate value qy too large for P384 (have = %d bytes, max = %d "
"bytes)",
uj_qy.coordinate_len, kP384CoordBytes);
return false;
}
memset(pub_p384->x, 0, kP384CoordBytes);
memcpy(pub_p384->x, uj_qx.coordinate, uj_qx.coordinate_len);
memset(pub_p384->y, 0, kP384CoordBytes);
memcpy(pub_p384->y, uj_qy.coordinate, uj_qy.coordinate_len);
public_key->key_mode = kOtcryptoKeyModeEcdsa;
public_key->key_length = sizeof(p384_point_t);
public_key->key = (uint32_t *)pub_p384;
*digest_len = kP384ScalarWords;
if (uj_signature.r_len > kP384ScalarBytes) {
LOG_ERROR(
"Signature r value too large for P384 (have = %d bytes, max = %d "
"bytes)",
uj_signature.r_len, kP384ScalarBytes);
return false;
}
if (uj_signature.s_len > kP384ScalarBytes) {
LOG_ERROR(
"Signature s value too large for P384 (have = %d bytes, max = %d "
"bytes)",
uj_signature.s_len, kP384ScalarBytes);
return false;
}
memset(signature_p384->r, 0, kP384ScalarBytes);
memcpy(signature_p384->r, uj_signature.r, uj_signature.r_len);
memset(signature_p384->s, 0, kP384ScalarBytes);
memcpy(signature_p384->s, uj_signature.s, uj_signature.s_len);
signature_mut->len = kP384ScalarWords * 2;
signature_mut->data = (uint32_t *)signature_p384;

return true;
}

status_t interpret_verification_result(ujson_t *uj,
hardened_bool_t *verification_result) {
cryptotest_ecdsa_verify_output_t uj_output;
Expand Down Expand Up @@ -158,6 +222,42 @@ status_t p256_sign(ujson_t *uj, cryptotest_ecdsa_private_key_t *uj_private_key,
return OK_STATUS(0);
}

status_t p384_sign(ujson_t *uj, cryptotest_ecdsa_private_key_t *uj_private_key,
otcrypto_ecc_curve_t elliptic_curve,
otcrypto_hash_digest_t message_digest,
otcrypto_word32_buf_t signature_mut,
cryptotest_ecdsa_signature_t *uj_signature) {
p384_masked_scalar_t private_key_masked;
otcrypto_blinded_key_t private_key = {
.config = kP384PrivateKeyConfig,
.keyblob_length = sizeof(private_key_masked),
.keyblob = (uint32_t *)&private_key_masked,
};
memset(private_key_masked.share0, 0, kP384MaskedScalarShareBytes);
memcpy(private_key_masked.share0, uj_private_key->d0, kP384ScalarBytes);
memset(private_key_masked.share1, 0, kP384MaskedScalarShareBytes);
memcpy(private_key_masked.share1, uj_private_key->d1, kP384ScalarBytes);
private_key.checksum = integrity_blinded_checksum(&private_key);

otcrypto_status_t status = otcrypto_ecdsa_sign(
&private_key, message_digest, &elliptic_curve, signature_mut);
if (status.value != kOtcryptoStatusValueOk) {
return INTERNAL(status.value);
}

memset(uj_signature->r, 0, ECDSA_CMD_MAX_SIGNATURE_SCALAR_BYTES);
memset(uj_signature->s, 0, ECDSA_CMD_MAX_SIGNATURE_SCALAR_BYTES);
p384_ecdsa_signature_t *signature_p384 =
(p384_ecdsa_signature_t *)signature_mut.data;
memcpy(uj_signature->r, signature_p384->r, kP384ScalarBytes);
uj_signature->r_len = kP384ScalarBytes;
memcpy(uj_signature->s, signature_p384->s, kP384ScalarBytes);
uj_signature->s_len = kP384ScalarBytes;
RESP_OK(ujson_serialize_cryptotest_ecdsa_signature_t, uj, uj_signature);

return OK_STATUS(0);
}

status_t handle_ecdsa(ujson_t *uj) {
// Declare ECDSA parameter ujson deserializer types
cryptotest_ecdsa_operation_t uj_op;
Expand Down Expand Up @@ -186,7 +286,9 @@ status_t handle_ecdsa(ujson_t *uj) {
otcrypto_word32_buf_t signature_mut;
int success;
p256_ecdsa_signature_t signature_p256;
p384_ecdsa_signature_t signature_p384;
p256_point_t pub_p256;
p384_point_t pub_p384;
switch (uj_curve) {
case kCryptotestEcdsaCurveP256:
success = set_nist_p256_params(uj_qx, uj_qy, uj_signature, &curve_type,
Expand All @@ -196,6 +298,14 @@ status_t handle_ecdsa(ujson_t *uj) {
return INVALID_ARGUMENT();
}
break;
case kCryptotestEcdsaCurveP384:
success = set_nist_p384_params(uj_qx, uj_qy, uj_signature, &curve_type,
&public_key, &signature_p384, &pub_p384,
&signature_mut, &digest_len);
if (!success) {
return INVALID_ARGUMENT();
}
break;
default:
LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
return INVALID_ARGUMENT();
Expand Down Expand Up @@ -251,6 +361,10 @@ status_t handle_ecdsa(ujson_t *uj) {
return p256_sign(uj, &uj_private_key, elliptic_curve, message_digest,
signature_mut, &uj_signature);
}
case kCryptotestEcdsaCurveP384: {
return p384_sign(uj, &uj_private_key, elliptic_curve, message_digest,
signature_mut, &uj_signature);
}
default:
LOG_ERROR("Unsupported ECC curve: %d", uj_curve);
return INVALID_ARGUMENT();
Expand Down

0 comments on commit 777277f

Please sign in to comment.