apdu_command.h 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef COMPONENTS_APDU_APDU_COMMAND_H_
  5. #define COMPONENTS_APDU_APDU_COMMAND_H_
  6. #include <cinttypes>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/component_export.h"
  10. #include "base/containers/span.h"
  11. #include "base/gtest_prod_util.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. namespace apdu {
  14. // APDU commands are defined as part of ISO 7816-4. Commands can be serialized
  15. // into either short length encodings, where the maximum data length is 256
  16. // bytes, or an extended length encoding, where the maximum data length is 65536
  17. // bytes. This class implements only the extended length encoding. Serialized
  18. // commands consist of a CLA byte, denoting the class of instruction, an INS
  19. // byte, denoting the instruction code, P1 and P2, each one byte denoting
  20. // instruction parameters, a length field (Lc), a data field of length Lc, and
  21. // a maximum expected response length (Le).
  22. class COMPONENT_EXPORT(APDU) ApduCommand {
  23. public:
  24. // Constructs an APDU command from the serialized message data.
  25. static absl::optional<ApduCommand> CreateFromMessage(
  26. base::span<const uint8_t> message);
  27. ApduCommand();
  28. ApduCommand(uint8_t cla,
  29. uint8_t ins,
  30. uint8_t p1,
  31. uint8_t p2,
  32. size_t response_length,
  33. std::vector<uint8_t> data);
  34. ApduCommand(ApduCommand&& that);
  35. ApduCommand& operator=(ApduCommand&& that);
  36. ApduCommand(const ApduCommand&) = delete;
  37. ApduCommand& operator=(const ApduCommand&) = delete;
  38. ~ApduCommand();
  39. // Returns serialized message data.
  40. std::vector<uint8_t> GetEncodedCommand() const;
  41. void set_cla(uint8_t cla) { cla_ = cla; }
  42. void set_ins(uint8_t ins) { ins_ = ins; }
  43. void set_p1(uint8_t p1) { p1_ = p1; }
  44. void set_p2(uint8_t p2) { p2_ = p2; }
  45. void set_data(std::vector<uint8_t> data) { data_ = std::move(data); }
  46. void set_response_length(size_t response_length) {
  47. response_length_ = response_length;
  48. }
  49. uint8_t cla() const { return cla_; }
  50. uint8_t ins() const { return ins_; }
  51. uint8_t p1() const { return p1_; }
  52. uint8_t p2() const { return p2_; }
  53. size_t response_length() const { return response_length_; }
  54. const std::vector<uint8_t>& data() const { return data_; }
  55. static constexpr size_t kApduMaxResponseLength = 65536;
  56. private:
  57. FRIEND_TEST_ALL_PREFIXES(ApduTest, TestDeserializeBasic);
  58. FRIEND_TEST_ALL_PREFIXES(ApduTest, TestDeserializeComplex);
  59. FRIEND_TEST_ALL_PREFIXES(ApduTest, TestSerializeEdgeCases);
  60. static constexpr size_t kApduMinHeader = 4;
  61. static constexpr size_t kApduMaxHeader = 7;
  62. static constexpr size_t kApduCommandDataOffset = 7;
  63. static constexpr size_t kApduCommandLengthOffset = 5;
  64. // As defined in ISO7816-4, extended length APDU request data is limited to
  65. // 16 bits in length with a maximum value of 65535. Response data length is
  66. // also limited to 16 bits in length with a value of 0x0000 corresponding to
  67. // a length of 65536.
  68. static constexpr size_t kApduMaxDataLength = 65535;
  69. static constexpr size_t kApduMaxLength =
  70. kApduMaxDataLength + kApduMaxHeader + 2;
  71. uint8_t cla_ = 0;
  72. uint8_t ins_ = 0;
  73. uint8_t p1_ = 0;
  74. uint8_t p2_ = 0;
  75. size_t response_length_ = 0;
  76. std::vector<uint8_t> data_;
  77. };
  78. } // namespace apdu
  79. #endif // COMPONENTS_APDU_APDU_COMMAND_H_