2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file capi-certificate-chains.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
27 #include <dpl/test/test_runner.h>
29 #include <tests_common.h>
30 #include <test-certs.h>
31 #include <ckm-common.h>
33 #include <ckmc/ckmc-manager.h>
34 #include <ckmc/ckmc-control.h>
35 #include <ckmc/ckmc-type.h>
36 #include <ckmc/ckmc-error.h>
40 const char *CHAINS_PASSWD = "chains-pass";
42 typedef std::unique_ptr<ckmc_cert_s, void (*)(ckmc_cert_s*)> CertPtr;
43 typedef std::unique_ptr<ckmc_cert_list_s, void (*)(ckmc_cert_list_s*)> CertListPtr;
44 typedef std::unique_ptr<ckmc_alias_list_s, void (*)(ckmc_alias_list_s*)> AliasListPtr;
46 ckmc_cert_s* create_cert(TestData::certificateID idx) {
48 std::string cert_raw = TestData::getTestCertificateBase64(idx);
50 ckmc_cert_s* cert = NULL;
51 assert_positive(ckmc_cert_new,
52 reinterpret_cast<unsigned char*>(const_cast<char*>(cert_raw.c_str())),
57 RUNNER_ASSERT_MSG(cert != NULL, "Cert is NULL");
61 void save_cert(const ckmc_cert_s* cert, const char* alias) {
63 policy.password = NULL;
64 policy.extractable = 1;
66 assert_positive(ckmc_save_cert, alias, *cert, policy);
69 // list gets copies of aliases
70 AliasListPtr create_alias_list(const char* alias, ...) {
71 AliasListPtr aliasList(NULL, ckmc_alias_list_all_free);
76 ckmc_alias_list_s* last = NULL;
77 for (const char* a = alias; a != NULL; a = va_arg(ap, const char*)) {
78 if (aliasList == NULL) {
79 ckmc_alias_list_s* tmp = NULL;
80 assert_positive(ckmc_alias_list_new, strdup(a), &tmp);
81 aliasList = AliasListPtr(tmp, ckmc_alias_list_all_free);
82 RUNNER_ASSERT_MSG(!!aliasList, "Alias list is NULL");
83 last = aliasList.get();
85 assert_positive(ckmc_alias_list_add, last, strdup(a), &last);
86 RUNNER_ASSERT_MSG(last != NULL, "Last alias on the list is NULL");
94 // list takes ownership of provided certificates
95 CertListPtr create_cert_list(ckmc_cert_s* cert, ...) {
96 CertListPtr certList(NULL, ckmc_cert_list_all_free);
101 ckmc_cert_list_s* last = NULL;
102 for (ckmc_cert_s* c = cert; c!=NULL; c = va_arg(ap, ckmc_cert_s*)) {
104 ckmc_cert_list_s* tmp = NULL;
105 assert_positive(ckmc_cert_list_new, c, &tmp);
106 certList = CertListPtr(tmp, ckmc_cert_list_all_free);
107 RUNNER_ASSERT_MSG(!!certList, "Cert list is NULL");
108 last = certList.get();
110 assert_positive(ckmc_cert_list_add, last, c, &last);
111 RUNNER_ASSERT_MSG(last != NULL, "Last cert on the list is NULL");
119 const ckmc_alias_list_s* NULL_ALIASES = NULL;
120 const ckmc_cert_s* NULL_CERT = NULL;
121 ckmc_cert_list_s** NULL_CHAIN = NULL;
126 static int createChain(const ckmc_cert_s *cert,
127 const ckmc_cert_list_s *untrustedcerts,
128 const ckmc_cert_list_s* /*trustedcerts*/,
129 const bool /*use_trustedsystemcerts*/,
130 ckmc_cert_list_s **ppcert_chain_list)
132 return ckmc_get_cert_chain(cert, untrustedcerts, ppcert_chain_list);
135 static int createChainWithAlias(const ckmc_cert_s *cert,
136 const ckmc_alias_list_s *untrustedcerts,
137 const ckmc_alias_list_s* /*trustedcerts*/,
138 const bool /*use_trustedsystemcerts*/,
139 ckmc_cert_list_s **ppcert_chain_list)
141 return ckmc_get_cert_chain_with_alias(cert, untrustedcerts, ppcert_chain_list);
148 static int createChain(const ckmc_cert_s *cert,
149 const ckmc_cert_list_s *untrustedcerts,
150 const ckmc_cert_list_s *trustedcerts,
151 const bool use_trustedsystemcerts,
152 ckmc_cert_list_s **ppcert_chain_list)
154 return ckmc_get_cert_chain_with_trustedcert(cert,
157 use_trustedsystemcerts,
161 static int createChainWithAlias(const ckmc_cert_s *cert,
162 const ckmc_alias_list_s *untrustedcerts,
163 const ckmc_alias_list_s *trustedcerts,
164 const bool use_trustedsystemcerts,
165 ckmc_cert_list_s **ppcert_chain_list)
167 return ckmc_get_cert_chain_with_trustedcert_alias(cert,
170 use_trustedsystemcerts,
176 * Helper class for certificate verification
178 template <typename T=ChainApiNew>
185 void addTrusted(TestData::certificateID idx);
186 void addUntrusted(TestData::certificateID idx);
187 void enableSystem(bool enable);
189 void verifyPositive(TestData::certificateID idx, size_t expected);
190 void verifyNegative(TestData::certificateID idx, int error = CKMC_ERROR_VERIFICATION_FAILED);
193 void addCert(ckmc_cert_list_s*& list, ckmc_cert_s* cert);
194 void addAlias(ckmc_alias_list_s*& list, const char* alias);
196 ckmc_cert_list_s* m_trustedCerts;
197 ckmc_alias_list_s* m_trustedAliases;
199 ckmc_cert_list_s* m_untrustedCerts;
200 ckmc_alias_list_s* m_untrustedAliases;
205 template <typename T>
206 ChainVerifier<T>::ChainVerifier() :
207 m_trustedCerts(NULL),
208 m_trustedAliases(NULL),
209 m_untrustedCerts(NULL),
210 m_untrustedAliases(NULL),
215 template <typename T>
216 ChainVerifier<T>::~ChainVerifier()
218 ckmc_cert_list_all_free(m_trustedCerts);
219 ckmc_cert_list_all_free(m_untrustedCerts);
220 ckmc_alias_list_all_free(m_trustedAliases);
221 ckmc_alias_list_all_free(m_untrustedAliases);
224 template <typename T>
225 void ChainVerifier<T>::addTrusted(TestData::certificateID idx)
227 size_t size = list_size(m_trustedCerts);
228 ckmc_cert_s* cert = create_cert(idx);
229 addCert(m_trustedCerts, cert);
231 std::stringstream ss;
232 ss << "TRUSTED_CERT_ALIAS_" << size;
233 save_cert(cert, ss.str().c_str());
234 addAlias(m_trustedAliases, ss.str().c_str());
237 template <typename T>
238 void ChainVerifier<T>::addUntrusted(TestData::certificateID idx)
240 size_t size = list_size(m_untrustedCerts);
241 ckmc_cert_s* cert = create_cert(idx);
242 addCert(m_untrustedCerts, cert);
244 std::stringstream ss;
245 ss << "UNTRUSTED_CERT_ALIAS_" << size;
246 save_cert(cert, ss.str().c_str());
247 addAlias(m_untrustedAliases, ss.str().c_str());
250 template <typename T>
251 void ChainVerifier<T>::enableSystem(bool enable)
256 template <typename T>
257 void ChainVerifier<T>::addCert(ckmc_cert_list_s*& list, ckmc_cert_s* cert)
260 ckmc_cert_list_s* tmp = NULL;
261 assert_positive(ckmc_cert_list_new, cert, &tmp);
262 RUNNER_ASSERT_MSG(!!tmp, "Cert list is NULL");
265 ckmc_cert_list_s* last = list;
268 assert_positive(ckmc_cert_list_add, last, cert, &last);
269 RUNNER_ASSERT_MSG(last != NULL, "Last cert on the list is NULL");
273 template <typename T>
274 void ChainVerifier<T>::addAlias(ckmc_alias_list_s*& list, const char* alias)
277 ckmc_alias_list_s* tmp = NULL;
278 assert_positive(ckmc_alias_list_new, strdup(alias), &tmp);
279 RUNNER_ASSERT_MSG(!!tmp, "Alias list is NULL");
282 ckmc_alias_list_s* last = list;
285 assert_positive(ckmc_alias_list_add, last, strdup(alias), &last);
286 RUNNER_ASSERT_MSG(last != NULL, "Last alias on the list is NULL");
290 template <typename T>
291 void ChainVerifier<T>::verifyPositive(TestData::certificateID idx, size_t expected)
293 ckmc_cert_s* cert = create_cert(idx);
295 ckmc_cert_list_s* chain = NULL;
297 assert_positive(T::createChain,
304 size_t size = list_size(chain);
305 ckmc_cert_list_all_free(chain);
307 RUNNER_ASSERT_MSG(size == expected, "Expected chain size: " << expected << " got: " << size);
309 assert_positive(T::createChainWithAlias,
316 size = list_size(chain);
317 ckmc_cert_list_all_free(chain);
319 RUNNER_ASSERT_MSG(size == expected, "Expected chain size: " << expected << " got: " << size);
320 ckmc_cert_free(cert);
323 template <typename T>
324 void ChainVerifier<T>::verifyNegative(TestData::certificateID idx, int error)
326 ckmc_cert_s* cert = create_cert(idx);
328 ckmc_cert_list_s* chain = NULL;
337 RUNNER_ASSERT_MSG(chain == NULL, "Chain is not empty");
340 T::createChainWithAlias,
347 RUNNER_ASSERT_MSG(chain == NULL, "Chain is not empty");
348 ckmc_cert_free(cert);
350 } // namespace anonymous
352 RUNNER_TEST_GROUP_INIT(T307_CKMC_CAPI_CERTIFICATE_CHAINS);
354 RUNNER_TEST(TCCH_0000_init)
356 reset_user_data(0, CHAINS_PASSWD);
360 RUNNER_TEST(TCCH_0010_get_chain_old_api)
362 reset_user_data(0, CHAINS_PASSWD);
364 ChainVerifier<ChainApiOld> cv;
365 cv.verifyNegative(TestData::GOOGLE_COM);
367 cv.addUntrusted(TestData::GIAG2);
368 cv.verifyPositive(TestData::GOOGLE_COM, 3); // including system cert
369 cv.verifyNegative(TestData::TEST_LEAF);
373 RUNNER_TEST(TCCH_0020_get_chain_old_api_system_only)
375 reset_user_data(0, CHAINS_PASSWD);
377 ChainVerifier<ChainApiOld> cv;
378 cv.verifyPositive(TestData::GIAG2, 2); // including system cert
381 // check invalid arguments
382 RUNNER_TEST(TCCH_0100_get_certificate_chain_invalid_param)
384 reset_user_data(0, CHAINS_PASSWD);
386 ckmc_cert_s* ca2 = create_cert(TestData::GIAG2);
387 ckmc_cert_s* ca1 = create_cert(TestData::GEOTRUST);
388 ckmc_cert_list_s* chain = NULL;
391 CertListPtr untrusted_c = create_cert_list(ca1, NULL);
394 assert_invalid_param(ckmc_get_cert_chain_with_trustedcert,
401 assert_invalid_param(ckmc_get_cert_chain_with_trustedcert,
409 ca1 = create_cert(TestData::GEOTRUST);
410 save_cert(ca1, "GEOTRUST");
411 AliasListPtr untrusted_a = create_alias_list("GEOTRUST", NULL);
413 assert_invalid_param(ckmc_get_cert_chain_with_trustedcert_alias,
420 assert_invalid_param(ckmc_get_cert_chain_with_trustedcert_alias,
430 // check invalid arguments
431 RUNNER_TEST(TCCH_0110_get_certificate_chain_alias_unknown)
433 reset_user_data(0, CHAINS_PASSWD);
435 ckmc_cert_s* ca2 = create_cert(TestData::GIAG2);
436 ckmc_cert_list_s* chain = NULL;
438 AliasListPtr non_existing = create_alias_list("NON_EXISTING_ALIAS", NULL);
439 assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
440 ckmc_get_cert_chain_with_trustedcert_alias,
447 assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
448 ckmc_get_cert_chain_with_trustedcert_alias,
458 * This test verifies that chain of trust won't be successfully built unless system or trusted
459 * certificates are used even if real trusted root ca certs are used as untrusted.
461 RUNNER_TEST(TCCH_0120_get_certificate_chain_root_ca_negative)
463 reset_user_data(0, CHAINS_PASSWD);
466 cv.enableSystem(false);
467 cv.verifyNegative(TestData::EQUIFAX);
469 cv.addUntrusted(TestData::GIAG2);
470 cv.verifyNegative(TestData::GOOGLE_COM);
474 * This test verifies that it's possible to build a chain of trust with single trusted certificate
475 * and no system certificates.
477 RUNNER_TEST(TCCH_0140_get_certificate_chain_trusted_only)
479 reset_user_data(0, CHAINS_PASSWD);
482 cv.enableSystem(false);
483 cv.addTrusted(TestData::TEST_ROOT_CA);
484 cv.verifyPositive(TestData::TEST_IM_CA, 2);
485 cv.verifyNegative(TestData::TEST_LEAF);
489 * This test verifies that it's possible to build a chain of trust with system certificates only
491 RUNNER_TEST(TCCH_0150_get_certificate_chain_system_only)
493 reset_user_data(0, CHAINS_PASSWD);
496 cv.verifyPositive(TestData::GIAG2, 2); // including system cert
497 cv.verifyNegative(TestData::GOOGLE_COM);
501 * Verifies that chain of trust can be built without untrusted certificates.
503 RUNNER_TEST(TCCH_0160_get_certificate_chain_no_untrusted)
505 reset_user_data(0, CHAINS_PASSWD);
508 cv.addTrusted(TestData::TEST_ROOT_CA);
509 cv.verifyPositive(TestData::TEST_IM_CA, 2);// signed by trusted cert (TEST_ROOT_CA)
510 cv.verifyPositive(TestData::GIAG2, 2); // signed by system cert (GEOTRUST)
511 cv.verifyNegative(TestData::GOOGLE_COM);
514 RUNNER_TEST(TCCH_0170_get_certificate_chain_no_trusted)
516 reset_user_data(0, CHAINS_PASSWD);
519 cv.addUntrusted(TestData::GIAG2);
520 cv.verifyPositive(TestData::GOOGLE_COM,3); // including system cert
521 cv.verifyNegative(TestData::TEST_LEAF);
525 * Check if its possible to build a chain of trust without system certs.
527 RUNNER_TEST(TCCH_0180_get_certificate_chain_no_system)
529 reset_user_data(0, CHAINS_PASSWD);
532 cv.enableSystem(false);
533 cv.addTrusted(TestData::TEST_ROOT_CA);
534 cv.addUntrusted(TestData::TEST_IM_CA);
535 cv.verifyPositive(TestData::TEST_LEAF, 3);
536 cv.verifyNegative(TestData::GOOGLE_COM);
540 * Check if its possible to build a chain of trust with intermediate ca cert in trusted list.
542 RUNNER_TEST(TCCH_0190_get_certificate_chain_im_ca_in_trusted)
544 reset_user_data(0, CHAINS_PASSWD);
547 cv.enableSystem(false);
548 cv.addTrusted(TestData::TEST_ROOT_CA);
549 cv.addTrusted(TestData::TEST_IM_CA);
550 cv.verifyPositive(TestData::TEST_LEAF, 3);
551 cv.verifyNegative(TestData::GOOGLE_COM);
554 RUNNER_TEST(TCCH_0200_get_certificate_chain_all)
556 reset_user_data(0, CHAINS_PASSWD);
559 cv.enableSystem(true);
560 cv.addTrusted(TestData::TEST_ROOT_CA);
561 cv.addUntrusted(TestData::GEOTRUST);
562 cv.addUntrusted(TestData::GIAG2);
564 * In combat conditions this may as well be 3. Because of 2 existing GeoTrust certificates with
565 * same Subject and Public key one being root ca and the other not there are 2 possible chains
566 * of trust for this certificate.
568 cv.verifyPositive(TestData::GOOGLE_COM,4);
569 cv.verifyNegative(TestData::TEST_LEAF);
572 RUNNER_TEST(TCCH_9999_deinit)