Adding Encryptor class to encrypt content and place in Data packets.
Change-Id: Ie77fd51b58091bbbb182ab9197a58a55b183654c
Refs: #3014
diff --git a/src/encryptor.cpp b/src/encryptor.cpp
new file mode 100644
index 0000000..06ee785
--- /dev/null
+++ b/src/encryptor.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California
+ *
+ * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
+ * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
+ *
+ * ndn-group-encrypt is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-group-encrypt is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "encryptor.hpp"
+#include "random-number-generator.hpp"
+#include "encrypted-content.hpp"
+#include "algo/aes.hpp"
+#include "algo/rsa.hpp"
+
+#include "algo/error.hpp"
+
+namespace ndn {
+namespace gep {
+namespace algo {
+
+using namespace CryptoPP;
+
+/**
+ * @brief Helper method for symmetric encryption
+ *
+ * Encrypt @p payload using @p key according to @p params.
+ *
+ * @return An EncryptedContent
+ */
+static EncryptedContent
+encryptSymmetric(const uint8_t* payload, size_t payloadLen,
+ const uint8_t* key, size_t keyLen,
+ const Name& keyName, const EncryptParams& params)
+{
+ tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
+ const Buffer& iv = params.getIV();
+ KeyLocator keyLocator(keyName);
+
+ switch (algType) {
+ case tlv::AlgorithmAesCbc:
+ case tlv::AlgorithmAesEcb: {
+ BOOST_ASSERT(iv.size() == static_cast<size_t>(AES::BLOCKSIZE));
+
+ const Buffer& encryptedPayload = Aes::encrypt(key, keyLen, payload, payloadLen, params);
+ return EncryptedContent(algType, keyLocator, encryptedPayload.buf(), encryptedPayload.size(), iv.buf(), iv.size());
+ }
+ default: {
+ BOOST_ASSERT(false);
+ throw algo::Error("Unsupported encryption method");
+ }
+ }
+}
+
+/**
+ * @brief Helper method for asymmetric encryption
+ *
+ * Encrypt @p payload using @p key according to @p params.
+ *
+ * @pre @p payloadLen should be within the range of the key.
+ * @return An EncryptedContent
+ */
+static EncryptedContent
+encryptAsymmetric(const uint8_t* payload, size_t payloadLen,
+ const uint8_t* key, size_t keyLen,
+ const Name& keyName, const EncryptParams& params)
+{
+ tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
+ KeyLocator keyLocator(keyName);
+
+ switch (algType) {
+ case tlv::AlgorithmRsaPkcs:
+ case tlv::AlgorithmRsaOaep: {
+ Buffer encryptedPayload = Rsa::encrypt(key, keyLen, payload, payloadLen, params);
+ return EncryptedContent(algType, keyLocator, encryptedPayload.buf(), encryptedPayload.size());
+ }
+ default: {
+ BOOST_ASSERT(false);
+ throw algo::Error("Unsupported encryption method");
+ }
+ }
+}
+
+void
+encryptData(Data& data, const uint8_t* payload, size_t payloadLen,
+ const Name& keyName, const uint8_t* key, size_t keyLen,
+ const EncryptParams& params)
+{
+ switch(params.getAlgorithmType()) {
+ case tlv::AlgorithmAesCbc:
+ case tlv::AlgorithmAesEcb: {
+ const EncryptedContent& content = encryptSymmetric(payload, payloadLen, key, keyLen, keyName, params);
+ data.setContent(content.wireEncode());
+ break;
+ }
+ case tlv::AlgorithmRsaPkcs:
+ case tlv::AlgorithmRsaOaep: {
+ size_t maxPlaintextLength = 0;
+ RSA::PublicKey publicKey;
+ ByteQueue keyQueue;
+
+ keyQueue.LazyPut(key, keyLen);
+ publicKey.Load(keyQueue);
+ RSAES_PKCS1v15_Encryptor enc(publicKey);
+ maxPlaintextLength = enc.FixedMaxPlaintextLength();
+
+ if (maxPlaintextLength < payloadLen) {
+ RandomNumberGenerator rng;
+ SecByteBlock nonceKey(0x00, 16); // 128 bits key.
+ rng.GenerateBlock(nonceKey.data(), nonceKey.size());
+
+ Name nonceKeyName(keyName);
+ nonceKeyName.append("nonce");
+
+ EncryptParams symParams(tlv::AlgorithmAesCbc, AES::BLOCKSIZE);
+
+ const EncryptedContent& nonceContent =
+ encryptSymmetric(payload, payloadLen, nonceKey.data(), nonceKey.size(), nonceKeyName, symParams);
+
+ const EncryptedContent& payloadContent =
+ encryptAsymmetric(nonceKey.data(), nonceKey.size(), key, keyLen, keyName, params);
+
+ Block content(tlv::Content);
+ content.push_back(payloadContent.wireEncode());
+ content.push_back(nonceContent.wireEncode());
+
+ data.setContent(content);
+ return;
+ }
+ else {
+ const EncryptedContent& content = encryptAsymmetric(payload, payloadLen, key, keyLen, keyName, params);
+ data.setContent(content.wireEncode());
+ return;
+ }
+ }
+ default:
+ throw algo::Error("Unsupported encryption method");
+ }
+}
+
+} // namespace algo
+} // namespace gep
+} // namespace ndn