Skip to content

Commit

Permalink
[crypto] Consolidate P-384 OTBN binaries.
Browse files Browse the repository at this point in the history
Analogous to the P-256 refactor but more dramatic, because P-384 was split into
more pieces previously. With larger IMEM, we can use only one binary for P-384
operations, instead of the previous four (keygen/sign/verify/ecdh).

There's again a lot of code churn here, but the vast majority of it is only
moved, not changed. Like with P-256, some names had to be changed to fit the
naming convention of definitions from the same C header starting with the same
prefix (so e.g. "ecdsa_p384" became "p384_ecdsa").

This saves about 16.4 kB (!) of code size.

Signed-off-by: Jade Philipoom <[email protected]>
(cherry picked from commit 488bd4b)
  • Loading branch information
jadephilipoom committed Dec 16, 2024
1 parent 7e1d62d commit 1d2955d
Show file tree
Hide file tree
Showing 28 changed files with 901 additions and 1,716 deletions.
3 changes: 1 addition & 2 deletions sw/device/lib/crypto/impl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ cc_library(
":keyblob",
"//sw/device/lib/crypto/drivers:entropy",
"//sw/device/lib/crypto/drivers:hmac",
"//sw/device/lib/crypto/impl/ecc:ecdh_p384",
"//sw/device/lib/crypto/impl/ecc:ecdsa_p384",
"//sw/device/lib/crypto/impl/ecc:p256",
"//sw/device/lib/crypto/impl/ecc:p384",
"//sw/device/lib/crypto/include:datatypes",
],
)
Expand Down
104 changes: 30 additions & 74 deletions sw/device/lib/crypto/impl/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@

#include "sw/device/lib/crypto/drivers/entropy.h"
#include "sw/device/lib/crypto/drivers/hmac.h"
#include "sw/device/lib/crypto/impl/ecc/ecdh_p384.h"
#include "sw/device/lib/crypto/impl/ecc/ecdsa_p384.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 Down Expand Up @@ -155,11 +154,11 @@ otcrypto_status_t otcrypto_ecdsa_keygen_async_start(
if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
HARDENED_TRY(sideload_key_seed(private_key));
return ecdsa_p384_sideload_keygen_start();
return p384_sideload_keygen_start();
} else if (launder32(private_key->config.hw_backed) ==
kHardenedBoolFalse) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
return ecdsa_p384_keygen_start();
return p384_keygen_start();
} else {
return OTCRYPTO_BAD_ARGS;
}
Expand Down Expand Up @@ -369,18 +368,19 @@ static status_t internal_p256_keygen_finalize(
}

/**
* Finalize an ECDSA key generation operation for curve P-384.
* Finalize a keypair generation operation for curve P-384.
*
* This function assumes that space is already allocated for all key material
* and that the length parameters on the structs are set accordingly, in the
* same way as for `otcrypto_ecdsa_keygen_async_finalize`.
* same way as for `otcrypto_ecdh_keygen_async_finalize` and
* `otcrypto_ecdsa_keygen_async_finalize`.
*
* @param[out] private_key Private key to populate.
* @param[out] public_key Public key to populate.
* @return OK or error.
*/
OT_WARN_UNUSED_RESULT
static status_t internal_ecdsa_p384_keygen_finalize(
static status_t internal_p384_keygen_finalize(
otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
// Check the lengths of caller-allocated buffers.
HARDENED_TRY(p384_private_key_length_check(private_key));
Expand All @@ -395,15 +395,15 @@ static status_t internal_ecdsa_p384_keygen_finalize(
// be the last potentially error-causing line before returning to the
// caller.
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
HARDENED_TRY(ecdsa_p384_sideload_keygen_finalize(pk));
HARDENED_TRY(p384_sideload_keygen_finalize(pk));
} else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
// Note: This operation wipes DMEM after retrieving the keys, so if an error
// occurs after this point then the keys would be unrecoverable. This should
// be the last potentially error-causing line before returning to the
// caller.
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
HARDENED_TRY(ecdsa_p384_keygen_finalize(sk, pk));
HARDENED_TRY(p384_keygen_finalize(sk, pk));
private_key->checksum = integrity_blinded_checksum(private_key);
} else {
return OTCRYPTO_BAD_ARGS;
Expand Down Expand Up @@ -440,8 +440,7 @@ otcrypto_status_t otcrypto_ecdsa_keygen_async_finalize(
case kOtcryptoEccCurveTypeNistP384:
HARDENED_CHECK_EQ(elliptic_curve->curve_type,
kOtcryptoEccCurveTypeNistP384);
HARDENED_TRY(
internal_ecdsa_p384_keygen_finalize(private_key, public_key));
HARDENED_TRY(internal_p384_keygen_finalize(private_key, public_key));
break;
case kEccCurveTypeBrainpoolP256R1:
OT_FALLTHROUGH_INTENDED;
Expand Down Expand Up @@ -516,12 +515,12 @@ static status_t internal_ecdsa_p384_sign_start(
// Start the asynchronous signature-generation routine.
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
return ecdsa_p384_sign_start(message_digest.data, sk);
return p384_ecdsa_sign_start(message_digest.data, sk);
} else if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
// Load the key and start in sideloaded-key mode.
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
HARDENED_TRY(sideload_key_seed(private_key));
return ecdsa_p384_sideload_sign_start(message_digest.data);
return p384_ecdsa_sideload_sign_start(message_digest.data);
}

// Invalid value for private_key->hw_backed.
Expand Down Expand Up @@ -604,18 +603,18 @@ static status_t p256_signature_length_check(size_t len) {
* Check the length of a signature buffer for ECDSA with P-384.
*
* If this check passes on `signature.len`, it is safe to interpret
* `signature.data` as `ecdsa_p384_signature_t *`.
* `signature.data` as `p384_ecdsa_signature_t *`.
*
* @param len Length to check.
* @return OK if the lengths are correct or BAD_ARGS otherwise.
*/
OT_WARN_UNUSED_RESULT
static status_t p384_signature_length_check(size_t len) {
if (launder32(len) > UINT32_MAX / sizeof(uint32_t) ||
launder32(len) * sizeof(uint32_t) != sizeof(ecdsa_p384_signature_t)) {
launder32(len) * sizeof(uint32_t) != sizeof(p384_ecdsa_signature_t)) {
return OTCRYPTO_BAD_ARGS;
}
HARDENED_CHECK_EQ(len * sizeof(uint32_t), sizeof(ecdsa_p384_signature_t));
HARDENED_CHECK_EQ(len * sizeof(uint32_t), sizeof(p384_ecdsa_signature_t));

return OTCRYPTO_OK;
}
Expand Down Expand Up @@ -644,12 +643,12 @@ otcrypto_status_t otcrypto_ecdsa_sign_async_finalize(
HARDENED_CHECK_EQ(elliptic_curve->curve_type,
kOtcryptoEccCurveTypeNistP384);
HARDENED_TRY(p384_signature_length_check(signature.len));
ecdsa_p384_signature_t *sig_p384 =
(ecdsa_p384_signature_t *)signature.data;
p384_ecdsa_signature_t *sig_p384 =
(p384_ecdsa_signature_t *)signature.data;
// Note: This operation wipes DMEM, so if an error occurs after this
// point then the signature would be unrecoverable. This should be the
// last potentially error-causing line before returning to the caller.
HARDENED_TRY(ecdsa_p384_sign_finalize(sig_p384));
HARDENED_TRY(p384_ecdsa_sign_finalize(sig_p384));
break;
case kEccCurveTypeBrainpoolP256R1:
OT_FALLTHROUGH_INTENDED;
Expand Down Expand Up @@ -720,10 +719,10 @@ static status_t internal_ecdsa_p384_verify_start(

// Check the signature lengths.
HARDENED_TRY(p384_signature_length_check(signature.len));
ecdsa_p384_signature_t *sig = (ecdsa_p384_signature_t *)signature.data;
p384_ecdsa_signature_t *sig = (p384_ecdsa_signature_t *)signature.data;

// Start the asynchronous signature-verification routine.
return ecdsa_p384_verify_start(sig, message_digest.data, pk);
return p384_ecdsa_verify_start(sig, message_digest.data, pk);
}

otcrypto_status_t otcrypto_ecdsa_verify_async_start(
Expand Down Expand Up @@ -799,9 +798,9 @@ otcrypto_status_t otcrypto_ecdsa_verify_async_finalize(
HARDENED_CHECK_EQ(elliptic_curve->curve_type,
kOtcryptoEccCurveTypeNistP384);
HARDENED_TRY(p384_signature_length_check(signature.len));
ecdsa_p384_signature_t *sig_p384 =
(ecdsa_p384_signature_t *)signature.data;
return ecdsa_p384_verify_finalize(sig_p384, verification_result);
p384_ecdsa_signature_t *sig_p384 =
(p384_ecdsa_signature_t *)signature.data;
return p384_ecdsa_verify_finalize(sig_p384, verification_result);
case kEccCurveTypeBrainpoolP256R1:
OT_FALLTHROUGH_INTENDED;
case kOtcryptoEccCurveTypeCustom:
Expand Down Expand Up @@ -853,11 +852,11 @@ otcrypto_status_t otcrypto_ecdh_keygen_async_start(
if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
HARDENED_TRY(sideload_key_seed(private_key));
return ecdh_p384_sideload_keypair_start();
return p384_sideload_keygen_start();
} else if (launder32(private_key->config.hw_backed) ==
kHardenedBoolFalse) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
return ecdh_p384_keypair_start();
return p384_keygen_start();
}
return OTCRYPTO_BAD_ARGS;
case kEccCurveTypeBrainpoolP256R1:
Expand All @@ -874,49 +873,6 @@ otcrypto_status_t otcrypto_ecdh_keygen_async_start(
return OTCRYPTO_FATAL_ERR;
}

/**
* Finalize an ECDH keypair generation operation for curve P-384.
*
* This function assumes that space is already allocated for all key material
* and that the length parameters on the structs are set accordingly, in the
* same way as for `otcrypto_ecdh_keygen_async_finalize`.
*
* @param[out] private_key Private key to populate.
* @param[out] public_key Public key to populate.
* @return OK or error.
*/
OT_WARN_UNUSED_RESULT
static status_t internal_ecdh_p384_keygen_finalize(
otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
// Check the lengths of caller-allocated buffers.
HARDENED_TRY(p384_private_key_length_check(private_key));
HARDENED_TRY(p384_public_key_length_check(public_key));
p384_point_t *pk = (p384_point_t *)public_key->key;

// Note: The `finalize` operations wipe DMEM after retrieving the keys, so if
// an error occurs after this point then the keys would be unrecoverable.
// The `finalize` call should be the last potentially error-causing line
// before returning to the caller.

if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
HARDENED_TRY(ecdh_p384_sideload_keypair_finalize(pk));
} else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
HARDENED_TRY(ecdh_p384_keypair_finalize(sk, pk));
private_key->checksum = integrity_blinded_checksum(private_key);
} else {
return OTCRYPTO_BAD_ARGS;
}

// Prepare the public key.
public_key->checksum = integrity_unblinded_checksum(public_key);

// Clear the OTBN sideload slot (in case the seed was sideloaded).
return keymgr_sideload_clear_otbn();
}

otcrypto_status_t otcrypto_ecdh_keygen_async_finalize(
const otcrypto_ecc_curve_t *elliptic_curve,
otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) {
Expand Down Expand Up @@ -944,7 +900,7 @@ otcrypto_status_t otcrypto_ecdh_keygen_async_finalize(
case kOtcryptoEccCurveTypeNistP384:
HARDENED_CHECK_EQ(elliptic_curve->curve_type,
kOtcryptoEccCurveTypeNistP384);
HARDENED_TRY(internal_ecdh_p384_keygen_finalize(private_key, public_key));
HARDENED_TRY(internal_p384_keygen_finalize(private_key, public_key));
break;
case kEccCurveTypeBrainpoolP256R1:
OT_FALLTHROUGH_INTENDED;
Expand Down Expand Up @@ -1006,11 +962,11 @@ static status_t internal_ecdh_p384_start(
if (launder32(private_key->config.hw_backed) == kHardenedBoolTrue) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolTrue);
HARDENED_TRY(sideload_key_seed(private_key));
return ecdh_p384_sideload_shared_key_start(pk);
return p384_sideload_ecdh_start(pk);
} else if (launder32(private_key->config.hw_backed) == kHardenedBoolFalse) {
HARDENED_CHECK_EQ(private_key->config.hw_backed, kHardenedBoolFalse);
p384_masked_scalar_t *sk = (p384_masked_scalar_t *)private_key->keyblob;
return ecdh_p384_shared_key_start(sk, pk);
return p384_ecdh_start(sk, pk);
}

// Invalid value for `hw_backed`.
Expand Down Expand Up @@ -1155,8 +1111,8 @@ static status_t internal_ecdh_p384_finalize(
// Note: This operation wipes DMEM after retrieving the keys, so if an error
// occurs after this point then the keys would be unrecoverable. This should
// be the last potentially error-causing line before returning to the caller.
ecdh_p384_shared_key_t ss;
HARDENED_TRY(ecdh_p384_shared_key_finalize(&ss));
p384_ecdh_shared_key_t ss;
HARDENED_TRY(p384_ecdh_finalize(&ss));

keyblob_from_shares(ss.share0, ss.share1, shared_secret->config,
shared_secret->keyblob);
Expand Down
71 changes: 4 additions & 67 deletions sw/device/lib/crypto/impl/ecc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,78 +21,15 @@ cc_library(
)

cc_library(
name = "ecdh_p384",
srcs = ["ecdh_p384.c"],
hdrs = ["ecdh_p384.h"],
name = "p384",
srcs = ["p384.c"],
hdrs = ["p384.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":p384_common",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:hardened_memory",
"//sw/device/lib/crypto/drivers:otbn",
"//sw/otbn/crypto:p384_ecdh",
],
)

cc_library(
name = "ecdsa_p384",
hdrs = ["ecdsa_p384.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":ecdsa_p384_keygen",
":ecdsa_p384_sign",
":ecdsa_p384_verify",
],
)

cc_library(
name = "ecdsa_p384_keygen",
srcs = ["ecdsa_p384_keygen.c"],
hdrs = ["ecdsa_p384_keygen.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":p384_common",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:hardened_memory",
"//sw/device/lib/crypto/drivers:otbn",
"//sw/otbn/crypto:p384_ecdsa_keygen",
],
)

cc_library(
name = "ecdsa_p384_sign",
srcs = ["ecdsa_p384_sign.c"],
hdrs = ["ecdsa_p384_sign.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":p384_common",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:hardened_memory",
"//sw/device/lib/crypto/drivers:otbn",
"//sw/otbn/crypto:p384_ecdsa_sign",
],
)

cc_library(
name = "ecdsa_p384_verify",
srcs = ["ecdsa_p384_verify.c"],
hdrs = ["ecdsa_p384_verify.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":p384_common",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:hardened_memory",
"//sw/device/lib/crypto/drivers:otbn",
"//sw/otbn/crypto:p384_ecdsa_verify",
],
)

cc_library(
name = "p384_common",
srcs = ["p384_common.c"],
hdrs = ["p384_common.h"],
deps = [
"//sw/device/lib/crypto/drivers:otbn",
"//sw/device/lib/crypto/impl:status",
"//sw/otbn/crypto:run_p384",
],
)
Loading

0 comments on commit 1d2955d

Please sign in to comment.