blob: 3b28c665707f8eac5625eddb86eb1f280d8397a0 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu28fd32f2014-01-28 19:03:03 -08002/**
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.
Yingdi Yu28fd32f2014-01-28 19:03:03 -080020 */
21
Yingdi Yuf56c68f2014-04-24 21:50:13 -070022#include "security/sec-tpm-osx.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070023#include "security/cryptopp.hpp"
Yingdi Yu28fd32f2014-01-28 19:03:03 -080024
Yingdi Yuf56c68f2014-04-24 21:50:13 -070025#include "util/time.hpp"
26
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070027#include <boost/lexical_cast.hpp>
28
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070029#include "boost-test.hpp"
30
Alexander Afanasyev0abb2da2014-01-30 18:07:57 -080031namespace ndn {
Yingdi Yu28fd32f2014-01-28 19:03:03 -080032
Alexander Afanasyevd1b5c412014-03-27 15:03:51 -070033BOOST_AUTO_TEST_SUITE(SecurityTestSecTpmOsx)
Yingdi Yu28fd32f2014-01-28 19:03:03 -080034
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -070035BOOST_AUTO_TEST_CASE(Delete)
Yingdi Yu28fd32f2014-01-28 19:03:03 -080036{
37 SecTpmOsx tpm;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070038
Yingdi Yu5e96e002014-04-23 18:32:15 -070039 Name keyName("/TestSecTpmOsx/Delete/ksk-" +
Yingdi Yu7036ce22014-06-19 18:53:37 -070040 boost::lexical_cast<std::string>(
Yingdi Yu5e96e002014-04-23 18:32:15 -070041 time::toUnixTimestamp(time::system_clock::now()).count()));
Yingdi Yu7036ce22014-06-19 18:53:37 -070042 RsaKeyParams params(2048);
43 BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070044
Yingdi Yu28fd32f2014-01-28 19:03:03 -080045 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
46 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070047
Yingdi Yu28fd32f2014-01-28 19:03:03 -080048 tpm.deleteKeyPairInTpm(keyName);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070049
Yingdi Yu28fd32f2014-01-28 19:03:03 -080050 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
51 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
52}
53
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -070054BOOST_AUTO_TEST_CASE(SignVerify)
Yingdi Yu28fd32f2014-01-28 19:03:03 -080055{
56 SecTpmOsx tpm;
57
Yingdi Yu5e96e002014-04-23 18:32:15 -070058 Name keyName("/TestSecTpmOsx/SignVerify/ksk-" +
Yingdi Yu7036ce22014-06-19 18:53:37 -070059 boost::lexical_cast<std::string>(
Yingdi Yu5e96e002014-04-23 18:32:15 -070060 time::toUnixTimestamp(time::system_clock::now()).count()));
Yingdi Yu7036ce22014-06-19 18:53:37 -070061 RsaKeyParams params(2048);
62 BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070063
Yingdi Yube4150e2014-02-18 13:02:46 -080064 Data data("/TestSecTpmOsx/SignVaerify/Data/1");
Yingdi Yu28fd32f2014-01-28 19:03:03 -080065 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
66
Yingdi Yu2e57a582014-02-20 23:34:43 -080067 Block sigBlock;
Yingdi Yu5e96e002014-04-23 18:32:15 -070068 BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
69 keyName, DIGEST_ALGORITHM_SHA256));
Yingdi Yu28fd32f2014-01-28 19:03:03 -080070
Yingdi Yu7036ce22014-06-19 18:53:37 -070071 shared_ptr<PublicKey> publicKey;
72 BOOST_CHECK_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
Yingdi Yu2e57a582014-02-20 23:34:43 -080073 try
74 {
75 using namespace CryptoPP;
Yingdi Yu28fd32f2014-01-28 19:03:03 -080076
Yingdi Yu7036ce22014-06-19 18:53:37 -070077 RSA::PublicKey rsaPublicKey;
Yingdi Yu2e57a582014-02-20 23:34:43 -080078 ByteQueue queue;
Yingdi Yu7036ce22014-06-19 18:53:37 -070079 queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
80 rsaPublicKey.Load(queue);
Yingdi Yu2e57a582014-02-20 23:34:43 -080081
Yingdi Yu7036ce22014-06-19 18:53:37 -070082 RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
83 bool isVerified = verifier.VerifyMessage(content, sizeof(content),
84 sigBlock.value(), sigBlock.value_size());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070085
Yingdi Yu7036ce22014-06-19 18:53:37 -070086 BOOST_CHECK_EQUAL(isVerified, true);
Yingdi Yu2e57a582014-02-20 23:34:43 -080087 }
Yingdi Yu5e96e002014-04-23 18:32:15 -070088 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -080089 {
90 BOOST_CHECK(false);
91 }
Yingdi Yu28fd32f2014-01-28 19:03:03 -080092
93 tpm.deleteKeyPairInTpm(keyName);
94}
95
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -070096BOOST_AUTO_TEST_CASE(RandomGenerator)
Yingdi Yu4b752752014-02-18 12:24:03 -080097{
98 SecTpmOsx tpm;
99
100 size_t scale = 1000;
101 size_t size = 256 * scale;
102 uint8_t* block = new uint8_t[size];
103 tpm.generateRandomBlock(block, size);
104
Yingdi Yu7036ce22014-06-19 18:53:37 -0700105 std::map<uint8_t, int> counter;
106 for (size_t i = 0; i < size; i++)
107 {
108 counter[block[i]] += 1;
109 }
Yingdi Yu4b752752014-02-18 12:24:03 -0800110
111 float dev = 0.0;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700112 for (size_t i = 0; i != 255; i++)
113 {
114 dev += ((counter[i] - scale) * (counter[i] - scale)) * 1.0 / (scale * scale);
115 }
Yingdi Yu4b752752014-02-18 12:24:03 -0800116
117 BOOST_CHECK_CLOSE(dev / 256, 0.001, 100);
118
119}
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800120
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700121BOOST_AUTO_TEST_CASE(ExportImportKey)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800122{
123 using namespace CryptoPP;
124
125 SecTpmOsx tpm;
126
Yingdi Yu5e96e002014-04-23 18:32:15 -0700127 Name keyName("/TestSecTpmOsx/ExportImportKey/ksk-" +
Yingdi Yu7036ce22014-06-19 18:53:37 -0700128 boost::lexical_cast<std::string>(
Yingdi Yu5e96e002014-04-23 18:32:15 -0700129 time::toUnixTimestamp(time::system_clock::now()).count()));
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700130
Yingdi Yu7036ce22014-06-19 18:53:37 -0700131 RsaKeyParams params(2048);
132 BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800133
Yingdi Yu7036ce22014-06-19 18:53:37 -0700134 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
135 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800136
Yingdi Yu2e57a582014-02-20 23:34:43 -0800137 ConstBufferPtr exported;
Yingdi Yu5e96e002014-04-23 18:32:15 -0700138 BOOST_CHECK_NO_THROW(exported = tpm.exportPrivateKeyPkcs5FromTpm(keyName, "1234"));
Yingdi Yu7036ce22014-06-19 18:53:37 -0700139 shared_ptr<PublicKey> publicKey;
140 BOOST_REQUIRE_NO_THROW(publicKey = tpm.getPublicKeyFromTpm(keyName));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800141
142 tpm.deleteKeyPairInTpm(keyName);
143
Yingdi Yu7036ce22014-06-19 18:53:37 -0700144 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), false);
145 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), false);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800146
Yingdi Yu5e96e002014-04-23 18:32:15 -0700147 BOOST_REQUIRE(tpm.importPrivateKeyPkcs5IntoTpm(keyName,
148 exported->buf(), exported->size(),
149 "1234"));
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700150
Yingdi Yu7036ce22014-06-19 18:53:37 -0700151 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC), true);
152 BOOST_REQUIRE_EQUAL(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE), true);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800153
154 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
Yingdi Yu2e57a582014-02-20 23:34:43 -0800155 Block sigBlock;
Yingdi Yu5e96e002014-04-23 18:32:15 -0700156 BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
157 keyName, DIGEST_ALGORITHM_SHA256));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800158
Yingdi Yu2e57a582014-02-20 23:34:43 -0800159 try
160 {
161 using namespace CryptoPP;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800162
Yingdi Yu7036ce22014-06-19 18:53:37 -0700163 RSA::PublicKey rsaPublicKey;
Yingdi Yu2e57a582014-02-20 23:34:43 -0800164 ByteQueue queue;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700165 queue.Put(reinterpret_cast<const byte*>(publicKey->get().buf()), publicKey->get().size());
166 rsaPublicKey.Load(queue);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800167
Yingdi Yu7036ce22014-06-19 18:53:37 -0700168 RSASS<PKCS1v15, SHA256>::Verifier verifier(rsaPublicKey);
169 bool isVerified = verifier.VerifyMessage(content, sizeof(content),
170 sigBlock.value(), sigBlock.value_size());
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700171
Yingdi Yu7036ce22014-06-19 18:53:37 -0700172 BOOST_CHECK_EQUAL(isVerified, true);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800173 }
Yingdi Yu5e96e002014-04-23 18:32:15 -0700174 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800175 {
176 BOOST_CHECK(false);
177 }
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700178
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800179 tpm.deleteKeyPairInTpm(keyName);
180 // This is some problem related to Mac OS Key chain, and we will fix it later.
181 // BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE) == false);
182 // BOOST_REQUIRE(tpm.doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC) == false);
183}
184
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700185BOOST_AUTO_TEST_CASE(NonExistingKey)
186{
187 using namespace CryptoPP;
188
189 SecTpmOsx tpm;
190
191 Name keyName("/TestSecTpmOsx/NonExistingKey");
192
193 BOOST_REQUIRE_THROW(tpm.getPublicKeyFromTpm(keyName), SecTpmOsx::Error);
194
195 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
196 BOOST_REQUIRE_THROW(tpm.signInTpm(content, sizeof(content), keyName, DIGEST_ALGORITHM_SHA256),
197 SecTpmOsx::Error);
198
199 BOOST_REQUIRE_THROW(tpm.signInTpm(0, 1, keyName, DIGEST_ALGORITHM_SHA256),
200 SecTpmOsx::Error);
201}
202
Yingdi Yuc8f883c2014-06-20 23:25:22 -0700203BOOST_AUTO_TEST_CASE(EcdsaSigning)
204{
205 SecTpmOsx tpm;
206
207 Name keyName("/TestSecTpmOsx/EcdsaSigning/ksk-" +
208 boost::lexical_cast<std::string>(time::toUnixTimestamp(time::system_clock::now())));
209 EcdsaKeyParams params;
210 BOOST_CHECK_NO_THROW(tpm.generateKeyPairInTpm(keyName, params));
211
212 Data data("/TestSecTpmOsx/EcdsaSigning/Data/1");
213 const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
214
215 Block sigBlock;
216 BOOST_CHECK_NO_THROW(sigBlock = tpm.signInTpm(content, sizeof(content),
217 keyName, DIGEST_ALGORITHM_SHA256));
218
219 shared_ptr<PublicKey> pubkeyPtr;
220 BOOST_CHECK_NO_THROW(pubkeyPtr = tpm.getPublicKeyFromTpm(keyName));
221
222 try
223 {
224 using namespace CryptoPP;
225
226 ECDSA<ECP, SHA256>::PublicKey publicKey;
227 ByteQueue queue;
228 queue.Put(reinterpret_cast<const byte*>(pubkeyPtr->get().buf()), pubkeyPtr->get().size());
229 publicKey.Load(queue);
230
231 uint8_t buffer[64];
232 size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
233 sigBlock.value(), sigBlock.value_size(), DSA_DER);
234
235 ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
236 bool result = verifier.VerifyMessage(content, sizeof(content),
237 buffer, usedSize);
238
239 BOOST_CHECK_EQUAL(result, true);
240 }
241 catch (CryptoPP::Exception& e)
242 {
243 BOOST_CHECK(false);
244 }
245
246 tpm.deleteKeyPairInTpm(keyName);
247}
Alexander Afanasyevf82d13a2014-04-30 14:30:19 -0700248
Yingdi Yu28fd32f2014-01-28 19:03:03 -0800249BOOST_AUTO_TEST_SUITE_END()
Alexander Afanasyev0abb2da2014-01-30 18:07:57 -0800250
251} // namespace ndn