blob: c13ed419f8155eb400b6a33be6344fc5db1e139e [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 Thompsonc69163b2013-10-12 13:49:50 -070012#include <ctime>
13#include <fstream>
Jeff Thompsondb686892013-10-18 17:16:31 -070014#include <math.h>
Jeff Thompsonc69163b2013-10-12 13:49:50 -070015#include <ndn-cpp/key.hpp>
Jeff Thompson25b4e612013-10-10 16:03:24 -070016#include <ndn-cpp/sha256-with-rsa-signature.hpp>
17#include <ndn-cpp/security/security-exception.hpp>
Jeff Thompsonc69163b2013-10-12 13:49:50 -070018#include "../../util/logging.hpp"
Jeff Thompsondb686892013-10-18 17:16:31 -070019#include "../../c/util/time.h"
Jeff Thompson25b4e612013-10-10 16:03:24 -070020#include <ndn-cpp/security/identity/identity-manager.hpp>
Jeff Thompson41471912013-09-12 16:21:50 -070021
Jeff Thompsonc69163b2013-10-12 13:49:50 -070022INIT_LOGGER("ndn.security.IdentityManager")
23
Jeff Thompson9296f0c2013-09-23 18:10:27 -070024using namespace std;
25using namespace ndn::ptr_lib;
Jeff Thompson41471912013-09-12 16:21:50 -070026
Jeff Thompson9296f0c2013-09-23 18:10:27 -070027namespace ndn {
Jeff Thompson86e1d752013-09-17 17:22:38 -070028
Jeff Thompsone7e069b2013-09-27 15:48:48 -070029Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070030IdentityManager::createIdentity(const Name& identityName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -070031{
32 if (!identityStorage_->doesIdentityExist(identityName)) {
Jeff Thompsonc69163b2013-10-12 13:49:50 -070033 _LOG_DEBUG("Create Identity");
34 identityStorage_->addIdentity(identityName);
35
36 _LOG_DEBUG("Create Default RSA key pair");
37 Name keyName = generateRSAKeyPairAsDefault(identityName, true);
Jeff Thompsone7e069b2013-09-27 15:48:48 -070038
Jeff Thompsonc69163b2013-10-12 13:49:50 -070039 _LOG_DEBUG("Create self-signed certificate");
40 shared_ptr<IdentityCertificate> selfCert = selfSign(keyName);
41
42 _LOG_DEBUG("Add self-signed certificate as default");
Jeff Thompsone7e069b2013-09-27 15:48:48 -070043
Jeff Thompsonc69163b2013-10-12 13:49:50 -070044 addCertificateAsDefault(*selfCert);
45
46 return keyName;
Jeff Thompsone7e069b2013-09-27 15:48:48 -070047 }
48 else
49 throw SecurityException("Identity has already been created!");
50}
51
52Name
Jeff Thompsonc69163b2013-10-12 13:49:50 -070053IdentityManager::generateKeyPair(const Name& identityName, bool isKsk, KeyType keyType, int keySize)
54{
55 _LOG_DEBUG("Get new key ID");
56 Name keyName = identityStorage_->getNewKeyName(identityName, isKsk);
57
58 _LOG_DEBUG("Generate key pair in private storage");
59 privateKeyStorage_->generateKeyPair(keyName.toUri(), keyType, keySize);
60
61 _LOG_DEBUG("Create a key record in public storage");
62 shared_ptr<PublicKey> pubKey = privateKeyStorage_->getPublicKey(keyName.toUri());
63 identityStorage_->addKey(keyName, keyType, pubKey->getKeyDer());
64 _LOG_DEBUG("OK");
65 return keyName;
66}
67
68Name
Jeff Thompsone7e069b2013-09-27 15:48:48 -070069IdentityManager::generateRSAKeyPair(const Name& identityName, bool isKsk, int keySize)
70{
71 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
72 _LOG_DEBUG("OK2");
73 return keyName;
74}
75
76Name
77IdentityManager::generateRSAKeyPairAsDefault(const Name& identityName, bool isKsk, int keySize)
78{
79 Name keyName = generateKeyPair(identityName, isKsk, KEY_TYPE_RSA, keySize);
Jeff Thompsonc69163b2013-10-12 13:49:50 -070080
Jeff Thompsone7e069b2013-09-27 15:48:48 -070081 identityStorage_->setDefaultKeyNameForIdentity(keyName, identityName);
82
Jeff Thompsonc69163b2013-10-12 13:49:50 -070083 return keyName;
84}
85
86Name
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070087IdentityManager::createIdentityCertificate(const Name& keyName, const Name& signerCertificateName, const MillisecondsSince1970& notBefore, const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -070088{
89 Blob keyBlob = identityStorage_->getKey(keyName);
90 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
91
92 shared_ptr<IdentityCertificate> certificate = createIdentityCertificate
93 (keyName, *publicKey, signerCertificateName, notBefore, notAfter);
94
95 identityStorage_->addCertificate(*certificate);
96
97 return certificate->getName();
98}
99
100ptr_lib::shared_ptr<IdentityCertificate>
101IdentityManager::createIdentityCertificate
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700102 (const Name& keyName, const PublicKey& publicKey, const Name& signerCertificateName, const MillisecondsSince1970& notBefore, const MillisecondsSince1970& notAfter)
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700103{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700104 shared_ptr<IdentityCertificate> certificate(new IdentityCertificate());
105
106 Name certificateName;
Jeff Thompsondb686892013-10-18 17:16:31 -0700107 MillisecondsSince1970 ti = ::ndn_getNowMilliseconds();
108 // Get the number of seconds.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700109 ostringstream oss;
Jeff Thompsondb686892013-10-18 17:16:31 -0700110 oss << floor(ti / 1000.0);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700111
112 certificateName.append(keyName).append("ID-CERT").append(oss.str());
113 certificate->setName(certificateName);
114
115 certificate->setNotBefore(notBefore);
116 certificate->setNotAfter(notAfter);
117 certificate->setPublicKeyInfo(publicKey);
Jeff Thompsondb686892013-10-18 17:16:31 -0700118 certificate->addSubjectDescription(CertificateSubjectDescription("2.5.4.41", keyName.toUri()));
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700119 certificate->encode();
120
121 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
122
123 KeyLocator keyLocator;
Jeff Thompsondb686892013-10-18 17:16:31 -0700124 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700125 keyLocator.setKeyName(signerCertificateName);
126
127 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsondb686892013-10-18 17:16:31 -0700128 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(*publicKey.getDigest());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700129
Jeff Thompsondb686892013-10-18 17:16:31 -0700130 certificate->setSignature(*sha256Sig);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700131
Jeff Thompsondb686892013-10-18 17:16:31 -0700132 SignedBlob unsignedData = certificate->wireEncode();
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700133
Jeff Thompsondb686892013-10-18 17:16:31 -0700134 Blob sigBits = privateKeyStorage_->sign(unsignedData, keyName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700135
Jeff Thompsonba82c162013-10-18 17:21:23 -0700136 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700137
138 return certificate;
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700139}
140
141void
142IdentityManager::addCertificateAsDefault(const IdentityCertificate& certificate)
143{
144 identityStorage_->addCertificate(certificate);
145
146 Name keyName = identityStorage_->getKeyNameForCertificate(certificate.getName());
147
148 setDefaultKeyForIdentity(keyName);
149
150 setDefaultCertificateForKey(certificate.getName());
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700151}
152
153void
154IdentityManager::setDefaultCertificateForKey(const Name& certificateName)
155{
156 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700157
158 if(!identityStorage_->doesKeyExist(keyName))
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700159 throw SecurityException("No corresponding Key record for certificaite!");
160
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700161 identityStorage_->setDefaultCertificateNameForKey(keyName, certificateName);
162}
163
164ptr_lib::shared_ptr<Signature>
165IdentityManager::signByCertificate(const uint8_t* data, size_t dataLength, const Name& certificateName)
166{
Jeff Thompsonba82c162013-10-18 17:21:23 -0700167 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700168
169 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
170
Jeff Thompsonba82c162013-10-18 17:21:23 -0700171 Blob sigBits = privateKeyStorage_->sign(data, dataLength, keyName.toUri());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700172
173 //For temporary usage, we support RSA + SHA256 only, but will support more.
Jeff Thompsonba82c162013-10-18 17:21:23 -0700174 shared_ptr<Sha256WithRsaSignature> sha256Sig(new Sha256WithRsaSignature());
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700175
176 KeyLocator keyLocator;
Jeff Thompsonba82c162013-10-18 17:21:23 -0700177 keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
178 keyLocator.setKeyName(certificateName);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700179
180 sha256Sig->setKeyLocator(keyLocator);
Jeff Thompsonba82c162013-10-18 17:21:23 -0700181 sha256Sig->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(*publicKey->getDigest());
182 sha256Sig->setSignature(sigBits);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700183
184 return sha256Sig;
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700185}
186
187void
Jeff Thompson86e1d752013-09-17 17:22:38 -0700188IdentityManager::signByCertificate(Data &data, const Name &certificateName, WireFormat& wireFormat)
Jeff Thompson41471912013-09-12 16:21:50 -0700189{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700190 Name keyName = identityStorage_->getKeyNameForCertificate(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700191
192 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700193
194 // For temporary usage, we support RSA + SHA256 only, but will support more.
195 data.setSignature(Sha256WithRsaSignature());
196 // Get a pointer to the clone which Data made.
197 Sha256WithRsaSignature *signature = dynamic_cast<Sha256WithRsaSignature*>(data.getSignature());
198 DigestAlgorithm digestAlgorithm = DIGEST_ALGORITHM_SHA256;
199
200 signature->getKeyLocator().setType(ndn_KeyLocatorType_KEYNAME);
201 signature->getKeyLocator().setKeyName(certificateName);
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700202 // Omit the certificate digest.
203 signature->getKeyLocator().setKeyNameType((ndn_KeyNameType)-1);
Jeff Thompson86e1d752013-09-17 17:22:38 -0700204 // Ignore witness and leave the digestAlgorithm as the default.
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700205 signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publicKey->getDigest());
Jeff Thompson41471912013-09-12 16:21:50 -0700206
Jeff Thompson86e1d752013-09-17 17:22:38 -0700207 // Encode once to get the signed portion.
208 SignedBlob encoding = data.wireEncode(wireFormat);
209
210 signature->setSignature
Jeff Thompson9296f0c2013-09-23 18:10:27 -0700211 (privateKeyStorage_->sign(encoding.signedBuf(), encoding.signedSize(), keyName, digestAlgorithm));
Jeff Thompson86e1d752013-09-17 17:22:38 -0700212
213 // Encode again to include the signature.
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700214 data.wireEncode(wireFormat);
Jeff Thompson41471912013-09-12 16:21:50 -0700215}
216
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700217shared_ptr<IdentityCertificate>
218IdentityManager::selfSign(const Name& keyName)
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700219{
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700220#if 0
221 shared_ptr<IdentityCertificate> certificate = Create<IdentityCertificate>();
222
223 Name certificateName;
224 certificateName.append(keyName).append("ID-CERT").append("0");
225 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700226
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700227 Blob keyBlob = identityStorage_->getKey(keyName);
228 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700229
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700230 tm current = boost::posix_time::to_tm(time::Now());
231 current.tm_hour = 0;
232 current.tm_min = 0;
233 current.tm_sec = 0;
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700234 MillisecondsSince1970 notBefore = boost::posix_time::ptime_from_tm(current);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700235 current.tm_year = current.tm_year + 20;
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700236 MillisecondsSince1970 notAfter = boost::posix_time::ptime_from_tm(current);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700237
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700238 certificate->setNotBefore(notBefore);
239 certificate->setNotAfter(notAfter);
240 certificate->setPublicKeyInfo(*publicKey);
241 certificate->addSubjectDescription(CertificateSubDescrypt("2.5.4.41", keyName.toUri()));
242 certificate->encode();
243
244 shared_ptr<signature::Sha256WithRsa> sha256Sig = shared_ptr<signature::Sha256WithRsa>::Create();
245
246 KeyLocator keyLocator;
247 keyLocator.setType(KeyLocator::KEYNAME);
248 keyLocator.setKeyName(certificateName);
249
250 sha256Sig->setKeyLocator(keyLocator);
251 sha256Sig->setPublisherKeyDigest(*publicKey->getDigest());
252
253 certificate->setSignature(sha256Sig);
254
255 Blob unsignedData = certificate->encodeToUnsignedWire();
256
257 Blob sigBits = privateKeyStorage_->sign(*unsignedData, keyName.toUri());
258
259 sha256Sig->setSignatureBits(*sigBits);
260
261 return certificate;
262#else
Jeff Thompson4affbf52013-10-18 14:36:46 -0700263 throw runtime_error("not implemented");
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700264#endif
265}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700266
Jeff Thompson41471912013-09-12 16:21:50 -0700267}