1 /******************************************************************
3 * Copyright 2017 Samsung Electronics All Rights Reserved.
5 * Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
21 #define BOOST_TEST_MODULE Cert Parser
22 #include <boost/test/unit_test.hpp>
23 #include <mbedtls_wrapper.h>
24 #include <mbedtls/pem.h>
25 #include <cert_utils.h>
30 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
31 #define PEM_END_CRT "-----END CERTIFICATE-----\n"
33 namespace bt = boost::unit_test;
36 extern size_t test_data_cert_pem_size;
37 extern unsigned char test_data_cert_pem[];
38 extern size_t test_data_cert_pem2_size;
39 extern unsigned char test_data_cert_pem2[];
40 extern size_t tizen_org_pem_size;
41 extern unsigned char tizen_org_pem[];
44 BOOST_AUTO_TEST_CASE(test_create_destroy)
46 x509_crt_rewriter test_obj;
47 std::unique_ptr<x509_crt_rewriter> test_obj2(new x509_crt_rewriter());
50 BOOST_AUTO_TEST_CASE(test_parse_invalid_cert)
52 x509_crt_rewriter test_obj;
54 std::string invalid_cert("eir09r0934iut9083ug09854ug98u489ghu3908tguj");
56 int error = test_obj.parse(reinterpret_cast<const unsigned char *>(invalid_cert.c_str()),
59 BOOST_REQUIRE_NE(error, 0);
62 BOOST_AUTO_TEST_CASE(test_parse_valid_pem)
64 x509_crt_rewriter test_obj;
66 int error = test_obj.parse(test_data_cert_pem, test_data_cert_pem_size + 1);
67 BOOST_REQUIRE_EQUAL(error, 0);
68 error = test_obj.parse(test_data_cert_pem2, test_data_cert_pem2_size + 1);
69 BOOST_REQUIRE_EQUAL(error, 0);
72 BOOST_AUTO_TEST_CASE(test_parse_pem_without_null)
74 x509_crt_rewriter test_obj;
76 int error = test_obj.parse(test_data_cert_pem, test_data_cert_pem_size);
78 BOOST_REQUIRE_NE(error, 0);
81 BOOST_AUTO_TEST_CASE(test_parse_write_pem_without_sorting)
83 x509_crt_rewriter test_obj;
85 int error = test_obj.parse(test_data_cert_pem, test_data_cert_pem_size + 1);
86 BOOST_REQUIRE_EQUAL(error, 0);
88 BOOST_REQUIRE_THROW(test_obj.emit_pem(), std::exception);
91 BOOST_AUTO_TEST_CASE(test_parse_write_1_pem_with_sorting)
93 x509_crt_rewriter test_obj;
95 int error = test_obj.parse(test_data_cert_pem, test_data_cert_pem_size + 1);
96 BOOST_REQUIRE(error == 0);
98 test_obj.sort_chain();
100 std::string output_cert = test_obj.emit_pem();
102 BOOST_REQUIRE(!output_cert.empty());
103 BOOST_REQUIRE_EQUAL(output_cert[output_cert.length() - 1], 0);
104 BOOST_REQUIRE_EQUAL(output_cert.substr(0, sizeof(PEM_BEGIN_CRT) - 1), PEM_BEGIN_CRT);
106 std::string cert_end = output_cert.substr(output_cert.length() - sizeof(PEM_END_CRT), sizeof(PEM_END_CRT) - 1);
108 BOOST_REQUIRE_EQUAL(cert_end, PEM_END_CRT);
110 BOOST_CHECK_EQUAL(output_cert, std::string((const char *)test_data_cert_pem, test_data_cert_pem_size + 1));
113 BOOST_AUTO_TEST_CASE(test_parse_same_cert_twice)
115 x509_crt_rewriter test_obj;
117 std::string primary_cert((const char *)test_data_cert_pem, test_data_cert_pem_size);
119 std::string to_parse(primary_cert);
120 to_parse += primary_cert;
122 int error = test_obj.parse((const unsigned char *)to_parse.c_str(), to_parse.length() + 1);
123 BOOST_REQUIRE(error == 0);
125 test_obj.sort_chain();
127 BOOST_REQUIRE_THROW(test_obj.emit_pem(), std::exception);
130 BOOST_AUTO_TEST_CASE(test_parse_same_cert_three_times)
132 x509_crt_rewriter test_obj;
134 std::string primary_cert((const char *)test_data_cert_pem, test_data_cert_pem_size);
136 std::string to_parse(primary_cert);
137 to_parse += primary_cert;
138 to_parse += primary_cert;
140 int error = test_obj.parse((const unsigned char *)to_parse.c_str(), to_parse.length() + 1);
141 BOOST_REQUIRE(error == 0);
143 test_obj.sort_chain();
145 BOOST_REQUIRE_THROW(test_obj.emit_pem(), std::exception);
148 BOOST_AUTO_TEST_CASE(test_parse_different_certs)
150 x509_crt_rewriter test_obj;
152 std::string cert1((const char *)test_data_cert_pem, test_data_cert_pem_size);
153 std::string cert2((const char *)test_data_cert_pem2, test_data_cert_pem2_size);
155 std::string to_parse(cert1);
158 int error = test_obj.parse((const unsigned char *)to_parse.c_str(), to_parse.length() + 1);
159 BOOST_REQUIRE_EQUAL(error, 0);
161 test_obj.sort_chain();
163 std::string result_pem = test_obj.emit_pem();
165 std::string result_pem_without_zero = result_pem.substr(0, result_pem.length() - 1);
167 BOOST_REQUIRE((result_pem_without_zero == cert1 + cert2) || (result_pem_without_zero == cert2 + cert1));
170 BOOST_AUTO_TEST_CASE(test_parse_server_pem_tizen_org)
172 x509_crt_rewriter test_obj;
174 int error = test_obj.parse(tizen_org_pem, tizen_org_pem_size + 1);
175 BOOST_REQUIRE(error == 0);
177 test_obj.sort_chain();
179 std::string output_cert = test_obj.emit_pem();
181 BOOST_CHECK_EQUAL(output_cert, std::string((const char *)tizen_org_pem, tizen_org_pem_size + 1));
184 static std::string serialize_cert_chain(const std::vector<mbedtls_x509_crt *>& vec)
190 for(auto cert : vec) {
191 all_size += cert->raw.len * 4 + sizeof(PEM_BEGIN_CRT) + sizeof(PEM_END_CRT);
194 buffer.resize(all_size);
196 unsigned char * out_buffer = (unsigned char *)buffer.c_str();
197 size_t out_capacity = buffer.size();
198 size_t total_size = 0;
201 for(auto cert : vec) {
202 int error = mbedtls_pem_write_buffer(PEM_BEGIN_CRT,
206 out_buffer + total_size,
207 out_capacity - total_size,
211 throw std::runtime_error("Certificate write failure");
214 // Account for final 0 byte
215 total_size += this_len - 1;
218 buffer.resize(total_size);
224 BOOST_AUTO_TEST_CASE(test_case_shuffle_certificates)
226 mbedtls_x509_crt_wrapper chain;
228 int parse_result = mbedtls_x509_crt_parse(&chain, tizen_org_pem, tizen_org_pem_size + 1);
229 BOOST_REQUIRE_EQUAL(parse_result, 0);
231 std::vector<mbedtls_x509_crt *> certs;
233 for(mbedtls_x509_crt * cert = &chain ; cert ; cert = cert->next)
234 certs.push_back(cert);
236 std::sort(certs.begin(), certs.end());
238 std::string correct_pem(std::string((const char *)tizen_org_pem, tizen_org_pem_size + 1));
241 std::string permuted_chain = serialize_cert_chain(certs);
243 x509_crt_rewriter test_obj;
245 int error = test_obj.parse((unsigned char *)permuted_chain.c_str(), permuted_chain.length());
246 BOOST_REQUIRE(error == 0);
248 test_obj.sort_chain();
250 std::string pem = test_obj.emit_pem();
252 BOOST_CHECK_EQUAL(pem, correct_pem);
253 } while(std::next_permutation(certs.begin(), certs.end()));
256 BOOST_AUTO_TEST_CASE(test_case_incomplete_chain)
258 mbedtls_x509_crt_wrapper chain;
260 int parse_result = mbedtls_x509_crt_parse(&chain, tizen_org_pem, tizen_org_pem_size + 1);
261 BOOST_REQUIRE_EQUAL(parse_result, 0);
263 std::vector<mbedtls_x509_crt *> certs;
265 for(mbedtls_x509_crt * cert = &chain ; cert ; cert = cert->next)
266 certs.push_back(cert);
268 // Remove one from chain
269 certs.erase(certs.begin() + 1);
271 std::string correct_pem(std::string((const char *)tizen_org_pem, tizen_org_pem_size + 1));
273 std::string broken_chain = serialize_cert_chain(certs);
275 x509_crt_rewriter test_obj;
277 int error = test_obj.parse((unsigned char *)broken_chain.c_str(), broken_chain.length());
278 BOOST_REQUIRE(error == 0);
280 test_obj.sort_chain();
282 std::string pem = test_obj.emit_pem();
284 BOOST_CHECK_NE(pem, correct_pem);