blob: 69597fc6d7b76276d4f57f9a1cfbff895643b813 [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"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070023#include "../encoding/buffer-stream.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070024
Jeff Thompsona5dc3512013-10-17 10:26:19 -070025using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070026
27namespace ndn {
28
29Certificate::Certificate()
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070030 : m_notBefore(time::system_clock::TimePoint::max())
31 , m_notAfter(time::system_clock::TimePoint::min())
32{
33}
Jeff Thompsona5dc3512013-10-17 10:26:19 -070034
35Certificate::Certificate(const Data& data)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070036 // Use the copy constructor. It clones the signature object.
37 : Data(data)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070038{
Jeff Thompsona5dc3512013-10-17 10:26:19 -070039 decode();
40}
41
42Certificate::~Certificate()
43{
44 //TODO:
45}
46
47bool
48Certificate::isTooEarly()
49{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070050 if (time::system_clock::now() < m_notBefore)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070051 return true;
52 else
53 return false;
54}
55
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070056bool
Jeff Thompsona5dc3512013-10-17 10:26:19 -070057Certificate::isTooLate()
58{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070059 if (time::system_clock::now() > m_notAfter)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070060 return true;
61 else
62 return false;
63}
64
Jeff Thompsona5dc3512013-10-17 10:26:19 -070065void
66Certificate::encode()
67{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080068 // Name
69 // <key_name>/ID-CERT/<id#>
70 // Content
71 // DER encoded idCert:
72 //
73 // idCert ::= SEQUENCE {
74 // validity Validity,
75 // subject Name,
76 // subjectPubKeyInfo SubjectPublicKeyInfo,
77 // extension Extensions OPTIONAL }
78 //
79 // Validity ::= SEQUENCE {
80 // notBefore Time,
81 // notAfter Time }
82 //
83 // Name ::= CHOICE {
84 // RDNSequence }
85 //
86 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
87 //
88 // RelativeDistinguishedName ::=
89 // SET OF AttributeTypeAndValue
90 //
91 // SubjectPublicKeyInfo ::= SEQUENCE {
92 // algorithm AlgorithmIdentifier
93 // keybits BIT STRING }
94 //
95 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
96 //
97 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
98 //
99 // KeyLocator
100 // issuer’s certificate name
101 // Signature
102
103 using namespace CryptoPP;
104
105 OBufferStream os;
106 CryptoPP::FileSink sink(os);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700107
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800108 // idCert ::= SEQUENCE {
109 // validity Validity,
110 // subject Name,
111 // subjectPubKeyInfo SubjectPublicKeyInfo,
112 // extension Extensions OPTIONAL }
113 DERSequenceEncoder idCert(sink);
114 {
115 // Validity ::= SEQUENCE {
116 // notBefore Time,
117 // notAfter Time }
118 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700119 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700120 DEREncodeGeneralTime(validity, m_notBefore);
121 DEREncodeGeneralTime(validity, m_notAfter);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700122 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800123 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700124
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800125 // Name ::= CHOICE {
126 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700127 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800128 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
129 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700130 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700131 for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
132 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800133 {
134 it->encode(name);
135 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700136 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800137 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700138
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800139 // SubjectPublicKeyInfo
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700140 m_key.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700141
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800142 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
143 //
144 // Extension ::= SEQUENCE {
145 // extnID OBJECT IDENTIFIER,
146 // critical BOOLEAN DEFAULT FALSE,
147 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700148 if (!m_extensionList.empty())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800149 {
150 DERSequenceEncoder extensions(idCert);
151 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700152 for (ExtensionList::iterator it = m_extensionList.begin();
153 it != m_extensionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800154 {
155 it->encode(extensions);
156 }
157 }
158 extensions.MessageEnd();
159 }
160 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700161
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800162 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700163
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800164 setContent(os.buf());
165 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700166}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700167
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700168void
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700169Certificate::decode()
170{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800171 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700172
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800173 OBufferStream os;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700174 StringSource source(getContent().value(), getContent().value_size(), true);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700175
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800176 // idCert ::= SEQUENCE {
177 // validity Validity,
178 // subject Name,
179 // subjectPubKeyInfo SubjectPublicKeyInfo,
180 // extension Extensions OPTIONAL }
181 BERSequenceDecoder idCert(source);
182 {
183 // Validity ::= SEQUENCE {
184 // notBefore Time,
185 // notAfter Time }
186 BERSequenceDecoder validity(idCert);
187 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700188 BERDecodeTime(validity, m_notBefore);
189 BERDecodeTime(validity, m_notAfter);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800190 }
191 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700192
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800193 // Name ::= CHOICE {
194 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700195 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800196 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700197 m_subjectDescriptionList.clear();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800198 BERSequenceDecoder name(idCert);
199 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700200 while (!name.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800201 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700202 m_subjectDescriptionList.push_back(CertificateSubjectDescription(name));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800203 }
204 }
205 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700206
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800207 // SubjectPublicKeyInfo ::= SEQUENCE {
208 // algorithm AlgorithmIdentifier
209 // keybits BIT STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700210 m_key.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700211
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800212 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
213 //
214 // Extension ::= SEQUENCE {
215 // extnID OBJECT IDENTIFIER,
216 // critical BOOLEAN DEFAULT FALSE,
217 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700218 m_extensionList.clear();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700219 if (!idCert.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800220 {
221 BERSequenceDecoder extensions(idCert);
222 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700223 while (!extensions.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800224 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700225 m_extensionList.push_back(CertificateExtension(extensions));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800226 }
227 }
228 extensions.MessageEnd();
229 }
230 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700231
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800232 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700233}
234
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700235void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700236Certificate::printCertificate(std::ostream& os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700237{
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800238 os << "Certificate name:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800239 os << " " << getName() << endl;
240 os << "Validity:" << endl;
241 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700242 os << " NotBefore: " << time::toIsoString(m_notBefore) << endl;
243 os << " NotAfter: " << time::toIsoString(m_notAfter) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700244 }
245
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700246 os << "Subject Description:" << endl;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700247 for (SubjectDescriptionList::const_iterator it = m_subjectDescriptionList.begin();
248 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800249 {
250 os << " " << it->getOidString() << ": " << it->getValue() << endl;
251 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700252
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800253 os << "Public key bits:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800254 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700255 m_key.encode(encoder);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700256}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700257
Yingdi Yufc40d872014-02-18 12:56:04 -0800258} // namespace ndn