Merge from vendor branch ZLIB:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sec / dst / openssl_link.c
1 /*
2  * Portions Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Portions Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
11  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
13  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
16  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 /*
20  * Principal Author: Brian Wellington
21  * $Id: openssl_link.c,v 1.46.2.3 2004/03/09 06:11:41 marka Exp $
22  */
23 #ifdef OPENSSL
24
25 #include <config.h>
26
27 #include <isc/entropy.h>
28 #include <isc/mem.h>
29 #include <isc/mutex.h>
30 #include <isc/mutexblock.h>
31 #include <isc/string.h>
32 #include <isc/thread.h>
33 #include <isc/util.h>
34
35 #include "dst_internal.h"
36
37 #include <openssl/rand.h>
38 #include <openssl/crypto.h>
39
40 #if defined(CRYPTO_LOCK_ENGINE) && (OPENSSL_VERSION_NUMBER < 0x00907000L)
41 #define USE_ENGINE 1
42 #endif
43
44 #ifdef USE_ENGINE
45 #include <openssl/engine.h>
46 #endif
47
48 static RAND_METHOD *rm = NULL;
49 static isc_mutex_t *locks = NULL;
50 static int nlocks;
51
52 #ifdef USE_ENGINE
53 static ENGINE *e;
54 #endif
55
56
57 static int
58 entropy_get(unsigned char *buf, int num) {
59         isc_result_t result;
60         if (num < 0)
61                 return (-1);
62         result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
63         return (result == ISC_R_SUCCESS ? num : -1);
64 }
65
66 static int
67 entropy_getpseudo(unsigned char *buf, int num) {
68         isc_result_t result;
69         if (num < 0)
70                 return (-1);
71         result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
72         return (result == ISC_R_SUCCESS ? num : -1);
73 }
74
75 static void
76 entropy_add(const void *buf, int num, double entropy) {
77         /*
78          * Do nothing.  The only call to this provides no useful data anyway.
79          */
80         UNUSED(buf);
81         UNUSED(num);
82         UNUSED(entropy);
83 }
84
85 static void
86 lock_callback(int mode, int type, const char *file, int line) {
87         UNUSED(file);
88         UNUSED(line);
89         if ((mode & CRYPTO_LOCK) != 0)
90                 LOCK(&locks[type]);
91         else
92                 UNLOCK(&locks[type]);
93 }
94
95 static unsigned long
96 id_callback(void) {
97         return ((unsigned long)isc_thread_self());
98 }
99
100 isc_result_t
101 dst__openssl_init() {
102         isc_result_t result;
103
104         CRYPTO_set_mem_functions(dst__mem_alloc, dst__mem_realloc,
105                                  dst__mem_free);
106         nlocks = CRYPTO_num_locks();
107         locks = dst__mem_alloc(sizeof(isc_mutex_t) * nlocks);
108         if (locks == NULL)
109                 return (ISC_R_NOMEMORY);
110         result = isc_mutexblock_init(locks, nlocks);
111         if (result != ISC_R_SUCCESS)
112                 goto cleanup_mutexalloc;
113         CRYPTO_set_locking_callback(lock_callback);
114         CRYPTO_set_id_callback(id_callback);
115         rm = dst__mem_alloc(sizeof(RAND_METHOD));
116         if (rm == NULL) {
117                 result = ISC_R_NOMEMORY;
118                 goto cleanup_mutexinit;
119         }
120         rm->seed = NULL;
121         rm->bytes = entropy_get;
122         rm->cleanup = NULL;
123         rm->add = entropy_add;
124         rm->pseudorand = entropy_getpseudo;
125         rm->status = NULL;
126 #ifdef USE_ENGINE
127         e = ENGINE_new();
128         if (e == NULL) {
129                 result = ISC_R_NOMEMORY;
130                 goto cleanup_rm;
131         }
132         ENGINE_set_RAND(e, rm);
133         RAND_set_rand_method(e);
134 #else
135         RAND_set_rand_method(rm);
136 #endif
137         return (ISC_R_SUCCESS);
138
139 #ifdef USE_ENGINE
140  cleanup_rm:
141         dst__mem_free(rm);
142 #endif
143  cleanup_mutexinit:
144         RUNTIME_CHECK(isc_mutexblock_destroy(locks, nlocks) == ISC_R_SUCCESS);
145  cleanup_mutexalloc:
146         dst__mem_free(locks);
147         return (result);
148 }
149
150 void
151 dst__openssl_destroy() {
152 #ifdef USE_ENGINE
153         if (e != NULL) {
154                 ENGINE_free(e);
155                 e = NULL;
156         }
157 #endif
158         if (locks != NULL) {
159                 RUNTIME_CHECK(isc_mutexblock_destroy(locks, nlocks) ==
160                               ISC_R_SUCCESS);
161                 dst__mem_free(locks);
162         }
163         if (rm != NULL)
164                 dst__mem_free(rm);
165 }
166
167 #endif /* OPENSSL */