blob: 88e67824ed9dbc7cfeb3b39113b0cea923d4d216 [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>
Jeff Thompson25b4e612013-10-10 16:03:24 -070020#include <ndn-cpp/sha256-with-rsa-signature.hpp>
21#include <ndn-cpp/security/security-exception.hpp>
Jeff Thompsonc69163b2013-10-12 13:49:50 -070022#include "../../util/logging.hpp"
Jeff Thompsondb686892013-10-18 17:16:31 -070023#include "../../c/util/time.h"
Jeff Thompson25b4e612013-10-10 16:03:24 -070024#include <ndn-cpp/security/identity/identity-manager.hpp>
Jeff Thompson41471912013-09-12 16:21:50 -070025
Jeff Thompsonc69163b2013-10-12 13:49:50 -070026INIT_LOGGER("ndn.security.IdentityManager")
27
Jeff Thompson9296f0c2013-09-23 18:10:27 -070028using namespace std;
Jeff Thompson41471912013-09-12 16:21:50 -070029
Jeff Thompson9296f0c2013-09-23 18:10:27 -070030namespace ndn {
Jeff Thompson86e1d752013-09-17 17:22:38 -070031
Jeff Thompsone7e069b2013-09-27 15:48:48 -070032Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070033IdentityManager::createIdentity(const Name& identityName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -070034{
35 if (!identityStorage_->doesIdentityExist(identityName)) {
Jeff Thompsonc69163b2013-10-12 13:49:50 -070036 _LOG_DEBUG("Create Identity");
37 identityStorage_->addIdentity(identityName);
38
39 _LOG_DEBUG("Create Default RSA key pair");
40 Name keyName = generateRSAKeyPairAsDefault(identityName, true);
Jeff Thompsone7e069b2013-09-27 15:48:48 -070041
Jeff Thompsonc69163b2013-10-12 13:49:50 -070042 _LOG_DEBUG("Create self-signed certificate");
Jeff Thompsonce115762013-12-18 14:59:56 -080043 ptr_lib::shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070044
45 _LOG_DEBUG("Add self-signed certificate as default");
Jeff Thompsone7e069b2013-09-27 15:48:48 -070046
Jeff Thompsonc69163b2013-10-12 13:49:50 -070047 addCertificateAsDefault(*selfCert);
48
49 return keyName;
Jeff Thompsone7e069b2013-09-27 15:48:48 -070050 }
51 else
52 throw SecurityException("Identity has already been created!");
53}
54
55Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070056IdentityManager::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
57{
58 _LOG_DEBUG("Get new key ID");
59 Name keyName = identityStorage_->getNewKeyName(identityName, isKsk);
60
61 _LOG_DEBUG("Generate key pair in private storage");
62 privateKeyStorage_->generateKeyPair(keyName.toUri(), keyType, keySize);
63
64 _LOG_DEBUG("Create a key record in public storage");
Jeff Thompsonce115762013-12-18 14:59:56 -080065 ptr_lib::shared_ptr<PublicKey> pubKey = privateKeyStorage_->getPublicKey(keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -070066 identityStorage_->addKey(keyName, keyType, pubKey->getKeyDer());
Jeff Thompson418b05a2013-10-22 17:48:54 -070067
Jeff Thompsonc69163b2013-10-12 13:49:50 -070068 return keyName;
69}
70
71Name
Jeff Thompsone7e069b2013-09-27 15:48:48 -070072IdentityManager::generateRSAKeyPair(const Name& identityName, bool isKsk, int keySize)
73{
74 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompson418b05a2013-10-22 17:48:54 -070075
Jeff Thompsone7e069b2013-09-27 15:48:48 -070076 return keyName;
77}
78
79Name
80IdentityManager::generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
81{
82 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070083
Jeff Thompsone7e069b2013-09-27 15:48:48 -070084 identityStorage_->setDefaultKeyNameForIdentity(keyName, identityName);
85
Jeff Thompsonc69163b2013-10-12 13:49:50 -070086 return keyName;
87}
88
89Name
Jeff Thompson418b05a2013-10-22 17:48:54 -070090IdentityManager::createIdentityCertificate(const Name& certificatePrefix,
91 const Name& signerCertificateName,
92 const MillisecondsSince1970& notBefore,
93 const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -070094{
Jeff Thompson418b05a2013-10-22 17:48:54 -070095 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
96
Jeff Thompsonc69163b2013-10-12 13:49:50 -070097 Blob keyBlob = identityStorage_->getKey(keyName);
Jeff Thompsonce115762013-12-18 14:59:56 -080098 ptr_lib::shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070099
Jeff Thompsonce115762013-12-18 14:59:56 -0800100 ptr_lib::shared_ptr<IdentityCertificate> certificate = createIdentityCertificate
Jeff Thompson418b05a2013-10-22 17:48:54 -0700101 (certificatePrefix, *publicKey, signerCertificateName, notBefore, notAfter);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700102
103 identityStorage_->addCertificate(*certificate);
104
105 return certificate->getName();
106}
107
108ptr_lib::shared_ptr<IdentityCertificate>
Jeff Thompson418b05a2013-10-22 17:48:54 -0700109IdentityManager::createIdentityCertificate(const Name& certificatePrefix,
110 const PublicKey& publicKey,
111 const Name& signerCertificateName,
112 const MillisecondsSince1970& notBefore,
113 const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700114{
Jeff Thompsonce115762013-12-18 14:59:56 -0800115 ptr_lib::shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompson418b05a2013-10-22 17:48:54 -0700116 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700117
Jeff Thompson418b05a2013-10-22 17:48:54 -0700118 Name certificateName = certificatePrefix;
Jeff Thompsondb686892013-10-18 17:16:31 -0700119 MillisecondsSince1970 ti = ::ndn_getNowMilliseconds();
120 // Get the number of seconds.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700121 ostringstream oss;
Jeff Thompsondb686892013-10-18 17:16:31 -0700122 oss << floor(ti / 1000.0);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700123
Jeff Thompson418b05a2013-10-22 17:48:54 -0700124 certificateName.append("ID-CERT").append(oss.str());
125
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700126 certificate->setName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700127 certificate->setNotBefore(notBefore);
128 certificate->setNotAfter(notAfter);
129 certificate->setPublicKeyInfo(publicKey);
Jeff Thompsondb686892013-10-18 17:16:31 -0700130 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700131 certificate->encode();
132
Jeff Thompsonce115762013-12-18 14:59:56 -0800133 ptr_lib::shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700134
135 KeyLocator keyLocator;
Jeff Thompsondb686892013-10-18 17:16:31 -0700136 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700137 keyLocator.setKeyName(signerCertificateName);
138
139 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700140 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey.getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700141
Jeff Thompsondb686892013-10-18 17:16:31 -0700142 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700143
Jeff Thompsondb686892013-10-18 17:16:31 -0700144 SignedBlob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700145
Jeff Thompsonce115762013-12-18 14:59:56 -0800146 ptr_lib::shared_ptr<IdentityCertificate> signerCertificate = getCertificate(signerCertificateName);
Jeff Thompson418b05a2013-10-22 17:48:54 -0700147 Name signerkeyName = signerCertificate->getPublicKeyName();
148
149 Blob sigBits = privateKeyStorage_->sign(unsignedData, signerkeyName);
150
Jeff Thompsonba82c162013-10-18 17:21:23 -0700151 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700152
153 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700154}
155
156void
157IdentityManager::addCertificateAsDefault(const IdentityCertificate& certificate)
158{
159 identityStorage_->addCertificate(certificate);
160
Jeff Thompson418b05a2013-10-22 17:48:54 -0700161 setDefaultCertificateForKey(certificate);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700162}
163
164void
Jeff Thompson418b05a2013-10-22 17:48:54 -0700165IdentityManager::addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700166{
Jeff Thompson418b05a2013-10-22 17:48:54 -0700167 identityStorage_->addCertificate(certificate);
168
169 Name keyName = certificate.getPublicKeyName();
170
171 setDefaultKeyForIdentity(keyName);
172
173 setDefaultCertificateForKey(certificate);
174}
175
176void
177IdentityManager::setDefaultCertificateForKey(const IdentityCertificate& certificate)
178{
179 Name keyName = certificate.getPublicKeyName();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700180
181 if(!identityStorage_->doesKeyExist(keyName))
Jeff Thompson418b05a2013-10-22 17:48:54 -0700182 throw SecurityException("No corresponding Key record for certificate!");
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700183
Jeff Thompson418b05a2013-10-22 17:48:54 -0700184 identityStorage_->setDefaultCertificateNameForKey(keyName, certificate.getName());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700185}
186
187ptr_lib::shared_ptr<Signature>
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700188IdentityManager::signByCertificate(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
Jeff Thompson74942612013-10-24 16:42:32 -0700189{
190 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
Jeff Thompsonce115762013-12-18 14:59:56 -0800191 ptr_lib::shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700192
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700193 Blob sigBits = privateKeyStorage_->sign(buffer, bufferLength, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700194
195 //For temporary usage, we support RSA + SHA256 only, but will support more.
Jeff Thompsonce115762013-12-18 14:59:56 -0800196 ptr_lib::shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700197
198 KeyLocator keyLocator;
Jeff Thompsonba82c162013-10-18 17:21:23 -0700199 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
200 keyLocator.setKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700201
202 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700203 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonba82c162013-10-18 17:21:23 -0700204 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700205
206 return sha256Sig;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700207}
208
209void
Jeff Thompson86e1d752013-09-17 17:22:38 -0700210IdentityManager::signByCertificate(Data &data, const Name &certificateName, WireFormat& wireFormat)
Jeff Thompson41471912013-09-12 16:21:50 -0700211{
Jeff Thompson74942612013-10-24 16:42:32 -0700212 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
Jeff Thompsonce115762013-12-18 14:59:56 -0800213 ptr_lib::shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700214
215 // For temporary usage, we support RSA + SHA256 only, but will support more.
216 data.setSignature(Sha256WithRsaSignature());
217 // Get a pointer to the clone which Data made.
218 Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(data.getSignature());
219 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256;
220
221 signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompson40ada912013-12-17 11:36:27 -0800222 signature->getKeyLocator().setKeyName(certificateName.getPrefix(-1));
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700223 // Omit the certificate digest.
224 signature->getKeyLocator().setKeyNameType((ndn_KeyNameType)-1);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700225 // Ignore witness and leave the digestAlgorithm as the default.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700226 signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompson41471912013-09-12 16:21:50 -0700227
Jeff Thompson86e1d752013-09-17 17:22:38 -0700228 // Encode once to get the signed portion.
229 SignedBlob encoding = data.wireEncode(wireFormat);
230
231 signature->setSignature
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700232 (privateKeyStorage_->sign(encoding.signedBuf(), encoding.signedSize(), keyName, digestAlgorithm));
Jeff Thompson86e1d752013-09-17 17:22:38 -0700233
234 // Encode again to include the signature.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700235 data.wireEncode(wireFormat);
Jeff Thompson41471912013-09-12 16:21:50 -0700236}
237
Jeff Thompsonce115762013-12-18 14:59:56 -0800238ptr_lib::shared_ptr<IdentityCertificate>
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700239IdentityManager::selfSign(const Name& keyName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700240{
Jeff Thompsonce115762013-12-18 14:59:56 -0800241 ptr_lib::shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700242
Jeff Thompson418b05a2013-10-22 17:48:54 -0700243 Name certificateName = keyName.getSubName(0, keyName.size() - 1);
244 certificateName.append("KEY").append(keyName.get(keyName.size() - 1)).append("ID-CERT").append("0");
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700245 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700246
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700247 Blob keyBlob = identityStorage_->getKey(keyName);
Jeff Thompsonce115762013-12-18 14:59:56 -0800248 ptr_lib::shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700249
Jeff Thompsond63baba2013-10-18 17:47:58 -0700250#if NDN_CPP_HAVE_GMTIME_SUPPORT
251 time_t nowSeconds = time(NULL);
252 struct tm current = *gmtime(&nowSeconds);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700253 current.tm_hour = 0;
254 current.tm_min = 0;
255 current.tm_sec = 0;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700256 MillisecondsSince1970 notBefore = timegm(&current) * 1000.0;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700257 current.tm_year = current.tm_year + 20;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700258 MillisecondsSince1970 notAfter = timegm(&current) * 1000.0;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700259
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700260 certificate->setNotBefore(notBefore);
261 certificate->setNotAfter(notAfter);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700262#else
263 // Don't really expect this to happen.
264 throw SecurityException("selfSign: Can't set certificate validity because time functions are not supported by the standard library.");
265#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700266 certificate->setPublicKeyInfo(*publicKey);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700267 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700268 certificate->encode();
269
Jeff Thompsonce115762013-12-18 14:59:56 -0800270 ptr_lib::shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700271
272 KeyLocator keyLocator;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700273 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700274 keyLocator.setKeyName(certificateName);
275
276 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700277 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700278
Jeff Thompsond63baba2013-10-18 17:47:58 -0700279 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700280
Jeff Thompsond63baba2013-10-18 17:47:58 -0700281 Blob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700282
Jeff Thompsond63baba2013-10-18 17:47:58 -0700283 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700284
Jeff Thompsond63baba2013-10-18 17:47:58 -0700285 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700286
287 return certificate;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700288}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700289
Jeff Thompson418b05a2013-10-22 17:48:54 -0700290Name
291IdentityManager::getKeyNameFromCertificatePrefix(const Name & certificatePrefix)
292{
293 Name result;
294
295 string keyString("KEY");
296 int i = 0;
297 for(; i < certificatePrefix.size(); i++) {
298 if (certificatePrefix.get(i).toEscapedString() == keyString)
299 break;
300 }
301
302 if (i >= certificatePrefix.size())
303 throw SecurityException("Identity Certificate Prefix does not have a KEY component");
304
305 result.append(certificatePrefix.getSubName(0, i));
306 result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1));
307
308 return result;
309}
310
Jeff Thompson41471912013-09-12 16:21:50 -0700311}