blob: 9e12bfd4a5eec32d6aa8f837b2cab0388f303aec [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"
Yingdi Yu4f324632014-01-15 18:10:03 -080012#include "../util/time.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070013#include "cryptopp.hpp"
Yingdi Yu4f324632014-01-15 18:10:03 -080014#include "../encoding/cryptopp/asn_ext.hpp"
Jeff Thompsona5dc3512013-10-17 10:26:19 -070015
Jeff Thompsona5dc3512013-10-17 10:26:19 -070016using namespace std;
Jeff Thompsona5dc3512013-10-17 10:26:19 -070017
18namespace ndn {
19
20Certificate::Certificate()
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070021 : m_notBefore(time::system_clock::TimePoint::max())
22 , m_notAfter(time::system_clock::TimePoint::min())
23{
24}
Jeff Thompsona5dc3512013-10-17 10:26:19 -070025
26Certificate::Certificate(const Data& data)
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070027 // Use the copy constructor. It clones the signature object.
28 : Data(data)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070029{
Jeff Thompsona5dc3512013-10-17 10:26:19 -070030 decode();
31}
32
33Certificate::~Certificate()
34{
35 //TODO:
36}
37
38bool
39Certificate::isTooEarly()
40{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070041 if (time::system_clock::now() < m_notBefore)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070042 return true;
43 else
44 return false;
45}
46
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070047bool
Jeff Thompsona5dc3512013-10-17 10:26:19 -070048Certificate::isTooLate()
49{
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070050 if (time::system_clock::now() > m_notAfter)
Jeff Thompsona5dc3512013-10-17 10:26:19 -070051 return true;
52 else
53 return false;
54}
55
Jeff Thompsona5dc3512013-10-17 10:26:19 -070056void
57Certificate::encode()
58{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080059 // Name
60 // <key_name>/ID-CERT/<id#>
61 // Content
62 // DER encoded idCert:
63 //
64 // idCert ::= SEQUENCE {
65 // validity Validity,
66 // subject Name,
67 // subjectPubKeyInfo SubjectPublicKeyInfo,
68 // extension Extensions OPTIONAL }
69 //
70 // Validity ::= SEQUENCE {
71 // notBefore Time,
72 // notAfter Time }
73 //
74 // Name ::= CHOICE {
75 // RDNSequence }
76 //
77 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
78 //
79 // RelativeDistinguishedName ::=
80 // SET OF AttributeTypeAndValue
81 //
82 // SubjectPublicKeyInfo ::= SEQUENCE {
83 // algorithm AlgorithmIdentifier
84 // keybits BIT STRING }
85 //
86 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
87 //
88 // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
89 //
90 // KeyLocator
91 // issuer’s certificate name
92 // Signature
93
94 using namespace CryptoPP;
95
96 OBufferStream os;
97 CryptoPP::FileSink sink(os);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070098
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -080099 // idCert ::= SEQUENCE {
100 // validity Validity,
101 // subject Name,
102 // subjectPubKeyInfo SubjectPublicKeyInfo,
103 // extension Extensions OPTIONAL }
104 DERSequenceEncoder idCert(sink);
105 {
106 // Validity ::= SEQUENCE {
107 // notBefore Time,
108 // notAfter Time }
109 DERSequenceEncoder validity(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700110 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700111 DEREncodeGeneralTime(validity, m_notBefore);
112 DEREncodeGeneralTime(validity, m_notAfter);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700113 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800114 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700115
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800116 // Name ::= CHOICE {
117 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700118 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800119 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
120 DERSequenceEncoder name(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700121 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700122 for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin();
123 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800124 {
125 it->encode(name);
126 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700127 }
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800128 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700129
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800130 // SubjectPublicKeyInfo
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700131 m_key.encode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700132
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800133 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
134 //
135 // Extension ::= SEQUENCE {
136 // extnID OBJECT IDENTIFIER,
137 // critical BOOLEAN DEFAULT FALSE,
138 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700139 if (!m_extensionList.empty())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800140 {
141 DERSequenceEncoder extensions(idCert);
142 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700143 for (ExtensionList::iterator it = m_extensionList.begin();
144 it != m_extensionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800145 {
146 it->encode(extensions);
147 }
148 }
149 extensions.MessageEnd();
150 }
151 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700152
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800153 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700154
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800155 setContent(os.buf());
156 setContentType(MetaInfo::TYPE_KEY);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700157}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700158
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700159void
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700160Certificate::decode()
161{
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800162 using namespace CryptoPP;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700163
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800164 OBufferStream os;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700165 StringSource source(getContent().value(), getContent().value_size(), true);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700166
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800167 // idCert ::= SEQUENCE {
168 // validity Validity,
169 // subject Name,
170 // subjectPubKeyInfo SubjectPublicKeyInfo,
171 // extension Extensions OPTIONAL }
172 BERSequenceDecoder idCert(source);
173 {
174 // Validity ::= SEQUENCE {
175 // notBefore Time,
176 // notAfter Time }
177 BERSequenceDecoder validity(idCert);
178 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700179 BERDecodeTime(validity, m_notBefore);
180 BERDecodeTime(validity, m_notAfter);
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800181 }
182 validity.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700183
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800184 // Name ::= CHOICE {
185 // RDNSequence }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700186 //
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800187 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700188 m_subjectDescriptionList.clear();
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800189 BERSequenceDecoder name(idCert);
190 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700191 while (!name.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800192 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700193 m_subjectDescriptionList.push_back(CertificateSubjectDescription(name));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800194 }
195 }
196 name.MessageEnd();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700197
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800198 // SubjectPublicKeyInfo ::= SEQUENCE {
199 // algorithm AlgorithmIdentifier
200 // keybits BIT STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700201 m_key.decode(idCert);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700202
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800203 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
204 //
205 // Extension ::= SEQUENCE {
206 // extnID OBJECT IDENTIFIER,
207 // critical BOOLEAN DEFAULT FALSE,
208 // extnValue OCTET STRING }
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700209 m_extensionList.clear();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700210 if (!idCert.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800211 {
212 BERSequenceDecoder extensions(idCert);
213 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700214 while (!extensions.EndReached())
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800215 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700216 m_extensionList.push_back(CertificateExtension(extensions));
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800217 }
218 }
219 extensions.MessageEnd();
220 }
221 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700222
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800223 idCert.MessageEnd();
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700224}
225
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700226void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700227Certificate::printCertificate(std::ostream& os) const
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700228{
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800229 os << "Certificate name:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800230 os << " " << getName() << endl;
231 os << "Validity:" << endl;
232 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700233 os << " NotBefore: " << time::toIsoString(m_notBefore) << endl;
234 os << " NotAfter: " << time::toIsoString(m_notAfter) << endl;
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700235 }
236
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700237 os << "Subject Description:" << endl;
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700238 for (SubjectDescriptionList::const_iterator it = m_subjectDescriptionList.begin();
239 it != m_subjectDescriptionList.end(); ++it)
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800240 {
241 os << " " << it->getOidString() << ": " << it->getValue() << endl;
242 }
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700243
Alexander Afanasyev049f8f72013-12-26 19:07:15 -0800244 os << "Public key bits:" << endl;
Alexander Afanasyev0ea6e082013-12-26 15:16:37 -0800245 CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700246 m_key.encode(encoder);
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700247}
Jeff Thompsona5dc3512013-10-17 10:26:19 -0700248
Yingdi Yufc40d872014-02-18 12:56:04 -0800249} // namespace ndn