summaryrefslogtreecommitdiff
path: root/app/openssl/crypto/ecdsa
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2014-06-13 12:13:04 +0200
committerParménides GV <parmegv@sdf.org>2014-06-13 12:13:04 +0200
commit3a71bc9e4aa4296f460e2e3c55de74c9852477ad (patch)
treef816597a7c4322137f0657e7aa2bf392404d1870 /app/openssl/crypto/ecdsa
parentcfe67bfd8260253ce9288225b9e26f666d27133f (diff)
parent36247e71df88fa13c6c5a887de3b11d9a883615f (diff)
Merge branch 'feature/establish-an-upstream-relationship-with-ics-openvpn-codebase-#5381' into develop
Diffstat (limited to 'app/openssl/crypto/ecdsa')
-rw-r--r--app/openssl/crypto/ecdsa/ecdsa.h3
-rw-r--r--app/openssl/crypto/ecdsa/ecdsatest.c89
-rw-r--r--app/openssl/crypto/ecdsa/ecs_err.c5
-rw-r--r--app/openssl/crypto/ecdsa/ecs_lib.c32
-rw-r--r--app/openssl/crypto/ecdsa/ecs_locl.h13
-rw-r--r--app/openssl/crypto/ecdsa/ecs_ossl.c43
-rw-r--r--app/openssl/crypto/ecdsa/ecs_sign.c10
7 files changed, 170 insertions, 25 deletions
diff --git a/app/openssl/crypto/ecdsa/ecdsa.h b/app/openssl/crypto/ecdsa/ecdsa.h
index e61c5398..dc6a36b1 100644
--- a/app/openssl/crypto/ecdsa/ecdsa.h
+++ b/app/openssl/crypto/ecdsa/ecdsa.h
@@ -238,6 +238,7 @@ void ERR_load_ECDSA_strings(void);
/* Error codes for the ECDSA functions. */
/* Function codes. */
+#define ECDSA_F_ECDSA_CHECK 104
#define ECDSA_F_ECDSA_DATA_NEW_METHOD 100
#define ECDSA_F_ECDSA_DO_SIGN 101
#define ECDSA_F_ECDSA_DO_VERIFY 102
@@ -249,6 +250,8 @@ void ERR_load_ECDSA_strings(void);
#define ECDSA_R_ERR_EC_LIB 102
#define ECDSA_R_MISSING_PARAMETERS 103
#define ECDSA_R_NEED_NEW_SETUP_VALUES 106
+#define ECDSA_R_NONCE_CANNOT_BE_PRECOMPUTED 108
+#define ECDSA_R_NON_FIPS_METHOD 107
#define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 104
#define ECDSA_R_SIGNATURE_MALLOC_FAILED 105
diff --git a/app/openssl/crypto/ecdsa/ecdsatest.c b/app/openssl/crypto/ecdsa/ecdsatest.c
index 26a4a9ee..537bb303 100644
--- a/app/openssl/crypto/ecdsa/ecdsatest.c
+++ b/app/openssl/crypto/ecdsa/ecdsatest.c
@@ -262,6 +262,7 @@ int x9_62_tests(BIO *out)
"3238135532097973577080787768312505059318910517550078427819"
"78505179448783"))
goto x962_err;
+#ifndef OPENSSL_NO_EC2M
if (!x9_62_test_internal(out, NID_X9_62_c2tnb191v1,
"87194383164871543355722284926904419997237591535066528048",
"308992691965804947361541664549085895292153777025772063598"))
@@ -272,7 +273,7 @@ int x9_62_tests(BIO *out)
"1970303740007316867383349976549972270528498040721988191026"
"49413465737174"))
goto x962_err;
-
+#endif
ret = 1;
x962_err:
if (!restore_rand())
@@ -286,9 +287,13 @@ int test_builtin(BIO *out)
size_t crv_len = 0, n = 0;
EC_KEY *eckey = NULL, *wrong_eckey = NULL;
EC_GROUP *group;
+ ECDSA_SIG *ecdsa_sig = NULL;
unsigned char digest[20], wrong_digest[20];
- unsigned char *signature = NULL;
- unsigned int sig_len;
+ unsigned char *signature = NULL;
+ const unsigned char *sig_ptr;
+ unsigned char *sig_ptr2;
+ unsigned char *raw_buf = NULL;
+ unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len;
int nid, ret = 0;
/* fill digest values with some random data */
@@ -338,7 +343,8 @@ int test_builtin(BIO *out)
if (EC_KEY_set_group(eckey, group) == 0)
goto builtin_err;
EC_GROUP_free(group);
- if (EC_GROUP_get_degree(EC_KEY_get0_group(eckey)) < 160)
+ degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey));
+ if (degree < 160)
/* drop the curve */
{
EC_KEY_free(eckey);
@@ -414,26 +420,89 @@ int test_builtin(BIO *out)
}
BIO_printf(out, ".");
(void)BIO_flush(out);
- /* modify a single byte of the signature */
- offset = signature[10] % sig_len;
- dirt = signature[11];
- signature[offset] ^= dirt ? dirt : 1;
+ /* wrong length */
+ if (ECDSA_verify(0, digest, 20, signature, sig_len - 1,
+ eckey) == 1)
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ BIO_printf(out, ".");
+ (void)BIO_flush(out);
+
+ /* Modify a single byte of the signature: to ensure we don't
+ * garble the ASN1 structure, we read the raw signature and
+ * modify a byte in one of the bignums directly. */
+ sig_ptr = signature;
+ if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL)
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+
+ /* Store the two BIGNUMs in raw_buf. */
+ r_len = BN_num_bytes(ecdsa_sig->r);
+ s_len = BN_num_bytes(ecdsa_sig->s);
+ bn_len = (degree + 7) / 8;
+ if ((r_len > bn_len) || (s_len > bn_len))
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
+ buf_len = 2 * bn_len;
+ if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL)
+ goto builtin_err;
+ /* Pad the bignums with leading zeroes. */
+ memset(raw_buf, 0, buf_len);
+ BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len);
+ BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len);
+
+ /* Modify a single byte in the buffer. */
+ offset = raw_buf[10] % buf_len;
+ dirt = raw_buf[11] ? raw_buf[11] : 1;
+ raw_buf[offset] ^= dirt;
+ /* Now read the BIGNUMs back in from raw_buf. */
+ if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) ||
+ (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL))
+ goto builtin_err;
+
+ sig_ptr2 = signature;
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1)
{
BIO_printf(out, " failed\n");
goto builtin_err;
}
+ /* Sanity check: undo the modification and verify signature. */
+ raw_buf[offset] ^= dirt;
+ if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) ||
+ (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL))
+ goto builtin_err;
+
+ sig_ptr2 = signature;
+ sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
+ if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1)
+ {
+ BIO_printf(out, " failed\n");
+ goto builtin_err;
+ }
BIO_printf(out, ".");
(void)BIO_flush(out);
BIO_printf(out, " ok\n");
/* cleanup */
+ /* clean bogus errors */
+ ERR_clear_error();
OPENSSL_free(signature);
signature = NULL;
EC_KEY_free(eckey);
eckey = NULL;
EC_KEY_free(wrong_eckey);
wrong_eckey = NULL;
+ ECDSA_SIG_free(ecdsa_sig);
+ ecdsa_sig = NULL;
+ OPENSSL_free(raw_buf);
+ raw_buf = NULL;
}
ret = 1;
@@ -442,8 +511,12 @@ builtin_err:
EC_KEY_free(eckey);
if (wrong_eckey)
EC_KEY_free(wrong_eckey);
+ if (ecdsa_sig)
+ ECDSA_SIG_free(ecdsa_sig);
if (signature)
OPENSSL_free(signature);
+ if (raw_buf)
+ OPENSSL_free(raw_buf);
if (curves)
OPENSSL_free(curves);
diff --git a/app/openssl/crypto/ecdsa/ecs_err.c b/app/openssl/crypto/ecdsa/ecs_err.c
index 98e38d53..7406c6d8 100644
--- a/app/openssl/crypto/ecdsa/ecs_err.c
+++ b/app/openssl/crypto/ecdsa/ecs_err.c
@@ -1,6 +1,6 @@
/* crypto/ecdsa/ecs_err.c */
/* ====================================================================
- * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -70,6 +70,7 @@
static ERR_STRING_DATA ECDSA_str_functs[]=
{
+{ERR_FUNC(ECDSA_F_ECDSA_CHECK), "ECDSA_CHECK"},
{ERR_FUNC(ECDSA_F_ECDSA_DATA_NEW_METHOD), "ECDSA_DATA_NEW_METHOD"},
{ERR_FUNC(ECDSA_F_ECDSA_DO_SIGN), "ECDSA_do_sign"},
{ERR_FUNC(ECDSA_F_ECDSA_DO_VERIFY), "ECDSA_do_verify"},
@@ -84,6 +85,8 @@ static ERR_STRING_DATA ECDSA_str_reasons[]=
{ERR_REASON(ECDSA_R_ERR_EC_LIB) ,"err ec lib"},
{ERR_REASON(ECDSA_R_MISSING_PARAMETERS) ,"missing parameters"},
{ERR_REASON(ECDSA_R_NEED_NEW_SETUP_VALUES),"need new setup values"},
+{ERR_REASON(ECDSA_R_NONCE_CANNOT_BE_PRECOMPUTED),"nonce cannot be precomputed"},
+{ERR_REASON(ECDSA_R_NON_FIPS_METHOD) ,"non fips method"},
{ERR_REASON(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED),"random number generation failed"},
{ERR_REASON(ECDSA_R_SIGNATURE_MALLOC_FAILED),"signature malloc failed"},
{0,NULL}
diff --git a/app/openssl/crypto/ecdsa/ecs_lib.c b/app/openssl/crypto/ecdsa/ecs_lib.c
index 2ebae3aa..814a6bf4 100644
--- a/app/openssl/crypto/ecdsa/ecs_lib.c
+++ b/app/openssl/crypto/ecdsa/ecs_lib.c
@@ -60,6 +60,9 @@
#endif
#include <openssl/err.h>
#include <openssl/bn.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
const char ECDSA_version[]="ECDSA" OPENSSL_VERSION_PTEXT;
@@ -77,7 +80,16 @@ void ECDSA_set_default_method(const ECDSA_METHOD *meth)
const ECDSA_METHOD *ECDSA_get_default_method(void)
{
if(!default_ECDSA_method)
+ {
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return FIPS_ecdsa_openssl();
+ else
+ return ECDSA_OpenSSL();
+#else
default_ECDSA_method = ECDSA_OpenSSL();
+#endif
+ }
return default_ECDSA_method;
}
@@ -188,12 +200,26 @@ ECDSA_DATA *ecdsa_check(EC_KEY *key)
ecdsa_data = (ECDSA_DATA *)ecdsa_data_new();
if (ecdsa_data == NULL)
return NULL;
- EC_KEY_insert_key_method_data(key, (void *)ecdsa_data,
- ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free);
+ data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data,
+ ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free);
+ if (data != NULL)
+ {
+ /* Another thread raced us to install the key_method
+ * data and won. */
+ ecdsa_data_free(ecdsa_data);
+ ecdsa_data = (ECDSA_DATA *)data;
+ }
}
else
ecdsa_data = (ECDSA_DATA *)data;
-
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode() && !(ecdsa_data->flags & ECDSA_FLAG_FIPS_METHOD)
+ && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_CHECK, ECDSA_R_NON_FIPS_METHOD);
+ return NULL;
+ }
+#endif
return ecdsa_data;
}
diff --git a/app/openssl/crypto/ecdsa/ecs_locl.h b/app/openssl/crypto/ecdsa/ecs_locl.h
index 3a69a840..46f7ad91 100644
--- a/app/openssl/crypto/ecdsa/ecs_locl.h
+++ b/app/openssl/crypto/ecdsa/ecs_locl.h
@@ -70,8 +70,9 @@ struct ecdsa_method
const char *name;
ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len,
const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey);
- int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
- BIGNUM **r);
+ int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx,
+ BIGNUM **kinv, BIGNUM **r,
+ const unsigned char *dgst, int dlen);
int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
#if 0
@@ -82,6 +83,14 @@ struct ecdsa_method
char *app_data;
};
+/* If this flag is set the ECDSA method is FIPS compliant and can be used
+ * in FIPS mode. This is set in the validated module method. If an
+ * application sets this flag in its own methods it is its responsibility
+ * to ensure the result is compliant.
+ */
+
+#define ECDSA_FLAG_FIPS_METHOD 0x1
+
typedef struct ecdsa_data_st {
/* EC_KEY_METH_DATA part */
int (*init)(EC_KEY *);
diff --git a/app/openssl/crypto/ecdsa/ecs_ossl.c b/app/openssl/crypto/ecdsa/ecs_ossl.c
index 1bbf328d..325aca8c 100644
--- a/app/openssl/crypto/ecdsa/ecs_ossl.c
+++ b/app/openssl/crypto/ecdsa/ecs_ossl.c
@@ -60,11 +60,13 @@
#include <openssl/err.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
+#include <openssl/rand.h>
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen,
const BIGNUM *, const BIGNUM *, EC_KEY *eckey);
-static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
- BIGNUM **rp);
+static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
+ BIGNUM **kinvp, BIGNUM **rp,
+ const unsigned char *dgst, int dlen);
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
@@ -86,8 +88,9 @@ const ECDSA_METHOD *ECDSA_OpenSSL(void)
return &openssl_ecdsa_meth;
}
-static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
- BIGNUM **rp)
+static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
+ BIGNUM **kinvp, BIGNUM **rp,
+ const unsigned char *dgst, int dlen)
{
BN_CTX *ctx = NULL;
BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL;
@@ -136,11 +139,28 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
{
/* get random k */
do
- if (!BN_rand_range(k, order))
+#ifndef OPENSSL_NO_SHA512
+ if (EC_KEY_get_nonce_from_hash(eckey))
{
- ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
- ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
- goto err;
+ if (!BN_generate_dsa_nonce(
+ k, order,
+ EC_KEY_get0_private_key(eckey),
+ dgst, dlen, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
+ ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto err;
+ }
+ }
+ else
+#endif
+ {
+ if (!BN_rand_range(k, order))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
+ ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto err;
+ }
}
while (BN_is_zero(k));
@@ -167,6 +187,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
goto err;
}
}
+#ifndef OPENSSL_NO_EC2M
else /* NID_X9_62_characteristic_two_field */
{
if (!EC_POINT_get_affine_coordinates_GF2m(group,
@@ -176,6 +197,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
goto err;
}
}
+#endif
if (!BN_nnmod(r, X, order, ctx))
{
ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
@@ -280,7 +302,7 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
{
if (in_kinv == NULL || in_r == NULL)
{
- if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r))
+ if (!ecdsa->meth->ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
goto err;
@@ -454,6 +476,7 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
goto err;
}
}
+#ifndef OPENSSL_NO_EC2M
else /* NID_X9_62_characteristic_two_field */
{
if (!EC_POINT_get_affine_coordinates_GF2m(group,
@@ -463,7 +486,7 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
goto err;
}
}
-
+#endif
if (!BN_nnmod(u1, X, order, ctx))
{
ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
diff --git a/app/openssl/crypto/ecdsa/ecs_sign.c b/app/openssl/crypto/ecdsa/ecs_sign.c
index 353d5af5..ea79a24b 100644
--- a/app/openssl/crypto/ecdsa/ecs_sign.c
+++ b/app/openssl/crypto/ecdsa/ecs_sign.c
@@ -58,6 +58,7 @@
#include <openssl/engine.h>
#endif
#include <openssl/rand.h>
+#include <openssl/err.h>
ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
{
@@ -102,5 +103,12 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
ECDSA_DATA *ecdsa = ecdsa_check(eckey);
if (ecdsa == NULL)
return 0;
- return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
+ if (EC_KEY_get_nonce_from_hash(eckey))
+ {
+ /* You cannot precompute the ECDSA nonce if it is required to
+ * depend on the message. */
+ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_NONCE_CANNOT_BE_PRECOMPUTED);
+ return 0;
+ }
+ return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
}