blob: c7230644c7f9ab20eda91342527b946f5e567feb [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 Thompson6154ae22013-10-18 10:44:57 -07009#if 1 // TODO: Remove this when we don't throw "not implemented".
Jeff Thompson0f2096f2013-10-01 14:49:42 -070010#include <stdexcept>
11#endif
Jeff Thompsond63baba2013-10-18 17:47:58 -070012#include <ndn-cpp/ndn-cpp-config.h>
13#if NDN_CPP_HAVE_TIME_H
14#include <time.h>
15#endif
16#if NDN_CPP_HAVE_SYS_TIME_H
17#include <sys/time.h>
18#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -070019#include <ctime>
20#include <fstream>
Jeff Thompsondb686892013-10-18 17:16:31 -070021#include <math.h>
Jeff Thompsonc69163b2013-10-12 13:49:50 -070022#include <ndn-cpp/key.hpp>
Jeff Thompson25b4e612013-10-10 16:03:24 -070023#include <ndn-cpp/sha256-with-rsa-signature.hpp>
24#include <ndn-cpp/security/security-exception.hpp>
Jeff Thompsonc69163b2013-10-12 13:49:50 -070025#include "../../util/logging.hpp"
Jeff Thompsondb686892013-10-18 17:16:31 -070026#include "../../c/util/time.h"
Jeff Thompson25b4e612013-10-10 16:03:24 -070027#include <ndn-cpp/security/identity/identity-manager.hpp>
Jeff Thompson41471912013-09-12 16:21:50 -070028
Jeff Thompsonc69163b2013-10-12 13:49:50 -070029INIT_LOGGER("ndn.security.IdentityManager")
30
Jeff Thompson9296f0c2013-09-23 18:10:27 -070031using namespace std;
32using namespace ndn::ptr_lib;
Jeff Thompson41471912013-09-12 16:21:50 -070033
Jeff Thompson9296f0c2013-09-23 18:10:27 -070034namespace ndn {
Jeff Thompson86e1d752013-09-17 17:22:38 -070035
Jeff Thompsone7e069b2013-09-27 15:48:48 -070036Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070037IdentityManager::createIdentity(const Name& identityName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -070038{
39 if (!identityStorage_->doesIdentityExist(identityName)) {
Jeff Thompsonc69163b2013-10-12 13:49:50 -070040 _LOG_DEBUG("Create Identity");
41 identityStorage_->addIdentity(identityName);
42
43 _LOG_DEBUG("Create Default RSA key pair");
44 Name keyName = generateRSAKeyPairAsDefault(identityName, true);
Jeff Thompsone7e069b2013-09-27 15:48:48 -070045
Jeff Thompsonc69163b2013-10-12 13:49:50 -070046 _LOG_DEBUG("Create self-signed certificate");
47 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
48
49 _LOG_DEBUG("Add self-signed certificate as default");
Jeff Thompsone7e069b2013-09-27 15:48:48 -070050
Jeff Thompsonc69163b2013-10-12 13:49:50 -070051 addCertificateAsDefault(*selfCert);
52
53 return keyName;
Jeff Thompsone7e069b2013-09-27 15:48:48 -070054 }
55 else
56 throw SecurityException("Identity has already been created!");
57}
58
59Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070060IdentityManager::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
61{
62 _LOG_DEBUG("Get new key ID");
63 Name keyName = identityStorage_->getNewKeyName(identityName, isKsk);
64
65 _LOG_DEBUG("Generate key pair in private storage");
66 privateKeyStorage_->generateKeyPair(keyName.toUri(), keyType, keySize);
67
68 _LOG_DEBUG("Create a key record in public storage");
69 shared_ptr<PublicKey> pubKey = privateKeyStorage_->getPublicKey(keyName.toUri());
70 identityStorage_->addKey(keyName, keyType, pubKey->getKeyDer());
71 _LOG_DEBUG("OK");
72 return keyName;
73}
74
75Name
Jeff Thompsone7e069b2013-09-27 15:48:48 -070076IdentityManager::generateRSAKeyPair(const Name& identityName, bool isKsk, int keySize)
77{
78 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
79 _LOG_DEBUG("OK2");
80 return keyName;
81}
82
83Name
84IdentityManager::generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
85{
86 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070087
Jeff Thompsone7e069b2013-09-27 15:48:48 -070088 identityStorage_->setDefaultKeyNameForIdentity(keyName, identityName);
89
Jeff Thompsonc69163b2013-10-12 13:49:50 -070090 return keyName;
91}
92
93Name
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070094IdentityManager::createIdentityCertificate(const Name& keyName, const Name& signerCertificateName, const MillisecondsSince1970& notBefore, const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -070095{
96 Blob keyBlob = identityStorage_->getKey(keyName);
97 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
98
99 shared_ptr<IdentityCertificate> certificate = createIdentityCertificate
100 (keyName, *publicKey, signerCertificateName, notBefore, notAfter);
101
102 identityStorage_->addCertificate(*certificate);
103
104 return certificate->getName();
105}
106
107ptr_lib::shared_ptr<IdentityCertificate>
108IdentityManager::createIdentityCertificate
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700109 (const Name& keyName, const PublicKey& publicKey, const Name& signerCertificateName, const MillisecondsSince1970& notBefore, const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700110{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700111 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
112
113 Name certificateName;
Jeff Thompsondb686892013-10-18 17:16:31 -0700114 MillisecondsSince1970 ti = ::ndn_getNowMilliseconds();
115 // Get the number of seconds.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700116 ostringstream oss;
Jeff Thompsondb686892013-10-18 17:16:31 -0700117 oss << floor(ti / 1000.0);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700118
119 certificateName.append(keyName).append("ID-CERT").append(oss.str());
120 certificate->setName(certificateName);
121
122 certificate->setNotBefore(notBefore);
123 certificate->setNotAfter(notAfter);
124 certificate->setPublicKeyInfo(publicKey);
Jeff Thompsondb686892013-10-18 17:16:31 -0700125 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700126 certificate->encode();
127
128 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
129
130 KeyLocator keyLocator;
Jeff Thompsondb686892013-10-18 17:16:31 -0700131 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700132 keyLocator.setKeyName(signerCertificateName);
133
134 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700135 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey.getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700136
Jeff Thompsondb686892013-10-18 17:16:31 -0700137 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700138
Jeff Thompsondb686892013-10-18 17:16:31 -0700139 SignedBlob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700140
Jeff Thompsondb686892013-10-18 17:16:31 -0700141 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700142
Jeff Thompsonba82c162013-10-18 17:21:23 -0700143 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700144
145 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700146}
147
148void
149IdentityManager::addCertificateAsDefault(const IdentityCertificate& certificate)
150{
151 identityStorage_->addCertificate(certificate);
152
153 Name keyName = identityStorage_->getKeyNameForCertificate(certificate.getName());
154
155 setDefaultKeyForIdentity(keyName);
156
157 setDefaultCertificateForKey(certificate.getName());
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700158}
159
160void
161IdentityManager::setDefaultCertificateForKey(const Name& certificateName)
162{
163 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700164
165 if(!identityStorage_->doesKeyExist(keyName))
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700166 throw SecurityException("No corresponding Key record for certificaite!");
167
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700168 identityStorage_->setDefaultCertificateNameForKey(keyName, certificateName);
169}
170
171ptr_lib::shared_ptr<Signature>
172IdentityManager::signByCertificate(const uint8_t* data, size_t dataLength, const Name& certificateName)
173{
Jeff Thompsonba82c162013-10-18 17:21:23 -0700174 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700175
176 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
177
Jeff Thompsonba82c162013-10-18 17:21:23 -0700178 Blob sigBits = privateKeyStorage_->sign(data, dataLength, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700179
180 //For temporary usage, we support RSA + SHA256 only, but will support more.
Jeff Thompsonba82c162013-10-18 17:21:23 -0700181 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700182
183 KeyLocator keyLocator;
Jeff Thompsonba82c162013-10-18 17:21:23 -0700184 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
185 keyLocator.setKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700186
187 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700188 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonba82c162013-10-18 17:21:23 -0700189 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700190
191 return sha256Sig;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700192}
193
194void
Jeff Thompson86e1d752013-09-17 17:22:38 -0700195IdentityManager::signByCertificate(Data &data, const Name &certificateName, WireFormat& wireFormat)
Jeff Thompson41471912013-09-12 16:21:50 -0700196{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700197 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700198
199 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700200
201 // For temporary usage, we support RSA + SHA256 only, but will support more.
202 data.setSignature(Sha256WithRsaSignature());
203 // Get a pointer to the clone which Data made.
204 Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(data.getSignature());
205 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256;
206
207 signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
208 signature->getKeyLocator().setKeyName(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700209 // Omit the certificate digest.
210 signature->getKeyLocator().setKeyNameType((ndn_KeyNameType)-1);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700211 // Ignore witness and leave the digestAlgorithm as the default.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700212 signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompson41471912013-09-12 16:21:50 -0700213
Jeff Thompson86e1d752013-09-17 17:22:38 -0700214 // Encode once to get the signed portion.
215 SignedBlob encoding = data.wireEncode(wireFormat);
216
217 signature->setSignature
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700218 (privateKeyStorage_->sign(encoding.signedBuf(), encoding.signedSize(), keyName, digestAlgorithm));
Jeff Thompson86e1d752013-09-17 17:22:38 -0700219
220 // Encode again to include the signature.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700221 data.wireEncode(wireFormat);
Jeff Thompson41471912013-09-12 16:21:50 -0700222}
223
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700224shared_ptr<IdentityCertificate>
225IdentityManager::selfSign(const Name& keyName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700226{
Jeff Thompsond63baba2013-10-18 17:47:58 -0700227 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700228
229 Name certificateName;
230 certificateName.append(keyName).append("ID-CERT").append("0");
231 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700232
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700233 Blob keyBlob = identityStorage_->getKey(keyName);
234 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700235
Jeff Thompsond63baba2013-10-18 17:47:58 -0700236#if NDN_CPP_HAVE_GMTIME_SUPPORT
237 time_t nowSeconds = time(NULL);
238 struct tm current = *gmtime(&nowSeconds);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700239 current.tm_hour = 0;
240 current.tm_min = 0;
241 current.tm_sec = 0;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700242 MillisecondsSince1970 notBefore = timegm(&current) * 1000.0;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700243 current.tm_year = current.tm_year + 20;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700244 MillisecondsSince1970 notAfter = timegm(&current) * 1000.0;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700245
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700246 certificate->setNotBefore(notBefore);
247 certificate->setNotAfter(notAfter);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700248#else
249 // Don't really expect this to happen.
250 throw SecurityException("selfSign: Can't set certificate validity because time functions are not supported by the standard library.");
251#endif
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700252 certificate->setPublicKeyInfo(*publicKey);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700253 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700254 certificate->encode();
255
Jeff Thompsond63baba2013-10-18 17:47:58 -0700256 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700257
258 KeyLocator keyLocator;
Jeff Thompsond63baba2013-10-18 17:47:58 -0700259 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700260 keyLocator.setKeyName(certificateName);
261
262 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsond63baba2013-10-18 17:47:58 -0700263 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700264
Jeff Thompsond63baba2013-10-18 17:47:58 -0700265 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700266
Jeff Thompsond63baba2013-10-18 17:47:58 -0700267 Blob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700268
Jeff Thompsond63baba2013-10-18 17:47:58 -0700269 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700270
Jeff Thompsond63baba2013-10-18 17:47:58 -0700271 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700272
273 return certificate;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700274}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700275
Jeff Thompson41471912013-09-12 16:21:50 -0700276}