X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fengine%2Feng_openssl.c;h=d3e4cacefbdc0180b7626b5db7f5edfb839b4ed3;hp=c353df97d697eb488e4bc63ac325522d218da74b;hb=004aa803a96dbb6155267dbd85aecc5c5660229c;hpb=14cfde9c83ecfb36711930171ce129293463a83f diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c index c353df97d6..d3e4cacefb 100644 --- a/crypto/engine/eng_openssl.c +++ b/crypto/engine/eng_openssl.c @@ -1,9 +1,9 @@ -/* crypto/engine/engine_openssl.c */ +/* crypto/engine/eng_openssl.c */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -63,38 +63,56 @@ #include #include -/* This is the only function we need to implement as OpenSSL - * doesn't have a native CRT mod_exp. Perhaps this should be - * BN_mod_exp_crt and moved into crypto/bn/ ?? ... dunno. */ -static int openssl_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, - const BIGNUM *iqmp, BN_CTX *ctx); +/* This testing gunk is implemented (and explained) lower down. It also assumes + * the application explicitly calls "ENGINE_load_openssl()" because this is no + * longer automatic in ENGINE_load_builtin_engines(). */ +#define TEST_ENG_OPENSSL_RC4 +/* #define TEST_ENG_OPENSSL_RC4_OTHERS */ +#define TEST_ENG_OPENSSL_RC4_P_INIT +/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */ +#define TEST_ENG_OPENSSL_SHA +/* #define TEST_ENG_OPENSSL_SHA_OTHERS */ +/* #define TEST_ENG_OPENSSL_SHA_P_INIT */ +/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */ +/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */ + +#ifdef TEST_ENG_OPENSSL_RC4 +static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +#endif +#ifdef TEST_ENG_OPENSSL_SHA +static int openssl_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +#endif /* The constants used when creating the ENGINE */ static const char *engine_openssl_id = "openssl"; -static const char *engine_openssl_name = "Software default engine support"; +static const char *engine_openssl_name = "Software engine support"; -/* As this is only ever called once, there's no need for locking - * (indeed - the lock will already be held by our caller!!!) */ -ENGINE *ENGINE_openssl(void) +static ENGINE *engine_openssl(void) { ENGINE *ret = ENGINE_new(); if(!ret) return NULL; - if(!ENGINE_set_id(ret, engine_openssl_id) || - !ENGINE_set_name(ret, engine_openssl_name) || + if(!ENGINE_set_id(ret, engine_openssl_id) + || !ENGINE_set_name(ret, engine_openssl_name) #ifndef OPENSSL_NO_RSA - !ENGINE_set_RSA(ret, RSA_get_default_openssl_method()) || + || !ENGINE_set_RSA(ret, RSA_get_default_method()) #endif #ifndef OPENSSL_NO_DSA - !ENGINE_set_DSA(ret, DSA_get_default_openssl_method()) || + || !ENGINE_set_DSA(ret, DSA_get_default_method()) #endif #ifndef OPENSSL_NO_DH - !ENGINE_set_DH(ret, DH_get_default_openssl_method()) || + || !ENGINE_set_DH(ret, DH_get_default_method()) #endif - !ENGINE_set_RAND(ret, RAND_SSLeay()) || - !ENGINE_set_BN_mod_exp(ret, BN_mod_exp) || - !ENGINE_set_BN_mod_exp_crt(ret, openssl_mod_exp_crt)) + || !ENGINE_set_RAND(ret, RAND_SSLeay()) +#ifdef TEST_ENG_OPENSSL_RC4 + || !ENGINE_set_ciphers(ret, openssl_ciphers) +#endif +#ifdef TEST_ENG_OPENSSL_SHA + || !ENGINE_set_digests(ret, openssl_digests) +#endif + ) { ENGINE_free(ret); return NULL; @@ -102,64 +120,174 @@ ENGINE *ENGINE_openssl(void) return ret; } -/* Chinese Remainder Theorem, taken and adapted from rsa_eay.c */ -static int openssl_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *q, const BIGNUM *dmp1, - const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx) +void ENGINE_load_openssl(void) { - BIGNUM r1,m1; - int ret=0; - BN_CTX *bn_ctx; - BIGNUM *temp_bn = NULL; + ENGINE *toadd = engine_openssl(); + if(!toadd) return; + ENGINE_add(toadd); + /* If the "add" worked, it gets a structural reference. So either way, + * we release our just-created reference. */ + ENGINE_free(toadd); + ERR_clear_error(); + } - if (ctx) - bn_ctx = ctx; +#ifdef TEST_ENG_OPENSSL_RC4 +/* This section of code compiles an "alternative implementation" of two modes of + * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4" + * should under normal circumstances go via this support rather than the default + * EVP support. There are other symbols to tweak the testing; + * TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time + * we're asked for a cipher we don't support (should not happen). + * TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time + * the "init_key" handler is called. + * TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler. + */ +#include +#include +#define TEST_RC4_KEY_SIZE 16 +static int test_cipher_nids[] = {NID_rc4,NID_rc4_40}; +static int test_cipher_nids_number = 2; +typedef struct { + unsigned char key[TEST_RC4_KEY_SIZE]; + RC4_KEY ks; + } TEST_RC4_KEY; +#define test(ctx) ((TEST_RC4_KEY *)(ctx)->cipher_data) +static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { +#ifdef TEST_ENG_OPENSSL_RC4_P_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n"); +#endif + memcpy(&test(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx)); + RC4_set_key(&test(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx), + test(ctx)->key); + return 1; + } +static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) + { +#ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n"); +#endif + RC4(&test(ctx)->ks,inl,in,out); + return 1; + } +static const EVP_CIPHER test_r4_cipher= + { + NID_rc4, + 1,TEST_RC4_KEY_SIZE,0, + EVP_CIPH_VARIABLE_LENGTH, + test_rc4_init_key, + test_rc4_cipher, + NULL, + sizeof(TEST_RC4_KEY), + NULL, + NULL, + NULL + }; +static const EVP_CIPHER test_r4_40_cipher= + { + NID_rc4_40, + 1,5 /* 40 bit */,0, + EVP_CIPH_VARIABLE_LENGTH, + test_rc4_init_key, + test_rc4_cipher, + NULL, + sizeof(TEST_RC4_KEY), + NULL, + NULL, + NULL + }; +static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if(!cipher) + { + /* We are returning a list of supported nids */ + *nids = test_cipher_nids; + return test_cipher_nids_number; + } + /* We are being asked for a specific cipher */ + if(nid == NID_rc4) + *cipher = &test_r4_cipher; + else if(nid == NID_rc4_40) + *cipher = &test_r4_40_cipher; else - if ((bn_ctx=BN_CTX_new()) == NULL) goto err; - BN_init(&m1); - BN_init(&r1); - /* BN_mul() cannot accept const BIGNUMs so I use the BN_CTX - * to duplicate what I need. */ - BN_CTX_start(bn_ctx); - if ((temp_bn = BN_CTX_get(bn_ctx)) == NULL) goto err; - if (!BN_copy(temp_bn, iqmp)) goto err; - - if (!BN_mod(&r1, a, q, bn_ctx)) goto err; - if (!BN_mod_exp(&m1, &r1, dmq1, q, bn_ctx)) - goto err; - - if (!BN_mod(&r1, a, p, bn_ctx)) goto err; - if (!BN_mod_exp(r, &r1, dmp1, p, bn_ctx)) - goto err; + { +#ifdef TEST_ENG_OPENSSL_RC4_OTHERS + fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for " + "nid %d\n", nid); +#endif + *cipher = NULL; + return 0; + } + return 1; + } +#endif - if (!BN_sub(r, r, &m1)) goto err; - /* This will help stop the size of r0 increasing, which does - * affect the multiply if it optimised for a power of 2 size */ - if (r->neg) - if (!BN_add(r, r, p)) goto err; - - if (!BN_mul(&r1, r, temp_bn, bn_ctx)) goto err; - if (!BN_mod(r, &r1, p, bn_ctx)) goto err; - /* If p < q it is occasionally possible for the correction of - * adding 'p' if r is negative above to leave the result still - * negative. This can break the private key operations: the following - * second correction should *always* correct this rare occurrence. - * This will *never* happen with OpenSSL generated keys because - * they ensure p > q [steve] - */ - if (r->neg) - if (!BN_add(r, r, p)) goto err; - /* Again, BN_mul() will need non-const values. */ - if (!BN_copy(temp_bn, q)) goto err; - if (!BN_mul(&r1, r, temp_bn, bn_ctx)) goto err; - if (!BN_add(r, &r1, &m1)) goto err; - - ret=1; -err: - BN_clear_free(&m1); - BN_clear_free(&r1); - BN_CTX_end(ctx); - if (!ctx) - BN_CTX_free(bn_ctx); - return(ret); +#ifdef TEST_ENG_OPENSSL_SHA +/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */ +#include +#include +static int test_digest_nids[] = {NID_sha1}; +static int test_digest_nids_number = 1; +static int test_sha1_init(EVP_MD_CTX *ctx) + { +#ifdef TEST_ENG_OPENSSL_SHA_P_INIT + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n"); +#endif + return SHA1_Init(ctx->md_data); + } +static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,unsigned long count) + { +#ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n"); +#endif + return SHA1_Update(ctx->md_data,data,count); + } +static int test_sha1_final(EVP_MD_CTX *ctx,unsigned char *md) + { +#ifdef TEST_ENG_OPENSSL_SHA_P_FINAL + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n"); +#endif + return SHA1_Final(md,ctx->md_data); } +static const EVP_MD test_sha_md= + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + 0, + test_sha1_init, + test_sha1_update, + test_sha1_final, + NULL, + NULL, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof(EVP_MD *)+sizeof(SHA_CTX), + }; +static int openssl_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if(!digest) + { + /* We are returning a list of supported nids */ + *nids = test_digest_nids; + return test_digest_nids_number; + } + /* We are being asked for a specific digest */ + if(nid == NID_sha1) + *digest = &test_sha_md; + else + { +#ifdef TEST_ENG_OPENSSL_SHA_OTHERS + fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for " + "nid %d\n", nid); +#endif + *digest = NULL; + return 0; + } + return 1; + } +#endif