blob: da88444a667df0bb612b64b7dd6e0e51e8f29df4 [file] [log] [blame]
Jeff Thompsona5dc3512013-10-17 10:26:19 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
6 * See COPYING for copyright and distribution information.
7 */
8
Alexander Afanasyev8e96e582013-11-19 12:07:04 -08009#include <ndn-cpp/common.hpp>
10
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080011#include "certificate.hpp"
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080012
13#if NDN_CPP_USE_SYSTEM_BOOST
14#include <boost/iostreams/stream.hpp>
15#include <boost/iostreams/device/array.hpp>
16namespace ndnboost = boost;
17#else
Jeff Thompson415da1e2013-10-17 16:52:59 -070018// We can use ndnboost::iostreams because this is internal and will not conflict with the application if it uses boost::iostreams.
Jeff Thompson2d47db72013-10-17 15:19:52 -070019#include <ndnboost/iostreams/stream.hpp>
20#include <ndnboost/iostreams/device/array.hpp>
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080021#endif
22
Jeff Thompsona5dc3512013-10-17 10:26:19 -070023#include "../../util/logging.hpp"
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080024// #include "../../util/blob-stream.hpp"
25// #include <ndn-cpp/security/certificate/certificate.hpp>
26#include "../../util/time.hpp"
27
28#include <cryptopp/asn.h>
29#include <cryptopp/base64.h>
30#include <cryptopp/files.h>
31
32#include "../../encoding/cryptopp/asn_ext.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070033
34INIT_LOGGER("ndn.security.Certificate");
35
36using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070037
38namespace ndn {
39
40Certificate::Certificate()
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080041 : notBefore_(std::numeric_limits<MillisecondsSince1970>::max())
42 , notAfter_(std::numeric_limits<MillisecondsSince1970>::min())
Jeff Thompsona5dc3512013-10-17 10:26:19 -070043{}
44
45Certificate::Certificate(const Data& data)
46// Use the copy constructor. It clones the signature object.
47: Data(data)
48{
49 // _LOG_DEBUG("Finish local copy: " << getContent().getContent().size());
50
51 decode();
52}
53
54Certificate::~Certificate()
55{
56 //TODO:
57}
58
59bool
60Certificate::isTooEarly()
61{
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070062 MillisecondsSince1970 now = ndn_getNowMilliseconds();
Jeff Thompsona5dc3512013-10-17 10:26:19 -070063 if(now < notBefore_)
64 return true;
65 else
66 return false;
67}
68
69bool
70Certificate::isTooLate()
71{
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070072 MillisecondsSince1970 now = ndn_getNowMilliseconds();
Jeff Thompsona5dc3512013-10-17 10:26:19 -070073 if(now > notAfter_)
74 return true;
75 else
76 return false;
77}
78
Jeff Thompsona5dc3512013-10-17 10:26:19 -070079void
80Certificate::encode()
81{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080082 // Name
83 // <key_name>/ID-CERT/<id#>
84 // Content
85 // DER encoded idCert:
86 //
87 // idCert ::= SEQUENCE {
88 // validity Validity,
89 // subject Name,
90 // subjectPubKeyInfo SubjectPublicKeyInfo,
91 // extension Extensions OPTIONAL }
92 //
93 // Validity ::= SEQUENCE {
94 // notBefore Time,
95 // notAfter Time }
96 //
97 // Name ::= CHOICE {
98 // RDNSequence }
99 //
100 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
101 //
102 // RelativeDistinguishedName ::=
103 // SET OF AttributeTypeAndValue
104 //
105 // SubjectPublicKeyInfo ::= SEQUENCE {
106 // algorithm AlgorithmIdentifier
107 // keybits BIT STRING }
108 //
109 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
110 //
111 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
112 //
113 // KeyLocator
114 // issuer’s certificate name
115 // Signature
116
117 using namespace CryptoPP;
118
119 OBufferStream os;
120 CryptoPP::FileSink sink(os);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700121
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800122 // idCert ::= SEQUENCE {
123 // validity Validity,
124 // subject Name,
125 // subjectPubKeyInfo SubjectPublicKeyInfo,
126 // extension Extensions OPTIONAL }
127 DERSequenceEncoder idCert(sink);
128 {
129 // Validity ::= SEQUENCE {
130 // notBefore Time,
131 // notAfter Time }
132 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700133 {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800134 DEREncodeGeneralTime(validity, notBefore_);
135 DEREncodeGeneralTime(validity, notAfter_);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700136 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800137 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700138
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800139 // Name ::= CHOICE {
140 // RDNSequence }
141 //
142 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
143 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700144 {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800145 for(SubjectDescriptionList::iterator it = subjectDescriptionList_.begin();
146 it != subjectDescriptionList_.end(); ++it)
147 {
148 it->encode(name);
149 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700150 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800151 name.MessageEnd();
152
153 // SubjectPublicKeyInfo
154 key_.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700155
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800156 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
157 //
158 // Extension ::= SEQUENCE {
159 // extnID OBJECT IDENTIFIER,
160 // critical BOOLEAN DEFAULT FALSE,
161 // extnValue OCTET STRING }
162 if(!extensionList_.empty())
163 {
164 DERSequenceEncoder extensions(idCert);
165 {
166
167 for(ExtensionList::iterator it = extensionList_.begin();
168 it != extensionList_.end(); ++it)
169 {
170 it->encode(extensions);
171 }
172 }
173 extensions.MessageEnd();
174 }
175 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700176
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800177 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700178
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800179 setContent(os.buf());
180 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700181}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700182
183void
184Certificate::decode()
185{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800186 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700187
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800188 OBufferStream os;
189 CryptoPP::StringSource source(getContent().value(), getContent().value_size(), true);
190
191 // idCert ::= SEQUENCE {
192 // validity Validity,
193 // subject Name,
194 // subjectPubKeyInfo SubjectPublicKeyInfo,
195 // extension Extensions OPTIONAL }
196 BERSequenceDecoder idCert(source);
197 {
198 // Validity ::= SEQUENCE {
199 // notBefore Time,
200 // notAfter Time }
201 BERSequenceDecoder validity(idCert);
202 {
203 BERDecodeTime(validity, notBefore_);
204 BERDecodeTime(validity, notAfter_);
205 }
206 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700207
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800208 // Name ::= CHOICE {
209 // RDNSequence }
210 //
211 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
212 subjectDescriptionList_.clear();
213 BERSequenceDecoder name(idCert);
214 {
215 while(!name.EndReached())
216 {
217 subjectDescriptionList_.push_back(CertificateSubjectDescription(name));
218 }
219 }
220 name.MessageEnd();
221
222 // SubjectPublicKeyInfo ::= SEQUENCE {
223 // algorithm AlgorithmIdentifier
224 // keybits BIT STRING }
225 key_.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700226
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800227 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
228 //
229 // Extension ::= SEQUENCE {
230 // extnID OBJECT IDENTIFIER,
231 // critical BOOLEAN DEFAULT FALSE,
232 // extnValue OCTET STRING }
233 extensionList_.clear();
234 if(!idCert.EndReached())
235 {
236 BERSequenceDecoder extensions(idCert);
237 {
238 while(!extensions.EndReached())
239 {
240 extensionList_.push_back(CertificateExtension(extensions));
241 }
242 }
243 extensions.MessageEnd();
244 }
245 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700246
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800247 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700248}
249
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700250void
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800251Certificate::printCertificate(std::ostream &os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700252{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800253 os << "Certificate name: " << endl;
254 os << " " << getName() << endl;
255 os << "Validity:" << endl;
256 {
257 os << " NotBefore: " << toIsoString(notBefore_) << endl;
258 os << " NotAfter: " << toIsoString(notAfter_) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700259 }
260
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800261 os << "Subject Description:" << endl;
262 for(SubjectDescriptionList::const_iterator it = subjectDescriptionList_.begin();
263 it != subjectDescriptionList_.end(); ++it)
264 {
265 os << " " << it->getOidString() << ": " << it->getValue() << endl;
266 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700267
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800268 os << "Public key bits: " << endl;
269 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
270 key_.encode(encoder);
271
272 // ndnboost::iostreams::stream<ndnboost::iostreams::array_source> is((const char*)key_.getKeyDer().buf(), key_.getKeyDer().size());
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700273
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800274 // ptr_lib::shared_ptr<der::DerNode> keyRoot = der::DerNode::parse(reinterpret_cast<der::InputIterator&> (is));
275
276 // der::PrintVisitor printVisitor;
277 // keyRoot->accept(printVisitor, string(""));
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700278}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700279
280}