/********************************************************************
 * 2014 -
 * open source under Apache License Version 2.0
 ********************************************************************/
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CryptoCodec.h"
#include "Logger.h"

#include <inttypes.h>

using namespace Hdfs::Internal;


namespace Hdfs {

	//copy from java HDFS code
	std::string CryptoCodec::calculateIV(const std::string& initIV, unsigned long counter) {
		char IV[initIV.length()];

		int i = initIV.length(); // IV length
		int j = 0; // counter bytes index
		unsigned int sum = 0;
		while (i-- > 0) {
			// (sum >>> Byte.SIZE) is the carry for addition
			sum = (initIV[i] & 0xff) + (sum >> 8);
			if (j++ < 8) { // Big-endian, and long is 8 bytes length
				sum += (char) counter & 0xff;
				counter >>= 8;
			}
			IV[i] = (char) sum;
		}

		return std::string(IV, initIV.length());
	}

	CryptoCodec::CryptoCodec(FileEncryptionInfo *encryptionInfo, shared_ptr<KmsClientProvider> kcp, int32_t bufSize) :
		kcp(kcp), encryptionInfo(encryptionInfo), bufSize(bufSize)
	{

		// Init global status
		ERR_load_crypto_strings();
		OpenSSL_add_all_algorithms();
		#if OPENSSL_VERSION_NUMBER < 0x10100000L
		OPENSSL_config(NULL);
		#else
		OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
		#endif

		// Create cipher context
		cipherCtx = EVP_CIPHER_CTX_new();
		cipher = NULL;

		padding = 0;
		counter = 0;
		is_init = false;
	}

	CryptoCodec::~CryptoCodec()
	{
		if (cipherCtx)
			EVP_CIPHER_CTX_free(cipherCtx);
	}

	std::string CryptoCodec::getDecryptedKeyFromKms()
	{
		ptree map = kcp->decryptEncryptedKey(*encryptionInfo);
		std::string key;
		try {
			key = map.get < std::string > ("material");
		} catch (...) {
			THROW(HdfsIOException, "CryptoCodec : Can not get key from kms.");
		}

		int rem = key.length() % 4;
		if (rem) {
			rem = 4 - rem;
			while (rem != 0) {
				key = key + "=";
				rem--;
			}
		}

		std::replace(key.begin(), key.end(), '-', '+');
		std::replace(key.begin(), key.end(), '_', '/');

		LOG(DEBUG3, "CryptoCodec : getDecryptedKeyFromKms material is :%s", key.c_str());

		key = KmsClientProvider::base64Decode(key);
		return key;
	}

	int CryptoCodec::init(CryptoMethod crypto_method, int64_t stream_offset) {
		// Check CryptoCodec init or not.
		if (is_init)
			return 0;

		// Get decrypted key from KMS.
		decryptedKey = getDecryptedKeyFromKms();

		// Select cipher method based on the decrypted key length.
		AlgorithmBlockSize = decryptedKey.length();
		if (AlgorithmBlockSize == KEY_LENGTH_256) {
			cipher = EVP_aes_256_ctr();
		} else if (AlgorithmBlockSize == KEY_LENGTH_128) {
			cipher = EVP_aes_128_ctr();
		} else {
			LOG(WARNING, "CryptoCodec : Invalid key length.");
			return -1;
		}

		is_init = true;
		// Calculate iv and counter in order to init cipher context with cipher method. Default value is 0.
		if ((resetStreamOffset(crypto_method, stream_offset)) < 0) {
			is_init = false;
			return -1;
		}

		LOG(DEBUG3, "CryptoCodec init success, length of the decrypted key is : %lu, crypto method is : %d", AlgorithmBlockSize, crypto_method);
		return 1;

	}

	int CryptoCodec::resetStreamOffset(CryptoMethod crypto_method, int64_t stream_offset) {
		// Check CryptoCodec init or not.
		if (is_init == false)
			return -1;
		// Calculate new IV when appending an existed file.
		std::string iv = encryptionInfo->getIv();
		if (stream_offset > 0) {
                        // For AES, the algorithm block is fixed size of 128 bits.
			counter = stream_offset / 16;
			padding = stream_offset % 16;
			iv = this->calculateIV(iv, counter);
		} else if (stream_offset == 0) {
                        counter = 0;
                        padding = 0;
                } else {
                        LOG(WARNING, "CryptoCodec : Invalid stream_offset %" PRId64, stream_offset);
                        return -1;
                }

		// Judge the crypto method is encrypt or decrypt.
		int enc = (method == CryptoMethod::ENCRYPT) ? 1 : 0;

		// Init cipher context with cipher method.
		if (!EVP_CipherInit_ex(cipherCtx, cipher, NULL,
				(const unsigned char *) decryptedKey.c_str(), (const unsigned char *) iv.c_str(),
				enc)) {
			LOG(WARNING, "EVP_CipherInit_ex failed");
			return -1;
		}

		// AES/CTR/NoPadding, set padding to 0.
		EVP_CIPHER_CTX_set_padding(cipherCtx, 0);

		return 1;
	}

	std::string CryptoCodec::cipher_wrap(const char * buffer, int64_t size) {
		if (!is_init)
			THROW(InvalidParameter, "CryptoCodec isn't init");

		int offset = 0;
		int remaining = size;
		int len = 0;
		int ret = 0;

		std::string in_buf(buffer,size);
		std::string out_buf(size, 0);
		//set necessary padding when appending a existed file
		if (padding > 0) {
			in_buf.insert(0, padding, 0);
			out_buf.resize(padding+size);
			remaining += padding;
		}

		// If the encode/decode buffer size larger than crypto buffer size, encode/decode buffer one by one
		while (remaining > bufSize) {
			ret = EVP_CipherUpdate(cipherCtx, (unsigned char *) &out_buf[offset], &len,
				(const unsigned char *)in_buf.data() + offset, bufSize);

			if (!ret) {
				std::string err = ERR_lib_error_string(ERR_get_error());
				THROW(HdfsIOException, "CryptoCodec : cipher_wrap AES data failed:%s, crypto_method:%d", err.c_str(), method);
			}
			offset += len;
			remaining -= len;
			LOG(DEBUG3, "CryptoCodec : EVP_CipherUpdate successfully, len:%d", len);
		}

		if (remaining) {
			ret = EVP_CipherUpdate(cipherCtx, (unsigned char *) &out_buf[offset], &len,
				(const unsigned char *) in_buf.data() + offset, remaining);

			if (!ret) {
				std::string err = ERR_lib_error_string(ERR_get_error());
				THROW(HdfsIOException, "CryptoCodec : cipher_wrap AES data failed:%s, crypto_method:%d", err.c_str(), method);
			}

		}

		//cut off padding when necessary
		if (padding > 0) {
			out_buf.erase(0, padding);
			padding = 0;
		}

		return out_buf;
	}

}

