pki_layer.cc 14.3 KB
Newer Older
Yann Garcia's avatar
Yann Garcia committed
1
2
3
4
5
#include "pki_layer_factory.hh"
#include "codec_stack_builder.hh"

#include "loggers.hh"

Yann Garcia's avatar
Yann Garcia committed
6
7
8
9
#include "base_time.hh"

#include "registration.hh"

Yann Garcia's avatar
Yann Garcia committed
10
11
#include "converter.hh"

12
13
#include "security_services.hh"

Yann Garcia's avatar
Yann Garcia committed
14
#include "pki_layer.hh"
garciay's avatar
garciay committed
15

Yann Garcia's avatar
Yann Garcia committed
16
using namespace std; // Required for isnan()
Yann Garcia's avatar
Yann Garcia committed
17
#include "LibItsPki_TypesAndValues.hh"
Yann Garcia's avatar
Yann Garcia committed
18
19
#include "LibItsPki_TestSystem.hh"

20
pki_layer::pki_layer(const std::string & p_type, const std::string & param) : t_layer<LibItsPki__TestSystem::PkiPort>(p_type), _params(), _etsi_ts102941_types_enrolment_inner_request(), _etsi_ts102941_types_enrolment_inner_response(), _etsi_ts102941_types_authorization_validation_request(), _etsi_ts102941_types_authorization_validation_response(), _codec(), _ac_set_security_data(nullptr)
Yann Garcia's avatar
Yann Garcia committed
21
22
23
24
25
26
27
28
29
30
31
32
{
  loggers::get_instance().log(">>> pki_layer::pki_layer: %s, %s", to_string().c_str(), param.c_str());

  // Setup parameters
  params::convert(_params, param);
  // Sanity checks
  params::const_iterator it = _params.find(params::certificate);
  if (it == _params.cend()) {
    _params[params::certificate] = "CERT_TS_A_EA";
  }
  it = _params.find(params::peer_certificate);
  if (it == _params.cend()) {
33
    _params[params::peer_certificate] = "CERT_IUT_A_EA";
Yann Garcia's avatar
Yann Garcia committed
34
  }
garciay's avatar
garciay committed
35
  _params[params::its_aid] = "2468";
Yann Garcia's avatar
Yann Garcia committed
36
  _params[params::payload_type] = "";
37
  _params[params::signature] = "NISTP-256"; // TODO Should be removed
Yann Garcia's avatar
Yann Garcia committed
38
  _params[params::encrypted_mode] = "1";
39
  _params[params::hash] = "SHA-256"; // TODO Should be removed
Yann Garcia's avatar
Yann Garcia committed
40
41
42
43
44
45

  // Register this object for AdapterControlPort
  loggers::get_instance().log("pki_layer::pki_layer: Register %s/%p", p_type.c_str(), this);
  registration<pki_layer>::get_instance().add_item(p_type, this);
}

Yann Garcia's avatar
Yann Garcia committed
46
void pki_layer::sendMsg(const EtsiTs102941TypesEnrolment::InnerEcRequest& p_inner_ec_request, params& p_param) {
garciay's avatar
garciay committed
47
  loggers::get_instance().log_msg(">>> pki_layer::sendMsg: ", p_inner_ec_request);
Yann Garcia's avatar
Yann Garcia committed
48

Yann Garcia's avatar
Yann Garcia committed
49
50
51
52
53
54
55
56
  // Sanity checks
  if (_ac_set_security_data.get() == nullptr) {
    loggers::get_instance().error("pki_layer::sendMsg: Security data missing");
    return;
  }

  OCTETSTRING inner_ec_request;
  _etsi_ts102941_types_enrolment_inner_request.encode(p_inner_ec_request, inner_ec_request);
57
  // Build the EtsiTs103097Data-Signed
58
59
  OCTETSTRING etsi_ts_103097_data;
  if (generate_inner_ec_request_signed_for_pop(inner_ec_request, etsi_ts_103097_data, _params) == -1) {
Yann Garcia's avatar
Yann Garcia committed
60
61
    loggers::get_instance().warning("pki_layer::sendMsg: Failed to generate InnerExRequestSignedForPop");
    return;
Yann Garcia's avatar
Yann Garcia committed
62
  }
63
64
65
66
67
68
69
  // Secured the EtsiTs102941Data layer
  OCTETSTRING etsi_ts_102941_data;
  if (sign_and_encrypt_payload(etsi_ts_103097_data, etsi_ts_102941_data, _params) == -1) {
    loggers::get_instance().warning("pki_layer::sendMsg: Failed to secure Pki message");
    return;
  }
  
garciay's avatar
garciay committed
70
  loggers::get_instance().log_msg("<<< pki_layer::sendMsg: ", etsi_ts_102941_data);
71
72
  
  send_data(etsi_ts_102941_data, _params);
Yann Garcia's avatar
Yann Garcia committed
73
74
}

garciay's avatar
garciay committed
75
76
void pki_layer::sendMsg(const EtsiTs102941TypesEnrolment::InnerEcResponse& p_inner_ec_response, params& p_param) {
  loggers::get_instance().log_msg(">>> pki_layer::sendMsg: ", p_inner_ec_response);
garciay's avatar
garciay committed
77
78
  
  // Create the EtsiTs102941Data layer
79
  EtsiTs102941MessagesCa::EtsiTs102941Data etsi_ts_102941_data;
garciay's avatar
garciay committed
80
81
82
83
84
85
86
87
88
89
90
  etsi_ts_102941_data.content().enrolmentResponse() = p_inner_ec_response;
  loggers::get_instance().log_msg("pki_layer::sendMsg: InnerEcResponse: ", etsi_ts_102941_data);
  
  // Encode it
  OCTETSTRING etsi_ts_103097_data_enc;
  _codec_etsi_ts102941_data.encode(etsi_ts_102941_data, etsi_ts_103097_data_enc);
  if (!etsi_ts_103097_data_enc.is_bound()) {
    loggers::get_instance().warning("pki_layer::sendMsg: Failed to encode InnerEcResponse");
  }
  loggers::get_instance().log_msg("pki_layer::sendMsg: etsi_ts_103097_data_enc: ", etsi_ts_103097_data_enc);
  
91
92
  // Secured the EtsiTs102941Data layer
  OCTETSTRING secured_inner_ec_response;
garciay's avatar
garciay committed
93
  if (sign_and_encrypt_payload(etsi_ts_103097_data_enc, secured_inner_ec_response, p_param) == 0) {
94
95
    send_data(secured_inner_ec_response, _params);
  }
garciay's avatar
garciay committed
96
97
98
99
  
  loggers::get_instance().log_msg("<<< pki_layer::sendMsg: etsi_ts_102941_data:", secured_inner_ec_response);
  
  send_data(secured_inner_ec_response, _params);
100
101
102
103
104
105
106
107
108
}

void pki_layer::sendMsg(const EtsiTs102941TypesAuthorizationValidation::AuthorizationValidationRequest& p_authorization_validation_request, params& p_param) {
  loggers::get_instance().log_msg(">>> pki_layer::sendMsg: ", p_authorization_validation_request);

  // Sanity checks
  if (_ac_set_security_data.get() == nullptr) {
    loggers::get_instance().error("pki_layer::sendMsg: Security data missing");
    return;
Yann Garcia's avatar
Yann Garcia committed
109
  }
garciay's avatar
garciay committed
110
  
111
112
113
114
  // Create the EtsiTs102941Data layer
  EtsiTs102941MessagesCa::EtsiTs102941Data etsi_ts_102941_data;
  etsi_ts_102941_data.content().authorizationValidationRequest() = p_authorization_validation_request;
  loggers::get_instance().log_msg("pki_layer::sendMsg: AuthorizationValidationRequest: ", etsi_ts_102941_data);
garciay's avatar
garciay committed
115
  
garciay's avatar
garciay committed
116
117
118
119
120
121
122
123
  // Encode it
  OCTETSTRING etsi_ts_103097_data_enc;
  _codec_etsi_ts102941_data.encode(etsi_ts_102941_data, etsi_ts_103097_data_enc);
  if (!etsi_ts_103097_data_enc.is_bound()) {
    loggers::get_instance().warning("pki_layer::sendMsg: Failed to encode AuthorizationValidationRequest");
  }
  loggers::get_instance().log_msg("pki_layer::sendMsg: etsi_ts_103097_data_enc: ", etsi_ts_103097_data_enc);
  
124
  // Secured the EtsiTs102941Data layer
garciay's avatar
garciay committed
125
126
  OCTETSTRING secured_authorization_validation_request;
  if (sign_and_encrypt_payload(etsi_ts_103097_data_enc, secured_authorization_validation_request, _params) == -1) {
127
128
129
130
    loggers::get_instance().warning("pki_layer::sendMsg: Failed to secure Pki message");
    return;
  }
  
garciay's avatar
garciay committed
131
  loggers::get_instance().log_msg("<<< pki_layer::sendMsg: generate_authorization_validation_request: ", secured_authorization_validation_request);
132
  
garciay's avatar
garciay committed
133
  send_data(secured_authorization_validation_request, _params);
Yann Garcia's avatar
Yann Garcia committed
134
135
136
137
138
139
140
141
142
143
144
}

void pki_layer::send_data(OCTETSTRING& data, params& params) {
  loggers::get_instance().log_msg(">>> pki_layer::send_data: ", data);

  send_to_all_layers(data, params);
}

void pki_layer::receive_data(OCTETSTRING& data, params& params)
{
  loggers::get_instance().log_msg(">>> pki_layer::receive_data: ", data);
145
146
147
148
  
  // 1. Extract EtsiTs102941Data or EtsiTs103097DataSigned
  OCTETSTRING unsecured_payload;
  if (decrypt_and_check_signature(data, unsecured_payload, _params) == -1) {
149
150
151
    loggers::get_instance().warning("pki_layer::sendMsg: Failed to secure Pki message");
    return;
  }
152
153
154
  loggers::get_instance().log_msg("pki_layer::receive_data: unsecured_payload=", unsecured_payload);

  // Try to extract EtsiTs102941Data
155
  EtsiTs102941MessagesCa::EtsiTs102941Data etsi_ts_102941_data;
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  if (_codec_etsi_ts102941_data.decode(unsecured_payload, etsi_ts_102941_data) == -1) {
    // Try with EtsiTs103097Data-Signed
    IEEE1609dot2::Ieee1609Dot2Data etsi_ts_1609dot2_data;
    if (_codec.decode(unsecured_payload, etsi_ts_1609dot2_data) == -1) {
      loggers::get_instance().warning("pki_layer::sendMsg: Failed to decode unsecured payload");
      return;
    } else {
      // Process EtsiTs103097Data-Signed
      loggers::get_instance().log_msg("pki_layer::receive_data: Process ", etsi_ts_1609dot2_data);
    }
  } else {
    // TODO Process EtsiTs102941Data
    loggers::get_instance().log_msg("pki_layer::receive_data: Process ", etsi_ts_102941_data);
    // Check protocol version
    if (etsi_ts_102941_data.version() != 1) {
      loggers::get_instance().warning("pki_layer::sendMsg: Wrong ETSI TS 102 941 protocol version, discard it!");
      return;
    }
174
    if (etsi_ts_102941_data.content().ischosen(EtsiTs102941MessagesCa::EtsiTs102941DataContent::ALT_enrolmentResponse)) {
175
176
177
178
      // Pass it to the ports
      to_all_upper_ports(etsi_ts_102941_data.content().enrolmentResponse(), _params);
    }
  }
Yann Garcia's avatar
Yann Garcia committed
179
  
180
181
182
183
184
185
186
187
188
189
190
  // Pass it to the ports
  //to_all_upper_ports(pki_message, params);
}

void pki_layer::set_pki_keys(const LibItsPki__TypesAndValues::AcSetSecurityData& p_ac_set_security_data) {
  loggers::get_instance().log_msg(">>> pki_layer::set_pki_keys: ", p_ac_set_security_data);

  _ac_set_security_data.reset(new LibItsPki__TypesAndValues::AcSetSecurityData(p_ac_set_security_data));
  loggers::get_instance().log_msg("pki_layer::set_pki_keys: New data", *_ac_set_security_data);
  _params[params::certificate] = p_ac_set_security_data.certificateId();
  _params[params::peer_certificate] = p_ac_set_security_data.peer__certificateId();
Yann Garcia's avatar
Yann Garcia committed
191
192
}

193
int pki_layer::generate_inner_ec_request_signed_for_pop(const OCTETSTRING& p_inner_ec_request, OCTETSTRING& p_etsi_ts_103097_data, params& p_params) {
Yann Garcia's avatar
Yann Garcia committed
194
195
  loggers::get_instance().log_msg(">>> pki_layer::generate_inner_ec_request_signed_for_pop: ", p_inner_ec_request);

196
197
198
199
  // Re-configure default parameters
  params p(p_params);
  p[params::peer_certificate] = p[params::certificate]; // ETSI TS 102 941 Clause 6.2.3.2.1	Enrolment request 
  
Yann Garcia's avatar
Yann Garcia committed
200
201
202
  // Set unsecured data
  IEEE1609dot2::Ieee1609Dot2Content unsecured_data_content;
  unsecured_data_content.unsecuredData() = p_inner_ec_request;
203
  IEEE1609dot2::Ieee1609Dot2Data unsecured_data(security_services::get_instance().get_protocol_version(), unsecured_data_content);
Yann Garcia's avatar
Yann Garcia committed
204
205
  // Set hash algorithm
  IEEE1609dot2BaseTypes::HashAlgorithm hashId(IEEE1609dot2BaseTypes::HashAlgorithm::sha256);
206
  if (p[params::hash].compare("SHA-384") == 0) {
Yann Garcia's avatar
Yann Garcia committed
207
208
209
210
211
212
213
    hashId = IEEE1609dot2BaseTypes::HashAlgorithm::sha384;
  }
  // Set SignedDataPayload
  IEEE1609dot2::SignedDataPayload payload;
  payload.data() = unsecured_data;
  payload.extDataHash().set_to_omit();
  IEEE1609dot2::HeaderInfo header_info;
214
215
216
217
218
  header_info.psid() = converter::get_instance().string_to_int(p[params::its_aid]);
  unsigned long long ms = base_time::get_instance().get_its_current_time();
  INTEGER i;
  i.set_long_long_val((unsigned int)ms);
  header_info.generationTime() = OPTIONAL<INTEGER>(i);
Yann Garcia's avatar
Yann Garcia committed
219
220
221
222
223
224
225
226
227
228
229
  header_info.expiryTime().set_to_omit();
  header_info.generationLocation().set_to_omit();
  header_info.p2pcdLearningRequest().set_to_omit();
  header_info.missingCrlIdentifier().set_to_omit();
  header_info.encryptionKey().set_to_omit();
  header_info.inlineP2pcdRequest().set_to_omit();
  header_info.requestedCertificate().set_to_omit();

  IEEE1609dot2::ToBeSignedData tbs_data;
  tbs_data.payload() = payload;
  tbs_data.headerInfo() = header_info;
230
231
232
  loggers::get_instance().log_msg("pki_layer::generate_inner_ec_request_signed_for_pop: tbs_data = ", tbs_data);
  // Sign the ToBeSignedData data structure using the private key of the requested certificate
  loggers::get_instance().log_msg("pki_layer::generate_inner_ec_request_signed_for_pop: Private key = ", _ac_set_security_data->private__key());
Yann Garcia's avatar
Yann Garcia committed
233
  IEEE1609dot2BaseTypes::Signature signature;
234
235
  if (security_services::get_instance().sign_tbs_data(tbs_data, hashId, _ac_set_security_data->private__key(), signature, p) != 0) {
    loggers::get_instance().warning("pki_layer::generate_inner_ec_request_signed_for_pop: Failed to secure payload");
Yann Garcia's avatar
Yann Garcia committed
236
    return -1;
237
238
  }
  // Finalyse the EtsiTs103097Data-Signed
Yann Garcia's avatar
Yann Garcia committed
239
  IEEE1609dot2::SignerIdentifier signer;
240
  signer.self__() = ASN_NULL_VALUE;
Yann Garcia's avatar
Yann Garcia committed
241
  IEEE1609dot2::SignedData signed_data(hashId, tbs_data, signer, signature);
242
  loggers::get_instance().log_msg("pki_layer::generate_inner_ec_request_signed_for_pop: signed_data = ", signed_data);
Yann Garcia's avatar
Yann Garcia committed
243
244
245
  IEEE1609dot2::Ieee1609Dot2Content ieee_dot2_content;
  ieee_dot2_content.signedData() = signed_data;
  IEEE1609dot2::Ieee1609Dot2Data ieee_1609dot2_data(pki_layer::ProtocolVersion, ieee_dot2_content);
246
247
  loggers::get_instance().log_msg("pki_layer::generate_inner_ec_request_signed_for_pop: ieee_1609dot2_data = ", ieee_1609dot2_data);
  // Create the EtsiTs102941Data layer (InnerEcRequestSignedForPop)
248
  EtsiTs102941MessagesCa::EtsiTs102941Data etsi_ts_102941_data;
249
  etsi_ts_102941_data.content().enrolmentRequest() = ieee_1609dot2_data;
250
  loggers::get_instance().log_msg("pki_layer::generate_inner_ec_request_signed_for_pop: InnerEcRequestSignedForPop: ", etsi_ts_102941_data);
251
252
  _codec.encode(ieee_1609dot2_data, p_etsi_ts_103097_data);
  if (!p_etsi_ts_103097_data.is_bound()) {
253
254
255
    loggers::get_instance().warning("pki_layer::generate_inner_ec_request_signed_for_pop: Failed to encode InnerEcRequestSignedForPop");
    return -1;
  }
256
257
  
  loggers::get_instance().log_msg("<<< pki_layer::generate_inner_ec_request_signed_for_pop: ", p_etsi_ts_103097_data);
Yann Garcia's avatar
Yann Garcia committed
258
259
260
  return 0;
}

261
262
int pki_layer::sign_and_encrypt_payload(const OCTETSTRING& p_etsi_ts_102941_data, OCTETSTRING& p_secured_data, params& p_params) {
  loggers::get_instance().log_msg(">>> pki_layer::sign_and_encrypt_payload: ", p_etsi_ts_102941_data);
Yann Garcia's avatar
Yann Garcia committed
263

garciay's avatar
garciay committed
264
265
  // 1. Signed the data
  OCTETSTRING signed_data;
266
  if (security_services::get_instance().sign_payload(p_etsi_ts_102941_data, signed_data, p_params) == -1) {
garciay's avatar
garciay committed
267
268
    loggers::get_instance().warning("http_etsi_ieee1609dot2_codec::encode: Failed to sign data");
    return -1;
Yann Garcia's avatar
Yann Garcia committed
269
  }
garciay's avatar
garciay committed
270
271
  loggers::get_instance().log_msg("pki_layer::sign_and_encrypt_payload: signed_data=", signed_data);
  // 2. Encrypt the signed packet
272
273
274
275
276
277
278
279
280
  if (security_services::get_instance().encrypt_gn_payload(signed_data, p_secured_data, p_params) == -1) {
    loggers::get_instance().warning("http_etsi_ieee1609dot2_codec::sign_and_encrypt_payload: Failed to encrypt data");
    return -1;
  }
  loggers::get_instance().log_msg("<<< http_etsi_ieee1609dot2_codec::sign_and_encrypt_payload: ", p_secured_data);
  
  return 0;
}

281
int pki_layer::decrypt_and_check_signature(const OCTETSTRING& p_signed_and_encrypted_data, OCTETSTRING& p_unsecured_payload, params& p_params) {
282
283
284
285
286
  loggers::get_instance().log_msg(">>> pki_layer::decrypt_and_check_signature: ", p_signed_and_encrypted_data);

  // 1. Decrypt the Pki message
  OCTETSTRING os;
  if (security_services::get_instance().decrypt_gn_payload(p_signed_and_encrypted_data, os, p_params) == -1) {
287
288
289
290
291
292
293
294
295
    loggers::get_instance().warning("http_etsi_ieee1609dot2_codec::decrypt_and_check_signature: Failed to decrypt data");
    return -1;
  }
  loggers::get_instance().log_msg("pki_layer::decrypt_and_check_signature: Decrypted playload=", os);
  // 2. Decode EtsiTs103097Data-Signed and check signature
  IEEE1609dot2::Ieee1609Dot2Data etsi_ts_1609dot2_data;

  if (security_services::get_instance().verify_and_extract_gn_payload(os, true, etsi_ts_1609dot2_data, p_unsecured_payload, p_params) == -1) {
    loggers::get_instance().warning("http_etsi_ieee1609dot2_codec::decrypt_and_check_signature: Failed to verify EtsiTs103097Data-Signed data");
garciay's avatar
garciay committed
296
297
    return -1;
  }
298
  loggers::get_instance().log_msg("pki_layer::decrypt_and_check_signature: EtsiTs103097Data-Signed=", etsi_ts_1609dot2_data);
garciay's avatar
garciay committed
299
300
  
  return 0;
Yann Garcia's avatar
Yann Garcia committed
301
302
303
304
}

pki_layer_factory pki_layer_factory::_f;