/src/openssl31/crypto/dh/dh_backend.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Copyright 2020-2022 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  |  | /*  | 
11  |  |  * DH low level APIs are deprecated for public use, but still ok for  | 
12  |  |  * internal use.  | 
13  |  |  */  | 
14  |  | #include "internal/deprecated.h"  | 
15  |  |  | 
16  |  | #include <openssl/err.h>  | 
17  |  | #include <openssl/core_names.h>  | 
18  |  | #ifndef FIPS_MODULE  | 
19  |  | # include <openssl/x509.h>  | 
20  |  | #endif  | 
21  |  | #include "internal/param_build_set.h"  | 
22  |  | #include "crypto/dh.h"  | 
23  |  | #include "dh_local.h"  | 
24  |  |  | 
25  |  | /*  | 
26  |  |  * The intention with the "backend" source file is to offer backend functions  | 
27  |  |  * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider  | 
28  |  |  * implementations alike.  | 
29  |  |  */  | 
30  |  |  | 
31  |  | static int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[])  | 
32  | 2.57k  | { | 
33  | 2.57k  |     int ret;  | 
34  | 2.57k  |     FFC_PARAMS *ffc;  | 
35  |  |  | 
36  | 2.57k  |     if (dh == NULL)  | 
37  | 0  |         return 0;  | 
38  | 2.57k  |     ffc = ossl_dh_get0_params(dh);  | 
39  | 2.57k  |     if (ffc == NULL)  | 
40  | 0  |         return 0;  | 
41  |  |  | 
42  | 2.57k  |     ret = ossl_ffc_params_fromdata(ffc, params);  | 
43  | 2.57k  |     if (ret)  | 
44  | 2.57k  |         ossl_dh_cache_named_group(dh); /* This increments dh->dirty_cnt */  | 
45  | 2.57k  |     return ret;  | 
46  | 2.57k  | }  | 
47  |  |  | 
48  |  | int ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[])  | 
49  | 5.47k  | { | 
50  | 5.47k  |     const OSSL_PARAM *param_priv_len;  | 
51  | 5.47k  |     long priv_len;  | 
52  |  |  | 
53  | 5.47k  |     if (!dh_ffc_params_fromdata(dh, params))  | 
54  | 0  |         return 0;  | 
55  |  |  | 
56  | 5.47k  |     param_priv_len =  | 
57  | 5.47k  |         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);  | 
58  | 5.47k  |     if (param_priv_len != NULL  | 
59  | 5.47k  |         && (!OSSL_PARAM_get_long(param_priv_len, &priv_len)  | 
60  | 0  |             || !DH_set_length(dh, priv_len)))  | 
61  | 0  |         return 0;  | 
62  |  |  | 
63  | 5.47k  |     return 1;  | 
64  | 5.47k  | }  | 
65  |  |  | 
66  |  | int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private)  | 
67  | 5.47k  | { | 
68  | 5.47k  |     const OSSL_PARAM *param_priv_key, *param_pub_key;  | 
69  | 5.47k  |     BIGNUM *priv_key = NULL, *pub_key = NULL;  | 
70  |  |  | 
71  | 5.47k  |     if (dh == NULL)  | 
72  | 0  |         return 0;  | 
73  |  |  | 
74  | 5.47k  |     param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);  | 
75  | 5.47k  |     param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);  | 
76  |  |  | 
77  | 5.47k  |     if (include_private  | 
78  | 5.47k  |         && param_priv_key != NULL  | 
79  | 5.47k  |         && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))  | 
80  | 0  |         goto err;  | 
81  |  |  | 
82  | 5.47k  |     if (param_pub_key != NULL  | 
83  | 5.47k  |         && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))  | 
84  | 0  |         goto err;  | 
85  |  |  | 
86  | 5.47k  |     if (!DH_set0_key(dh, pub_key, priv_key))  | 
87  | 0  |         goto err;  | 
88  |  |  | 
89  | 5.47k  |     return 1;  | 
90  |  |  | 
91  | 0  |  err:  | 
92  | 0  |     BN_clear_free(priv_key);  | 
93  | 0  |     BN_free(pub_key);  | 
94  | 0  |     return 0;  | 
95  | 5.47k  | }  | 
96  |  |  | 
97  |  | int ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])  | 
98  | 56.8k  | { | 
99  | 56.8k  |     long l = DH_get_length(dh);  | 
100  |  |  | 
101  | 56.8k  |     if (!ossl_ffc_params_todata(ossl_dh_get0_params(dh), bld, params))  | 
102  | 0  |         return 0;  | 
103  | 56.8k  |     if (l > 0  | 
104  | 56.8k  |         && !ossl_param_build_set_long(bld, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))  | 
105  | 0  |         return 0;  | 
106  | 56.8k  |     return 1;  | 
107  | 56.8k  | }  | 
108  |  |  | 
109  |  | int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],  | 
110  |  |                        int include_private)  | 
111  | 56.8k  | { | 
112  | 56.8k  |     const BIGNUM *priv = NULL, *pub = NULL;  | 
113  |  |  | 
114  | 56.8k  |     if (dh == NULL)  | 
115  | 0  |         return 0;  | 
116  |  |  | 
117  | 56.8k  |     DH_get0_key(dh, &pub, &priv);  | 
118  | 56.8k  |     if (priv != NULL  | 
119  | 56.8k  |         && include_private  | 
120  | 56.8k  |         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))  | 
121  | 0  |         return 0;  | 
122  | 56.8k  |     if (pub != NULL  | 
123  | 56.8k  |         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))  | 
124  | 0  |         return 0;  | 
125  |  |  | 
126  | 56.8k  |     return 1;  | 
127  | 56.8k  | }  | 
128  |  |  | 
129  |  | int ossl_dh_is_foreign(const DH *dh)  | 
130  | 17.4k  | { | 
131  | 17.4k  | #ifndef FIPS_MODULE  | 
132  | 17.4k  |     if (dh->engine != NULL || ossl_dh_get_method(dh) != DH_OpenSSL())  | 
133  | 0  |         return 1;  | 
134  | 17.4k  | #endif  | 
135  | 17.4k  |     return 0;  | 
136  | 17.4k  | }  | 
137  |  |  | 
138  |  | static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f)  | 
139  | 8.33k  | { | 
140  | 8.33k  |     if (f != NULL && (*out = BN_dup(f)) == NULL)  | 
141  | 0  |         return 0;  | 
142  | 8.33k  |     return 1;  | 
143  | 8.33k  | }  | 
144  |  |  | 
145  |  | DH *ossl_dh_dup(const DH *dh, int selection)  | 
146  | 4.16k  | { | 
147  | 4.16k  |     DH *dupkey = NULL;  | 
148  |  |  | 
149  |  |     /* Do not try to duplicate foreign DH keys */  | 
150  | 4.16k  |     if (ossl_dh_is_foreign(dh))  | 
151  | 0  |         return NULL;  | 
152  |  |  | 
153  | 4.16k  |     if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL)  | 
154  | 0  |         return NULL;  | 
155  |  |  | 
156  | 4.16k  |     dupkey->length = DH_get_length(dh);  | 
157  | 4.16k  |     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0  | 
158  | 4.16k  |         && !ossl_ffc_params_copy(&dupkey->params, &dh->params))  | 
159  | 0  |         goto err;  | 
160  |  |  | 
161  | 4.16k  |     dupkey->flags = dh->flags;  | 
162  |  |  | 
163  | 4.16k  |     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0  | 
164  | 4.16k  |         && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0  | 
165  | 4.16k  |             || !dh_bn_dup_check(&dupkey->pub_key, dh->pub_key)))  | 
166  | 0  |         goto err;  | 
167  |  |  | 
168  | 4.16k  |     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0  | 
169  | 4.16k  |         && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0  | 
170  | 4.16k  |             || !dh_bn_dup_check(&dupkey->priv_key, dh->priv_key)))  | 
171  | 0  |         goto err;  | 
172  |  |  | 
173  | 4.16k  | #ifndef FIPS_MODULE  | 
174  | 4.16k  |     if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH,  | 
175  | 4.16k  |                             &dupkey->ex_data, &dh->ex_data))  | 
176  | 0  |         goto err;  | 
177  | 4.16k  | #endif  | 
178  |  |  | 
179  | 4.16k  |     return dupkey;  | 
180  |  |  | 
181  | 0  |  err:  | 
182  | 0  |     DH_free(dupkey);  | 
183  | 0  |     return NULL;  | 
184  | 4.16k  | }  | 
185  |  |  | 
186  |  | #ifndef FIPS_MODULE  | 
187  |  | DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,  | 
188  |  |                            OSSL_LIB_CTX *libctx, const char *propq)  | 
189  | 244  | { | 
190  | 244  |     const unsigned char *p, *pm;  | 
191  | 244  |     int pklen, pmlen;  | 
192  | 244  |     int ptype;  | 
193  | 244  |     const void *pval;  | 
194  | 244  |     const ASN1_STRING *pstr;  | 
195  | 244  |     const X509_ALGOR *palg;  | 
196  | 244  |     BIGNUM *privkey_bn = NULL;  | 
197  | 244  |     ASN1_INTEGER *privkey = NULL;  | 
198  | 244  |     DH *dh = NULL;  | 
199  |  |  | 
200  | 244  |     if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))  | 
201  | 0  |         return 0;  | 
202  |  |  | 
203  | 244  |     X509_ALGOR_get0(NULL, &ptype, &pval, palg);  | 
204  |  |  | 
205  | 244  |     if (ptype != V_ASN1_SEQUENCE)  | 
206  | 54  |         goto decerr;  | 
207  | 190  |     if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)  | 
208  | 21  |         goto decerr;  | 
209  |  |  | 
210  | 169  |     pstr = pval;  | 
211  | 169  |     pm = pstr->data;  | 
212  | 169  |     pmlen = pstr->length;  | 
213  | 169  |     switch (OBJ_obj2nid(palg->algorithm)) { | 
214  | 12  |     case NID_dhKeyAgreement:  | 
215  | 12  |         dh = d2i_DHparams(NULL, &pm, pmlen);  | 
216  | 12  |         break;  | 
217  | 157  |     case NID_dhpublicnumber:  | 
218  | 157  |         dh = d2i_DHxparams(NULL, &pm, pmlen);  | 
219  | 157  |         break;  | 
220  | 0  |     default:  | 
221  | 0  |         goto decerr;  | 
222  | 169  |     }  | 
223  | 169  |     if (dh == NULL)  | 
224  | 34  |         goto decerr;  | 
225  |  |  | 
226  |  |     /* We have parameters now set private key */  | 
227  | 135  |     if ((privkey_bn = BN_secure_new()) == NULL  | 
228  | 135  |         || !ASN1_INTEGER_to_BN(privkey, privkey_bn)) { | 
229  | 0  |         ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);  | 
230  | 0  |         BN_clear_free(privkey_bn);  | 
231  | 0  |         goto dherr;  | 
232  | 0  |     }  | 
233  | 135  |     if (!DH_set0_key(dh, NULL, privkey_bn))  | 
234  | 0  |         goto dherr;  | 
235  |  |     /* Calculate public key, increments dirty_cnt */  | 
236  | 135  |     if (!DH_generate_key(dh))  | 
237  | 49  |         goto dherr;  | 
238  |  |  | 
239  | 86  |     goto done;  | 
240  |  |  | 
241  | 109  |  decerr:  | 
242  | 109  |     ERR_raise(ERR_LIB_DH, EVP_R_DECODE_ERROR);  | 
243  | 158  |  dherr:  | 
244  | 158  |     DH_free(dh);  | 
245  | 158  |     dh = NULL;  | 
246  | 244  |  done:  | 
247  | 244  |     ASN1_STRING_clear_free(privkey);  | 
248  | 244  |     return dh;  | 
249  | 158  | }  | 
250  |  | #endif  |