blob: f0dfdf2e1568e172d99c1527b6a6bb78a998e846 [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 Afanasyev09c613f2014-01-29 00:23:58 -08009#include "common.hpp"
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080010
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080011#include "certificate.hpp"
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080012
Yingdi Yu4f324632014-01-15 18:10:03 -080013#include "../util/logging.hpp"
14#include "../util/time.hpp"
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080015
16#include <cryptopp/asn.h>
17#include <cryptopp/base64.h>
18#include <cryptopp/files.h>
19
Yingdi Yu4f324632014-01-15 18:10:03 -080020#include "../encoding/cryptopp/asn_ext.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070021
22INIT_LOGGER("ndn.security.Certificate");
23
24using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070025
26namespace ndn {
27
28Certificate::Certificate()
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080029 : notBefore_(std::numeric_limits<MillisecondsSince1970>::max())
30 , notAfter_(std::numeric_limits<MillisecondsSince1970>::min())
Jeff Thompsona5dc3512013-10-17 10:26:19 -070031{}
32
33Certificate::Certificate(const Data& data)
34// Use the copy constructor. It clones the signature object.
35: Data(data)
36{
37 // _LOG_DEBUG("Finish local copy: " << getContent().getContent().size());
38
39 decode();
40}
41
42Certificate::~Certificate()
43{
44 //TODO:
45}
46
47bool
48Certificate::isTooEarly()
49{
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070050 MillisecondsSince1970 now = ndn_getNowMilliseconds();
Jeff Thompsona5dc3512013-10-17 10:26:19 -070051 if(now < notBefore_)
52 return true;
53 else
54 return false;
55}
56
57bool
58Certificate::isTooLate()
59{
Jeff Thompson9a8e82f2013-10-17 14:13:43 -070060 MillisecondsSince1970 now = ndn_getNowMilliseconds();
Jeff Thompsona5dc3512013-10-17 10:26:19 -070061 if(now > notAfter_)
62 return true;
63 else
64 return false;
65}
66
Jeff Thompsona5dc3512013-10-17 10:26:19 -070067void
68Certificate::encode()
69{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080070 // Name
71 // <key_name>/ID-CERT/<id#>
72 // Content
73 // DER encoded idCert:
74 //
75 // idCert ::= SEQUENCE {
76 // validity Validity,
77 // subject Name,
78 // subjectPubKeyInfo SubjectPublicKeyInfo,
79 // extension Extensions OPTIONAL }
80 //
81 // Validity ::= SEQUENCE {
82 // notBefore Time,
83 // notAfter Time }
84 //
85 // Name ::= CHOICE {
86 // RDNSequence }
87 //
88 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
89 //
90 // RelativeDistinguishedName ::=
91 // SET OF AttributeTypeAndValue
92 //
93 // SubjectPublicKeyInfo ::= SEQUENCE {
94 // algorithm AlgorithmIdentifier
95 // keybits BIT STRING }
96 //
97 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
98 //
99 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
100 //
101 // KeyLocator
102 // issuer’s certificate name
103 // Signature
104
105 using namespace CryptoPP;
106
107 OBufferStream os;
108 CryptoPP::FileSink sink(os);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700109
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800110 // idCert ::= SEQUENCE {
111 // validity Validity,
112 // subject Name,
113 // subjectPubKeyInfo SubjectPublicKeyInfo,
114 // extension Extensions OPTIONAL }
115 DERSequenceEncoder idCert(sink);
116 {
117 // Validity ::= SEQUENCE {
118 // notBefore Time,
119 // notAfter Time }
120 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700121 {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800122 DEREncodeGeneralTime(validity, notBefore_);
123 DEREncodeGeneralTime(validity, notAfter_);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700124 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800125 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700126
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800127 // Name ::= CHOICE {
128 // RDNSequence }
129 //
130 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
131 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700132 {
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800133 for(SubjectDescriptionList::iterator it = subjectDescriptionList_.begin();
134 it != subjectDescriptionList_.end(); ++it)
135 {
136 it->encode(name);
137 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700138 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800139 name.MessageEnd();
140
141 // SubjectPublicKeyInfo
142 key_.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700143
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800144 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
145 //
146 // Extension ::= SEQUENCE {
147 // extnID OBJECT IDENTIFIER,
148 // critical BOOLEAN DEFAULT FALSE,
149 // extnValue OCTET STRING }
150 if(!extensionList_.empty())
151 {
152 DERSequenceEncoder extensions(idCert);
153 {
154
155 for(ExtensionList::iterator it = extensionList_.begin();
156 it != extensionList_.end(); ++it)
157 {
158 it->encode(extensions);
159 }
160 }
161 extensions.MessageEnd();
162 }
163 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700164
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800165 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700166
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800167 setContent(os.buf());
168 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700169}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700170
171void
172Certificate::decode()
173{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800174 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700175
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800176 OBufferStream os;
177 CryptoPP::StringSource source(getContent().value(), getContent().value_size(), true);
178
179 // idCert ::= SEQUENCE {
180 // validity Validity,
181 // subject Name,
182 // subjectPubKeyInfo SubjectPublicKeyInfo,
183 // extension Extensions OPTIONAL }
184 BERSequenceDecoder idCert(source);
185 {
186 // Validity ::= SEQUENCE {
187 // notBefore Time,
188 // notAfter Time }
189 BERSequenceDecoder validity(idCert);
190 {
191 BERDecodeTime(validity, notBefore_);
192 BERDecodeTime(validity, notAfter_);
193 }
194 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700195
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800196 // Name ::= CHOICE {
197 // RDNSequence }
198 //
199 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
200 subjectDescriptionList_.clear();
201 BERSequenceDecoder name(idCert);
202 {
203 while(!name.EndReached())
204 {
205 subjectDescriptionList_.push_back(CertificateSubjectDescription(name));
206 }
207 }
208 name.MessageEnd();
209
210 // SubjectPublicKeyInfo ::= SEQUENCE {
211 // algorithm AlgorithmIdentifier
212 // keybits BIT STRING }
213 key_.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700214
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800215 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
216 //
217 // Extension ::= SEQUENCE {
218 // extnID OBJECT IDENTIFIER,
219 // critical BOOLEAN DEFAULT FALSE,
220 // extnValue OCTET STRING }
221 extensionList_.clear();
222 if(!idCert.EndReached())
223 {
224 BERSequenceDecoder extensions(idCert);
225 {
226 while(!extensions.EndReached())
227 {
228 extensionList_.push_back(CertificateExtension(extensions));
229 }
230 }
231 extensions.MessageEnd();
232 }
233 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700234
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800235 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700236}
237
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700238void
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800239Certificate::printCertificate(std::ostream &os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700240{
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800241 os << "Certificate name:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800242 os << " " << getName() << endl;
243 os << "Validity:" << endl;
244 {
245 os << " NotBefore: " << toIsoString(notBefore_) << endl;
246 os << " NotAfter: " << toIsoString(notAfter_) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700247 }
248
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800249 os << "Subject Description:" << endl;
250 for(SubjectDescriptionList::const_iterator it = subjectDescriptionList_.begin();
251 it != subjectDescriptionList_.end(); ++it)
252 {
253 os << " " << it->getOidString() << ": " << it->getValue() << endl;
254 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700255
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800256 os << "Public key bits:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800257 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
258 key_.encode(encoder);
259
260 // ndnboost::iostreams::stream<ndnboost::iostreams::array_source> is((const char*)key_.getKeyDer().buf(), key_.getKeyDer().size());
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700261
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800262 // ptr_lib::shared_ptr<der::DerNode> keyRoot = der::DerNode::parse(reinterpret_cast<der::InputIterator&> (is));
263
264 // der::PrintVisitor printVisitor;
265 // keyRoot->accept(printVisitor, string(""));
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700266}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700267
Yingdi Yufc40d872014-02-18 12:56:04 -0800268} // namespace ndn