blob: 44f0d0b950a1f356d54beae7a48fa0876fe6dd4a [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompson41471912013-09-12 16:21:50 -07002/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07003 * Copyright (C) 2013 Regents of the University of California.
Jeff Thompson06e787d2013-09-12 19:00:55 -07004 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
Jeff Thompson7687dc02013-09-13 11:54:07 -07005 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompson41471912013-09-12 16:21:50 -07006 * See COPYING for copyright and distribution information.
7 */
8
Jeff Thompsond63baba2013-10-18 17:47:58 -07009#include <ndn-cpp/ndn-cpp-config.h>
10#if NDN_CPP_HAVE_TIME_H
11#include <time.h>
12#endif
13#if NDN_CPP_HAVE_SYS_TIME_H
14#include <sys/time.h>
15#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -070016#include <ctime>
17#include <fstream>
Jeff Thompsondb686892013-10-18 17:16:31 -070018#include <math.h>
Jeff Thompson71b2f872013-12-17 12:03:17 -080019#include <ndn-cpp/key-locator.hpp>
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080020
Jeff Thompsonc69163b2013-10-12 13:49:50 -070021#include "../../util/logging.hpp"
Jeff Thompsondb686892013-10-18 17:16:31 -070022#include "../../c/util/time.h"
Jeff Thompson25b4e612013-10-10 16:03:24 -070023#include <ndn-cpp/security/identity/identity-manager.hpp>
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080024#include <ndn-cpp/security/certificate/identity-certificate.hpp>
25#include <ndn-cpp/security/signature/signature-sha256-with-rsa.hpp>
Jeff Thompson41471912013-09-12 16:21:50 -070026
Jeff Thompsonc69163b2013-10-12 13:49:50 -070027INIT_LOGGER("ndn.security.IdentityManager")
28
Jeff Thompson9296f0c2013-09-23 18:10:27 -070029using namespace std;
Jeff Thompson41471912013-09-12 16:21:50 -070030
Jeff Thompson9296f0c2013-09-23 18:10:27 -070031namespace ndn {
Jeff Thompson86e1d752013-09-17 17:22:38 -070032
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080033IdentityManager::IdentityManager(const ptr_lib::shared_ptr<IdentityStorage> &identityStorage /* = DefaultIdentityStorage */,
34 const ptr_lib::shared_ptr<PrivateKeyStorage> &privateKeyStorage /* = DefaultPrivateKeyStorage */)
35 : identityStorage_(identityStorage)
36 , privateKeyStorage_(privateKeyStorage)
37{
38}
39
Jeff Thompsone7e069b2013-09-27 15:48:48 -070040Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070041IdentityManager::createIdentity(const Name& identityName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -070042{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080043 if (!info().doesIdentityExist(identityName)) {
44 _LOG_DEBUG("Create Identity");
45 info().addIdentity(identityName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070046
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080047 _LOG_DEBUG("Create Default RSA key pair");
48 Name keyName = generateRSAKeyPairAsDefault(identityName, true);
Jeff Thompsone7e069b2013-09-27 15:48:48 -070049
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080050 _LOG_DEBUG("Create self-signed certificate");
51 ptr_lib::shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070052
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080053 _LOG_DEBUG("Add self-signed certificate as default");
Jeff Thompsone7e069b2013-09-27 15:48:48 -070054
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080055 addCertificateAsDefault(*selfCert);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070056
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080057 return keyName;
Jeff Thompsone7e069b2013-09-27 15:48:48 -070058 }
59 else
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080060 throw Error("Identity has already been created!");
Jeff Thompsone7e069b2013-09-27 15:48:48 -070061}
62
63Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070064IdentityManager::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
65{
66 _LOG_DEBUG("Get new key ID");
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080067 Name keyName = info().getNewKeyName(identityName, isKsk);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070068
69 _LOG_DEBUG("Generate key pair in private storage");
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080070 tpm().generateKeyPair(keyName.toUri(), keyType, keySize);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070071
72 _LOG_DEBUG("Create a key record in public storage");
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080073 ptr_lib::shared_ptr<PublicKey> pubKey = tpm().getPublicKey(keyName.toUri());
74 info().addKey(keyName, keyType, *pubKey);
Jeff Thompson418b05a2013-10-22 17:48:54 -070075
Jeff Thompsonc69163b2013-10-12 13:49:50 -070076 return keyName;
77}
78
79Name
Jeff Thompsone7e069b2013-09-27 15:48:48 -070080IdentityManager::generateRSAKeyPair(const Name& identityName, bool isKsk, int keySize)
81{
82 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompson418b05a2013-10-22 17:48:54 -070083
Jeff Thompsone7e069b2013-09-27 15:48:48 -070084 return keyName;
85}
86
87Name
88IdentityManager::generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
89{
Alexander Afanasyeve64788e2014-01-05 22:38:21 -080090 defaultCertificate_.reset();
91
Jeff Thompsone7e069b2013-09-27 15:48:48 -070092 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070093
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080094 info().setDefaultKeyNameForIdentity(keyName, identityName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -070095
Jeff Thompsonc69163b2013-10-12 13:49:50 -070096 return keyName;
97}
98
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -080099ptr_lib::shared_ptr<IdentityCertificate>
Jeff Thompson418b05a2013-10-22 17:48:54 -0700100IdentityManager::createIdentityCertificate(const Name& certificatePrefix,
101 const Name& signerCertificateName,
102 const MillisecondsSince1970& notBefore,
103 const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700104{
Jeff Thompson418b05a2013-10-22 17:48:54 -0700105 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800106
107 ptr_lib::shared_ptr<PublicKey> pubKey = info().getKey(keyName);
108 if (!pubKey)
109 throw Error("Requested public key [" + keyName.toUri() + "] doesn't exist");
Jeff Thompson418b05a2013-10-22 17:48:54 -0700110
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800111 ptr_lib::shared_ptr<IdentityCertificate> certificate =
112 createIdentityCertificate(certificatePrefix,
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800113 *pubKey,
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800114 signerCertificateName,
115 notBefore, notAfter);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700116
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800117 info().addCertificate(*certificate);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700118
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800119 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700120}
121
122ptr_lib::shared_ptr<IdentityCertificate>
Jeff Thompson418b05a2013-10-22 17:48:54 -0700123IdentityManager::createIdentityCertificate(const Name& certificatePrefix,
124 const PublicKey& publicKey,
125 const Name& signerCertificateName,
126 const MillisecondsSince1970& notBefore,
127 const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700128{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800129 ptr_lib::shared_ptr<IdentityCertificate> certificate (new IdentityCertificate());
Jeff Thompson418b05a2013-10-22 17:48:54 -0700130 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700131
Jeff Thompson418b05a2013-10-22 17:48:54 -0700132 Name certificateName = certificatePrefix;
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800133 certificateName.append("ID-CERT").appendVersion();
Jeff Thompson418b05a2013-10-22 17:48:54 -0700134
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700135 certificate->setName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700136 certificate->setNotBefore(notBefore);
137 certificate->setNotAfter(notAfter);
138 certificate->setPublicKeyInfo(publicKey);
Jeff Thompsondb686892013-10-18 17:16:31 -0700139 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700140 certificate->encode();
141
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800142 signByCertificate(*certificate, signerCertificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700143
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800144 return certificate;
145}
146
147ptr_lib::shared_ptr<IdentityCertificate>
148IdentityManager::selfSign(const Name& keyName)
149{
150 ptr_lib::shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700151
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800152 Name certificateName = keyName.getSubName(0, keyName.size() - 1);
153 certificateName.append("KEY").append(keyName.get(keyName.size() - 1)).append("ID-CERT").appendVersion();
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800154
155 ptr_lib::shared_ptr<PublicKey> pubKey = info().getKey(keyName);
156 if (!pubKey)
157 throw Error("Requested public key [" + keyName.toUri() + "] doesn't exist");
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800158
159 certificate->setName(certificateName);
160 certificate->setNotBefore(ndn_getNowMilliseconds());
161 certificate->setNotAfter(ndn_getNowMilliseconds() + 630720000 /* 20 years*/);
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800162 certificate->setPublicKeyInfo(*pubKey);
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800163 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
164 certificate->encode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700165
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800166 selfSign(*certificate);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700167 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700168}
169
170void
171IdentityManager::addCertificateAsDefault(const IdentityCertificate& certificate)
172{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800173 info().addCertificate(certificate);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700174
Jeff Thompson418b05a2013-10-22 17:48:54 -0700175 setDefaultCertificateForKey(certificate);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700176}
177
178void
Jeff Thompson418b05a2013-10-22 17:48:54 -0700179IdentityManager::addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700180{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800181 info().addCertificate(certificate);
Jeff Thompson418b05a2013-10-22 17:48:54 -0700182
183 Name keyName = certificate.getPublicKeyName();
184
185 setDefaultKeyForIdentity(keyName);
186
187 setDefaultCertificateForKey(certificate);
188}
189
190void
191IdentityManager::setDefaultCertificateForKey(const IdentityCertificate& certificate)
192{
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800193 defaultCertificate_.reset();
194
Jeff Thompson418b05a2013-10-22 17:48:54 -0700195 Name keyName = certificate.getPublicKeyName();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700196
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800197 if(!info().doesKeyExist(keyName))
198 throw Error("No corresponding Key record for certificate!");
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700199
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800200 info().setDefaultCertificateNameForKey(keyName, certificate.getName());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700201}
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800202
203void
204IdentityManager::sign(Data &data)
205{
206 if (!defaultCertificate_)
207 {
208 defaultCertificate_ = info().getCertificate(
209 info().getDefaultCertificateNameForIdentity(
210 info().getDefaultIdentity()));
211
212 if(!defaultCertificate_)
213 throw Error("Default IdentityCertificate cannot be determined");
214 }
215
216 signByCertificate(data, *defaultCertificate_);
217}
218
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800219Signature
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700220IdentityManager::signByCertificate(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
Jeff Thompson74942612013-10-24 16:42:32 -0700221{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800222 ptr_lib::shared_ptr<IdentityCertificate> cert = info().getCertificate(certificateName);
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800223 if (!cert)
224 throw Error("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
225
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800226 SignatureSha256WithRsa signature;
227 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800228
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800229 // For temporary usage, we support RSA + SHA256 only, but will support more.
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800230 signature.setValue
231 (tpm().sign(buffer, bufferLength, cert->getPublicKeyName(), DIGEST_ALGORITHM_SHA256));
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800232 return signature;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700233}
234
235void
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800236IdentityManager::signByCertificate(Data &data, const Name &certificateName)
Jeff Thompson41471912013-09-12 16:21:50 -0700237{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800238 ptr_lib::shared_ptr<IdentityCertificate> cert = info().getCertificate(certificateName);
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800239 if (!cert)
240 throw Error("Requested certificate [" + certificateName.toUri() + "] doesn't exist");
241
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800242 SignatureSha256WithRsa signature;
243 signature.setKeyLocator(certificateName.getPrefix(-1)); // implicit conversion should take care
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800244 data.setSignature(signature);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700245
246 // For temporary usage, we support RSA + SHA256 only, but will support more.
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800247 tpm().sign(data, cert->getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Jeff Thompson41471912013-09-12 16:21:50 -0700248}
249
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800250void
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800251IdentityManager::signByCertificate(Data& data, const IdentityCertificate& certificate)
252{
253 SignatureSha256WithRsa signature;
254 signature.setKeyLocator(certificate.getName().getPrefix(-1));
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800255 data.setSignature(signature);
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800256
257 // For temporary usage, we support RSA + SHA256 only, but will support more.
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800258 tpm().sign(data, certificate.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Alexander Afanasyeve64788e2014-01-05 22:38:21 -0800259}
260
261void
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800262IdentityManager::selfSign (IdentityCertificate& cert)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700263{
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800264 SignatureSha256WithRsa signature;
265 signature.setKeyLocator(cert.getName().getPrefix(cert.getName().size()-1)); // implicit conversion should take care
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800266 cert.setSignature(signature);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700267
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800268 // For temporary usage, we support RSA + SHA256 only, but will support more.
Alexander Afanasyev04b22a92014-01-05 22:40:17 -0800269 tpm().sign(cert, cert.getPublicKeyName(), DIGEST_ALGORITHM_SHA256);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700270}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700271
Jeff Thompson418b05a2013-10-22 17:48:54 -0700272Name
273IdentityManager::getKeyNameFromCertificatePrefix(const Name & certificatePrefix)
274{
275 Name result;
276
277 string keyString("KEY");
278 int i = 0;
279 for(; i < certificatePrefix.size(); i++) {
280 if (certificatePrefix.get(i).toEscapedString() == keyString)
281 break;
282 }
283
284 if (i >= certificatePrefix.size())
Alexander Afanasyevbf1a67a2014-01-05 23:36:13 -0800285 throw Error("Identity Certificate Prefix does not have a KEY component");
Jeff Thompson418b05a2013-10-22 17:48:54 -0700286
287 result.append(certificatePrefix.getSubName(0, i));
288 result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1));
289
290 return result;
291}
292
Jeff Thompson41471912013-09-12 16:21:50 -0700293}