]>
Commit | Line | Data |
---|---|---|
dc8de3e6 SL |
1 | /* |
2 | * Copyright 2019-2020 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 <string.h> /* memset */ | |
b03ec3b5 | 11 | #include <openssl/core_names.h> |
dc8de3e6 | 12 | #include "internal/ffc.h" |
b03ec3b5 | 13 | #include "internal/param_build_set.h" |
4f2271d5 SL |
14 | #include "internal/nelem.h" |
15 | #include "e_os.h" /* strcasecmp */ | |
b03ec3b5 | 16 | |
f844f9eb | 17 | #ifndef FIPS_MODULE |
5357c106 | 18 | # include <openssl/asn1.h> /* ossl_ffc_params_print */ |
dc8de3e6 SL |
19 | #endif |
20 | ||
5357c106 | 21 | void ossl_ffc_params_init(FFC_PARAMS *params) |
dc8de3e6 | 22 | { |
86cde318 | 23 | memset(params, 0, sizeof(*params)); |
dc8de3e6 | 24 | params->pcounter = -1; |
f11f86f6 | 25 | params->gindex = FFC_UNVERIFIABLE_GINDEX; |
4f2271d5 | 26 | params->flags = FFC_PARAM_FLAG_VALIDATE_ALL; |
dc8de3e6 SL |
27 | } |
28 | ||
5357c106 | 29 | void ossl_ffc_params_cleanup(FFC_PARAMS *params) |
dc8de3e6 SL |
30 | { |
31 | BN_free(params->p); | |
32 | BN_free(params->q); | |
33 | BN_free(params->g); | |
34 | BN_free(params->j); | |
35 | OPENSSL_free(params->seed); | |
5357c106 | 36 | ossl_ffc_params_init(params); |
dc8de3e6 SL |
37 | } |
38 | ||
5357c106 | 39 | void ossl_ffc_params_set0_pqg(FFC_PARAMS *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) |
dc8de3e6 SL |
40 | { |
41 | if (p != NULL && p != d->p) { | |
42 | BN_free(d->p); | |
43 | d->p = p; | |
44 | } | |
45 | if (q != NULL && q != d->q) { | |
46 | BN_free(d->q); | |
47 | d->q = q; | |
48 | } | |
49 | if (g != NULL && g != d->g) { | |
50 | BN_free(d->g); | |
51 | d->g = g; | |
52 | } | |
53 | } | |
54 | ||
5357c106 P |
55 | void ossl_ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p, |
56 | const BIGNUM **q, const BIGNUM **g) | |
dc8de3e6 SL |
57 | { |
58 | if (p != NULL) | |
59 | *p = d->p; | |
60 | if (q != NULL) | |
61 | *q = d->q; | |
62 | if (g != NULL) | |
63 | *g = d->g; | |
64 | } | |
65 | ||
66 | ||
67 | /* j is the 'cofactor' that is optionally output for ASN1. */ | |
5357c106 | 68 | void ossl_ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j) |
dc8de3e6 SL |
69 | { |
70 | BN_free(d->j); | |
71 | d->j = NULL; | |
72 | if (j != NULL) | |
73 | d->j = j; | |
74 | } | |
75 | ||
5357c106 P |
76 | int ossl_ffc_params_set_seed(FFC_PARAMS *params, |
77 | const unsigned char *seed, size_t seedlen) | |
dc8de3e6 SL |
78 | { |
79 | if (params == NULL) | |
80 | return 0; | |
81 | ||
b03ec3b5 SL |
82 | if (params->seed != NULL) { |
83 | if (params->seed == seed) | |
84 | return 1; | |
dc8de3e6 | 85 | OPENSSL_free(params->seed); |
b03ec3b5 | 86 | } |
dc8de3e6 SL |
87 | |
88 | if (seed != NULL && seedlen > 0) { | |
89 | params->seed = OPENSSL_memdup(seed, seedlen); | |
90 | if (params->seed == NULL) | |
91 | return 0; | |
92 | params->seedlen = seedlen; | |
93 | } else { | |
94 | params->seed = NULL; | |
95 | params->seedlen = 0; | |
96 | } | |
b03ec3b5 SL |
97 | return 1; |
98 | } | |
99 | ||
5357c106 | 100 | void ossl_ffc_params_set_gindex(FFC_PARAMS *params, int index) |
b03ec3b5 SL |
101 | { |
102 | params->gindex = index; | |
103 | } | |
104 | ||
5357c106 | 105 | void ossl_ffc_params_set_pcounter(FFC_PARAMS *params, int index) |
b03ec3b5 SL |
106 | { |
107 | params->pcounter = index; | |
108 | } | |
109 | ||
5357c106 | 110 | void ossl_ffc_params_set_h(FFC_PARAMS *params, int index) |
b03ec3b5 SL |
111 | { |
112 | params->h = index; | |
113 | } | |
114 | ||
5357c106 | 115 | void ossl_ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags) |
4f2271d5 SL |
116 | { |
117 | params->flags = flags; | |
118 | } | |
119 | ||
5357c106 P |
120 | void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags, |
121 | int enable) | |
38145fba SL |
122 | { |
123 | if (enable) | |
124 | params->flags |= flags; | |
125 | else | |
126 | params->flags &= ~flags; | |
127 | } | |
128 | ||
5357c106 | 129 | int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props) |
4f2271d5 SL |
130 | { |
131 | params->mdname = alg; | |
132 | params->mdprops = props; | |
133 | return 1; | |
134 | } | |
135 | ||
5357c106 P |
136 | int ossl_ffc_params_set_validate_params(FFC_PARAMS *params, |
137 | const unsigned char *seed, | |
138 | size_t seedlen, int counter) | |
b03ec3b5 | 139 | { |
5357c106 | 140 | if (!ossl_ffc_params_set_seed(params, seed, seedlen)) |
b03ec3b5 | 141 | return 0; |
dc8de3e6 SL |
142 | params->pcounter = counter; |
143 | return 1; | |
144 | } | |
145 | ||
5357c106 P |
146 | void ossl_ffc_params_get_validate_params(const FFC_PARAMS *params, |
147 | unsigned char **seed, size_t *seedlen, | |
148 | int *pcounter) | |
dc8de3e6 SL |
149 | { |
150 | if (seed != NULL) | |
151 | *seed = params->seed; | |
152 | if (seedlen != NULL) | |
153 | *seedlen = params->seedlen; | |
154 | if (pcounter != NULL) | |
155 | *pcounter = params->pcounter; | |
156 | } | |
157 | ||
158 | static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src) | |
159 | { | |
160 | BIGNUM *a; | |
161 | ||
162 | /* | |
163 | * If source is read only just copy the pointer, so | |
164 | * we don't have to reallocate it. | |
165 | */ | |
166 | if (src == NULL) | |
167 | a = NULL; | |
168 | else if (BN_get_flags(src, BN_FLG_STATIC_DATA) | |
169 | && !BN_get_flags(src, BN_FLG_MALLOCED)) | |
170 | a = (BIGNUM *)src; | |
171 | else if ((a = BN_dup(src)) == NULL) | |
172 | return 0; | |
173 | BN_clear_free(*dst); | |
174 | *dst = a; | |
175 | return 1; | |
176 | } | |
177 | ||
5357c106 | 178 | int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src) |
dc8de3e6 SL |
179 | { |
180 | if (!ffc_bn_cpy(&dst->p, src->p) | |
181 | || !ffc_bn_cpy(&dst->g, src->g) | |
182 | || !ffc_bn_cpy(&dst->q, src->q) | |
183 | || !ffc_bn_cpy(&dst->j, src->j)) | |
184 | return 0; | |
185 | ||
186 | OPENSSL_free(dst->seed); | |
187 | dst->seedlen = src->seedlen; | |
188 | if (src->seed != NULL) { | |
189 | dst->seed = OPENSSL_memdup(src->seed, src->seedlen); | |
190 | if (dst->seed == NULL) | |
191 | return 0; | |
192 | } else { | |
193 | dst->seed = NULL; | |
194 | } | |
b03ec3b5 | 195 | dst->nid = src->nid; |
dc8de3e6 | 196 | dst->pcounter = src->pcounter; |
b03ec3b5 SL |
197 | dst->h = src->h; |
198 | dst->gindex = src->gindex; | |
2145ba5e | 199 | dst->flags = src->flags; |
dc8de3e6 SL |
200 | return 1; |
201 | } | |
202 | ||
5357c106 | 203 | int ossl_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q) |
dc8de3e6 SL |
204 | { |
205 | return BN_cmp(a->p, b->p) == 0 | |
206 | && BN_cmp(a->g, b->g) == 0 | |
207 | && (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */ | |
208 | } | |
209 | ||
4f2271d5 SL |
210 | static const OSSL_ITEM flag_map[] = { |
211 | { FFC_PARAM_FLAG_VALIDATE_PQ, OSSL_FFC_PARAM_VALIDATE_PQ }, | |
212 | { FFC_PARAM_FLAG_VALIDATE_G, OSSL_FFC_PARAM_VALIDATE_G }, | |
213 | { FFC_PARAM_FLAG_VALIDATE_ALL, OSSL_FFC_PARAM_VALIDATE_PQG }, | |
214 | { 0, "" } | |
215 | }; | |
216 | ||
5357c106 | 217 | int ossl_ffc_params_flags_from_name(const char *name) |
4f2271d5 SL |
218 | { |
219 | size_t i; | |
220 | ||
221 | for (i = 0; i < OSSL_NELEM(flag_map); ++i) { | |
222 | if (strcasecmp(flag_map[i].ptr, name) == 0) | |
223 | return flag_map[i].id; | |
224 | } | |
225 | return NID_undef; | |
226 | } | |
227 | ||
5357c106 | 228 | const char *ossl_ffc_params_flags_to_name(int flags) |
4f2271d5 SL |
229 | { |
230 | size_t i; | |
231 | ||
232 | flags &= FFC_PARAM_FLAG_VALIDATE_ALL; | |
233 | for (i = 0; i < OSSL_NELEM(flag_map); ++i) { | |
234 | if ((int)flag_map[i].id == flags) | |
235 | return flag_map[i].ptr; | |
236 | } | |
237 | return ""; | |
238 | } | |
239 | ||
5357c106 | 240 | int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld, |
b03ec3b5 SL |
241 | OSSL_PARAM params[]) |
242 | { | |
243 | if (ffc == NULL) | |
244 | return 0; | |
245 | ||
246 | if (ffc->p != NULL | |
247 | && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_P, ffc->p)) | |
248 | return 0; | |
249 | if (ffc->q != NULL | |
250 | && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_Q, ffc->q)) | |
251 | return 0; | |
252 | if (ffc->g != NULL | |
253 | && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_G, ffc->g)) | |
254 | return 0; | |
255 | if (ffc->j != NULL | |
256 | && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_COFACTOR, | |
257 | ffc->j)) | |
258 | return 0; | |
259 | if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_GINDEX, | |
260 | ffc->gindex)) | |
261 | return 0; | |
262 | if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_PCOUNTER, | |
263 | ffc->pcounter)) | |
264 | return 0; | |
265 | if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_H, ffc->h)) | |
266 | return 0; | |
267 | if (ffc->seed != NULL | |
268 | && !ossl_param_build_set_octet_string(bld, params, | |
269 | OSSL_PKEY_PARAM_FFC_SEED, | |
270 | ffc->seed, ffc->seedlen)) | |
271 | return 0; | |
272 | if (ffc->nid != NID_undef) { | |
c829c23b RL |
273 | const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid); |
274 | const char *name = ossl_ffc_named_group_get_name(group); | |
b03ec3b5 SL |
275 | |
276 | if (name == NULL | |
277 | || !ossl_param_build_set_utf8_string(bld, params, | |
023b188c | 278 | OSSL_PKEY_PARAM_GROUP_NAME, |
b03ec3b5 SL |
279 | name)) |
280 | return 0; | |
281 | } | |
4f2271d5 SL |
282 | if (!ossl_param_build_set_utf8_string(bld, params, |
283 | OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE, | |
5357c106 | 284 | ossl_ffc_params_flags_to_name(ffc->flags))) |
4f2271d5 SL |
285 | return 0; |
286 | if (ffc->mdname != NULL | |
287 | && !ossl_param_build_set_utf8_string(bld, params, | |
288 | OSSL_PKEY_PARAM_FFC_DIGEST, | |
289 | ffc->mdname)) | |
290 | return 0; | |
291 | if (ffc->mdprops != NULL | |
292 | && !ossl_param_build_set_utf8_string(bld, params, | |
293 | OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, | |
294 | ffc->mdprops)) | |
295 | return 0; | |
b03ec3b5 SL |
296 | return 1; |
297 | } | |
298 | ||
f844f9eb | 299 | #ifndef FIPS_MODULE |
5357c106 | 300 | int ossl_ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent) |
dc8de3e6 SL |
301 | { |
302 | if (!ASN1_bn_print(bp, "prime P:", ffc->p, NULL, indent)) | |
303 | goto err; | |
304 | if (!ASN1_bn_print(bp, "generator G:", ffc->g, NULL, indent)) | |
305 | goto err; | |
306 | if (ffc->q != NULL | |
307 | && !ASN1_bn_print(bp, "subgroup order Q:", ffc->q, NULL, indent)) | |
308 | goto err; | |
309 | if (ffc->j != NULL | |
310 | && !ASN1_bn_print(bp, "subgroup factor:", ffc->j, NULL, indent)) | |
311 | goto err; | |
312 | if (ffc->seed != NULL) { | |
313 | size_t i; | |
776cf98b SL |
314 | |
315 | if (!BIO_indent(bp, indent, 128) | |
316 | || BIO_puts(bp, "seed:") <= 0) | |
317 | goto err; | |
dc8de3e6 SL |
318 | for (i = 0; i < ffc->seedlen; i++) { |
319 | if ((i % 15) == 0) { | |
320 | if (BIO_puts(bp, "\n") <= 0 | |
321 | || !BIO_indent(bp, indent + 4, 128)) | |
322 | goto err; | |
323 | } | |
324 | if (BIO_printf(bp, "%02x%s", ffc->seed[i], | |
325 | ((i + 1) == ffc->seedlen) ? "" : ":") <= 0) | |
326 | goto err; | |
327 | } | |
328 | if (BIO_write(bp, "\n", 1) <= 0) | |
329 | return 0; | |
330 | } | |
331 | if (ffc->pcounter != -1) { | |
776cf98b SL |
332 | if (!BIO_indent(bp, indent, 128) |
333 | || BIO_printf(bp, "counter: %d\n", ffc->pcounter) <= 0) | |
dc8de3e6 SL |
334 | goto err; |
335 | } | |
336 | return 1; | |
337 | err: | |
338 | return 0; | |
339 | } | |
f844f9eb | 340 | #endif /* FIPS_MODULE */ |