1/*
2 * libssl_compat.c -- OpenSSL v1.1 compatibility functions
3 *
4 * ---------------------------------------------------------------------
5 * Written by Juergen Perlinger <perlinger@ntp.org> for the NTP project
6 *
7 * Based on an idea by Kurt Roeckx <kurt@roeckx.be>
8 *
9 * ---------------------------------------------------------------------
10 * This is a clean room implementation of shim functions that have
11 * counterparts in the OpenSSL v1.1 API but not in earlier versions. So
12 * while OpenSSL broke binary compatibility with v1.1, this shim module
13 * should provide the necessary source code compatibility with older
14 * versions of OpenSSL.
15 * ---------------------------------------------------------------------
16 */
17#include "config.h"
18
19#include <string.h>
20#include <openssl/bn.h>
21#include <openssl/evp.h>
22
23#include "ntp_types.h"
24
25/* ----------------------------------------------------------------- */
26#if OPENSSL_VERSION_NUMBER < 0x10100000L
27/* ----------------------------------------------------------------- */
28
29#include "libssl_compat.h"
30#include "ntp_assert.h"
31
32/* --------------------------------------------------------------------
33 * replace a BIGNUM owned by the caller with another one if it's not
34 * NULL, taking over the ownership of the new value. This clears & frees
35 * the old value -- the clear might be overkill, but it's better to err
36 * on the side of paranoia here.
37 */
38static void
39replace_bn_nn(
40	BIGNUM **	ps,
41	BIGNUM *	n
42	)
43{
44	if (n) {
45		REQUIRE(*ps != n);
46		BN_clear_free(*ps);
47		*ps = n;
48	}
49}
50
51/* --------------------------------------------------------------------
52 * allocation and deallocation of prime number callbacks
53 */
54BN_GENCB*
55sslshimBN_GENCB_new(void)
56{
57	return calloc(1,sizeof(BN_GENCB));
58}
59
60void
61sslshimBN_GENCB_free(
62	BN_GENCB	*cb
63	)
64{
65	free(cb);
66}
67
68/* --------------------------------------------------------------------
69 * allocation and deallocation of message digests
70 */
71EVP_MD_CTX*
72sslshim_EVP_MD_CTX_new(void)
73{
74	return calloc(1, sizeof(EVP_MD_CTX));
75}
76
77void
78sslshim_EVP_MD_CTX_free(
79	EVP_MD_CTX *	pctx
80	)
81{
82	free(pctx);
83}
84
85/* --------------------------------------------------------------------
86 * get EVP keys and key type
87 */
88int
89sslshim_EVP_PKEY_id(
90	const EVP_PKEY *pkey
91	)
92{
93	return (pkey) ? pkey->type : EVP_PKEY_NONE;
94}
95
96int
97sslshim_EVP_PKEY_base_id(
98	const EVP_PKEY *pkey
99	)
100{
101	return (pkey) ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
102}
103
104RSA*
105sslshim_EVP_PKEY_get0_RSA(
106	EVP_PKEY *	pkey
107	)
108{
109	return (pkey) ? pkey->pkey.rsa : NULL;
110}
111
112DSA*
113sslshim_EVP_PKEY_get0_DSA(
114	EVP_PKEY *	pkey
115	)
116{
117	return (pkey) ? pkey->pkey.dsa : NULL;
118}
119
120/* --------------------------------------------------------------------
121 * set/get RSA params
122 */
123void
124sslshim_RSA_get0_key(
125	const RSA *	prsa,
126	const BIGNUM **	pn,
127	const BIGNUM **	pe,
128	const BIGNUM **	pd
129	)
130{
131	REQUIRE(prsa != NULL);
132
133	if (pn)
134		*pn = prsa->n;
135	if (pe)
136		*pe = prsa->e;
137	if (pd)
138		*pd = prsa->d;
139}
140
141int
142sslshim_RSA_set0_key(
143	RSA *		prsa,
144	BIGNUM *	n,
145	BIGNUM *	e,
146	BIGNUM *	d
147	)
148{
149	REQUIRE(prsa != NULL);
150	if (!((prsa->n || n) && (prsa->e || e)))
151		return 0;
152
153	replace_bn_nn(&prsa->n, n);
154	replace_bn_nn(&prsa->e, e);
155	replace_bn_nn(&prsa->d, d);
156
157	return 1;
158}
159
160void
161sslshim_RSA_get0_factors(
162	const RSA *	prsa,
163	const BIGNUM **	pp,
164	const BIGNUM **	pq
165	)
166{
167	REQUIRE(prsa != NULL);
168
169	if (pp)
170		*pp = prsa->p;
171	if (pq)
172		*pq = prsa->q;
173}
174
175int
176sslshim_RSA_set0_factors(
177	RSA    *	prsa,
178	BIGNUM *	p,
179	BIGNUM *	q
180	)
181{
182	REQUIRE(prsa != NULL);
183	if (!((prsa->p || p) && (prsa->q || q)))
184		return 0;
185
186	replace_bn_nn(&prsa->p, p);
187	replace_bn_nn(&prsa->q, q);
188
189	return 1;
190}
191
192int
193sslshim_RSA_set0_crt_params(
194	RSA    *	prsa,
195	BIGNUM *	dmp1,
196	BIGNUM *	dmq1,
197	BIGNUM *	iqmp
198	)
199{
200	REQUIRE(prsa != NULL);
201	if (!((prsa->dmp1 || dmp1) &&
202	      (prsa->dmq1 || dmq1) &&
203	      (prsa->iqmp || iqmp) ))
204		return 0;
205
206	replace_bn_nn(&prsa->dmp1, dmp1);
207	replace_bn_nn(&prsa->dmq1, dmq1);
208	replace_bn_nn(&prsa->iqmp, iqmp);
209
210	return 1;
211}
212
213/* --------------------------------------------------------------------
214 * set/get DSA signature parameters
215 */
216void
217sslshim_DSA_SIG_get0(
218	const DSA_SIG *	psig,
219	const BIGNUM **	pr,
220	const BIGNUM **	ps
221	)
222{
223	REQUIRE(psig != NULL);
224
225	if (pr != NULL)
226		*pr = psig->r;
227	if (ps != NULL)
228		*ps = psig->s;
229}
230
231int
232sslshim_DSA_SIG_set0(
233	DSA_SIG *	psig,
234	BIGNUM *	r,
235	BIGNUM *	s
236	)
237{
238	REQUIRE(psig != NULL);
239	if (!(r && s))
240		return 0;
241
242	replace_bn_nn(&psig->r, r);
243	replace_bn_nn(&psig->s, s);
244
245	return 1;
246}
247
248/* --------------------------------------------------------------------
249 * get/set DSA parameters
250 */
251void
252sslshim_DSA_get0_pqg(
253	const DSA *	pdsa,
254	const BIGNUM **	pp,
255	const BIGNUM **	pq,
256	const BIGNUM **	pg
257	)
258{
259	REQUIRE(pdsa != NULL);
260
261	if (pp != NULL)
262		*pp = pdsa->p;
263	if (pq != NULL)
264		*pq = pdsa->q;
265	if (pg != NULL)
266		*pg = pdsa->g;
267}
268
269int
270sslshim_DSA_set0_pqg(
271	DSA *		pdsa,
272	BIGNUM *	p,
273	BIGNUM *	q,
274	BIGNUM *	g
275	)
276{
277	if (!((pdsa->p || p) && (pdsa->q || q) && (pdsa->g || g)))
278		return 0;
279
280	replace_bn_nn(&pdsa->p, p);
281	replace_bn_nn(&pdsa->q, q);
282	replace_bn_nn(&pdsa->g, g);
283
284	return 1;
285}
286
287void
288sslshim_DSA_get0_key(
289	const DSA *	pdsa,
290	const BIGNUM **	ppub_key,
291	const BIGNUM **	ppriv_key
292	)
293{
294	REQUIRE(pdsa != NULL);
295
296	if (ppub_key != NULL)
297		*ppub_key = pdsa->pub_key;
298	if (ppriv_key != NULL)
299		*ppriv_key = pdsa->priv_key;
300}
301
302int
303sslshim_DSA_set0_key(
304	DSA *		pdsa,
305	BIGNUM *	pub_key,
306	BIGNUM *	priv_key
307	)
308{
309	REQUIRE(pdsa != NULL);
310	if (!(pdsa->pub_key || pub_key))
311		return 0;
312
313	replace_bn_nn(&pdsa->pub_key, pub_key);
314	replace_bn_nn(&pdsa->priv_key, priv_key);
315
316	return 1;
317}
318
319int
320sslshim_X509_get_signature_nid(
321	const X509 *x
322	)
323{
324	return OBJ_obj2nid(x->sig_alg->algorithm);
325}
326
327/* ----------------------------------------------------------------- */
328#else /* OPENSSL_VERSION_NUMBER >= v1.1.0 */
329/* ----------------------------------------------------------------- */
330
331NONEMPTY_TRANSLATION_UNIT
332
333/* ----------------------------------------------------------------- */
334#endif
335/* ----------------------------------------------------------------- */
336