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