Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
isotpsecondary.cc
1 #include "isotpsecondary.h"
2 
3 #include <linux/can.h>
4 #include <linux/can/raw.h>
5 #include <net/if.h>
6 #include <sys/ioctl.h>
7 
8 #include <array>
9 #include <future>
10 
11 #include <boost/algorithm/hex.hpp>
12 #include <boost/lexical_cast.hpp>
13 
14 #include "storage/invstorage.h"
15 
16 #define LIBUPTINY_ISOTP_PRIMARY_CANID 0x7D8
17 
18 constexpr size_t kChunkSize = 500;
19 
20 enum class IsoTpUptaneMesType {
21  kGetSerial = 0x01,
22  kGetSerialResp = 0x41,
23  kGetHwId = 0x02,
24  kGetHwIdResp = 0x42,
25  kGetPkey = 0x03,
26  kGetPkeyResp = 0x43,
27  kGetRootVer = 0x04,
28  kGetRootVerResp = 0x44,
29  kGetManifest = 0x05,
30  kGetManifestResp = 0x45,
31  kPutRoot = 0x06,
32  kPutTargets = 0x07,
33  kPutImageChunk = 0x08,
34  kPutImageChunkAckErr = 0x48,
35 };
36 
37 namespace Uptane {
38 
39 IsoTpSecondary::IsoTpSecondary(const std::string& can_iface, uint16_t can_id)
40  : conn(can_iface, LIBUPTINY_ISOTP_PRIMARY_CANID, can_id) {}
41 
42 EcuSerial IsoTpSecondary::getSerial() const {
43  std::string out;
44  std::string in;
45 
46  out += static_cast<char>(IsoTpUptaneMesType::kGetSerial);
47  if (!conn.SendRecv(out, &in)) {
48  return EcuSerial::Unknown();
49  }
50 
51  if (in[0] != static_cast<char>(IsoTpUptaneMesType::kGetSerialResp)) {
52  return EcuSerial::Unknown();
53  }
54  return EcuSerial(in.substr(1));
55 }
56 
57 HardwareIdentifier IsoTpSecondary::getHwId() const {
58  std::string out;
59  std::string in;
60 
61  out += static_cast<char>(IsoTpUptaneMesType::kGetHwId);
62  if (!conn.SendRecv(out, &in)) {
63  return HardwareIdentifier::Unknown();
64  }
65 
66  if (in[0] != static_cast<char>(IsoTpUptaneMesType::kGetHwIdResp)) {
67  return HardwareIdentifier::Unknown();
68  }
69  return HardwareIdentifier(in.substr(1));
70 }
71 
72 PublicKey IsoTpSecondary::getPublicKey() const {
73  std::string out;
74  std::string in;
75 
76  out += static_cast<char>(IsoTpUptaneMesType::kGetPkey);
77  if (!conn.SendRecv(out, &in)) {
78  return PublicKey("", KeyType::kUnknown);
79  }
80 
81  if (in[0] != static_cast<char>(IsoTpUptaneMesType::kGetPkeyResp)) {
82  return PublicKey("", KeyType::kUnknown);
83  }
84  return PublicKey(boost::algorithm::hex(in.substr(1)), KeyType::kED25519);
85 }
86 
87 Uptane::Manifest IsoTpSecondary::getManifest() const {
88  std::string out;
89  std::string in;
90 
91  out += static_cast<char>(IsoTpUptaneMesType::kGetManifest);
92  if (!conn.SendRecv(out, &in)) {
93  return Json::Value(Json::nullValue);
94  }
95 
96  if (in[0] != static_cast<char>(IsoTpUptaneMesType::kGetManifestResp)) {
97  return Json::Value(Json::nullValue);
98  }
99  return Utils::parseJSON(in.substr(1));
100 }
101 
102 int IsoTpSecondary::getRootVersion(bool director) const {
103  if (!director) {
104  return 0;
105  }
106 
107  std::string out;
108  std::string in;
109 
110  out += static_cast<char>(IsoTpUptaneMesType::kGetRootVer);
111  if (!conn.SendRecv(out, &in)) {
112  return -1;
113  }
114 
115  if (in[0] != static_cast<char>(IsoTpUptaneMesType::kGetRootVerResp)) {
116  return -1;
117  }
118  try {
119  return boost::lexical_cast<int>(in.substr(1));
120  } catch (boost::bad_lexical_cast const&) {
121  return -1;
122  }
123 }
124 
125 data::InstallationResult IsoTpSecondary::putRoot(const std::string& root, bool director) {
126  if (!director) {
127  return data::InstallationResult(data::ResultCode::Numeric::kOk, "");
128  }
129  std::string out;
130  out += static_cast<char>(IsoTpUptaneMesType::kPutRoot);
131  out += root;
132 
133  if (conn.Send(out)) {
134  return data::InstallationResult(data::ResultCode::Numeric::kOk, "");
135  } else {
137  "Error sending metadata to Secondary");
138  }
139 }
140 
141 data::InstallationResult IsoTpSecondary::putMetadata(const Target& target) {
142  (void)target;
143  // Partial verification only.
144  std::string director_targets;
145  if (!secondary_provider_->getDirectorMetadata(nullptr, &director_targets)) {
146  LOG_ERROR << "Unable to read Director metadata.";
147  return data::InstallationResult(data::ResultCode::Numeric::kInternalError, "Unable to read Director metadata");
148  }
149 
150  std::string out;
151  out += static_cast<char>(IsoTpUptaneMesType::kPutTargets);
152  out += director_targets;
153 
154  if (conn.Send(out)) {
155  return data::InstallationResult(data::ResultCode::Numeric::kOk, "");
156  } else {
158  "Error sending metadata to Secondary");
159  }
160 }
161 
162 data::InstallationResult IsoTpSecondary::sendFirmware(const Target& target) {
163  (void)target;
164  return data::InstallationResult(data::ResultCode::Numeric::kOk, "");
165 }
166 
167 data::InstallationResult IsoTpSecondary::install(const Target& target) {
168  auto result = data::InstallationResult(data::ResultCode::Numeric::kOk, "");
169 
170  try {
171  auto image_reader = secondary_provider_->getTargetFileHandle(target);
172  uint64_t image_size = target.length();
173 
174  size_t num_chunks = (image_size / kChunkSize) + (static_cast<bool>(image_size % kChunkSize) ? 1 : 0);
175 
176  if (num_chunks > 127) {
178  }
179 
180  for (size_t i = 0; i < num_chunks; ++i) {
181  std::string out;
182  std::string in;
183  out += static_cast<char>(IsoTpUptaneMesType::kPutImageChunk);
184  out += static_cast<char>(num_chunks);
185  out += static_cast<char>(i + 1);
186 
187  std::array<char, kChunkSize> buf{};
188  image_reader.read(buf.data(), kChunkSize);
189  out += std::string(buf.data());
190 
191  if (!conn.SendRecv(out, &in)) {
193  "Error sending metadata to Secondary");
194  break;
195  }
196  if (in[0] != static_cast<char>(IsoTpUptaneMesType::kPutImageChunkAckErr)) {
198  "Error sending metadata to Secondary");
199  break;
200  }
201  if (in[1] != 0x00) {
203  "Error sending metadata to Secondary");
204  break;
205  }
206  }
207 
208  } catch (const std::exception& exc) {
209  LOG_ERROR << "Failed to upload a target image: " << target.filename() << ", error " << exc.what();
210  return data::InstallationResult(data::ResultCode::Numeric::kDownloadFailed, "Error sending metadata to Secondary");
211  }
212  return result;
213 }
214 
215 } // namespace Uptane
SWM Internal integrity error.
Results of libaktualizr API calls.
Definition: results.h:12
Base data types that are used in The Update Framework (TUF), part of Uptane.
Definition: types.h:304