blob: 690ec3166e870b4d8d0faf41e59dda44a6f5a97d [file] [log] [blame]
Jeff Thompsona5dc3512013-10-17 10:26:19 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
13 * @author Jeff Thompson <jefft0@remap.ucla.edu>
14 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Jeff Thompsona5dc3512013-10-17 10:26:19 -070015 */
16
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080017#include "common.hpp"
Alexander Afanasyev8e96e582013-11-19 12:07:04 -080018
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080019#include "certificate.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080020#include "../util/time.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070021#include "cryptopp.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080022#include "../encoding/cryptopp/asn_ext.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070023
Jeff Thompsona5dc3512013-10-17 10:26:19 -070024using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070025
26namespace ndn {
27
28Certificate::Certificate()
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070029 : m_notBefore(time::system_clock::TimePoint::max())
30 , m_notAfter(time::system_clock::TimePoint::min())
31{
32}
Jeff Thompsona5dc3512013-10-17 10:26:19 -070033
34Certificate::Certificate(const Data& data)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070035 // Use the copy constructor. It clones the signature object.
36 : Data(data)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070037{
Jeff Thompsona5dc3512013-10-17 10:26:19 -070038 decode();
39}
40
41Certificate::~Certificate()
42{
43 //TODO:
44}
45
46bool
47Certificate::isTooEarly()
48{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070049 if (time::system_clock::now() < m_notBefore)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070050 return true;
51 else
52 return false;
53}
54
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070055bool
Jeff Thompsona5dc3512013-10-17 10:26:19 -070056Certificate::isTooLate()
57{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070058 if (time::system_clock::now() > m_notAfter)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070059 return true;
60 else
61 return false;
62}
63
Jeff Thompsona5dc3512013-10-17 10:26:19 -070064void
65Certificate::encode()
66{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080067 // Name
68 // <key_name>/ID-CERT/<id#>
69 // Content
70 // DER encoded idCert:
71 //
72 // idCert ::= SEQUENCE {
73 // validity Validity,
74 // subject Name,
75 // subjectPubKeyInfo SubjectPublicKeyInfo,
76 // extension Extensions OPTIONAL }
77 //
78 // Validity ::= SEQUENCE {
79 // notBefore Time,
80 // notAfter Time }
81 //
82 // Name ::= CHOICE {
83 // RDNSequence }
84 //
85 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
86 //
87 // RelativeDistinguishedName ::=
88 // SET OF AttributeTypeAndValue
89 //
90 // SubjectPublicKeyInfo ::= SEQUENCE {
91 // algorithm AlgorithmIdentifier
92 // keybits BIT STRING }
93 //
94 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
95 //
96 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
97 //
98 // KeyLocator
99 // issuer’s certificate name
100 // Signature
101
102 using namespace CryptoPP;
103
104 OBufferStream os;
105 CryptoPP::FileSink sink(os);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700106
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800107 // idCert ::= SEQUENCE {
108 // validity Validity,
109 // subject Name,
110 // subjectPubKeyInfo SubjectPublicKeyInfo,
111 // extension Extensions OPTIONAL }
112 DERSequenceEncoder idCert(sink);
113 {
114 // Validity ::= SEQUENCE {
115 // notBefore Time,
116 // notAfter Time }
117 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700118 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700119 DEREncodeGeneralTime(validity, m_notBefore);
120 DEREncodeGeneralTime(validity, m_notAfter);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700121 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800122 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700123
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800124 // Name ::= CHOICE {
125 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700126 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800127 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
128 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700129 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700130 for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
131 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800132 {
133 it->encode(name);
134 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700135 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800136 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700137
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800138 // SubjectPublicKeyInfo
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700139 m_key.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700140
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800141 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
142 //
143 // Extension ::= SEQUENCE {
144 // extnID OBJECT IDENTIFIER,
145 // critical BOOLEAN DEFAULT FALSE,
146 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700147 if (!m_extensionList.empty())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800148 {
149 DERSequenceEncoder extensions(idCert);
150 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700151 for (ExtensionList::iterator it = m_extensionList.begin();
152 it != m_extensionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800153 {
154 it->encode(extensions);
155 }
156 }
157 extensions.MessageEnd();
158 }
159 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700160
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800161 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700162
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800163 setContent(os.buf());
164 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700165}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700166
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700167void
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700168Certificate::decode()
169{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800170 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700171
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800172 OBufferStream os;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700173 StringSource source(getContent().value(), getContent().value_size(), true);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700174
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800175 // idCert ::= SEQUENCE {
176 // validity Validity,
177 // subject Name,
178 // subjectPubKeyInfo SubjectPublicKeyInfo,
179 // extension Extensions OPTIONAL }
180 BERSequenceDecoder idCert(source);
181 {
182 // Validity ::= SEQUENCE {
183 // notBefore Time,
184 // notAfter Time }
185 BERSequenceDecoder validity(idCert);
186 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700187 BERDecodeTime(validity, m_notBefore);
188 BERDecodeTime(validity, m_notAfter);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800189 }
190 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700191
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800192 // Name ::= CHOICE {
193 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700194 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800195 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700196 m_subjectDescriptionList.clear();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800197 BERSequenceDecoder name(idCert);
198 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700199 while (!name.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800200 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700201 m_subjectDescriptionList.push_back(CertificateSubjectDescription(name));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800202 }
203 }
204 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700205
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800206 // SubjectPublicKeyInfo ::= SEQUENCE {
207 // algorithm AlgorithmIdentifier
208 // keybits BIT STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700209 m_key.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700210
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800211 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
212 //
213 // Extension ::= SEQUENCE {
214 // extnID OBJECT IDENTIFIER,
215 // critical BOOLEAN DEFAULT FALSE,
216 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700217 m_extensionList.clear();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700218 if (!idCert.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800219 {
220 BERSequenceDecoder extensions(idCert);
221 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700222 while (!extensions.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800223 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700224 m_extensionList.push_back(CertificateExtension(extensions));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800225 }
226 }
227 extensions.MessageEnd();
228 }
229 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700230
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800231 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700232}
233
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700234void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700235Certificate::printCertificate(std::ostream& os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700236{
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800237 os << "Certificate name:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800238 os << " " << getName() << endl;
239 os << "Validity:" << endl;
240 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700241 os << " NotBefore: " << time::toIsoString(m_notBefore) << endl;
242 os << " NotAfter: " << time::toIsoString(m_notAfter) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700243 }
244
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700245 os << "Subject Description:" << endl;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700246 for (SubjectDescriptionList::const_iterator it = m_subjectDescriptionList.begin();
247 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800248 {
249 os << " " << it->getOidString() << ": " << it->getValue() << endl;
250 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700251
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800252 os << "Public key bits:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800253 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700254 m_key.encode(encoder);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700255}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700256
Yingdi Yufc40d872014-02-18 12:56:04 -0800257} // namespace ndn