blob: 73827a36d5130b994928288ab6a97c74191bf190 [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 Afanasyev736708b2014-01-06 14:45:34 -08009#if __clang__
10#pragma clang diagnostic push
11#pragma clang diagnostic ignored "-Wreorder"
12#pragma clang diagnostic ignored "-Wtautological-compare"
13#pragma clang diagnostic ignored "-Wunused-variable"
14#pragma clang diagnostic ignored "-Wunused-function"
15#elif __GNUC__
16#pragma GCC diagnostic ignored "-Wreorder"
17#pragma GCC diagnostic ignored "-Wtautological-compare"
18#pragma GCC diagnostic ignored "-Wunused-variable"
19#pragma GCC diagnostic ignored "-Wunused-function"
20#endif
21
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080022#include <ndn-cpp/common.hpp>
23
Alexander Afanasyev6be1a6a2014-01-06 00:08:14 -080024#include <ndn-cpp/security/certificate/certificate.hpp>
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080025
Jeff Thompsona5dc3512013-10-17 10:26:19 -070026#include "../../util/logging.hpp"
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080027#include "../../util/time.hpp"
28
29#include <cryptopp/asn.h>
30#include <cryptopp/base64.h>
31#include <cryptopp/files.h>
32
33#include "../../encoding/cryptopp/asn_ext.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070034
35INIT_LOGGER("ndn.security.Certificate");
36
37using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070038
39namespace ndn {
40
41Certificate::Certificate()
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080042 : notBefore_(std::numeric_limits<MillisecondsSince1970>::max())
43 , notAfter_(std::numeric_limits<MillisecondsSince1970>::min())
Jeff Thompsona5dc3512013-10-17 10:26:19 -070044{}
45
46Certificate::Certificate(const Data& data)
47// Use the copy constructor. It clones the signature object.
48: Data(data)
49{
50 // _LOG_DEBUG("Finish local copy: " << getContent().getContent().size());
51
52 decode();
53}
54
55Certificate::~Certificate()
56{
57 //TODO:
58}
59
60bool
61Certificate::isTooEarly()
62{
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070063 MillisecondsSince1970 now = ndn_getNowMilliseconds();
Jeff Thompsona5dc3512013-10-17 10:26:19 -070064 if(now < notBefore_)
65 return true;
66 else
67 return false;
68}
69
70bool
71Certificate::isTooLate()
72{
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070073 MillisecondsSince1970 now = ndn_getNowMilliseconds();
Jeff Thompsona5dc3512013-10-17 10:26:19 -070074 if(now > notAfter_)
75 return true;
76 else
77 return false;
78}
79
Jeff Thompsona5dc3512013-10-17 10:26:19 -070080void
81Certificate::encode()
82{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080083 // Name
84 // <key_name>/ID-CERT/<id#>
85 // Content
86 // DER encoded idCert:
87 //
88 // idCert ::= SEQUENCE {
89 // validity Validity,
90 // subject Name,
91 // subjectPubKeyInfo SubjectPublicKeyInfo,
92 // extension Extensions OPTIONAL }
93 //
94 // Validity ::= SEQUENCE {
95 // notBefore Time,
96 // notAfter Time }
97 //
98 // Name ::= CHOICE {
99 // RDNSequence }
100 //
101 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
102 //
103 // RelativeDistinguishedName ::=
104 // SET OF AttributeTypeAndValue
105 //
106 // SubjectPublicKeyInfo ::= SEQUENCE {
107 // algorithm AlgorithmIdentifier
108 // keybits BIT STRING }
109 //
110 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
111 //
112 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
113 //
114 // KeyLocator
115 // issuer’s certificate name
116 // Signature
117
118 using namespace CryptoPP;
119
120 OBufferStream os;
121 CryptoPP::FileSink sink(os);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700122
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800123 // idCert ::= SEQUENCE {
124 // validity Validity,
125 // subject Name,
126 // subjectPubKeyInfo SubjectPublicKeyInfo,
127 // extension Extensions OPTIONAL }
128 DERSequenceEncoder idCert(sink);
129 {
130 // Validity ::= SEQUENCE {
131 // notBefore Time,
132 // notAfter Time }
133 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700134 {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800135 DEREncodeGeneralTime(validity, notBefore_);
136 DEREncodeGeneralTime(validity, notAfter_);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700137 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800138 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700139
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800140 // Name ::= CHOICE {
141 // RDNSequence }
142 //
143 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
144 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700145 {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800146 for(SubjectDescriptionList::iterator it = subjectDescriptionList_.begin();
147 it != subjectDescriptionList_.end(); ++it)
148 {
149 it->encode(name);
150 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700151 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800152 name.MessageEnd();
153
154 // SubjectPublicKeyInfo
155 key_.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700156
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800157 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
158 //
159 // Extension ::= SEQUENCE {
160 // extnID OBJECT IDENTIFIER,
161 // critical BOOLEAN DEFAULT FALSE,
162 // extnValue OCTET STRING }
163 if(!extensionList_.empty())
164 {
165 DERSequenceEncoder extensions(idCert);
166 {
167
168 for(ExtensionList::iterator it = extensionList_.begin();
169 it != extensionList_.end(); ++it)
170 {
171 it->encode(extensions);
172 }
173 }
174 extensions.MessageEnd();
175 }
176 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700177
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800178 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700179
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800180 setContent(os.buf());
181 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700182}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700183
184void
185Certificate::decode()
186{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800187 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700188
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800189 OBufferStream os;
190 CryptoPP::StringSource source(getContent().value(), getContent().value_size(), true);
191
192 // idCert ::= SEQUENCE {
193 // validity Validity,
194 // subject Name,
195 // subjectPubKeyInfo SubjectPublicKeyInfo,
196 // extension Extensions OPTIONAL }
197 BERSequenceDecoder idCert(source);
198 {
199 // Validity ::= SEQUENCE {
200 // notBefore Time,
201 // notAfter Time }
202 BERSequenceDecoder validity(idCert);
203 {
204 BERDecodeTime(validity, notBefore_);
205 BERDecodeTime(validity, notAfter_);
206 }
207 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700208
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800209 // Name ::= CHOICE {
210 // RDNSequence }
211 //
212 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
213 subjectDescriptionList_.clear();
214 BERSequenceDecoder name(idCert);
215 {
216 while(!name.EndReached())
217 {
218 subjectDescriptionList_.push_back(CertificateSubjectDescription(name));
219 }
220 }
221 name.MessageEnd();
222
223 // SubjectPublicKeyInfo ::= SEQUENCE {
224 // algorithm AlgorithmIdentifier
225 // keybits BIT STRING }
226 key_.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700227
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800228 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
229 //
230 // Extension ::= SEQUENCE {
231 // extnID OBJECT IDENTIFIER,
232 // critical BOOLEAN DEFAULT FALSE,
233 // extnValue OCTET STRING }
234 extensionList_.clear();
235 if(!idCert.EndReached())
236 {
237 BERSequenceDecoder extensions(idCert);
238 {
239 while(!extensions.EndReached())
240 {
241 extensionList_.push_back(CertificateExtension(extensions));
242 }
243 }
244 extensions.MessageEnd();
245 }
246 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700247
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800248 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700249}
250
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700251void
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800252Certificate::printCertificate(std::ostream &os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700253{
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800254 os << "Certificate name:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800255 os << " " << getName() << endl;
256 os << "Validity:" << endl;
257 {
258 os << " NotBefore: " << toIsoString(notBefore_) << endl;
259 os << " NotAfter: " << toIsoString(notAfter_) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700260 }
261
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800262 os << "Subject Description:" << endl;
263 for(SubjectDescriptionList::const_iterator it = subjectDescriptionList_.begin();
264 it != subjectDescriptionList_.end(); ++it)
265 {
266 os << " " << it->getOidString() << ": " << it->getValue() << endl;
267 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700268
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800269 os << "Public key bits:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800270 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
271 key_.encode(encoder);
272
273 // ndnboost::iostreams::stream<ndnboost::iostreams::array_source> is((const char*)key_.getKeyDer().buf(), key_.getKeyDer().size());
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700274
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800275 // ptr_lib::shared_ptr<der::DerNode> keyRoot = der::DerNode::parse(reinterpret_cast<der::InputIterator&> (is));
276
277 // der::PrintVisitor printVisitor;
278 // keyRoot->accept(printVisitor, string(""));
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700279}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700280
281}