Encrypt::Encrypt(CryptoConfig config, Slice key, Slice iv, Slice entity): WithState(State::INITIAL), config_(config), buffer_(VERSION_SIZE + config.ivLength + config.keyLength), version_(buffer_(0, VERSION_SIZE)), iv_(buffer_(VERSION_SIZE, VERSION_SIZE + config.ivLength)), key_(buffer_(VERSION_SIZE + config.ivLength, VERSION_SIZE + config.ivLength + config.keyLength)), entity_(entity.length()), tag_(config_.tagLength) { checkArgument(key.length() == config_.keyLength, "Invalid key"); checkArgument(iv.length() == config_.ivLength, "Invalid IV"); version_[FORMAT_BYTE] = FORMAT_VALUE; version_[CONFIG_BYTE] = config_.id; // copy the data to memory I own iv.copyTo(iv_); key.copyTo(key_); entity.copyTo(entity_); const EVP_CIPHER* cipher = config_.cipher; ctx_ = EVP_CIPHER_CTX_new(); check(ctx_, "Encryption context creation failed"); int code = EVP_EncryptInit_ex(ctx_, cipher, NULL, NULL, NULL); check(code == EVP_SUCCESS, "Encryption context creation failed (cipher)"); code = EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IVLEN, config_.ivLength, NULL); check(code == EVP_SUCCESS, "Encryption context creation failed (IV length)"); code = EVP_EncryptInit_ex(ctx_, NULL, NULL, key_.offset(0), iv_.offset(0)); check(code == EVP_SUCCESS, "Encryption initialization failed"); }