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