blob: eb9966e35e6009912e918b0a6feb409227d21833 [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());
68 _LOG_DEBUG("OK");
69 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);
76 _LOG_DEBUG("OK2");
77 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 Thompson9a8e82f2013-10-17 14:13:43 -070091IdentityManager::createIdentityCertificate(const Name& keyName, const Name& signerCertificateName, const MillisecondsSince1970& notBefore, const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -070092{
93 Blob keyBlob = identityStorage_->getKey(keyName);
94 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
95
96 shared_ptr<IdentityCertificate> certificate = createIdentityCertificate
97 (keyName, *publicKey, signerCertificateName, notBefore, notAfter);
98
99 identityStorage_->addCertificate(*certificate);
100
101 return certificate->getName();
102}
103
104ptr_lib::shared_ptr<IdentityCertificate>
105IdentityManager::createIdentityCertificate
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700106 (const Name& keyName, const PublicKey& publicKey, const Name& signerCertificateName, const MillisecondsSince1970& notBefore, const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700107{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700108 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
109
110 Name certificateName;
Jeff Thompsondb686892013-10-18 17:16:31 -0700111 MillisecondsSince1970 ti = ::ndn_getNowMilliseconds();
112 // Get the number of seconds.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700113 ostringstream oss;
Jeff Thompsondb686892013-10-18 17:16:31 -0700114 oss << floor(ti / 1000.0);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700115
116 certificateName.append(keyName).append("ID-CERT").append(oss.str());
117 certificate->setName(certificateName);
118
119 certificate->setNotBefore(notBefore);
120 certificate->setNotAfter(notAfter);
121 certificate->setPublicKeyInfo(publicKey);
Jeff Thompsondb686892013-10-18 17:16:31 -0700122 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700123 certificate->encode();
124
125 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
126
127 KeyLocator keyLocator;
Jeff Thompsondb686892013-10-18 17:16:31 -0700128 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700129 keyLocator.setKeyName(signerCertificateName);
130
131 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700132 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey.getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700133
Jeff Thompsondb686892013-10-18 17:16:31 -0700134 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700135
Jeff Thompsondb686892013-10-18 17:16:31 -0700136 SignedBlob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700137
Jeff Thompsondb686892013-10-18 17:16:31 -0700138 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700139
Jeff Thompsonba82c162013-10-18 17:21:23 -0700140 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700141
142 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700143}
144
145void
146IdentityManager::addCertificateAsDefault(const IdentityCertificate& certificate)
147{
148 identityStorage_->addCertificate(certificate);
149
150 Name keyName = identityStorage_->getKeyNameForCertificate(certificate.getName());
151
152 setDefaultKeyForIdentity(keyName);
153
154 setDefaultCertificateForKey(certificate.getName());
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700155}
156
157void
158IdentityManager::setDefaultCertificateForKey(const Name& certificateName)
159{
160 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700161
162 if(!identityStorage_->doesKeyExist(keyName))
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700163 throw SecurityException("No corresponding Key record for certificaite!");
164
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700165 identityStorage_->setDefaultCertificateNameForKey(keyName, certificateName);
166}
167
168ptr_lib::shared_ptr<Signature>
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700169IdentityManager::signByCertificate(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700170{
Jeff Thompsonba82c162013-10-18 17:21:23 -0700171 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700172
173 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
174
Jeff Thompsonc01e1782013-10-21 14:08:42 -0700175 Blob sigBits = privateKeyStorage_->sign(buffer, bufferLength, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700176
177 //For temporary usage, we support RSA + SHA256 only, but will support more.
Jeff Thompsonba82c162013-10-18 17:21:23 -0700178 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700179
180 KeyLocator keyLocator;
Jeff Thompsonba82c162013-10-18 17:21:23 -0700181 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
182 keyLocator.setKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700183
184 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700185 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonba82c162013-10-18 17:21:23 -0700186 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700187
188 return sha256Sig;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700189}
190
191void
Jeff Thompson86e1d752013-09-17 17:22:38 -0700192IdentityManager::signByCertificate(Data &data, const Name &certificateName, WireFormat& wireFormat)
Jeff Thompson41471912013-09-12 16:21:50 -0700193{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700194 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700195
196 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700197
198 // For temporary usage, we support RSA + SHA256 only, but will support more.
199 data.setSignature(Sha256WithRsaSignature());
200 // Get a pointer to the clone which Data made.
201 Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(data.getSignature());
202 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256;
203
204 signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
205 signature->getKeyLocator().setKeyName(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700206 // Omit the certificate digest.
207 signature->getKeyLocator().setKeyNameType((ndn_KeyNameType)-1);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700208 // Ignore witness and leave the digestAlgorithm as the default.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700209 signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompson41471912013-09-12 16:21:50 -0700210
Jeff Thompson86e1d752013-09-17 17:22:38 -0700211 // Encode once to get the signed portion.
212 SignedBlob encoding = data.wireEncode(wireFormat);
213
214 signature->setSignature
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700215 (privateKeyStorage_->sign(encoding.signedBuf(), encoding.signedSize(), keyName, digestAlgorithm));
Jeff Thompson86e1d752013-09-17 17:22:38 -0700216
217 // Encode again to include the signature.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700218 data.wireEncode(wireFormat);
Jeff Thompson41471912013-09-12 16:21:50 -0700219}
220
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700221shared_ptr<IdentityCertificate>
222IdentityManager::selfSign(const Name& keyName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700223{
Jeff Thompsond63baba2013-10-18 17:47:58 -0700224 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700225
226 Name certificateName;
227 certificateName.append(keyName).append("ID-CERT").append("0");
228 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700229
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700230 Blob keyBlob = identityStorage_->getKey(keyName);
231 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700232
Jeff Thompsond63baba2013-10-18 17:47:58 -0700233#if NDN_CPP_HAVE_GMTIME_SUPPORT
234 time_t nowSeconds = time(NULL);
235 struct tm current = *gmtime(&nowSeconds);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700236 current.tm_hour = 0;
237 current.tm_min = 0;
238 current.tm_sec = 0;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700239 MillisecondsSince1970 notBefore = timegm(&current) * 1000.0;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700240 current.tm_year = current.tm_year + 20;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700241 MillisecondsSince1970 notAfter = timegm(&current) * 1000.0;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700242
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700243 certificate->setNotBefore(notBefore);
244 certificate->setNotAfter(notAfter);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700245#else
246 // Don't really expect this to happen.
247 throw SecurityException("selfSign: Can't set certificate validity because time functions are not supported by the standard library.");
248#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700249 certificate->setPublicKeyInfo(*publicKey);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700250 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700251 certificate->encode();
252
Jeff Thompsond63baba2013-10-18 17:47:58 -0700253 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700254
255 KeyLocator keyLocator;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700256 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700257 keyLocator.setKeyName(certificateName);
258
259 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700260 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700261
Jeff Thompsond63baba2013-10-18 17:47:58 -0700262 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700263
Jeff Thompsond63baba2013-10-18 17:47:58 -0700264 Blob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700265
Jeff Thompsond63baba2013-10-18 17:47:58 -0700266 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700267
Jeff Thompsond63baba2013-10-18 17:47:58 -0700268 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700269
270 return certificate;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700271}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700272
Jeff Thompson41471912013-09-12 16:21:50 -0700273}