NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: 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; -*- */
22 #include "public-key.hpp"
23 #include "buffer-source.hpp"
24 #include "stream-source.hpp"
25 #include "base64-encode.hpp"
26 #include "base64-decode.hpp"
27 #include "stream-sink.hpp"
28 #include "../../encoding/buffer-stream.hpp"
29 #include "../detail/openssl-helper.hpp"
30 
31 #define ENSURE_PUBLIC_KEY_LOADED(key) \
32  do { \
33  if (key == nullptr) \
34  BOOST_THROW_EXCEPTION(Error("Public key has not been loaded yet")); \
35  } while (false)
36 
37 namespace ndn {
38 namespace security {
39 namespace transform {
40 
42 {
43 public:
44  Impl()
45  : key(nullptr)
46  {
47  }
48 
50  {
51  EVP_PKEY_free(key);
52  }
53 
54 public:
55  EVP_PKEY* key;
56 };
57 
59  : m_impl(new Impl)
60 {
61 }
62 
63 PublicKey::~PublicKey() = default;
64 
65 KeyType
67 {
68  ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
69 
70 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
71  switch (EVP_PKEY_type(m_impl->key->type)) {
72 #else
73  switch (EVP_PKEY_base_id(m_impl->key)) {
74 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
75  case EVP_PKEY_RSA:
76  return KeyType::RSA;
77  case EVP_PKEY_EC:
78  return KeyType::EC;
79  default:
80  BOOST_THROW_EXCEPTION(Error("Public key type is not recognized"));
81  }
82 }
83 
84 void
85 PublicKey::loadPkcs8(const uint8_t* buf, size_t size)
86 {
87  m_impl->key = d2i_PUBKEY(nullptr, &buf, size);
88 
89  ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
90 }
91 
92 void
93 PublicKey::loadPkcs8(std::istream& is)
94 {
95  OBufferStream os;
96  {
97  using namespace transform;
98  streamSource(is) >> streamSink(os);
99  }
100  this->loadPkcs8(os.buf()->buf(), os.buf()->size());
101 }
102 
103 void
104 PublicKey::loadPkcs8Base64(const uint8_t* buf, size_t size)
105 {
106  OBufferStream os;
107  {
108  using namespace transform;
109  bufferSource(buf, size) >> base64Decode() >> streamSink(os);
110  }
111  this->loadPkcs8(os.buf()->buf(), os.buf()->size());
112 }
113 
114 void
115 PublicKey::loadPkcs8Base64(std::istream& is)
116 {
117  OBufferStream os;
118  {
119  using namespace transform;
120  streamSource(is) >> base64Decode() >> streamSink(os);
121  }
122  this->loadPkcs8(os.buf()->buf(), os.buf()->size());
123 }
124 
125 void
126 PublicKey::savePkcs8(std::ostream& os) const
127 {
128  using namespace transform;
129  bufferSource(*this->toPkcs8()) >> streamSink(os);
130 }
131 
132 void
133 PublicKey::savePkcs8Base64(std::ostream& os) const
134 {
135  using namespace transform;
136  bufferSource(*this->toPkcs8()) >> base64Encode() >> streamSink(os);
137 }
138 
140 PublicKey::encrypt(const uint8_t* plainText, size_t plainLen) const
141 {
142  ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
143 
144 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
145  switch (EVP_PKEY_type(m_impl->key->type)) {
146 #else
147  switch (EVP_PKEY_base_id(m_impl->key)) {
148 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
149  case EVP_PKEY_RSA:
150  return rsaEncrypt(plainText, plainLen);
151  default:
152  BOOST_THROW_EXCEPTION(Error("Encryption is not supported for this key type"));
153  }
154 }
155 
156 void*
157 PublicKey::getEvpPkey() const
158 {
159  return m_impl->key;
160 }
161 
163 PublicKey::toPkcs8() const
164 {
165  ENSURE_PUBLIC_KEY_LOADED(m_impl->key);
166 
167  uint8_t* pkcs8 = nullptr;
168  int len = i2d_PUBKEY(m_impl->key, &pkcs8);
169 
170  if (pkcs8 == nullptr)
171  BOOST_THROW_EXCEPTION(Error("Failed to convert to pkcs8 format"));
172 
173  auto buffer = make_shared<Buffer>(pkcs8, len);
174  OPENSSL_free(pkcs8);
175 
176  return buffer;
177 }
178 
180 PublicKey::rsaEncrypt(const uint8_t* plainText, size_t plainLen) const
181 {
182  detail::EvpPkeyCtx ctx(m_impl->key);
183 
184  if (EVP_PKEY_encrypt_init(ctx.get()) <= 0)
185  BOOST_THROW_EXCEPTION(Error("Failed to initialize encryption context"));
186 
187  if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING) <= 0)
188  BOOST_THROW_EXCEPTION(Error("Failed to set padding"));
189 
190  size_t outlen = 0;
191  // Determine buffer length
192  if (EVP_PKEY_encrypt(ctx.get(), nullptr, &outlen, plainText, plainLen) <= 0)
193  BOOST_THROW_EXCEPTION(Error("Failed to estimate output length"));
194 
195  auto out = make_shared<Buffer>(outlen);
196 
197  if (EVP_PKEY_encrypt(ctx.get(), out->buf(), &outlen, plainText, plainLen) <= 0)
198  BOOST_THROW_EXCEPTION(Error("Failed to decrypt cipher text"));
199 
200  out->resize(outlen);
201  return out;
202 }
203 
204 } // namespace transform
205 } // namespace security
206 } // namespace ndn
KeyType getKeyType() const
Get the type of the public key.
Definition: public-key.cpp:66
Copyright (c) 2011-2015 Regents of the University of California.
unique_ptr< Transform > base64Decode(bool expectNewlineEvery64Bytes)
#define ENSURE_PUBLIC_KEY_LOADED(key)
Copyright (c) 2013-2016 Regents of the University of California.
Definition: public-key.cpp:31
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:51
void loadPkcs8(const uint8_t *buf, size_t size)
Load the public key in PKCS#8 format from a buffer buf.
Definition: public-key.cpp:85
ConstBufferPtr encrypt(const uint8_t *plainText, size_t plainLen) const
Definition: public-key.cpp:140
void loadPkcs8Base64(const uint8_t *buf, size_t size)
Load the public key in base64-encoded PKCS#8 format from a buffer buf.
Definition: public-key.cpp:104
PublicKey()
Create a public key instance.
Definition: public-key.cpp:58
void savePkcs8Base64(std::ostream &os) const
Save the public key in base64-encoded PKCS#8 format into a stream os.
Definition: public-key.cpp:133
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
implements an output stream that constructs ndn::Buffer
void savePkcs8(std::ostream &os) const
Save the public key in PKCS#8 format into a stream os.
Definition: public-key.cpp:126
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:33
unique_ptr< Transform > base64Encode(bool needBreak)