bool AESEncryptor::start()

in util/EncryptionUtils.cpp [277:332]


bool AESEncryptor::start(const EncryptionParams& encryptionData,
                         std::string& ivOut) {
  WDT_CHECK(!started_);

  // reset the enc ctx
  // To reuse the same ctx, we have to have different reset code for different
  // openssl version. So, we will just create another ctx for simplification
  evpCtx_.reset(createAndInitCtx());

  type_ = encryptionData.getType();

  const std::string& key = encryptionData.getSecret();
  if (key.length() != kAESBlockSize) {
    WLOG(ERROR) << "Encryption key size must be " << kAESBlockSize
                << ", but input size length " << key.length();
    return false;
  }

  ivOut.resize(kAESBlockSize);

  uint8_t* ivPtr = (uint8_t*)(&ivOut.front());
  uint8_t* keyPtr = (uint8_t*)(&key.front());
  if (RAND_bytes(ivPtr, kAESBlockSize) != 1) {
    WLOG(ERROR)
        << "RAND_bytes failed, unable to generate initialization vector";
    return false;
  }

  const EVP_CIPHER* cipher = getCipher(type_);
  if (cipher == nullptr) {
    return false;
  }
  int cipherBlockSize = EVP_CIPHER_block_size(cipher);
  WDT_CHECK_EQ(1, cipherBlockSize);

  // Not super clear this is actually needed - but probably if not set
  // gcm only uses 96 out of the 128 bits of IV. Let's use all of it to
  // reduce chances of attacks on large data transfers.
  if (type_ == ENC_AES128_GCM) {
    if (EVP_EncryptInit_ex(evpCtx_.get(), cipher, nullptr, nullptr, nullptr) !=
        1) {
      WLOG(ERROR) << "GCM First init error";
    }
    if (EVP_CIPHER_CTX_ctrl(evpCtx_.get(), EVP_CTRL_GCM_SET_IVLEN, ivOut.size(),
                            nullptr) != 1) {
      WLOG(ERROR) << "Encrypt Init ivlen set failed";
    }
  }

  if (EVP_EncryptInit_ex(evpCtx_.get(), cipher, nullptr, keyPtr, ivPtr) != 1) {
    WLOG(ERROR) << "Encrypt Init failed";
    return false;
  }
  started_ = true;
  return true;
}