Search code examples
cencryptionopensslpoco-libraries

Need help decrypting with OpenSSL 3.0.8 Libraries


I'm trying to write a service to decrypt a large number of openssl-encrypted content. It works great with a simple command line program, but when I use the same code in a Poco (multi-threaded) server, I get:

error:1C800064:Provider routines::bad decrypt

OpenSSL 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023)

I tried copying std::strings into C arrays, to see if that would help -- no luck

I don't know what I'm doing wrong. Any ideas on how I can make this work? I see old references to using mutex callbacks but the docs say they're not needed anymore.

Here's the code that always works on a CLI program but never works in my Poco service:

int decodeAndDecrypt(const char          * dataIn,
                     const unsigned char * key,
                     const unsigned char * iv,
                     char                * dataOut,
                     int                 * outLen,
                     char                * errorMsg)
{
   while (ERR_get_error());
   BIO * bio = BIO_new_mem_buf((void *)dataIn, -1);
   BIO * b64 = BIO_new(BIO_f_base64());
   BIO * cipher =  BIO_new(BIO_f_cipher());

   BIO_set_cipher(cipher, EVP_aes_256_cbc(), key, iv, 0);
   BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

   BIO_push(cipher, b64);
   BIO_push(b64, bio);

   char * outPtr = dataOut;
   int max = *outLen;
   *outLen = 0;
   errorMsg[0] = 0;

   while (true)
   {
      char tmp[1024] = {0};
      int bytesRead = BIO_read(cipher, tmp, sizeof(tmp));
      if (bytesRead <= 0)
      {
         break;
      }
      if (bytesRead > max)
      {
         snprintf(errorMsg, ERR_SZ, "%s: result data exceeds maximum buffer size.", __func__);
         return EXIT_FAILURE;
      }
      snprintf(outPtr, max, "%s", tmp);

      outPtr += bytesRead;
      *outLen += bytesRead;
      max -= bytesRead;
   }

   if (*outLen == 0) // If no data was transferred, check for errors
   {
      unsigned long errNo(0);
      bool errorsFound(false);
      while ((errNo = ERR_get_error()))
      {
         errorsFound = true;
         array< char, 256 > temp;
         ERR_error_string_n(errNo, temp.data(), temp.size());
         strcat(errorMsg, temp.data());
      }
      if (errorsFound)
      {
         return EXIT_FAILURE;
      }
   }

   BIO_free_all(cipher);

   return EXIT_SUCCESS;
}


Solution

  • I didn't realize that EVP_aes_256_cbc() must have a 256 bit key and a 128 bit IV. After making sure that both values were the correct length and zero padded for shorter values, this routine began to work properly.