974fcb24462d9789c974632b5980202023f4304e
[openssl.git] / crypto / ec / ec_check.c
1 /*
2  * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "ec_lcl.h"
11 #include <openssl/err.h>
12
13 int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
14                                BN_CTX *ctx)
15 {
16     int nid = NID_undef;
17 #ifndef FIPS_MODE
18     BN_CTX *new_ctx = NULL;
19
20     if (ctx == NULL) {
21         ctx = new_ctx = BN_CTX_new();
22         if (ctx == NULL) {
23             ECerr(EC_F_EC_GROUP_CHECK_NAMED_CURVE, ERR_R_MALLOC_FAILURE);
24             goto err;
25         }
26     }
27 #endif
28
29     nid = ec_curve_nid_from_params(group, ctx);
30     if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL)
31         nid = NID_undef;
32
33 #ifndef FIPS_MODE
34  err:
35     BN_CTX_free(ctx);
36 #endif
37     return nid;
38 }
39
40 int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
41 {
42 #ifdef FIPS_MODE
43     /*
44     * ECC domain parameter validation.
45     * See SP800-56A R3 5.5.2 "Assurances of Domain-Parameter Validity" Part 1b.
46     */
47     return EC_GROUP_check_named_curve(group, 1, ctx) >= 0 ? 1 : 0;
48 #else
49     int ret = 0;
50     const BIGNUM *order;
51     BN_CTX *new_ctx = NULL;
52     EC_POINT *point = NULL;
53
54     if (group == NULL || group->meth == NULL) {
55         ECerr(EC_F_EC_GROUP_CHECK, ERR_R_PASSED_NULL_PARAMETER);
56         return 0;
57     }
58
59     /* Custom curves assumed to be correct */
60     if ((group->meth->flags & EC_FLAGS_CUSTOM_CURVE) != 0)
61         return 1;
62
63     if (ctx == NULL) {
64         ctx = new_ctx = BN_CTX_new();
65         if (ctx == NULL) {
66             ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
67             goto err;
68         }
69     }
70
71     /* check the discriminant */
72     if (!EC_GROUP_check_discriminant(group, ctx)) {
73         ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
74         goto err;
75     }
76
77     /* check the generator */
78     if (group->generator == NULL) {
79         ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
80         goto err;
81     }
82     if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {
83         ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
84         goto err;
85     }
86
87     /* check the order of the generator */
88     if ((point = EC_POINT_new(group)) == NULL)
89         goto err;
90     order = EC_GROUP_get0_order(group);
91     if (order == NULL)
92         goto err;
93     if (BN_is_zero(order)) {
94         ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
95         goto err;
96     }
97
98     if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx))
99         goto err;
100     if (!EC_POINT_is_at_infinity(group, point)) {
101         ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
102         goto err;
103     }
104
105     ret = 1;
106
107  err:
108     BN_CTX_free(new_ctx);
109     EC_POINT_free(point);
110     return ret;
111 #endif /* FIPS_MODE */
112 }