blob: 06ee785e478a27fdc6accce5e6b6c64dd4dba1cc [file] [log] [blame]
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California
4 *
5 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
6 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
7 *
8 * ndn-group-encrypt is free software: you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free Software
10 * Foundation, either version 3 of the License, or (at your option) any later version.
11 *
12 * ndn-group-encrypt is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "encryptor.hpp"
21#include "random-number-generator.hpp"
22#include "encrypted-content.hpp"
23#include "algo/aes.hpp"
24#include "algo/rsa.hpp"
25
26#include "algo/error.hpp"
27
28namespace ndn {
29namespace gep {
30namespace algo {
31
32using namespace CryptoPP;
33
34/**
35 * @brief Helper method for symmetric encryption
36 *
37 * Encrypt @p payload using @p key according to @p params.
38 *
39 * @return An EncryptedContent
40 */
41static EncryptedContent
42encryptSymmetric(const uint8_t* payload, size_t payloadLen,
43 const uint8_t* key, size_t keyLen,
44 const Name& keyName, const EncryptParams& params)
45{
46 tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
47 const Buffer& iv = params.getIV();
48 KeyLocator keyLocator(keyName);
49
50 switch (algType) {
51 case tlv::AlgorithmAesCbc:
52 case tlv::AlgorithmAesEcb: {
53 BOOST_ASSERT(iv.size() == static_cast<size_t>(AES::BLOCKSIZE));
54
55 const Buffer& encryptedPayload = Aes::encrypt(key, keyLen, payload, payloadLen, params);
56 return EncryptedContent(algType, keyLocator, encryptedPayload.buf(), encryptedPayload.size(), iv.buf(), iv.size());
57 }
58 default: {
59 BOOST_ASSERT(false);
60 throw algo::Error("Unsupported encryption method");
61 }
62 }
63}
64
65/**
66 * @brief Helper method for asymmetric encryption
67 *
68 * Encrypt @p payload using @p key according to @p params.
69 *
70 * @pre @p payloadLen should be within the range of the key.
71 * @return An EncryptedContent
72 */
73static EncryptedContent
74encryptAsymmetric(const uint8_t* payload, size_t payloadLen,
75 const uint8_t* key, size_t keyLen,
76 const Name& keyName, const EncryptParams& params)
77{
78 tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
79 KeyLocator keyLocator(keyName);
80
81 switch (algType) {
82 case tlv::AlgorithmRsaPkcs:
83 case tlv::AlgorithmRsaOaep: {
84 Buffer encryptedPayload = Rsa::encrypt(key, keyLen, payload, payloadLen, params);
85 return EncryptedContent(algType, keyLocator, encryptedPayload.buf(), encryptedPayload.size());
86 }
87 default: {
88 BOOST_ASSERT(false);
89 throw algo::Error("Unsupported encryption method");
90 }
91 }
92}
93
94void
95encryptData(Data& data, const uint8_t* payload, size_t payloadLen,
96 const Name& keyName, const uint8_t* key, size_t keyLen,
97 const EncryptParams& params)
98{
99 switch(params.getAlgorithmType()) {
100 case tlv::AlgorithmAesCbc:
101 case tlv::AlgorithmAesEcb: {
102 const EncryptedContent& content = encryptSymmetric(payload, payloadLen, key, keyLen, keyName, params);
103 data.setContent(content.wireEncode());
104 break;
105 }
106 case tlv::AlgorithmRsaPkcs:
107 case tlv::AlgorithmRsaOaep: {
108 size_t maxPlaintextLength = 0;
109 RSA::PublicKey publicKey;
110 ByteQueue keyQueue;
111
112 keyQueue.LazyPut(key, keyLen);
113 publicKey.Load(keyQueue);
114 RSAES_PKCS1v15_Encryptor enc(publicKey);
115 maxPlaintextLength = enc.FixedMaxPlaintextLength();
116
117 if (maxPlaintextLength < payloadLen) {
118 RandomNumberGenerator rng;
119 SecByteBlock nonceKey(0x00, 16); // 128 bits key.
120 rng.GenerateBlock(nonceKey.data(), nonceKey.size());
121
122 Name nonceKeyName(keyName);
123 nonceKeyName.append("nonce");
124
125 EncryptParams symParams(tlv::AlgorithmAesCbc, AES::BLOCKSIZE);
126
127 const EncryptedContent& nonceContent =
128 encryptSymmetric(payload, payloadLen, nonceKey.data(), nonceKey.size(), nonceKeyName, symParams);
129
130 const EncryptedContent& payloadContent =
131 encryptAsymmetric(nonceKey.data(), nonceKey.size(), key, keyLen, keyName, params);
132
133 Block content(tlv::Content);
134 content.push_back(payloadContent.wireEncode());
135 content.push_back(nonceContent.wireEncode());
136
137 data.setContent(content);
138 return;
139 }
140 else {
141 const EncryptedContent& content = encryptAsymmetric(payload, payloadLen, key, keyLen, keyName, params);
142 data.setContent(content.wireEncode());
143 return;
144 }
145 }
146 default:
147 throw algo::Error("Unsupported encryption method");
148 }
149}
150
151} // namespace algo
152} // namespace gep
153} // namespace ndn