2f3dca7c2159e280117f6194bf067d6cf27f6e5e
[platform/core/test/security-tests.git] / tests / ckm / capi-certificate-chains.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file       capi-certificate-chains.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <stdarg.h>
23
24 #include <string>
25 #include <memory>
26
27 #include <dpl/test/test_runner.h>
28
29 #include <tests_common.h>
30 #include <test-certs.h>
31 #include <ckm-common.h>
32
33 #include <ckmc/ckmc-manager.h>
34 #include <ckmc/ckmc-control.h>
35 #include <ckmc/ckmc-type.h>
36 #include <ckmc/ckmc-error.h>
37
38 namespace {
39
40 typedef std::unique_ptr<ckmc_cert_s, void (*)(ckmc_cert_s*)> CertPtr;
41 typedef std::unique_ptr<ckmc_cert_list_s, void (*)(ckmc_cert_list_s*)> CertListPtr;
42 typedef std::unique_ptr<ckmc_alias_list_s, void (*)(ckmc_alias_list_s*)> AliasListPtr;
43
44 ckmc_cert_s* create_cert(TestData::certificateID idx) {
45
46     std::string cert_raw = TestData::getTestCertificateBase64(idx);
47
48     ckmc_cert_s* cert = NULL;
49     assert_positive(ckmc_cert_new,
50                     reinterpret_cast<unsigned char*>(const_cast<char*>(cert_raw.c_str())),
51                     cert_raw.size(),
52                     CKMC_FORM_PEM,
53                     &cert);
54
55     RUNNER_ASSERT_MSG(cert != NULL, "Cert is NULL");
56     return cert;
57 }
58
59 void save_cert(const ckmc_cert_s* cert, const char* alias) {
60     ckmc_policy_s policy;
61     policy.password = NULL;
62     policy.extractable = 1;
63
64     assert_positive(ckmc_save_cert, alias, *cert, policy);
65 }
66
67 // list gets copies of aliases
68 AliasListPtr create_alias_list(const char* alias, ...) {
69     AliasListPtr aliasList(NULL, ckmc_alias_list_all_free);
70
71     va_list ap;
72
73     va_start(ap, alias);
74     ckmc_alias_list_s* last = NULL;
75     for (const char* a = alias; a != NULL; a = va_arg(ap, const char*)) {
76         if (aliasList == NULL) {
77             ckmc_alias_list_s* tmp = NULL;
78             assert_positive(ckmc_alias_list_new, strdup(a), &tmp);
79             aliasList = AliasListPtr(tmp, ckmc_alias_list_all_free);
80             RUNNER_ASSERT_MSG(!!aliasList, "Alias list is NULL");
81             last = aliasList.get();
82         } else {
83             assert_positive(ckmc_alias_list_add, last, strdup(a), &last);
84             RUNNER_ASSERT_MSG(last != NULL, "Last alias on the list is NULL");
85         }
86     }
87     va_end(ap);
88
89     return aliasList;
90 }
91
92 // list takes ownership of provided certificates
93 CertListPtr create_cert_list(ckmc_cert_s* cert, ...) {
94     CertListPtr certList(NULL, ckmc_cert_list_all_free);
95
96     va_list ap;
97
98     va_start(ap, cert);
99     ckmc_cert_list_s* last = NULL;
100     for (ckmc_cert_s* c = cert; c!=NULL; c = va_arg(ap, ckmc_cert_s*)) {
101         if (!certList) {
102             ckmc_cert_list_s* tmp = NULL;
103             assert_positive(ckmc_cert_list_new, c, &tmp);
104             certList = CertListPtr(tmp, ckmc_cert_list_all_free);
105             RUNNER_ASSERT_MSG(!!certList, "Cert list is NULL");
106             last = certList.get();
107         } else {
108             assert_positive(ckmc_cert_list_add, last, c, &last);
109             RUNNER_ASSERT_MSG(last != NULL, "Last cert on the list is NULL");
110         }
111     }
112     va_end(ap);
113
114     return certList;
115 }
116
117 const ckmc_alias_list_s* NULL_ALIASES = NULL;
118 const ckmc_cert_s* NULL_CERT = NULL;
119 ckmc_cert_list_s** NULL_CHAIN = NULL;
120
121 // old api wrapper
122 class ChainApiOld {
123 public:
124     static int createChain(const ckmc_cert_s *cert,
125                            const ckmc_cert_list_s *untrustedcerts,
126                            const ckmc_cert_list_s* /*trustedcerts*/,
127                            const bool /*use_trustedsystemcerts*/,
128                            ckmc_cert_list_s **ppcert_chain_list)
129     {
130         return ckmc_get_cert_chain(cert, untrustedcerts, ppcert_chain_list);
131     }
132
133     static int createChainWithAlias(const ckmc_cert_s *cert,
134                                     const ckmc_alias_list_s *untrustedcerts,
135                                     const ckmc_alias_list_s* /*trustedcerts*/,
136                                     const bool /*use_trustedsystemcerts*/,
137                                     ckmc_cert_list_s **ppcert_chain_list)
138     {
139         return ckmc_get_cert_chain_with_alias(cert, untrustedcerts, ppcert_chain_list);
140     }
141 };
142
143 // new api wrapper
144 class ChainApiNew {
145 public:
146     static int createChain(const ckmc_cert_s *cert,
147                            const ckmc_cert_list_s *untrustedcerts,
148                            const ckmc_cert_list_s *trustedcerts,
149                            const bool use_trustedsystemcerts,
150                            ckmc_cert_list_s **ppcert_chain_list)
151     {
152         return ckmc_get_cert_chain_with_trustedcert(cert,
153                                                     untrustedcerts,
154                                                     trustedcerts,
155                                                     use_trustedsystemcerts,
156                                                     ppcert_chain_list);
157     }
158
159     static int createChainWithAlias(const ckmc_cert_s *cert,
160                                     const ckmc_alias_list_s *untrustedcerts,
161                                     const ckmc_alias_list_s *trustedcerts,
162                                     const bool use_trustedsystemcerts,
163                                     ckmc_cert_list_s **ppcert_chain_list)
164     {
165         return ckmc_get_cert_chain_with_trustedcert_alias(cert,
166                                                           untrustedcerts,
167                                                           trustedcerts,
168                                                           use_trustedsystemcerts,
169                                                           ppcert_chain_list);
170     }
171 };
172
173 /*
174  * Helper class for certificate verification
175  */
176 template <typename T=ChainApiNew>
177 class ChainVerifier
178 {
179 public:
180     ChainVerifier();
181     ~ChainVerifier();
182
183     void addTrusted(TestData::certificateID idx);
184     void addUntrusted(TestData::certificateID idx);
185     void enableSystem(bool enable);
186
187     void verifyPositive(TestData::certificateID idx, size_t expected);
188     void verifyNegative(TestData::certificateID idx, int error = CKMC_ERROR_VERIFICATION_FAILED);
189
190 private:
191     void addCert(ckmc_cert_list_s*& list, ckmc_cert_s* cert);
192     void addAlias(ckmc_alias_list_s*& list, const char* alias);
193
194     ckmc_cert_list_s* m_trustedCerts;
195     ckmc_alias_list_s* m_trustedAliases;
196
197     ckmc_cert_list_s* m_untrustedCerts;
198     ckmc_alias_list_s* m_untrustedAliases;
199
200     bool m_system;
201 };
202
203 template <typename T>
204 ChainVerifier<T>::ChainVerifier() :
205         m_trustedCerts(NULL),
206         m_trustedAliases(NULL),
207         m_untrustedCerts(NULL),
208         m_untrustedAliases(NULL),
209         m_system(true)
210 {
211 }
212
213 template <typename T>
214 ChainVerifier<T>::~ChainVerifier()
215 {
216     ckmc_cert_list_all_free(m_trustedCerts);
217     ckmc_cert_list_all_free(m_untrustedCerts);
218     ckmc_alias_list_all_free(m_trustedAliases);
219     ckmc_alias_list_all_free(m_untrustedAliases);
220 }
221
222 template <typename T>
223 void ChainVerifier<T>::addTrusted(TestData::certificateID idx)
224 {
225     size_t size = list_size(m_trustedCerts);
226     ckmc_cert_s* cert = create_cert(idx);
227     addCert(m_trustedCerts, cert);
228
229     std::stringstream ss;
230     ss << "TRUSTED_CERT_ALIAS_" << size;
231     save_cert(cert, ss.str().c_str());
232     addAlias(m_trustedAliases, ss.str().c_str());
233 }
234
235 template <typename T>
236 void ChainVerifier<T>::addUntrusted(TestData::certificateID idx)
237 {
238     size_t size = list_size(m_untrustedCerts);
239     ckmc_cert_s* cert = create_cert(idx);
240     addCert(m_untrustedCerts, cert);
241
242     std::stringstream ss;
243     ss << "UNTRUSTED_CERT_ALIAS_" << size;
244     save_cert(cert, ss.str().c_str());
245     addAlias(m_untrustedAliases, ss.str().c_str());
246 }
247
248 template <typename T>
249 void ChainVerifier<T>::enableSystem(bool enable)
250 {
251     m_system = enable;
252 }
253
254 template <typename T>
255 void ChainVerifier<T>::addCert(ckmc_cert_list_s*& list, ckmc_cert_s* cert)
256 {
257     if (!list) {
258         ckmc_cert_list_s* tmp = NULL;
259         assert_positive(ckmc_cert_list_new, cert, &tmp);
260         RUNNER_ASSERT_MSG(!!tmp, "Cert list is NULL");
261         list = tmp;
262     } else {
263         ckmc_cert_list_s* last = list;
264         while(last->next)
265             last = last->next;
266         assert_positive(ckmc_cert_list_add, last, cert, &last);
267         RUNNER_ASSERT_MSG(last != NULL, "Last cert on the list is NULL");
268     }
269 }
270
271 template <typename T>
272 void ChainVerifier<T>::addAlias(ckmc_alias_list_s*& list, const char* alias)
273 {
274     if (!list) {
275         ckmc_alias_list_s* tmp = NULL;
276         assert_positive(ckmc_alias_list_new, strdup(alias), &tmp);
277         RUNNER_ASSERT_MSG(!!tmp, "Alias list is NULL");
278         list = tmp;
279     } else {
280         ckmc_alias_list_s* last = list;
281         while(last->next)
282             last = last->next;
283         assert_positive(ckmc_alias_list_add, last, strdup(alias), &last);
284         RUNNER_ASSERT_MSG(last != NULL, "Last alias on the list is NULL");
285     }
286 }
287
288 template <typename T>
289 void ChainVerifier<T>::verifyPositive(TestData::certificateID idx, size_t expected)
290 {
291     ckmc_cert_s* cert = create_cert(idx);
292
293     ckmc_cert_list_s* chain = NULL;
294
295     assert_positive(T::createChain,
296                     cert,
297                     m_untrustedCerts,
298                     m_trustedCerts,
299                     m_system,
300                     &chain);
301
302     size_t size = list_size(chain);
303     ckmc_cert_list_all_free(chain);
304     chain = NULL;
305     RUNNER_ASSERT_MSG(size == expected, "Expected chain size: " << expected << " got: " << size);
306
307     assert_positive(T::createChainWithAlias,
308                     cert,
309                     m_untrustedAliases,
310                     m_trustedAliases,
311                     m_system,
312                     &chain);
313
314     size = list_size(chain);
315     ckmc_cert_list_all_free(chain);
316     chain = NULL;
317     RUNNER_ASSERT_MSG(size == expected, "Expected chain size: " << expected << " got: " << size);
318     ckmc_cert_free(cert);
319 }
320
321 template <typename T>
322 void ChainVerifier<T>::verifyNegative(TestData::certificateID idx, int error)
323 {
324     ckmc_cert_s* cert = create_cert(idx);
325
326     ckmc_cert_list_s* chain = NULL;
327
328     assert_result(error,
329                   T::createChain,
330                   cert,
331                   m_untrustedCerts,
332                   m_trustedCerts,
333                   m_system,
334                   &chain);
335     RUNNER_ASSERT_MSG(chain == NULL, "Chain is not empty");
336
337     assert_result(error,
338                   T::createChainWithAlias,
339                   cert,
340                   m_untrustedAliases,
341                   m_trustedAliases,
342                   m_system,
343                   &chain);
344
345     RUNNER_ASSERT_MSG(chain == NULL, "Chain is not empty");
346     ckmc_cert_free(cert);
347 }
348
349 } // namespace anonymous
350
351 RUNNER_TEST_GROUP_INIT(T307_CKMC_CAPI_CERTIFICATE_CHAINS);
352
353 RUNNER_TEST(TCCH_0000_init)
354 {
355     assert_positive(ckmc_unlock_user_key, 0, "test-pass");
356 }
357
358 // old API
359 RUNNER_TEST(TCCH_0010_get_chain_old_api)
360 {
361     assert_positive(ckmc_remove_user_data,0);
362
363     ChainVerifier<ChainApiOld> cv;
364     cv.verifyNegative(TestData::GOOGLE_COM);
365
366     cv.addUntrusted(TestData::GIAG2);
367     cv.verifyPositive(TestData::GOOGLE_COM, 3); // including system cert
368     cv.verifyNegative(TestData::TEST_LEAF);
369 }
370
371 // old API
372 RUNNER_TEST(TCCH_0020_get_chain_old_api_system_only)
373 {
374     assert_positive(ckmc_remove_user_data,0);
375
376     ChainVerifier<ChainApiOld> cv;
377     cv.verifyPositive(TestData::GIAG2, 2); // including system cert
378 }
379
380 // check invalid arguments
381 RUNNER_TEST(TCCH_0100_get_certificate_chain_invalid_param)
382 {
383     assert_positive(ckmc_remove_user_data,0);
384
385     ckmc_cert_s* ca2 = create_cert(TestData::GIAG2);
386     ckmc_cert_s* ca1 = create_cert(TestData::GEOTRUST);
387     ckmc_cert_list_s* chain = NULL;
388
389     // cert
390     CertListPtr untrusted_c = create_cert_list(ca1, NULL);
391     ca1 = NULL;
392
393     assert_invalid_param(ckmc_get_cert_chain_with_trustedcert,
394                          NULL_CERT,
395                          untrusted_c.get(),
396                          untrusted_c.get(),
397                          true,
398                          &chain);
399
400     assert_invalid_param(ckmc_get_cert_chain_with_trustedcert,
401                          ca2,
402                          untrusted_c.get(),
403                          untrusted_c.get(),
404                          true,
405                          NULL_CHAIN);
406
407     // alias
408     ca1 = create_cert(TestData::GEOTRUST);
409     save_cert(ca1, "GEOTRUST");
410     AliasListPtr untrusted_a = create_alias_list("GEOTRUST", NULL);
411
412     assert_invalid_param(ckmc_get_cert_chain_with_trustedcert_alias,
413                          NULL_CERT,
414                          untrusted_a.get(),
415                          untrusted_a.get(),
416                          true,
417                          &chain);
418
419     assert_invalid_param(ckmc_get_cert_chain_with_trustedcert_alias,
420                          ca2,
421                          untrusted_a.get(),
422                          untrusted_a.get(),
423                          true,
424                          NULL_CHAIN);
425
426     ckmc_cert_free(ca2);
427 }
428
429 // check invalid arguments
430 RUNNER_TEST(TCCH_0110_get_certificate_chain_alias_unknown)
431 {
432     assert_positive(ckmc_remove_user_data,0);
433
434     ckmc_cert_s* ca2 = create_cert(TestData::GIAG2);
435     ckmc_cert_list_s* chain = NULL;
436
437     AliasListPtr non_existing = create_alias_list("NON_EXISTING_ALIAS", NULL);
438     assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
439                   ckmc_get_cert_chain_with_trustedcert_alias,
440                   ca2,
441                   non_existing.get(),
442                   NULL_ALIASES,
443                   true,
444                   &chain);
445
446     assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
447                   ckmc_get_cert_chain_with_trustedcert_alias,
448                   ca2,
449                   NULL_ALIASES,
450                   non_existing.get(),
451                   true,
452                   &chain);
453     ckmc_cert_free(ca2);
454 }
455
456 /*
457  * This test verifies that chain of trust won't be successfully built unless system or trusted
458  * certificates are used even if real trusted root ca certs are used as untrusted.
459  */
460 RUNNER_TEST(TCCH_0120_get_certificate_chain_root_ca_negative)
461 {
462     assert_positive(ckmc_remove_user_data,0);
463
464     ChainVerifier<> cv;
465     cv.enableSystem(false);
466     cv.verifyNegative(TestData::EQUIFAX);
467
468     cv.addUntrusted(TestData::GIAG2);
469     cv.verifyNegative(TestData::GOOGLE_COM);
470 }
471
472 /*
473  * This test verifies that it's possible to build a chain of trust with single trusted certificate
474  * and no system certificates.
475  */
476 RUNNER_TEST(TCCH_0140_get_certificate_chain_trusted_only)
477 {
478     assert_positive(ckmc_remove_user_data,0);
479
480     ChainVerifier<> cv;
481     cv.enableSystem(false);
482     cv.addTrusted(TestData::TEST_ROOT_CA);
483     cv.verifyPositive(TestData::TEST_IM_CA, 2);
484     cv.verifyNegative(TestData::TEST_LEAF);
485 }
486
487 /*
488  * This test verifies that it's possible to build a chain of trust with system certificates only
489  */
490 RUNNER_TEST(TCCH_0150_get_certificate_chain_system_only)
491 {
492     assert_positive(ckmc_remove_user_data,0);
493
494     ChainVerifier<> cv;
495     cv.verifyPositive(TestData::GIAG2, 2); // including system cert
496     cv.verifyNegative(TestData::GOOGLE_COM);
497 }
498
499 /*
500  * Verifies that chain of trust can be built without untrusted certificates.
501  */
502 RUNNER_TEST(TCCH_0160_get_certificate_chain_no_untrusted)
503 {
504     assert_positive(ckmc_remove_user_data,0);
505
506     ChainVerifier<> cv;
507     cv.addTrusted(TestData::TEST_ROOT_CA);
508     cv.verifyPositive(TestData::TEST_IM_CA, 2);// signed by trusted cert (TEST_ROOT_CA)
509     cv.verifyPositive(TestData::GIAG2, 2);    // signed by system cert (GEOTRUST)
510     cv.verifyNegative(TestData::GOOGLE_COM);
511 }
512
513 RUNNER_TEST(TCCH_0170_get_certificate_chain_no_trusted)
514 {
515     assert_positive(ckmc_remove_user_data,0);
516
517     ChainVerifier<> cv;
518     cv.addUntrusted(TestData::GIAG2);
519     cv.verifyPositive(TestData::GOOGLE_COM,3); // including system cert
520     cv.verifyNegative(TestData::TEST_LEAF);
521 }
522
523 /*
524  * Check if its possible to build a chain of trust without system certs.
525  */
526 RUNNER_TEST(TCCH_0180_get_certificate_chain_no_system)
527 {
528     assert_positive(ckmc_remove_user_data,0);
529
530     ChainVerifier<> cv;
531     cv.enableSystem(false);
532     cv.addTrusted(TestData::TEST_ROOT_CA);
533     cv.addUntrusted(TestData::TEST_IM_CA);
534     cv.verifyPositive(TestData::TEST_LEAF, 3);
535     cv.verifyNegative(TestData::GOOGLE_COM);
536 }
537
538 /*
539  * Check if its possible to build a chain of trust with intermediate ca cert in trusted list.
540  */
541 RUNNER_TEST(TCCH_0190_get_certificate_chain_im_ca_in_trusted)
542 {
543     assert_positive(ckmc_remove_user_data,0);
544
545     ChainVerifier<> cv;
546     cv.enableSystem(false);
547     cv.addTrusted(TestData::TEST_ROOT_CA);
548     cv.addTrusted(TestData::TEST_IM_CA);
549     cv.verifyPositive(TestData::TEST_LEAF, 3);
550     cv.verifyNegative(TestData::GOOGLE_COM);
551 }
552
553 RUNNER_TEST(TCCH_0200_get_certificate_chain_all)
554 {
555     assert_positive(ckmc_remove_user_data,0);
556
557     ChainVerifier<> cv;
558     cv.enableSystem(true);
559     cv.addTrusted(TestData::TEST_ROOT_CA);
560     cv.addUntrusted(TestData::GEOTRUST);
561     cv.addUntrusted(TestData::GIAG2);
562     /*
563      * In combat conditions this may as well be 3. Because of 2 existing GeoTrust certificates with
564      * same Subject and Public key one being root ca and the other not there are 2 possible chains
565      * of trust for this certificate.
566      */
567     cv.verifyPositive(TestData::GOOGLE_COM,4);
568     cv.verifyNegative(TestData::TEST_LEAF);
569 }
570
571 RUNNER_TEST(TCCH_9999_deinit)
572 {
573     assert_positive(ckmc_lock_user_key, 0);
574     assert_positive(ckmc_remove_user_data, 0);
575 }