esp8266ndn
NDN Arduino library for ESP8266 and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ec.hpp
Go to the documentation of this file.
1 #ifndef NDNPH_KEYCHAIN_EC_HPP
2 #define NDNPH_KEYCHAIN_EC_HPP
3 
4 #include "../port/ec/port.hpp"
5 #include "certificate.hpp"
6 #include "keychain.hpp"
7 
8 namespace ndnph {
9 namespace ec {
10 namespace detail {
11 
12 using namespace ndnph::detail;
13 
16 
18 inline tlv::Value
20  static const uint8_t bytes[] = {
21  0x30, 0x59, // SEQUENCE
22  0x30, 0x13, // . SEQUENCE
23  0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, // .. OID ecPublicKey
24  0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, // .. OID prime256v1
25  0x03, 0x42, 0x00 // . BIT STRING
26  };
27  static const tlv::Value value(bytes, sizeof(bytes));
28  return value;
29 }
30 
32 inline tlv::Value
33 getOid() {
34  static const tlv::Value value(getSpkiHeader().begin() + 4, 9);
35  return value;
36 }
37 
42 inline const uint8_t*
44  if (!certificate::isCertificate(data)) {
45  return nullptr;
46  }
47 
48  auto content = data.getContent();
49  if (content.size() < PubLen::value) {
50  return nullptr;
51  }
52 
53  auto oid = getOid();
54  auto found = std::search(content.begin(), content.end(), oid.begin(), oid.end());
55  if (found == content.end()) {
56  return nullptr;
57  }
58 
59  return content.end() - PubLen::value;
60 }
61 
62 } // namespace detail
63 
65 class EcPublicKey : public detail::NamedPublicKey<SigType::Sha256WithEcdsa> {
66 public:
68 
70  explicit operator bool() const {
71  return m_key != nullptr;
72  }
73 
80  bool import(const Name& name, const uint8_t raw[KeyLen::value]) {
81  if (!certificate::isKeyName(name)) {
82  return false;
83  }
84 
85  m_key.reset(new port::Ec::PublicKey());
86  if (!m_key->import(raw)) {
87  m_key.reset();
88  return false;
89  }
90 
91  setName(name);
92  std::copy_n(raw, sizeof(m_raw), m_raw);
93  return true;
94  }
95 
102  bool import(Region& region, const Data& data) {
103  const uint8_t* raw = detail::findPublicKeyInCertificate(data);
104  if (raw == nullptr) {
105  return false;
106  }
107 
108  Name name = certificate::toKeyName(region, data.getName());
109  if (!name) {
110  return false;
111  }
112 
113  return import(name, raw);
114  }
115 
126  template<typename Signer>
127  Data::Signed buildCertificate(Region& region, const Name& name, const ValidityPeriod& validity,
128  const Signer& signer) const {
129  return detail::buildCertificate(region, name, validity, signer, [&](Data& data) {
130  auto spkiHdr = detail::getSpkiHeader();
131  size_t spkiLen = spkiHdr.size() + KeyLen::value;
132  uint8_t* spki = region.alloc(spkiLen);
133  if (spki == nullptr) {
134  return false;
135  }
136 
137  auto pos = std::copy_n(spkiHdr.begin(), spkiHdr.size(), spki);
138  std::copy_n(m_raw, KeyLen::value, pos);
139  data.setContent(tlv::Value(spki, spkiLen));
140  return true;
141  });
142  }
143 
153  template<typename Signer>
154  Data::Signed selfSign(Region& region, const ValidityPeriod& validity,
155  const Signer& signer) const {
156  Name certName = certificate::makeCertName(region, getName(), certificate::getIssuerSelf());
157  return buildCertificate(region, certName, validity, signer);
158  }
159 
165  bool verify(std::initializer_list<tlv::Value> chunks, const uint8_t* sig,
166  size_t sigLen) const final {
167  if (m_key == nullptr) {
168  return false;
169  }
170  uint8_t digest[NDNPH_SHA256_LEN];
171  return detail::computeDigest(chunks, digest) && m_key->verify(digest, sig, sigLen);
172  }
173 
174 private:
175  std::unique_ptr<port::Ec::PublicKey> m_key;
176  uint8_t m_raw[KeyLen::value];
177 };
178 
180 class EcPrivateKey : public detail::NamedPrivateKey<SigType::Sha256WithEcdsa> {
181 public:
183  using MaxSigLen = port::Ec::Curve::MaxSigLen;
184 
186  explicit operator bool() const {
187  return m_key != nullptr;
188  }
189 
194  bool import(const Name& name, const uint8_t raw[KeyLen::value]) {
195  if (!certificate::isKeyName(name)) {
196  return false;
197  }
198 
199  m_key.reset(new port::Ec::PrivateKey());
200  if (!m_key->import(raw)) {
201  m_key.reset();
202  return false;
203  }
204 
205  setName(name);
206  return true;
207  }
208 
209  size_t getMaxSigLen() const final {
210  return MaxSigLen::value;
211  }
212 
213  ssize_t sign(std::initializer_list<tlv::Value> chunks, uint8_t* sig) const final {
214  if (m_key == nullptr) {
215  return -1;
216  }
217  uint8_t digest[NDNPH_SHA256_LEN];
218  if (!detail::computeDigest(chunks, digest)) {
219  return -1;
220  }
221  return m_key->sign(digest, sig);
222  }
223 
224 private:
225  std::unique_ptr<port::Ec::PrivateKey> m_key;
226 };
227 
232 inline bool
233 generateRaw(uint8_t pvt[EcPrivateKey::KeyLen::value], uint8_t pub[EcPublicKey::KeyLen::value]) {
234  return port::Ec::generateKey(pvt, pub);
235 }
236 
237 namespace detail {
238 
241  uint8_t pvt[PvtLen::value];
242  uint8_t pub[PubLen::value];
243 };
244 
245 inline bool
246 generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub, KeyChain* keyChain,
247  const char* id) {
248  Name keyName = certificate::toKeyName(region, name, true);
249  if (!keyName) {
250  return false;
251  }
252 
253  ScopedEncoder encoder(region);
254  encoder.prepend(keyName);
255  auto stored = reinterpret_cast<StoredKeyPair*>(encoder.prependRoom(sizeof(StoredKeyPair)));
256  bool ok = stored != nullptr && generateRaw(stored->pvt, stored->pub) &&
257  pvt.import(keyName, stored->pvt) && pub.import(keyName, stored->pub);
258 
259  if (keyChain != nullptr) {
260  ok = ok && keyChain->keys.set(id, tlv::Value(encoder));
261  }
262  return ok;
263 }
264 
265 } // namespace detail
266 
275 inline bool
276 generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub) {
277  return detail::generate(region, name, pvt, pub, nullptr, nullptr);
278 }
279 
290 inline bool
291 generate(Region& region, const Name& name, EcPrivateKey& pvt, EcPublicKey& pub, KeyChain& keyChain,
292  const char* id) {
293  return detail::generate(region, name, pvt, pub, &keyChain, id);
294 }
295 
300 inline bool
301 load(KeyChain& keyChain, const char* id, Region& region, EcPrivateKey& pvt, EcPublicKey& pub) {
302  tlv::Value storedObject = keyChain.keys.get(id, region);
303  if (storedObject.size() < sizeof(detail::StoredKeyPair)) {
304  return false;
305  }
306  auto stored = reinterpret_cast<const detail::StoredKeyPair*>(storedObject.begin());
307  Name name;
308  Decoder decoder(storedObject.begin() + sizeof(detail::StoredKeyPair),
309  storedObject.size() - sizeof(detail::StoredKeyPair));
310  return decoder.decode(name) && pvt.import(name, stored->pvt) && pub.import(name, stored->pub);
311 }
312 
318 inline bool
319 isCertificate(const Data& data) {
320  return detail::findPublicKeyInCertificate(data) != nullptr;
321 }
322 
323 } // namespace ec
324 
327 
328 } // namespace ndnph
329 
330 #endif // NDNPH_KEYCHAIN_EC_HPP
Data packet.
Definition: data.hpp:136
void setContent(tlv::Value v)
Definition: data.hpp:176
tlv::Value getContent() const
Definition: data.hpp:172
TLV decoder.
Definition: decoder.hpp:10
bool decode(T &target) const
Decode first TLV into target object.
Definition: decoder.hpp:158
bool prepend(const First &first, const Arg &... arg)
Prepend a sequence of values.
Definition: encoder.hpp:123
uint8_t * prependRoom(size_t size)
Make room to prepend an object.
Definition: encoder.hpp:90
File based key and certificate store.
Definition: keychain.hpp:36
KeyChainKeys keys
Definition: keychain.hpp:51
tlv::Value get(const char *key, Region &region)
Retrieve a value.
Definition: kv.hpp:38
bool set(const char *key, tlv::Value value)
Store a value.
Definition: kv.hpp:69
Name.
Definition: name.hpp:14
Region-based memory allocator thats owns memory of NDNph objects.
Definition: region.hpp:9
uint8_t * alloc(size_t size)
Allocate a buffer with no alignment requirement.
Definition: region.hpp:27
Encoder that auto-discards upon destruction.
Definition: encoder.hpp:198
ValidityPeriod of a certificate.
Definition: validity-period.hpp:37
Definition: helper.hpp:64
Definition: helper.hpp:54
Definition: data.hpp:42
EC private key.
Definition: ec.hpp:180
bool import(const Name &name, const uint8_t raw[KeyLen::value])
Import a private key from raw key bits.
Definition: ec.hpp:194
detail::PvtLen KeyLen
Definition: ec.hpp:182
ssize_t sign(std::initializer_list< tlv::Value > chunks, uint8_t *sig) const final
Perform signing.
Definition: ec.hpp:213
size_t getMaxSigLen() const final
Definition: ec.hpp:209
port::Ec::Curve::MaxSigLen MaxSigLen
Definition: ec.hpp:183
EC public key.
Definition: ec.hpp:65
Data::Signed buildCertificate(Region &region, const Name &name, const ValidityPeriod &validity, const Signer &signer) const
Generate certificate of this public key.
Definition: ec.hpp:127
bool verify(std::initializer_list< tlv::Value > chunks, const uint8_t *sig, size_t sigLen) const final
Perform verification.
Definition: ec.hpp:165
detail::PubLen KeyLen
Definition: ec.hpp:67
bool import(const Name &name, const uint8_t raw[KeyLen::value])
Import from raw key bits.
Definition: ec.hpp:80
Data::Signed selfSign(Region &region, const ValidityPeriod &validity, const Signer &signer) const
Generate self-signed certificate of this public key.
Definition: ec.hpp:154
A sequence of bytes, usually TLV-VALUE.
Definition: value.hpp:11
const uint8_t * begin() const
Definition: value.hpp:38
size_t size() const
Definition: value.hpp:46
#define NDNPH_SHA256_LEN
SHA256 digest length.
Definition: common.hpp:34
bool isCertificate(const Data &data)
Determine if the Data packet is a certificate.
Definition: certificate.hpp:170
bool isKeyName(const Name &name)
Determine if the input is a key name.
Definition: certificate.hpp:37
Component getIssuerSelf()
Return 'self' component as self-signed issuerId.
Definition: certificate.hpp:29
Name toKeyName(Region &region, const Name &input, bool mustCopy=false)
Convert to key name.
Definition: certificate.hpp:82
Name makeCertName(Region &region, const Name &input, const Component &issuerId, const Component &version)
Construct certificate name with specified issuerId and version.
Definition: certificate.hpp:149
Definition: input-iterator-pointer-proxy.hpp:5
Data::Signed buildCertificate(Region &region, const Name &name, const ValidityPeriod &validity, const Signer &signer, const Modify &modify)
Definition: certificate.hpp:207
bool computeDigest(std::initializer_list< tlv::Value > chunks, uint8_t digest[NDNPH_SHA256_LEN])
Definition: helper.hpp:15
port::Ec::Curve::PvtLen PvtLen
Definition: ec.hpp:14
bool generate(Region &region, const Name &name, EcPrivateKey &pvt, EcPublicKey &pub, KeyChain *keyChain, const char *id)
Definition: ec.hpp:246
const uint8_t * findPublicKeyInCertificate(const Data &data)
Extract raw public key from a certificate.
Definition: ec.hpp:43
port::Ec::Curve::PubLen PubLen
Definition: ec.hpp:15
tlv::Value getSpkiHeader()
Return EC P-256 SPKI except the key.
Definition: ec.hpp:19
tlv::Value getOid()
Return '1.2.840.10045.2.1 ecPublicKey' OID bytes.
Definition: ec.hpp:33
bool generateRaw(uint8_t pvt[EcPrivateKey::KeyLen::value], uint8_t pub[EcPublicKey::KeyLen::value])
Generate key pair in raw format.
Definition: ec.hpp:233
bool isCertificate(const Data &data)
Determine if the Data packet is a certificate that contains an EC public key.
Definition: ec.hpp:319
bool load(KeyChain &keyChain, const char *id, Region &region, EcPrivateKey &pvt, EcPublicKey &pub)
Load key pair from KeyChain.
Definition: ec.hpp:301
Definition: fs.hpp:33
ec::EcPrivateKey EcPrivateKey
Definition: ec.hpp:326
ec::EcPublicKey EcPublicKey
Definition: ec.hpp:325
Key pair stored in KeyChain.
Definition: ec.hpp:240