blob: a61bdc1149d6bffa8794c74a215f905cd939d2c9 [file] [log] [blame]
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
19 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 */
21
22#include "ccnx-verifier.h"
Zhenkai Zhu746d4442013-03-13 17:06:54 -070023#include "ccnx-wrapper.h"
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070024
25namespace Ccnx {
26
27static const size_t ROOT_KEY_DIGEST_LEN = 32; // SHA-256
28static const unsigned char ROOT_KEY_DIGEST[ROOT_KEY_DIGEST_LEN] = {0xa7, 0xd9, 0x8b, 0x81, 0xde, 0x13, 0xfc,
290x56, 0xc5, 0xa6, 0x92, 0xb4, 0x44, 0x93, 0x6e, 0x56, 0x70, 0x9d, 0x52, 0x6f, 0x70,
300xed, 0x39, 0xef, 0xb5, 0xe2, 0x3, 0x29, 0xa5, 0x53, 0x3e, 0x68};
31
32Verifier::Verifier(CcnxWrapper *ccnx)
33 : m_ccnx(ccnx)
34 , m_rootKeyDigest(ROOT_KEY_DIGEST, ROOT_KEY_DIGEST_LEN)
35{
36}
37
38Verifier::~Verifier()
39{
40}
41
42bool
Zhenkai Zhud5d99be2013-03-13 19:15:56 -070043Verifier::verify(const PcoPtr &pco, double maxWait)
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070044{
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070045 HashPtr publisherPublicKeyDigest = pco->publisherPublicKeyDigest();
Zhenkai Zhu746d4442013-03-13 17:06:54 -070046
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070047 {
Zhenkai Zhu746d4442013-03-13 17:06:54 -070048 UniqueRecLock lock(m_cacheLock);
49 CertCache::iterator it = m_certCache.find(*publisherPublicKeyDigest);
50 if (it != m_certCache.end())
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070051 {
Zhenkai Zhu746d4442013-03-13 17:06:54 -070052 CertPtr cert = it->second;
53 if (cert->validity() == Cert::WITHIN_VALID_TIME_SPAN)
54 {
Zhenkai Zhud5d99be2013-03-13 19:15:56 -070055 pco->verifySignature(cert);
56 return pco->verified();
Zhenkai Zhu746d4442013-03-13 17:06:54 -070057 }
58 else
59 {
60 // delete the invalid cert cache
61 m_certCache.erase(it);
62 }
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070063 }
64 }
65
66 // keyName is the name specified in key locator, i.e. without version and segment
67 Name keyName = pco->keyName();
68 int keyNameSize = keyName.size();
69
Zhenkai Zhu9dd9adc2013-03-13 16:12:09 -070070 if (keyNameSize == 0)
71 {
72 return false;
73 }
74
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070075 // for keys, we have to make sure key name is strictly prefix of the content name
76 if (pco->type() == ParsedContentObject::KEY)
77 {
78 Name contentName = pco->name();
79 if (keyNameSize >= contentName.size() || contentName.getPartialName(0, keyNameSize) != keyName)
80 {
81 return false;
82 }
83 }
84 else
85 {
86 // for now, user can assign any data using his key
87 }
88
89 Name metaName = keyName.getPartialName(0, keyNameSize - 1) + Name("/info") + keyName.getPartialName(keyNameSize - 1);
90
91 Selectors selectors;
92
93 selectors.childSelector(Selectors::RIGHT)
Zhenkai Zhud5d99be2013-03-13 19:15:56 -070094 .interestLifetime(maxWait);
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070095
96 PcoPtr keyObject = m_ccnx->get(keyName, selectors);
97 PcoPtr metaObject = m_ccnx->get(metaName, selectors);
Zhenkai Zhud5d99be2013-03-13 19:15:56 -070098 if (!keyObject || !metaObject )
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -070099 {
100 return false;
101 }
102
103 HashPtr publisherKeyHashInKeyObject = keyObject->publisherPublicKeyDigest();
104 HashPtr publisherKeyHashInMetaObject = metaObject->publisherPublicKeyDigest();
105
106 // make sure key and meta are signed using the same key
107 if (publisherKeyHashInKeyObject->IsZero() || ! (*publisherKeyHashInKeyObject == *publisherKeyHashInMetaObject))
108 {
109 return false;
110 }
111
Zhenkai Zhu9dd9adc2013-03-13 16:12:09 -0700112 CertPtr cert = boost::make_shared<Cert>(keyObject, metaObject);
113 if (cert->validity() != Cert::WITHIN_VALID_TIME_SPAN)
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700114 {
115 return false;
116 }
117
Zhenkai Zhud5d99be2013-03-13 19:15:56 -0700118 // check pco is actually signed by this key (i.e. we don't trust the publisherPublicKeyDigest given by ccnx c lib)
Zhenkai Zhu9dd9adc2013-03-13 16:12:09 -0700119 if (! (*pco->publisherPublicKeyDigest() == cert->keyDigest()))
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700120 {
121 return false;
122 }
123
Zhenkai Zhu9dd9adc2013-03-13 16:12:09 -0700124 // now we only need to make sure the key is trustworthy
125 if (cert->keyDigest() == m_rootKeyDigest)
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700126 {
127 // the key is the root key
128 // do nothing now
129 }
130 else
131 {
Zhenkai Zhud5d99be2013-03-13 19:15:56 -0700132 // can not verify key or can not verify meta
133 if (!verify(keyObject, maxWait) || !verify(metaObject, maxWait))
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700134 {
135 return false;
136 }
137 }
138
139 // ok, keyObject verified, because metaObject is signed by the same parent key and integrity checked
140 // so metaObject is also verified
Zhenkai Zhu746d4442013-03-13 17:06:54 -0700141 {
142 UniqueRecLock lock(m_cacheLock);
143 m_certCache.insert(std::make_pair(cert->keyDigest(), cert));
144 }
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700145
Zhenkai Zhud5d99be2013-03-13 19:15:56 -0700146 pco->verifySignature(cert);
147 return pco->verified();
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700148}
149
150} // Ccnx