Fix race for X509 store found by thread sanitizer
[openssl.git] / crypto / ffc / ffc_dh.c
1 /*
2  * Copyright 2020-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 #include "internal/ffc.h"
11 #include "internal/nelem.h"
12 #include "crypto/bn_dh.h"
13 #include "e_os.h" /* strcasecmp */
14
15 #ifndef OPENSSL_NO_DH
16
17 # define FFDHE(sz) {                                                        \
18         SN_ffdhe##sz, NID_ffdhe##sz,                                        \
19         sz,                                                                 \
20         &ossl_bignum_ffdhe##sz##_p, &ossl_bignum_ffdhe##sz##_q,             \
21         &ossl_bignum_const_2,                                               \
22     }
23
24 # define MODP(sz)  {                                                        \
25         SN_modp_##sz, NID_modp_##sz,                                        \
26         sz,                                                                 \
27         &ossl_bignum_modp_##sz##_p, &ossl_bignum_modp_##sz##_q,             \
28         &ossl_bignum_const_2                                                \
29     }
30
31 # define RFC5114(name, uid, sz, tag) {                                      \
32         name, uid,                                                          \
33         sz,                                                                 \
34         &ossl_bignum_dh##tag##_p, &ossl_bignum_dh##tag##_q,                 \
35         &ossl_bignum_dh##tag##_g                                            \
36     }
37
38 #else
39
40 # define FFDHE(sz)                      { SN_ffdhe##sz, NID_ffdhe##sz }
41 # define MODP(sz)                       { SN_modp_##sz, NID_modp_##sz }
42 # define RFC5114(name, uid, sz, tag)    { name, uid }
43
44 #endif
45
46 struct dh_named_group_st {
47     const char *name;
48     int uid;
49 #ifndef OPENSSL_NO_DH
50     int32_t nbits;
51     const BIGNUM *p;
52     const BIGNUM *q;
53     const BIGNUM *g;
54 #endif
55 };
56
57 static const DH_NAMED_GROUP dh_named_groups[] = {
58     FFDHE(2048),
59     FFDHE(3072),
60     FFDHE(4096),
61     FFDHE(6144),
62     FFDHE(8192),
63 #ifndef FIPS_MODULE
64     MODP(1536),
65 #endif
66     MODP(2048),
67     MODP(3072),
68     MODP(4096),
69     MODP(6144),
70     MODP(8192),
71     /*
72      * Additional dh named groups from RFC 5114 that have a different g.
73      * The uid can be any unique identifier.
74      */
75 #ifndef FIPS_MODULE
76     RFC5114("dh_1024_160", 1, 1024, 1024_160),
77     RFC5114("dh_2048_224", 2, 2048, 2048_224),
78     RFC5114("dh_2048_256", 3, 2048, 2048_256),
79 #endif
80 };
81
82 const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name)
83 {
84     size_t i;
85
86     for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
87         if (strcasecmp(dh_named_groups[i].name, name) == 0)
88             return &dh_named_groups[i];
89     }
90     return NULL;
91 }
92
93 const DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid)
94 {
95     size_t i;
96
97     for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
98         if (dh_named_groups[i].uid == uid)
99             return &dh_named_groups[i];
100     }
101     return NULL;
102 }
103
104 #ifndef OPENSSL_NO_DH
105 const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p,
106                                                          const BIGNUM *q,
107                                                          const BIGNUM *g)
108 {
109     size_t i;
110
111     for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
112         /* Keep searching until a matching p and g is found */
113         if (BN_cmp(p, dh_named_groups[i].p) == 0
114             && BN_cmp(g, dh_named_groups[i].g) == 0
115             /* Verify q is correct if it exists */
116             && (q == NULL || BN_cmp(q, dh_named_groups[i].q) == 0))
117             return &dh_named_groups[i];
118     }
119     return NULL;
120 }
121 #endif
122
123 int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group)
124 {
125     if (group == NULL)
126         return NID_undef;
127     return group->uid;
128 }
129
130 const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *group)
131 {
132     if (group == NULL)
133         return NULL;
134     return group->name;
135 }
136
137 #ifndef OPENSSL_NO_DH
138 const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group)
139 {
140     if (group == NULL)
141         return NULL;
142     return group->q;
143 }
144
145 int ossl_ffc_named_group_set_pqg(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group)
146 {
147     if (ffc == NULL || group == NULL)
148         return 0;
149
150     ossl_ffc_params_set0_pqg(ffc, (BIGNUM *)group->p, (BIGNUM *)group->q,
151                              (BIGNUM *)group->g);
152
153     /* flush the cached nid, The DH layer is responsible for caching */
154     ffc->nid = NID_undef;
155     return 1;
156 }
157 #endif