Aktualizr
C++ SOTA Client
asn1_test.cc
Go to the documentation of this file.
1 /**
2  * \file
3  */
4 
5 #include <gtest/gtest.h>
6 
7 #include <iostream>
8 #include <string>
9 
10 #include "asn1/asn1_message.h"
11 #include "config/config.h"
12 #include "der_encoder.h"
13 
14 void printStringHex(const std::string& s) {
15  for (char c : s) {
16  std::cerr << std::setfill('0') << std::setw(2) << std::hex << (((unsigned int)c) & 0xFF);
17  std::cerr << ' ';
18  }
19 
20  std::cerr << std::dec << std::endl;
21 }
22 
23 std::string CCString(OCTET_STRING_t par) { return std::string((const char*)par.buf, (size_t)par.size); }
24 bool operator==(const AKTlsConfig& cc_config, const TlsConfig& config) {
25  if (config.server != CCString(cc_config.server)) return false;
26  if (config.server_url_path.string() != CCString(cc_config.serverUrlPath)) return false;
27  if (static_cast<int>(config.ca_source) != cc_config.caSource) return false;
28  if (static_cast<int>(config.pkey_source) != cc_config.pkeySource) return false;
29  if (static_cast<int>(config.cert_source) != cc_config.certSource) return false;
30  return true;
31 }
32 
33 bool operator==(const TlsConfig& config, const AKTlsConfig& cc_config) { return cc_config == config; }
34 
35 TEST(asn1_config, tls_config) {
37 
38  conf.server = "https://example.com";
39  conf.server_url_path = "";
40  conf.ca_source = CryptoSource::kFile;
41  conf.pkey_source = CryptoSource::kPkcs11;
42  conf.cert_source = CryptoSource::kPkcs11;
43 
44  asn1::Serializer ser;
45  ser << conf;
46  asn1::Deserializer des(ser.getResult());
47 
48  TlsConfig conf2;
49  EXPECT_NO_THROW(des >> conf2);
50  EXPECT_EQ(conf.server, conf2.server);
51  EXPECT_EQ(conf.server_url_path, conf2.server_url_path);
52  EXPECT_EQ(conf.ca_source, conf2.ca_source);
53  EXPECT_EQ(conf.pkey_source, conf2.pkey_source);
54  EXPECT_EQ(conf.cert_source, conf2.cert_source);
55 }
56 
57 TEST(asn1_config, tls_config_asn1cc_to_man) {
58  AKTlsConfig_t cc_tls_conf;
59  memset(&cc_tls_conf, 0, sizeof(cc_tls_conf));
60 
61  std::string server = "https://example.com";
62  EXPECT_EQ(0, OCTET_STRING_fromBuf(&cc_tls_conf.server, server.c_str(), static_cast<int>(server.length())));
63 
64  std::string server_url_path = "";
65  EXPECT_EQ(0, OCTET_STRING_fromBuf(&cc_tls_conf.serverUrlPath, server_url_path.c_str(),
66  static_cast<int>(server_url_path.length())));
67 
68  cc_tls_conf.caSource = static_cast<int>(CryptoSource::kFile);
69  cc_tls_conf.pkeySource = static_cast<int>(CryptoSource::kPkcs11);
70  cc_tls_conf.certSource = static_cast<int>(CryptoSource::kPkcs11);
71 
72  asn_enc_rval_t enc;
73  std::string der;
74 
75  enc = der_encode(&asn_DEF_AKTlsConfig, &cc_tls_conf, Asn1StringAppendCallback, &der);
76  EXPECT_NE(enc.encoded, -1);
77 
79  asn1::Deserializer des(der);
80  EXPECT_NO_THROW(des >> conf);
81  EXPECT_EQ(conf, cc_tls_conf);
82  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_AKTlsConfig, &cc_tls_conf);
83 }
84 
85 TEST(asn1_config, tls_config_man_to_asn1cc) {
87 
88  conf.server = "https://example.com";
89  conf.server_url_path = "";
90  conf.ca_source = CryptoSource::kFile;
91  conf.pkey_source = CryptoSource::kPkcs11;
92  conf.cert_source = CryptoSource::kPkcs11;
93 
94  asn1::Serializer ser;
95 
96  ser << conf;
97 
98  AKTlsConfig_t* cc_tls_conf = nullptr;
99  asn_dec_rval_t ret =
100  ber_decode(0, &asn_DEF_AKTlsConfig, (void**)&cc_tls_conf, ser.getResult().c_str(), ser.getResult().length());
101  EXPECT_EQ(ret.code, RC_OK);
102  EXPECT_EQ(*cc_tls_conf, conf);
103  ASN_STRUCT_FREE(asn_DEF_AKTlsConfig, cc_tls_conf);
104 }
105 
106 TEST(asn1_common, longstring) {
107  std::string in =
108  "-----BEGIN PUBLIC KEY-----\
109 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumdoILJANzcKUn0IZi1B\
110 OB6jj0uE5XrZPTbUuQT8jsA+rYNet1VF1Y0X8/hftShHzL8M+X9rlEwvnAhzdWKd\
111 IEQUjfuiJIOLBtAGZZNYdTTXx7sFQ/UQwKo8mU6vSMqsbOdzidp6SpRRiEHpWH4m\
112 rvurn/jWPAVY2vwD0VxUBl1ps/C4qYGqeRQz7o7SAgV3NPDZLPbKVz9+YH+tkVR+\
113 FMsH9/YebTpaiL8uQsf24WdeVUc7WCJLzOTvPh+FnNB2y78ye29sIwHpbiivmfrO\
114 GSdjzMzSMr0UATqOXcaONhPKGNDQ3jhTCayi/lryYBgpRyvSLRpaIlaS0dLtp7Zp\
115 zQIDAQAB\
116 -----END PUBLIC KEY-----";
117 
118  asn1::Serializer ser;
119  ser << asn1::implicit<kAsn1OctetString>(in);
120  asn1::Deserializer des(ser.getResult());
121 
122  std::string out;
123  EXPECT_NO_THROW(des >> asn1::implicit<kAsn1OctetString>(out));
124  EXPECT_EQ(in, out);
125 }
126 
127 TEST(asn1_common, longlongstring) {
128  std::string in =
129  "-----BEGIN PUBLIC KEY-----\
130 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumdoILJANzcKUn0IZi1B\
131 OB6jj0uE5XrZPTbUuQT8jsA+rYNet1VF1Y0X8/hftShHzL8M+X9rlEwvnAhzdWKd\
132 IEQUjfuiJIOLBtAGZZNYdTTXx7sFQ/UQwKo8mU6vSMqsbOdzidp6SpRRiEHpWH4m\
133 rvurn/jWPAVY2vwD0VxUBl1ps/C4qYGqeRQz7o7SAgV3NPDZLPbKVz9+YH+tkVR+\
134 FMsH9/YebTpaiL8uQsf24WdeVUc7WCJLzOTvPh+FnNB2y78ye29sIwHpbiivmfrO\
135 GSdjzMzSMr0UATqOXcaONhPKGNDQ3jhTCayi/lryYBgpRyvSLRpaIlaS0dLtp7Zp\
136 zQIDAQAB\
137 -----END PUBLIC KEY-----\
138 -----BEGIN PUBLIC KEY-----\
139 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumdoILJANzcKUn0IZi1B\
140 OB6jj0uE5XrZPTbUuQT8jsA+rYNet1VF1Y0X8/hftShHzL8M+X9rlEwvnAhzdWKd\
141 IEQUjfuiJIOLBtAGZZNYdTTXx7sFQ/UQwKo8mU6vSMqsbOdzidp6SpRRiEHpWH4m\
142 rvurn/jWPAVY2vwD0VxUBl1ps/C4qYGqeRQz7o7SAgV3NPDZLPbKVz9+YH+tkVR+\
143 FMsH9/YebTpaiL8uQsf24WdeVUc7WCJLzOTvPh+FnNB2y78ye29sIwHpbiivmfrO\
144 GSdjzMzSMr0UATqOXcaONhPKGNDQ3jhTCayi/lryYBgpRyvSLRpaIlaS0dLtp7Zp\
145 zQIDAQAB\
146 -----END PUBLIC KEY-----\
147 -----BEGIN PUBLIC KEY-----\
148 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumdoILJANzcKUn0IZi1B\
149 OB6jj0uE5XrZPTbUuQT8jsA+rYNet1VF1Y0X8/hftShHzL8M+X9rlEwvnAhzdWKd\
150 IEQUjfuiJIOLBtAGZZNYdTTXx7sFQ/UQwKo8mU6vSMqsbOdzidp6SpRRiEHpWH4m\
151 rvurn/jWPAVY2vwD0VxUBl1ps/C4qYGqeRQz7o7SAgV3NPDZLPbKVz9+YH+tkVR+\
152 FMsH9/YebTpaiL8uQsf24WdeVUc7WCJLzOTvPh+FnNB2y78ye29sIwHpbiivmfrO\
153 GSdjzMzSMr0UATqOXcaONhPKGNDQ3jhTCayi/lryYBgpRyvSLRpaIlaS0dLtp7Zp\
154 zQIDAQAB\
155 -----END PUBLIC KEY-----\
156 -----BEGIN PUBLIC KEY-----\
157 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumdoILJANzcKUn0IZi1B\
158 OB6jj0uE5XrZPTbUuQT8jsA+rYNet1VF1Y0X8/hftShHzL8M+X9rlEwvnAhzdWKd\
159 IEQUjfuiJIOLBtAGZZNYdTTXx7sFQ/UQwKo8mU6vSMqsbOdzidp6SpRRiEHpWH4m\
160 rvurn/jWPAVY2vwD0VxUBl1ps/C4qYGqeRQz7o7SAgV3NPDZLPbKVz9+YH+tkVR+\
161 FMsH9/YebTpaiL8uQsf24WdeVUc7WCJLzOTvPh+FnNB2y78ye29sIwHpbiivmfrO\
162 GSdjzMzSMr0UATqOXcaONhPKGNDQ3jhTCayi/lryYBgpRyvSLRpaIlaS0dLtp7Zp\
163 zQIDAQAB\
164 -----END PUBLIC KEY-----";
165 
166  asn1::Serializer ser;
167  ser << asn1::implicit<kAsn1OctetString>(in);
168  asn1::Deserializer des(ser.getResult());
169 
170  std::string out;
171  EXPECT_NO_THROW(des >> asn1::implicit<kAsn1OctetString>(out));
172  EXPECT_EQ(in, out);
173 }
174 
175 TEST(asn1_common, Asn1MessageSimple) {
176  // Fill in a message
177  Asn1Message::Ptr original(Asn1Message::Empty());
178  original->present(AKIpUptaneMes_PR_discoveryResp);
179  Asn1Message::SubPtr<AKDiscoveryRespMes_t> req = original->discoveryResp();
180  SetString(&req->ecuSerial, "serial1234");
181 
182  // BER encode
183  std::string buffer;
184  der_encode(&asn_DEF_AKIpUptaneMes, &original->msg_, Asn1StringAppendCallback, &buffer);
185 
186  EXPECT_GT(buffer.size(), 0);
187 
188  // BER decode
189  asn_codec_ctx_t context;
190  memset(&context, 0, sizeof(context));
191 
192  AKIpUptaneMes_t* m = nullptr;
193  asn_dec_rval_t res =
194  ber_decode(&context, &asn_DEF_AKIpUptaneMes, reinterpret_cast<void**>(&m), buffer.c_str(), buffer.size());
195  Asn1Message::Ptr msg = Asn1Message::FromRaw(&m);
196 
197  // Check decoding succeeded
198  EXPECT_EQ(res.code, RC_OK);
199  EXPECT_EQ(res.consumed, buffer.size());
200 
201  // Check results are what we started with
202  EXPECT_EQ(msg->present(), AKIpUptaneMes_PR_discoveryResp);
203  Asn1Message::SubPtr<AKDiscoveryRespMes_t> resp = msg->discoveryResp();
204  msg.reset(); // Asn1Message::SubPtr<T> keeps the root object alive
205  EXPECT_EQ(ToString(resp->ecuSerial), "serial1234");
206 }
207 
208 TEST(asn1_common, parse) {
209  std::string data = Utils::fromBase64("rAowCAQGaGVsbG8K");
210  // BER decode
211  asn_codec_ctx_t context;
212  memset(&context, 0, sizeof(context));
213 
214  AKIpUptaneMes_t* m = nullptr;
215  asn_dec_rval_t res =
216  ber_decode(&context, &asn_DEF_AKIpUptaneMes, reinterpret_cast<void**>(&m), data.c_str(), data.size());
217  Asn1Message::Ptr msg = Asn1Message::FromRaw(&m);
218  EXPECT_EQ(res.code, RC_OK);
219  EXPECT_EQ(AKIpUptaneMes_PR_sendFirmwareReq, msg->present());
220 }
221 
222 TEST(asn1_common, Asn1MessageFromRawNull) {
223  Asn1Message::FromRaw(nullptr);
224  AKIpUptaneMes_t* m = nullptr;
226 }
227 
228 #ifndef __NO_MAIN__
229 int main(int argc, char** argv) {
230  ::testing::InitGoogleTest(&argc, argv);
231  return RUN_ALL_TESTS();
232 }
233 #endif
General data structures.
Definition: types.cc:6
static Asn1Message::Ptr FromRaw(AKIpUptaneMes_t **msg)
Destructively copy from a raw msg pointer created by parsing an incomming message.
Definition: asn1_message.h:53
Config conf("tests/config/basic.toml")
static Asn1Message::Ptr Empty()
Create a new Asn1Message, in order to fill it with data and send it.
Definition: asn1_message.h:46