AuthenticationSecure.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2023 SICK AG, Waldkirch
3 //
4 // SPDX-License-Identifier: Unlicense
5 
6 #include "AuthenticationSecure.h"
7 #include "CoLaParameterWriter.h"
8 #include "SHA256.h"
9 
10 namespace visionary {
11 
12 namespace {
13 enum class ChallengeResponseResult : std::uint8_t
14 {
15  SUCCESS = 0u,
16  INVALID_CLIENT = 1u,
17  NOT_ACCEPTED = 2u,
18  UNKNOWN_CHALLENGE = 3u,
19  PWD_NOT_CHANGABLE = 4u,
20  TIMELOCK_ACTIVE = 5u
21 };
22 }
23 
24 AuthenticationSecure::AuthenticationSecure(VisionaryControl& vctrl) : m_VisionaryControl(vctrl), m_protocolType(UNKNOWN)
25 
26 {
27 }
28 
30 
32  const std::string& password,
33  const ChallengeRequest& challengeRequest,
34  ProtocolType protocolType)
35 {
36  PasswordHash passwordHash{};
37  std::string passwordPrefix{};
38 
39  switch (userLevel)
40  {
41  case UserLevel::RUN:
42  {
43  passwordPrefix = "Run";
44  break;
45  }
47  {
48  passwordPrefix = "Operator";
49  break;
50  }
52  {
53  passwordPrefix = "Maintenance";
54  break;
55  }
57  {
58  passwordPrefix = "AuthorizedClient";
59  break;
60  }
61  case UserLevel::SERVICE:
62  {
63  passwordPrefix = "Service";
64  break;
65  }
66  default:
67  {
68  // return empty hash code in case of error
69  return passwordHash;
70  break;
71  }
72  }
73  std::string separator = ":";
74  std::string passwordWithPrefix = passwordPrefix + ":SICK Sensor:" + password;
75 
76  hash_state hashState{};
77  sha256_init(&hashState);
78 
79  sha256_process(&hashState,
80  reinterpret_cast<const uint8_t*>(passwordWithPrefix.c_str()),
81  static_cast<ulong32>(passwordWithPrefix.size()));
82  if (protocolType == SUL2)
83  {
85  &hashState, reinterpret_cast<const uint8_t*>(separator.c_str()), static_cast<ulong32>(separator.size()));
86  sha256_process(&hashState, challengeRequest.salt.data(), static_cast<ulong32>(challengeRequest.salt.size()));
87  }
88  sha256_done(&hashState, passwordHash.data());
89 
90  return passwordHash;
91 }
92 
94  const std::string& password,
95  const ChallengeRequest& challengeRequest,
96  ProtocolType protocolType)
97 {
98  ChallengeResponse challengeResponse{};
99  PasswordHash passwordHash = CreatePasswordHash(userLevel, password, challengeRequest, protocolType);
100 
101  hash_state hashState{};
102  sha256_init(&hashState);
103  sha256_process(&hashState, passwordHash.data(), static_cast<ulong32>(passwordHash.size()));
105  &hashState, challengeRequest.challenge.data(), static_cast<ulong32>(challengeRequest.challenge.size()));
106  sha256_done(&hashState, challengeResponse.data());
107 
108  return challengeResponse;
109 }
110 
112  const std::string& password,
113  const CoLaParameterReader& getChallengeResponse,
114  ProtocolType protocolType)
115 {
116  bool isLoginSuccessful = false;
117  // read and check response of GetChallenge command
118  CoLaParameterReader coLaParameterReader = CoLaParameterReader(getChallengeResponse);
119  if (static_cast<ChallengeResponseResult>(coLaParameterReader.readUSInt()) == ChallengeResponseResult::SUCCESS)
120  {
121  ChallengeRequest challengeRequest{};
122  for (std::uint32_t byteCounter = 0u; byteCounter < sizeof(challengeRequest.challenge); byteCounter++)
123  {
124  challengeRequest.challenge[byteCounter] = coLaParameterReader.readUSInt();
125  }
126  if (protocolType == SUL2)
127  {
128  for (std::uint32_t byteCounter = 0u; byteCounter < sizeof(challengeRequest.salt); byteCounter++)
129  {
130  challengeRequest.salt[byteCounter] = coLaParameterReader.readUSInt();
131  }
132  }
133 
134  ChallengeResponse challengeResponse = CreateChallengeResponse(userLevel, password, challengeRequest, protocolType);
135 
136  CoLaParameterWriter coLaParameterWriter = CoLaParameterWriter(CoLaCommandType::METHOD_INVOCATION, "SetUserLevel");
137 
138  // add challenge response value to set user level command
139  for (unsigned char b : challengeResponse)
140  {
141  coLaParameterWriter.parameterUSInt(b);
142  }
143 
144  // add user Level to command and build it
145  CoLaCommand getUserLevelCommand = coLaParameterWriter.parameterUSInt(static_cast<uint8_t>(userLevel)).build();
146  CoLaCommand getUserLevelResponse = m_VisionaryControl.sendCommand(getUserLevelCommand);
147  if (getUserLevelResponse.getError() == CoLaError::OK)
148  {
149  coLaParameterReader = CoLaParameterReader(getUserLevelResponse);
150  if (static_cast<ChallengeResponseResult>(coLaParameterReader.readUSInt()) == ChallengeResponseResult::SUCCESS)
151  {
152  isLoginSuccessful = true;
153  }
154  }
155  m_protocolType = protocolType;
156  }
157  return isLoginSuccessful;
158 }
159 
160 bool AuthenticationSecure::login(UserLevel userLevel, const std::string& password)
161 {
162  bool isLoginSuccessful{false};
163 
164  // create command to get the challenge
165  CoLaParameterWriter getChallengeCommandBuilder =
168  {
169  // send command and get the response
170  CoLaCommand getChallengeResponse = m_VisionaryControl.sendCommand(getChallengeCommandBuilder.build());
171  // check whether there occurred an error with the CoLa communication
172  const auto errorCode = getChallengeResponse.getError();
173  if (errorCode == CoLaError::OK)
174  {
175  isLoginSuccessful = loginImpl(userLevel, password, getChallengeResponse, SUL1);
176  }
177  else if (errorCode == CoLaError::BUFFER_UNDERFLOW)
178  {
180  }
181  }
182 
183  if (m_protocolType == SUL2)
184  {
185  CoLaCommand getChallengeCommand =
186  getChallengeCommandBuilder.parameterUSInt(static_cast<uint8_t>(userLevel)).build();
187  CoLaCommand getChallengeResponse = m_VisionaryControl.sendCommand(getChallengeCommand);
188  // check whether there occurred an error with the CoLa communication
189  if (getChallengeResponse.getError() == CoLaError::OK)
190  {
191  // read and check response of GetChallenge command
192  CoLaParameterReader coLaParameterReader = CoLaParameterReader(getChallengeResponse);
193  isLoginSuccessful = loginImpl(userLevel, password, getChallengeResponse, SUL2);
194  }
195  }
196  return isLoginSuccessful;
197 }
198 
200 {
202  CoLaCommand runResponse = m_VisionaryControl.sendCommand(runCommand);
203 
204  if (runResponse.getError() == CoLaError::OK)
205  {
206  return CoLaParameterReader(runResponse).readUSInt() != 0u;
207  }
208  return false;
209 }
210 
211 } // namespace visionary
visionary::CoLaParameterWriter::parameterUSInt
CoLaParameterWriter & parameterUSInt(const uint8_t uSInt)
Add a unsigned short (8-bit, range [0, 255]).
Definition: CoLaParameterWriter.cpp:30
visionary::IAuthentication::UserLevel
UserLevel
Available CoLa user levels.
Definition: IAuthentication.h:15
visionary::IAuthentication::UserLevel::AUTHORIZED_CLIENT
@ AUTHORIZED_CLIENT
visionary::CoLaParameterReader
Class for reading data from a CoLaCommand.
Definition: CoLaParameterReader.h:17
visionary::AuthenticationSecure::logout
bool logout() override
Definition: AuthenticationSecure.cpp:199
visionary::AuthenticationSecure::CreatePasswordHash
PasswordHash CreatePasswordHash(UserLevel userLevel, const std::string &password, const ChallengeRequest &challengeRequest, ProtocolType protocolType)
Definition: AuthenticationSecure.cpp:31
visionary::ProtocolType
ProtocolType
Definition: AuthenticationSecure.h:13
visionary::IAuthentication::UserLevel::SERVICE
@ SERVICE
visionary
Definition: MD5.cpp:44
visionary::CoLaCommand::getError
CoLaError::Enum getError() const
Get error.
Definition: CoLaCommand.cpp:159
AuthenticationSecure.h
visionary::CoLaParameterWriter
Builder for constructing CoLaCommands.
Definition: CoLaParameterWriter.h:19
visionary::CoLaCommand
Definition: CoLaCommand.h:17
visionary::IAuthentication::UserLevel::OPERATOR
@ OPERATOR
visionary::CoLaError::BUFFER_UNDERFLOW
@ BUFFER_UNDERFLOW
More data was expected, the allocated buffer could not be filled.
Definition: CoLaError.h:43
visionary::CoLaError::OK
@ OK
No error.
Definition: CoLaError.h:19
Hash_state
Definition: SHA256.h:33
visionary::ChallengeRequest::salt
std::array< std::uint8_t, 16 > salt
Definition: AuthenticationSecure.h:22
visionary::AuthenticationSecure::m_protocolType
ProtocolType m_protocolType
Definition: AuthenticationSecure.h:39
visionary::SUL2
@ SUL2
Definition: AuthenticationSecure.h:17
CoLaParameterWriter.h
visionary::AuthenticationSecure::m_VisionaryControl
VisionaryControl & m_VisionaryControl
Definition: AuthenticationSecure.h:38
visionary::AuthenticationSecure::~AuthenticationSecure
~AuthenticationSecure() override
visionary::AuthenticationSecure::loginImpl
bool loginImpl(UserLevel userLevel, const std::string &password, const CoLaParameterReader &getChallengeResponse, ProtocolType protocolType)
Definition: AuthenticationSecure.cpp:111
visionary::AuthenticationSecure::AuthenticationSecure
AuthenticationSecure(VisionaryControl &vctrl)
Definition: AuthenticationSecure.cpp:24
visionary::ChallengeResponse
std::array< std::uint8_t, 32 > ChallengeResponse
Definition: AuthenticationSecure.h:26
SUCCESS
SUCCESS
visionary::AuthenticationSecure::login
bool login(UserLevel userLevel, const std::string &password) override
Definition: AuthenticationSecure.cpp:160
sha256_process
int sha256_process(hash_state *md, const ulong8 *in, ulong32 inlen)
Definition: SHA256.cpp:195
ulong32
uint32_t ulong32
Definition: SHA256.h:15
sha256_init
int sha256_init(hash_state *md)
Definition: SHA256.cpp:163
SHA256.h
visionary::AuthenticationSecure::CreateChallengeResponse
ChallengeResponse CreateChallengeResponse(UserLevel userLevel, const std::string &password, const ChallengeRequest &challengeRequest, ProtocolType protocolType)
Definition: AuthenticationSecure.cpp:93
visionary::PasswordHash
std::array< std::uint8_t, 32 > PasswordHash
Definition: AuthenticationSecure.h:25
visionary::IAuthentication::UserLevel::RUN
@ RUN
visionary::CoLaCommandType::METHOD_INVOCATION
@ METHOD_INVOCATION
Definition: CoLaCommandType.h:20
visionary::CoLaParameterReader::readUSInt
uint8_t readUSInt()
Read a unsigned short int (8 bit, range [0, 255]) and advances position by 1 byte....
Definition: CoLaParameterReader.cpp:39
visionary::ChallengeRequest::challenge
std::array< std::uint8_t, 16 > challenge
Definition: AuthenticationSecure.h:21
visionary::SUL1
@ SUL1
Definition: AuthenticationSecure.h:16
visionary::VisionaryControl::sendCommand
CoLaCommand sendCommand(const CoLaCommand &command)
Send a CoLaBCommand to the device and waits for the result.
Definition: VisionaryControl.cpp:201
visionary::ChallengeRequest
Definition: AuthenticationSecure.h:19
visionary::UNKNOWN
@ UNKNOWN
Definition: AuthenticationSecure.h:15
sha256_done
int sha256_done(hash_state *md, unsigned char *out)
Definition: SHA256.cpp:249
visionary::VisionaryControl
Definition: VisionaryControl.h:19
visionary::CoLaParameterWriter::build
const CoLaCommand build()
Definition: CoLaParameterWriter.cpp:181
visionary::IAuthentication::UserLevel::MAINTENANCE
@ MAINTENANCE


sick_visionary_ros
Author(s): SICK AG TechSupport 3D Snapshot
autogenerated on Thu Feb 8 2024 03:36:38