From b67e6786da0f1fdb010233c8b609baaa2d302a50 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 24 Jul 2018 16:22:38 -0400 Subject: [PATCH 1/5] Add ability to add Authority Key Identifier to reconstructed SSL public cert --- src/utility/ECCX08Cert.cpp | 72 ++++++++++++++++++++++++++++++++++---- src/utility/ECCX08Cert.h | 8 +++++ 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/utility/ECCX08Cert.cpp b/src/utility/ECCX08Cert.cpp index 1311c3092..7369b1024 100644 --- a/src/utility/ECCX08Cert.cpp +++ b/src/utility/ECCX08Cert.cpp @@ -73,6 +73,7 @@ ECCX08CertClass::ECCX08CertClass() : _keySlot(-1), _compressedCertSlot(-1), _serialNumberSlot(-1), + _authorityKeyIdentifier(NULL), _bytes(NULL), _length(0) { @@ -334,10 +335,19 @@ int ECCX08CertClass::endReconstruction() int publicKeyLen = publicKeyLength(); + int authorityKeyIdentifierLen = authorityKeyIdentifierLength(_authorityKeyIdentifier); + int signatureLen = signatureLength(compressedCert.signature); int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + 32 + - subjectHeaderLen + subjectLen + publicKeyLen + 4; + subjectHeaderLen + subjectLen + publicKeyLen; + + if (authorityKeyIdentifierLen) { + certInfoLen += authorityKeyIdentifierLen; + } else { + certInfoLen += 4; + } + int certInfoHeaderLen = sequenceHeaderLength(certInfoLen); int certDataLen = certInfoLen + certInfoHeaderLen + signatureLen; @@ -411,11 +421,16 @@ int ECCX08CertClass::endReconstruction() appendPublicKey(publicKey, out); out += publicKeyLen; - // null sequence - *out++ = 0xA3; - *out++ = 0x02; - *out++ = 0x30; - *out++ = 0x00; + if (authorityKeyIdentifierLen) { + appendAuthorityKeyIdentifier(_authorityKeyIdentifier, out); + out += authorityKeyIdentifierLen; + } else { + // null sequence + *out++ = 0xA3; + *out++ = 0x02; + *out++ = 0x30; + *out++ = 0x00; + } // signature appendSignature(compressedCert.signature, out); @@ -494,6 +509,11 @@ void ECCX08CertClass::setSubjectCommonName(const String& commonName) _subjectCommonName = commonName; } +void ECCX08CertClass::setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]) +{ + _authorityKeyIdentifier = authorityKeyIdentifier; +} + int ECCX08CertClass::versionLength() { return 3; @@ -546,6 +566,11 @@ int ECCX08CertClass::publicKeyLength() return (2 + 2 + 9 + 10 + 4 + 64); } +int ECCX08CertClass::authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]) +{ + return (authorityKeyIdentifier == NULL) ? 0 : 37; +} + int ECCX08CertClass::signatureLength(const byte signature[]) { const byte* r = &signature[0]; @@ -684,6 +709,41 @@ void ECCX08CertClass::appendPublicKey(const byte publicKey[], byte out[]) 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 diff --git a/src/utility/ECCX08Cert.h b/src/utility/ECCX08Cert.h index 882ba76d1..84197021e 100644 --- a/src/utility/ECCX08Cert.h +++ b/src/utility/ECCX08Cert.h @@ -42,6 +42,8 @@ class ECCX08CertClass { void setSubjectOrganizationalUnitName(const String& organizationalUnitName); void setSubjectCommonName(const String& commonName); + void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); + private: int versionLength(); @@ -54,6 +56,8 @@ class ECCX08CertClass { int publicKeyLength(); + int authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]); + int signatureLength(const byte signature[]); int serialNumberLength(const byte serialNumber[]); @@ -72,6 +76,8 @@ class ECCX08CertClass { 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[]); @@ -103,6 +109,8 @@ class ECCX08CertClass { String _subjectOrganizationalUnitName; String _subjectCommonName; + const byte* _authorityKeyIdentifier; + byte _temp[88]; byte* _bytes; int _length; From 3f4ab805e76d3e02de748894ca635370fad60eb9 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 24 Jul 2018 16:23:03 -0400 Subject: [PATCH 2/5] Set Authority Key Identifier when re-constructing cert --- src/ArduinoCloud.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ArduinoCloud.cpp b/src/ArduinoCloud.cpp index 05159a144..4a6515a28 100644 --- a/src/ArduinoCloud.cpp +++ b/src/ArduinoCloud.cpp @@ -48,6 +48,12 @@ int ArduinoCloudClass::begin(Client& net) ECCX08Cert.setIssuerOrganizationalUnitName("IT"); ECCX08Cert.setIssuerCommonName("Arduino"); + const byte authorityKeyIdentifier[20] = { + 0xb2, 0xed, 0xef, 0xed, 0x3b, 0xbf, 0xc7, 0x71, 0x75, 0x24, 0x33, 0xd1, 0xae, 0x8b, 0x54, 0xed, 0x97, 0x14, 0x7a, 0x1d + }; + + ECCX08Cert.setAuthorityKeyIdentifier(authorityKeyIdentifier); + if (!ECCX08Cert.endReconstruction()) { return 0; } From b2644280a5fb234565570607eebcb5861f7f0d4a Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Wed, 25 Jul 2018 18:17:45 -0400 Subject: [PATCH 3/5] Use ECCX08 slot to store Authority Key Identifier, and request in provisioning sketch --- .../utility/Provisioning/Provisioning.ino | 38 +++++++------ src/ArduinoCloud.cpp | 17 ++---- src/utility/ECCX08Cert.cpp | 57 ++++++++++++++----- src/utility/ECCX08Cert.h | 16 +++--- 4 files changed, 77 insertions(+), 51 deletions(-) diff --git a/examples/utility/Provisioning/Provisioning.ino b/examples/utility/Provisioning/Provisioning.ino index 29cb46793..0777dcb1f 100644 --- a/examples/utility/Provisioning/Provisioning.ino +++ b/examples/utility/Provisioning/Provisioning.ino @@ -3,12 +3,13 @@ #include #include -#include +#include -const int keySlot = 0; -const int compressedCertSlot = 10; -const int serialNumberSlot = 11; -const int thingIdSlot = 12; +const int keySlot = 0; +const int compressedCertSlot = 10; +const int serialNumberSlot = 11; +const int authorityKeyIdentifierSlot = 12; +const int thingIdSlot = 13; void setup() { Serial.begin(9600); @@ -68,37 +69,41 @@ void setup() { Serial.println(); Serial.println(csr); - String thingId = promptAndReadLine("Please enter the thing id: "); - String issueYear = promptAndReadLine("Please enter the issue year of the certificate (2000 - 2031): "); - String issueMonth = promptAndReadLine("Please enter the issue month of the certificate (1 - 12): "); - String issueDay = promptAndReadLine("Please enter the issue day of the certificate (1 - 31): "); - String issueHour = promptAndReadLine("Please enter the issue hour of the certificate (0 - 23): "); - String expireYears = promptAndReadLine("Please enter how many years the certificate is valid for (0 - 31): "); - String serialNumber = promptAndReadLine("Please enter the certificates serial number: "); - String signature = promptAndReadLine("Please enter the certificates signature: "); + String thingId = promptAndReadLine("Please enter the thing id: "); + String issueYear = promptAndReadLine("Please enter the issue year of the certificate (2000 - 2031): "); + String issueMonth = promptAndReadLine("Please enter the issue month of the certificate (1 - 12): "); + String issueDay = promptAndReadLine("Please enter the issue day of the certificate (1 - 31): "); + String issueHour = promptAndReadLine("Please enter the issue hour of the certificate (0 - 23): "); + String expireYears = promptAndReadLine("Please enter how many years the certificate is valid for (0 - 31): "); + String serialNumber = promptAndReadLine("Please enter the certificates serial number: "); + String authorityKeyIdentifier = promptAndReadLine("Please enter the certificates authority key identifier: "); + String signature = promptAndReadLine("Please enter the certificates signature: "); serialNumber.toUpperCase(); signature.toUpperCase(); byte thingIdBytes[72]; byte serialNumberBytes[16]; + byte authorityKeyIdentifierBytes[20]; byte signatureBytes[64]; thingId.getBytes(thingIdBytes, sizeof(thingIdBytes)); hexStringToBytes(serialNumber, serialNumberBytes, sizeof(serialNumberBytes)); - hexStringToBytes(signature, signatureBytes, 64); + hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); if (!ECCX08.writeSlot(thingIdSlot, thingIdBytes, sizeof(thingIdBytes))) { Serial.println("Error storing thing id!"); while (1); } - if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberSlot)) { + if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberSlot, authorityKeyIdentifierSlot)) { 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()); @@ -111,7 +116,7 @@ void setup() { while (1); } - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberSlot)) { + if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberSlot, authorityKeyIdentifierSlot)) { Serial.println("Error starting ECCX08 cert reconstruction!"); while (1); } @@ -189,4 +194,3 @@ void hexStringToBytes(const String& in, byte out[], int length) { out[outLength++] = (highByte << 4) | lowByte; } } - diff --git a/src/ArduinoCloud.cpp b/src/ArduinoCloud.cpp index 4a6515a28..64cb7dca5 100644 --- a/src/ArduinoCloud.cpp +++ b/src/ArduinoCloud.cpp @@ -7,10 +7,11 @@ const static char server[] = "a19g5nbe27wn47.iot.us-east-1.amazonaws.com"; //"xxxxxxxxxxxxxx.iot.xx-xxxx-x.amazonaws.com"; -const static int keySlot = 0; -const static int compressedCertSlot = 10; -const static int serialNumberSlot = 11; -const static int thingIdSlot = 12; +const static int keySlot = 0; +const static int compressedCertSlot = 10; +const static int serialNumberSlot = 11; +const static int authorityKeyIdentifierSlot = 12; +const static int thingIdSlot = 13; ArduinoCloudClass::ArduinoCloudClass() : _bearSslClient(NULL), @@ -38,7 +39,7 @@ int ArduinoCloudClass::begin(Client& net) } _id = (char*)thingIdBytes; - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberSlot)) { + if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberSlot, authorityKeyIdentifierSlot)) { return 0; } @@ -48,12 +49,6 @@ int ArduinoCloudClass::begin(Client& net) ECCX08Cert.setIssuerOrganizationalUnitName("IT"); ECCX08Cert.setIssuerCommonName("Arduino"); - const byte authorityKeyIdentifier[20] = { - 0xb2, 0xed, 0xef, 0xed, 0x3b, 0xbf, 0xc7, 0x71, 0x75, 0x24, 0x33, 0xd1, 0xae, 0x8b, 0x54, 0xed, 0x97, 0x14, 0x7a, 0x1d - }; - - ECCX08Cert.setAuthorityKeyIdentifier(authorityKeyIdentifier); - if (!ECCX08Cert.endReconstruction()) { return 0; } diff --git a/src/utility/ECCX08Cert.cpp b/src/utility/ECCX08Cert.cpp index 7369b1024..bfcd0dfc4 100644 --- a/src/utility/ECCX08Cert.cpp +++ b/src/utility/ECCX08Cert.cpp @@ -18,7 +18,8 @@ struct __attribute__((__packed__)) CompressedCert { byte unused[5]; }; -#define SERIAL_NUMBER_LENGTH 16 +#define SERIAL_NUMBER_LENGTH 16 +#define AUTHORITY_KEY_IDENTIFIER_LENGTH 20 static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { @@ -73,7 +74,7 @@ ECCX08CertClass::ECCX08CertClass() : _keySlot(-1), _compressedCertSlot(-1), _serialNumberSlot(-1), - _authorityKeyIdentifier(NULL), + _authorityKeyIdentifierSlot(-1), _bytes(NULL), _length(0) { @@ -185,7 +186,7 @@ String ECCX08CertClass::endCSR() return base64Encode(csr, csrLen + csrHeaderLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); } -int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberSlot) +int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot) { if (compressedCertSlot < 8 || compressedCertSlot > 15) { return 0; @@ -195,8 +196,15 @@ int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberSlot) return 0; } + if (authorityKeyIdentifierSlot > -1) { + if (authorityKeyIdentifierSlot < 8 || authorityKeyIdentifierSlot > 15) { + return 0; + } + } + _compressedCertSlot = compressedCertSlot; _serialNumberSlot = serialNumberSlot; + _authorityKeyIdentifierSlot = authorityKeyIdentifierSlot; memset(_temp, 0x00, sizeof(_temp)); @@ -256,11 +264,16 @@ void ECCX08CertClass::setExpireYears(int expireYears) compressedCert->dates[2] |= expireYears; } -void ECCX08CertClass::setSerialNumber(byte serialNumber[]) +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)) { @@ -271,10 +284,14 @@ int ECCX08CertClass::endStorage() return 0; } + if (!ECCX08.writeSlot(_authorityKeyIdentifierSlot, &_temp[88], AUTHORITY_KEY_IDENTIFIER_LENGTH)) { + return 0; + } + return 1; } -int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberSlot) +int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot) { if (keySlot < 0 || keySlot > 8) { return 0; @@ -288,9 +305,16 @@ int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, in return 0; } + if (authorityKeyIdentifierSlot > -1) { + if (authorityKeyIdentifierSlot < 8 || authorityKeyIdentifierSlot > 15) { + return 0; + } + } + _keySlot = keySlot; _compressedCertSlot = compressedCertSlot; _serialNumberSlot = serialNumberSlot; + _authorityKeyIdentifierSlot = authorityKeyIdentifierSlot; return 1; } @@ -300,6 +324,7 @@ int ECCX08CertClass::endReconstruction() byte publicKey[64]; struct CompressedCert compressedCert; byte serialNumber[SERIAL_NUMBER_LENGTH]; + byte authorityKeyIdentifier[AUTHORITY_KEY_IDENTIFIER_LENGTH]; if (!ECCX08.generatePublicKey(_keySlot, publicKey)) { return 0; @@ -313,6 +338,11 @@ int ECCX08CertClass::endReconstruction() return 0; } + if (_authorityKeyIdentifierSlot > -1 && + !ECCX08.readSlot(_authorityKeyIdentifierSlot, authorityKeyIdentifier, sizeof(authorityKeyIdentifier))) { + return 0; + } + int serialNumberLen = serialNumberLength(serialNumber); int issuerLen = issuerOrSubjectLength(_issuerCountryName, @@ -335,7 +365,11 @@ int ECCX08CertClass::endReconstruction() int publicKeyLen = publicKeyLength(); - int authorityKeyIdentifierLen = authorityKeyIdentifierLength(_authorityKeyIdentifier); + int authorityKeyIdentifierLen = 0; + + if (_authorityKeyIdentifierSlot > -1) { + authorityKeyIdentifierLen = authorityKeyIdentifierLength(); + } int signatureLen = signatureLength(compressedCert.signature); @@ -422,7 +456,7 @@ int ECCX08CertClass::endReconstruction() out += publicKeyLen; if (authorityKeyIdentifierLen) { - appendAuthorityKeyIdentifier(_authorityKeyIdentifier, out); + appendAuthorityKeyIdentifier(authorityKeyIdentifier, out); out += authorityKeyIdentifierLen; } else { // null sequence @@ -509,11 +543,6 @@ void ECCX08CertClass::setSubjectCommonName(const String& commonName) _subjectCommonName = commonName; } -void ECCX08CertClass::setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]) -{ - _authorityKeyIdentifier = authorityKeyIdentifier; -} - int ECCX08CertClass::versionLength() { return 3; @@ -566,9 +595,9 @@ int ECCX08CertClass::publicKeyLength() return (2 + 2 + 9 + 10 + 4 + 64); } -int ECCX08CertClass::authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]) +int ECCX08CertClass::authorityKeyIdentifierLength() { - return (authorityKeyIdentifier == NULL) ? 0 : 37; + return 37; } int ECCX08CertClass::signatureLength(const byte signature[]) diff --git a/src/utility/ECCX08Cert.h b/src/utility/ECCX08Cert.h index 84197021e..f0f4df380 100644 --- a/src/utility/ECCX08Cert.h +++ b/src/utility/ECCX08Cert.h @@ -12,17 +12,18 @@ class ECCX08CertClass { int beginCSR(int keySlot, bool newPrivateKey = true); String endCSR(); - int beginStorage(int compressedCertSlot, int serialNumberSlot); + int beginStorage(int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot); 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(byte serialNumber[]); + void setSerialNumber(const byte serialNumber[]); + void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); int endStorage(); - int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberSlot); + int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot); int endReconstruction(); byte* bytes(); @@ -42,8 +43,6 @@ class ECCX08CertClass { void setSubjectOrganizationalUnitName(const String& organizationalUnitName); void setSubjectCommonName(const String& commonName); - void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); - private: int versionLength(); @@ -56,7 +55,7 @@ class ECCX08CertClass { int publicKeyLength(); - int authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]); + int authorityKeyIdentifierLength(); int signatureLength(const byte signature[]); @@ -94,6 +93,7 @@ class ECCX08CertClass { int _keySlot; int _compressedCertSlot; int _serialNumberSlot; + int _authorityKeyIdentifierSlot; String _issuerCountryName; String _issuerStateProvinceName; @@ -109,9 +109,7 @@ class ECCX08CertClass { String _subjectOrganizationalUnitName; String _subjectCommonName; - const byte* _authorityKeyIdentifier; - - byte _temp[88]; + byte _temp[108]; byte* _bytes; int _length; }; From 8d3eaeb73bad861b47e285582d840e5b102e8c15 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Thu, 26 Jul 2018 10:08:42 -0400 Subject: [PATCH 4/5] Combine certificate serial number and authority key identifier data into one slot --- .../utility/Provisioning/Provisioning.ino | 13 ++-- src/ArduinoCloud.cpp | 11 ++- src/utility/ECCX08Cert.cpp | 78 ++++++++----------- src/utility/ECCX08Cert.h | 9 +-- 4 files changed, 47 insertions(+), 64 deletions(-) diff --git a/examples/utility/Provisioning/Provisioning.ino b/examples/utility/Provisioning/Provisioning.ino index 0777dcb1f..a58b486b3 100644 --- a/examples/utility/Provisioning/Provisioning.ino +++ b/examples/utility/Provisioning/Provisioning.ino @@ -5,11 +5,10 @@ #include #include -const int keySlot = 0; -const int compressedCertSlot = 10; -const int serialNumberSlot = 11; -const int authorityKeyIdentifierSlot = 12; -const int thingIdSlot = 13; +const int keySlot = 0; +const int compressedCertSlot = 10; +const int serialNumberAndAuthorityKeyIdentifierSlot = 11; +const int thingIdSlot = 12; void setup() { Serial.begin(9600); @@ -97,7 +96,7 @@ void setup() { while (1); } - if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberSlot, authorityKeyIdentifierSlot)) { + if (!ECCX08Cert.beginStorage(compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { Serial.println("Error starting ECCX08 storage!"); while (1); } @@ -116,7 +115,7 @@ void setup() { while (1); } - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberSlot, authorityKeyIdentifierSlot)) { + if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { Serial.println("Error starting ECCX08 cert reconstruction!"); while (1); } diff --git a/src/ArduinoCloud.cpp b/src/ArduinoCloud.cpp index 64cb7dca5..dddf3683d 100644 --- a/src/ArduinoCloud.cpp +++ b/src/ArduinoCloud.cpp @@ -7,11 +7,10 @@ const static char server[] = "a19g5nbe27wn47.iot.us-east-1.amazonaws.com"; //"xxxxxxxxxxxxxx.iot.xx-xxxx-x.amazonaws.com"; -const static int keySlot = 0; -const static int compressedCertSlot = 10; -const static int serialNumberSlot = 11; -const static int authorityKeyIdentifierSlot = 12; -const static int thingIdSlot = 13; +const static int keySlot = 0; +const static int compressedCertSlot = 10; +const static int serialNumberAndAuthorityKeyIdentifierSlot = 11; +const static int thingIdSlot = 12; ArduinoCloudClass::ArduinoCloudClass() : _bearSslClient(NULL), @@ -39,7 +38,7 @@ int ArduinoCloudClass::begin(Client& net) } _id = (char*)thingIdBytes; - if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberSlot, authorityKeyIdentifierSlot)) { + if (!ECCX08Cert.beginReconstruction(keySlot, compressedCertSlot, serialNumberAndAuthorityKeyIdentifierSlot)) { return 0; } diff --git a/src/utility/ECCX08Cert.cpp b/src/utility/ECCX08Cert.cpp index bfcd0dfc4..7d38969bc 100644 --- a/src/utility/ECCX08Cert.cpp +++ b/src/utility/ECCX08Cert.cpp @@ -21,6 +21,11 @@ struct __attribute__((__packed__)) CompressedCert { #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]; +}; + static String base64Encode(const byte in[], unsigned int length, const char* prefix, const char* suffix) { static const char* CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; @@ -73,8 +78,7 @@ static String base64Encode(const byte in[], unsigned int length, const char* pre ECCX08CertClass::ECCX08CertClass() : _keySlot(-1), _compressedCertSlot(-1), - _serialNumberSlot(-1), - _authorityKeyIdentifierSlot(-1), + _serialNumberAndAuthorityKeyIdentifierSlot(-1), _bytes(NULL), _length(0) { @@ -186,25 +190,18 @@ String ECCX08CertClass::endCSR() return base64Encode(csr, csrLen + csrHeaderLen, "-----BEGIN CERTIFICATE REQUEST-----\n", "\n-----END CERTIFICATE REQUEST-----\n"); } -int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot) +int ECCX08CertClass::beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { if (compressedCertSlot < 8 || compressedCertSlot > 15) { return 0; } - if (serialNumberSlot < 8 || serialNumberSlot > 15) { + if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { return 0; } - if (authorityKeyIdentifierSlot > -1) { - if (authorityKeyIdentifierSlot < 8 || authorityKeyIdentifierSlot > 15) { - return 0; - } - } - _compressedCertSlot = compressedCertSlot; - _serialNumberSlot = serialNumberSlot; - _authorityKeyIdentifierSlot = authorityKeyIdentifierSlot; + _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; memset(_temp, 0x00, sizeof(_temp)); @@ -280,18 +277,14 @@ int ECCX08CertClass::endStorage() return 0; } - if (!ECCX08.writeSlot(_serialNumberSlot, &_temp[72], SERIAL_NUMBER_LENGTH)) { - return 0; - } - - if (!ECCX08.writeSlot(_authorityKeyIdentifierSlot, &_temp[88], AUTHORITY_KEY_IDENTIFIER_LENGTH)) { + 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 serialNumberSlot, int authorityKeyIdentifierSlot) +int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot) { if (keySlot < 0 || keySlot > 8) { return 0; @@ -301,20 +294,13 @@ int ECCX08CertClass::beginReconstruction(int keySlot, int compressedCertSlot, in return 0; } - if (serialNumberSlot < 8 || serialNumberSlot > 15) { + if (serialNumberAndAuthorityKeyIdentifierSlot < 8 || serialNumberAndAuthorityKeyIdentifierSlot > 15) { return 0; } - if (authorityKeyIdentifierSlot > -1) { - if (authorityKeyIdentifierSlot < 8 || authorityKeyIdentifierSlot > 15) { - return 0; - } - } - _keySlot = keySlot; _compressedCertSlot = compressedCertSlot; - _serialNumberSlot = serialNumberSlot; - _authorityKeyIdentifierSlot = authorityKeyIdentifierSlot; + _serialNumberAndAuthorityKeyIdentifierSlot = serialNumberAndAuthorityKeyIdentifierSlot; return 1; } @@ -323,8 +309,7 @@ int ECCX08CertClass::endReconstruction() { byte publicKey[64]; struct CompressedCert compressedCert; - byte serialNumber[SERIAL_NUMBER_LENGTH]; - byte authorityKeyIdentifier[AUTHORITY_KEY_IDENTIFIER_LENGTH]; + struct SerialNumberAndAuthorityKeyIdentifier serialNumberAndAuthorityKeyIdentifier; if (!ECCX08.generatePublicKey(_keySlot, publicKey)) { return 0; @@ -334,16 +319,11 @@ int ECCX08CertClass::endReconstruction() return 0; } - if (!ECCX08.readSlot(_serialNumberSlot, serialNumber, sizeof(serialNumber))) { + if (!ECCX08.readSlot(_serialNumberAndAuthorityKeyIdentifierSlot, (byte*)&serialNumberAndAuthorityKeyIdentifier, sizeof(serialNumberAndAuthorityKeyIdentifier))) { return 0; } - if (_authorityKeyIdentifierSlot > -1 && - !ECCX08.readSlot(_authorityKeyIdentifierSlot, authorityKeyIdentifier, sizeof(authorityKeyIdentifier))) { - return 0; - } - - int serialNumberLen = serialNumberLength(serialNumber); + int serialNumberLen = serialNumberLength(serialNumberAndAuthorityKeyIdentifier.serialNumber); int issuerLen = issuerOrSubjectLength(_issuerCountryName, _issuerStateProvinceName, @@ -365,12 +345,8 @@ int ECCX08CertClass::endReconstruction() int publicKeyLen = publicKeyLength(); - int authorityKeyIdentifierLen = 0; - - if (_authorityKeyIdentifierSlot > -1) { - authorityKeyIdentifierLen = authorityKeyIdentifierLength(); - } - + int authorityKeyIdentifierLen = authorityKeyIdentifierLength(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier); + int signatureLen = signatureLength(compressedCert.signature); int certInfoLen = 5 + serialNumberLen + 12 + issuerHeaderLen + issuerLen + 32 + @@ -411,7 +387,7 @@ int ECCX08CertClass::endReconstruction() *out++ = 0x02; // serial number - appendSerialNumber(serialNumber, out); + appendSerialNumber(serialNumberAndAuthorityKeyIdentifier.serialNumber, out); out += serialNumberLen; // ecdsaWithSHA256 @@ -456,7 +432,7 @@ int ECCX08CertClass::endReconstruction() out += publicKeyLen; if (authorityKeyIdentifierLen) { - appendAuthorityKeyIdentifier(authorityKeyIdentifier, out); + appendAuthorityKeyIdentifier(serialNumberAndAuthorityKeyIdentifier.authorityKeyIdentifier, out); out += authorityKeyIdentifierLen; } else { // null sequence @@ -595,9 +571,19 @@ int ECCX08CertClass::publicKeyLength() return (2 + 2 + 9 + 10 + 4 + 64); } -int ECCX08CertClass::authorityKeyIdentifierLength() +int ECCX08CertClass::authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]) { - return 37; + 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[]) diff --git a/src/utility/ECCX08Cert.h b/src/utility/ECCX08Cert.h index f0f4df380..2b35f7777 100644 --- a/src/utility/ECCX08Cert.h +++ b/src/utility/ECCX08Cert.h @@ -12,7 +12,7 @@ class ECCX08CertClass { int beginCSR(int keySlot, bool newPrivateKey = true); String endCSR(); - int beginStorage(int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot); + int beginStorage(int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); void setSignature(byte signature[]); void setIssueYear(int issueYear); void setIssueMonth(int issueMonth); @@ -23,7 +23,7 @@ class ECCX08CertClass { void setAuthorityKeyIdentifier(const byte authorityKeyIdentifier[]); int endStorage(); - int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberSlot, int authorityKeyIdentifierSlot); + int beginReconstruction(int keySlot, int compressedCertSlot, int serialNumberAndAuthorityKeyIdentifierSlot); int endReconstruction(); byte* bytes(); @@ -55,7 +55,7 @@ class ECCX08CertClass { int publicKeyLength(); - int authorityKeyIdentifierLength(); + int authorityKeyIdentifierLength(const byte authorityKeyIdentifier[]); int signatureLength(const byte signature[]); @@ -92,8 +92,7 @@ class ECCX08CertClass { private: int _keySlot; int _compressedCertSlot; - int _serialNumberSlot; - int _authorityKeyIdentifierSlot; + int _serialNumberAndAuthorityKeyIdentifierSlot; String _issuerCountryName; String _issuerStateProvinceName; From 156fc1069aa9e01f9b053d200cfa0c7d7f1f4ba5 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 22 Aug 2018 17:17:57 +0200 Subject: [PATCH 5/5] fix hex to byte conversion --- examples/utility/Provisioning/Provisioning.ino | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/utility/Provisioning/Provisioning.ino b/examples/utility/Provisioning/Provisioning.ino index a58b486b3..1d5dce576 100644 --- a/examples/utility/Provisioning/Provisioning.ino +++ b/examples/utility/Provisioning/Provisioning.ino @@ -78,9 +78,6 @@ void setup() { String authorityKeyIdentifier = promptAndReadLine("Please enter the certificates authority key identifier: "); String signature = promptAndReadLine("Please enter the certificates signature: "); - serialNumber.toUpperCase(); - signature.toUpperCase(); - byte thingIdBytes[72]; byte serialNumberBytes[16]; byte authorityKeyIdentifierBytes[20]; @@ -90,7 +87,7 @@ void setup() { hexStringToBytes(serialNumber, serialNumberBytes, sizeof(serialNumberBytes)); hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); - + if (!ECCX08.writeSlot(thingIdSlot, thingIdBytes, sizeof(thingIdBytes))) { Serial.println("Error storing thing id!"); while (1); @@ -179,8 +176,9 @@ String readLine() { return line; } -void hexStringToBytes(const String& in, byte out[], int length) { +void hexStringToBytes(String& in, byte out[], int length) { int inLength = in.length(); + in.toUpperCase(); int outLength = 0; for (int i = 0; i < inLength && outLength < length; i += 2) { @@ -190,6 +188,6 @@ void hexStringToBytes(const String& in, byte out[], int length) { byte highByte = (highChar <= '9') ? (highChar - '0') : (highChar + 10 - 'A'); byte lowByte = (lowChar <= '9') ? (lowChar - '0') : (lowChar + 10 - 'A'); - out[outLength++] = (highByte << 4) | lowByte; + out[outLength++] = (highByte << 4) | (lowByte & 0xF); } }