summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/freebl/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/ec.c')
-rw-r--r--security/nss/lib/freebl/ec.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/security/nss/lib/freebl/ec.c b/security/nss/lib/freebl/ec.c
index 35a848395c..cd6a88c7b0 100644
--- a/security/nss/lib/freebl/ec.c
+++ b/security/nss/lib/freebl/ec.c
@@ -18,6 +18,7 @@
#include "verified/Hacl_P384.h"
#include "verified/Hacl_P521.h"
#include "secport.h"
+#include "verified/Hacl_Ed25519.h"
#define EC_DOUBLECHECK PR_FALSE
@@ -65,6 +66,27 @@ ec_secp521r1_scalar_validate(const SECItem *scalar)
return SECSuccess;
}
+SECStatus
+ec_ED25519_pt_validate(const SECItem *px)
+{
+ if (!px || !px->data || px->len != Ed25519_PUBLIC_KEYLEN) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+ec_ED25519_scalar_validate(const SECItem *scalar)
+{
+ if (!scalar || !scalar->data || scalar->len != Ed25519_PRIVATE_KEYLEN) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
static const ECMethod kMethods[] = {
{ ECCurve25519,
ec_Curve25519_pt_mul,
@@ -96,6 +118,12 @@ static const ECMethod kMethods[] = {
NULL,
NULL,
},
+ { ECCurve_Ed25519,
+ NULL,
+ ec_ED25519_pt_validate,
+ ec_ED25519_scalar_validate,
+ NULL,
+ NULL },
};
static const ECMethod *
@@ -353,6 +381,16 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
/* Compute corresponding public key */
/* Use curve specific code for point multiplication */
+
+ if (ecParams->name == ECCurve_Ed25519) {
+ rv = ED_DerivePublicKey(&key->privateValue, &key->publicValue);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */
+ goto done;
+ }
+
if (ecParams->fieldID.type == ec_field_plain) {
const ECMethod *method = ec_get_method_from_name(ecParams->name);
if (method == NULL || method->pt_mul == NULL) {
@@ -435,6 +473,7 @@ ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey)
uint8_t leading_coeff_mask;
switch (ecParams->name) {
+ case ECCurve_Ed25519:
case ECCurve25519:
case ECCurve_NIST_P256:
case ECCurve_NIST_P384:
@@ -490,8 +529,9 @@ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
goto cleanup;
}
rv = ec_GenerateRandomPrivateKey(ecParams, &privKeyRand);
- if (rv != SECSuccess || privKeyRand.data == NULL)
+ if (rv != SECSuccess || privKeyRand.data == NULL) {
goto cleanup;
+ }
/* generate public key */
CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyRand.data, privKeyRand.len));
@@ -1317,3 +1357,103 @@ done:
return rv;
}
+
+/*EdDSA: Currently only Ed22519 is implemented.*/
+
+/*
+** Computes the EdDSA signature on the message using the given key.
+*/
+
+SECStatus
+ec_ED25519_public_key_validate(const ECPublicKey *key)
+{
+ if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return ec_ED25519_pt_validate(&key->publicValue);
+}
+
+SECStatus
+ec_ED25519_private_key_validate(const ECPrivateKey *key)
+{
+ if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
+
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return ec_ED25519_scalar_validate(&key->privateValue);
+}
+
+SECStatus
+ED_SignMessage(ECPrivateKey *key, SECItem *signature, const SECItem *msg)
+{
+ if (!msg || !signature || signature->len != Ed25519_SIGN_LEN) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (ec_ED25519_private_key_validate(key) != SECSuccess) {
+ return SECFailure; /* error code set by ec_ED25519_scalar_validate. */
+ }
+
+ if (signature->data) {
+ Hacl_Ed25519_sign(signature->data, key->privateValue.data, msg->len,
+ msg->data);
+ }
+ signature->len = ED25519_SIGN_LEN;
+ BLAPI_CLEAR_STACK(2048);
+ return SECSuccess;
+}
+
+/*
+** Checks the signature on the given message using the key provided.
+*/
+
+SECStatus
+ED_VerifyMessage(ECPublicKey *key, const SECItem *signature,
+ const SECItem *msg)
+{
+ if (!msg || !signature || !signature->data || signature->len != Ed25519_SIGN_LEN) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (ec_ED25519_public_key_validate(key) != SECSuccess) {
+ return SECFailure; /* error code set by ec_ED25519_pt_validate. */
+ }
+
+ bool rv = Hacl_Ed25519_verify(key->publicValue.data, msg->len, msg->data,
+ signature->data);
+ BLAPI_CLEAR_STACK(2048);
+
+#if EC_DEBUG
+ printf("ED_VerifyMessage returning %s\n",
+ (rv) ? "success" : "failure");
+#endif
+
+ if (rv) {
+ return SECSuccess;
+ }
+
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ return SECFailure;
+}
+
+SECStatus
+ED_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey)
+{
+ /* Currently supporting only Ed25519.*/
+ if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != Ed25519_PUBLIC_KEYLEN) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (ec_ED25519_scalar_validate(privateKey) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ Hacl_Ed25519_secret_to_public(publicKey->data, privateKey->data);
+ return SECSuccess;
+} \ No newline at end of file