summaryrefslogtreecommitdiffstats
path: root/crypto/evp/evp_enc.c
diff options
context:
space:
mode:
authorGeoff Thorpe <geoff@openssl.org>2001-09-25 21:37:02 +0000
committerGeoff Thorpe <geoff@openssl.org>2001-09-25 21:37:02 +0000
commit11a57c7be519b8977cc345db1b51a3e596faaec4 (patch)
tree3d0eb9743f122e1dd061d989b911abfe1a0694ed /crypto/evp/evp_enc.c
parentb370230b786eed9b73c9a1f5c0a5e008e8009989 (diff)
This changes EVP's cipher and digest code to hook via the ENGINE support.
See crypto/engine/README for details. - it also removes openbsd_hw.c from the build (that functionality is going to be available in the openbsd ENGINE in a upcoming commit) - evp_test has had the extra initialisation added so it will use (if possible) any ENGINEs supporting the algorithms required.
Diffstat (limited to 'crypto/evp/evp_enc.c')
-rw-r--r--crypto/evp/evp_enc.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 83b70129ca..ff7f7705a4 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -60,6 +60,7 @@
#include "cryptlib.h"
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/engine.h>
#include "evp_locl.h"
#include <assert.h>
@@ -75,24 +76,70 @@ void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv, int enc)
{
+ return EVP_CipherInit_ex(ctx,cipher,NULL,key,iv,enc);
+ }
+int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
+ const unsigned char *key, const unsigned char *iv, int enc)
+ {
if(enc && (enc != -1)) enc = 1;
+ /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
+ * so this context may already have an ENGINE! Try to avoid releasing
+ * the previous handle, re-querying for an ENGINE, and having a
+ * reinitialisation, when it may all be unecessary. */
+ if (ctx->engine && ctx->cipher && (!cipher ||
+ (cipher && (cipher->nid == ctx->cipher->nid))))
+ goto skip_to_init;
if (cipher)
{
+ /* Ensure an ENGINE left lying around from last time is cleared
+ * (the previous check attempted to avoid this if the same
+ * ENGINE and EVP_CIPHER could be used). */
+ if(ctx->engine)
+ ENGINE_finish(ctx->engine);
+ if(!impl)
+ /* Ask if an ENGINE is reserved for this job */
+ impl = ENGINE_get_cipher_engine(cipher->nid);
+ if(impl)
+ {
+ /* There's an ENGINE for this job ... (apparently) */
+ const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
+ if(!c)
+ {
+ /* One positive side-effect of US's export
+ * control history, is that we should at least
+ * be able to avoid using US mispellings of
+ * "initialisation"? */
+ EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
+ return 0;
+ }
+ /* We'll use the ENGINE's private cipher definition */
+ cipher = c;
+ /* Store the ENGINE functional reference so we know
+ * 'cipher' came from an ENGINE and we need to release
+ * it when done. */
+ ctx->engine = impl;
+ }
+ else
+ ctx->engine = NULL;
ctx->cipher=cipher;
ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size);
ctx->key_len = cipher->key_len;
ctx->flags = 0;
- if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
+ if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT)
+ {
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL))
+ {
EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
return 0;
+ }
}
}
- } else if(!ctx->cipher) {
+ else if(!ctx->cipher)
+ {
EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_NO_CIPHER_SET);
return 0;
- }
-
+ }
+skip_to_init:
/* we assume block size is a power of 2 in *cryptUpdate */
assert(ctx->cipher->block_size == 1
|| ctx->cipher->block_size == 8
@@ -144,7 +191,7 @@ int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
if (ctx->encrypt)
return EVP_EncryptFinal(ctx,out,outl);
- else return(EVP_DecryptFinal(ctx,out,outl));
+ else return EVP_DecryptFinal(ctx,out,outl);
}
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
@@ -355,6 +402,10 @@ int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
if(!c->cipher->cleanup(c)) return 0;
}
OPENSSL_free(c->cipher_data);
+ if (c->engine)
+ /* The EVP_CIPHER we used belongs to an ENGINE, release the
+ * functional reference we held for this reason. */
+ ENGINE_finish(c->engine);
memset(c,0,sizeof(EVP_CIPHER_CTX));
return 1;
}