crypto: ecdh - add public key verification test
diff mbox series

Message ID 1563354162-397-2-git-send-email-paolo.pisati@canonical.com
State New
Headers show
Series
  • crypto: ecdh - add public key verification test
Related show

Commit Message

Paolo Pisati July 17, 2019, 9:02 a.m. UTC
From: Stephan Mueller <smueller@chronox.de>

According to SP800-56A section 5.6.2.1, the public key to be processed
for the ECDH operation shall be checked for appropriateness. When the
public key is considered to be an ephemeral key, the partial validation
test as defined in SP800-56A section 5.6.2.3.4 can be applied.

The partial verification test requires the presence of the field
elements of a and b. For the implemented NIST curves, b is defined in
FIPS 186-4 appendix D.1.2. The element a is implicitly given with the
Weierstrass equation given in D.1.2 where a = p - 3.

Without the test, the NIST ACVP testing fails. After adding this check,
the NIST ACVP testing passes.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

CVE-2018-5383

(cherry picked from commit ea169a30a6bf6782a05a51d2b9cf73db151eab8b)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
---
 crypto/ecc.c            | 42 ++++++++++++++++++++++++++++++++++++++----
 crypto/ecc_curve_defs.h | 22 ++++++++++++++++++----
 2 files changed, 56 insertions(+), 8 deletions(-)

Comments

Stefan Bader July 18, 2019, 8:21 a.m. UTC | #1
On 17.07.19 11:02, Paolo Pisati wrote:
> From: Stephan Mueller <smueller@chronox.de>
> 
> According to SP800-56A section 5.6.2.1, the public key to be processed
> for the ECDH operation shall be checked for appropriateness. When the
> public key is considered to be an ephemeral key, the partial validation
> test as defined in SP800-56A section 5.6.2.3.4 can be applied.
> 
> The partial verification test requires the presence of the field
> elements of a and b. For the implemented NIST curves, b is defined in
> FIPS 186-4 appendix D.1.2. The element a is implicitly given with the
> Weierstrass equation given in D.1.2 where a = p - 3.
> 
> Without the test, the NIST ACVP testing fails. After adding this check,
> the NIST ACVP testing passes.
> 
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> 
> CVE-2018-5383
> 
> (cherry picked from commit ea169a30a6bf6782a05a51d2b9cf73db151eab8b)
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>  crypto/ecc.c            | 42 ++++++++++++++++++++++++++++++++++++++----
>  crypto/ecc_curve_defs.h | 22 ++++++++++++++++++----
>  2 files changed, 56 insertions(+), 8 deletions(-)
> 
> diff --git a/crypto/ecc.c b/crypto/ecc.c
> index 18f32f2..4ceec6a 100644
> --- a/crypto/ecc.c
> +++ b/crypto/ecc.c
> @@ -1019,6 +1019,36 @@ int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
>  	return ret;
>  }
>  
> +/* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
> +static int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
> +				       struct ecc_point *pk)
> +{
> +	u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
> +
> +	/* Check 1: Verify key is not the zero point. */
> +	if (ecc_point_is_zero(pk))
> +		return -EINVAL;
> +
> +	/* Check 2: Verify key is in the range [1, p-1]. */
> +	if (vli_cmp(curve->p, pk->x, pk->ndigits) != 1)
> +		return -EINVAL;
> +	if (vli_cmp(curve->p, pk->y, pk->ndigits) != 1)
> +		return -EINVAL;
> +
> +	/* Check 3: Verify that y^2 == (x^3 + a·x + b) mod p */
> +	vli_mod_square_fast(yy, pk->y, curve->p, pk->ndigits); /* y^2 */
> +	vli_mod_square_fast(xxx, pk->x, curve->p, pk->ndigits); /* x^2 */
> +	vli_mod_mult_fast(xxx, xxx, pk->x, curve->p, pk->ndigits); /* x^3 */
> +	vli_mod_mult_fast(w, curve->a, pk->x, curve->p, pk->ndigits); /* a·x */
> +	vli_mod_add(w, w, curve->b, curve->p, pk->ndigits); /* a·x + b */
> +	vli_mod_add(w, w, xxx, curve->p, pk->ndigits); /* x^3 + a·x + b */
> +	if (vli_cmp(yy, w, pk->ndigits) != 0) /* Equation */
> +		return -EINVAL;
> +
> +	return 0;
> +
> +}
> +
>  int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
>  			      const u64 *private_key, const u64 *public_key,
>  			      u64 *secret)
> @@ -1045,16 +1075,20 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
>  		goto out;
>  	}
>  
> +	ecc_swap_digits(public_key, pk->x, ndigits);
> +	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
> +	ret = ecc_is_pubkey_valid_partial(curve, pk);
> +	if (ret)
> +		goto err_alloc_product;
> +
> +	ecc_swap_digits(private_key, priv, ndigits);
> +
>  	product = ecc_alloc_point(ndigits);
>  	if (!product) {
>  		ret = -ENOMEM;
>  		goto err_alloc_product;
>  	}
>  
> -	ecc_swap_digits(public_key, pk->x, ndigits);
> -	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
> -	ecc_swap_digits(private_key, priv, ndigits);
> -
>  	ecc_point_mult(product, pk, priv, rand_z, curve->p, ndigits);
>  
>  	ecc_swap_digits(product->x, secret, ndigits);
> diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
> index b80f45d..94e883a 100644
> --- a/crypto/ecc_curve_defs.h
> +++ b/crypto/ecc_curve_defs.h
> @@ -13,9 +13,11 @@ struct ecc_curve {
>  	struct ecc_point g;
>  	u64 *p;
>  	u64 *n;
> +	u64 *a;
> +	u64 *b;
>  };
>  
> -/* NIST P-192 */
> +/* NIST P-192: a = p - 3 */
>  static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull,
>  				0x188DA80EB03090F6ull };
>  static u64 nist_p192_g_y[] = { 0x73F977A11E794811ull, 0x631011ED6B24CDD5ull,
> @@ -24,6 +26,10 @@ static u64 nist_p192_p[] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFEull,
>  				0xFFFFFFFFFFFFFFFFull };
>  static u64 nist_p192_n[] = { 0x146BC9B1B4D22831ull, 0xFFFFFFFF99DEF836ull,
>  				0xFFFFFFFFFFFFFFFFull };
> +static u64 nist_p192_a[] = { 0xFFFFFFFFFFFFFFFCull, 0xFFFFFFFFFFFFFFFEull,
> +				0xFFFFFFFFFFFFFFFEull };
> +static u64 nist_p192_b[] = { 0xFEB8DEECC146B9B1ull, 0x0FA7E9AB72243049ull,
> +				0x64210519E59C80E7ull };
>  static struct ecc_curve nist_p192 = {
>  	.name = "nist_192",
>  	.g = {
> @@ -32,10 +38,12 @@ static struct ecc_curve nist_p192 = {
>  		.ndigits = 3,
>  	},
>  	.p = nist_p192_p,
> -	.n = nist_p192_n
> +	.n = nist_p192_n,
> +	.a = nist_p192_a,
> +	.b = nist_p192_b
>  };
>  
> -/* NIST P-256 */
> +/* NIST P-256: a = p - 3 */
>  static u64 nist_p256_g_x[] = { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,
>  				0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull };
>  static u64 nist_p256_g_y[] = { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,
> @@ -44,6 +52,10 @@ static u64 nist_p256_p[] = { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull,
>  				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
>  static u64 nist_p256_n[] = { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,
>  				0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull };
> +static u64 nist_p256_a[] = { 0xFFFFFFFFFFFFFFFCull, 0x00000000FFFFFFFFull,
> +				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
> +static u64 nist_p256_b[] = { 0x3BCE3C3E27D2604Bull, 0x651D06B0CC53B0F6ull,
> +				0xB3EBBD55769886BCull, 0x5AC635D8AA3A93E7ull };
>  static struct ecc_curve nist_p256 = {
>  	.name = "nist_256",
>  	.g = {
> @@ -52,7 +64,9 @@ static struct ecc_curve nist_p256 = {
>  		.ndigits = 4,
>  	},
>  	.p = nist_p256_p,
> -	.n = nist_p256_n
> +	.n = nist_p256_n,
> +	.a = nist_p256_a,
> +	.b = nist_p256_b
>  };
>  
>  #endif
>
Connor Kuehl July 22, 2019, 6:22 p.m. UTC | #2
On 7/17/19 2:02 AM, Paolo Pisati wrote:
> From: Stephan Mueller <smueller@chronox.de>
> 
> According to SP800-56A section 5.6.2.1, the public key to be processed
> for the ECDH operation shall be checked for appropriateness. When the
> public key is considered to be an ephemeral key, the partial validation
> test as defined in SP800-56A section 5.6.2.3.4 can be applied.
> 
> The partial verification test requires the presence of the field
> elements of a and b. For the implemented NIST curves, b is defined in
> FIPS 186-4 appendix D.1.2. The element a is implicitly given with the
> Weierstrass equation given in D.1.2 where a = p - 3.
> 
> Without the test, the NIST ACVP testing fails. After adding this check,
> the NIST ACVP testing passes.
> 
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> 
> CVE-2018-5383
> 
> (cherry picked from commit ea169a30a6bf6782a05a51d2b9cf73db151eab8b)
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>

Acked-by: Connor Kuehl <connor.kuehl@canonical.com>

> ---
>  crypto/ecc.c            | 42 ++++++++++++++++++++++++++++++++++++++----
>  crypto/ecc_curve_defs.h | 22 ++++++++++++++++++----
>  2 files changed, 56 insertions(+), 8 deletions(-)
> 
> diff --git a/crypto/ecc.c b/crypto/ecc.c
> index 18f32f2..4ceec6a 100644
> --- a/crypto/ecc.c
> +++ b/crypto/ecc.c
> @@ -1019,6 +1019,36 @@ int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
>  	return ret;
>  }
>  
> +/* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
> +static int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
> +				       struct ecc_point *pk)
> +{
> +	u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
> +
> +	/* Check 1: Verify key is not the zero point. */
> +	if (ecc_point_is_zero(pk))
> +		return -EINVAL;
> +
> +	/* Check 2: Verify key is in the range [1, p-1]. */
> +	if (vli_cmp(curve->p, pk->x, pk->ndigits) != 1)
> +		return -EINVAL;
> +	if (vli_cmp(curve->p, pk->y, pk->ndigits) != 1)
> +		return -EINVAL;
> +
> +	/* Check 3: Verify that y^2 == (x^3 + a·x + b) mod p */
> +	vli_mod_square_fast(yy, pk->y, curve->p, pk->ndigits); /* y^2 */
> +	vli_mod_square_fast(xxx, pk->x, curve->p, pk->ndigits); /* x^2 */
> +	vli_mod_mult_fast(xxx, xxx, pk->x, curve->p, pk->ndigits); /* x^3 */
> +	vli_mod_mult_fast(w, curve->a, pk->x, curve->p, pk->ndigits); /* a·x */
> +	vli_mod_add(w, w, curve->b, curve->p, pk->ndigits); /* a·x + b */
> +	vli_mod_add(w, w, xxx, curve->p, pk->ndigits); /* x^3 + a·x + b */
> +	if (vli_cmp(yy, w, pk->ndigits) != 0) /* Equation */
> +		return -EINVAL;
> +
> +	return 0;
> +
> +}
> +
>  int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
>  			      const u64 *private_key, const u64 *public_key,
>  			      u64 *secret)
> @@ -1045,16 +1075,20 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
>  		goto out;
>  	}
>  
> +	ecc_swap_digits(public_key, pk->x, ndigits);
> +	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
> +	ret = ecc_is_pubkey_valid_partial(curve, pk);
> +	if (ret)
> +		goto err_alloc_product;
> +
> +	ecc_swap_digits(private_key, priv, ndigits);
> +
>  	product = ecc_alloc_point(ndigits);
>  	if (!product) {
>  		ret = -ENOMEM;
>  		goto err_alloc_product;
>  	}
>  
> -	ecc_swap_digits(public_key, pk->x, ndigits);
> -	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
> -	ecc_swap_digits(private_key, priv, ndigits);
> -
>  	ecc_point_mult(product, pk, priv, rand_z, curve->p, ndigits);
>  
>  	ecc_swap_digits(product->x, secret, ndigits);
> diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
> index b80f45d..94e883a 100644
> --- a/crypto/ecc_curve_defs.h
> +++ b/crypto/ecc_curve_defs.h
> @@ -13,9 +13,11 @@ struct ecc_curve {
>  	struct ecc_point g;
>  	u64 *p;
>  	u64 *n;
> +	u64 *a;
> +	u64 *b;
>  };
>  
> -/* NIST P-192 */
> +/* NIST P-192: a = p - 3 */
>  static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull,
>  				0x188DA80EB03090F6ull };
>  static u64 nist_p192_g_y[] = { 0x73F977A11E794811ull, 0x631011ED6B24CDD5ull,
> @@ -24,6 +26,10 @@ static u64 nist_p192_p[] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFEull,
>  				0xFFFFFFFFFFFFFFFFull };
>  static u64 nist_p192_n[] = { 0x146BC9B1B4D22831ull, 0xFFFFFFFF99DEF836ull,
>  				0xFFFFFFFFFFFFFFFFull };
> +static u64 nist_p192_a[] = { 0xFFFFFFFFFFFFFFFCull, 0xFFFFFFFFFFFFFFFEull,
> +				0xFFFFFFFFFFFFFFFEull };
> +static u64 nist_p192_b[] = { 0xFEB8DEECC146B9B1ull, 0x0FA7E9AB72243049ull,
> +				0x64210519E59C80E7ull };
>  static struct ecc_curve nist_p192 = {
>  	.name = "nist_192",
>  	.g = {
> @@ -32,10 +38,12 @@ static struct ecc_curve nist_p192 = {
>  		.ndigits = 3,
>  	},
>  	.p = nist_p192_p,
> -	.n = nist_p192_n
> +	.n = nist_p192_n,
> +	.a = nist_p192_a,
> +	.b = nist_p192_b
>  };
>  
> -/* NIST P-256 */
> +/* NIST P-256: a = p - 3 */
>  static u64 nist_p256_g_x[] = { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,
>  				0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull };
>  static u64 nist_p256_g_y[] = { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,
> @@ -44,6 +52,10 @@ static u64 nist_p256_p[] = { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull,
>  				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
>  static u64 nist_p256_n[] = { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,
>  				0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull };
> +static u64 nist_p256_a[] = { 0xFFFFFFFFFFFFFFFCull, 0x00000000FFFFFFFFull,
> +				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
> +static u64 nist_p256_b[] = { 0x3BCE3C3E27D2604Bull, 0x651D06B0CC53B0F6ull,
> +				0xB3EBBD55769886BCull, 0x5AC635D8AA3A93E7ull };
>  static struct ecc_curve nist_p256 = {
>  	.name = "nist_256",
>  	.g = {
> @@ -52,7 +64,9 @@ static struct ecc_curve nist_p256 = {
>  		.ndigits = 4,
>  	},
>  	.p = nist_p256_p,
> -	.n = nist_p256_n
> +	.n = nist_p256_n,
> +	.a = nist_p256_a,
> +	.b = nist_p256_b
>  };
>  
>  #endif
>

Patch
diff mbox series

diff --git a/crypto/ecc.c b/crypto/ecc.c
index 18f32f2..4ceec6a 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1019,6 +1019,36 @@  int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
 	return ret;
 }
 
+/* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
+static int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
+				       struct ecc_point *pk)
+{
+	u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
+
+	/* Check 1: Verify key is not the zero point. */
+	if (ecc_point_is_zero(pk))
+		return -EINVAL;
+
+	/* Check 2: Verify key is in the range [1, p-1]. */
+	if (vli_cmp(curve->p, pk->x, pk->ndigits) != 1)
+		return -EINVAL;
+	if (vli_cmp(curve->p, pk->y, pk->ndigits) != 1)
+		return -EINVAL;
+
+	/* Check 3: Verify that y^2 == (x^3 + a·x + b) mod p */
+	vli_mod_square_fast(yy, pk->y, curve->p, pk->ndigits); /* y^2 */
+	vli_mod_square_fast(xxx, pk->x, curve->p, pk->ndigits); /* x^2 */
+	vli_mod_mult_fast(xxx, xxx, pk->x, curve->p, pk->ndigits); /* x^3 */
+	vli_mod_mult_fast(w, curve->a, pk->x, curve->p, pk->ndigits); /* a·x */
+	vli_mod_add(w, w, curve->b, curve->p, pk->ndigits); /* a·x + b */
+	vli_mod_add(w, w, xxx, curve->p, pk->ndigits); /* x^3 + a·x + b */
+	if (vli_cmp(yy, w, pk->ndigits) != 0) /* Equation */
+		return -EINVAL;
+
+	return 0;
+
+}
+
 int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
 			      const u64 *private_key, const u64 *public_key,
 			      u64 *secret)
@@ -1045,16 +1075,20 @@  int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
 		goto out;
 	}
 
+	ecc_swap_digits(public_key, pk->x, ndigits);
+	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
+	ret = ecc_is_pubkey_valid_partial(curve, pk);
+	if (ret)
+		goto err_alloc_product;
+
+	ecc_swap_digits(private_key, priv, ndigits);
+
 	product = ecc_alloc_point(ndigits);
 	if (!product) {
 		ret = -ENOMEM;
 		goto err_alloc_product;
 	}
 
-	ecc_swap_digits(public_key, pk->x, ndigits);
-	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
-	ecc_swap_digits(private_key, priv, ndigits);
-
 	ecc_point_mult(product, pk, priv, rand_z, curve->p, ndigits);
 
 	ecc_swap_digits(product->x, secret, ndigits);
diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
index b80f45d..94e883a 100644
--- a/crypto/ecc_curve_defs.h
+++ b/crypto/ecc_curve_defs.h
@@ -13,9 +13,11 @@  struct ecc_curve {
 	struct ecc_point g;
 	u64 *p;
 	u64 *n;
+	u64 *a;
+	u64 *b;
 };
 
-/* NIST P-192 */
+/* NIST P-192: a = p - 3 */
 static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull,
 				0x188DA80EB03090F6ull };
 static u64 nist_p192_g_y[] = { 0x73F977A11E794811ull, 0x631011ED6B24CDD5ull,
@@ -24,6 +26,10 @@  static u64 nist_p192_p[] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFEull,
 				0xFFFFFFFFFFFFFFFFull };
 static u64 nist_p192_n[] = { 0x146BC9B1B4D22831ull, 0xFFFFFFFF99DEF836ull,
 				0xFFFFFFFFFFFFFFFFull };
+static u64 nist_p192_a[] = { 0xFFFFFFFFFFFFFFFCull, 0xFFFFFFFFFFFFFFFEull,
+				0xFFFFFFFFFFFFFFFEull };
+static u64 nist_p192_b[] = { 0xFEB8DEECC146B9B1ull, 0x0FA7E9AB72243049ull,
+				0x64210519E59C80E7ull };
 static struct ecc_curve nist_p192 = {
 	.name = "nist_192",
 	.g = {
@@ -32,10 +38,12 @@  static struct ecc_curve nist_p192 = {
 		.ndigits = 3,
 	},
 	.p = nist_p192_p,
-	.n = nist_p192_n
+	.n = nist_p192_n,
+	.a = nist_p192_a,
+	.b = nist_p192_b
 };
 
-/* NIST P-256 */
+/* NIST P-256: a = p - 3 */
 static u64 nist_p256_g_x[] = { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,
 				0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull };
 static u64 nist_p256_g_y[] = { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,
@@ -44,6 +52,10 @@  static u64 nist_p256_p[] = { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull,
 				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
 static u64 nist_p256_n[] = { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,
 				0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull };
+static u64 nist_p256_a[] = { 0xFFFFFFFFFFFFFFFCull, 0x00000000FFFFFFFFull,
+				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
+static u64 nist_p256_b[] = { 0x3BCE3C3E27D2604Bull, 0x651D06B0CC53B0F6ull,
+				0xB3EBBD55769886BCull, 0x5AC635D8AA3A93E7ull };
 static struct ecc_curve nist_p256 = {
 	.name = "nist_256",
 	.g = {
@@ -52,7 +64,9 @@  static struct ecc_curve nist_p256 = {
 		.ndigits = 4,
 	},
 	.p = nist_p256_p,
-	.n = nist_p256_n
+	.n = nist_p256_n,
+	.a = nist_p256_a,
+	.b = nist_p256_b
 };
 
 #endif