blob: 6ee30828353cc93ca52005350d9b06047473b54b [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 Thompsonc69163b2013-10-12 13:49:50 -070019#include <ndn-cpp/key.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;
29using namespace ndn::ptr_lib;
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
Jeff Thompsone7e069b2013-09-27 15:48:48 -070033Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070034IdentityManager::createIdentity(const Name& identityName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -070035{
36 if (!identityStorage_->doesIdentityExist(identityName)) {
Jeff Thompsonc69163b2013-10-12 13:49:50 -070037 _LOG_DEBUG("Create Identity");
38 identityStorage_->addIdentity(identityName);
39
40 _LOG_DEBUG("Create Default RSA key pair");
41 Name keyName = generateRSAKeyPairAsDefault(identityName, true);
Jeff Thompsone7e069b2013-09-27 15:48:48 -070042
Jeff Thompsonc69163b2013-10-12 13:49:50 -070043 _LOG_DEBUG("Create self-signed certificate");
44 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
45
46 _LOG_DEBUG("Add self-signed certificate as default");
Jeff Thompsone7e069b2013-09-27 15:48:48 -070047
Jeff Thompsonc69163b2013-10-12 13:49:50 -070048 addCertificateAsDefault(*selfCert);
49
50 return keyName;
Jeff Thompsone7e069b2013-09-27 15:48:48 -070051 }
52 else
53 throw SecurityException("Identity has already been created!");
54}
55
56Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070057IdentityManager::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
58{
59 _LOG_DEBUG("Get new key ID");
60 Name keyName = identityStorage_->getNewKeyName(identityName, isKsk);
61
62 _LOG_DEBUG("Generate key pair in private storage");
63 privateKeyStorage_->generateKeyPair(keyName.toUri(), keyType, keySize);
64
65 _LOG_DEBUG("Create a key record in public storage");
66 shared_ptr<PublicKey> pubKey = privateKeyStorage_->getPublicKey(keyName.toUri());
67 identityStorage_->addKey(keyName, keyType, pubKey->getKeyDer());
Jeff Thompson418b05a2013-10-22 17:48:54 -070068
Jeff Thompsonc69163b2013-10-12 13:49:50 -070069 return keyName;
70}
71
72Name
Jeff Thompsone7e069b2013-09-27 15:48:48 -070073IdentityManager::generateRSAKeyPair(const Name& identityName, bool isKsk, int keySize)
74{
75 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompson418b05a2013-10-22 17:48:54 -070076
Jeff Thompsone7e069b2013-09-27 15:48:48 -070077 return keyName;
78}
79
80Name
81IdentityManager::generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
82{
83 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070084
Jeff Thompsone7e069b2013-09-27 15:48:48 -070085 identityStorage_->setDefaultKeyNameForIdentity(keyName, identityName);
86
Jeff Thompsonc69163b2013-10-12 13:49:50 -070087 return keyName;
88}
89
90Name
Jeff Thompson418b05a2013-10-22 17:48:54 -070091IdentityManager::createIdentityCertificate(const Name& certificatePrefix,
92 const Name& signerCertificateName,
93 const MillisecondsSince1970& notBefore,
94 const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -070095{
Jeff Thompson418b05a2013-10-22 17:48:54 -070096 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
97
Jeff Thompsonc69163b2013-10-12 13:49:50 -070098 Blob keyBlob = identityStorage_->getKey(keyName);
99 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
100
101 shared_ptr<IdentityCertificate> certificate = createIdentityCertificate
Jeff Thompson418b05a2013-10-22 17:48:54 -0700102 (certificatePrefix, *publicKey, signerCertificateName, notBefore, notAfter);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700103
104 identityStorage_->addCertificate(*certificate);
105
106 return certificate->getName();
107}
108
109ptr_lib::shared_ptr<IdentityCertificate>
Jeff Thompson418b05a2013-10-22 17:48:54 -0700110IdentityManager::createIdentityCertificate(const Name& certificatePrefix,
111 const PublicKey& publicKey,
112 const Name& signerCertificateName,
113 const MillisecondsSince1970& notBefore,
114 const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700115{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700116 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompson418b05a2013-10-22 17:48:54 -0700117 Name keyName = getKeyNameFromCertificatePrefix(certificatePrefix);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700118
Jeff Thompson418b05a2013-10-22 17:48:54 -0700119 Name certificateName = certificatePrefix;
Jeff Thompsondb686892013-10-18 17:16:31 -0700120 MillisecondsSince1970 ti = ::ndn_getNowMilliseconds();
121 // Get the number of seconds.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700122 ostringstream oss;
Jeff Thompsondb686892013-10-18 17:16:31 -0700123 oss << floor(ti / 1000.0);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700124
Jeff Thompson418b05a2013-10-22 17:48:54 -0700125 certificateName.append("ID-CERT").append(oss.str());
126
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700127 certificate->setName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700128 certificate->setNotBefore(notBefore);
129 certificate->setNotAfter(notAfter);
130 certificate->setPublicKeyInfo(publicKey);
Jeff Thompsondb686892013-10-18 17:16:31 -0700131 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700132 certificate->encode();
133
134 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
135
136 KeyLocator keyLocator;
Jeff Thompsondb686892013-10-18 17:16:31 -0700137 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700138 keyLocator.setKeyName(signerCertificateName);
139
140 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700141 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey.getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700142
Jeff Thompsondb686892013-10-18 17:16:31 -0700143 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700144
Jeff Thompsondb686892013-10-18 17:16:31 -0700145 SignedBlob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700146
Jeff Thompson418b05a2013-10-22 17:48:54 -0700147 shared_ptr<IdentityCertificate> signerCertificate = getCertificate(signerCertificateName);
148 Name signerkeyName = signerCertificate->getPublicKeyName();
149
150 Blob sigBits = privateKeyStorage_->sign(unsignedData, signerkeyName);
151
Jeff Thompsonba82c162013-10-18 17:21:23 -0700152 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700153
154 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700155}
156
157void
158IdentityManager::addCertificateAsDefault(const IdentityCertificate& certificate)
159{
160 identityStorage_->addCertificate(certificate);
161
Jeff Thompson418b05a2013-10-22 17:48:54 -0700162 setDefaultCertificateForKey(certificate);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700163}
164
165void
Jeff Thompson418b05a2013-10-22 17:48:54 -0700166IdentityManager::addCertificateAsIdentityDefault(const IdentityCertificate& certificate)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700167{
Jeff Thompson418b05a2013-10-22 17:48:54 -0700168 identityStorage_->addCertificate(certificate);
169
170 Name keyName = certificate.getPublicKeyName();
171
172 setDefaultKeyForIdentity(keyName);
173
174 setDefaultCertificateForKey(certificate);
175}
176
177void
178IdentityManager::setDefaultCertificateForKey(const IdentityCertificate& certificate)
179{
180 Name keyName = certificate.getPublicKeyName();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700181
182 if(!identityStorage_->doesKeyExist(keyName))
Jeff Thompson418b05a2013-10-22 17:48:54 -0700183 throw SecurityException("No corresponding Key record for certificate!");
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700184
Jeff Thompson418b05a2013-10-22 17:48:54 -0700185 identityStorage_->setDefaultCertificateNameForKey(keyName, certificate.getName());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700186}
187
188ptr_lib::shared_ptr<Signature>
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700189IdentityManager::signByCertificate(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700190{
Jeff Thompson418b05a2013-10-22 17:48:54 -0700191 shared_ptr<IdentityCertificate> certificate = getCertificate(certificateName);
192 Name keyName = certificate->getPublicKeyName();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700193 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
194
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700195 Blob sigBits = privateKeyStorage_->sign(buffer, bufferLength, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700196
197 //For temporary usage, we support RSA + SHA256 only, but will support more.
Jeff Thompsonba82c162013-10-18 17:21:23 -0700198 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700199
200 KeyLocator keyLocator;
Jeff Thompsonba82c162013-10-18 17:21:23 -0700201 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
202 keyLocator.setKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700203
204 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700205 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonba82c162013-10-18 17:21:23 -0700206 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700207
208 return sha256Sig;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700209}
210
211void
Jeff Thompson86e1d752013-09-17 17:22:38 -0700212IdentityManager::signByCertificate(Data &data, const Name &certificateName, WireFormat& wireFormat)
Jeff Thompson41471912013-09-12 16:21:50 -0700213{
Jeff Thompson418b05a2013-10-22 17:48:54 -0700214 shared_ptr<IdentityCertificate> certificate = getCertificate(certificateName);
215 Name keyName = certificate->getPublicKeyName();
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700216 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700217
218 // For temporary usage, we support RSA + SHA256 only, but will support more.
219 data.setSignature(Sha256WithRsaSignature());
220 // Get a pointer to the clone which Data made.
221 Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(data.getSignature());
222 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256;
223
224 signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
225 signature->getKeyLocator().setKeyName(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700226 // Omit the certificate digest.
227 signature->getKeyLocator().setKeyNameType((ndn_KeyNameType)-1);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700228 // Ignore witness and leave the digestAlgorithm as the default.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700229 signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompson41471912013-09-12 16:21:50 -0700230
Jeff Thompson86e1d752013-09-17 17:22:38 -0700231 // Encode once to get the signed portion.
232 SignedBlob encoding = data.wireEncode(wireFormat);
233
234 signature->setSignature
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700235 (privateKeyStorage_->sign(encoding.signedBuf(), encoding.signedSize(), keyName, digestAlgorithm));
Jeff Thompson86e1d752013-09-17 17:22:38 -0700236
237 // Encode again to include the signature.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700238 data.wireEncode(wireFormat);
Jeff Thompson41471912013-09-12 16:21:50 -0700239}
240
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700241shared_ptr<IdentityCertificate>
242IdentityManager::selfSign(const Name& keyName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700243{
Jeff Thompsond63baba2013-10-18 17:47:58 -0700244 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700245
Jeff Thompson418b05a2013-10-22 17:48:54 -0700246 Name certificateName = keyName.getSubName(0, keyName.size() - 1);
247 certificateName.append("KEY").append(keyName.get(keyName.size() - 1)).append("ID-CERT").append("0");
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700248 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700249
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700250 Blob keyBlob = identityStorage_->getKey(keyName);
251 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700252
Jeff Thompsond63baba2013-10-18 17:47:58 -0700253#if NDN_CPP_HAVE_GMTIME_SUPPORT
254 time_t nowSeconds = time(NULL);
255 struct tm current = *gmtime(&nowSeconds);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700256 current.tm_hour = 0;
257 current.tm_min = 0;
258 current.tm_sec = 0;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700259 MillisecondsSince1970 notBefore = timegm(&current) * 1000.0;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700260 current.tm_year = current.tm_year + 20;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700261 MillisecondsSince1970 notAfter = timegm(&current) * 1000.0;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700262
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700263 certificate->setNotBefore(notBefore);
264 certificate->setNotAfter(notAfter);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700265#else
266 // Don't really expect this to happen.
267 throw SecurityException("selfSign: Can't set certificate validity because time functions are not supported by the standard library.");
268#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700269 certificate->setPublicKeyInfo(*publicKey);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700270 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700271 certificate->encode();
272
Jeff Thompsond63baba2013-10-18 17:47:58 -0700273 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700274
275 KeyLocator keyLocator;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700276 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700277 keyLocator.setKeyName(certificateName);
278
279 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700280 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700281
Jeff Thompsond63baba2013-10-18 17:47:58 -0700282 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700283
Jeff Thompsond63baba2013-10-18 17:47:58 -0700284 Blob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700285
Jeff Thompsond63baba2013-10-18 17:47:58 -0700286 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700287
Jeff Thompsond63baba2013-10-18 17:47:58 -0700288 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700289
290 return certificate;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700291}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700292
Jeff Thompson418b05a2013-10-22 17:48:54 -0700293Name
294IdentityManager::getKeyNameFromCertificatePrefix(const Name & certificatePrefix)
295{
296 Name result;
297
298 string keyString("KEY");
299 int i = 0;
300 for(; i < certificatePrefix.size(); i++) {
301 if (certificatePrefix.get(i).toEscapedString() == keyString)
302 break;
303 }
304
305 if (i >= certificatePrefix.size())
306 throw SecurityException("Identity Certificate Prefix does not have a KEY component");
307
308 result.append(certificatePrefix.getSubName(0, i));
309 result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1));
310
311 return result;
312}
313
Jeff Thompson41471912013-09-12 16:21:50 -0700314}