| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string.h> /* memset */
 | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  | #include <openssl/core_names.h>
 | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | #include "internal/ffc.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  | #include "internal/param_build_set.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | # include <openssl/asn1.h> /* ffc_params_print */
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_init(FFC_PARAMS *params) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-16 16:02:38 +08:00
										 |  |  |     memset(params, 0, sizeof(*params)); | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  |     params->pcounter = -1; | 
					
						
							| 
									
										
										
										
											2020-02-06 20:28:36 +08:00
										 |  |  |     params->gindex = FFC_UNVERIFIABLE_GINDEX; | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_cleanup(FFC_PARAMS *params) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BN_free(params->p); | 
					
						
							|  |  |  |     BN_free(params->q); | 
					
						
							|  |  |  |     BN_free(params->g); | 
					
						
							|  |  |  |     BN_free(params->j); | 
					
						
							|  |  |  |     OPENSSL_free(params->seed); | 
					
						
							|  |  |  |     ffc_params_init(params); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_set0_pqg(FFC_PARAMS *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (p != NULL && p != d->p) { | 
					
						
							|  |  |  |         BN_free(d->p); | 
					
						
							|  |  |  |         d->p = p; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (q != NULL && q != d->q) { | 
					
						
							|  |  |  |         BN_free(d->q); | 
					
						
							|  |  |  |         d->q = q; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (g != NULL && g != d->g) { | 
					
						
							|  |  |  |         BN_free(d->g); | 
					
						
							|  |  |  |         d->g = g; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p, | 
					
						
							|  |  |  |                          const BIGNUM **q, const BIGNUM **g) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (p != NULL) | 
					
						
							|  |  |  |         *p = d->p; | 
					
						
							|  |  |  |     if (q != NULL) | 
					
						
							|  |  |  |         *q = d->q; | 
					
						
							|  |  |  |     if (g != NULL) | 
					
						
							|  |  |  |         *g = d->g; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* j is the 'cofactor' that is optionally output for ASN1. */ | 
					
						
							|  |  |  | void ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *j) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BN_free(d->j); | 
					
						
							|  |  |  |     d->j = NULL; | 
					
						
							|  |  |  |     if (j != NULL) | 
					
						
							|  |  |  |         d->j = j; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  | int ffc_params_set_seed(FFC_PARAMS *params, | 
					
						
							|  |  |  |                         const unsigned char *seed, size_t seedlen) | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (params == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |     if (params->seed != NULL) { | 
					
						
							|  |  |  |         if (params->seed == seed) | 
					
						
							|  |  |  |             return 1; | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  |         OPENSSL_free(params->seed); | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (seed != NULL && seedlen > 0) { | 
					
						
							|  |  |  |         params->seed = OPENSSL_memdup(seed, seedlen); | 
					
						
							|  |  |  |         if (params->seed == NULL) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         params->seedlen = seedlen; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         params->seed = NULL; | 
					
						
							|  |  |  |         params->seedlen = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_set_gindex(FFC_PARAMS *params, int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     params->gindex = index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_set_pcounter(FFC_PARAMS *params, int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     params->pcounter = index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_set_h(FFC_PARAMS *params, int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     params->h = index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ffc_params_set_validate_params(FFC_PARAMS *params, | 
					
						
							|  |  |  |                                    const unsigned char *seed, size_t seedlen, | 
					
						
							|  |  |  |                                    int counter) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!ffc_params_set_seed(params, seed, seedlen)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  |     params->pcounter = counter; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ffc_params_get_validate_params(const FFC_PARAMS *params, | 
					
						
							|  |  |  |                                     unsigned char **seed, size_t *seedlen, | 
					
						
							|  |  |  |                                     int *pcounter) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (seed != NULL) | 
					
						
							|  |  |  |         *seed = params->seed; | 
					
						
							|  |  |  |     if (seedlen != NULL) | 
					
						
							|  |  |  |         *seedlen = params->seedlen; | 
					
						
							|  |  |  |     if (pcounter != NULL) | 
					
						
							|  |  |  |         *pcounter = params->pcounter; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BIGNUM *a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If source is read only just copy the pointer, so | 
					
						
							|  |  |  |      * we don't have to reallocate it. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (src == NULL) | 
					
						
							|  |  |  |         a = NULL; | 
					
						
							|  |  |  |     else if (BN_get_flags(src, BN_FLG_STATIC_DATA) | 
					
						
							|  |  |  |              && !BN_get_flags(src, BN_FLG_MALLOCED)) | 
					
						
							|  |  |  |         a = (BIGNUM *)src; | 
					
						
							|  |  |  |     else if ((a = BN_dup(src)) == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     BN_clear_free(*dst); | 
					
						
							|  |  |  |     *dst = a; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!ffc_bn_cpy(&dst->p, src->p) | 
					
						
							|  |  |  |         || !ffc_bn_cpy(&dst->g, src->g) | 
					
						
							|  |  |  |         || !ffc_bn_cpy(&dst->q, src->q) | 
					
						
							|  |  |  |         || !ffc_bn_cpy(&dst->j, src->j)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     OPENSSL_free(dst->seed); | 
					
						
							|  |  |  |     dst->seedlen = src->seedlen; | 
					
						
							|  |  |  |     if (src->seed != NULL) { | 
					
						
							|  |  |  |         dst->seed = OPENSSL_memdup(src->seed, src->seedlen); | 
					
						
							|  |  |  |         if  (dst->seed == NULL) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         dst->seed = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |     dst->nid = src->nid; | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  |     dst->pcounter = src->pcounter; | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |     dst->h = src->h; | 
					
						
							|  |  |  |     dst->gindex = src->gindex; | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return BN_cmp(a->p, b->p) == 0 | 
					
						
							|  |  |  |            && BN_cmp(a->g, b->g) == 0 | 
					
						
							|  |  |  |            && (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  | int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld, | 
					
						
							|  |  |  |                       OSSL_PARAM params[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (ffc == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ffc->p != NULL | 
					
						
							|  |  |  |         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_P, ffc->p)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (ffc->q != NULL | 
					
						
							|  |  |  |         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_Q, ffc->q)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (ffc->g != NULL | 
					
						
							|  |  |  |         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_G, ffc->g)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (ffc->j != NULL | 
					
						
							|  |  |  |         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_FFC_COFACTOR, | 
					
						
							|  |  |  |                                     ffc->j)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_GINDEX, | 
					
						
							|  |  |  |                                   ffc->gindex)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_PCOUNTER, | 
					
						
							|  |  |  |                                   ffc->pcounter)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (!ossl_param_build_set_int(bld, params, OSSL_PKEY_PARAM_FFC_H, ffc->h)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (ffc->seed != NULL | 
					
						
							|  |  |  |         && !ossl_param_build_set_octet_string(bld, params, | 
					
						
							|  |  |  |                                               OSSL_PKEY_PARAM_FFC_SEED, | 
					
						
							|  |  |  |                                               ffc->seed, ffc->seedlen)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (ffc->nid != NID_undef) { | 
					
						
							| 
									
										
										
										
											2020-04-20 21:05:23 +08:00
										 |  |  | #ifndef OPENSSL_NO_DH
 | 
					
						
							| 
									
										
										
										
											2020-04-15 23:14:00 +08:00
										 |  |  |         const char *name = ffc_named_group_from_uid(ffc->nid); | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (name == NULL | 
					
						
							|  |  |  |             || !ossl_param_build_set_utf8_string(bld, params, | 
					
						
							| 
									
										
										
										
											2020-05-26 11:53:07 +08:00
										 |  |  |                                                  OSSL_PKEY_PARAM_DH_GROUP, | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |                                                  name)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2020-04-20 21:05:23 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |         /* How could this be? We should not have a nid in a no-dh build. */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-15 19:02:52 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2020-01-24 12:09:33 +08:00
										 |  |  | int ffc_params_print(BIO *bp, const FFC_PARAMS *ffc, int indent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!ASN1_bn_print(bp, "prime P:", ffc->p, NULL, indent)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     if (!ASN1_bn_print(bp, "generator G:", ffc->g, NULL, indent)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     if (ffc->q != NULL | 
					
						
							|  |  |  |         && !ASN1_bn_print(bp, "subgroup order Q:", ffc->q, NULL, indent)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     if (ffc->j != NULL | 
					
						
							|  |  |  |         && !ASN1_bn_print(bp, "subgroup factor:", ffc->j, NULL, indent)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     if (ffc->seed != NULL) { | 
					
						
							|  |  |  |         size_t i; | 
					
						
							|  |  |  |         BIO_indent(bp, indent, 128); | 
					
						
							|  |  |  |         BIO_puts(bp, "seed:"); | 
					
						
							|  |  |  |         for (i = 0; i < ffc->seedlen; i++) { | 
					
						
							|  |  |  |             if ((i % 15) == 0) { | 
					
						
							|  |  |  |                 if (BIO_puts(bp, "\n") <= 0 | 
					
						
							|  |  |  |                     || !BIO_indent(bp, indent + 4, 128)) | 
					
						
							|  |  |  |                     goto err; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (BIO_printf(bp, "%02x%s", ffc->seed[i], | 
					
						
							|  |  |  |                            ((i + 1) == ffc->seedlen) ? "" : ":") <= 0) | 
					
						
							|  |  |  |                 goto err; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (BIO_write(bp, "\n", 1) <= 0) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ffc->pcounter != -1) { | 
					
						
							|  |  |  |         BIO_indent(bp, indent, 128); | 
					
						
							|  |  |  |         if (BIO_printf(bp, "counter: %d\n", ffc->pcounter) <= 0) | 
					
						
							|  |  |  |             goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #endif /* FIPS_MODULE */
 |