NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
public-key.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2022 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
30 
31 #define ENSURE_PUBLIC_KEY_LOADED(key) \
32  do { \
33  if ((key) == nullptr) \
34  NDN_THROW(Error("Public key has not been loaded yet")); \
35  } while (false)
36 
37 #define ENSURE_PUBLIC_KEY_NOT_LOADED(key) \
38  do { \
39  if ((key) != nullptr) \
40  NDN_THROW(Error("Public key has already been loaded")); \
41  } while (false)
42 
43 namespace ndn {
44 namespace security {
45 namespace transform {
46 
47 class PublicKey::Impl : noncopyable
48 {
49 public:
50  Impl() noexcept
51  : key(nullptr)
52  {
53  }
54 
56  {
57  EVP_PKEY_free(key);
58  }
59 
60 public:
61  EVP_PKEY* key;
62 };
63 
65  : m_impl(make_unique<Impl>())
66 {
67 }
68 
69 PublicKey::~PublicKey() = default;
70 
71 KeyType
73 {
74  if (!m_impl->key)
75  return KeyType::NONE;
76 
77  switch (detail::getEvpPkeyType(m_impl->key)) {
78  case EVP_PKEY_RSA:
79  return KeyType::RSA;
80  case EVP_PKEY_EC:
81  return KeyType::EC;
82  default:
83  return KeyType::NONE;
84  }
85 }
86 
87 size_t
89 {
90  switch (getKeyType()) {
91  case KeyType::RSA:
92  case KeyType::EC:
93  return static_cast<size_t>(EVP_PKEY_bits(m_impl->key));
94  default:
95  return 0;
96  }
97 }
98 
99 void
100 PublicKey::loadPkcs8(span<const uint8_t> buf)
101 {
102  ENSURE_PUBLIC_KEY_NOT_LOADED(m_impl->key);
103 
104  auto ptr = buf.data();
105  if (d2i_PUBKEY(&m_impl->key, &ptr, static_cast<long>(buf.size())) == nullptr)
106  NDN_THROW(Error("Failed to load public key"));
107 }
108 
109 void
110 PublicKey::loadPkcs8(std::istream& is)
111 {
112  OBufferStream os;
113  streamSource(is) >> streamSink(os);
114  loadPkcs8(*os.buf());
115 }
116 
117 void
118 PublicKey::loadPkcs8Base64(span<const uint8_t> buf)
119 {
120  OBufferStream os;
121  bufferSource(buf) >> base64Decode() >> streamSink(os);
122  loadPkcs8(*os.buf());
123 }
124 
125 void
126 PublicKey::loadPkcs8Base64(std::istream& is)
127 {
128  OBufferStream os;
129  streamSource(is) >> base64Decode() >> streamSink(os);
130  loadPkcs8(*os.buf());
131 }
132 
133 void
134 PublicKey::savePkcs8(std::ostream& os) const
135 {
136  bufferSource(*toPkcs8()) >> streamSink(os);
137 }
138 
139 void
140 PublicKey::savePkcs8Base64(std::ostream& os) const
141 {
142  bufferSource(*toPkcs8()) >> base64Encode() >> streamSink(os);
143 }
144 
146 PublicKey::encrypt(span<const uint8_t> plainText) const
147 {
148  ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
149 
150  int keyType = detail::getEvpPkeyType(m_impl->key);
151  switch (keyType) {
152  case EVP_PKEY_NONE:
153  NDN_THROW(Error("Failed to determine key type"));
154  case EVP_PKEY_RSA:
155  return rsaEncrypt(plainText);
156  default:
157  NDN_THROW(Error("Encryption is not supported for key type " + to_string(keyType)));
158  }
159 }
160 
161 void*
162 PublicKey::getEvpPkey() const
163 {
164  return m_impl->key;
165 }
166 
168 PublicKey::toPkcs8() const
169 {
170  ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
171 
172  uint8_t* pkcs8 = nullptr;
173  int len = i2d_PUBKEY(m_impl->key, &pkcs8);
174  if (len < 0)
175  NDN_THROW(Error("Cannot convert key to PKCS #8 format"));
176 
177  auto buffer = make_shared<Buffer>(pkcs8, len);
178  OPENSSL_free(pkcs8);
179 
180  return buffer;
181 }
182 
184 PublicKey::rsaEncrypt(span<const uint8_t> plainText) const
185 {
186  detail::EvpPkeyCtx ctx(m_impl->key);
187 
188  if (EVP_PKEY_encrypt_init(ctx) <= 0)
189  NDN_THROW(Error("Failed to initialize encryption context"));
190 
191  if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0)
192  NDN_THROW(Error("Failed to set padding"));
193 
194  size_t outlen = 0;
195  // Determine buffer length
196  if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, plainText.data(), plainText.size()) <= 0)
197  NDN_THROW(Error("Failed to estimate output length"));
198 
199  auto out = make_shared<Buffer>(outlen);
200  if (EVP_PKEY_encrypt(ctx, out->data(), &outlen, plainText.data(), plainText.size()) <= 0)
201  NDN_THROW(Error("Failed to encrypt plaintext"));
202 
203  out->resize(outlen);
204  return out;
205 }
206 
207 } // namespace transform
208 } // namespace security
209 } // namespace ndn
KeyType getKeyType() const
Return the type of the public key.
Definition: public-key.cpp:72
Copyright (c) 2011-2015 Regents of the University of California.
Unknown or unsupported key type.
std::string to_string(const T &val)
Definition: backports.hpp:86
void loadPkcs8Base64(span< const uint8_t > buf)
Load the public key in base64-encoded PKCS#8 format from a buffer buf.
Definition: public-key.cpp:118
unique_ptr< Transform > base64Decode(bool expectNewlineEvery64Bytes)
RSA key, supports sign/verify and encrypt/decrypt operations.
int getEvpPkeyType(const EVP_PKEY *key)
ConstBufferPtr encrypt(span< const uint8_t > plainText) const
Definition: public-key.cpp:146
void loadPkcs8(span< const uint8_t > buf)
Load the public key in PKCS#8 format from a buffer buf.
Definition: public-key.cpp:100
#define NDN_THROW(e)
Definition: exception.hpp:61
KeyType
The type of a cryptographic key.
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:53
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
size_t getKeySize() const
Return the size of the public key in bits.
Definition: public-key.cpp:88
PublicKey()
Create an empty public key instance.
Definition: public-key.cpp:64
void savePkcs8Base64(std::ostream &os) const
Save the public key in base64-encoded PKCS#8 format into a stream os.
Definition: public-key.cpp:140
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
#define ENSURE_PUBLIC_KEY_NOT_LOADED(key)
Definition: public-key.cpp:37
implements an output stream that constructs ndn::Buffer
#define ENSURE_PUBLIC_KEY_LOADED(key)
Definition: public-key.cpp:31
void savePkcs8(std::ostream &os) const
Save the public key in PKCS#8 format into a stream os.
Definition: public-key.cpp:134
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:139
unique_ptr< Transform > base64Encode(bool needBreak)