Coverity CID 1444952: Null pointer dereferences
[openssl.git] / crypto / evp / evp_enc.c
index 7b22e21ee6363974ee8af77eacfd9d5c8e4d8984..4bc63703254f841005f43c592df7ef5b11a23489 100644 (file)
@@ -145,6 +145,21 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         case NID_aes_256_cbc:
         case NID_aes_192_cbc:
         case NID_aes_128_cbc:
+        case NID_aes_256_ofb128:
+        case NID_aes_192_ofb128:
+        case NID_aes_128_ofb128:
+        case NID_aes_256_cfb128:
+        case NID_aes_192_cfb128:
+        case NID_aes_128_cfb128:
+        case NID_aes_256_cfb1:
+        case NID_aes_192_cfb1:
+        case NID_aes_128_cfb1:
+        case NID_aes_256_cfb8:
+        case NID_aes_192_cfb8:
+        case NID_aes_128_cfb8:
+        case NID_aes_256_ctr:
+        case NID_aes_192_ctr:
+        case NID_aes_128_ctr:
             break;
         default:
             goto legacy;
@@ -191,7 +206,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
     ctx->cipher = cipher;
     if (ctx->provctx == NULL) {
-        ctx->provctx = ctx->cipher->newctx();
+        ctx->provctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
         if (ctx->provctx == NULL) {
             EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -226,7 +241,13 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             return 0;
         }
 
-        return ctx->cipher->einit(ctx->provctx, key, iv);
+        return ctx->cipher->einit(ctx->provctx,
+                                  key,
+                                  key == NULL ? 0
+                                              : EVP_CIPHER_CTX_key_length(ctx),
+                                  iv,
+                                  iv == NULL ? 0
+                                             : EVP_CIPHER_CTX_iv_length(ctx));
     }
 
     if (ctx->cipher->dinit == NULL) {
@@ -234,7 +255,13 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         return 0;
     }
 
-    return ctx->cipher->dinit(ctx->provctx, key, iv);
+    return ctx->cipher->dinit(ctx->provctx,
+                              key,
+                              key == NULL ? 0
+                                          : EVP_CIPHER_CTX_key_length(ctx),
+                              iv,
+                              iv == NULL ? 0
+                                         : EVP_CIPHER_CTX_iv_length(ctx));
 
     /* TODO(3.0): Remove legacy code below */
  legacy:
@@ -311,6 +338,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 #ifndef OPENSSL_NO_ENGINE
  skip_to_init:
 #endif
+    if (ctx->cipher == NULL)
+        return 0;
+
     /* we assume block size is a power of 2 in *cryptUpdate */
     OPENSSL_assert(ctx->cipher->block_size == 1
                    || ctx->cipher->block_size == 8
@@ -539,6 +569,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
 {
     int ret;
     size_t soutl;
+    int blocksize;
 
     /* Prevent accidental use of decryption context when encrypting */
     if (!ctx->encrypt) {
@@ -549,11 +580,15 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
         goto legacy;
 
-    if (ctx->cipher->cupdate == NULL) {
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (ctx->cipher->cupdate == NULL  || blocksize < 1) {
         EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
         return 0;
     }
-    ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl, in, (size_t)inl);
+    ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
+                               inl + (blocksize == 1 ? 0 : blocksize), in,
+                               (size_t)inl);
 
     if (soutl > INT_MAX) {
         EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
@@ -580,6 +615,7 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
     int n, ret;
     unsigned int i, b, bl;
     size_t soutl;
+    int blocksize;
 
     /* Prevent accidental use of decryption context when encrypting */
     if (!ctx->encrypt) {
@@ -587,15 +623,22 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
         return 0;
     }
 
-    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+    if (ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
+    if (ctx->cipher->prov == NULL)
         goto legacy;
 
-    if (ctx->cipher->cfinal == NULL) {
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
         EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
         return 0;
     }
 
-    ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl);
+    ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
+                              blocksize == 1 ? 0 : blocksize);
 
     if (soutl > INT_MAX) {
         EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
@@ -651,6 +694,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     int fix_len, cmpl = inl, ret;
     unsigned int b;
     size_t soutl;
+    int blocksize;
 
     /* Prevent accidental use of encryption context when decrypting */
     if (ctx->encrypt) {
@@ -658,14 +702,22 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
         return 0;
     }
 
-    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+    if (ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
+    if (ctx->cipher->prov == NULL)
         goto legacy;
 
-    if (ctx->cipher->cupdate == NULL) {
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (ctx->cipher->cupdate == NULL || blocksize < 1) {
         EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
         return 0;
     }
-    ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl, in, (size_t)inl);
+    ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
+                               inl + (blocksize == 1 ? 0 : blocksize), in,
+                               (size_t)inl);
 
     if (ret) {
         if (soutl > INT_MAX) {
@@ -756,6 +808,7 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
     unsigned int b;
     size_t soutl;
     int ret;
+    int blocksize;
 
     /* Prevent accidental use of encryption context when decrypting */
     if (ctx->encrypt) {
@@ -766,12 +819,15 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
     if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
         goto legacy;
 
-    if (ctx->cipher->cfinal == NULL) {
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
         EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
         return 0;
     }
 
-    ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl);
+    ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
+                              blocksize == 1 ? 0 : blocksize);
 
     if (ret) {
         if (soutl > INT_MAX) {
@@ -787,6 +843,10 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
  legacy:
 
     *outl = 0;
+    if (ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
 
     if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
         i = ctx->cipher->do_cipher(ctx, out, NULL, 0);
@@ -904,9 +964,11 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
 
 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 {
+    int kl;
     if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
         return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
-    if (RAND_priv_bytes(key, ctx->key_len) <= 0)
+    kl = EVP_CIPHER_CTX_key_length(ctx);
+    if (kl <= 0 || RAND_priv_bytes(key, kl) <= 0)
         return 0;
     return 1;
 }
@@ -1068,12 +1130,16 @@ static void *evp_cipher_from_dispatch(int nid, const OSSL_DISPATCH *fns,
     }
     if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
             || (fnciphcnt == 0 && cipher->ccipher == NULL)
-            || fnctxcnt != 2) {
+            || fnctxcnt != 2
+            || cipher->blocksize == NULL
+            || cipher->iv_length == NULL
+            || cipher->key_length == NULL) {
         /*
          * In order to be a consistent set of functions we must have at least
          * a complete set of "encrypt" functions, or a complete set of "decrypt"
          * functions, or a single "cipher" function. In all cases we need a
-         * complete set of context management functions
+         * complete set of context management functions, as well as the
+         * blocksize, iv_length and key_length functions.
          */
         EVP_CIPHER_meth_free(cipher);
         EVPerr(EVP_F_EVP_CIPHER_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS);