OLD | NEW |
| (Empty) |
1 /* crypto/engine/eng_openssl.c */ | |
2 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL | |
3 * project 2000. | |
4 */ | |
5 /* ==================================================================== | |
6 * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. | |
7 * | |
8 * Redistribution and use in source and binary forms, with or without | |
9 * modification, are permitted provided that the following conditions | |
10 * are met: | |
11 * | |
12 * 1. Redistributions of source code must retain the above copyright | |
13 * notice, this list of conditions and the following disclaimer. | |
14 * | |
15 * 2. Redistributions in binary form must reproduce the above copyright | |
16 * notice, this list of conditions and the following disclaimer in | |
17 * the documentation and/or other materials provided with the | |
18 * distribution. | |
19 * | |
20 * 3. All advertising materials mentioning features or use of this | |
21 * software must display the following acknowledgment: | |
22 * "This product includes software developed by the OpenSSL Project | |
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 * | |
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 * endorse or promote products derived from this software without | |
27 * prior written permission. For written permission, please contact | |
28 * licensing@OpenSSL.org. | |
29 * | |
30 * 5. Products derived from this software may not be called "OpenSSL" | |
31 * nor may "OpenSSL" appear in their names without prior written | |
32 * permission of the OpenSSL Project. | |
33 * | |
34 * 6. Redistributions of any form whatsoever must retain the following | |
35 * acknowledgment: | |
36 * "This product includes software developed by the OpenSSL Project | |
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 * | |
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 * ==================================================================== | |
52 * | |
53 * This product includes cryptographic software written by Eric Young | |
54 * (eay@cryptsoft.com). This product includes software written by Tim | |
55 * Hudson (tjh@cryptsoft.com). | |
56 * | |
57 */ | |
58 /* ==================================================================== | |
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | |
60 * ECDH support in OpenSSL originally developed by | |
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. | |
62 */ | |
63 | |
64 | |
65 #include <stdio.h> | |
66 #include <openssl/crypto.h> | |
67 #include "cryptlib.h" | |
68 #include <openssl/engine.h> | |
69 #include <openssl/dso.h> | |
70 #include <openssl/pem.h> | |
71 #include <openssl/evp.h> | |
72 #include <openssl/rand.h> | |
73 #ifndef OPENSSL_NO_RSA | |
74 #include <openssl/rsa.h> | |
75 #endif | |
76 #ifndef OPENSSL_NO_DSA | |
77 #include <openssl/dsa.h> | |
78 #endif | |
79 #ifndef OPENSSL_NO_DH | |
80 #include <openssl/dh.h> | |
81 #endif | |
82 | |
83 /* This testing gunk is implemented (and explained) lower down. It also assumes | |
84 * the application explicitly calls "ENGINE_load_openssl()" because this is no | |
85 * longer automatic in ENGINE_load_builtin_engines(). */ | |
86 #define TEST_ENG_OPENSSL_RC4 | |
87 #define TEST_ENG_OPENSSL_PKEY | |
88 /* #define TEST_ENG_OPENSSL_RC4_OTHERS */ | |
89 #define TEST_ENG_OPENSSL_RC4_P_INIT | |
90 /* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */ | |
91 #define TEST_ENG_OPENSSL_SHA | |
92 /* #define TEST_ENG_OPENSSL_SHA_OTHERS */ | |
93 /* #define TEST_ENG_OPENSSL_SHA_P_INIT */ | |
94 /* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */ | |
95 /* #define TEST_ENG_OPENSSL_SHA_P_FINAL */ | |
96 | |
97 /* Now check what of those algorithms are actually enabled */ | |
98 #ifdef OPENSSL_NO_RC4 | |
99 #undef TEST_ENG_OPENSSL_RC4 | |
100 #undef TEST_ENG_OPENSSL_RC4_OTHERS | |
101 #undef TEST_ENG_OPENSSL_RC4_P_INIT | |
102 #undef TEST_ENG_OPENSSL_RC4_P_CIPHER | |
103 #endif | |
104 #if defined(OPENSSL_NO_SHA) || defined(OPENSSL_NO_SHA0) || defined(OPENSSL_NO_SH
A1) | |
105 #undef TEST_ENG_OPENSSL_SHA | |
106 #undef TEST_ENG_OPENSSL_SHA_OTHERS | |
107 #undef TEST_ENG_OPENSSL_SHA_P_INIT | |
108 #undef TEST_ENG_OPENSSL_SHA_P_UPDATE | |
109 #undef TEST_ENG_OPENSSL_SHA_P_FINAL | |
110 #endif | |
111 | |
112 #ifdef TEST_ENG_OPENSSL_RC4 | |
113 static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, | |
114 const int **nids, int nid); | |
115 #endif | |
116 #ifdef TEST_ENG_OPENSSL_SHA | |
117 static int openssl_digests(ENGINE *e, const EVP_MD **digest, | |
118 const int **nids, int nid); | |
119 #endif | |
120 | |
121 #ifdef TEST_ENG_OPENSSL_PKEY | |
122 static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, | |
123 UI_METHOD *ui_method, void *callback_data); | |
124 #endif | |
125 | |
126 /* The constants used when creating the ENGINE */ | |
127 static const char *engine_openssl_id = "openssl"; | |
128 static const char *engine_openssl_name = "Software engine support"; | |
129 | |
130 /* This internal function is used by ENGINE_openssl() and possibly by the | |
131 * "dynamic" ENGINE support too */ | |
132 static int bind_helper(ENGINE *e) | |
133 { | |
134 if(!ENGINE_set_id(e, engine_openssl_id) | |
135 || !ENGINE_set_name(e, engine_openssl_name) | |
136 #ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS | |
137 #ifndef OPENSSL_NO_RSA | |
138 || !ENGINE_set_RSA(e, RSA_get_default_method()) | |
139 #endif | |
140 #ifndef OPENSSL_NO_DSA | |
141 || !ENGINE_set_DSA(e, DSA_get_default_method()) | |
142 #endif | |
143 #ifndef OPENSSL_NO_ECDH | |
144 || !ENGINE_set_ECDH(e, ECDH_OpenSSL()) | |
145 #endif | |
146 #ifndef OPENSSL_NO_ECDSA | |
147 || !ENGINE_set_ECDSA(e, ECDSA_OpenSSL()) | |
148 #endif | |
149 #ifndef OPENSSL_NO_DH | |
150 || !ENGINE_set_DH(e, DH_get_default_method()) | |
151 #endif | |
152 || !ENGINE_set_RAND(e, RAND_SSLeay()) | |
153 #ifdef TEST_ENG_OPENSSL_RC4 | |
154 || !ENGINE_set_ciphers(e, openssl_ciphers) | |
155 #endif | |
156 #ifdef TEST_ENG_OPENSSL_SHA | |
157 || !ENGINE_set_digests(e, openssl_digests) | |
158 #endif | |
159 #endif | |
160 #ifdef TEST_ENG_OPENSSL_PKEY | |
161 || !ENGINE_set_load_privkey_function(e, openssl_load_pri
vkey) | |
162 #endif | |
163 ) | |
164 return 0; | |
165 /* If we add errors to this ENGINE, ensure the error handling is setup h
ere */ | |
166 /* openssl_load_error_strings(); */ | |
167 return 1; | |
168 } | |
169 | |
170 static ENGINE *engine_openssl(void) | |
171 { | |
172 ENGINE *ret = ENGINE_new(); | |
173 if(!ret) | |
174 return NULL; | |
175 if(!bind_helper(ret)) | |
176 { | |
177 ENGINE_free(ret); | |
178 return NULL; | |
179 } | |
180 return ret; | |
181 } | |
182 | |
183 void ENGINE_load_openssl(void) | |
184 { | |
185 ENGINE *toadd = engine_openssl(); | |
186 if(!toadd) return; | |
187 ENGINE_add(toadd); | |
188 /* If the "add" worked, it gets a structural reference. So either way, | |
189 * we release our just-created reference. */ | |
190 ENGINE_free(toadd); | |
191 ERR_clear_error(); | |
192 } | |
193 | |
194 /* This stuff is needed if this ENGINE is being compiled into a self-contained | |
195 * shared-library. */ | |
196 #ifdef ENGINE_DYNAMIC_SUPPORT | |
197 static int bind_fn(ENGINE *e, const char *id) | |
198 { | |
199 if(id && (strcmp(id, engine_openssl_id) != 0)) | |
200 return 0; | |
201 if(!bind_helper(e)) | |
202 return 0; | |
203 return 1; | |
204 } | |
205 IMPLEMENT_DYNAMIC_CHECK_FN() | |
206 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) | |
207 #endif /* ENGINE_DYNAMIC_SUPPORT */ | |
208 | |
209 #ifdef TEST_ENG_OPENSSL_RC4 | |
210 /* This section of code compiles an "alternative implementation" of two modes of | |
211 * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4" | |
212 * should under normal circumstances go via this support rather than the default | |
213 * EVP support. There are other symbols to tweak the testing; | |
214 * TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time | |
215 * we're asked for a cipher we don't support (should not happen). | |
216 * TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time | |
217 * the "init_key" handler is called. | |
218 * TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler. | |
219 */ | |
220 #include <openssl/rc4.h> | |
221 #define TEST_RC4_KEY_SIZE 16 | |
222 static int test_cipher_nids[] = {NID_rc4,NID_rc4_40}; | |
223 static int test_cipher_nids_number = 2; | |
224 typedef struct { | |
225 unsigned char key[TEST_RC4_KEY_SIZE]; | |
226 RC4_KEY ks; | |
227 } TEST_RC4_KEY; | |
228 #define test(ctx) ((TEST_RC4_KEY *)(ctx)->cipher_data) | |
229 static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | |
230 const unsigned char *iv, int enc) | |
231 { | |
232 #ifdef TEST_ENG_OPENSSL_RC4_P_INIT | |
233 fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n"); | |
234 #endif | |
235 memcpy(&test(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx)); | |
236 RC4_set_key(&test(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx), | |
237 test(ctx)->key); | |
238 return 1; | |
239 } | |
240 static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
241 const unsigned char *in, size_t inl) | |
242 { | |
243 #ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER | |
244 fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n"); | |
245 #endif | |
246 RC4(&test(ctx)->ks,inl,in,out); | |
247 return 1; | |
248 } | |
249 static const EVP_CIPHER test_r4_cipher= | |
250 { | |
251 NID_rc4, | |
252 1,TEST_RC4_KEY_SIZE,0, | |
253 EVP_CIPH_VARIABLE_LENGTH, | |
254 test_rc4_init_key, | |
255 test_rc4_cipher, | |
256 NULL, | |
257 sizeof(TEST_RC4_KEY), | |
258 NULL, | |
259 NULL, | |
260 NULL, | |
261 NULL | |
262 }; | |
263 static const EVP_CIPHER test_r4_40_cipher= | |
264 { | |
265 NID_rc4_40, | |
266 1,5 /* 40 bit */,0, | |
267 EVP_CIPH_VARIABLE_LENGTH, | |
268 test_rc4_init_key, | |
269 test_rc4_cipher, | |
270 NULL, | |
271 sizeof(TEST_RC4_KEY), | |
272 NULL, | |
273 NULL, | |
274 NULL, | |
275 NULL | |
276 }; | |
277 static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, | |
278 const int **nids, int nid) | |
279 { | |
280 if(!cipher) | |
281 { | |
282 /* We are returning a list of supported nids */ | |
283 *nids = test_cipher_nids; | |
284 return test_cipher_nids_number; | |
285 } | |
286 /* We are being asked for a specific cipher */ | |
287 if(nid == NID_rc4) | |
288 *cipher = &test_r4_cipher; | |
289 else if(nid == NID_rc4_40) | |
290 *cipher = &test_r4_40_cipher; | |
291 else | |
292 { | |
293 #ifdef TEST_ENG_OPENSSL_RC4_OTHERS | |
294 fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for " | |
295 "nid %d\n", nid); | |
296 #endif | |
297 *cipher = NULL; | |
298 return 0; | |
299 } | |
300 return 1; | |
301 } | |
302 #endif | |
303 | |
304 #ifdef TEST_ENG_OPENSSL_SHA | |
305 /* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */ | |
306 #include <openssl/sha.h> | |
307 static int test_digest_nids[] = {NID_sha1}; | |
308 static int test_digest_nids_number = 1; | |
309 static int test_sha1_init(EVP_MD_CTX *ctx) | |
310 { | |
311 #ifdef TEST_ENG_OPENSSL_SHA_P_INIT | |
312 fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n"); | |
313 #endif | |
314 return SHA1_Init(ctx->md_data); | |
315 } | |
316 static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,size_t count) | |
317 { | |
318 #ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE | |
319 fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n"); | |
320 #endif | |
321 return SHA1_Update(ctx->md_data,data,count); | |
322 } | |
323 static int test_sha1_final(EVP_MD_CTX *ctx,unsigned char *md) | |
324 { | |
325 #ifdef TEST_ENG_OPENSSL_SHA_P_FINAL | |
326 fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n"); | |
327 #endif | |
328 return SHA1_Final(md,ctx->md_data); | |
329 } | |
330 static const EVP_MD test_sha_md= | |
331 { | |
332 NID_sha1, | |
333 NID_sha1WithRSAEncryption, | |
334 SHA_DIGEST_LENGTH, | |
335 0, | |
336 test_sha1_init, | |
337 test_sha1_update, | |
338 test_sha1_final, | |
339 NULL, | |
340 NULL, | |
341 EVP_PKEY_RSA_method, | |
342 SHA_CBLOCK, | |
343 sizeof(EVP_MD *)+sizeof(SHA_CTX), | |
344 }; | |
345 static int openssl_digests(ENGINE *e, const EVP_MD **digest, | |
346 const int **nids, int nid) | |
347 { | |
348 if(!digest) | |
349 { | |
350 /* We are returning a list of supported nids */ | |
351 *nids = test_digest_nids; | |
352 return test_digest_nids_number; | |
353 } | |
354 /* We are being asked for a specific digest */ | |
355 if(nid == NID_sha1) | |
356 *digest = &test_sha_md; | |
357 else | |
358 { | |
359 #ifdef TEST_ENG_OPENSSL_SHA_OTHERS | |
360 fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for " | |
361 "nid %d\n", nid); | |
362 #endif | |
363 *digest = NULL; | |
364 return 0; | |
365 } | |
366 return 1; | |
367 } | |
368 #endif | |
369 | |
370 #ifdef TEST_ENG_OPENSSL_PKEY | |
371 static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, | |
372 UI_METHOD *ui_method, void *callback_data) | |
373 { | |
374 BIO *in; | |
375 EVP_PKEY *key; | |
376 fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", key_i
d); | |
377 in = BIO_new_file(key_id, "r"); | |
378 if (!in) | |
379 return NULL; | |
380 key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL); | |
381 BIO_free(in); | |
382 return key; | |
383 } | |
384 #endif | |
OLD | NEW |