blob: c9f774522f374fc3da9d6f7cf8e7cf3cddef3456 [file] [log] [blame]
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhang19a11d22018-04-12 22:58:20 -07003 * Copyright (c) 2014-2018, Regents of the University of California
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -07004 *
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"
Yingdi Yub3c47762016-03-20 19:37:27 -070021#include "aes.hpp"
22#include "rsa.hpp"
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070023#include "../encrypted-content.hpp"
Yingdi Yub3c47762016-03-20 19:37:27 -070024#include "error.hpp"
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070025#include <openssl/rand.h>
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070026
27namespace ndn {
28namespace gep {
29namespace algo {
30
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070031/**
32 * @brief Helper method for symmetric encryption
33 *
34 * Encrypt @p payload using @p key according to @p params.
35 *
36 * @return An EncryptedContent
37 */
38static EncryptedContent
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070039encryptSymmetric(const uint8_t* payload,
40 size_t payloadLen,
41 const uint8_t* key,
42 size_t keyLen,
43 const Name& keyName,
44 const EncryptParams& params)
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070045{
46 tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
47 const Buffer& iv = params.getIV();
48 KeyLocator keyLocator(keyName);
49
50 switch (algType) {
Yingdi Yu3decf4e2015-11-02 12:33:31 -080051 case tlv::AlgorithmAesCbc: {
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070052 const Buffer& encryptedPayload = Aes::encrypt(key, keyLen, payload, payloadLen, params);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070053 return EncryptedContent(algType, keyLocator,
54 encryptedPayload.data(),
55 encryptedPayload.size(),
56 iv.data(), iv.size());
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070057 }
58 default: {
59 BOOST_ASSERT(false);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070060 BOOST_THROW_EXCEPTION(algo::Error("Unsupported encryption method"));
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070061 }
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,
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070076 const Name& keyName,
77 const EncryptParams& params)
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070078{
79 tlv::AlgorithmTypeValue algType = params.getAlgorithmType();
80 KeyLocator keyLocator(keyName);
81
82 switch (algType) {
83 case tlv::AlgorithmRsaPkcs:
84 case tlv::AlgorithmRsaOaep: {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070085 Buffer encryptedPayload = Rsa::encrypt(key, keyLen, payload, payloadLen);
86 return EncryptedContent(algType, keyLocator, encryptedPayload.data(), encryptedPayload.size());
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070087 }
88 default: {
89 BOOST_ASSERT(false);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070090 BOOST_THROW_EXCEPTION(algo::Error("Unsupported encryption method"));
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -070091 }
92 }
93}
94
95void
96encryptData(Data& data, const uint8_t* payload, size_t payloadLen,
97 const Name& keyName, const uint8_t* key, size_t keyLen,
98 const EncryptParams& params)
99{
Yingdi Yu3decf4e2015-11-02 12:33:31 -0800100 Name dataName = data.getName();
101 dataName.append(NAME_COMPONENT_FOR).append(keyName);
102 data.setName(dataName);
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700103 switch (params.getAlgorithmType()) {
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700104 case tlv::AlgorithmAesCbc:
105 case tlv::AlgorithmAesEcb: {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700106 const EncryptedContent& content =
107 encryptSymmetric(payload, payloadLen, key, keyLen, keyName, params);
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700108 data.setContent(content.wireEncode());
109 break;
110 }
111 case tlv::AlgorithmRsaPkcs:
112 case tlv::AlgorithmRsaOaep: {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700113 if (payloadLen > keyLen - 11) {
114 uint8_t nonceKey[16];
115 int result = RAND_bytes(nonceKey, sizeof(nonceKey));
116 if (result != 1) {
117 BOOST_THROW_EXCEPTION(Error("Cannot generate 32 bytes random AES key"));
118 }
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700119
120 Name nonceKeyName(keyName);
121 nonceKeyName.append("nonce");
122
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700123 EncryptParams symParams(tlv::AlgorithmAesCbc, 16);
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700124
125 const EncryptedContent& nonceContent =
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700126 encryptSymmetric(payload, payloadLen, nonceKey, sizeof(nonceKey), nonceKeyName, symParams);
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700127
128 const EncryptedContent& payloadContent =
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700129 encryptAsymmetric(nonceKey, sizeof(nonceKey), key, keyLen, keyName, params);
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700130
131 Block content(tlv::Content);
132 content.push_back(payloadContent.wireEncode());
133 content.push_back(nonceContent.wireEncode());
134
135 data.setContent(content);
136 return;
137 }
138 else {
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700139 const EncryptedContent& content =
140 encryptAsymmetric(payload, payloadLen, key, keyLen, keyName, params);
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700141 data.setContent(content.wireEncode());
142 return;
143 }
144 }
145 default:
Zhiyi Zhang19a11d22018-04-12 22:58:20 -0700146 BOOST_THROW_EXCEPTION(algo::Error("Unsupported encryption method"));
Prashanth Swaminathand5b3eae2015-07-09 15:37:05 -0700147 }
148}
149
150} // namespace algo
151} // namespace gep
152} // namespace ndn