Add SRP support.
[oweals/openssl.git] / crypto / ec / ec_key.c
index 12fb0e6d6d7378d57e0ec2965f97eb62cd001d6d..1615ec8a5a7204b760e2a8beb039bd6e67169635 100644 (file)
@@ -61,6 +61,8 @@
  * contributed to the OpenSSL project.
  */
 
+#define OPENSSL_FIPSAPI
+
 #include <string.h>
 #include "ec_lcl.h"
 #include <openssl/err.h>
@@ -230,6 +232,35 @@ int EC_KEY_up_ref(EC_KEY *r)
        return ((i > 1) ? 1 : 0);
        }
 
+#ifdef OPENSSL_FIPS
+
+#include <openssl/evp.h>
+
+static int fips_ec_pairwise_fail = 0;
+
+void FIPS_corrupt_ec_keygen(void)
+       {
+       fips_ec_pairwise_fail = 1;
+       }
+
+static int fips_check_ec(EC_KEY *key)
+       {
+       EVP_PKEY pk;
+       unsigned char tbs[] = "ECDSA Pairwise Check Data";
+       pk.type = EVP_PKEY_EC;
+       pk.pkey.ec = key;
+
+       if (!fips_pkey_signature_test(&pk, tbs, -1, NULL, 0, NULL, 0, NULL))
+               {
+               FIPSerr(FIPS_F_FIPS_CHECK_EC,FIPS_R_PAIRWISE_TEST_FAILED);
+               fips_set_selftest_fail();
+               return 0;
+               }
+       return 1;
+       }
+
+#endif
+
 int EC_KEY_generate_key(EC_KEY *eckey)
        {       
        int     ok = 0;
@@ -278,6 +309,17 @@ int EC_KEY_generate_key(EC_KEY *eckey)
        eckey->priv_key = priv_key;
        eckey->pub_key  = pub_key;
 
+#ifdef OPENSSL_FIPS
+       if (fips_ec_pairwise_fail)
+               BN_add_word(eckey->priv_key, 1);
+       if(!fips_check_ec(eckey))
+               {
+               eckey->priv_key = NULL;
+               eckey->pub_key  = NULL;
+               goto err;
+               }
+#endif
+
        ok=1;
 
 err:   
@@ -304,7 +346,13 @@ int EC_KEY_check_key(const EC_KEY *eckey)
                ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
                return 0;
                }
-       
+
+       if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key))
+               {
+               ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
+               goto err;
+               }
+
        if ((ctx = BN_CTX_new()) == NULL)
                goto err;
        if ((point = EC_POINT_new(eckey->group)) == NULL)
@@ -365,6 +413,82 @@ err:
        return(ok);
        }
 
+int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
+       {
+       BN_CTX *ctx = NULL;
+       BIGNUM *tx, *ty;
+       EC_POINT *point = NULL;
+       int ok = 0, tmp_nid, is_char_two = 0;
+
+       if (!key || !key->group || !x || !y)
+               {
+               ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
+                                               ERR_R_PASSED_NULL_PARAMETER);
+               return 0;
+               }
+       ctx = BN_CTX_new();
+       if (!ctx)
+               goto err;
+
+       point = EC_POINT_new(key->group);
+
+       if (!point)
+               goto err;
+
+       tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
+
+        if (tmp_nid == NID_X9_62_characteristic_two_field)
+               is_char_two = 1;
+
+       tx = BN_CTX_get(ctx);
+       ty = BN_CTX_get(ctx);
+#ifndef OPENSSL_NO_EC2M
+       if (is_char_two)
+               {
+               if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
+                                                               x, y, ctx))
+                       goto err;
+               if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
+                                                               tx, ty, ctx))
+                       goto err;
+               }
+       else
+#endif
+               {
+               if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
+                                                               x, y, ctx))
+                       goto err;
+               if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
+                                                               tx, ty, ctx))
+                       goto err;
+               }
+       /* Check if retrieved coordinates match originals: if not values
+        * are out of range.
+        */
+       if (BN_cmp(x, tx) || BN_cmp(y, ty))
+               {
+               ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
+                       EC_R_COORDINATES_OUT_OF_RANGE);
+               goto err;
+               }
+
+       if (!EC_KEY_set_public_key(key, point))
+               goto err;
+
+       if (EC_KEY_check_key(key) == 0)
+               goto err;
+
+       ok = 1;
+
+       err:
+       if (ctx)
+               BN_CTX_free(ctx);
+       if (point)
+               EC_POINT_free(point);
+       return ok;
+
+       }
+
 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
        {
        return key->group;