github.com/arduino/arduino-cloud-cli@v0.0.0-20240517070944-e7a449561083/firmware/provision/CryptoProvision/CryptoProvision.ino (about) 1 /* 2 This file is part of ArduinoIoTCloud. 3 4 Copyright 2019 ARDUINO SA (http://www.arduino.cc/) 5 6 This software is released under the GNU General Public License version 3, 7 which covers the main part of arduino-cli. 8 The terms of this license can be found at: 9 https://www.gnu.org/licenses/gpl-3.0.en.html 10 11 You can be released from the requirements of the above licenses by purchasing 12 a commercial license. Buying such a license is mandatory if you want to modify or 13 otherwise use the software for commercial activities involving the Arduino 14 software without disclosing the source code of your own applications. To purchase 15 a commercial license, send an email to license@arduino.cc. 16 */ 17 18 #include <ArduinoIoTCloud.h> 19 #include "ECCX08TLSConfig.h" 20 21 #include "uCRC16Lib.h" 22 const uint8_t SKETCH_INFO[] = {0x55, 0xaa, 0x01, 0x00, 0x01, 0xff, 0xaa, 0x55}; 23 const bool DEBUG = true; 24 25 ArduinoIoTCloudCertClass Cert; 26 CryptoUtil Crypto; 27 28 enum class MESSAGE_TYPE { NONE = 0, COMMAND, DATA, RESPONSE }; 29 enum class COMMAND { 30 GET_SKETCH_INFO = 1, 31 GET_CSR, 32 SET_LOCKED, 33 GET_LOCKED, 34 WRITE_CRYPTO, 35 BEGIN_STORAGE, 36 SET_DEVICE_ID, 37 SET_YEAR, 38 SET_MONTH, 39 SET_DAY, 40 SET_HOUR, 41 SET_VALIDITY, 42 SET_CERT_SERIAL, 43 SET_AUTH_KEY, 44 SET_SIGNATURE, 45 END_STORAGE, 46 RECONSTRUCT_CERT 47 48 }; 49 enum class PROVISIONING_ERROR : uint8_t { 50 NONE = 0, 51 SYNC, 52 LOCK_FAIL, 53 LOCK_SUCCESS, 54 WRITE_CONFIG_FAIL, 55 CRC_FAIL, 56 CSR_GEN_FAIL, 57 CSR_GEN_SUCCESS, 58 SKETCH_UNKNOWN, 59 GENERIC, 60 NO_DATA 61 }; 62 63 enum class RESPONSE { 64 RESPONSE_NONE = 1, 65 RESPONSE_ACK, 66 RESPONSE_NACK, 67 RESPONSE_ERROR 68 }; 69 70 #define MAX_PAYLOAD_LENGTH 130 71 #define CRC_SIZE 2 72 uint8_t 73 payloadBuffer[MAX_PAYLOAD_LENGTH + 74 CRC_SIZE]; // max 64 bytes will be stored before next round 75 uint8_t msgStart[] = {0x55, 0xaa}; 76 uint8_t msgEnd[] = {0xaa, 0x55}; 77 MESSAGE_TYPE msgType = MESSAGE_TYPE::NONE; 78 uint16_t msgLength = 0; 79 uint16_t msgByteIndex = 0; 80 // message is structured as such {START H}{START L}{TYPE}{LENGTH H}{LENGHT L}{PAYLOAD}{PAYLOAD CRC H}{PAYLOAD CRC L}{END} 81 // minimum length is by commands with no payload 2+1+1+1+1+2+2 => 10 82 83 const uint16_t minMessageLength = 10; 84 85 enum class MACHINE_STATE { 86 IDLE = 0, 87 RECEIVING_PAYLOAD, 88 PROCESS_CMD, 89 PROCESS_MSG, 90 PROCESS_MSG_END, 91 SENDING, 92 WRITING, 93 LOCKING 94 }; 95 96 97 MACHINE_STATE machineState = MACHINE_STATE::IDLE; 98 uint8_t deviceIDBytes[72]; 99 String deviceIDstring; 100 String csr; 101 102 String issueYear; 103 String issueMonth; 104 String issueDay; 105 String issueHour; 106 String expireYears; 107 String authorityKeyIdentifier; 108 String signature; 109 110 void setup() { 111 112 Serial.begin(57600); 113 Serial1.begin(115200); 114 uint8_t cryptoInitOK = cryptoInit(); 115 if (!cryptoInitOK) { 116 Serial1.println("FAILED TO DETECT CRYPTO ELEMENT"); 117 while (1); 118 } else { 119 Serial1.println("Crypto-element initialized"); 120 } 121 if (cryptoLock() != PROVISIONING_ERROR::LOCK_SUCCESS) { 122 Serial1.println("FAILED TO LOCK CRYPTO ELEMENT"); 123 while (1); 124 } else { 125 Serial1.println("Crypto-element locked"); 126 } 127 } 128 129 void loop() { 130 if (machineState == MACHINE_STATE::IDLE) { 131 waitForMessage(); 132 133 } 134 if (machineState == MACHINE_STATE::RECEIVING_PAYLOAD) { 135 payloadBuffer[msgByteIndex] = (uint8_t)Serial.read(); 136 Serial1.print(payloadBuffer[msgByteIndex], HEX); 137 Serial1.print(" "); 138 msgByteIndex++; 139 if (msgByteIndex >= msgLength) { 140 changeState(MACHINE_STATE::PROCESS_MSG_END); 141 } 142 } 143 if (machineState == MACHINE_STATE::PROCESS_MSG_END) { 144 checkMessageEnd(); 145 } 146 147 } 148 149 void waitForMessage() { 150 if (Serial.available() >= minMessageLength) { 151 uint8_t msgStartBuffer[2]; 152 uint8_t byteIn; 153 bool msgStartByteOK = false; 154 while (!msgStartByteOK && Serial.available()) { 155 byteIn = (uint8_t)Serial.read(); 156 if (byteIn == msgStart[0]) { 157 msgStartBuffer[0] = byteIn; 158 byteIn = (uint8_t)Serial.read(); 159 if (byteIn == msgStart[1]) { 160 msgStartBuffer[1] = byteIn; 161 msgStartByteOK = true; 162 } 163 } 164 } 165 166 //Serial.readBytes(msgStartBuffer, sizeof(msgStart)); 167 if (memcmp(msgStartBuffer, msgStart, sizeof(msgStart)) == 0) { 168 Serial1.println("message START"); 169 msgType = (MESSAGE_TYPE)Serial.read(); 170 uint8_t lengthH = (uint8_t)Serial.read(); 171 uint8_t lengthL = (uint8_t)Serial.read(); 172 Serial1.print(lengthH); 173 Serial1.print(" - "); 174 Serial1.println(lengthL); 175 msgLength = lengthH << 8 | lengthL; 176 177 Serial1.print("TYPE: "); 178 Serial1.println((int)msgType); 179 Serial1.print("LENGTH: "); 180 Serial1.println((int)msgLength); 181 182 //delay(1000); 183 184 if (msgLength > 0) { 185 changeState(MACHINE_STATE::RECEIVING_PAYLOAD); 186 } else { 187 changeState(MACHINE_STATE::PROCESS_MSG_END); 188 } 189 } 190 } 191 } 192 void checkMessageEnd() { 193 if (Serial.available() >= sizeof(msgEnd)) { 194 uint8_t msgEndBuffer[2]; 195 Serial.readBytes((char*)msgEndBuffer, sizeof(msgEnd)); 196 if (memcmp(msgEndBuffer, msgEnd, sizeof(msgEnd)) == 0) { 197 Serial1.println("message END"); 198 if (processMessage() == PROVISIONING_ERROR::CRC_FAIL) { 199 Serial1.println("ERROR:: CRC FAIL"); 200 sendData(MESSAGE_TYPE::RESPONSE, (char*)RESPONSE::RESPONSE_NACK, 1); 201 } 202 //delay(2000); 203 // Serial.end(); 204 // for(;;) { 205 // delay(500); 206 // }; 207 changeState(MACHINE_STATE::IDLE); 208 } 209 } 210 } 211 212 PROVISIONING_ERROR processMessage() { 213 bool checkSumOK = false; 214 if (msgLength > 0) { 215 // checksum verification 216 // uint8_t csHI = payloadBuffer[msgLength - 2]; 217 // uint8_t csLO = payloadBuffer[msgLength - 1]; 218 // char receivedCS[] = {csHI, csLO}; 219 uint16_t receivedCRC = ((uint16_t)payloadBuffer[msgLength - 2] << 8 | payloadBuffer[msgLength - 1]); 220 uint16_t computedCRC = uCRC16Lib::calculate((char *)payloadBuffer, msgLength - CRC_SIZE); 221 Serial1.print("DATA CRC: "); 222 Serial1.println(receivedCRC, HEX); 223 224 Serial1.print("COMPUTED CRC: "); 225 Serial1.println(computedCRC, HEX); 226 if (receivedCRC != computedCRC) return PROVISIONING_ERROR::CRC_FAIL; 227 Serial1.println("CRC aligned"); 228 checkSumOK = true; 229 } 230 231 if (msgType == MESSAGE_TYPE::COMMAND) { 232 processCommand(); 233 } 234 if (msgType == MESSAGE_TYPE::DATA) { 235 processRawData(checkSumOK); 236 } 237 return PROVISIONING_ERROR::NONE; 238 } 239 240 void processCommand() { 241 Serial1.print("%%%%% "); 242 Serial1.println(">> processing command"); 243 COMMAND cmdCode = (COMMAND)payloadBuffer[0]; 244 245 if (cmdCode == COMMAND::GET_SKETCH_INFO) { 246 Serial1.println("get sketch info"); 247 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 248 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 249 } 250 if (cmdCode == COMMAND::GET_CSR) { 251 // extract payload from [1] to [payloadLength] 252 // this will be the device_id used to generate a valid CSR 253 Serial1.println("get CSR"); 254 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 255 deviceIDBytes[i - 1] = payloadBuffer[i]; 256 } 257 258 // clear device ID string 259 // this will be sent to the host 260 deviceIDstring = ""; 261 Serial1.print("Device ID from host: "); 262 char charBuffer[2]; 263 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 264 Serial1.print(deviceIDBytes[i], HEX); 265 } 266 267 deviceIDstring = String((char*)deviceIDBytes); 268 269 Serial1.println(); 270 Serial1.print("request for CSR with device ID "); 271 Serial1.println(deviceIDstring); 272 273 if (generateCSR() == PROVISIONING_ERROR::CSR_GEN_SUCCESS) { 274 sendData(MESSAGE_TYPE::DATA, csr.c_str(), csr.length()); 275 Serial1.println("CSR GENERATED ON BOARD"); 276 } else { 277 Serial1.println("SOMETHING WENT WRONG"); 278 while (1); 279 } 280 } 281 if (cmdCode == COMMAND::BEGIN_STORAGE) { 282 Serial1.println("begin storage"); 283 if (!Crypto.writeDeviceId(deviceIDstring, CryptoSlot::DeviceId)) { 284 Serial1.println("Error storing device id!"); 285 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 286 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 287 return; 288 } 289 if (!Cert.begin()) { 290 Serial1.println("Error starting Crypto storage!"); 291 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 292 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 293 return; 294 } 295 Cert.setSubjectCommonName(deviceIDstring); 296 Cert.setIssuerCountryName("US"); 297 Cert.setIssuerOrganizationName("Arduino LLC US"); 298 Cert.setIssuerOrganizationalUnitName("IT"); 299 Cert.setIssuerCommonName("Arduino"); 300 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 301 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 302 } 303 if (cmdCode == COMMAND::SET_YEAR) { 304 Serial1.println("set year"); 305 char yearBytes[4]; 306 String yearString; 307 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 308 yearBytes[i - 1] = payloadBuffer[i]; 309 } 310 Serial1.print("Year from host: "); 311 char charBuffer[2]; 312 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 313 Serial1.print(yearBytes[i], HEX); 314 sprintf(charBuffer, "%d", yearBytes[i]); 315 yearString += String(yearBytes[i]);//String(deviceIDBytes[i], 16); 316 } 317 318 Serial1.println(); 319 Serial1.print("set Cert YEAR to "); 320 Serial1.println(yearString); 321 Cert.setIssueYear(yearString.toInt()); 322 323 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 324 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 325 } 326 if (cmdCode == COMMAND::SET_MONTH) { 327 Serial1.println("set month"); 328 char monthBytes[4]; 329 String monthString; 330 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 331 monthBytes[i - 1] = payloadBuffer[i]; 332 } 333 Serial1.print("month from host: "); 334 char charBuffer[2]; 335 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 336 Serial1.print(monthBytes[i], HEX); 337 sprintf(charBuffer, "%d", monthBytes[i]); 338 monthString += String(monthBytes[i]);//String(deviceIDBytes[i], 16); 339 } 340 341 Serial1.println(); 342 Serial1.print("set Cert MONTH to "); 343 Serial1.println(monthString); 344 Cert.setIssueMonth(monthString.toInt()); 345 346 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 347 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 348 } 349 if (cmdCode == COMMAND::SET_DAY) { 350 Serial1.println("set day"); 351 char dayBytes[4]; 352 String dayString; 353 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 354 dayBytes[i - 1] = payloadBuffer[i]; 355 } 356 Serial1.print("day from host: "); 357 char charBuffer[2]; 358 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 359 Serial1.print(dayBytes[i], HEX); 360 sprintf(charBuffer, "%d", dayBytes[i]); 361 dayString += String(dayBytes[i]);//String(deviceIDBytes[i], 16); 362 } 363 364 Serial1.println(); 365 Serial1.print("set Cert day to "); 366 Serial1.println(dayString); 367 Cert.setIssueDay(dayString.toInt()); 368 369 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 370 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 371 } 372 if (cmdCode == COMMAND::SET_HOUR) { 373 Serial1.println("set hour"); 374 char hourBytes[4]; 375 String hourString; 376 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 377 hourBytes[i - 1] = payloadBuffer[i]; 378 } 379 Serial1.print("hour from host: "); 380 char charBuffer[2]; 381 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 382 Serial1.print(hourBytes[i], HEX); 383 sprintf(charBuffer, "%d", hourBytes[i]); 384 hourString += String(hourBytes[i]);//String(deviceIDBytes[i], 16); 385 } 386 387 Serial1.println(); 388 Serial1.print("set Cert hour to "); 389 Serial1.println(hourString); 390 Cert.setIssueHour(hourString.toInt()); 391 392 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 393 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 394 } 395 if (cmdCode == COMMAND::SET_VALIDITY) { 396 Serial1.println("set validity"); 397 char validityBytes[4]; 398 String validityString; 399 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 400 validityBytes[i - 1] = payloadBuffer[i]; 401 } 402 Serial1.print("validity from host: "); 403 char charBuffer[2]; 404 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 405 Serial1.print(validityBytes[i], HEX); 406 sprintf(charBuffer, "%d", validityBytes[i]); 407 validityString += String(validityBytes[i]);//String(deviceIDBytes[i], 16); 408 } 409 410 Serial1.println(); 411 Serial1.print("set Cert validity to "); 412 Serial1.println(validityString); 413 Cert.setExpireYears(validityString.toInt()); 414 415 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 416 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 417 } 418 if (cmdCode == COMMAND::SET_CERT_SERIAL) { 419 // extract payload from [1] to [payloadLength] 420 // this will be the certificate serial number included in the device certificate 421 Serial1.println("set CERT Serial"); 422 byte certSerialBytes[msgLength - CRC_SIZE - 1]; 423 424 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 425 certSerialBytes[i - 1] = payloadBuffer[i]; 426 } 427 428 Serial1.print("Serial Number from host: "); 429 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 430 Serial1.print(certSerialBytes[i], HEX); 431 } 432 Serial1.println(); 433 434 if(!Cert.setSerialNumber(certSerialBytes, sizeof(certSerialBytes))) { 435 Serial1.println("set CERT Error"); 436 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 437 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 438 return; 439 } 440 441 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 442 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 443 } 444 if (cmdCode == COMMAND::SET_AUTH_KEY) { 445 // extract payload from [1] to [payloadLength] 446 // this will be the authority key id included in the device certificate 447 Serial1.println("set Auth Key Id"); 448 byte authKeyBytes[msgLength - CRC_SIZE - 1]; 449 450 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 451 authKeyBytes[i - 1] = payloadBuffer[i]; 452 } 453 454 Serial1.print("Authority Key Id from host: "); 455 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 456 Serial1.print(authKeyBytes[i], HEX); 457 } 458 Serial1.println(); 459 460 if(!Cert.setAuthorityKeyId(authKeyBytes, sizeof(authKeyBytes))) { 461 Serial1.println("set AuthorityKeyId Error"); 462 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 463 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 464 return; 465 } 466 467 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 468 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 469 } 470 if (cmdCode == COMMAND::SET_SIGNATURE) { 471 // extract payload from [1] to [payloadLength] 472 // this will be the signature included in the device certificate 473 Serial1.println("set Signature "); 474 byte signatureBytes[msgLength - CRC_SIZE - 1]; 475 476 for (uint8_t i = 1; i < msgLength - CRC_SIZE; i++) { 477 signatureBytes[i - 1] = payloadBuffer[i]; 478 } 479 480 Serial1.print("Signature from host: "); 481 for (uint8_t i = 0; i < msgLength - CRC_SIZE - 1; i++) { 482 Serial1.print(signatureBytes[i], HEX); 483 } 484 Serial1.println(); 485 486 if(!Cert.setSignature(signatureBytes, sizeof(signatureBytes))) { 487 Serial1.println("set signature Error"); 488 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 489 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 490 return; 491 } 492 493 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 494 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 495 } 496 if (cmdCode == COMMAND::END_STORAGE) { 497 Serial1.println("end storage"); 498 if (!Crypto.buildCert(Cert, CryptoSlot::Key)) { 499 Serial1.println("Error creating cert!"); 500 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 501 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 502 return; 503 } 504 505 if (!Crypto.writeCert(Cert, CryptoSlot::CompressedCertificate)) { 506 Serial1.println("Error storing Crypto cert!"); 507 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 508 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 509 return; 510 } 511 512 Serial1.println("Certificate PEM file"); 513 Serial1.println(Cert.getCertPEM()); 514 515 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 516 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 517 } 518 if (cmdCode == COMMAND::RECONSTRUCT_CERT) { 519 Serial1.println("reconstruct certificate"); 520 if (!Crypto.readCert(Cert, CryptoSlot::CompressedCertificate)) { 521 Serial1.println("Error reconstructing Crypto cert!"); 522 char response[] = {char(RESPONSE::RESPONSE_ERROR)}; 523 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 524 return; 525 } 526 527 Serial1.println("Compressed cert = "); 528 529 const byte *certData = Cert.bytes(); 530 int certLength = Cert.length(); 531 532 for (int i = 0; i < certLength; i++) { 533 byte b = certData[i]; 534 535 if (b < 16) { 536 Serial1.print('0'); 537 } 538 Serial1.print(b, HEX); 539 } 540 Serial1.println(); 541 char response[] = {char(RESPONSE::RESPONSE_ACK)}; 542 sendData(MESSAGE_TYPE::RESPONSE, response, 1); 543 } 544 545 } 546 547 void processRawData(bool checkSumOK) { 548 Serial1.println(">> processing raw data"); 549 550 if (checkSumOK) { 551 uint8_t resp[] = {0x55, 0xaa, (uint8_t)MESSAGE_TYPE::RESPONSE, 0x01, (uint8_t)RESPONSE::RESPONSE_ACK, 0xaa, 0x55}; 552 for (uint8_t i = 0; i < sizeof(resp); i++) { 553 Serial1.print(resp[i]); 554 Serial1.print(" "); 555 } 556 Serial.write(resp, sizeof(resp)); 557 } else { 558 uint8_t resp[] = {0x55, 0xaa, (uint8_t)MESSAGE_TYPE::RESPONSE, 0x01, (uint8_t)RESPONSE::RESPONSE_NACK, 0xaa, 0x55}; 559 for (uint8_t i = 0; i < sizeof(resp); i++) { 560 Serial1.print(resp[i]); 561 Serial1.print(" "); 562 } 563 Serial.write(resp, sizeof(resp)); 564 } 565 } 566 567 void sendData(MESSAGE_TYPE _msgType, const char* _msgPayload, uint16_t _payloadSize) { 568 Serial1.print("payload size: "); 569 Serial1.print(_payloadSize); 570 Serial1.print(" ["); 571 Serial1.print(_payloadSize, HEX); 572 Serial1.println("]"); 573 Serial1.println(_msgPayload); 574 575 Serial.write(msgStart, sizeof(msgStart)); 576 Serial.write((uint8_t)_msgType); 577 Serial.write((_payloadSize + CRC_SIZE) >> 8) ; 578 Serial.write((_payloadSize + CRC_SIZE) & 0xff); 579 Serial.write(_msgPayload, _payloadSize); 580 uint16_t payloadCRC = uCRC16Lib::calculate((char *)_msgPayload, _payloadSize); 581 Serial1.print("payload CRC out: "); 582 Serial1.println(payloadCRC, HEX); 583 Serial.write((uint8_t)(payloadCRC >> 8)); 584 Serial.write((uint8_t)(payloadCRC & 0xff)); 585 Serial.write(msgEnd, sizeof(msgEnd)); 586 587 } 588 589 void sendResponse() { 590 591 } 592 void changeState(MACHINE_STATE _newState) { 593 Serial1.print("changing state to "); 594 Serial1.println((uint8_t)_newState); 595 if (_newState == machineState) 596 return; 597 if (_newState == MACHINE_STATE::RECEIVING_PAYLOAD) { 598 msgByteIndex = 0; 599 } 600 if (_newState == MACHINE_STATE::IDLE) { 601 602 } 603 machineState = _newState; 604 } 605 606 uint8_t cryptoInit() { 607 unsigned long ecctimeout = 1000; 608 unsigned long beginOfTime = millis(); 609 bool eccOK = 0; 610 while (!(eccOK = Crypto.begin()) || (millis() - beginOfTime < ecctimeout)) { 611 } 612 return eccOK; 613 } 614 615 PROVISIONING_ERROR cryptoLock() { 616 if (!Crypto.locked()) { 617 618 if (!Crypto.writeConfiguration(DEFAULT_ECCX08_TLS_CONFIG)) { 619 return PROVISIONING_ERROR::WRITE_CONFIG_FAIL; 620 } 621 622 if (!Crypto.lock()) { 623 return PROVISIONING_ERROR::LOCK_FAIL; 624 } 625 return PROVISIONING_ERROR::LOCK_SUCCESS; 626 } 627 return PROVISIONING_ERROR::LOCK_SUCCESS; 628 } 629 630 PROVISIONING_ERROR generateCSR() { 631 if (!Crypto.locked()) { 632 Serial1.println("Chip is not locked"); 633 return PROVISIONING_ERROR::LOCK_FAIL; 634 } 635 Serial1.println("CSR generation in progress"); 636 637 if (!Cert.begin()) { 638 Serial1.println("Error initializing CSR data!"); 639 return PROVISIONING_ERROR::CSR_GEN_FAIL; 640 } 641 642 Cert.setSubjectCommonName(deviceIDstring); 643 644 if (!Crypto.buildCSR(Cert, CryptoSlot::Key, true)) { 645 Serial1.println("Error generating CSR!"); 646 return PROVISIONING_ERROR::CSR_GEN_FAIL; 647 } 648 649 csr = Cert.getCSRPEM(); 650 if (!csr) { 651 Serial1.println("Error reading CSR PEM data!"); 652 return PROVISIONING_ERROR::CSR_GEN_FAIL; 653 } 654 Serial1.println(csr.length()); 655 Serial1.println(csr); 656 657 return PROVISIONING_ERROR::CSR_GEN_SUCCESS; 658 }