Fix encrypt overflow
[openssl.git] / crypto / evp / evp_enc.c
index 111351852e278f9249d60164b0409a707c03139f..e02e801949c0eb883ad8def26f63875ec6dda2ed 100644 (file)
@@ -1,4 +1,3 @@
-/* crypto/evp/evp_enc.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  */
 
 #include <stdio.h>
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/evp.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
+#include <openssl/engine.h>
+#include "internal/evp_int.h"
 #include "evp_locl.h"
 
-const char EVP_version[] = "EVP" OPENSSL_VERSION_PTEXT;
-
-void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
+int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c)
 {
-    memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
-    /* ctx->cipher=NULL; */
+    if (c == NULL)
+        return 1;
+    if (c->cipher != NULL) {
+        if (c->cipher->cleanup && !c->cipher->cleanup(c))
+            return 0;
+        /* Cleanse cipher context data */
+        if (c->cipher_data && c->cipher->ctx_size)
+            OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
+    }
+    OPENSSL_free(c->cipher_data);
+#ifndef OPENSSL_NO_ENGINE
+    ENGINE_finish(c->engine);
+#endif
+    memset(c, 0, sizeof(*c));
+    return 1;
 }
 
 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
 {
-    EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof *ctx);
-    if (ctx)
-        EVP_CIPHER_CTX_init(ctx);
-    return ctx;
+    return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX));
+}
+
+void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
+{
+    EVP_CIPHER_CTX_reset(ctx);
+    OPENSSL_free(ctx);
 }
 
 int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                    const unsigned char *key, const unsigned char *iv, int enc)
 {
-    if (cipher)
-        EVP_CIPHER_CTX_init(ctx);
+    EVP_CIPHER_CTX_reset(ctx);
     return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
 }
 
@@ -106,12 +117,10 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
      * 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.
+     * reinitialisation, when it may all be unnecessary.
      */
-    if (ctx->engine && ctx->cipher && (!cipher ||
-                                       (cipher
-                                        && (cipher->nid ==
-                                            ctx->cipher->nid))))
+    if (ctx->engine && ctx->cipher
+        && (!cipher || (cipher && (cipher->nid == ctx->cipher->nid))))
         goto skip_to_init;
 #endif
     if (cipher) {
@@ -122,7 +131,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
          */
         if (ctx->cipher) {
             unsigned long flags = ctx->flags;
-            EVP_CIPHER_CTX_cleanup(ctx);
+            EVP_CIPHER_CTX_reset(ctx);
             /* Restore encrypt and flags */
             ctx->encrypt = enc;
             ctx->flags = flags;
@@ -143,7 +152,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                 /*
                  * 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"?
+                 * misspellings of "initialisation"?
                  */
                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
                 return 0;
@@ -161,8 +170,8 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
         ctx->cipher = cipher;
         if (ctx->cipher->ctx_size) {
-            ctx->cipher_data = OPENSSL_malloc(ctx->cipher->ctx_size);
-            if (!ctx->cipher_data) {
+            ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size);
+            if (ctx->cipher_data == NULL) {
                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE);
                 return 0;
             }
@@ -196,7 +205,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         return 0;
     }
 
-    if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
+    if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_CUSTOM_IV)) {
         switch (EVP_CIPHER_CTX_mode(ctx)) {
 
         case EVP_CIPH_STREAM_CIPHER:
@@ -227,7 +236,6 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
         default:
             return 0;
-            break;
         }
     }
 
@@ -324,7 +332,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     bl = ctx->cipher->block_size;
     OPENSSL_assert(bl <= (int)sizeof(ctx->buf));
     if (i != 0) {
-        if (i + inl < bl) {
+        if (bl - i > inl) {
             memcpy(&(ctx->buf[i]), in, inl);
             ctx->buf_len += inl;
             *outl = 0;
@@ -521,37 +529,6 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
     return (1);
 }
 
-void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
-{
-    if (ctx) {
-        EVP_CIPHER_CTX_cleanup(ctx);
-        OPENSSL_free(ctx);
-    }
-}
-
-int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
-{
-    if (c->cipher != NULL) {
-        if (c->cipher->cleanup && !c->cipher->cleanup(c))
-            return 0;
-        /* Cleanse cipher context data */
-        if (c->cipher_data)
-            OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
-    }
-    if (c->cipher_data)
-        OPENSSL_free(c->cipher_data);
-#ifndef OPENSSL_NO_ENGINE
-    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);
-#endif
-    memset(c, 0, sizeof(EVP_CIPHER_CTX));
-    return 1;
-}
-
 int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
 {
     if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
@@ -620,12 +597,12 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
     }
 #endif
 
-    EVP_CIPHER_CTX_cleanup(out);
-    memcpy(out, in, sizeof *out);
+    EVP_CIPHER_CTX_reset(out);
+    memcpy(out, in, sizeof(*out));
 
     if (in->cipher_data && in->cipher->ctx_size) {
         out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
-        if (!out->cipher_data) {
+        if (out->cipher_data == NULL) {
             EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_MALLOC_FAILURE);
             return 0;
         }