~ubuntu-branches/ubuntu/hardy/openssl/hardy-security

« back to all changes in this revision

Viewing changes to crypto/engine/eng_openssl.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Martin
  • Date: 2004-05-24 17:02:29 UTC
  • Revision ID: james.westby@ubuntu.com-20040524170229-ixlo08bbbly0xied
Tags: upstream-0.9.7d
ImportĀ upstreamĀ versionĀ 0.9.7d

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
60
#include <stdio.h>
 
61
#include <openssl/crypto.h>
 
62
#include "cryptlib.h"
 
63
#include <openssl/engine.h>
 
64
#include <openssl/dso.h>
 
65
#include <openssl/pem.h>
 
66
#include <openssl/evp.h>
 
67
 
 
68
/* This testing gunk is implemented (and explained) lower down. It also assumes
 
69
 * the application explicitly calls "ENGINE_load_openssl()" because this is no
 
70
 * longer automatic in ENGINE_load_builtin_engines(). */
 
71
#define TEST_ENG_OPENSSL_RC4
 
72
#define TEST_ENG_OPENSSL_PKEY
 
73
/* #define TEST_ENG_OPENSSL_RC4_OTHERS */
 
74
#define TEST_ENG_OPENSSL_RC4_P_INIT
 
75
/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */
 
76
#define TEST_ENG_OPENSSL_SHA
 
77
/* #define TEST_ENG_OPENSSL_SHA_OTHERS */
 
78
/* #define TEST_ENG_OPENSSL_SHA_P_INIT */
 
79
/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */
 
80
/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */
 
81
 
 
82
/* Now check what of those algorithms are actually enabled */
 
83
#ifdef OPENSSL_NO_RC4
 
84
#undef TEST_ENG_OPENSSL_RC4
 
85
#undef TEST_ENG_OPENSSL_RC4_OTHERS
 
86
#undef TEST_ENG_OPENSSL_RC4_P_INIT
 
87
#undef TEST_ENG_OPENSSL_RC4_P_CIPHER
 
88
#endif
 
89
#if defined(OPENSSL_NO_SHA) || defined(OPENSSL_NO_SHA0) || defined(OPENSSL_NO_SHA1)
 
90
#undef TEST_ENG_OPENSSL_SHA
 
91
#undef TEST_ENG_OPENSSL_SHA_OTHERS
 
92
#undef TEST_ENG_OPENSSL_SHA_P_INIT
 
93
#undef TEST_ENG_OPENSSL_SHA_P_UPDATE
 
94
#undef TEST_ENG_OPENSSL_SHA_P_FINAL 
 
95
#endif
 
96
 
 
97
#ifdef TEST_ENG_OPENSSL_RC4
 
98
static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
 
99
                                const int **nids, int nid);
 
100
#endif
 
101
#ifdef TEST_ENG_OPENSSL_SHA
 
102
static int openssl_digests(ENGINE *e, const EVP_MD **digest,
 
103
                                const int **nids, int nid);
 
104
#endif
 
105
 
 
106
#ifdef TEST_ENG_OPENSSL_PKEY
 
107
static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
 
108
        UI_METHOD *ui_method, void *callback_data);
 
109
#endif
 
110
 
 
111
/* The constants used when creating the ENGINE */
 
112
static const char *engine_openssl_id = "openssl";
 
113
static const char *engine_openssl_name = "Software engine support";
 
114
 
 
115
/* This internal function is used by ENGINE_openssl() and possibly by the
 
116
 * "dynamic" ENGINE support too */
 
117
static int bind_helper(ENGINE *e)
 
118
        {
 
119
        if(!ENGINE_set_id(e, engine_openssl_id)
 
120
                        || !ENGINE_set_name(e, engine_openssl_name)
 
121
#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS
 
122
#ifndef OPENSSL_NO_RSA
 
123
                        || !ENGINE_set_RSA(e, RSA_get_default_method())
 
124
#endif
 
125
#ifndef OPENSSL_NO_DSA
 
126
                        || !ENGINE_set_DSA(e, DSA_get_default_method())
 
127
#endif
 
128
#ifndef OPENSSL_NO_DH
 
129
                        || !ENGINE_set_DH(e, DH_get_default_method())
 
130
#endif
 
131
                        || !ENGINE_set_RAND(e, RAND_SSLeay())
 
132
#ifdef TEST_ENG_OPENSSL_RC4
 
133
                        || !ENGINE_set_ciphers(e, openssl_ciphers)
 
134
#endif
 
135
#ifdef TEST_ENG_OPENSSL_SHA
 
136
                        || !ENGINE_set_digests(e, openssl_digests)
 
137
#endif
 
138
#endif
 
139
#ifdef TEST_ENG_OPENSSL_PKEY
 
140
                        || !ENGINE_set_load_privkey_function(e, openssl_load_privkey)
 
141
#endif
 
142
                        )
 
143
                return 0;
 
144
        /* If we add errors to this ENGINE, ensure the error handling is setup here */
 
145
        /* openssl_load_error_strings(); */
 
146
        return 1;
 
147
        }
 
148
 
 
149
static ENGINE *engine_openssl(void)
 
150
        {
 
151
        ENGINE *ret = ENGINE_new();
 
152
        if(!ret)
 
153
                return NULL;
 
154
        if(!bind_helper(ret))
 
155
                {
 
156
                ENGINE_free(ret);
 
157
                return NULL;
 
158
                }
 
159
        return ret;
 
160
        }
 
161
 
 
162
void ENGINE_load_openssl(void)
 
163
        {
 
164
        ENGINE *toadd = engine_openssl();
 
165
        if(!toadd) return;
 
166
        ENGINE_add(toadd);
 
167
        /* If the "add" worked, it gets a structural reference. So either way,
 
168
         * we release our just-created reference. */
 
169
        ENGINE_free(toadd);
 
170
        ERR_clear_error();
 
171
        }
 
172
 
 
173
/* This stuff is needed if this ENGINE is being compiled into a self-contained
 
174
 * shared-library. */
 
175
#ifdef ENGINE_DYNAMIC_SUPPORT
 
176
static int bind_fn(ENGINE *e, const char *id)
 
177
        {
 
178
        if(id && (strcmp(id, engine_openssl_id) != 0))
 
179
                return 0;
 
180
        if(!bind_helper(e))
 
181
                return 0;
 
182
        return 1;
 
183
        }
 
184
IMPLEMENT_DYNAMIC_CHECK_FN()
 
185
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
 
186
#endif /* ENGINE_DYNAMIC_SUPPORT */
 
187
 
 
188
#ifdef TEST_ENG_OPENSSL_RC4
 
189
/* This section of code compiles an "alternative implementation" of two modes of
 
190
 * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4"
 
191
 * should under normal circumstances go via this support rather than the default
 
192
 * EVP support. There are other symbols to tweak the testing;
 
193
 *    TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time
 
194
 *        we're asked for a cipher we don't support (should not happen).
 
195
 *    TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time
 
196
 *        the "init_key" handler is called.
 
197
 *    TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler.
 
198
 */
 
199
#include <openssl/rc4.h>
 
200
#define TEST_RC4_KEY_SIZE               16
 
201
static int test_cipher_nids[] = {NID_rc4,NID_rc4_40};
 
202
static int test_cipher_nids_number = 2;
 
203
typedef struct {
 
204
        unsigned char key[TEST_RC4_KEY_SIZE];
 
205
        RC4_KEY ks;
 
206
        } TEST_RC4_KEY;
 
207
#define test(ctx) ((TEST_RC4_KEY *)(ctx)->cipher_data)
 
208
static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 
209
                        const unsigned char *iv, int enc)
 
210
        {
 
211
#ifdef TEST_ENG_OPENSSL_RC4_P_INIT
 
212
        fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n");
 
213
#endif
 
214
        memcpy(&test(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx));
 
215
        RC4_set_key(&test(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),
 
216
                test(ctx)->key);
 
217
        return 1;
 
218
        }
 
219
static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
 
220
                      const unsigned char *in, unsigned int inl)
 
221
        {
 
222
#ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER
 
223
        fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n");
 
224
#endif
 
225
        RC4(&test(ctx)->ks,inl,in,out);
 
226
        return 1;
 
227
        }
 
228
static const EVP_CIPHER test_r4_cipher=
 
229
        {
 
230
        NID_rc4,
 
231
        1,TEST_RC4_KEY_SIZE,0,
 
232
        EVP_CIPH_VARIABLE_LENGTH,
 
233
        test_rc4_init_key,
 
234
        test_rc4_cipher,
 
235
        NULL,
 
236
        sizeof(TEST_RC4_KEY),
 
237
        NULL,
 
238
        NULL,
 
239
        NULL
 
240
        };
 
241
static const EVP_CIPHER test_r4_40_cipher=
 
242
        {
 
243
        NID_rc4_40,
 
244
        1,5 /* 40 bit */,0,
 
245
        EVP_CIPH_VARIABLE_LENGTH,
 
246
        test_rc4_init_key,
 
247
        test_rc4_cipher,
 
248
        NULL,
 
249
        sizeof(TEST_RC4_KEY),
 
250
        NULL, 
 
251
        NULL,
 
252
        NULL
 
253
        };
 
254
static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
 
255
                        const int **nids, int nid)
 
256
        {
 
257
        if(!cipher)
 
258
                {
 
259
                /* We are returning a list of supported nids */
 
260
                *nids = test_cipher_nids;
 
261
                return test_cipher_nids_number;
 
262
                }
 
263
        /* We are being asked for a specific cipher */
 
264
        if(nid == NID_rc4)
 
265
                *cipher = &test_r4_cipher;
 
266
        else if(nid == NID_rc4_40)
 
267
                *cipher = &test_r4_40_cipher;
 
268
        else
 
269
                {
 
270
#ifdef TEST_ENG_OPENSSL_RC4_OTHERS
 
271
                fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for "
 
272
                                "nid %d\n", nid);
 
273
#endif
 
274
                *cipher = NULL;
 
275
                return 0;
 
276
                }
 
277
        return 1;
 
278
        }
 
279
#endif
 
280
 
 
281
#ifdef TEST_ENG_OPENSSL_SHA
 
282
/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */
 
283
#include <openssl/sha.h>
 
284
static int test_digest_nids[] = {NID_sha1};
 
285
static int test_digest_nids_number = 1;
 
286
static int test_sha1_init(EVP_MD_CTX *ctx)
 
287
        {
 
288
#ifdef TEST_ENG_OPENSSL_SHA_P_INIT
 
289
        fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n");
 
290
#endif
 
291
        return SHA1_Init(ctx->md_data);
 
292
        }
 
293
static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,unsigned long count)
 
294
        {
 
295
#ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE
 
296
        fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n");
 
297
#endif
 
298
        return SHA1_Update(ctx->md_data,data,count);
 
299
        }
 
300
static int test_sha1_final(EVP_MD_CTX *ctx,unsigned char *md)
 
301
        {
 
302
#ifdef TEST_ENG_OPENSSL_SHA_P_FINAL
 
303
        fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n");
 
304
#endif
 
305
        return SHA1_Final(md,ctx->md_data);
 
306
        }
 
307
static const EVP_MD test_sha_md=
 
308
        {
 
309
        NID_sha1,
 
310
        NID_sha1WithRSAEncryption,
 
311
        SHA_DIGEST_LENGTH,
 
312
        0,
 
313
        test_sha1_init,
 
314
        test_sha1_update,
 
315
        test_sha1_final,
 
316
        NULL,
 
317
        NULL,
 
318
        EVP_PKEY_RSA_method,
 
319
        SHA_CBLOCK,
 
320
        sizeof(EVP_MD *)+sizeof(SHA_CTX),
 
321
        };
 
322
static int openssl_digests(ENGINE *e, const EVP_MD **digest,
 
323
                        const int **nids, int nid)
 
324
        {
 
325
        if(!digest)
 
326
                {
 
327
                /* We are returning a list of supported nids */
 
328
                *nids = test_digest_nids;
 
329
                return test_digest_nids_number;
 
330
                }
 
331
        /* We are being asked for a specific digest */
 
332
        if(nid == NID_sha1)
 
333
                *digest = &test_sha_md;
 
334
        else
 
335
                {
 
336
#ifdef TEST_ENG_OPENSSL_SHA_OTHERS
 
337
                fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for "
 
338
                                "nid %d\n", nid);
 
339
#endif
 
340
                *digest = NULL;
 
341
                return 0;
 
342
                }
 
343
        return 1;
 
344
        }
 
345
#endif
 
346
 
 
347
#ifdef TEST_ENG_OPENSSL_PKEY
 
348
static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
 
349
        UI_METHOD *ui_method, void *callback_data)
 
350
        {
 
351
        BIO *in;
 
352
        EVP_PKEY *key;
 
353
        fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", key_id);
 
354
        in = BIO_new_file(key_id, "r");
 
355
        if (!in)
 
356
                return NULL;
 
357
        key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
 
358
        BIO_free(in);
 
359
        return key;
 
360
        }
 
361
#endif