blob: 6b3c29cbed87c9d1746ea44a4aa14388336d12b6 [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 Thompsondb686892013-10-18 17:16:31 -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{
167#if 0
168 Name keyName = identityStorage_->getKeyNameForCertificate(certName);
169
170 shared_ptr<PublicKey> publicKey = privateKeyStorage_->getPublicKey(keyName.toUri());
171
172 Blob sigBits = privateKeyStorage_->sign(blob, keyName.toUri());
173
174 //For temporary usage, we support RSA + SHA256 only, but will support more.
175 shared_ptr<signature::Sha256WithRsa> sha256Sig = shared_ptr<signature::Sha256WithRsa>::Create();
176
177 KeyLocator keyLocator;
178 keyLocator.setType(KeyLocator::KEYNAME);
179 keyLocator.setKeyName(certName);
180
181 sha256Sig->setKeyLocator(keyLocator);
182 sha256Sig->setPublisherKeyDigest(*publicKey->getDigest());
183 sha256Sig->setSignatureBits(*sigBits);
184
185 return sha256Sig;
186#else
Jeff Thompson4affbf52013-10-18 14:36:46 -0700187 throw runtime_error("not implemented");
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700188#endif
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 Thompsonc69163b2013-10-12 13:49:50 -0700224#if 0
225 shared_ptr<IdentityCertificate> certificate = Create<IdentityCertificate>();
226
227 Name certificateName;
228 certificateName.append(keyName).append("ID-CERT").append("0");
229 certificate->setName(certificateName);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700230
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700231 Blob keyBlob = identityStorage_->getKey(keyName);
232 shared_ptr<PublicKey> publicKey = PublicKey::fromDer(keyBlob);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700233
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700234 tm current = boost::posix_time::to_tm(time::Now());
235 current.tm_hour = 0;
236 current.tm_min = 0;
237 current.tm_sec = 0;
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700238 MillisecondsSince1970 notBefore = boost::posix_time::ptime_from_tm(current);
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700239 current.tm_year = current.tm_year + 20;
Jeff Thompson9a8e82f2013-10-17 14:13:43 -0700240 MillisecondsSince1970 notAfter = boost::posix_time::ptime_from_tm(current);
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700241
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700242 certificate->setNotBefore(notBefore);
243 certificate->setNotAfter(notAfter);
244 certificate->setPublicKeyInfo(*publicKey);
245 certificate->addSubjectDescription(CertificateSubDescrypt("2.5.4.41", keyName.toUri()));
246 certificate->encode();
247
248 shared_ptr<signature::Sha256WithRsa> sha256Sig = shared_ptr<signature::Sha256WithRsa>::Create();
249
250 KeyLocator keyLocator;
251 keyLocator.setType(KeyLocator::KEYNAME);
252 keyLocator.setKeyName(certificateName);
253
254 sha256Sig->setKeyLocator(keyLocator);
255 sha256Sig->setPublisherKeyDigest(*publicKey->getDigest());
256
257 certificate->setSignature(sha256Sig);
258
259 Blob unsignedData = certificate->encodeToUnsignedWire();
260
261 Blob sigBits = privateKeyStorage_->sign(*unsignedData, keyName.toUri());
262
263 sha256Sig->setSignatureBits(*sigBits);
264
265 return certificate;
266#else
Jeff Thompson4affbf52013-10-18 14:36:46 -0700267 throw runtime_error("not implemented");
Jeff Thompsone7e069b2013-09-27 15:48:48 -0700268#endif
269}
Jeff Thompsonc69163b2013-10-12 13:49:50 -0700270
Jeff Thompson41471912013-09-12 16:21:50 -0700271}