From 2ad21622be479cd19cc43bc923727f5565f0eb61 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 19 Dec 2024 11:34:08 +0100 Subject: [PATCH 01/13] Add function to rebuild certificate from compressed data --- .../SElementArduinoCloudCertificate.cpp | 66 +++++++++++++++++++ src/utility/SElementArduinoCloudCertificate.h | 4 ++ 2 files changed, 70 insertions(+) diff --git a/src/utility/SElementArduinoCloudCertificate.cpp b/src/utility/SElementArduinoCloudCertificate.cpp index e44ccd2..b505128 100644 --- a/src/utility/SElementArduinoCloudCertificate.cpp +++ b/src/utility/SElementArduinoCloudCertificate.cpp @@ -14,6 +14,30 @@ #include +/****************************************************************************** + * LOCAL MODULE FUNCTIONS + ******************************************************************************/ + +static 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) { + char highChar = in[i]; + char lowChar = in[i + 1]; + + byte highByte = (highChar <= '9') ? (highChar - '0') : (highChar + 10 - 'A'); + byte lowByte = (lowChar <= '9') ? (lowChar - '0') : (lowChar + 10 - 'A'); + + out[outLength++] = (highByte << 4) | (lowByte & 0xF); + } +} + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + int SElementArduinoCloudCertificate::write(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot) { #if defined(SECURE_ELEMENT_IS_SE050) || defined(SECURE_ELEMENT_IS_SOFTSE) @@ -92,3 +116,45 @@ int SElementArduinoCloudCertificate::read(SecureElement & se, ECP256Certificate #endif return 1; } + +int SElementArduinoCloudCertificate::rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, const String & authorityKeyIdentifier, const String & signature, const SElementArduinoCloudSlot keySlot) +{ + byte serialNumberBytes[ECP256_CERT_SERIAL_NUMBER_LENGTH]; + byte authorityKeyIdentifierBytes[ECP256_CERT_AUTHORITY_KEY_ID_LENGTH]; + byte signatureBytes[ECP256_CERT_SIGNATURE_LENGTH]; + + if (!deviceId.length() || !notBefore.length() || !notAfter.length() || !serialNumber.length() || !authorityKeyIdentifier.length() || !signature.length() ) { + DEBUG_ERROR("SEACC::%s input params error.", __FUNCTION__); + return 0; + } + + hexStringToBytes(serialNumber, serialNumberBytes, sizeof(serialNumberBytes)); + hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + hexStringToBytes(signature, signatureBytes, sizeof(signatureBytes)); + + if (!cert.begin()) { + DEBUG_ERROR("SEACC::%s cert begin error", __FUNCTION__); + return -1; + } + + cert.setSubjectCommonName(deviceId); + cert.setIssuerCountryName("US"); + cert.setIssuerOrganizationName("Arduino LLC US"); + cert.setIssuerOrganizationalUnitName("IT"); + cert.setIssuerCommonName("Arduino"); + cert.setSignature(signatureBytes, sizeof(signatureBytes)); + cert.setAuthorityKeyId(authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + cert.setSerialNumber(serialNumberBytes, sizeof(serialNumberBytes)); + cert.setIssueYear(notBefore.substring(0,4).toInt()); + cert.setIssueMonth(notBefore.substring(5,7).toInt()); + cert.setIssueDay(notBefore.substring(8,10).toInt()); + cert.setIssueHour(notBefore.substring(11,13).toInt()); + cert.setExpireYears(notAfter.substring(0,4).toInt() - notBefore.substring(0,4).toInt()); + + + if (!SElementCertificate::build(se, cert, static_cast(keySlot))) { + DEBUG_ERROR("SEACC::%s cert build error", __FUNCTION__); + return -1; + } + return 1; +} diff --git a/src/utility/SElementArduinoCloudCertificate.h b/src/utility/SElementArduinoCloudCertificate.h index f6a1284..0315901 100644 --- a/src/utility/SElementArduinoCloudCertificate.h +++ b/src/utility/SElementArduinoCloudCertificate.h @@ -28,6 +28,10 @@ class SElementArduinoCloudCertificate : public SElementCertificate static int write(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot); static int read(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot, const SElementArduinoCloudSlot keySlot = SElementArduinoCloudSlot::Key); + static int rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, + const String & notBefore, const String & notAfter, const String & serialNumber, + const String & authorityKeyIdentifier, const String & signature, + const SElementArduinoCloudSlot keySlot = SElementArduinoCloudSlot::Key); }; From 0a4d121942d971bd969c12d8388d69d03752f0fb Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 8 Jan 2025 18:37:23 +0100 Subject: [PATCH 02/13] Add function to get authorityKeyId from certificate --- src/ECP256Certificate.cpp | 13 +++++++++++++ src/ECP256Certificate.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/ECP256Certificate.cpp b/src/ECP256Certificate.cpp index 1cf5de5..627a0f4 100644 --- a/src/ECP256Certificate.cpp +++ b/src/ECP256Certificate.cpp @@ -12,6 +12,8 @@ * INCLUDE ******************************************************************************/ +#define _GNU_SOURCE +#include #include "ECP256Certificate.h" /****************************************************************************** @@ -384,6 +386,17 @@ int ECP256Certificate::setSignature(const byte* signature, int signatureLen) { return 0; } +const byte * ECP256Certificate::authorityKeyId() const { + static const byte objectId[] = {0x06, 0x03, 0x55, 0x1D, 0x23}; + byte * result = nullptr; + void * ptr = memmem(_certBuffer, _certBufferLen, objectId, sizeof(objectId)); + if (ptr != nullptr) { + result = (byte*)ptr; + result += 11; + } + return result; +} + /****************************************************************************** * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ diff --git a/src/ECP256Certificate.h b/src/ECP256Certificate.h index 4e065df..d4c6f62 100644 --- a/src/ECP256Certificate.h +++ b/src/ECP256Certificate.h @@ -68,6 +68,9 @@ class ECP256Certificate { inline byte* bytes() { return _certBuffer; } inline int length() { return _certBufferLen; } + /* Parsing Helpers */ + const byte * authorityKeyId() const; + #if defined(SECURE_ELEMENT_IS_ECCX08) /* Get Data to create ECCX08 compressed cert */ inline byte* compressedCertBytes() { return _compressedCert.data; } From 708376e041d69b3fced749c20737277fc62da6f8 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 8 Jan 2025 18:40:04 +0100 Subject: [PATCH 03/13] Use Arduino_DebugUtils if already included in the build --- src/SecureElementConfig.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/SecureElementConfig.h b/src/SecureElementConfig.h index 12815d0..064afb7 100644 --- a/src/SecureElementConfig.h +++ b/src/SecureElementConfig.h @@ -29,4 +29,30 @@ #define SECURE_ELEMENT_IS_SOFTSE #endif +#if defined __has_include + #if __has_include () + #include + #endif +#endif + +#ifndef DEBUG_ERROR + #define DEBUG_ERROR(fmt, ...) +#endif + +#ifndef DEBUG_WARNING + #define DEBUG_WARNING(fmt, ...) +#endif + +#ifndef DEBUG_INFO + #define DEBUG_INFO(fmt, ...) +#endif + +#ifndef DEBUG_DEBUG + #define DEBUG_DEBUG(fmt, ...) +#endif + +#ifndef DEBUG_VERBOSE + #define DEBUG_VERBOSE(fmt, ...) +#endif + #endif /* SECURE_ELEMENT_CONFIG_H_ */ From 431e86a1ac99cefebfa8eeed56a67f028422abd3 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 10 Jan 2025 14:49:04 +0100 Subject: [PATCH 04/13] Add function to compare certificate authority key identifier --- .../SElementArduinoCloudCertificate.cpp | 19 +++++++++++++++++++ src/utility/SElementArduinoCloudCertificate.h | 1 + 2 files changed, 20 insertions(+) diff --git a/src/utility/SElementArduinoCloudCertificate.cpp b/src/utility/SElementArduinoCloudCertificate.cpp index b505128..799d48b 100644 --- a/src/utility/SElementArduinoCloudCertificate.cpp +++ b/src/utility/SElementArduinoCloudCertificate.cpp @@ -117,6 +117,25 @@ int SElementArduinoCloudCertificate::read(SecureElement & se, ECP256Certificate return 1; } +int SElementArduinoCloudCertificate::isAuthorityKeyIdDifferent(const ECP256Certificate & cert, const String & authorityKeyIdentifier) +{ + byte authorityKeyIdentifierBytes[ECP256_CERT_AUTHORITY_KEY_ID_LENGTH]; + + if (authorityKeyIdentifier.length() == 0 || cert.authorityKeyId() == nullptr) { + DEBUG_ERROR("SEACC::%s input params error.", __FUNCTION__); + return -1; + } + + hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); + + /* If authorityKeyId are matching there is no need to rebuild*/ + if (memcmp(authorityKeyIdentifierBytes, cert.authorityKeyId() , ECP256_CERT_AUTHORITY_KEY_ID_LENGTH) == 0) { + DEBUG_VERBOSE("SEACC::%s authorityKeyIdentifierBytes are equal", __FUNCTION__); + return 0; + } + return 1; +} + int SElementArduinoCloudCertificate::rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, const String & authorityKeyIdentifier, const String & signature, const SElementArduinoCloudSlot keySlot) { byte serialNumberBytes[ECP256_CERT_SERIAL_NUMBER_LENGTH]; diff --git a/src/utility/SElementArduinoCloudCertificate.h b/src/utility/SElementArduinoCloudCertificate.h index 0315901..319b12c 100644 --- a/src/utility/SElementArduinoCloudCertificate.h +++ b/src/utility/SElementArduinoCloudCertificate.h @@ -28,6 +28,7 @@ class SElementArduinoCloudCertificate : public SElementCertificate static int write(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot); static int read(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot, const SElementArduinoCloudSlot keySlot = SElementArduinoCloudSlot::Key); + static int isAuthorityKeyIdDifferent(const ECP256Certificate & cert, const String & authorityKeyIdentifier); static int rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, const String & authorityKeyIdentifier, const String & signature, From cd3eda55760c2543db7ae48310bbcb0046d2929a Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 15 Jan 2025 11:04:26 +0100 Subject: [PATCH 05/13] Add C O OU and CN const expressions --- .../SElementArduinoCloudCertificate.cpp | 25 +++++++++++++------ src/utility/SElementArduinoCloudCertificate.h | 7 ++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/utility/SElementArduinoCloudCertificate.cpp b/src/utility/SElementArduinoCloudCertificate.cpp index 799d48b..5f82e7e 100644 --- a/src/utility/SElementArduinoCloudCertificate.cpp +++ b/src/utility/SElementArduinoCloudCertificate.cpp @@ -34,6 +34,15 @@ static void hexStringToBytes(String in, byte out[], int length) { } } +/****************************************************************************** + * STATIC MEMBER DEFINITIONS + ******************************************************************************/ + +const char constexpr SElementArduinoCloudCertificate::SEACC_ISSUER_COUNTRY_NAME[]; +const char constexpr SElementArduinoCloudCertificate::SEACC_ISSUER_ORGANIZATION_NAME[]; +const char constexpr SElementArduinoCloudCertificate::SEACC_ISSUER_ORGANIZATIONAL_UNIT_NAME[]; +const char constexpr SElementArduinoCloudCertificate::SEACC_ISSUER_COMMON_NAME[]; + /****************************************************************************** * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ @@ -97,10 +106,10 @@ int SElementArduinoCloudCertificate::read(SecureElement & se, ECP256Certificate } cert.setSubjectCommonName(deviceId); - cert.setIssuerCountryName("US"); - cert.setIssuerOrganizationName("Arduino LLC US"); - cert.setIssuerOrganizationalUnitName("IT"); - cert.setIssuerCommonName("Arduino"); + cert.setIssuerCountryName(SEACC_ISSUER_COUNTRY_NAME); + cert.setIssuerOrganizationName(SEACC_ISSUER_ORGANIZATION_NAME); + cert.setIssuerOrganizationalUnitName(SEACC_ISSUER_ORGANIZATIONAL_UNIT_NAME); + cert.setIssuerCommonName(SEACC_ISSUER_COMMON_NAME); if (!cert.setPublicKey(publicKey, ECP256_CERT_PUBLIC_KEY_LENGTH)) { return 0; @@ -157,10 +166,10 @@ int SElementArduinoCloudCertificate::rebuild(SecureElement & se, ECP256Certifica } cert.setSubjectCommonName(deviceId); - cert.setIssuerCountryName("US"); - cert.setIssuerOrganizationName("Arduino LLC US"); - cert.setIssuerOrganizationalUnitName("IT"); - cert.setIssuerCommonName("Arduino"); + cert.setIssuerCountryName(SEACC_ISSUER_COUNTRY_NAME); + cert.setIssuerOrganizationName(SEACC_ISSUER_ORGANIZATION_NAME); + cert.setIssuerOrganizationalUnitName(SEACC_ISSUER_ORGANIZATIONAL_UNIT_NAME); + cert.setIssuerCommonName(SEACC_ISSUER_COMMON_NAME); cert.setSignature(signatureBytes, sizeof(signatureBytes)); cert.setAuthorityKeyId(authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); cert.setSerialNumber(serialNumberBytes, sizeof(serialNumberBytes)); diff --git a/src/utility/SElementArduinoCloudCertificate.h b/src/utility/SElementArduinoCloudCertificate.h index 319b12c..19244fe 100644 --- a/src/utility/SElementArduinoCloudCertificate.h +++ b/src/utility/SElementArduinoCloudCertificate.h @@ -34,6 +34,13 @@ class SElementArduinoCloudCertificate : public SElementCertificate const String & authorityKeyIdentifier, const String & signature, const SElementArduinoCloudSlot keySlot = SElementArduinoCloudSlot::Key); +private: + + static const char constexpr SEACC_ISSUER_COUNTRY_NAME[] = "US"; + static const char constexpr SEACC_ISSUER_ORGANIZATION_NAME[] = "Arduino LLC US"; + static const char constexpr SEACC_ISSUER_ORGANIZATIONAL_UNIT_NAME[] = "IT"; + static const char constexpr SEACC_ISSUER_COMMON_NAME[] = "Arduino"; + }; #endif /* SECURE_ELEMENT_ARDUINO_CLOUD_CERTIFICATE_H_ */ \ No newline at end of file From c5aebc6fc1827266633968bbff5bb9fd8f9b022b Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Jan 2025 10:46:04 +0100 Subject: [PATCH 06/13] Add functions to import signature and key id to compressed cert struct --- src/ECP256Certificate.cpp | 79 +++++++++++++++++++++++++++++++++++++++ src/ECP256Certificate.h | 3 ++ 2 files changed, 82 insertions(+) diff --git a/src/ECP256Certificate.cpp b/src/ECP256Certificate.cpp index 627a0f4..a00b491 100644 --- a/src/ECP256Certificate.cpp +++ b/src/ECP256Certificate.cpp @@ -302,6 +302,16 @@ int ECP256Certificate::importCert(const byte certDER[], size_t derLen) memcpy(_certBuffer, certDER, _certBufferLen); + /* Import Authority Key Identifier to compressed cert struct */ + if (!importCompressedAuthorityKeyIdentifier()) { + return 0; + } + + /* Import signature to compressed cert struct */ + if (!importCompressedSignature()) { + return 0; + } + return 1; } @@ -914,3 +924,72 @@ int ECP256Certificate::appendAuthorityKeyId(const byte authorityKeyId[], int len return length + 17; } + +int ECP256Certificate::importCompressedAuthorityKeyIdentifier() { + static const byte objectId[] = {0x06, 0x03, 0x55, 0x1D, 0x23}; + byte * result = nullptr; + void * ptr = memmem(_certBuffer, _certBufferLen, objectId, sizeof(objectId)); + if (ptr != nullptr) { + result = (byte*)ptr; + result += 11; + memcpy(_compressedCert.slot.two.values.authorityKeyId, result, ECP256_CERT_AUTHORITY_KEY_ID_LENGTH); + return 1; + } + return 0; +} + +int ECP256Certificate::importCompressedSignature() { + byte * result = nullptr; + byte paddingBytes = 0; + byte rLen = 0; + byte sLen = 0; + + /* Search AuthorityKeyIdentifier */ + static const byte KeyId[] = {0x06, 0x03, 0x55, 0x1D, 0x23}; + void * ptr = memmem(_certBuffer, _certBufferLen, KeyId, sizeof(KeyId)); + if(ptr == nullptr) { + return 0; + } + result = (byte*)ptr; + + /* Search Algorithm identifier */ + static const byte AlgId[] = {0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02}; + ptr = memmem(result, _certBufferLen - (_certBuffer - result), AlgId, sizeof(AlgId)); + if(ptr == nullptr) { + return 0; + } + result = (byte*)ptr; + + /* Skip algorithm identifier */ + result += sizeof(AlgId); + + /* Search signature sequence */ + if (result[0] == 0x03) { + /* Move to the first element of R sequence skipping 0x03 0x49 0x00 0x30 0xXX*/ + result += 5; + /* Check if value is padded */ + if (result[0] == 0x02 && result[1] == 0x21 && result[2] == 0x00) { + paddingBytes = 1; + } + rLen = result[1] - paddingBytes; + /* Skip padding and ASN INTEGER sequence 0x02 0xXX */ + result += (2 + paddingBytes); + /* Copy data to compressed slot */ + memcpy(_compressedCert.slot.one.values.signature, result, rLen); + /* reset padding before importing S sequence */ + paddingBytes = 0; + /* Move to the first element of S sequence skipping R values */ + result += rLen; + /* Check if value is padded */ + if (result[0] == 0x02 && result[1] == 0x21 && result[2] == 0x00) { + paddingBytes = 1; + } + sLen = result[1] - paddingBytes; + /* Skip padding and ASN INTEGER sequence 0x02 0xXX */ + result += (2 + paddingBytes); + /* Copy data to compressed slot */ + memcpy(&_compressedCert.slot.one.values.signature[rLen], result, sLen); + return 1; + } + return 0; +} diff --git a/src/ECP256Certificate.h b/src/ECP256Certificate.h index d4c6f62..8733a2f 100644 --- a/src/ECP256Certificate.h +++ b/src/ECP256Certificate.h @@ -176,6 +176,9 @@ class ECP256Certificate { int appendEcdsaWithSHA256(byte out[]); int appendAuthorityKeyId(const byte authorityKeyId[], int length, byte out[]); + int importCompressedAuthorityKeyIdentifier(); + int importCompressedSignature(); + }; #endif /* ECP256_CERTIFICATE_H */ From 82977c568ac6445122b774cfaba181ef3c99b470 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Jan 2025 10:46:38 +0100 Subject: [PATCH 07/13] Add functions to read signature and key id from compressed struct --- src/ECP256Certificate.cpp | 1 + src/ECP256Certificate.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/ECP256Certificate.cpp b/src/ECP256Certificate.cpp index a00b491..af14bfe 100644 --- a/src/ECP256Certificate.cpp +++ b/src/ECP256Certificate.cpp @@ -12,6 +12,7 @@ * INCLUDE ******************************************************************************/ +/* This is neededn for memmem */ #define _GNU_SOURCE #include #include "ECP256Certificate.h" diff --git a/src/ECP256Certificate.h b/src/ECP256Certificate.h index 8733a2f..6b0e676 100644 --- a/src/ECP256Certificate.h +++ b/src/ECP256Certificate.h @@ -84,6 +84,9 @@ class ECP256Certificate { inline byte* subjectCommonNameBytes() { return (byte*)_subjectData.commonName.begin(); } inline int subjectCommonNameLenght() {return _subjectData.commonName.length(); } + inline const byte* authorityKeyIdentifierBytes() { return _compressedCert.slot.two.values.authorityKeyId; } + inline const byte* signatureBytes() { return _compressedCert.slot.one.values.signature; } + /* Build CSR */ int buildCSR(); int signCSR(byte signature[]); From 85cb540bb22a8cc5e5470c754ca3611faf4dabd9 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Jan 2025 10:56:04 +0100 Subject: [PATCH 08/13] Add function to compare certificate signature --- .../SElementArduinoCloudCertificate.cpp | 19 +++++++++++++++++++ src/utility/SElementArduinoCloudCertificate.h | 1 + 2 files changed, 20 insertions(+) diff --git a/src/utility/SElementArduinoCloudCertificate.cpp b/src/utility/SElementArduinoCloudCertificate.cpp index 5f82e7e..c231023 100644 --- a/src/utility/SElementArduinoCloudCertificate.cpp +++ b/src/utility/SElementArduinoCloudCertificate.cpp @@ -126,6 +126,25 @@ int SElementArduinoCloudCertificate::read(SecureElement & se, ECP256Certificate return 1; } +int SElementArduinoCloudCertificate::signatureCompare(const byte * signatureA, const String & signatureB) +{ + byte signatureBytes[ECP256_CERT_SIGNATURE_LENGTH]; + + if (signatureB.length() == 0 || signatureA == nullptr) { + DEBUG_ERROR("SEACC::%s input params error.", __FUNCTION__); + return -1; + } + + hexStringToBytes(signatureB, signatureBytes, sizeof(signatureBytes)); + + /* If authorityKeyId are matching there is no need to rebuild*/ + if (memcmp(signatureBytes, signatureA , sizeof(signatureBytes)) == 0) { + DEBUG_VERBOSE("SEACC::%s signatures are equal", __FUNCTION__); + return 0; + } + return 1; +} + int SElementArduinoCloudCertificate::isAuthorityKeyIdDifferent(const ECP256Certificate & cert, const String & authorityKeyIdentifier) { byte authorityKeyIdentifierBytes[ECP256_CERT_AUTHORITY_KEY_ID_LENGTH]; diff --git a/src/utility/SElementArduinoCloudCertificate.h b/src/utility/SElementArduinoCloudCertificate.h index 19244fe..d269ecd 100644 --- a/src/utility/SElementArduinoCloudCertificate.h +++ b/src/utility/SElementArduinoCloudCertificate.h @@ -29,6 +29,7 @@ class SElementArduinoCloudCertificate : public SElementCertificate static int write(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot); static int read(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot, const SElementArduinoCloudSlot keySlot = SElementArduinoCloudSlot::Key); static int isAuthorityKeyIdDifferent(const ECP256Certificate & cert, const String & authorityKeyIdentifier); + static int signatureCompare(const byte * signatureA, const String & signatureB); static int rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, const String & authorityKeyIdentifier, const String & signature, From 5507b0cbdae473c3c2953dacc13e7720c018c79c Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Jan 2025 10:58:16 +0100 Subject: [PATCH 09/13] Remove isAuthorityKeyIdDifferent function --- .../SElementArduinoCloudCertificate.cpp | 19 ------------------- src/utility/SElementArduinoCloudCertificate.h | 1 - 2 files changed, 20 deletions(-) diff --git a/src/utility/SElementArduinoCloudCertificate.cpp b/src/utility/SElementArduinoCloudCertificate.cpp index c231023..ddf7599 100644 --- a/src/utility/SElementArduinoCloudCertificate.cpp +++ b/src/utility/SElementArduinoCloudCertificate.cpp @@ -145,25 +145,6 @@ int SElementArduinoCloudCertificate::signatureCompare(const byte * signatureA, c return 1; } -int SElementArduinoCloudCertificate::isAuthorityKeyIdDifferent(const ECP256Certificate & cert, const String & authorityKeyIdentifier) -{ - byte authorityKeyIdentifierBytes[ECP256_CERT_AUTHORITY_KEY_ID_LENGTH]; - - if (authorityKeyIdentifier.length() == 0 || cert.authorityKeyId() == nullptr) { - DEBUG_ERROR("SEACC::%s input params error.", __FUNCTION__); - return -1; - } - - hexStringToBytes(authorityKeyIdentifier, authorityKeyIdentifierBytes, sizeof(authorityKeyIdentifierBytes)); - - /* If authorityKeyId are matching there is no need to rebuild*/ - if (memcmp(authorityKeyIdentifierBytes, cert.authorityKeyId() , ECP256_CERT_AUTHORITY_KEY_ID_LENGTH) == 0) { - DEBUG_VERBOSE("SEACC::%s authorityKeyIdentifierBytes are equal", __FUNCTION__); - return 0; - } - return 1; -} - int SElementArduinoCloudCertificate::rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, const String & authorityKeyIdentifier, const String & signature, const SElementArduinoCloudSlot keySlot) { byte serialNumberBytes[ECP256_CERT_SERIAL_NUMBER_LENGTH]; diff --git a/src/utility/SElementArduinoCloudCertificate.h b/src/utility/SElementArduinoCloudCertificate.h index d269ecd..d20559a 100644 --- a/src/utility/SElementArduinoCloudCertificate.h +++ b/src/utility/SElementArduinoCloudCertificate.h @@ -28,7 +28,6 @@ class SElementArduinoCloudCertificate : public SElementCertificate static int write(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot); static int read(SecureElement & se, ECP256Certificate & cert, const SElementArduinoCloudSlot certSlot, const SElementArduinoCloudSlot keySlot = SElementArduinoCloudSlot::Key); - static int isAuthorityKeyIdDifferent(const ECP256Certificate & cert, const String & authorityKeyIdentifier); static int signatureCompare(const byte * signatureA, const String & signatureB); static int rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, From 70defd8905019a4f8a23c3d20e93b3e307770479 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Jan 2025 11:00:24 +0100 Subject: [PATCH 10/13] Remove ECP256Certificate::authorityKeyId function --- src/ECP256Certificate.cpp | 11 ----------- src/ECP256Certificate.h | 3 --- 2 files changed, 14 deletions(-) diff --git a/src/ECP256Certificate.cpp b/src/ECP256Certificate.cpp index af14bfe..4f40b44 100644 --- a/src/ECP256Certificate.cpp +++ b/src/ECP256Certificate.cpp @@ -397,17 +397,6 @@ int ECP256Certificate::setSignature(const byte* signature, int signatureLen) { return 0; } -const byte * ECP256Certificate::authorityKeyId() const { - static const byte objectId[] = {0x06, 0x03, 0x55, 0x1D, 0x23}; - byte * result = nullptr; - void * ptr = memmem(_certBuffer, _certBufferLen, objectId, sizeof(objectId)); - if (ptr != nullptr) { - result = (byte*)ptr; - result += 11; - } - return result; -} - /****************************************************************************** * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ diff --git a/src/ECP256Certificate.h b/src/ECP256Certificate.h index 6b0e676..68a4c36 100644 --- a/src/ECP256Certificate.h +++ b/src/ECP256Certificate.h @@ -68,9 +68,6 @@ class ECP256Certificate { inline byte* bytes() { return _certBuffer; } inline int length() { return _certBufferLen; } - /* Parsing Helpers */ - const byte * authorityKeyId() const; - #if defined(SECURE_ELEMENT_IS_ECCX08) /* Get Data to create ECCX08 compressed cert */ inline byte* compressedCertBytes() { return _compressedCert.data; } From a7b46681bd117f08c9df5568000a030d9fe030bc Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 17 Jan 2025 14:34:45 +0100 Subject: [PATCH 11/13] Fix typo in comments --- src/ECP256Certificate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ECP256Certificate.cpp b/src/ECP256Certificate.cpp index 4f40b44..b5fe3a5 100644 --- a/src/ECP256Certificate.cpp +++ b/src/ECP256Certificate.cpp @@ -12,7 +12,7 @@ * INCLUDE ******************************************************************************/ -/* This is neededn for memmem */ +/* This is needed for memmem */ #define _GNU_SOURCE #include #include "ECP256Certificate.h" From d0e0ecdd076194c769a7bd56551cb63d44d7e293 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 22 Jan 2025 09:17:24 +0100 Subject: [PATCH 12/13] Add check on signature length --- src/ECP256Certificate.cpp | 8 ++++++++ src/ECP256Certificate.h | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ECP256Certificate.cpp b/src/ECP256Certificate.cpp index b5fe3a5..e146a2f 100644 --- a/src/ECP256Certificate.cpp +++ b/src/ECP256Certificate.cpp @@ -964,6 +964,10 @@ int ECP256Certificate::importCompressedSignature() { rLen = result[1] - paddingBytes; /* Skip padding and ASN INTEGER sequence 0x02 0xXX */ result += (2 + paddingBytes); + /* Check data length */ + if (rLen != ECP256_CERT_SIGNATURE_R_LENGTH) { + return 0; + } /* Copy data to compressed slot */ memcpy(_compressedCert.slot.one.values.signature, result, rLen); /* reset padding before importing S sequence */ @@ -977,6 +981,10 @@ int ECP256Certificate::importCompressedSignature() { sLen = result[1] - paddingBytes; /* Skip padding and ASN INTEGER sequence 0x02 0xXX */ result += (2 + paddingBytes); + /* Check data length */ + if (sLen != ECP256_CERT_SIGNATURE_S_LENGTH) { + return 0; + } /* Copy data to compressed slot */ memcpy(&_compressedCert.slot.one.values.signature[rLen], result, sLen); return 1; diff --git a/src/ECP256Certificate.h b/src/ECP256Certificate.h index 68a4c36..2be7c5c 100644 --- a/src/ECP256Certificate.h +++ b/src/ECP256Certificate.h @@ -22,10 +22,12 @@ #define ECP256_CERT_SERIAL_NUMBER_LENGTH 16 #define ECP256_CERT_AUTHORITY_KEY_ID_LENGTH 20 #define ECP256_CERT_PUBLIC_KEY_LENGTH 64 -#define ECP256_CERT_SIGNATURE_LENGTH 64 +#define ECP256_CERT_SIGNATURE_R_LENGTH 32 +#define ECP256_CERT_SIGNATURE_S_LENGTH ECP256_CERT_SIGNATURE_R_LENGTH +#define ECP256_CERT_SIGNATURE_LENGTH (ECP256_CERT_SIGNATURE_R_LENGTH + ECP256_CERT_SIGNATURE_S_LENGTH) #define ECP256_CERT_DATES_LENGTH 3 #define ECP256_CERT_COMPRESSED_CERT_SLOT_LENGTH 72 -#define ECP256_CERT_COMPRESSED_CERT_LENGTH ECP256_CERT_COMPRESSED_CERT_SLOT_LENGTH + ECP256_CERT_SERIAL_NUMBER_LENGTH + ECP256_CERT_AUTHORITY_KEY_ID_LENGTH +#define ECP256_CERT_COMPRESSED_CERT_LENGTH (ECP256_CERT_COMPRESSED_CERT_SLOT_LENGTH + ECP256_CERT_SERIAL_NUMBER_LENGTH + ECP256_CERT_AUTHORITY_KEY_ID_LENGTH) #include From b94975b4ad9d9f8e218e27415b7fa367f45096bf Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Wed, 22 Jan 2025 09:21:13 +0100 Subject: [PATCH 13/13] Change rebuild function parameters formatting Co-authored-by: Andrea Gilardoni <4046444+andreagilardoni@users.noreply.github.com> --- src/utility/SElementArduinoCloudCertificate.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utility/SElementArduinoCloudCertificate.cpp b/src/utility/SElementArduinoCloudCertificate.cpp index ddf7599..598e5a5 100644 --- a/src/utility/SElementArduinoCloudCertificate.cpp +++ b/src/utility/SElementArduinoCloudCertificate.cpp @@ -145,7 +145,11 @@ int SElementArduinoCloudCertificate::signatureCompare(const byte * signatureA, c return 1; } -int SElementArduinoCloudCertificate::rebuild(SecureElement & se, ECP256Certificate & cert, const String & deviceId, const String & notBefore, const String & notAfter, const String & serialNumber, const String & authorityKeyIdentifier, const String & signature, const SElementArduinoCloudSlot keySlot) +int SElementArduinoCloudCertificate::rebuild( + SecureElement & se, ECP256Certificate & cert, const String & deviceId, + const String & notBefore, const String & notAfter, const String & serialNumber, + const String & authorityKeyIdentifier, const String & signature, + const SElementArduinoCloudSlot keySlot) { byte serialNumberBytes[ECP256_CERT_SERIAL_NUMBER_LENGTH]; byte authorityKeyIdentifierBytes[ECP256_CERT_AUTHORITY_KEY_ID_LENGTH];