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