1/*
2 * Copyright (c) 2011-12 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * Copyright (c) 2006 Kungliga Tekniska Högskolan
26 * (Royal Institute of Technology, Stockholm, Sweden).
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * 1. Redistributions of source code must retain the above copyright
34 *    notice, this list of conditions and the following disclaimer.
35 *
36 * 2. Redistributions in binary form must reproduce the above copyright
37 *    notice, this list of conditions and the following disclaimer in the
38 *    documentation and/or other materials provided with the distribution.
39 *
40 * 3. Neither the name of the Institute nor the names of its contributors
41 *    may be used to endorse or promote products derived from this software
42 *    without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57#include "ossl-config.h"
58
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62
63#include "ossl-engine.h"
64
65#ifdef HAVE_DLFCN_H
66#include <dlfcn.h>
67#ifndef RTLD_NOW
68#define RTLD_NOW    0
69#endif
70#endif
71
72#ifndef PACKAGE_VERSION
73#define PACKAGE_VERSION    "0.9.0"
74#endif
75
76struct ossl_engine {
77	int			references;
78	char *			name;
79	char *			id;
80	void			(*destroy)(ENGINE *);
81	const DSA_METHOD *	dsa;
82	const RSA_METHOD *	rsa;
83	const DH_METHOD *	dh;
84	const RAND_METHOD *	rand;
85};
86
87ENGINE *
88ENGINE_new(void)
89{
90	ENGINE *engine;
91
92	engine = calloc(1, sizeof(*engine));
93	engine->references = 1;
94
95	return (engine);
96}
97
98
99int
100ENGINE_free(ENGINE *engine)
101{
102	return (ENGINE_finish(engine));
103}
104
105
106int
107ENGINE_finish(ENGINE *engine)
108{
109	if (engine->references-- <= 0) {
110		abort();
111	}
112	if (engine->references > 0) {
113		return (1);
114	}
115
116	if (engine->name) {
117		free(engine->name);
118	}
119	if (engine->id) {
120		free(engine->id);
121	}
122	if (engine->destroy) {
123		(*engine->destroy)(engine);
124	}
125
126	memset(engine, 0, sizeof(*engine));
127	engine->references = -1;
128
129
130	free(engine);
131	return (1);
132}
133
134
135int
136ENGINE_up_ref(ENGINE *engine)
137{
138	if (engine->references < 0) {
139		abort();
140	}
141	engine->references++;	/* XXX atomic op */
142	return (1);
143}
144
145
146int
147ENGINE_set_id(ENGINE *engine, const char *id)
148{
149	engine->id = strdup(id);
150	return ((engine->id == NULL) ? 0 : 1);
151}
152
153
154int
155ENGINE_set_name(ENGINE *engine, const char *name)
156{
157	engine->name = strdup(name);
158	return ((engine->name == NULL) ? 0 : 1);
159}
160
161
162int
163ENGINE_set_DSA(ENGINE *engine, const DSA_METHOD *method)
164{
165	engine->dsa = method;
166	return (1);
167}
168
169
170int
171ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method)
172{
173	engine->rsa = method;
174	return (1);
175}
176
177
178int
179ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method)
180{
181	engine->dh = method;
182	return (1);
183}
184
185
186int
187ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *))
188{
189	e->destroy = destroy;
190	return (1);
191}
192
193
194const char *
195ENGINE_get_id(const ENGINE *engine)
196{
197	return (engine->id);
198}
199
200
201const char *
202ENGINE_get_name(const ENGINE *engine)
203{
204	return (engine->name);
205}
206
207
208const DSA_METHOD *
209ENGINE_get_DSA(const ENGINE *engine)
210{
211	return (engine->dsa);
212}
213
214
215const RSA_METHOD *
216ENGINE_get_RSA(const ENGINE *engine)
217{
218	return (engine->rsa);
219}
220
221
222const DH_METHOD *
223ENGINE_get_DH(const ENGINE *engine)
224{
225	return (engine->dh);
226}
227
228
229const RAND_METHOD *
230ENGINE_get_RAND(const ENGINE *engine)
231{
232	return (engine->rand);
233}
234
235
236/*
237 *
238 */
239
240#define SG_default_engine(type)				  \
241	static ENGINE *type ## _engine;			  \
242	int						  \
243	    ENGINE_set_default_ ## type(ENGINE *engine)	  \
244	{						  \
245		if (type ## _engine) {			  \
246			ENGINE_finish(type ## _engine); } \
247		type ## _engine = engine;		  \
248		if (type ## _engine) {			  \
249			ENGINE_up_ref(type ## _engine); } \
250		return 1;				  \
251	}						  \
252	ENGINE *					  \
253	ENGINE_get_default_ ## type(void)		  \
254	{						  \
255		if (type ## _engine) {			  \
256			ENGINE_up_ref(type ## _engine); } \
257		return type ## _engine;			  \
258	}
259
260SG_default_engine(DSA)
261SG_default_engine(RSA)
262SG_default_engine(DH)
263
264#undef SG_default_engine
265
266/*
267 *
268 */
269
270static ENGINE **engines;
271static unsigned int num_engines;
272
273static int
274add_engine(ENGINE *engine)
275{
276	ENGINE **d, *dup;
277
278	dup = ENGINE_by_id(engine->id);
279	if (dup) {
280		return (0);
281	}
282
283	d = realloc(engines, (num_engines + 1) * sizeof(*engines));
284	if (d == NULL) {
285		return (1);
286	}
287	engines = d;
288	engines[num_engines++] = engine;
289
290	return (1);
291}
292
293
294#if !defined(PR_10783242_FIXED) || !defined(PR_8174774_FIXED) || !defined(PR_10488503_FIXED) || !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED)
295const DH_METHOD *DH_eay_method(void);
296const DSA_METHOD *DSA_eay_method(void);
297const RSA_METHOD *RSA_eay_method(void);
298
299#endif
300
301void
302ENGINE_load_builtin_engines(void)
303{
304	ENGINE *engine;
305	int ret;
306
307	engine = ENGINE_new();
308	if (engine == NULL) {
309		return;
310	}
311
312	ENGINE_set_id(engine, "builtin");
313	ENGINE_set_name(engine,
314	    "cryptoshims builtin engine version " PACKAGE_VERSION);
315
316/*
317 *  XXX <radr://problem/107832242> and <rda://problem/8174874> are
318 *  blocking the use of CommonCrypto's RSA code for OpenSSH.
319 *
320 *  XXX <rdar://problem/10488503> is blocking the use of
321 *  CommonCrypto's (non-existing) DSA.
322 *
323 *  XXX <rdar://problem/10771223> and <rdar://problem/10771188> are
324 *  blocking the use of CommonCrypto's DH code.
325 */
326#if !defined(PR_10783242_FIXED) || !defined(PR_8174774_FIXED) || !defined(PR_10488503_FIXED) || !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED)
327	ENGINE_set_DH(engine, DH_eay_method());
328	ENGINE_set_DSA(engine, DSA_eay_method());
329	ENGINE_set_RSA(engine, RSA_eay_method());
330#elif defined(HAVE_COMMONCRYPTO_COMMONRSACRYPTOR_H) && defined(HAVE_COMMONCRYPTO_COMMONDH_H) && defined(HAVE_COMMONCRYPTO_COMMONDSACRYPTOR_H)
331	ENGINE_set_DH(engine, DH_eay_method());
332	ENGINE_set_DSA(engine, DSA_eay_method());
333	ENGINE_set_RSA(engine, RSA_cc_method());
334#elif HAVE_CDSA
335	ENGINE_set_DH(engine, DH_cdsa_method());
336	ENGINE_set_DSA(engine, DSA_null_method());
337	ENGINE_set_RSA(engine, RSA_cdsa_method());
338#elif defined(__APPLE_TARGET_EMBEDDED__)
339	ENGINE_set_DH(engine, DH_null_method());
340	ENGINE_set_DSA(engine, DSA_null_method());
341	ENGINE_set_RSA(engine, RSA_null_method());
342#elif defined(HEIM_HC_SF)
343	ENGINE_set_RSA(engine, RSA_ltm_method());
344	ENGINE_set_DH(engine, DH_sf_method());
345	ENGINE_set_DSA(engine, DSA_null_method());
346#elif defined(HEIM_HC_LTM)
347	ENGINE_set_RSA(engine, RSA_ltm_method());
348	ENGINE_set_DH(engine, DH_ltm_method());
349	ENGINE_set_DSA(engine, DSA_null_method());
350#else
351	ENGINE_set_RSA(engine, RSA_tfm_method());
352	ENGINE_set_DH(engine, DH_tfm_method());
353	ENGINE_set_DSA(engine, DSA_null_method());
354#endif
355
356	ret = add_engine(engine);
357	if (ret != 1) {
358		ENGINE_finish(engine);
359	}
360
361#if !defined(PR_10783242_FIXED) || !defined(PR_8174774_FIXED) || !defined(PR_1048850_FIXED) || !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED)
362
363	/*
364	 * EAY
365	 */
366	engine = ENGINE_new();
367	if (engine == NULL) {
368		return;
369	}
370
371	ENGINE_set_id(engine, "eay");
372	ENGINE_set_name(engine,
373	    "ossl eay engine version " PACKAGE_VERSION);
374	ENGINE_set_RSA(engine, RSA_eay_method());
375	ENGINE_set_DH(engine, DH_eay_method());
376	ENGINE_set_DSA(engine, DSA_eay_method());
377
378	ret = add_engine(engine);
379	if (ret != 1) {
380		ENGINE_finish(engine);
381	}
382#endif
383
384#if defined(HAVE_COMMONCRYPTO_COMMONRSACRYPTOR_H) && defined(HAVE_COMMONCRYPTO_COMMONDH_H) && defined(HAVE_COMMONCRYPTO_COMMONDSACRYPTOR_H)
385
386	/*
387	 * CC
388	 */
389	engine = ENGINE_new();
390	if (engine == NULL) {
391		return;
392	}
393
394	ENGINE_set_id(engine, "cc");
395	ENGINE_set_name(engine,
396	    "ossl cc engine version " PACKAGE_VERSION);
397	ENGINE_set_RSA(engine, RSA_cc_method());
398	ENGINE_set_DH(engine, DH_cc_method());
399	ENGINE_set_DSA(engine, DSA_eay_method());
400
401	ret = add_engine(engine);
402	if (ret != 1) {
403		ENGINE_finish(engine);
404	}
405#endif  /* COMMONCRYPTO */
406
407#ifdef USE_HCRYPTO_TFM
408
409	/*
410	 * TFM
411	 */
412
413	engine = ENGINE_new();
414	if (engine == NULL) {
415		return;
416	}
417
418	ENGINE_set_id(engine, "tfm");
419	ENGINE_set_name(engine,
420	    "ossl tfm engine version " PACKAGE_VERSION);
421	ENGINE_set_RSA(engine, RSA_tfm_method());
422	ENGINE_set_DH(engine, DH_tfm_method());
423
424	ret = add_engine(engine);
425	if (ret != 1) {
426		ENGINE_finish(engine);
427	}
428#endif  /* USE_HCRYPTO_TFM */
429
430#ifdef USE_HCRYPTO_LTM
431
432	/*
433	 * ltm
434	 */
435
436	engine = ENGINE_new();
437	if (engine == NULL) {
438		return;
439	}
440
441	ENGINE_set_id(engine, "ltm");
442	ENGINE_set_name(engine,
443	    "ossl ltm engine version " PACKAGE_VERSION);
444	ENGINE_set_RSA(engine, RSA_ltm_method());
445	ENGINE_set_DH(engine, DH_ltm_method());
446
447	ret = add_engine(engine);
448	if (ret != 1) {
449		ENGINE_finish(engine);
450	}
451#endif
452
453#ifdef HAVE_GMP
454
455	/*
456	 * gmp
457	 */
458
459	engine = ENGINE_new();
460	if (engine == NULL) {
461		return;
462	}
463
464	ENGINE_set_id(engine, "gmp");
465	ENGINE_set_name(engine,
466	    "ossl gmp engine version " PACKAGE_VERSION);
467	ENGINE_set_RSA(engine, RSA_gmp_method());
468
469	ret = add_engine(engine);
470	if (ret != 1) {
471		ENGINE_finish(engine);
472	}
473#endif
474}
475
476
477ENGINE *
478ENGINE_by_dso(const char *path, const char *id)
479{
480#ifdef HAVE_DLOPEN
481	ENGINE *engine;
482	void *handle;
483	int ret;
484
485	engine = calloc(1, sizeof(*engine));
486	if (engine == NULL) {
487		return (NULL);
488	}
489
490	handle = dlopen(path, RTLD_NOW);
491	if (handle == NULL) {
492		/* printf("error: %s\n", dlerror()); */
493		free(engine);
494		return (NULL);
495	}
496
497	{
498		unsigned long version;
499		openssl_v_check v_check;
500
501		v_check = (openssl_v_check)dlsym(handle, "v_check");
502		if (v_check == NULL) {
503			dlclose(handle);
504			free(engine);
505			return (NULL);
506		}
507
508		version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
509		if (version == 0) {
510			dlclose(handle);
511			free(engine);
512			return (NULL);
513		}
514	}
515
516	{
517		openssl_bind_engine bind_engine;
518
519		bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine");
520		if (bind_engine == NULL) {
521			dlclose(handle);
522			free(engine);
523			return (NULL);
524		}
525
526		ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */
527		if (ret != 1) {
528			dlclose(handle);
529			free(engine);
530			return (NULL);
531		}
532	}
533
534	ENGINE_up_ref(engine);
535
536	ret = add_engine(engine);
537	if (ret != 1) {
538		dlclose(handle);
539		ENGINE_finish(engine);
540		return (NULL);
541	}
542
543	return (engine);
544
545#else
546	return (NULL);
547#endif
548}
549
550
551ENGINE *
552ENGINE_by_id(const char *id)
553{
554	int i;
555
556	for (i = 0; i < num_engines; i++) {
557		if (strcmp(id, engines[i]->id) == 0) {
558			ENGINE_up_ref(engines[i]);
559			return (engines[i]);
560		}
561	}
562	return (NULL);
563}
564
565
566void
567ENGINE_add_conf_module(void)
568{
569}
570