blob: 167992b571406ae2fb0df3472268838f4a4c293b [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompsona5dc3512013-10-17 10:26:19 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
22 * @author Jeff Thompson <jefft0@remap.ucla.edu>
23 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Jeff Thompsona5dc3512013-10-17 10:26:19 -070024 */
25
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080026#include "common.hpp"
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080027
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080028#include "certificate.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080029#include "../util/time.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070030#include "cryptopp.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080031#include "../encoding/cryptopp/asn_ext.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070032#include "../encoding/buffer-stream.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070033
Jeff Thompsona5dc3512013-10-17 10:26:19 -070034using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070035
36namespace ndn {
37
38Certificate::Certificate()
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070039 : m_notBefore(time::system_clock::TimePoint::max())
40 , m_notAfter(time::system_clock::TimePoint::min())
41{
42}
Jeff Thompsona5dc3512013-10-17 10:26:19 -070043
44Certificate::Certificate(const Data& data)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070045 // Use the copy constructor. It clones the signature object.
46 : Data(data)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070047{
Jeff Thompsona5dc3512013-10-17 10:26:19 -070048 decode();
49}
50
51Certificate::~Certificate()
52{
53 //TODO:
54}
55
56bool
57Certificate::isTooEarly()
58{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070059 if (time::system_clock::now() < m_notBefore)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070060 return true;
61 else
62 return false;
63}
64
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070065bool
Jeff Thompsona5dc3512013-10-17 10:26:19 -070066Certificate::isTooLate()
67{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070068 if (time::system_clock::now() > m_notAfter)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070069 return true;
70 else
71 return false;
72}
73
Jeff Thompsona5dc3512013-10-17 10:26:19 -070074void
75Certificate::encode()
76{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080077 // Name
78 // <key_name>/ID-CERT/<id#>
79 // Content
80 // DER encoded idCert:
81 //
82 // idCert ::= SEQUENCE {
83 // validity Validity,
84 // subject Name,
85 // subjectPubKeyInfo SubjectPublicKeyInfo,
86 // extension Extensions OPTIONAL }
87 //
88 // Validity ::= SEQUENCE {
89 // notBefore Time,
90 // notAfter Time }
91 //
92 // Name ::= CHOICE {
93 // RDNSequence }
94 //
95 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
96 //
97 // RelativeDistinguishedName ::=
98 // SET OF AttributeTypeAndValue
99 //
100 // SubjectPublicKeyInfo ::= SEQUENCE {
101 // algorithm AlgorithmIdentifier
102 // keybits BIT STRING }
103 //
104 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
105 //
106 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
107 //
108 // KeyLocator
109 // issuer’s certificate name
110 // Signature
111
112 using namespace CryptoPP;
113
114 OBufferStream os;
115 CryptoPP::FileSink sink(os);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700116
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800117 // idCert ::= SEQUENCE {
118 // validity Validity,
119 // subject Name,
120 // subjectPubKeyInfo SubjectPublicKeyInfo,
121 // extension Extensions OPTIONAL }
122 DERSequenceEncoder idCert(sink);
123 {
124 // Validity ::= SEQUENCE {
125 // notBefore Time,
126 // notAfter Time }
127 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700128 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700129 DEREncodeGeneralTime(validity, m_notBefore);
130 DEREncodeGeneralTime(validity, m_notAfter);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700131 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800132 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700133
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800134 // Name ::= CHOICE {
135 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700136 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800137 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
138 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700139 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700140 for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
141 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800142 {
143 it->encode(name);
144 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700145 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800146 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700147
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800148 // SubjectPublicKeyInfo
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700149 m_key.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700150
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800151 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
152 //
153 // Extension ::= SEQUENCE {
154 // extnID OBJECT IDENTIFIER,
155 // critical BOOLEAN DEFAULT FALSE,
156 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700157 if (!m_extensionList.empty())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800158 {
159 DERSequenceEncoder extensions(idCert);
160 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700161 for (ExtensionList::iterator it = m_extensionList.begin();
162 it != m_extensionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800163 {
164 it->encode(extensions);
165 }
166 }
167 extensions.MessageEnd();
168 }
169 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700170
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800171 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700172
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800173 setContent(os.buf());
174 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700175}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700176
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700177void
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700178Certificate::decode()
179{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800180 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700181
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800182 OBufferStream os;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700183 StringSource source(getContent().value(), getContent().value_size(), true);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700184
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800185 // idCert ::= SEQUENCE {
186 // validity Validity,
187 // subject Name,
188 // subjectPubKeyInfo SubjectPublicKeyInfo,
189 // extension Extensions OPTIONAL }
190 BERSequenceDecoder idCert(source);
191 {
192 // Validity ::= SEQUENCE {
193 // notBefore Time,
194 // notAfter Time }
195 BERSequenceDecoder validity(idCert);
196 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700197 BERDecodeTime(validity, m_notBefore);
198 BERDecodeTime(validity, m_notAfter);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800199 }
200 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700201
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800202 // Name ::= CHOICE {
203 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700204 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800205 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700206 m_subjectDescriptionList.clear();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800207 BERSequenceDecoder name(idCert);
208 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700209 while (!name.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800210 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700211 m_subjectDescriptionList.push_back(CertificateSubjectDescription(name));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800212 }
213 }
214 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700215
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800216 // SubjectPublicKeyInfo ::= SEQUENCE {
217 // algorithm AlgorithmIdentifier
218 // keybits BIT STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700219 m_key.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700220
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800221 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
222 //
223 // Extension ::= SEQUENCE {
224 // extnID OBJECT IDENTIFIER,
225 // critical BOOLEAN DEFAULT FALSE,
226 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700227 m_extensionList.clear();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700228 if (!idCert.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800229 {
230 BERSequenceDecoder extensions(idCert);
231 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700232 while (!extensions.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800233 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700234 m_extensionList.push_back(CertificateExtension(extensions));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800235 }
236 }
237 extensions.MessageEnd();
238 }
239 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700240
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800241 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700242}
243
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700244void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700245Certificate::printCertificate(std::ostream& os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700246{
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800247 os << "Certificate name:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800248 os << " " << getName() << endl;
249 os << "Validity:" << endl;
250 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700251 os << " NotBefore: " << time::toIsoString(m_notBefore) << endl;
252 os << " NotAfter: " << time::toIsoString(m_notAfter) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700253 }
254
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700255 os << "Subject Description:" << endl;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700256 for (SubjectDescriptionList::const_iterator it = m_subjectDescriptionList.begin();
257 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800258 {
259 os << " " << it->getOidString() << ": " << it->getValue() << endl;
260 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700261
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800262 os << "Public key bits:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800263 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700264 m_key.encode(encoder);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700265}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700266
Yingdi Yufc40d872014-02-18 12:56:04 -0800267} // namespace ndn