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