1283d8404f699849485446bbf4f21e66d52ea2c5
[oweals/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 /*
11  * ECDSA low level APIs are deprecated for public use, but still ok for
12  * internal use.
13  */
14 #include "internal/deprecated.h"
15
16 #include "ec_local.h"
17 #include <openssl/err.h>
18
19 int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
20                                BN_CTX *ctx)
21 {
22     int nid = NID_undef;
23     BN_CTX *new_ctx = NULL;
24
25     if (group == NULL) {
26         ECerr(0, ERR_R_PASSED_NULL_PARAMETER);
27         goto err;
28     }
29
30     if (ctx == NULL) {
31         ctx = new_ctx = BN_CTX_new_ex(NULL);
32         if (ctx == NULL) {
33             ECerr(0, ERR_R_MALLOC_FAILURE);
34             return NID_undef;
35         }
36     }
37
38     nid = ec_curve_nid_from_params(group, ctx);
39     if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL)
40         nid = NID_undef;
41
42 err:
43     BN_CTX_free(new_ctx);
44     return nid;
45 }
46
47 int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
48 {
49 #ifdef FIPS_MODE
50     /*
51     * ECC domain parameter validation.
52     * See SP800-56A R3 5.5.2 "Assurances of Domain-Parameter Validity" Part 1b.
53     */
54     return EC_GROUP_check_named_curve(group, 1, ctx) >= 0 ? 1 : 0;
55 #else
56     int ret = 0;
57     const BIGNUM *order;
58     BN_CTX *new_ctx = NULL;
59     EC_POINT *point = NULL;
60
61     if (group == NULL || group->meth == NULL) {
62         ECerr(EC_F_EC_GROUP_CHECK, ERR_R_PASSED_NULL_PARAMETER);
63         return 0;
64     }
65
66     /* Custom curves assumed to be correct */
67     if ((group->meth->flags & EC_FLAGS_CUSTOM_CURVE) != 0)
68         return 1;
69
70     if (ctx == NULL) {
71         ctx = new_ctx = BN_CTX_new();
72         if (ctx == NULL) {
73             ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
74             goto err;
75         }
76     }
77
78     /* check the discriminant */
79     if (!EC_GROUP_check_discriminant(group, ctx)) {
80         ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
81         goto err;
82     }
83
84     /* check the generator */
85     if (group->generator == NULL) {
86         ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
87         goto err;
88     }
89     if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {
90         ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
91         goto err;
92     }
93
94     /* check the order of the generator */
95     if ((point = EC_POINT_new(group)) == NULL)
96         goto err;
97     order = EC_GROUP_get0_order(group);
98     if (order == NULL)
99         goto err;
100     if (BN_is_zero(order)) {
101         ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
102         goto err;
103     }
104
105     if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx))
106         goto err;
107     if (!EC_POINT_is_at_infinity(group, point)) {
108         ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
109         goto err;
110     }
111
112     ret = 1;
113
114  err:
115     BN_CTX_free(new_ctx);
116     EC_POINT_free(point);
117     return ret;
118 #endif /* FIPS_MODE */
119 }