blob: 10168d15d8e71642833f8f9a45899609a462d18f [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 Thompson74942612013-10-24 16:42:32 -0700190{
191 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700192 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
193
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700194 Blob sigBits = privateKeyStorage_->sign(buffer, bufferLength, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700195
196 //For temporary usage, we support RSA + SHA256 only, but will support more.
Jeff Thompsonba82c162013-10-18 17:21:23 -0700197 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700198
199 KeyLocator keyLocator;
Jeff Thompsonba82c162013-10-18 17:21:23 -0700200 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
201 keyLocator.setKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700202
203 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700204 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonba82c162013-10-18 17:21:23 -0700205 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700206
207 return sha256Sig;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700208}
209
210void
Jeff Thompson86e1d752013-09-17 17:22:38 -0700211IdentityManager::signByCertificate(Data &data, const Name &certificateName, WireFormat& wireFormat)
Jeff Thompson41471912013-09-12 16:21:50 -0700212{
Jeff Thompson74942612013-10-24 16:42:32 -0700213 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700214 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700215
216 // For temporary usage, we support RSA + SHA256 only, but will support more.
217 data.setSignature(Sha256WithRsaSignature());
218 // Get a pointer to the clone which Data made.
219 Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(data.getSignature());
220 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256;
221
222 signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompson40ada912013-12-17 11:36:27 -0800223 signature->getKeyLocator().setKeyName(certificateName.getPrefix(-1));
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700224 // Omit the certificate digest.
225 signature->getKeyLocator().setKeyNameType((ndn_KeyNameType)-1);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700226 // Ignore witness and leave the digestAlgorithm as the default.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700227 signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompson41471912013-09-12 16:21:50 -0700228
Jeff Thompson86e1d752013-09-17 17:22:38 -0700229 // Encode once to get the signed portion.
230 SignedBlob encoding = data.wireEncode(wireFormat);
231
232 signature->setSignature
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700233 (privateKeyStorage_->sign(encoding.signedBuf(), encoding.signedSize(), keyName, digestAlgorithm));
Jeff Thompson86e1d752013-09-17 17:22:38 -0700234
235 // Encode again to include the signature.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700236 data.wireEncode(wireFormat);
Jeff Thompson41471912013-09-12 16:21:50 -0700237}
238
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700239shared_ptr<IdentityCertificate>
240IdentityManager::selfSign(const Name& keyName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700241{
Jeff Thompsond63baba2013-10-18 17:47:58 -0700242 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700243
Jeff Thompson418b05a2013-10-22 17:48:54 -0700244 Name certificateName = keyName.getSubName(0, keyName.size() - 1);
245 certificateName.append("KEY").append(keyName.get(keyName.size() - 1)).append("ID-CERT").append("0");
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700246 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700247
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700248 Blob keyBlob = identityStorage_->getKey(keyName);
249 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700250
Jeff Thompsond63baba2013-10-18 17:47:58 -0700251#if NDN_CPP_HAVE_GMTIME_SUPPORT
252 time_t nowSeconds = time(NULL);
253 struct tm current = *gmtime(&nowSeconds);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700254 current.tm_hour = 0;
255 current.tm_min = 0;
256 current.tm_sec = 0;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700257 MillisecondsSince1970 notBefore = timegm(&current) * 1000.0;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700258 current.tm_year = current.tm_year + 20;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700259 MillisecondsSince1970 notAfter = timegm(&current) * 1000.0;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700260
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700261 certificate->setNotBefore(notBefore);
262 certificate->setNotAfter(notAfter);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700263#else
264 // Don't really expect this to happen.
265 throw SecurityException("selfSign: Can't set certificate validity because time functions are not supported by the standard library.");
266#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700267 certificate->setPublicKeyInfo(*publicKey);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700268 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700269 certificate->encode();
270
Jeff Thompsond63baba2013-10-18 17:47:58 -0700271 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700272
273 KeyLocator keyLocator;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700274 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700275 keyLocator.setKeyName(certificateName);
276
277 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700278 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700279
Jeff Thompsond63baba2013-10-18 17:47:58 -0700280 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700281
Jeff Thompsond63baba2013-10-18 17:47:58 -0700282 Blob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700283
Jeff Thompsond63baba2013-10-18 17:47:58 -0700284 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700285
Jeff Thompsond63baba2013-10-18 17:47:58 -0700286 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700287
288 return certificate;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700289}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700290
Jeff Thompson418b05a2013-10-22 17:48:54 -0700291Name
292IdentityManager::getKeyNameFromCertificatePrefix(const Name & certificatePrefix)
293{
294 Name result;
295
296 string keyString("KEY");
297 int i = 0;
298 for(; i < certificatePrefix.size(); i++) {
299 if (certificatePrefix.get(i).toEscapedString() == keyString)
300 break;
301 }
302
303 if (i >= certificatePrefix.size())
304 throw SecurityException("Identity Certificate Prefix does not have a KEY component");
305
306 result.append(certificatePrefix.getSubName(0, i));
307 result.append(certificatePrefix.getSubName(i + 1, certificatePrefix.size()-i-1));
308
309 return result;
310}
311
Jeff Thompson41471912013-09-12 16:21:50 -0700312}