b355146
/*
31d61b1
 * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
9189f03
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
b355146
 *
510bcc2
 * Licensed under the OpenSSL license (the "License").  You may not use
510bcc2
 * this file except in compliance with the License.  You can obtain a copy
510bcc2
 * in the file LICENSE in the source distribution or at
510bcc2
 * https://www.openssl.org/source/license.html
b355146
 */
510bcc2
9189f03
#include "internal/nelem.h"
9189f03
#include "testutil.h"
b355146
9189f03
#ifndef OPENSSL_NO_EC
a1fb602
# include <openssl/ec.h>
a1fb602
# ifndef OPENSSL_NO_ENGINE
a1fb602
#  include <openssl/engine.h>
a1fb602
# endif
a1fb602
# include <openssl/err.h>
a1fb602
# include <openssl/obj_mac.h>
a1fb602
# include <openssl/objects.h>
a1fb602
# include <openssl/rand.h>
a1fb602
# include <openssl/bn.h>
a1fb602
# include <openssl/opensslconf.h>
a1fb602
9189f03
static size_t crv_len = 0;
9189f03
static EC_builtin_curve *curves = NULL;
b355146
b355146
/* test multiplication with group order, long and negative scalars */
9189f03
static int group_order_tests(EC_GROUP *group)
a1fb602
{
9189f03
    BIGNUM *n1 = NULL, *n2 = NULL, *order = NULL;
9189f03
    EC_POINT *P = NULL, *Q = NULL, *R = NULL, *S = NULL;
62ec0f1
    const EC_POINT *G = NULL;
9189f03
    BN_CTX *ctx = NULL;
9189f03
    int i = 0, r = 0;
9189f03
9189f03
    if (!TEST_ptr(n1 = BN_new())
9189f03
        || !TEST_ptr(n2 = BN_new())
9189f03
        || !TEST_ptr(order = BN_new())
9189f03
        || !TEST_ptr(ctx = BN_CTX_new())
62ec0f1
        || !TEST_ptr(G = EC_GROUP_get0_generator(group))
9189f03
        || !TEST_ptr(P = EC_POINT_new(group))
9189f03
        || !TEST_ptr(Q = EC_POINT_new(group))
9189f03
        || !TEST_ptr(R = EC_POINT_new(group))
9189f03
        || !TEST_ptr(S = EC_POINT_new(group)))
9189f03
        goto err;
9189f03
9189f03
    if (!TEST_true(EC_GROUP_get_order(group, order, ctx))
9189f03
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
9189f03
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
9189f03
        || !TEST_true(EC_GROUP_precompute_mult(group, ctx))
9189f03
        || !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
62ec0f1
        || !TEST_true(EC_POINT_is_at_infinity(group, Q))
62ec0f1
        || !TEST_true(EC_POINT_copy(P, G))
62ec0f1
        || !TEST_true(BN_one(n1))
62ec0f1
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
62ec0f1
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
62ec0f1
        || !TEST_true(BN_sub(n1, order, n1))
62ec0f1
        || !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
62ec0f1
        || !TEST_true(EC_POINT_invert(group, Q, ctx))
62ec0f1
        || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
9189f03
        goto err;
9189f03
a1fb602
    for (i = 1; i <= 2; i++) {
a1fb602
        const BIGNUM *scalars[6];
a1fb602
        const EC_POINT *points[6];
a1fb602
9189f03
        if (!TEST_true(BN_set_word(n1, i))
9189f03
            /*
9189f03
             * If i == 1, P will be the predefined generator for which
9189f03
             * EC_GROUP_precompute_mult has set up precomputation.
9189f03
             */
9189f03
            || !TEST_true(EC_POINT_mul(group, P, n1, NULL, NULL, ctx))
62ec0f1
            || (i == 1 && !TEST_int_eq(0, EC_POINT_cmp(group, P, G, ctx)))
9189f03
            || !TEST_true(BN_one(n1))
9189f03
            /* n1 = 1 - order */
9189f03
            || !TEST_true(BN_sub(n1, n1, order))
9189f03
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n1, ctx))
9189f03
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
9189f03
9189f03
            /* n2 = 1 + order */
9189f03
            || !TEST_true(BN_add(n2, order, BN_value_one()))
9189f03
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
9189f03
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
9189f03
9189f03
            /* n2 = (1 - order) * (1 + order) = 1 - order^2 */
9189f03
            || !TEST_true(BN_mul(n2, n1, n2, ctx))
9189f03
            || !TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
9189f03
            || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
9189f03
            goto err;
a1fb602
a1fb602
        /* n2 = order^2 - 1 */
a1fb602
        BN_set_negative(n2, 0);
9189f03
        if (!TEST_true(EC_POINT_mul(group, Q, NULL, P, n2, ctx))
9189f03
            /* Add P to verify the result. */
9189f03
            || !TEST_true(EC_POINT_add(group, Q, Q, P, ctx))
9189f03
            || !TEST_true(EC_POINT_is_at_infinity(group, Q))
9189f03
9189f03
            /* Exercise EC_POINTs_mul, including corner cases. */
9189f03
            || !TEST_false(EC_POINT_is_at_infinity(group, P)))
9189f03
            goto err;
510bcc2
510bcc2
        scalars[0] = scalars[1] = BN_value_one();
510bcc2
        points[0]  = points[1]  = P;
510bcc2
9189f03
        if (!TEST_true(EC_POINTs_mul(group, R, NULL, 2, points, scalars, ctx))
9189f03
            || !TEST_true(EC_POINT_dbl(group, S, points[0], ctx))
9189f03
            || !TEST_int_eq(0, EC_POINT_cmp(group, R, S, ctx)))
9189f03
            goto err;
510bcc2
a1fb602
        scalars[0] = n1;
a1fb602
        points[0] = Q;          /* => infinity */
a1fb602
        scalars[1] = n2;
a1fb602
        points[1] = P;          /* => -P */
a1fb602
        scalars[2] = n1;
a1fb602
        points[2] = Q;          /* => infinity */
a1fb602
        scalars[3] = n2;
a1fb602
        points[3] = Q;          /* => infinity */
a1fb602
        scalars[4] = n1;
a1fb602
        points[4] = P;          /* => P */
a1fb602
        scalars[5] = n2;
a1fb602
        points[5] = Q;          /* => infinity */
9189f03
        if (!TEST_true(EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))
9189f03
            || !TEST_true(EC_POINT_is_at_infinity(group, P)))
9189f03
            goto err;
a1fb602
    }
a1fb602
9189f03
    r = 1;
9189f03
err:
9189f03
    if (r == 0 && i != 0)
9189f03
        TEST_info(i == 1 ? "allowing precomputation" :
9189f03
                           "without precomputation");
a1fb602
    EC_POINT_free(P);
a1fb602
    EC_POINT_free(Q);
510bcc2
    EC_POINT_free(R);
510bcc2
    EC_POINT_free(S);
a1fb602
    BN_free(n1);
a1fb602
    BN_free(n2);
a1fb602
    BN_free(order);
a1fb602
    BN_CTX_free(ctx);
9189f03
    return r;
a1fb602
}
b355146
9189f03
static int prime_field_tests(void)
a1fb602
{
a1fb602
    BN_CTX *ctx = NULL;
9189f03
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *scalar3 = NULL;
9189f03
    EC_GROUP *group = NULL, *tmp = NULL;
9189f03
    EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL,
9189f03
             *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
9189f03
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
9189f03
    BIGNUM *x = NULL, *y = NULL, *z = NULL, *yplusone = NULL;
9189f03
    const EC_POINT *points[4];
9189f03
    const BIGNUM *scalars[4];
a1fb602
    unsigned char buf[100];
9189f03
    size_t len, r = 0;
a1fb602
    int k;
a1fb602
9189f03
    if (!TEST_ptr(ctx = BN_CTX_new())
9189f03
        || !TEST_ptr(p = BN_new())
9189f03
        || !TEST_ptr(a = BN_new())
9189f03
        || !TEST_ptr(b = BN_new())
9189f03
        /*
9189f03
         * applications should use EC_GROUP_new_curve_GFp so
9189f03
         * that the library gets to choose the EC_METHOD
9189f03
         */
9189f03
        || !TEST_ptr(group = EC_GROUP_new(EC_GFp_mont_method()))
9189f03
        || !TEST_ptr(tmp = EC_GROUP_new(EC_GROUP_method_of(group)))
9189f03
        || !TEST_true(EC_GROUP_copy(tmp, group)))
9189f03
        goto err;
9189f03
    EC_GROUP_free(group);
9189f03
    group = tmp;
9189f03
    tmp = NULL;
9189f03
9189f03
    buf[0] = 0;
9189f03
    if (!TEST_ptr(P = EC_POINT_new(group))
9189f03
        || !TEST_ptr(Q = EC_POINT_new(group))
9189f03
        || !TEST_ptr(R = EC_POINT_new(group))
9189f03
        || !TEST_ptr(x = BN_new())
9189f03
        || !TEST_ptr(y = BN_new())
9189f03
        || !TEST_ptr(z = BN_new())
9189f03
        || !TEST_ptr(yplusone = BN_new()))
9189f03
        goto err;
a1fb602
e443a79
    /* Curve P-224 (FIPS PUB 186-2, App. 6) */
e443a79
9189f03
    if (!TEST_true(BN_hex2bn(&p,         "FFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFF000000000000000000000001"))
9189f03
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
9189f03
        || !TEST_true(BN_hex2bn(&a,         "FFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))
9189f03
        || !TEST_true(BN_hex2bn(&b,         "B4050A850C04B3ABF5413256"
9189f03
                                    "5044B0B7D7BFD8BA270B39432355FFB4"))
62ec0f1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
9189f03
        || !TEST_true(BN_hex2bn(&x,         "B70E0CBD6BB4BF7F321390B9"
9189f03
                                    "4A03C1D356C21122343280D6115C1D21"))
62ec0f1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
9189f03
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
9189f03
        || !TEST_true(BN_hex2bn(&z,         "FFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFF16A2E0B8F03E13DD29455C5C2A3D"))
9189f03
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
62ec0f1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
9189f03
        goto err;
9189f03
9189f03
    TEST_info("NIST curve P-224 -- Generator");
9189f03
    test_output_bignum("x", x);
9189f03
    test_output_bignum("y", y);
e443a79
    /* G_y value taken from the standard: */
9189f03
    if (!TEST_true(BN_hex2bn(&z,         "BD376388B5F723FB4C22DFE6"
9189f03
                                 "CD4375A05A07476444D5819985007E34"))
9189f03
        || !TEST_BN_eq(y, z)
9189f03
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
e443a79
    /*
e443a79
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
e443a79
     * and therefore setting the coordinates should fail.
e443a79
     */
62ec0f1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
62ec0f1
                                                       ctx))
9189f03
        || !TEST_int_eq(EC_GROUP_get_degree(group), 224)
9189f03
        || !group_order_tests(group)
9189f03
        || !TEST_ptr(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))
9189f03
        || !TEST_true(EC_GROUP_copy(P_224, group))
e443a79
a1fb602
    /* Curve P-256 (FIPS PUB 186-2, App. 6) */
a1fb602
9189f03
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFF000000010000000000000000"
9189f03
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFF"))
9189f03
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
9189f03
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFF000000010000000000000000"
9189f03
                                    "00000000FFFFFFFFFFFFFFFFFFFFFFFC"))
9189f03
        || !TEST_true(BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC"
9189f03
                                    "651D06B0CC53B0F63BCE3C3E27D2604B"))
62ec0f1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
9189f03
9189f03
        || !TEST_true(BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F2"
9189f03
                                    "77037D812DEB33A0F4A13945D898C296"))
62ec0f1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
9189f03
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
9189f03
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
9189f03
                                    "BCE6FAADA7179E84F3B9CAC2FC632551"))
9189f03
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
62ec0f1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
9189f03
        goto err;
9189f03
9189f03
    TEST_info("NIST curve P-256 -- Generator");
9189f03
    test_output_bignum("x", x);
9189f03
    test_output_bignum("y", y);
a1fb602
    /* G_y value taken from the standard: */
9189f03
    if (!TEST_true(BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
9189f03
                                 "2BCE33576B315ECECBB6406837BF51F5"))
9189f03
        || !TEST_BN_eq(y, z)
9189f03
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
510bcc2
    /*
510bcc2
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
510bcc2
     * and therefore setting the coordinates should fail.
510bcc2
     */
62ec0f1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
62ec0f1
                                                       ctx))
9189f03
        || !TEST_int_eq(EC_GROUP_get_degree(group), 256)
9189f03
        || !group_order_tests(group)
9189f03
        || !TEST_ptr(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))
9189f03
        || !TEST_true(EC_GROUP_copy(P_256, group))
a1fb602
a1fb602
    /* Curve P-384 (FIPS PUB 186-2, App. 6) */
a1fb602
9189f03
        || !TEST_true(BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
9189f03
                                    "FFFFFFFF0000000000000000FFFFFFFF"))
9189f03
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
9189f03
        || !TEST_true(BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
9189f03
                                    "FFFFFFFF0000000000000000FFFFFFFC"))
9189f03
        || !TEST_true(BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19"
9189f03
                                    "181D9C6EFE8141120314088F5013875A"
9189f03
                                    "C656398D8A2ED19D2A85C8EDD3EC2AEF"))
62ec0f1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
9189f03
9189f03
        || !TEST_true(BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD74"
9189f03
                                    "6E1D3B628BA79B9859F741E082542A38"
9189f03
                                    "5502F25DBF55296C3A545E3872760AB7"))
62ec0f1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx))
9189f03
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
9189f03
        || !TEST_true(BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
9189f03
                                    "581A0DB248B0A77AECEC196ACCC52973"))
9189f03
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
62ec0f1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
9189f03
        goto err;
9189f03
9189f03
    TEST_info("NIST curve P-384 -- Generator");
9189f03
    test_output_bignum("x", x);
9189f03
    test_output_bignum("y", y);
a1fb602
    /* G_y value taken from the standard: */
9189f03
    if (!TEST_true(BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29"
9189f03
                                 "F8F41DBD289A147CE9DA3113B5F0B8C0"
9189f03
                                 "0A60B1CE1D7E819D7A431D7C90EA0E5F"))
9189f03
        || !TEST_BN_eq(y, z)
9189f03
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
510bcc2
    /*
510bcc2
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
510bcc2
     * and therefore setting the coordinates should fail.
510bcc2
     */
62ec0f1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
62ec0f1
                                                       ctx))
9189f03
        || !TEST_int_eq(EC_GROUP_get_degree(group), 384)
9189f03
        || !group_order_tests(group)
9189f03
        || !TEST_ptr(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))
9189f03
        || !TEST_true(EC_GROUP_copy(P_384, group))
a1fb602
a1fb602
    /* Curve P-521 (FIPS PUB 186-2, App. 6) */
9189f03
        || !TEST_true(BN_hex2bn(&p,                              "1FF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))
9189f03
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
9189f03
        || !TEST_true(BN_hex2bn(&a,                              "1FF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))
9189f03
        || !TEST_true(BN_hex2bn(&b,                              "051"
9189f03
                                    "953EB9618E1C9A1F929A21A0B68540EE"
9189f03
                                    "A2DA725B99B315F3B8B489918EF109E1"
9189f03
                                    "56193951EC7E937B1652C0BD3BB1BF07"
9189f03
                                    "3573DF883D2C34F1EF451FD46B503F00"))
62ec0f1
        || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
9189f03
        || !TEST_true(BN_hex2bn(&x,                               "C6"
9189f03
                                    "858E06B70404E9CD9E3ECB662395B442"
9189f03
                                    "9C648139053FB521F828AF606B4D3DBA"
9189f03
                                    "A14B5E77EFE75928FE1DC127A2FFA8DE"
9189f03
                                    "3348B3C1856A429BF97E7E31C2E5BD66"))
62ec0f1
        || !TEST_true(EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx))
9189f03
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
9189f03
        || !TEST_true(BN_hex2bn(&z,                              "1FF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
9189f03
                                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA"
9189f03
                                    "51868783BF2F966B7FCC0148F709A5D0"
9189f03
                                    "3BB5C9B8899C47AEBB6FB71E91386409"))
9189f03
        || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one()))
62ec0f1
        || !TEST_true(EC_POINT_get_affine_coordinates(group, P, x, y, ctx)))
9189f03
        goto err;
9189f03
9189f03
    TEST_info("NIST curve P-521 -- Generator");
9189f03
    test_output_bignum("x", x);
9189f03
    test_output_bignum("y", y);
a1fb602
    /* G_y value taken from the standard: */
9189f03
    if (!TEST_true(BN_hex2bn(&z,                              "118"
9189f03
                                 "39296A789A3BC0045C8A5FB42C7D1BD9"
9189f03
                                 "98F54449579B446817AFBD17273E662C"
9189f03
                                 "97EE72995EF42640C550B9013FAD0761"
9189f03
                                 "353C7086A272C24088BE94769FD16650"))
9189f03
        || !TEST_BN_eq(y, z)
9189f03
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
510bcc2
    /*
510bcc2
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
510bcc2
     * and therefore setting the coordinates should fail.
510bcc2
     */
62ec0f1
        || !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
62ec0f1
                                                       ctx))
9189f03
        || !TEST_int_eq(EC_GROUP_get_degree(group), 521)
9189f03
        || !group_order_tests(group)
9189f03
        || !TEST_ptr(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))
9189f03
        || !TEST_true(EC_GROUP_copy(P_521, group))
a1fb602
a1fb602
    /* more tests using the last curve */
a1fb602
510bcc2
    /* Restore the point that got mangled in the (x, y + 1) test. */
62ec0f1
        || !TEST_true(EC_POINT_set_affine_coordinates(group, P, x, y, ctx))
9189f03
        || !TEST_true(EC_POINT_copy(Q, P))
9189f03
        || !TEST_false(EC_POINT_is_at_infinity(group, Q))
9189f03
        || !TEST_true(EC_POINT_dbl(group, P, P, ctx))
9189f03
        || !TEST_int_gt(EC_POINT_is_on_curve(group, P, ctx), 0)
9189f03
        || !TEST_true(EC_POINT_invert(group, Q, ctx))       /* P = -2Q */
9189f03
        || !TEST_true(EC_POINT_add(group, R, P, Q, ctx))
9189f03
        || !TEST_true(EC_POINT_add(group, R, R, Q, ctx))
9189f03
        || !TEST_true(EC_POINT_is_at_infinity(group, R))    /* R = P + 2Q */
9189f03
        || !TEST_false(EC_POINT_is_at_infinity(group, Q)))
9189f03
        goto err;
9189f03
    points[0] = Q;
9189f03
    points[1] = Q;
9189f03
    points[2] = Q;
9189f03
    points[3] = Q;
9189f03
9189f03
    if (!TEST_true(EC_GROUP_get_order(group, z, ctx))
9189f03
        || !TEST_true(BN_add(y, z, BN_value_one()))
9189f03
        || !TEST_BN_even(y)
9189f03
        || !TEST_true(BN_rshift1(y, y)))
9189f03
        goto err;
9189f03
    scalars[0] = y;         /* (group order + 1)/2, so y*Q + y*Q = Q */
9189f03
    scalars[1] = y;
9189f03
9189f03
    TEST_note("combined multiplication ...");
9189f03
9189f03
    /* z is still the group order */
9189f03
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
9189f03
        || !TEST_true(EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))
9189f03
        || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))
9189f03
        || !TEST_int_eq(0, EC_POINT_cmp(group, R, Q, ctx))
9189f03
        || !TEST_true(BN_rand(y, BN_num_bits(y), 0, 0))
9189f03
        || !TEST_true(BN_add(z, z, y)))
9189f03
        goto err;
9189f03
    BN_set_negative(z, 1);
9189f03
    scalars[0] = y;
9189f03
    scalars[1] = z;         /* z = -(order + y) */
9189f03
9189f03
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
9189f03
        || !TEST_true(EC_POINT_is_at_infinity(group, P))
9189f03
        || !TEST_true(BN_rand(x, BN_num_bits(y) - 1, 0, 0))
9189f03
        || !TEST_true(BN_add(z, x, y)))
9189f03
        goto err;
9189f03
    BN_set_negative(z, 1);
9189f03
    scalars[0] = x;
9189f03
    scalars[1] = y;
9189f03
    scalars[2] = z;         /* z = -(x+y) */
9189f03
9189f03
    if (!TEST_ptr(scalar3 = BN_new()))
9189f03
        goto err;
9189f03
    BN_zero(scalar3);
9189f03
    scalars[3] = scalar3;
9189f03
9189f03
    if (!TEST_true(EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx))
9189f03
        || !TEST_true(EC_POINT_is_at_infinity(group, P)))
9189f03
        goto err;
9189f03
9189f03
    TEST_note(" ok\n");
9189f03
9189f03
9189f03
    r = 1;
9189f03
err:
510bcc2
    BN_CTX_free(ctx);
a1fb602
    BN_free(p);
a1fb602
    BN_free(a);
a1fb602
    BN_free(b);
a1fb602
    EC_GROUP_free(group);
9189f03
    EC_GROUP_free(tmp);
a1fb602
    EC_POINT_free(P);
a1fb602
    EC_POINT_free(Q);
a1fb602
    EC_POINT_free(R);
a1fb602
    BN_free(x);
a1fb602
    BN_free(y);
a1fb602
    BN_free(z);
510bcc2
    BN_free(yplusone);
9189f03
    BN_free(scalar3);
a1fb602
e443a79
    EC_GROUP_free(P_224);
510bcc2
    EC_GROUP_free(P_256);
510bcc2
    EC_GROUP_free(P_384);
510bcc2
    EC_GROUP_free(P_521);
9189f03
    return r;
a1fb602
}
b355146
9189f03
static int internal_curve_test(int n)
a1fb602
{
9189f03
    EC_GROUP *group = NULL;
9189f03
    int nid = curves[n].nid;
a1fb602
9189f03
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
9189f03
        TEST_info("EC_GROUP_new_curve_name() failed with curve %s\n",
9189f03
                  OBJ_nid2sn(nid));
9189f03
        return 0;
a1fb602
    }
9189f03
    if (!TEST_true(EC_GROUP_check(group, NULL))) {
9189f03
        TEST_info("EC_GROUP_check() failed with curve %s\n", OBJ_nid2sn(nid));
a1fb602
        EC_GROUP_free(group);
9189f03
        return 0;
a1fb602
    }
9189f03
    EC_GROUP_free(group);
9189f03
    return 1;
9189f03
}
510bcc2
9189f03
static int internal_curve_test_method(int n)
9189f03
{
9189f03
    int r, nid = curves[n].nid;
9189f03
    EC_GROUP *group;
510bcc2
9189f03
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))) {
9189f03
        TEST_info("Curve %s failed\n", OBJ_nid2sn(nid));
9189f03
        return 0;
9189f03
    }
9189f03
    r = group_order_tests(group);
9189f03
    EC_GROUP_free(group);
9189f03
    return r;
a1fb602
}
a1fb602
a1fb602
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
a1fb602
/*
a1fb602
 * nistp_test_params contains magic numbers for testing our optimized
a1fb602
 * implementations of several NIST curves with characteristic > 3.
a1fb602
 */
a1fb602
struct nistp_test_params {
62ec0f1
    const EC_METHOD *(*meth) (void);
a1fb602
    int degree;
a1fb602
    /*
a1fb602
     * Qx, Qy and D are taken from
e7a0ff5
     * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
a1fb602
     * Otherwise, values are standard curve parameters from FIPS 180-3
a1fb602
     */
a1fb602
    const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
a1fb602
};
a1fb602
a1fb602
static const struct nistp_test_params nistp_tests_params[] = {
a1fb602
    {
9189f03
     /* P-224 */
9189f03
     EC_GFp_nistp224_method,
9189f03
     224,
9189f03
     /* p */
9189f03
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
9189f03
     /* a */
9189f03
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
9189f03
     /* b */
9189f03
     "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
9189f03
     /* Qx */
9189f03
     "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E",
9189f03
     /* Qy */
9189f03
     "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555",
9189f03
     /* Gx */
9189f03
     "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
9189f03
     /* Gy */
9189f03
     "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
9189f03
     /* order */
9189f03
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
9189f03
     /* d */
9189f03
     "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8",
9189f03
     },
9189f03
    {
a1fb602
     /* P-256 */
a1fb602
     EC_GFp_nistp256_method,
a1fb602
     256,
a1fb602
     /* p */
a1fb602
     "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
a1fb602
     /* a */
a1fb602
     "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
a1fb602
     /* b */
a1fb602
     "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
a1fb602
     /* Qx */
a1fb602
     "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19",
a1fb602
     /* Qy */
a1fb602
     "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09",
a1fb602
     /* Gx */
a1fb602
     "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
a1fb602
     /* Gy */
a1fb602
     "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
a1fb602
     /* order */
a1fb602
     "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
a1fb602
     /* d */
a1fb602
     "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96",
a1fb602
     },
a1fb602
    {
a1fb602
     /* P-521 */
a1fb602
     EC_GFp_nistp521_method,
a1fb602
     521,
a1fb602
     /* p */
9189f03
                                                                  "1ff"
9189f03
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
9189f03
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
a1fb602
     /* a */
9189f03
                                                                  "1ff"
9189f03
     "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
9189f03
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
a1fb602
     /* b */
9189f03
                                                                  "051"
9189f03
     "953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e1"
9189f03
     "56193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
a1fb602
     /* Qx */
9189f03
                                                                 "0098"
9189f03
     "e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e"
9189f03
     "59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4",
a1fb602
     /* Qy */
9189f03
                                                                 "0164"
9189f03
     "350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8"
9189f03
     "554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e",
a1fb602
     /* Gx */
9189f03
                                                                   "c6"
9189f03
     "858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dba"
9189f03
     "a14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
a1fb602
     /* Gy */
9189f03
                                                                  "118"
9189f03
     "39296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c"
9189f03
     "97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
a1fb602
     /* order */
9189f03
                                                                  "1ff"
9189f03
     "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"
9189f03
     "51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
a1fb602
     /* d */
9189f03
                                                                 "0100"
9189f03
     "085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eee"
9189f03
     "df09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722",
a1fb602
     },
a1fb602
};
a1fb602
9189f03
static int nistp_single_test(int idx)
a1fb602
{
9189f03
    const struct nistp_test_params *test = nistp_tests_params + idx;
9189f03
    BN_CTX *ctx = NULL;
9189f03
    BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
9189f03
    BIGNUM *n = NULL, *m = NULL, *order = NULL, *yplusone = NULL;
9189f03
    EC_GROUP *NISTP = NULL;
9189f03
    EC_POINT *G = NULL, *P = NULL, *Q = NULL, *Q_CHECK = NULL;
9189f03
    int r = 0;
9189f03
9189f03
    TEST_note("NIST curve P-%d (optimised implementation):",
9189f03
              test->degree);
9189f03
    if (!TEST_ptr(ctx = BN_CTX_new())
9189f03
        || !TEST_ptr(p = BN_new())
9189f03
        || !TEST_ptr(a = BN_new())
9189f03
        || !TEST_ptr(b = BN_new())
9189f03
        || !TEST_ptr(x = BN_new())
9189f03
        || !TEST_ptr(y = BN_new())
9189f03
        || !TEST_ptr(m = BN_new())
9189f03
        || !TEST_ptr(n = BN_new())
9189f03
        || !TEST_ptr(order = BN_new())
9189f03
        || !TEST_ptr(yplusone = BN_new())
9189f03
9189f03
        || !TEST_ptr(NISTP = EC_GROUP_new(test->meth()))
9189f03
        || !TEST_true(BN_hex2bn(&p, test->p))
9189f03
        || !TEST_int_eq(1, BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))
9189f03
        || !TEST_true(BN_hex2bn(&a, test->a))
9189f03
        || !TEST_true(BN_hex2bn(&b, test->b))
62ec0f1
        || !TEST_true(EC_GROUP_set_curve(NISTP, p, a, b, ctx))
9189f03
        || !TEST_ptr(G = EC_POINT_new(NISTP))
9189f03
        || !TEST_ptr(P = EC_POINT_new(NISTP))
9189f03
        || !TEST_ptr(Q = EC_POINT_new(NISTP))
9189f03
        || !TEST_ptr(Q_CHECK = EC_POINT_new(NISTP))
9189f03
        || !TEST_true(BN_hex2bn(&x, test->Qx))
9189f03
        || !TEST_true(BN_hex2bn(&y, test->Qy))
9189f03
        || !TEST_true(BN_add(yplusone, y, BN_value_one()))
510bcc2
    /*
510bcc2
     * When (x, y) is on the curve, (x, y + 1) is, as it happens, not,
510bcc2
     * and therefore setting the coordinates should fail.
510bcc2
     */
62ec0f1
        || !TEST_false(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x,
62ec0f1
                                                       yplusone, ctx))
62ec0f1
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, Q_CHECK, x, y,
62ec0f1
                                                      ctx))
9189f03
        || !TEST_true(BN_hex2bn(&x, test->Gx))
9189f03
        || !TEST_true(BN_hex2bn(&y, test->Gy))
62ec0f1
        || !TEST_true(EC_POINT_set_affine_coordinates(NISTP, G, x, y, ctx))
9189f03
        || !TEST_true(BN_hex2bn(&order, test->order))
9189f03
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one()))
9189f03
        || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree))
9189f03
        goto err;
9189f03
9189f03
    TEST_note("NIST test vectors ... ");
9189f03
    if (!TEST_true(BN_hex2bn(&n, test->d)))
9189f03
        goto err;
a1fb602
    /* fixed point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
9189f03
        goto err;
a1fb602
    /* random point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
9189f03
9189f03
        /* set generator to P = 2*G, where G is the standard generator */
9189f03
        || !TEST_true(EC_POINT_dbl(NISTP, P, G, ctx))
9189f03
        || !TEST_true(EC_GROUP_set_generator(NISTP, P, order, BN_value_one()))
9189f03
        /* set the scalar to m=n/2, where n is the NIST test scalar */
9189f03
        || !TEST_true(BN_rshift(m, n, 1)))
9189f03
        goto err;
a1fb602
a1fb602
    /* test the non-standard generator */
a1fb602
    /* fixed point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
9189f03
        goto err;
a1fb602
    /* random point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
a1fb602
e7a0ff5
    /*
e7a0ff5
     * We have not performed precomputation so have_precompute mult should be
e7a0ff5
     * false
e7a0ff5
     */
9189f03
        || !TEST_false(EC_GROUP_have_precompute_mult(NISTP))
e7a0ff5
a1fb602
    /* now repeat all tests with precomputation */
9189f03
        || !TEST_true(EC_GROUP_precompute_mult(NISTP, ctx))
9189f03
        || !TEST_true(EC_GROUP_have_precompute_mult(NISTP)))
9189f03
        goto err;
a1fb602
a1fb602
    /* fixed point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
9189f03
        goto err;
a1fb602
    /* random point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx))
a1fb602
a1fb602
    /* reset generator */
9189f03
        || !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one())))
9189f03
        goto err;
a1fb602
    /* fixed point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
9189f03
        goto err;
a1fb602
    /* random point multiplication */
a1fb602
    EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
9189f03
    if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
9189f03
        goto err;
9189f03
9189f03
    /* regression test for felem_neg bug */
9189f03
    if (!TEST_true(BN_set_word(m, 32))
9189f03
        || !TEST_true(BN_set_word(n, 31))
9189f03
        || !TEST_true(EC_POINT_copy(P, G))
9189f03
        || !TEST_true(EC_POINT_invert(NISTP, P, ctx))
9189f03
        || !TEST_true(EC_POINT_mul(NISTP, Q, m, P, n, ctx))
9189f03
        || !TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, G, ctx)))
9189f03
      goto err;
9189f03
9189f03
    r = group_order_tests(NISTP);
9189f03
err:
a1fb602
    EC_GROUP_free(NISTP);
a1fb602
    EC_POINT_free(G);
a1fb602
    EC_POINT_free(P);
a1fb602
    EC_POINT_free(Q);
a1fb602
    EC_POINT_free(Q_CHECK);
a1fb602
    BN_free(n);
a1fb602
    BN_free(m);
a1fb602
    BN_free(p);
a1fb602
    BN_free(a);
a1fb602
    BN_free(b);
a1fb602
    BN_free(x);
a1fb602
    BN_free(y);
a1fb602
    BN_free(order);
510bcc2
    BN_free(yplusone);
a1fb602
    BN_CTX_free(ctx);
9189f03
    return r;
a1fb602
}
31d61b1
31d61b1
/*
31d61b1
 * Tests a point known to cause an incorrect underflow in an old version of
31d61b1
 * ecp_nist521.c
31d61b1
 */
31d61b1
static int underflow_test(void)
31d61b1
{
31d61b1
    BN_CTX *ctx = NULL;
31d61b1
    EC_GROUP *grp = NULL;
31d61b1
    EC_POINT *P = NULL, *Q = NULL, *R = NULL;
31d61b1
    BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL;
31d61b1
    BIGNUM *k = NULL;
31d61b1
    int testresult = 0;
31d61b1
    const char *x1str =
31d61b1
        "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4"
31d61b1
        "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004";
31d61b1
    const char *p521m1 =
31d61b1
        "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
31d61b1
        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe";
31d61b1
31d61b1
    ctx = BN_CTX_new();
31d61b1
    if (!TEST_ptr(ctx))
31d61b1
        return 0;
31d61b1
31d61b1
    BN_CTX_start(ctx);
31d61b1
    x1 = BN_CTX_get(ctx);
31d61b1
    y1 = BN_CTX_get(ctx);
31d61b1
    z1 = BN_CTX_get(ctx);
31d61b1
    x2 = BN_CTX_get(ctx);
31d61b1
    y2 = BN_CTX_get(ctx);
31d61b1
    k = BN_CTX_get(ctx);
31d61b1
    if (!TEST_ptr(k))
31d61b1
        goto err;
31d61b1
31d61b1
    grp = EC_GROUP_new_by_curve_name(NID_secp521r1);
31d61b1
    P = EC_POINT_new(grp);
31d61b1
    Q = EC_POINT_new(grp);
31d61b1
    R = EC_POINT_new(grp);
31d61b1
    if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R))
31d61b1
        goto err;
31d61b1
31d61b1
    if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0)
31d61b1
            || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0)
31d61b1
            || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0)
31d61b1
            || !TEST_int_gt(BN_hex2bn(&k, "02"), 0)
31d61b1
            || !TEST_true(EC_POINT_set_Jprojective_coordinates_GFp(grp, P, x1,
31d61b1
                                                                   y1, z1, ctx))
31d61b1
            || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx))
31d61b1
            || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx))
31d61b1
            || !TEST_true(EC_POINT_dbl(grp, R, P, ctx))
31d61b1
            || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx)))
31d61b1
        goto err;
31d61b1
31d61b1
    if (!TEST_int_eq(BN_cmp(x1, x2), 0)
31d61b1
            || !TEST_int_eq(BN_cmp(y1, y2), 0))
31d61b1
        goto err;
31d61b1
31d61b1
    testresult = 1;
31d61b1
31d61b1
 err:
31d61b1
    BN_CTX_end(ctx);
31d61b1
    EC_POINT_free(P);
31d61b1
    EC_POINT_free(Q);
31d61b1
    EC_POINT_free(R);
31d61b1
    EC_GROUP_free(grp);
31d61b1
    BN_CTX_free(ctx);
31d61b1
31d61b1
    return testresult;
31d61b1
}
9189f03
# endif
a1fb602
9189f03
static const unsigned char p521_named[] = {
9189f03
    0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
9189f03
};
a1fb602
9189f03
static const unsigned char p521_explicit[] = {
9189f03
    0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, 0x4d, 0x06, 0x07, 0x2a,
9189f03
    0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0x30, 0x81, 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xfc, 0x04, 0x42, 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a,
9189f03
    0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72,
9189f03
    0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09,
9189f03
    0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0,
9189f03
    0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34,
9189f03
    0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00, 0x03, 0x15, 0x00,
9189f03
    0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17,
9189f03
    0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, 0x04, 0x81, 0x85, 0x04,
9189f03
    0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e,
9189f03
    0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
9189f03
    0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b,
9189f03
    0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
9189f03
    0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
9189f03
    0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78,
9189f03
    0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
9189f03
    0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17,
9189f03
    0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
9189f03
    0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86,
9189f03
    0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
9189f03
    0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9189f03
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
9189f03
    0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48,
9189f03
    0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
9189f03
    0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01,
9189f03
};
a1fb602
f6a62c4
/*
f6a62c4
 * Sometime we cannot compare nids for equality, as the built-in curve table
f6a62c4
 * includes aliases with different names for the same curve.
f6a62c4
 *
f6a62c4
 * This function returns TRUE (1) if the checked nids are identical, or if they
f6a62c4
 * alias to the same curve. FALSE (0) otherwise.
f6a62c4
 */
f6a62c4
static ossl_inline
f6a62c4
int are_ec_nids_compatible(int n1d, int n2d)
f6a62c4
{
f6a62c4
    int ret = 0;
f6a62c4
    switch (n1d) {
f6a62c4
# ifndef OPENSSL_NO_EC2M
f6a62c4
        case NID_sect113r1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls4:
f6a62c4
            ret = (n2d == NID_sect113r1 || n2d == NID_wap_wsg_idm_ecid_wtls4);
f6a62c4
            break;
f6a62c4
        case NID_sect163k1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls3:
f6a62c4
            ret = (n2d == NID_sect163k1 || n2d == NID_wap_wsg_idm_ecid_wtls3);
f6a62c4
            break;
f6a62c4
        case NID_sect233k1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls10:
f6a62c4
            ret = (n2d == NID_sect233k1 || n2d == NID_wap_wsg_idm_ecid_wtls10);
f6a62c4
            break;
f6a62c4
        case NID_sect233r1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls11:
f6a62c4
            ret = (n2d == NID_sect233r1 || n2d == NID_wap_wsg_idm_ecid_wtls11);
f6a62c4
            break;
f6a62c4
        case NID_X9_62_c2pnb163v1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls5:
f6a62c4
            ret = (n2d == NID_X9_62_c2pnb163v1
f6a62c4
                   || n2d == NID_wap_wsg_idm_ecid_wtls5);
f6a62c4
            break;
f6a62c4
# endif /* OPENSSL_NO_EC2M */
f6a62c4
        case NID_secp112r1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls6:
f6a62c4
            ret = (n2d == NID_secp112r1 || n2d == NID_wap_wsg_idm_ecid_wtls6);
f6a62c4
            break;
f6a62c4
        case NID_secp160r2:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls7:
f6a62c4
            ret = (n2d == NID_secp160r2 || n2d == NID_wap_wsg_idm_ecid_wtls7);
f6a62c4
            break;
f6a62c4
# ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
f6a62c4
        case NID_secp224r1:
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls12:
f6a62c4
            ret = (n2d == NID_secp224r1 || n2d == NID_wap_wsg_idm_ecid_wtls12);
f6a62c4
            break;
f6a62c4
# else
f6a62c4
        /*
f6a62c4
         * For SEC P-224 we want to ensure that the SECP nid is returned, as
f6a62c4
         * that is associated with a specialized method.
f6a62c4
         */
f6a62c4
        case NID_wap_wsg_idm_ecid_wtls12:
f6a62c4
            ret = (n2d == NID_secp224r1);
f6a62c4
            break;
f6a62c4
# endif /* def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
f6a62c4
f6a62c4
        default:
f6a62c4
            ret = (n1d == n2d);
f6a62c4
    }
f6a62c4
    return ret;
f6a62c4
}
f6a62c4
f6a62c4
/*
f6a62c4
 * This checks that EC_GROUP_bew_from_ecparameters() returns a "named"
f6a62c4
 * EC_GROUP for built-in curves.
f6a62c4
 *
f6a62c4
 * Note that it is possible to retrieve an alternative alias that does not match
f6a62c4
 * the original nid.
f6a62c4
 *
f6a62c4
 * Ensure that the OPENSSL_EC_EXPLICIT_CURVE ASN1 flag is set.
f6a62c4
 */
f6a62c4
static int check_named_curve_from_ecparameters(int id)
f6a62c4
{
f6a62c4
    int ret = 0, nid, tnid;
f6a62c4
    EC_GROUP *group = NULL, *tgroup = NULL, *tmpg = NULL;
f6a62c4
    const EC_POINT *group_gen = NULL;
f6a62c4
    EC_POINT *other_gen = NULL;
f6a62c4
    BIGNUM *group_cofactor = NULL, *other_cofactor = NULL;
f6a62c4
    BIGNUM *other_gen_x = NULL, *other_gen_y = NULL;
f6a62c4
    const BIGNUM *group_order = NULL;
f6a62c4
    BIGNUM *other_order = NULL;
f6a62c4
    BN_CTX *bn_ctx = NULL;
f6a62c4
    static const unsigned char invalid_seed[] = "THIS IS NOT A VALID SEED";
f6a62c4
    static size_t invalid_seed_len = sizeof(invalid_seed);
f6a62c4
    ECPARAMETERS *params = NULL, *other_params = NULL;
f6a62c4
    EC_GROUP *g_ary[8] = {NULL};
f6a62c4
    EC_GROUP **g_next = &g_ary[0];
f6a62c4
    ECPARAMETERS *p_ary[8] = {NULL};
f6a62c4
    ECPARAMETERS **p_next = &p_ary[0];
f6a62c4
f6a62c4
    /* Do some setup */
f6a62c4
    nid = curves[id].nid;
f6a62c4
    TEST_note("Curve %s", OBJ_nid2sn(nid));
f6a62c4
    if (!TEST_ptr(bn_ctx = BN_CTX_new()))
f6a62c4
        return ret;
f6a62c4
    BN_CTX_start(bn_ctx);
f6a62c4
f6a62c4
    if (/* Allocations */
f6a62c4
        !TEST_ptr(group_cofactor = BN_CTX_get(bn_ctx))
f6a62c4
        || !TEST_ptr(other_gen_x = BN_CTX_get(bn_ctx))
f6a62c4
        || !TEST_ptr(other_gen_y = BN_CTX_get(bn_ctx))
f6a62c4
        || !TEST_ptr(other_order = BN_CTX_get(bn_ctx))
f6a62c4
        || !TEST_ptr(other_cofactor = BN_CTX_get(bn_ctx))
f6a62c4
        /* Generate reference group and params */
f6a62c4
        || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
f6a62c4
        || !TEST_ptr(params = EC_GROUP_get_ecparameters(group, NULL))
f6a62c4
        || !TEST_ptr(group_gen = EC_GROUP_get0_generator(group))
f6a62c4
        || !TEST_ptr(group_order = EC_GROUP_get0_order(group))
f6a62c4
        || !TEST_true(EC_GROUP_get_cofactor(group, group_cofactor, NULL))
f6a62c4
        /* compute `other_*` values */
f6a62c4
        || !TEST_ptr(tmpg = EC_GROUP_dup(group))
f6a62c4
        || !TEST_ptr(other_gen = EC_POINT_dup(group_gen, group))
f6a62c4
        || !TEST_true(EC_POINT_add(group, other_gen, group_gen, group_gen, NULL))
f6a62c4
        || !TEST_true(EC_POINT_get_affine_coordinates(group, other_gen,
f6a62c4
                      other_gen_x, other_gen_y, bn_ctx))
f6a62c4
        || !TEST_true(BN_copy(other_order, group_order))
f6a62c4
        || !TEST_true(BN_add_word(other_order, 1))
f6a62c4
        || !TEST_true(BN_copy(other_cofactor, group_cofactor))
f6a62c4
        || !TEST_true(BN_add_word(other_cofactor, 1)))
f6a62c4
        goto err;
f6a62c4
f6a62c4
    EC_POINT_free(other_gen);
f6a62c4
    other_gen = NULL;
f6a62c4
f6a62c4
    if (!TEST_ptr(other_gen = EC_POINT_new(tmpg))
f6a62c4
        || !TEST_true(EC_POINT_set_affine_coordinates(tmpg, other_gen,
f6a62c4
                                                      other_gen_x, other_gen_y,
f6a62c4
                                                      bn_ctx)))
f6a62c4
        goto err;
f6a62c4
f6a62c4
    /*
f6a62c4
     * ###########################
f6a62c4
     * # Actual tests start here #
f6a62c4
     * ###########################
f6a62c4
     */
f6a62c4
f6a62c4
    /*
f6a62c4
     * Creating a group from built-in explicit parameters returns a
f6a62c4
     * "named" EC_GROUP
f6a62c4
     */
f6a62c4
    if (!TEST_ptr(tgroup = *g_next++ = EC_GROUP_new_from_ecparameters(params))
f6a62c4
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef))
f6a62c4
        goto err;
f6a62c4
    /*
f6a62c4
     * We cannot always guarantee the names match, as the built-in table
f6a62c4
     * contains aliases for the same curve with different names.
f6a62c4
     */
f6a62c4
    if (!TEST_true(are_ec_nids_compatible(nid, tnid))) {
f6a62c4
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
f6a62c4
        goto err;
f6a62c4
    }
f6a62c4
    /* Ensure that the OPENSSL_EC_EXPLICIT_CURVE ASN1 flag is set. */
f6a62c4
    if (!TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup), OPENSSL_EC_EXPLICIT_CURVE))
f6a62c4
        goto err;
f6a62c4
f6a62c4
    /*
f6a62c4
     * An invalid seed in the parameters should be ignored: expect a "named"
f6a62c4
     * group.
f6a62c4
     */
f6a62c4
    if (!TEST_int_eq(EC_GROUP_set_seed(tmpg, invalid_seed, invalid_seed_len),
f6a62c4
                     invalid_seed_len)
f6a62c4
            || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                         EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
            || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                          EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
            || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
            || !TEST_true(are_ec_nids_compatible(nid, tnid))
f6a62c4
            || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
f6a62c4
                            OPENSSL_EC_EXPLICIT_CURVE)) {
f6a62c4
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
f6a62c4
        goto err;
f6a62c4
    }
f6a62c4
f6a62c4
    /*
f6a62c4
     * A null seed in the parameters should be ignored, as it is optional:
f6a62c4
     * expect a "named" group.
f6a62c4
     */
f6a62c4
    if (!TEST_int_eq(EC_GROUP_set_seed(tmpg, NULL, 0), 1)
f6a62c4
            || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                         EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
            || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                          EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
            || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
            || !TEST_true(are_ec_nids_compatible(nid, tnid))
f6a62c4
            || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
f6a62c4
                            OPENSSL_EC_EXPLICIT_CURVE)) {
f6a62c4
        TEST_info("nid = %s, tnid = %s", OBJ_nid2sn(nid), OBJ_nid2sn(tnid));
f6a62c4
        goto err;
f6a62c4
    }
f6a62c4
f6a62c4
    /*
f6a62c4
     * Check that changing any of the generator parameters does not yield a
f6a62c4
     * match with the built-in curves
f6a62c4
     */
f6a62c4
    if (/* Other gen, same group order & cofactor */
f6a62c4
        !TEST_true(EC_GROUP_set_generator(tmpg, other_gen, group_order,
f6a62c4
                                          group_cofactor))
f6a62c4
        || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                     EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
        || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                      EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
        || !TEST_int_eq((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
        /* Same gen & cofactor, different order */
f6a62c4
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, other_order,
f6a62c4
                                             group_cofactor))
f6a62c4
        || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                     EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
        || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                      EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
        || !TEST_int_eq((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
        /* The order is not an optional field, so this should fail */
f6a62c4
        || !TEST_false(EC_GROUP_set_generator(tmpg, group_gen, NULL,
f6a62c4
                                              group_cofactor))
f6a62c4
        /* Check that a wrong cofactor is ignored, and we still match */
f6a62c4
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
f6a62c4
                                             other_cofactor))
f6a62c4
        || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                     EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
        || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                      EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
f6a62c4
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
f6a62c4
                        OPENSSL_EC_EXPLICIT_CURVE)
f6a62c4
        /* Check that if the cofactor is not set then it still matches */
f6a62c4
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
f6a62c4
                                             NULL))
f6a62c4
        || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                     EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
        || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                      EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
f6a62c4
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
f6a62c4
                        OPENSSL_EC_EXPLICIT_CURVE)
f6a62c4
        /* check that restoring the generator passes */
f6a62c4
        || !TEST_true(EC_GROUP_set_generator(tmpg, group_gen, group_order,
f6a62c4
                                             group_cofactor))
f6a62c4
        || !TEST_ptr(other_params = *p_next++ =
f6a62c4
                     EC_GROUP_get_ecparameters(tmpg, NULL))
f6a62c4
        || !TEST_ptr(tgroup = *g_next++ =
f6a62c4
                      EC_GROUP_new_from_ecparameters(other_params))
f6a62c4
        || !TEST_int_ne((tnid = EC_GROUP_get_curve_name(tgroup)), NID_undef)
f6a62c4
        || !TEST_true(are_ec_nids_compatible(nid, tnid))
f6a62c4
        || !TEST_int_eq(EC_GROUP_get_asn1_flag(tgroup),
f6a62c4
                        OPENSSL_EC_EXPLICIT_CURVE))
f6a62c4
        goto err;
f6a62c4
f6a62c4
    ret = 1;
f6a62c4
err:
f6a62c4
    for (g_next = &g_ary[0]; g_next < g_ary + OSSL_NELEM(g_ary); g_next++)
f6a62c4
        EC_GROUP_free(*g_next);
f6a62c4
    for (p_next = &p_ary[0]; p_next < p_ary + OSSL_NELEM(g_ary); p_next++)
f6a62c4
        ECPARAMETERS_free(*p_next);
f6a62c4
    ECPARAMETERS_free(params);
f6a62c4
    EC_POINT_free(other_gen);
f6a62c4
    EC_GROUP_free(tmpg);
f6a62c4
    EC_GROUP_free(group);
f6a62c4
    BN_CTX_end(bn_ctx);
f6a62c4
    BN_CTX_free(bn_ctx);
f6a62c4
    return ret;
f6a62c4
}
f6a62c4
9189f03
static int parameter_test(void)
510bcc2
{
9189f03
    EC_GROUP *group = NULL, *group2 = NULL;
9189f03
    ECPARAMETERS *ecparameters = NULL;
9189f03
    unsigned char *buf = NULL;
9189f03
    int r = 0, len;
9189f03
9189f03
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp384r1))
9189f03
        || !TEST_ptr(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
9189f03
        || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
9189f03
        || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))
9189f03
        goto err;
510bcc2
9189f03
    EC_GROUP_free(group);
9189f03
    group = NULL;
510bcc2
9189f03
    /* Test the named curve encoding, which should be default. */
9189f03
    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp521r1))
9189f03
        || !TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
9189f03
        || !TEST_mem_eq(buf, len, p521_named, sizeof(p521_named)))
9189f03
        goto err;
510bcc2
9189f03
    OPENSSL_free(buf);
9189f03
    buf = NULL;
510bcc2
9189f03
    /*
9189f03
     * Test the explicit encoding. P-521 requires correctly zero-padding the
9189f03
     * curve coefficients.
9189f03
     */
9189f03
    EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
9189f03
    if (!TEST_true((len = i2d_ECPKParameters(group, &buf)) >= 0)
9189f03
        || !TEST_mem_eq(buf, len, p521_explicit, sizeof(p521_explicit)))
9189f03
        goto err;
510bcc2
9189f03
    r = 1;
9189f03
err:
510bcc2
    EC_GROUP_free(group);
510bcc2
    EC_GROUP_free(group2);
510bcc2
    ECPARAMETERS_free(ecparameters);
9189f03
    OPENSSL_free(buf);
9189f03
    return r;
510bcc2
}
f6a62c4
f6a62c4
/*-
f6a62c4
 * random 256-bit explicit parameters curve, cofactor absent
f6a62c4
 * order:    0x0c38d96a9f892b88772ec2e39614a82f4f (132 bit)
f6a62c4
 * cofactor:   0x12bc94785251297abfafddf1565100da (125 bit)
f6a62c4
 */
f6a62c4
static const unsigned char params_cf_pass[] = {
f6a62c4
    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
f6a62c4
    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xe5, 0x00, 0x1f, 0xc5,
f6a62c4
    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
f6a62c4
    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
f6a62c4
    0x44, 0x88, 0xe6, 0x91, 0x30, 0x44, 0x04, 0x20, 0xe5, 0x00, 0x1f, 0xc5,
f6a62c4
    0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
f6a62c4
    0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
f6a62c4
    0x44, 0x88, 0xe6, 0x8e, 0x04, 0x20, 0x18, 0x8c, 0x59, 0x57, 0xc4, 0xbc,
f6a62c4
    0x85, 0x57, 0xc3, 0x66, 0x9f, 0x89, 0xd5, 0x92, 0x0d, 0x7e, 0x42, 0x27,
f6a62c4
    0x07, 0x64, 0xaa, 0x26, 0xed, 0x89, 0xc4, 0x09, 0x05, 0x4d, 0xc7, 0x23,
f6a62c4
    0x47, 0xda, 0x04, 0x41, 0x04, 0x1b, 0x6b, 0x41, 0x0b, 0xf9, 0xfb, 0x77,
f6a62c4
    0xfd, 0x50, 0xb7, 0x3e, 0x23, 0xa3, 0xec, 0x9a, 0x3b, 0x09, 0x31, 0x6b,
f6a62c4
    0xfa, 0xf6, 0xce, 0x1f, 0xff, 0xeb, 0x57, 0x93, 0x24, 0x70, 0xf3, 0xf4,
f6a62c4
    0xba, 0x7e, 0xfa, 0x86, 0x6e, 0x19, 0x89, 0xe3, 0x55, 0x6d, 0x5a, 0xe9,
f6a62c4
    0xc0, 0x3d, 0xbc, 0xfb, 0xaf, 0xad, 0xd4, 0x7e, 0xa6, 0xe5, 0xfa, 0x1a,
f6a62c4
    0x58, 0x07, 0x9e, 0x8f, 0x0d, 0x3b, 0xf7, 0x38, 0xca, 0x02, 0x11, 0x0c,
f6a62c4
    0x38, 0xd9, 0x6a, 0x9f, 0x89, 0x2b, 0x88, 0x77, 0x2e, 0xc2, 0xe3, 0x96,
f6a62c4
    0x14, 0xa8, 0x2f, 0x4f
f6a62c4
};
f6a62c4
f6a62c4
/*-
f6a62c4
 * random 256-bit explicit parameters curve, cofactor absent
f6a62c4
 * order:    0x045a75c0c17228ebd9b169a10e34a22101 (131 bit)
f6a62c4
 * cofactor:   0x2e134b4ede82649f67a2e559d361e5fe (126 bit)
f6a62c4
 */
f6a62c4
static const unsigned char params_cf_fail[] = {
f6a62c4
    0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
f6a62c4
    0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xc8, 0x95, 0x27, 0x37,
f6a62c4
    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
f6a62c4
    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
f6a62c4
    0x33, 0xc2, 0xea, 0x13, 0x30, 0x44, 0x04, 0x20, 0xc8, 0x95, 0x27, 0x37,
f6a62c4
    0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
f6a62c4
    0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
f6a62c4
    0x33, 0xc2, 0xea, 0x10, 0x04, 0x20, 0xbf, 0xa6, 0xa8, 0x05, 0x1d, 0x09,
f6a62c4
    0xac, 0x70, 0x39, 0xbb, 0x4d, 0xb2, 0x90, 0x8a, 0x15, 0x41, 0x14, 0x1d,
f6a62c4
    0x11, 0x86, 0x9f, 0x13, 0xa2, 0x63, 0x1a, 0xda, 0x95, 0x22, 0x4d, 0x02,
f6a62c4
    0x15, 0x0a, 0x04, 0x41, 0x04, 0xaf, 0x16, 0x71, 0xf9, 0xc4, 0xc8, 0x59,
f6a62c4
    0x1d, 0xa3, 0x6f, 0xe7, 0xc3, 0x57, 0xa1, 0xfa, 0x9f, 0x49, 0x7c, 0x11,
f6a62c4
    0x27, 0x05, 0xa0, 0x7f, 0xff, 0xf9, 0xe0, 0xe7, 0x92, 0xdd, 0x9c, 0x24,
f6a62c4
    0x8e, 0xc7, 0xb9, 0x52, 0x71, 0x3f, 0xbc, 0x7f, 0x6a, 0x9f, 0x35, 0x70,
f6a62c4
    0xe1, 0x27, 0xd5, 0x35, 0x8a, 0x13, 0xfa, 0xa8, 0x33, 0x3e, 0xd4, 0x73,
f6a62c4
    0x1c, 0x14, 0x58, 0x9e, 0xc7, 0x0a, 0x87, 0x65, 0x8d, 0x02, 0x11, 0x04,
f6a62c4
    0x5a, 0x75, 0xc0, 0xc1, 0x72, 0x28, 0xeb, 0xd9, 0xb1, 0x69, 0xa1, 0x0e,
f6a62c4
    0x34, 0xa2, 0x21, 0x01
f6a62c4
};
f6a62c4
f6a62c4
/*-
f6a62c4
 * Test two random 256-bit explicit parameters curves with absent cofactor.
f6a62c4
 * The two curves are chosen to roughly straddle the bounds at which the lib
f6a62c4
 * can compute the cofactor automatically, roughly 4*sqrt(p). So test that:
f6a62c4
 *
f6a62c4
 * - params_cf_pass: order is sufficiently close to p to compute cofactor
f6a62c4
 * - params_cf_fail: order is too far away from p to compute cofactor
f6a62c4
 *
f6a62c4
 * For standards-compliant curves, cofactor is chosen as small as possible.
f6a62c4
 * So you can see neither of these curves are fit for cryptographic use.
f6a62c4
 *
f6a62c4
 * Some standards even mandate an upper bound on the cofactor, e.g. SECG1 v2:
f6a62c4
 * h <= 2**(t/8) where t is the security level of the curve, for which the lib
f6a62c4
 * will always succeed in computing the cofactor. Neither of these curves
f6a62c4
 * conform to that -- this is just robustness testing.
f6a62c4
 */
f6a62c4
static int cofactor_range_test(void)
f6a62c4
{
f6a62c4
    EC_GROUP *group = NULL;
f6a62c4
    BIGNUM *cf = NULL;
f6a62c4
    int ret = 0;
f6a62c4
    const unsigned char *b1 = (const unsigned char *)params_cf_fail;
f6a62c4
    const unsigned char *b2 = (const unsigned char *)params_cf_pass;
f6a62c4
f6a62c4
    if (!TEST_ptr(group = d2i_ECPKParameters(NULL, &b1, sizeof(params_cf_fail)))
f6a62c4
        || !TEST_BN_eq_zero(EC_GROUP_get0_cofactor(group))
f6a62c4
        || !TEST_ptr(group = d2i_ECPKParameters(&group, &b2,
f6a62c4
                                                sizeof(params_cf_pass)))
f6a62c4
        || !TEST_int_gt(BN_hex2bn(&cf, "12bc94785251297abfafddf1565100da"), 0)
f6a62c4
        || !TEST_BN_eq(cf, EC_GROUP_get0_cofactor(group)))
f6a62c4
        goto err;
f6a62c4
    ret = 1;
f6a62c4
 err:
f6a62c4
    BN_free(cf);
f6a62c4
    EC_GROUP_free(group);
f6a62c4
    return ret;
f6a62c4
}
f6a62c4
f6a62c4
/*-
f6a62c4
 * For named curves, test that:
f6a62c4
 * - the lib correctly computes the cofactor if passed a NULL or zero cofactor
f6a62c4
 * - a nonsensical cofactor throws an error (negative test)
f6a62c4
 * - nonsensical orders throw errors (negative tests)
f6a62c4
 */
f6a62c4
static int cardinality_test(int n)
f6a62c4
{
f6a62c4
    int ret = 0;
f6a62c4
    int nid = curves[n].nid;
f6a62c4
    BN_CTX *ctx = NULL;
f6a62c4
    EC_GROUP *g1 = NULL, *g2 = NULL;
f6a62c4
    EC_POINT *g2_gen = NULL;
f6a62c4
    BIGNUM *g1_p = NULL, *g1_a = NULL, *g1_b = NULL, *g1_x = NULL, *g1_y = NULL,
f6a62c4
           *g1_order = NULL, *g1_cf = NULL, *g2_cf = NULL;
f6a62c4
f6a62c4
    TEST_info("Curve %s cardinality test", OBJ_nid2sn(nid));
f6a62c4
f6a62c4
    if (!TEST_ptr(ctx = BN_CTX_new())
f6a62c4
        || !TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))
f6a62c4
        || !TEST_ptr(g2 = EC_GROUP_new(EC_GROUP_method_of(g1)))) {
f6a62c4
        EC_GROUP_free(g1);
f6a62c4
        EC_GROUP_free(g2);
f6a62c4
        BN_CTX_free(ctx);
f6a62c4
        return 0;
f6a62c4
    }
f6a62c4
f6a62c4
    BN_CTX_start(ctx);
f6a62c4
    g1_p = BN_CTX_get(ctx);
f6a62c4
    g1_a = BN_CTX_get(ctx);
f6a62c4
    g1_b = BN_CTX_get(ctx);
f6a62c4
    g1_x = BN_CTX_get(ctx);
f6a62c4
    g1_y = BN_CTX_get(ctx);
f6a62c4
    g1_order = BN_CTX_get(ctx);
f6a62c4
    g1_cf = BN_CTX_get(ctx);
f6a62c4
f6a62c4
    if (!TEST_ptr(g2_cf = BN_CTX_get(ctx))
f6a62c4
        /* pull out the explicit curve parameters */
f6a62c4
        || !TEST_true(EC_GROUP_get_curve(g1, g1_p, g1_a, g1_b, ctx))
f6a62c4
        || !TEST_true(EC_POINT_get_affine_coordinates(g1,
f6a62c4
                      EC_GROUP_get0_generator(g1), g1_x, g1_y, ctx))
f6a62c4
        || !TEST_true(BN_copy(g1_order, EC_GROUP_get0_order(g1)))
f6a62c4
        || !TEST_true(EC_GROUP_get_cofactor(g1, g1_cf, ctx))
f6a62c4
        /* construct g2 manually with g1 parameters */
f6a62c4
        || !TEST_true(EC_GROUP_set_curve(g2, g1_p, g1_a, g1_b, ctx))
f6a62c4
        || !TEST_ptr(g2_gen = EC_POINT_new(g2))
f6a62c4
        || !TEST_true(EC_POINT_set_affine_coordinates(g2, g2_gen, g1_x, g1_y, ctx))
f6a62c4
        /* pass NULL cofactor: lib should compute it */
f6a62c4
        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
f6a62c4
        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
f6a62c4
        || !TEST_BN_eq(g1_cf, g2_cf)
f6a62c4
        /* pass zero cofactor: lib should compute it */
f6a62c4
        || !TEST_true(BN_set_word(g2_cf, 0))
f6a62c4
        || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
f6a62c4
        || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
f6a62c4
        || !TEST_BN_eq(g1_cf, g2_cf)
f6a62c4
        /* negative test for invalid cofactor */
f6a62c4
        || !TEST_true(BN_set_word(g2_cf, 0))
f6a62c4
        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
f6a62c4
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
f6a62c4
        /* negative test for NULL order */
f6a62c4
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, NULL, NULL))
f6a62c4
        /* negative test for zero order */
f6a62c4
        || !TEST_true(BN_set_word(g1_order, 0))
f6a62c4
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
f6a62c4
        /* negative test for negative order */
f6a62c4
        || !TEST_true(BN_set_word(g2_cf, 0))
f6a62c4
        || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
f6a62c4
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
f6a62c4
        /* negative test for too large order */
f6a62c4
        || !TEST_true(BN_lshift(g1_order, g1_p, 2))
f6a62c4
        || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL)))
f6a62c4
        goto err;
f6a62c4
    ret = 1;
f6a62c4
 err:
f6a62c4
    EC_POINT_free(g2_gen);
f6a62c4
    EC_GROUP_free(g1);
f6a62c4
    EC_GROUP_free(g2);
f6a62c4
    BN_CTX_end(ctx);
f6a62c4
    BN_CTX_free(ctx);
f6a62c4
    return ret;
f6a62c4
}
9189f03
#endif
510bcc2
9189f03
int setup_tests(void)
a1fb602
{
9189f03
#ifndef OPENSSL_NO_EC
9189f03
    crv_len = EC_get_builtin_curves(NULL, 0);
9189f03
    if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
9189f03
        || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
9189f03
        return 0;
a1fb602
9189f03
    ADD_TEST(parameter_test);
f6a62c4
    ADD_TEST(cofactor_range_test);
f6a62c4
    ADD_ALL_TESTS(cardinality_test, crv_len);
9189f03
    ADD_TEST(prime_field_tests);
a1fb602
# ifndef OPENSSL_NO_EC2M
9189f03
    ADD_TEST(char2_field_tests);
9189f03
    ADD_ALL_TESTS(char2_curve_test, OSSL_NELEM(char2_curve_tests));
a1fb602
# endif
a1fb602
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
9189f03
    ADD_ALL_TESTS(nistp_single_test, OSSL_NELEM(nistp_tests_params));
31d61b1
    ADD_TEST(underflow_test);
a1fb602
# endif
9189f03
    ADD_ALL_TESTS(internal_curve_test, crv_len);
9189f03
    ADD_ALL_TESTS(internal_curve_test_method, crv_len);
f6a62c4
f6a62c4
    ADD_ALL_TESTS(check_named_curve_from_ecparameters, crv_len);
f6a62c4
#endif /* OPENSSL_NO_EC */
9189f03
    return 1;
a1fb602
}
9189f03
9189f03
void cleanup_tests(void)
9189f03
{
9189f03
#ifndef OPENSSL_NO_EC
9189f03
    OPENSSL_free(curves);
b355146
#endif
9189f03
}