diff --git a/examples/utility/SelfProvisioning/ECCX08Cert.cpp b/examples/utility/SelfProvisioning/ECCX08Cert.cpp deleted file mode 100644 index db037d4e0..000000000 --- a/examples/utility/SelfProvisioning/ECCX08Cert.cpp +++ /dev/null @@ -1,939 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include -#include -#include "ECCX08Cert.h" -#include "tls/utility/SHA256.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_NULL 0x05 -#define ASN1_OBJECT_IDENTIFIER 0x06 -#define ASN1_PRINTABLE_STRING 0x13 -#define ASN1_SEQUENCE 0x30 -#define ASN1_SET 0x31 - -struct __attribute__((__packed__)) CompressedCert { - byte signature[64]; - byte dates[3]; - byte unused[5]; -}; - -#define SERIAL_NUMBER_LENGTH 16 -#define AUTHORITY_KEY_IDENTIFIER_LENGTH 20 - -struct __attribute__((__packed__)) SerialNumberAndAuthorityKeyIdentifier { - byte serialNumber[SERIAL_NUMBER_LENGTH]; - byte authorityKeyIdentifier[AUTHORITY_KEY_IDENTIFIER_LENGTH]; -}; - -/****************************************************************************** - * LOCAL MODULE FUNCTIONS - ******************************************************************************/ - -static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { - static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - - int b; - String out; - - int reserveLength = 4 * ((length + 2) / 3) + ((length / 3 * 4) / 76) + strlen(prefix) + strlen(suffix); - out.reserve(reserveLength); - - if (prefix) { - out += prefix; - } - - for (unsigned int i = 0; i < length; i += 3) { - if (i > 0 && (i / 3 * 4) % 76 == 0) { - out += '\n'; - } - - b = (in[i] & 0xFC) >> 2; - out += CODES[b]; - - b = (in[i] & 0x03) << 4; - if (i + 1 < length) { - b |= (in[i + 1] & 0xF0) >> 4; - out += CODES[b]; - b = (in[i + 1] & 0x0F) << 2; - if (i + 2 < length) { - b |= (in[i + 2] & 0xC0) >> 6; - out += CODES[b]; - b = in[i + 2] & 0x3F; - out += CODES[b]; - } else { - out += CODES[b]; - out += '='; - } - } else { - out += CODES[b]; - out += "=="; - } - } - - if (suffix) { - out += suffix; - } - - return out; -} - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -ECCX08CertClass::ECCX08CertClass() : - _keySlot(-1), - _compressedCertSlot(-1), - _serialNumberAndAuthorityKeyIdentifierSlot(-1), - _bytes(NULL), - _length(0) { -} - -ECCX08CertClass::~ECCX08CertClass() { - if (_bytes) { - free(_bytes); - _bytes = NULL; - } -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -int ECCX08CertClass::beginCSR(int keySlot, bool newPrivateKey) { - if (keySlot < 0 || keySlot > 8) { - return 0; - } - - _keySlot = keySlot; - - if (newPrivateKey) { - if (!ECCX08.generatePrivateKey(_keySlot, _temp)) { - return 0; - } - } else { - if (!ECCX08.generatePublicKey(_keySlot, _temp)) { - return 0; - } - } - - return 1; -} - -String ECCX08CertClass::endCSR() { - int versionLen = versionLength(); - int subjectLen = issuerOrSubjectLength(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName); - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - int publicKeyLen = publicKeyLength(); - - int csrInfoLen = versionLen + subjectHeaderLen + subjectLen + publicKeyLen + 2; - int csrInfoHeaderLen = sequenceHeaderLength(csrInfoLen); - - byte csrInfo[csrInfoHeaderLen + csrInfoLen]; - byte* out = csrInfo; - - appendSequenceHeader(csrInfoLen, out); - out += csrInfoHeaderLen; - - // version - appendVersion(0x00, out); - out += versionLen; - - // subject - appendSequenceHeader(subjectLen, out); - out += subjectHeaderLen; - appendIssuerOrSubject(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName, out); - out += subjectLen; - - // public key - appendPublicKey(_temp, out); - out += publicKeyLen; - - // terminator - *out++ = 0xa0; - *out++ = 0x00; - - SHA256 sha256; - byte csrInfoSha256[64]; - byte signature[64]; - - sha256.begin(); - sha256.update(csrInfo, csrInfoHeaderLen + csrInfoLen); - sha256.finalize(csrInfoSha256); - - if (!ECCX08.ecSign(_keySlot, csrInfoSha256, signature)) { - return ""; - } - - int signatureLen = signatureLength(signature); - int csrLen = csrInfoHeaderLen + csrInfoLen + signatureLen; - int csrHeaderLen = sequenceHeaderLength(csrLen); - - byte csr[csrLen + csrHeaderLen]; - out = csr; - - appendSequenceHeader(csrLen, out); - out += csrHeaderLen; - - // info - memcpy(out, csrInfo, csrInfoHeaderLen + csrInfoLen); - out += (csrInfoHeaderLen + csrInfoLen); - - // signature - appendSignature(signature, out); - out += signatureLen; - - return base64Encode(csr, csrLen + csrHeaderLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); -} - -int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { - if (compressedCertSlot < 8 || compressedCertSlot > 15) { - return 0; - } - - if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { - return 0; - } - - _compressedCertSlot = compressedCertSlot; - _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; - - memset(_temp, 0x00, sizeof(_temp)); - - return 1; -} - -void ECCX08CertClass::setSignature(byte signature[]) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - memcpy(compressedCert->signature, signature, 64); -} - -void ECCX08CertClass::setIssueYear(int issueYear) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[0] &= 0x07; - compressedCert->dates[0] |= (issueYear - 2000) << 3; -} - -void ECCX08CertClass::setIssueMonth(int issueMonth) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[0] &= 0xf8; - compressedCert->dates[0] |= issueMonth >> 1; - - compressedCert->dates[1] &= 0x7f; - compressedCert->dates[1] |= issueMonth << 7; -} - -void ECCX08CertClass::setIssueDay(int issueDay) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[1] &= 0x83; - compressedCert->dates[1] |= issueDay << 2; -} - -void ECCX08CertClass::setIssueHour(int issueHour) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[2] &= 0x1f; - compressedCert->dates[2] |= issueHour << 5; - - compressedCert->dates[1] &= 0xfc; - compressedCert->dates[1] |= issueHour >> 3; -} - -void ECCX08CertClass::setExpireYears(int expireYears) { - struct CompressedCert* compressedCert = (struct CompressedCert*)_temp; - - compressedCert->dates[2] &= 0xe0; - compressedCert->dates[2] |= expireYears; -} - -void ECCX08CertClass::setSerialNumber(const byte serialNumber[]) { - memcpy(&_temp[72], serialNumber, SERIAL_NUMBER_LENGTH); -} - -void ECCX08CertClass::setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]) { - memcpy(&_temp[88], authorityKeyIdentifier, AUTHORITY_KEY_IDENTIFIER_LENGTH); -} - -int ECCX08CertClass::endStorage() { - if (!ECCX08.writeSlot(_compressedCertSlot, &_temp[0], 72)) { - return 0; - } - - if (!ECCX08.writeSlot(_serialNumberAndAuthorityKeyIdentifierSlot, &_temp[72], SERIAL_NUMBER_LENGTH + AUTHORITY_KEY_IDENTIFIER_LENGTH)) { - return 0; - } - - return 1; -} - -int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { - if (keySlot < 0 || keySlot > 8) { - return 0; - } - - if (compressedCertSlot < 8 || compressedCertSlot > 15) { - return 0; - } - - if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { - return 0; - } - - _keySlot = keySlot; - _compressedCertSlot = compressedCertSlot; - _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; - - return 1; -} - -int ECCX08CertClass::endReconstruction() { - byte publicKey[64]; - struct CompressedCert compressedCert; - struct SerialNumberAndAuthorityKeyIdentifier serialNumberAndAuthorityKeyIdentifier; - - if (!ECCX08.generatePublicKey(_keySlot, publicKey)) { - return 0; - } - - if (!ECCX08.readSlot(_compressedCertSlot, (byte*)&compressedCert, sizeof(compressedCert))) { - return 0; - } - - if (!ECCX08.readSlot(_serialNumberAndAuthorityKeyIdentifierSlot, (byte*)&serialNumberAndAuthorityKeyIdentifier, sizeof(serialNumberAndAuthorityKeyIdentifier))) { - return 0; - } - - // dates - int year = (compressedCert.dates[0] >> 3) + 2000; - int month = ((compressedCert.dates[0] & 0x07) << 1) | (compressedCert.dates[1] >> 7); - int day = (compressedCert.dates[1] & 0x7c) >> 2; - int hour = ((compressedCert.dates[1] & 0x03) << 3) | (compressedCert.dates[2] >> 5); - int expireYears = (compressedCert.dates[2] & 0x1f); - - int datesSize = 30; - - if (year > 2049) { - // two more bytes for GeneralizedTime - datesSize += 2; - } - - if ((year + expireYears) > 2049) { - // two more bytes for GeneralizedTime - datesSize += 2; - } - - int serialNumberLen = serialNumberLength(serialNumberAndAuthorityKeyIdentifier.serialNumber); - - int issuerLen = issuerOrSubjectLength(_issuerCountryName, - _issuerStateProvinceName, - _issuerLocalityName, - _issuerOrganizationName, - _issuerOrganizationalUnitName, - _issuerCommonName); - - int issuerHeaderLen = sequenceHeaderLength(issuerLen); - - int subjectLen = issuerOrSubjectLength(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName); - - int subjectHeaderLen = sequenceHeaderLength(subjectLen); - - int publicKeyLen = publicKeyLength(); - - int authorityKeyIdentifierLen = authorityKeyIdentifierLength(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier); - - int signatureLen = signatureLength(compressedCert.signature); - - int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + (datesSize + 2) + - subjectHeaderLen + subjectLen + publicKeyLen; - - if (authorityKeyIdentifierLen) { - certInfoLen += authorityKeyIdentifierLen; - } else { - certInfoLen += 4; - } - - int certInfoHeaderLen = sequenceHeaderLength(certInfoLen); - - int certDataLen = certInfoLen + certInfoHeaderLen + signatureLen; - int certDataHeaderLen = sequenceHeaderLength(certDataLen); - - _length = certDataLen + certDataHeaderLen; - _bytes = (byte*)realloc(_bytes, _length); - - if (!_bytes) { - _length = 0; - return 0; - } - - byte* out = _bytes; - - appendSequenceHeader(certDataLen, out); - out += certDataHeaderLen; - - appendSequenceHeader(certInfoLen, out); - out += certInfoHeaderLen; - - // version - *out++ = 0xA0; - *out++ = 0x03; - *out++ = 0x02; - *out++ = 0x01; - *out++ = 0x02; - - // serial number - appendSerialNumber(serialNumberAndAuthorityKeyIdentifier.serialNumber, out); - out += serialNumberLen; - - // ecdsaWithSHA256 - out += appendEcdsaWithSHA256(out); - - // issuer - appendSequenceHeader(issuerLen, out); - out += issuerHeaderLen; - appendIssuerOrSubject(_issuerCountryName, - _issuerStateProvinceName, - _issuerLocalityName, - _issuerOrganizationName, - _issuerOrganizationalUnitName, - _issuerCommonName, out); - out += issuerLen; - - *out++ = ASN1_SEQUENCE; - *out++ = datesSize; - out += appendDate(year, month, day, hour, 0, 0, out); - out += appendDate(year + expireYears, month, day, hour, 0, 0, out); - - // subject - appendSequenceHeader(subjectLen, out); - out += subjectHeaderLen; - appendIssuerOrSubject(_subjectCountryName, - _subjectStateProvinceName, - _subjectLocalityName, - _subjectOrganizationName, - _subjectOrganizationalUnitName, - _subjectCommonName, out); - out += subjectLen; - - // public key - appendPublicKey(publicKey, out); - out += publicKeyLen; - - if (authorityKeyIdentifierLen) { - appendAuthorityKeyIdentifier(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier, out); - out += authorityKeyIdentifierLen; - } else { - // null sequence - *out++ = 0xA3; - *out++ = 0x02; - *out++ = 0x30; - *out++ = 0x00; - } - - // signature - appendSignature(compressedCert.signature, out); - out += signatureLen; - - return 1; -} - -byte* ECCX08CertClass::bytes() { - return _bytes; -} - -int ECCX08CertClass::length() { - return _length; -} - -void ECCX08CertClass::setIssuerCountryName(const String& countryName) { - _issuerCountryName = countryName; -} - -void ECCX08CertClass::setIssuerStateProvinceName(const String& stateProvinceName) { - _issuerStateProvinceName = stateProvinceName; -} - -void ECCX08CertClass::setIssuerLocalityName(const String& localityName) { - _issuerLocalityName = localityName; -} - -void ECCX08CertClass::setIssuerOrganizationName(const String& organizationName) { - _issuerOrganizationName = organizationName; -} - -void ECCX08CertClass::setIssuerOrganizationalUnitName(const String& organizationalUnitName) { - _issuerOrganizationalUnitName = organizationalUnitName; -} - -void ECCX08CertClass::setIssuerCommonName(const String& commonName) { - _issuerCommonName = commonName; -} - -void ECCX08CertClass::setSubjectCountryName(const String& countryName) { - _subjectCountryName = countryName; -} - -void ECCX08CertClass::setSubjectStateProvinceName(const String& stateProvinceName) { - _subjectStateProvinceName = stateProvinceName; -} - -void ECCX08CertClass::setSubjectLocalityName(const String& localityName) { - _subjectLocalityName = localityName; -} - -void ECCX08CertClass::setSubjectOrganizationName(const String& organizationName) { - _subjectOrganizationName = organizationName; -} - -void ECCX08CertClass::setSubjectOrganizationalUnitName(const String& organizationalUnitName) { - _subjectOrganizationName = organizationalUnitName; -} - -void ECCX08CertClass::setSubjectCommonName(const String& commonName) { - _subjectCommonName = commonName; -} - -int ECCX08CertClass::versionLength() { - return 3; -} - -int ECCX08CertClass::issuerOrSubjectLength(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName) { - int length = 0; - int countryNameLength = countryName.length(); - int stateProvinceNameLength = stateProvinceName.length(); - int localityNameLength = localityName.length(); - int organizationNameLength = organizationName.length(); - int organizationalUnitNameLength = organizationalUnitName.length(); - int commonNameLength = commonName.length(); - - if (countryNameLength) { - length += (11 + countryNameLength); - } - - if (stateProvinceNameLength) { - length += (11 + stateProvinceNameLength); - } - - if (localityNameLength) { - length += (11 + localityNameLength); - } - - if (organizationNameLength) { - length += (11 + organizationNameLength); - } - - if (organizationalUnitNameLength) { - length += (11 + organizationalUnitNameLength); - } - - if (commonNameLength) { - length += (11 + commonNameLength); - } - - return length; -} - -int ECCX08CertClass::publicKeyLength() { - return (2 + 2 + 9 + 10 + 4 + 64); -} - -int ECCX08CertClass::authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]) { - bool set = false; - - // check if the authority key identifier is non-zero - for (int i = 0; i < AUTHORITY_KEY_IDENTIFIER_LENGTH; i++) { - if (authorityKeyIdentifier[i] != 0) { - set = true; - break; - } - } - - return (set ? 37 : 0); -} - -int ECCX08CertClass::signatureLength(const byte signature[]) { - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0x00 && rLength) { - r++; - rLength--; - } - - if (*r & 0x80) { - rLength++; - } - - while (*s == 0x00 && sLength) { - s++; - sLength--; - } - - if (*s & 0x80) { - sLength++; - } - - return (21 + rLength + sLength); -} - -int ECCX08CertClass::serialNumberLength(const byte serialNumber[]) { - int length = SERIAL_NUMBER_LENGTH; - - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - return (2 + length); -} - -int ECCX08CertClass::sequenceHeaderLength(int length) { - if (length > 255) { - return 4; - } else if (length > 127) { - return 3; - } else { - return 2; - } -} - -void ECCX08CertClass::appendVersion(int version, byte out[]) { - out[0] = ASN1_INTEGER; - out[1] = 0x01; - out[2] = version; -} - -void ECCX08CertClass::appendIssuerOrSubject(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName, - byte out[]) { - if (countryName.length() > 0) { - out += appendName(countryName, 0x06, out); - } - - if (stateProvinceName.length() > 0) { - out += appendName(stateProvinceName, 0x08, out); - } - - if (localityName.length() > 0) { - out += appendName(localityName, 0x07, out); - } - - if (organizationName.length() > 0) { - out += appendName(organizationName, 0x0a, out); - } - - if (organizationalUnitName.length() > 0) { - out += appendName(organizationalUnitName, 0x0b, out); - } - - if (commonName.length() > 0) { - out += appendName(commonName, 0x03, out); - } -} - -void ECCX08CertClass::appendPublicKey(const byte publicKey[], byte out[]) { - int subjectPublicKeyDataLength = 2 + 9 + 10 + 4 + 64; - - // subject public key - *out++ = ASN1_SEQUENCE; - *out++ = (subjectPublicKeyDataLength) & 0xff; - - *out++ = ASN1_SEQUENCE; - *out++ = 0x13; - - // EC public key - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x07; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x02; - *out++ = 0x01; - - // PRIME 256 v1 - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x03; - *out++ = 0x01; - *out++ = 0x07; - - *out++ = 0x03; - *out++ = 0x42; - *out++ = 0x00; - *out++ = 0x04; - - memcpy(out, publicKey, 64); -} - -void ECCX08CertClass::appendAuthorityKeyIdentifier(const byte authorityKeyIdentifier[], byte out[]) { - // [3] - *out++ = 0xa3; - *out++ = 0x23; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x21; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x1f; - - // 2.5.29.35 authorityKeyIdentifier(X.509 extension) - *out++ = 0x06; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x1d; - *out++ = 0x23; - - // octet string - *out++ = 0x04; - *out++ = 0x18; - - // sequence - *out++ = ASN1_SEQUENCE; - *out++ = 0x16; - - *out++ = 0x80; - *out++ = 0x14; - - memcpy(out, authorityKeyIdentifier, 20); -} - -void ECCX08CertClass::appendSignature(const byte signature[], byte out[]) { - // signature algorithm - *out++ = ASN1_SEQUENCE; - *out++ = 0x0a; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - - // ECDSA with SHA256 - *out++ = 0x2a; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xce; - *out++ = 0x3d; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - const byte* r = &signature[0]; - const byte* s = &signature[32]; - - int rLength = 32; - int sLength = 32; - - while (*r == 0 && rLength) { - r++; - rLength--; - } - - while (*s == 0 && sLength) { - s++; - sLength--; - } - - if (*r & 0x80) { - rLength++; - } - - if (*s & 0x80) { - sLength++; - } - - *out++ = ASN1_BIT_STRING; - *out++ = (rLength + sLength + 7); - *out++ = 0; - - *out++ = ASN1_SEQUENCE; - *out++ = (rLength + sLength + 4); - - *out++ = ASN1_INTEGER; - *out++ = rLength; - if ((*r & 0x80) && rLength) { - *out++ = 0; - rLength--; - } - memcpy(out, r, rLength); - out += rLength; - - *out++ = ASN1_INTEGER; - *out++ = sLength; - if ((*s & 0x80) && sLength) { - *out++ = 0; - sLength--; - } - memcpy(out, s, sLength); - out += rLength; -} - -void ECCX08CertClass::appendSerialNumber(const byte serialNumber[], byte out[]) { - int length = SERIAL_NUMBER_LENGTH; - - while (*serialNumber == 0 && length) { - serialNumber++; - length--; - } - - if (*serialNumber & 0x80) { - length++; - } - - *out++ = ASN1_INTEGER; - *out++ = length; - - if (*serialNumber & 0x80) { - *out++ = 0x00; - length--; - } - - memcpy(out, serialNumber, length); -} - -int ECCX08CertClass::appendName(const String& name, int type, byte out[]) { - int nameLength = name.length(); - - *out++ = ASN1_SET; - *out++ = nameLength + 9; - - *out++ = ASN1_SEQUENCE; - *out++ = nameLength + 7; - - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x03; - *out++ = 0x55; - *out++ = 0x04; - *out++ = type; - - *out++ = ASN1_PRINTABLE_STRING; - *out++ = nameLength; - memcpy(out, name.c_str(), nameLength); - - return (nameLength + 11); -} - -void ECCX08CertClass::appendSequenceHeader(int length, byte out[]) { - *out++ = ASN1_SEQUENCE; - if (length > 255) { - *out++ = 0x82; - *out++ = (length >> 8) & 0xff; - } else if (length > 127) { - *out++ = 0x81; - } - *out++ = (length) & 0xff; -} - -int ECCX08CertClass::appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]) { - bool useGeneralizedTime = (year > 2049); - - if (useGeneralizedTime) { - *out++ = 0x18; - *out++ = 0x0f; - *out++ = '0' + (year / 1000); - *out++ = '0' + ((year % 1000) / 100); - *out++ = '0' + ((year % 100) / 10); - *out++ = '0' + (year % 10); - } else { - year -= 2000; - - *out++ = 0x17; - *out++ = 0x0d; - *out++ = '0' + (year / 10); - *out++ = '0' + (year % 10); - } - *out++ = '0' + (month / 10); - *out++ = '0' + (month % 10); - *out++ = '0' + (day / 10); - *out++ = '0' + (day % 10); - *out++ = '0' + (hour / 10); - *out++ = '0' + (hour % 10); - *out++ = '0' + (minute / 10); - *out++ = '0' + (minute % 10); - *out++ = '0' + (second / 10); - *out++ = '0' + (second % 10); - *out++ = 0x5a; // UTC - - return (useGeneralizedTime ? 17 : 15); -} - -int ECCX08CertClass::appendEcdsaWithSHA256(byte out[]) { - *out++ = ASN1_SEQUENCE; - *out++ = 0x0A; - *out++ = ASN1_OBJECT_IDENTIFIER; - *out++ = 0x08; - *out++ = 0x2A; - *out++ = 0x86; - *out++ = 0x48; - *out++ = 0xCE; - *out++ = 0x3D; - *out++ = 0x04; - *out++ = 0x03; - *out++ = 0x02; - - return 12; -} diff --git a/examples/utility/SelfProvisioning/ECCX08Cert.h b/examples/utility/SelfProvisioning/ECCX08Cert.h deleted file mode 100644 index d40d4cd02..000000000 --- a/examples/utility/SelfProvisioning/ECCX08Cert.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -#ifndef _ECCX08_CERT_H_ -#define _ECCX08_CERT_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class ECCX08CertClass { - - public: - ECCX08CertClass(); - virtual ~ECCX08CertClass(); - - int beginCSR(int keySlot, bool newPrivateKey = true); - String endCSR(); - - int beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); - void setSignature(byte signature[]); - void setIssueYear(int issueYear); - void setIssueMonth(int issueMonth); - void setIssueDay(int issueDay); - void setIssueHour(int issueHour); - void setExpireYears(int expireYears); - void setSerialNumber(const byte serialNumber[]); - void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); - int endStorage(); - - int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); - int endReconstruction(); - - byte* bytes(); - int length(); - - void setIssuerCountryName(const String& countryName); - void setIssuerStateProvinceName(const String& stateProvinceName); - void setIssuerLocalityName(const String& localityName); - void setIssuerOrganizationName(const String& organizationName); - void setIssuerOrganizationalUnitName(const String& organizationalUnitName); - void setIssuerCommonName(const String& commonName); - - void setSubjectCountryName(const String& countryName); - void setSubjectStateProvinceName(const String& stateProvinceName); - void setSubjectLocalityName(const String& localityName); - void setSubjectOrganizationName(const String& organizationName); - void setSubjectOrganizationalUnitName(const String& organizationalUnitName); - void setSubjectCommonName(const String& commonName); - - private: - int versionLength(); - - int issuerOrSubjectLength(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName); - - int publicKeyLength(); - - int authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]); - - int signatureLength(const byte signature[]); - - int serialNumberLength(const byte serialNumber[]); - - int sequenceHeaderLength(int length); - - void appendVersion(int version, byte out[]); - - void appendIssuerOrSubject(const String& countryName, - const String& stateProvinceName, - const String& localityName, - const String& organizationName, - const String& organizationalUnitName, - const String& commonName, - byte out[]); - - void appendPublicKey(const byte publicKey[], byte out[]); - - void appendAuthorityKeyIdentifier(const byte authorityKeyIdentifier[], byte out[]); - - void appendSignature(const byte signature[], byte out[]); - - void appendSerialNumber(const byte serialNumber[], byte out[]); - - int appendName(const String& name, int type, byte out[]); - - void appendSequenceHeader(int length, byte out[]); - - int appendDate(int year, int month, int day, int hour, int minute, int second, byte out[]); - - int appendEcdsaWithSHA256(byte out[]); - - private: - int _keySlot; - int _compressedCertSlot; - int _serialNumberAndAuthorityKeyIdentifierSlot; - - String _issuerCountryName; - String _issuerStateProvinceName; - String _issuerLocalityName; - String _issuerOrganizationName; - String _issuerOrganizationalUnitName; - String _issuerCommonName; - - String _subjectCountryName; - String _subjectStateProvinceName; - String _subjectLocalityName; - String _subjectOrganizationName; - String _subjectOrganizationalUnitName; - String _subjectCommonName; - - byte _temp[108]; - byte* _bytes; - int _length; -}; - -#endif /* _ECCX08_CERT_H_ */ diff --git a/examples/utility/SelfProvisioning/ECCX08TLSConfig.h b/examples/utility/SelfProvisioning/ECCX08TLSConfig.h deleted file mode 100644 index 9126b3666..000000000 --- a/examples/utility/SelfProvisioning/ECCX08TLSConfig.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2019 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -#ifndef _ECCX08_TLS_CONFIG_H_ -#define _ECCX08_TLS_CONFIG_H_ - -const byte DEFAULT_ECCX08_TLS_CONFIG[128] = { - // Read only - start - // SN[0:3] - 0x01, 0x23, 0x00, 0x00, - // RevNum - 0x00, 0x00, 0x50, 0x00, - // SN[4:8] - 0x00, 0x00, 0x00, 0x00, 0x00, - // Reserved - 0xC0, - // I2C_Enable - 0x71, - // Reserved - 0x00, - // Read only - end - // I2C_Address - 0xC0, - // Reserved - 0x00, - // OTPmode - 0x55, - // ChipMode - 0x00, - // SlotConfig - 0x83, 0x20, // External Signatures | Internal Signatures | IsSecret | Write Configure Never, Default: 0x83, 0x20, - 0x87, 0x20, // External Signatures | Internal Signatures | ECDH | IsSecret | Write Configure Never, Default: 0x87, 0x20, - 0x87, 0x20, // External Signatures | Internal Signatures | ECDH | IsSecret | Write Configure Never, Default: 0x8F, 0x20, - 0x87, 0x2F, // External Signatures | Internal Signatures | ECDH | IsSecret | WriteKey all slots | Write Configure Never, Default: 0xC4, 0x8F, - 0x87, 0x2F, // External Signatures | Internal Signatures | ECDH | IsSecret | WriteKey all slots | Write Configure Never, Default: 0x8F, 0x8F, - 0x8F, 0x8F, - 0x9F, 0x8F, - 0xAF, 0x8F, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0xAF, 0x8F, - // Counter[0] - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - // Counter[1] - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - // LastKeyUse - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - // Write via commands only - start - // UserExtra - 0x00, - // Selector - 0x00, - // LockValue - 0x55, - // LockConfig - 0x55, - // SlotLocked - 0xFF, 0xFF, - // Write via commands only - end - // RFU - 0x00, 0x00, - // X509format - 0x00, 0x00, 0x00, 0x00, - // KeyConfig - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x33, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x1C, 0x00, - 0x33, 0x00, // Private | Public | P256 NIST ECC key, Default: 0x1C, 0x00, - 0x1C, 0x00, - 0x1C, 0x00, - 0x1C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x3C, 0x00, - 0x1C, 0x00 -}; - -#endif /* _ECCX08_TLS_CONFIG_H_ */ diff --git a/examples/utility/SelfProvisioning/SelfProvisioning.ino b/examples/utility/SelfProvisioning/SelfProvisioning.ino index a0c13724b..46bfcafef 100644 --- a/examples/utility/SelfProvisioning/SelfProvisioning.ino +++ b/examples/utility/SelfProvisioning/SelfProvisioning.ino @@ -16,23 +16,13 @@ */ #include "arduino_secrets.h" -#include "ECCX08TLSConfig.h" -#include "ECCX08Cert.h" -#include +#include +#include +#include +#include #include -#include - -// from section 10.3.3 of the SAMD datasheet -#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C) -#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040) -#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044) -#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048) const bool DEBUG = true; -const int keySlot = 0; -const int compressedCertSlot = 10; -const int serialNumberAndAuthorityKeyIdentifierSlot = 11; -const int deviceIdSlot = 12; char ssid[] = SECRET_SSID; char pass[] = SECRET_PASS; @@ -40,13 +30,44 @@ char client_id[] = SECRET_CLIENT_ID; char secret_id[] = SECRET_SECRET_ID; #if defined(ARDUINO_SAMD_NANO_33_IOT) + #include char board_type[] = "nano_33_iot"; // Nano 33 IoT char board_fqbn[] = "arduino:samd:nano_33_iot"; // Nano 33 IoT #elif defined(ARDUINO_SAMD_MKRWIFI1010) + #include char board_type[] = "mkrwifi1010"; // MKR WiFi 1010 char board_fqbn[] = "arduino:samd:mkrwifi1010"; // MKR WiFi 1010 +#elif defined(ARDUINO_NANO_RP2040_CONNECT) + #include + char board_type[] = "nanorp2040connect"; // Nano RP2040 Connect + char board_fqbn[] = "arduino:mbed_nano:nanorp2040connect"; // Nano RP2040 Connect +#elif defined(ARDUINO_PORTENTA_H7_M7) + #include + char board_type[] = "envie_m7"; // Portenta H7 + char board_fqbn[] = "arduino:mbed_portenta:envie_m7"; // Portenta H7 +#elif defined(ARDUINO_NICLA_VISION) + #include + char board_type[] = "nicla_vision"; // Nicla Vision + char board_fqbn[] = "arduino:mbed_nicla:nicla_vision"; // Nicla Vision +#elif defined(ARDUINO_GIGA) + #include + char board_type[] = "giga"; // Giga R1 WiFi + char board_fqbn[] = "arduino:mbed_giga:giga"; // Giga R1 WiFi +#elif defined(ARDUINO_OPTA) + #include + char board_type[] = "opta"; // Opta + char board_fqbn[] = "arduino:mbed_opta:opta"; // Opta +#elif defined(ARDUINO_PORTENTA_C33) + #include + #include + char board_type[] = "portenta_c33"; // Portenta C33 + char board_fqbn[] = "arduino:renesas_portenta:portenta_c33"; // Portenta C33 +#elif defined(ARDUINO_UNOR4_WIFI) + #include + char board_type[] = "unor4wifi"; // UNO R4 WiFi + char board_fqbn[] = "arduino:renesas_uno:unor4wifi"; // UNO R4 WiFI #else - char board_type[] = "nonina"; // Not supported boards + char board_type[] = "unsupported"; // Not supported boards char board_fqbn[] = ""; #endif @@ -67,13 +88,13 @@ char server[] = "api2.arduino.cc"; // server address WiFiSSLClient client; int status = WL_IDLE_STATUS; -ECCX08CertClass ECCX08Cert; +SecureElement secureElement; void setup() { Serial.begin(9600); while (!Serial); - if (board_type == "nonina") { + if (board_type == "unsupported") { Serial.println("Sorry, this sketch only works on Nano 33 IoT and MKR 1010 WiFi"); while (1) { ; } } @@ -84,7 +105,7 @@ void setup() { // Connect to WPA/WPA2 network: status = WiFi.begin(ssid, pass); - delay(10000); + delay(3000); } Serial.print("SSID: "); @@ -94,56 +115,37 @@ void setup() { Serial.print("IP Address: "); Serial.println(ip); - while (!ECCX08.begin()) { - Serial.println("No ECCX08 present!"); + while (!secureElement.begin()) { + Serial.println("No secureElement present!"); delay(100); } - if (!ECCX08.locked()) { + if (!secureElement.locked()) { - if (!ECCX08.writeConfiguration(DEFAULT_ECCX08_TLS_CONFIG)) { - Serial.println("Writing ECCX08 configuration failed!"); + if (!secureElement.writeConfiguration()) { + Serial.println("Writing secureElement configuration failed!"); Serial.println("Stopping Provisioning"); while (1); } - if (!ECCX08.lock()) { - Serial.println("Locking ECCX08 configuration failed!"); + if (!secureElement.lock()) { + Serial.println("Locking secureElement configuration failed!"); Serial.println("Stopping Provisioning"); while (1); } - Serial.println("ECCX08 locked successfully"); + Serial.println("secureElement locked successfully"); Serial.println(); } //Random number for device name - board_name += String(ECCX08.random(65535)); - - uint32_t BoardUniqueID[4]; - BoardUniqueID[0] = SERIAL_NUMBER_WORD_0; - BoardUniqueID[1] = SERIAL_NUMBER_WORD_1; - BoardUniqueID[2] = SERIAL_NUMBER_WORD_2; - BoardUniqueID[3] = SERIAL_NUMBER_WORD_3; - uint8_t bid[32]; - for (int i = 0; i < 4; i++) - { - bid[i*4+0] = (uint8_t)(BoardUniqueID[i] >> 24); - bid[i*4+1] = (uint8_t)(BoardUniqueID[i] >> 16); - bid[i*4+2] = (uint8_t)(BoardUniqueID[i] >> 8); - bid[i*4+3] = (uint8_t)(BoardUniqueID[i] >> 0); - } - - for (size_t i = 0; i < 16; i++) { - if (bid[i] < 16) { - ArduinoID += String(0, HEX); - } - ArduinoID += String(bid[i], HEX); - } - ArduinoID.toUpperCase(); - + board_name += String(secureElement.random(65535)); Serial.print("Device Name: "); Serial.println(board_name); + //Board Serial Number + ArduinoID = ArduinoSerialNumber(); + Serial.print("SN: "); + Serial.println(ArduinoID); // Create Arduino Token ArduinoToken(client_id, secret_id); Serial.print("Bearer Token: "); @@ -155,18 +157,32 @@ void setup() { delay(2000); - while (!ECCX08Cert.beginCSR(keySlot, true)) { + // Configure WiFi firmware version + String fv = WiFi.firmwareVersion(); + WiFiFirmwareVersion(fv, deviceId, Arduino_Token); + Serial.print("WiFi Firmware Version: "); + Serial.println(fv); + + ECP256Certificate Certificate; + + while (!Certificate.begin()) { Serial.println("Error starting CSR generation!"); - delay(2000); + while (1); } - ECCX08Cert.setSubjectCommonName(deviceId); + Certificate.setSubjectCommonName(deviceId); - String csr = ECCX08Cert.endCSR(); + if (!SElementCSR::build(secureElement, Certificate, static_cast(SElementArduinoCloudSlot::Key), true)) { + Serial.println("Error generating CSR!"); + while (1); + } + + String csr = Certificate.getCSRPEM(); - while (!csr) { + if (!csr) { + /* WARNING: This string is parsed from IoTCloud frontend */ Serial.println("Error generating CSR!"); - delay(2000); + while (1); } Serial.println("Generated CSR is:"); @@ -206,42 +222,37 @@ void setup() { hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); - if (!ECCX08.writeSlot(deviceIdSlot, deviceIdBytes, sizeof(deviceIdBytes))) { + if (!secureElement.writeSlot(static_cast(SElementArduinoCloudSlot::DeviceId), deviceIdBytes, sizeof(deviceIdBytes))) { Serial.println("Error storing device id!"); while (1); } - if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { - Serial.println("Error starting ECCX08 storage!"); - while (1); - } - - ECCX08Cert.setSignature(signatureBytes); - ECCX08Cert.setAuthorityKeyIdentifier(authorityKeyIdentifierBytes); - ECCX08Cert.setSerialNumber(serialNumberBytes); - ECCX08Cert.setIssueYear(issueYear.toInt()); - ECCX08Cert.setIssueMonth(issueMonth.toInt()); - ECCX08Cert.setIssueDay(issueDay.toInt()); - ECCX08Cert.setIssueHour(issueHour.toInt()); - ECCX08Cert.setExpireYears(expireYears.toInt()); - - if (!ECCX08Cert.endStorage()) { - Serial.println("Error storing ECCX08 compressed cert!"); + if (!Certificate.begin()) { + Serial.println("Error starting secureElement storage!"); while (1); } - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { - Serial.println("Error starting ECCX08 cert reconstruction!"); + Certificate.setSubjectCommonName(deviceId); + Certificate.setIssuerCountryName("US"); + Certificate.setIssuerOrganizationName("Arduino LLC US"); + Certificate.setIssuerOrganizationalUnitName("IT"); + Certificate.setIssuerCommonName("Arduino"); + Certificate.setSignature(signatureBytes, sizeof(signatureBytes)); + Certificate.setAuthorityKeyId(authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + Certificate.setSerialNumber(serialNumberBytes, sizeof(serialNumberBytes)); + Certificate.setIssueYear(issueYear.toInt()); + Certificate.setIssueMonth(issueMonth.toInt()); + Certificate.setIssueDay(issueDay.toInt()); + Certificate.setIssueHour(issueHour.toInt()); + Certificate.setExpireYears(expireYears.toInt()); + + if (!SElementArduinoCloudCertificate::build(secureElement, Certificate, static_cast(SElementArduinoCloudSlot::Key))) { + Serial.println("Error building secureElement compressed cert!"); while (1); } - ECCX08Cert.setIssuerCountryName("US"); - ECCX08Cert.setIssuerOrganizationName("Arduino LLC US"); - ECCX08Cert.setIssuerOrganizationalUnitName("IT"); - ECCX08Cert.setIssuerCommonName("Arduino"); - - if (!ECCX08Cert.endReconstruction()) { - Serial.println("Error reconstructing ECCX08 compressed cert!"); + if (!SElementArduinoCloudCertificate::write(secureElement, Certificate, SElementArduinoCloudSlot::CompressedCertificate)) { + Serial.println("Error storing cert!"); while (1); } @@ -251,8 +262,8 @@ void setup() { Serial.println("Compressed cert = "); - const byte* certData = ECCX08Cert.bytes(); - int certLength = ECCX08Cert.length(); + const byte* certData = Certificate.bytes(); + int certLength = Certificate.length(); for (int i = 0; i < certLength; i++) { byte b = certData[i]; @@ -314,6 +325,81 @@ void hexStringToBytes(String& in, byte out[], int length) { } } +#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RENESAS) + +static void utox8(uint32_t val, uint8_t* s) { + for (int i = 0; i < 16; i=i+2) { + int d = val & 0XF; + val = (val >> 4); + + s[15 - i -1] = d > 9 ? 'A' + d - 10 : '0' + d; + s[15 - i] = '\0'; + } +} +#endif + +#ifdef ARDUINO_ARCH_SAMD + +uint8_t getUniqueSerialNumber(uint8_t* name) { + utox8(*(volatile uint32_t*)(0x0080A00C), &name[0]); + utox8(*(volatile uint32_t*)(0x0080A040), &name[16]); + utox8(*(volatile uint32_t*)(0x0080A044), &name[32]); + utox8(*(volatile uint32_t*)(0x0080A048), &name[48]); + return 64; +} + +#endif + +#ifdef ARDUINO_ARCH_RENESAS +uint8_t getUniqueSerialNumber(uint8_t* name) { + const bsp_unique_id_t* t = R_BSP_UniqueIdGet(); + utox8(t->unique_id_words[0], &name[0]); + utox8(t->unique_id_words[1], &name[16]); + utox8(t->unique_id_words[2], &name[32]); + utox8(t->unique_id_words[3], &name[48]); + return 64; +} +#endif + +String ArduinoSerialNumber() { + + uint8_t uniqueSerialNumber[64 + 1] = {0}; + char BoardUniqueID[32 + 1] = {0}; + + int uniqueSerialNumberLength = getUniqueSerialNumber(uniqueSerialNumber); + for(int i = 0, k = 0; i < uniqueSerialNumberLength; i = i+2, k++) { + BoardUniqueID[k] = uniqueSerialNumber[i]; + } + + String serialNumber = String(BoardUniqueID); + serialNumber.toUpperCase(); + return serialNumber; + +} + +void WiFiFirmwareVersion(String fv, String deviceId, String token) { + Serial.println("Configuring WiFi firmware version..."); + String PostData = "{\"wifi_fw_version\":\""; + PostData += fv; + PostData += "\"}"; + + if (client.connect(server, 443)) { + client.print("POST /iot/v2/devices/"); + client.print(deviceId); + client.println(" HTTP/1.1"); + client.println("Host: api2.arduino.cc"); + client.println("Connection: close"); + client.println("Content-Type: application/json;charset=UTF-8"); + client.print("Authorization: Bearer "); + client.println(token); + client.print("Content-Length: "); + client.println(PostData.length()); + client.println(); + client.println(PostData); + } + client.stop(); +} + void ArduinoToken(String client_id, String client_secret) { Serial.println("Creating Bearer Token..."); String PostData = "grant_type=client_credentials&client_id="; @@ -354,12 +440,14 @@ void ArduinoToken(String client_id, String client_secret) { if (tokenResponse[intIndex] == -1) { break; } + delay(1); intIndex++; } JSONVar myObject = JSON.parse(tokenResponse); if (myObject.hasOwnProperty("access_token")) { Arduino_Token += (const char*) myObject["access_token"]; } + client.stop(); } void BoardUuid(String board_name, String board_type, String board_fqbn, String board_serial, String user_token) { @@ -388,7 +476,8 @@ void BoardUuid(String board_name, String board_type, String board_fqbn, String b } while (!client.available()) { - ; + Serial.println("No client"); + delay(2000); } char endOfHeaders[] = "\r\n\r\n"; @@ -407,12 +496,14 @@ void BoardUuid(String board_name, String board_type, String board_fqbn, String b if (deviceResponse[intIndex] == -1) { break; } + delay(1); intIndex++; } JSONVar myObject = JSON.parse(deviceResponse); if (myObject.hasOwnProperty("id")) { deviceId += (const char*) myObject["id"]; } + client.stop(); } void ArduinoCertificate(String user_token, String DeviceUuid, String csr) { @@ -461,24 +552,27 @@ void ArduinoCertificate(String user_token, String DeviceUuid, String csr) { if (certResponse[intIndex] == -1) { break; } + delay(1); intIndex++; } - JSONVar myObject = JSON.parse(certResponse); + char* p = strstr(certResponse, "{"); + JSONVar myObject = JSON.parse(p); String certZip = JSON.stringify(myObject["compressed"]); JSONVar myCert = JSON.parse(certZip); - if (myCert.hasOwnProperty("not_before")) { + if (myCert.hasOwnProperty("not_before") && + myCert.hasOwnProperty("serial") && + myCert.hasOwnProperty("authority_key_identifier") && + myCert.hasOwnProperty("signature_asn1_x") && + myCert.hasOwnProperty("signature_asn1_x")) { not_before += (const char*) myCert["not_before"]; - } - if (myCert.hasOwnProperty("serial")) { serialNumber += (const char*) myCert["serial"]; - } - if (myCert.hasOwnProperty("authority_key_identifier")) { authorityKeyIdentifier += (const char*) myCert["authority_key_identifier"]; - } - if (myCert.hasOwnProperty("signature_asn1_x")) { signature += (const char*) myCert["signature_asn1_x"]; - } - if (myCert.hasOwnProperty("signature_asn1_y")) { signature += (const char*) myCert["signature_asn1_y"]; + } else { + Serial.println("Error parsing cloud certificate"); + while (1) { + ; + } } -} \ No newline at end of file +}