clang-format: copy latest and re-format
clang-format-17 has some backwards incompatible changes that require
additional settings for best compatibility and re-running the formatter.
Copy the latest .clang-format from the docs repository and reformat the
repository.
Change-Id: I4610d1d37873b2019baa2ae22c036f81f4319214
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/.clang-format b/.clang-format
index d92a3f1..d43e884 100644
--- a/.clang-format
+++ b/.clang-format
@@ -14,26 +14,30 @@
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
-AllowShortIfStatementsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLambdasOnASingleLine: true
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
+BitFieldColonSpacing: None
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
+ AfterExternBlock: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
- AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
+ BeforeLambdaBody: false
+ BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
@@ -48,17 +52,16 @@
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
-DeriveLineEnding: false
DerivePointerAlignment: false
-PointerAlignment: Left
DisableFormat: false
-ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
-ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^[<"](gtest|gmock)'
@@ -78,6 +81,7 @@
- Regex: '.*'
Priority: 6
IndentCaseLabels: true
+IndentExternBlock: NoIndent
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: true
@@ -92,6 +96,7 @@
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
+PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 25
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
@@ -100,12 +105,13 @@
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
+PointerAlignment: Left
QualifierAlignment: Left
ReferenceAlignment: Left
ReflowComments: true
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: Keyword
-SortIncludes: true
+SortIncludes: CaseSensitive
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
@@ -117,7 +123,7 @@
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
+SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
diff --git a/subprojects/dhcp-done/dhcp-done.cpp b/subprojects/dhcp-done/dhcp-done.cpp
index 818915e..00c0e3b 100644
--- a/subprojects/dhcp-done/dhcp-done.cpp
+++ b/subprojects/dhcp-done/dhcp-done.cpp
@@ -79,7 +79,7 @@
{
stdplus::fd::sendExact(*fd, data, stdplus::fd::SendFlags(0));
}
- });
+ });
return event.loop();
}
catch (const std::exception& e)
diff --git a/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h b/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h
index 8a673b2..4bf30ca 100644
--- a/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h
+++ b/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h
@@ -34,185 +34,186 @@
// Currently RSA4096 (in bytes).
#define LIBCR51SIGN_MAX_SIGNATURE_SIZE 512
- // List of common error codes that can be returned
- enum libcr51sign_validation_failure_reason
- {
- // All PayloadRegionState fields are valid & authenticated.
- LIBCR51SIGN_SUCCESS = 0,
+// List of common error codes that can be returned
+enum libcr51sign_validation_failure_reason
+{
+ // All PayloadRegionState fields are valid & authenticated.
+ LIBCR51SIGN_SUCCESS = 0,
- // Descriptor sanity check failed. None of the following
- // PayloadRegionState fields are valid/populated.
- LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
- LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR = 2,
- LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
+ // Descriptor sanity check failed. None of the following
+ // PayloadRegionState fields are valid/populated.
+ LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
+ LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR = 2,
+ LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
- // All fields are populated but may not be authentic.
- LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
- LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
- LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED = 6,
- LIBCR51SIGN_ERROR_UNTRUSTED_KEY = 7,
- LIBCR51SIGN_ERROR_INVALID_SIGNATURE = 8,
- LIBCR51SIGN_ERROR_INVALID_HASH = 9,
- LIBCR51SIGN_ERROR_INVALID_HASH_TYPE = 10,
- // Invalid argument
- LIBCR51SIGN_ERROR_INVALID_ARGUMENT = 11,
- LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC = 12,
- LIBCR51SIGN_ERROR_INVALID_CONTEXT = 13,
- LIBCR51SIGN_ERROR_INVALID_INTERFACE = 14,
- LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME = 15,
- LIBCR51SIGN_ERROR_MAX = 16,
- // Invalid image region
- LIBCR51SIGN_ERROR_INVALID_REGION_INPUT = 17,
- LIBCR51SIGN_ERROR_INVALID_REGION_SIZE = 18,
- };
+ // All fields are populated but may not be authentic.
+ LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
+ LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
+ LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED = 6,
+ LIBCR51SIGN_ERROR_UNTRUSTED_KEY = 7,
+ LIBCR51SIGN_ERROR_INVALID_SIGNATURE = 8,
+ LIBCR51SIGN_ERROR_INVALID_HASH = 9,
+ LIBCR51SIGN_ERROR_INVALID_HASH_TYPE = 10,
+ // Invalid argument
+ LIBCR51SIGN_ERROR_INVALID_ARGUMENT = 11,
+ LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC = 12,
+ LIBCR51SIGN_ERROR_INVALID_CONTEXT = 13,
+ LIBCR51SIGN_ERROR_INVALID_INTERFACE = 14,
+ LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME = 15,
+ LIBCR51SIGN_ERROR_MAX = 16,
+ // Invalid image region
+ LIBCR51SIGN_ERROR_INVALID_REGION_INPUT = 17,
+ LIBCR51SIGN_ERROR_INVALID_REGION_SIZE = 18,
+};
- struct libcr51sign_ctx
- {
- // Absolute image start offset
- uint32_t start_offset;
- // Absolute image end offset
- uint32_t end_offset;
- size_t block_size;
- enum image_family current_image_family;
- enum image_type current_image_type;
- // keyring_len - number of keys in @a keyring
- int keyring_len;
- // valid_key - index of valid key on success
- size_t* valid_key;
- // keyring - array of pointers to public keys
- const void* keyring;
- void* priv;
- struct image_descriptor descriptor;
- };
+struct libcr51sign_ctx
+{
+ // Absolute image start offset
+ uint32_t start_offset;
+ // Absolute image end offset
+ uint32_t end_offset;
+ size_t block_size;
+ enum image_family current_image_family;
+ enum image_type current_image_type;
+ // keyring_len - number of keys in @a keyring
+ int keyring_len;
+ // valid_key - index of valid key on success
+ size_t* valid_key;
+ // keyring - array of pointers to public keys
+ const void* keyring;
+ void* priv;
+ struct image_descriptor descriptor;
+};
- struct libcr51sign_intf
- {
- // @func read read data from the image into a buffer
- //
- // @param[in] ctx - context struct
- // @param[in] offset - bytes to seek into the image before reading
- // @param[in] count - number of bytes to read
- // @param[out] buf - pointer to buffer where result will be written
- //
- // @return nonzero on error, zero on success
-
- int (*read)(const void*, uint32_t, uint32_t, uint8_t*);
-
- // @func hash_init get ready to compute a hash
- //
- // @param[in] ctx - context struct
- // @param[in] hash_type - type of hash function to use
- //
- // @return nonzero on error, zero on success
-
- int (*hash_init)(const void*, enum hash_type);
-
- // @func hash_update add data to the hash
- //
- // @param[in] ctx - context struct
- // @param[in] buf - data to add to hash
- // @param[in] count - number of bytes of data to add
- // @param[in] hash_type - type of hash function to use
- //
- // @return nonzero on error, zero on success
-
- int (*hash_update)(void*, const uint8_t*, size_t);
-
- // Note this is a combination of an spi_nor_read() with
- // spi_transaction() It is the responsibility of the caller to
- // synchronize with other potential SPI clients / transactions.
- // Collapsing the SPI stack results in a 2x throughput improvement (~20s
- // -> ~10s to verify an Indus image with SHA256 HW acceleration).
- //
- // The caller is responsible for calling DCRYPTO_init()/HASH_final().
-
- int (*read_and_hash_update)(void* ctx, uint32_t offset, uint32_t size);
-
- // @func hash_final finish hash calculation
- //
- // @param[in] ctx - context struct
- // @param[out] hash - buffer to write hash to
- // @param[in] hash_type - type of hash function to use
- //
- // @return nonzero on error, zero on success
-
- int (*hash_final)(void*, uint8_t*);
-
- // @func verify check that the signature is valid for given hashed data
- //
- // @param[in] ctx - context struct
- // @param[in] scheme - type of signature, hash, etc.
- // @param[in] sig - signature blob
- // @param[in] sig_len - length of signature in bytes
- // @param[in] data - pre-hashed data to verify
- // @param[in] data_len - length of hashed data in bytes
- //
- // @return nonzero on error, zero on success
-
- int (*verify_signature)(const void*, enum signature_scheme,
- const uint8_t*, size_t, const uint8_t*, size_t);
-
- // @func verify check that if the prod to dev downgrade/ hardware
- // allowlist is allowed
- // @return true: if allowed
- // false: if not allowed
- // BMC would return always false or pass a NULL pointer
- // If NULL, treated as if the function always returns false.
-
- bool (*prod_to_dev_downgrade_allowed)();
-
- // @func returns true if the current firmware is running in production
- // mode.
- // @return true: if in production mode
- // false: if in any non-production mode
-
- bool (*is_production_mode)();
-
- // @func returns true if the descriptor image size is valid.
- bool (*image_size_valid)(size_t);
- };
-
- struct libcr51sign_validated_regions
- {
- uint32_t region_count;
- struct image_region image_regions[LIBCR51SIGN_MAX_REGION_COUNT];
- };
-
- // Check whether the signature on the image is valid.
- // Validates the authenticity of an EEPROM image. Scans for & validates the
- // signature on the image descriptor. If the descriptor validates, hashes
- // the rest of the image to verify its integrity.
+struct libcr51sign_intf
+{
+ // @func read read data from the image into a buffer
//
- // @param[in] ctx - context which describes the image and holds opaque
- // private
- // data for the user of the library
- // @param[in] intf - function pointers which interface to the current system
- // and environment
- // @param[out] image_regions - image_region pointer to an array for the
- // output
+ // @param[in] ctx - context struct
+ // @param[in] offset - bytes to seek into the image before reading
+ // @param[in] count - number of bytes to read
+ // @param[out] buf - pointer to buffer where result will be written
//
// @return nonzero on error, zero on success
- enum libcr51sign_validation_failure_reason libcr51sign_validate(
- const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
- struct libcr51sign_validated_regions* image_regions);
+ int (*read)(const void*, uint32_t, uint32_t, uint8_t*);
- // Function to convert error code to string format
- // @param[in] ec - error code
- // @return error code in string format
-
- const char* libcr51sign_errorcode_to_string(
- enum libcr51sign_validation_failure_reason ec);
-
- // Returns the hash_type for a given signature scheme
- // @param[in] scheme - signature scheme
- // @param[out] type - hash_type supported by given signature_scheme
+ // @func hash_init get ready to compute a hash
+ //
+ // @param[in] ctx - context struct
+ // @param[in] hash_type - type of hash function to use
//
// @return nonzero on error, zero on success
- enum libcr51sign_validation_failure_reason
- get_hash_type_from_signature(enum signature_scheme scheme,
- enum hash_type* type);
+ int (*hash_init)(const void*, enum hash_type);
+
+ // @func hash_update add data to the hash
+ //
+ // @param[in] ctx - context struct
+ // @param[in] buf - data to add to hash
+ // @param[in] count - number of bytes of data to add
+ // @param[in] hash_type - type of hash function to use
+ //
+ // @return nonzero on error, zero on success
+
+ int (*hash_update)(void*, const uint8_t*, size_t);
+
+ // Note this is a combination of an spi_nor_read() with
+ // spi_transaction() It is the responsibility of the caller to
+ // synchronize with other potential SPI clients / transactions.
+ // Collapsing the SPI stack results in a 2x throughput improvement (~20s
+ // -> ~10s to verify an Indus image with SHA256 HW acceleration).
+ //
+ // The caller is responsible for calling DCRYPTO_init()/HASH_final().
+
+ int (*read_and_hash_update)(void* ctx, uint32_t offset, uint32_t size);
+
+ // @func hash_final finish hash calculation
+ //
+ // @param[in] ctx - context struct
+ // @param[out] hash - buffer to write hash to
+ // @param[in] hash_type - type of hash function to use
+ //
+ // @return nonzero on error, zero on success
+
+ int (*hash_final)(void*, uint8_t*);
+
+ // @func verify check that the signature is valid for given hashed data
+ //
+ // @param[in] ctx - context struct
+ // @param[in] scheme - type of signature, hash, etc.
+ // @param[in] sig - signature blob
+ // @param[in] sig_len - length of signature in bytes
+ // @param[in] data - pre-hashed data to verify
+ // @param[in] data_len - length of hashed data in bytes
+ //
+ // @return nonzero on error, zero on success
+
+ int (*verify_signature)(const void*, enum signature_scheme, const uint8_t*,
+ size_t, const uint8_t*, size_t);
+
+ // @func verify check that if the prod to dev downgrade/ hardware
+ // allowlist is allowed
+ // @return true: if allowed
+ // false: if not allowed
+ // BMC would return always false or pass a NULL pointer
+ // If NULL, treated as if the function always returns false.
+
+ bool (*prod_to_dev_downgrade_allowed)();
+
+ // @func returns true if the current firmware is running in production
+ // mode.
+ // @return true: if in production mode
+ // false: if in any non-production mode
+
+ bool (*is_production_mode)();
+
+ // @func returns true if the descriptor image size is valid.
+ bool (*image_size_valid)(size_t);
+};
+
+struct libcr51sign_validated_regions
+{
+ uint32_t region_count;
+ struct image_region image_regions[LIBCR51SIGN_MAX_REGION_COUNT];
+};
+
+// Check whether the signature on the image is valid.
+// Validates the authenticity of an EEPROM image. Scans for & validates the
+// signature on the image descriptor. If the descriptor validates, hashes
+// the rest of the image to verify its integrity.
+//
+// @param[in] ctx - context which describes the image and holds opaque
+// private
+// data for the user of the library
+// @param[in] intf - function pointers which interface to the current system
+// and environment
+// @param[out] image_regions - image_region pointer to an array for the
+// output
+//
+// @return nonzero on error, zero on success
+
+enum libcr51sign_validation_failure_reason
+ libcr51sign_validate(const struct libcr51sign_ctx* ctx,
+ struct libcr51sign_intf* intf,
+ struct libcr51sign_validated_regions* image_regions);
+
+// Function to convert error code to string format
+// @param[in] ec - error code
+// @return error code in string format
+
+const char* libcr51sign_errorcode_to_string(
+ enum libcr51sign_validation_failure_reason ec);
+
+// Returns the hash_type for a given signature scheme
+// @param[in] scheme - signature scheme
+// @param[out] type - hash_type supported by given signature_scheme
+//
+// @return nonzero on error, zero on success
+
+enum libcr51sign_validation_failure_reason
+ get_hash_type_from_signature(enum signature_scheme scheme,
+ enum hash_type* type);
#ifdef __cplusplus
} // extern "C"
diff --git a/subprojects/libcr51sign/include/libcr51sign/libcr51sign_support.h b/subprojects/libcr51sign/include/libcr51sign/libcr51sign_support.h
index 3a50628..ed0d2cb 100644
--- a/subprojects/libcr51sign/include/libcr51sign/libcr51sign_support.h
+++ b/subprojects/libcr51sign/include/libcr51sign/libcr51sign_support.h
@@ -23,58 +23,58 @@
{
#endif
- struct hash_ctx
+struct hash_ctx
+{
+ enum hash_type hash_type;
+ union
{
- enum hash_type hash_type;
- union
- {
- SHA256_CTX sha256_ctx;
- SHA512_CTX sha512_ctx;
- };
+ SHA256_CTX sha256_ctx;
+ SHA512_CTX sha512_ctx;
};
+};
- // @func hash_init get ready to compute a hash
- //
- // @param[in] ctx - context struct
- // @param[in] hash_type - type of hash function to use
- //
- // @return nonzero on error, zero on success
+// @func hash_init get ready to compute a hash
+//
+// @param[in] ctx - context struct
+// @param[in] hash_type - type of hash function to use
+//
+// @return nonzero on error, zero on success
- int hash_init(const void* ctx, enum hash_type type);
+int hash_init(const void* ctx, enum hash_type type);
- // @func hash_update add data to the hash
- //
- // @param[in] ctx - context struct
- // @param[in] buf - data to add to hash
- // @param[in] count - number of bytes of data to add
- //
- // @return nonzero on error, zero on success
+// @func hash_update add data to the hash
+//
+// @param[in] ctx - context struct
+// @param[in] buf - data to add to hash
+// @param[in] count - number of bytes of data to add
+//
+// @return nonzero on error, zero on success
- int hash_update(void* ctx, const uint8_t* data, size_t size);
+int hash_update(void* ctx, const uint8_t* data, size_t size);
- // @func hash_final finish hash calculation
- //
- // @param[in] ctx - context struct
- // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
- //
- // @return nonzero on error, zero on success
+// @func hash_final finish hash calculation
+//
+// @param[in] ctx - context struct
+// @param[out] hash - buffer to write hash to (guaranteed to be big enough)
+//
+// @return nonzero on error, zero on success
- int hash_final(void* ctx, uint8_t* hash);
+int hash_final(void* ctx, uint8_t* hash);
- // @func verify check that the signature is valid for given hashed data
- //
- // @param[in] ctx - context struct
- // @param[in] scheme - type of signature, hash, etc.
- // @param[in] sig - signature blob
- // @param[in] sig_len - length of signature in bytes
- // @param[in] data - pre-hashed data to verify
- // @param[in] data_len - length of hashed data in bytes
- //
- // @return nonzero on error, zero on success
+// @func verify check that the signature is valid for given hashed data
+//
+// @param[in] ctx - context struct
+// @param[in] scheme - type of signature, hash, etc.
+// @param[in] sig - signature blob
+// @param[in] sig_len - length of signature in bytes
+// @param[in] data - pre-hashed data to verify
+// @param[in] data_len - length of hashed data in bytes
+//
+// @return nonzero on error, zero on success
- int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
- const uint8_t* sig, size_t sig_len,
- const uint8_t* data, size_t data_len);
+int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
+ const uint8_t* sig, size_t sig_len, const uint8_t* data,
+ size_t data_len);
#ifdef __cplusplus
} // extern "C"
diff --git a/subprojects/libcr51sign/src/libcr51sign.c b/subprojects/libcr51sign/src/libcr51sign.c
index fff1826..75d8b70 100644
--- a/subprojects/libcr51sign/src/libcr51sign.c
+++ b/subprojects/libcr51sign/src/libcr51sign.c
@@ -53,943 +53,923 @@
#define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
#endif
- typedef enum libcr51sign_validation_failure_reason failure_reason;
+typedef enum libcr51sign_validation_failure_reason failure_reason;
- // Returns the bytes size of keys used in the given signature_scheme.
- // Return error if signature_scheme is invalid.
- //
- static failure_reason get_key_size(enum signature_scheme signature_scheme,
- uint16_t* key_size)
+// Returns the bytes size of keys used in the given signature_scheme.
+// Return error if signature_scheme is invalid.
+//
+static failure_reason get_key_size(enum signature_scheme signature_scheme,
+ uint16_t* key_size)
+{
+ switch (signature_scheme)
{
- switch (signature_scheme)
- {
- case SIGNATURE_RSA2048_PKCS15:
- *key_size = 256;
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA3072_PKCS15:
- *key_size = 384;
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA4096_PKCS15:
- case SIGNATURE_RSA4096_PKCS15_SHA512:
- *key_size = 512;
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
- }
+ case SIGNATURE_RSA2048_PKCS15:
+ *key_size = 256;
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA3072_PKCS15:
+ *key_size = 384;
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA4096_PKCS15:
+ case SIGNATURE_RSA4096_PKCS15_SHA512:
+ *key_size = 512;
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
+ }
+}
+
+// Returns the hash_type for a given signature scheme
+// Returns error if scheme is invalid.
+failure_reason get_hash_type_from_signature(enum signature_scheme scheme,
+ enum hash_type* type)
+{
+ switch (scheme)
+ {
+ case SIGNATURE_RSA2048_PKCS15:
+ case SIGNATURE_RSA3072_PKCS15:
+ case SIGNATURE_RSA4096_PKCS15:
+ *type = HASH_SHA2_256;
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA4096_PKCS15_SHA512:
+ *type = HASH_SHA2_512;
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
+ }
+}
+
+// Check if the given hash_type is supported.
+// Returns error if hash_type is not supported.
+static failure_reason is_hash_type_supported(enum hash_type type)
+{
+ switch (type)
+ {
+ case HASH_SHA2_256:
+ case HASH_SHA2_512:
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+ }
+}
+
+// Determines digest size for a given hash_type.
+// Returns error if hash_type is not supported.
+static failure_reason get_hash_digest_size(enum hash_type type, uint32_t* size)
+{
+ switch (type)
+ {
+ case HASH_SHA2_256:
+ *size = LIBCR51SIGN_SHA256_DIGEST_SIZE;
+ return LIBCR51SIGN_SUCCESS;
+ case HASH_SHA2_512:
+ *size = LIBCR51SIGN_SHA512_DIGEST_SIZE;
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+ }
+}
+
+// Determines hash struct size for a given hash_type.
+// Returns error if hash_type is not supported.
+static failure_reason get_hash_struct_size(enum hash_type type, uint32_t* size)
+{
+ switch (type)
+ {
+ case HASH_SHA2_256:
+ *size = sizeof(struct hash_sha256);
+ return LIBCR51SIGN_SUCCESS;
+ case HASH_SHA2_512:
+ *size = sizeof(struct hash_sha256);
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+ }
+}
+
+// Checks that:
+// - The signing key is trusted
+// - The target version is not denylisted
+// If validating a staged update, also checks that:
+// - The target image family matches the current image family
+// - The image type transition is legal (i.e. dev -> *|| prod -> prod) or
+// alternatively that the hardware ID is allowlisted
+// Assuming the caller has performed following:
+// board_get_base_key_index();
+// board_get_key_array
+// Possible return codes:
+// LIBCR51SIGN_SUCCESS = 0,
+// LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
+// LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
+// LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
+// LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
+
+static failure_reason validate_transition(const struct libcr51sign_ctx* ctx,
+ const struct libcr51sign_intf* intf,
+ uint32_t signature_struct_offset)
+{
+ BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) ==
+ SIGNATURE_OFFSET &&
+ offsetof(struct signature_rsa3072_pkcs15, modulus) ==
+ SIGNATURE_OFFSET &&
+ offsetof(struct signature_rsa4096_pkcs15, modulus) ==
+ SIGNATURE_OFFSET));
+
+ // Read up to the modulus.
+ enum
+ {
+ read_len = SIGNATURE_OFFSET
+ };
+ uint8_t buffer[read_len];
+ int rv;
+ rv = intf->read(ctx, signature_struct_offset, read_len, buffer);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_transition: failed to read signature struct\n");
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ if (*(uint32_t*)buffer != SIGNATURE_MAGIC)
+ {
+ CPRINTS(ctx, "validate_transition: bad signature magic\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
}
- // Returns the hash_type for a given signature scheme
- // Returns error if scheme is invalid.
- failure_reason get_hash_type_from_signature(enum signature_scheme scheme,
- enum hash_type* type)
+ if (ctx->descriptor.image_family != ctx->current_image_family &&
+ ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
+ ctx->current_image_family != IMAGE_FAMILY_ALL)
{
- switch (scheme)
- {
- case SIGNATURE_RSA2048_PKCS15:
- case SIGNATURE_RSA3072_PKCS15:
- case SIGNATURE_RSA4096_PKCS15:
- *type = HASH_SHA2_256;
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA4096_PKCS15_SHA512:
- *type = HASH_SHA2_512;
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
- }
+ CPRINTS(ctx, "validate_transition: invalid image family\n");
+ return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY;
}
- // Check if the given hash_type is supported.
- // Returns error if hash_type is not supported.
- static failure_reason is_hash_type_supported(enum hash_type type)
+ if (intf->is_production_mode == NULL)
{
- switch (type)
+ CPRINTS(ctx, "validate_transition: missing is_production_mode\n");
+ return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ }
+ if (intf->is_production_mode() && (ctx->descriptor.image_type == IMAGE_DEV))
+ {
+ CPRINTS(ctx, "validate_transition: checking exemption allowlist\n");
+
+ // If function is NULL or if the function call return false, return
+ // error
+ if (intf->prod_to_dev_downgrade_allowed == NULL ||
+ !intf->prod_to_dev_downgrade_allowed())
{
- case HASH_SHA2_256:
- case HASH_SHA2_512:
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+ CPRINTS(ctx, "validate_transition: illegal image type\n");
+ return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
}
}
+ return LIBCR51SIGN_SUCCESS;
+}
- // Determines digest size for a given hash_type.
- // Returns error if hash_type is not supported.
- static failure_reason get_hash_digest_size(enum hash_type type,
- uint32_t* size)
+// If caller had provided read_and_hash_update call that, otherwise call
+// read and then update.
+
+static failure_reason read_and_hash_update(const struct libcr51sign_ctx* ctx,
+ const struct libcr51sign_intf* intf,
+ uint32_t offset, uint32_t size)
+{
+ uint8_t read_buffer[MAX_READ_SIZE];
+ int rv;
+ int read_size;
+
+ if (intf->read_and_hash_update)
{
- switch (type)
- {
- case HASH_SHA2_256:
- *size = LIBCR51SIGN_SHA256_DIGEST_SIZE;
- return LIBCR51SIGN_SUCCESS;
- case HASH_SHA2_512:
- *size = LIBCR51SIGN_SHA512_DIGEST_SIZE;
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
- }
+ rv = intf->read_and_hash_update((void*)ctx, offset, size);
}
-
- // Determines hash struct size for a given hash_type.
- // Returns error if hash_type is not supported.
- static failure_reason get_hash_struct_size(enum hash_type type,
- uint32_t* size)
+ else
{
- switch (type)
+ if (!intf->hash_update)
{
- case HASH_SHA2_256:
- *size = sizeof(struct hash_sha256);
- return LIBCR51SIGN_SUCCESS;
- case HASH_SHA2_512:
- *size = sizeof(struct hash_sha256);
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
- }
- }
-
- // Checks that:
- // - The signing key is trusted
- // - The target version is not denylisted
- // If validating a staged update, also checks that:
- // - The target image family matches the current image family
- // - The image type transition is legal (i.e. dev -> *|| prod -> prod) or
- // alternatively that the hardware ID is allowlisted
- // Assuming the caller has performed following:
- // board_get_base_key_index();
- // board_get_key_array
- // Possible return codes:
- // LIBCR51SIGN_SUCCESS = 0,
- // LIBCR51SIGN_ERROR_RUNTIME_FAILURE = 1,
- // LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR = 3,
- // LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY = 4,
- // LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED = 5,
-
- static failure_reason
- validate_transition(const struct libcr51sign_ctx* ctx,
- const struct libcr51sign_intf* intf,
- uint32_t signature_struct_offset)
- {
- BUILD_ASSERT((offsetof(struct signature_rsa2048_pkcs15, modulus) ==
- SIGNATURE_OFFSET &&
- offsetof(struct signature_rsa3072_pkcs15, modulus) ==
- SIGNATURE_OFFSET &&
- offsetof(struct signature_rsa4096_pkcs15, modulus) ==
- SIGNATURE_OFFSET));
-
- // Read up to the modulus.
- enum
- {
- read_len = SIGNATURE_OFFSET
- };
- uint8_t buffer[read_len];
- int rv;
- rv = intf->read(ctx, signature_struct_offset, read_len, buffer);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx,
- "validate_transition: failed to read signature struct\n");
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- if (*(uint32_t*)buffer != SIGNATURE_MAGIC)
- {
- CPRINTS(ctx, "validate_transition: bad signature magic\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
-
- if (ctx->descriptor.image_family != ctx->current_image_family &&
- ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
- ctx->current_image_family != IMAGE_FAMILY_ALL)
- {
- CPRINTS(ctx, "validate_transition: invalid image family\n");
- return LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY;
- }
-
- if (intf->is_production_mode == NULL)
- {
- CPRINTS(ctx, "validate_transition: missing is_production_mode\n");
+ CPRINTS(ctx, "read_and_hash_update: missing hash_update\n");
return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
}
- if (intf->is_production_mode() &&
- (ctx->descriptor.image_type == IMAGE_DEV))
+ do
{
- CPRINTS(ctx, "validate_transition: checking exemption allowlist\n");
-
- // If function is NULL or if the function call return false, return
- // error
- if (intf->prod_to_dev_downgrade_allowed == NULL ||
- !intf->prod_to_dev_downgrade_allowed())
+ read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE;
+ rv = intf->read((void*)ctx, offset, read_size, read_buffer);
+ if (rv != LIBCR51SIGN_SUCCESS)
{
- CPRINTS(ctx, "validate_transition: illegal image type\n");
- return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
}
- }
- return LIBCR51SIGN_SUCCESS;
+ rv = intf->hash_update((void*)ctx, read_buffer, read_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ offset += read_size;
+ size -= read_size;
+ } while (size > 0);
+ }
+ return rv;
+}
+
+// Validates the image_region array, namely that:
+// - The regions are aligned, contiguous & exhaustive
+// - That the image descriptor resides in a static region
+//
+// If the array is consistent, proceeds to hash the static regions and
+// validates the hash. d_offset is the absolute image descriptor offset
+
+static failure_reason validate_payload_regions(
+ const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
+ uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
+{
+ // Allocate buffer to accomodate largest supported hash-type(SHA512)
+ uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) +
+ LIBCR51SIGN_SHA512_DIGEST_SIZE];
+ uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
+ uint32_t byte_count, region_count, image_size, hash_offset, digest_size;
+ uint32_t i;
+ uint8_t d_region_num = 0;
+ int rv;
+ const struct image_region* region;
+
+ if (image_regions == NULL)
+ {
+ CPRINTS(ctx, "Missing image region input\n");
+ return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT;
}
- // If caller had provided read_and_hash_update call that, otherwise call
- // read and then update.
+ BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) ==
+ MEMBER_SIZE(struct hash_sha512, hash_magic)));
+ image_size = ctx->descriptor.image_size;
+ region_count = ctx->descriptor.region_count;
+ hash_offset = d_offset + sizeof(struct image_descriptor) +
+ region_count * sizeof(struct image_region);
+ // Read the image_region array.
- static failure_reason
- read_and_hash_update(const struct libcr51sign_ctx* ctx,
- const struct libcr51sign_intf* intf,
- uint32_t offset, uint32_t size)
+ if (region_count > ARRAY_SIZE(image_regions->image_regions))
{
- uint8_t read_buffer[MAX_READ_SIZE];
- int rv;
- int read_size;
+ CPRINTS(ctx, "validate_payload_regions: "
+ "ctx->descriptor.region_count is greater "
+ "than LIBCR51SIGN_MAX_REGION_COUNT\n");
+ return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE;
+ }
- if (intf->read_and_hash_update)
+ rv = intf->read(ctx, d_offset + sizeof(struct image_descriptor),
+ region_count * sizeof(struct image_region),
+ (uint8_t*)&image_regions->image_regions);
+
+ image_regions->region_count = region_count;
+
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_payload_regions: failed to read region array\n");
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+
+ // Validate that the regions are contiguous & exhaustive.
+ for (i = 0, byte_count = 0; i < region_count; i++)
+ {
+ region = image_regions->image_regions + i;
+
+ CPRINTS(ctx, "validate_payload_regions: region #%d \"%s\" (%x - %x)\n",
+ i, (const char*)region->region_name, region->region_offset,
+ region->region_offset + region->region_size);
+ if ((region->region_offset % IMAGE_REGION_ALIGNMENT) != 0 ||
+ (region->region_size % IMAGE_REGION_ALIGNMENT) != 0)
{
- rv = intf->read_and_hash_update((void*)ctx, offset, size);
+ CPRINTS(ctx, "validate_payload_regions: regions must be sector "
+ "aligned\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
}
- else
+ if (region->region_offset != byte_count ||
+ region->region_size > image_size - byte_count)
{
- if (!intf->hash_update)
+ CPRINTS(ctx, "validate_payload_regions: invalid region array\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+ byte_count += region->region_size;
+ // The image descriptor must be part of a static region.
+ if (d_offset >= region->region_offset && d_offset < byte_count)
+ {
+ d_region_num = i;
+ CPRINTS(ctx,
+ "validate_payload_regions: image descriptor in region %d\n",
+ i);
+ // The descriptor can't span regions.
+ if (ctx->descriptor.descriptor_area_size > byte_count ||
+ !(region->region_attributes & IMAGE_REGION_STATIC))
{
- CPRINTS(ctx, "read_and_hash_update: missing hash_update\n");
- return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ CPRINTS(ctx,
+ "validate_payload_regions: descriptor must reside in "
+ "static region\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
}
- do
- {
- read_size = size < MAX_READ_SIZE ? size : MAX_READ_SIZE;
- rv = intf->read((void*)ctx, offset, read_size, read_buffer);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- rv = intf->hash_update((void*)ctx, read_buffer, read_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- offset += read_size;
- size -= read_size;
- } while (size > 0);
}
+ }
+ if (byte_count != image_size)
+ {
+ CPRINTS(ctx, "validate_payload_regions: invalid image size\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+
+ rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
return rv;
}
- // Validates the image_region array, namely that:
- // - The regions are aligned, contiguous & exhaustive
- // - That the image descriptor resides in a static region
- //
- // If the array is consistent, proceeds to hash the static regions and
- // validates the hash. d_offset is the absolute image descriptor offset
-
- static failure_reason validate_payload_regions(
- const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
- uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
+ rv = intf->read(ctx, hash_offset,
+ MEMBER_SIZE(struct hash_sha256, hash_magic) + digest_size,
+ magic_and_digest);
+ if (rv != LIBCR51SIGN_SUCCESS)
{
- // Allocate buffer to accomodate largest supported hash-type(SHA512)
- uint8_t magic_and_digest[MEMBER_SIZE(struct hash_sha512, hash_magic) +
- LIBCR51SIGN_SHA512_DIGEST_SIZE];
- uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
- uint32_t byte_count, region_count, image_size, hash_offset, digest_size;
- uint32_t i;
- uint8_t d_region_num = 0;
- int rv;
- const struct image_region* region;
-
- if (image_regions == NULL)
- {
- CPRINTS(ctx, "Missing image region input\n");
- return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT;
- }
-
- BUILD_ASSERT((MEMBER_SIZE(struct hash_sha256, hash_magic) ==
- MEMBER_SIZE(struct hash_sha512, hash_magic)));
- image_size = ctx->descriptor.image_size;
- region_count = ctx->descriptor.region_count;
- hash_offset = d_offset + sizeof(struct image_descriptor) +
- region_count * sizeof(struct image_region);
- // Read the image_region array.
-
- if (region_count > ARRAY_SIZE(image_regions->image_regions))
- {
- CPRINTS(ctx, "validate_payload_regions: "
- "ctx->descriptor.region_count is greater "
- "than LIBCR51SIGN_MAX_REGION_COUNT\n");
- return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE;
- }
-
- rv = intf->read(ctx, d_offset + sizeof(struct image_descriptor),
- region_count * sizeof(struct image_region),
- (uint8_t*)&image_regions->image_regions);
-
- image_regions->region_count = region_count;
-
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx,
- "validate_payload_regions: failed to read region array\n");
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
-
- // Validate that the regions are contiguous & exhaustive.
- for (i = 0, byte_count = 0; i < region_count; i++)
- {
- region = image_regions->image_regions + i;
-
- CPRINTS(ctx,
- "validate_payload_regions: region #%d \"%s\" (%x - %x)\n",
- i, (const char*)region->region_name, region->region_offset,
- region->region_offset + region->region_size);
- if ((region->region_offset % IMAGE_REGION_ALIGNMENT) != 0 ||
- (region->region_size % IMAGE_REGION_ALIGNMENT) != 0)
- {
- CPRINTS(ctx, "validate_payload_regions: regions must be sector "
- "aligned\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- if (region->region_offset != byte_count ||
- region->region_size > image_size - byte_count)
- {
- CPRINTS(ctx,
- "validate_payload_regions: invalid region array\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- byte_count += region->region_size;
- // The image descriptor must be part of a static region.
- if (d_offset >= region->region_offset && d_offset < byte_count)
- {
- d_region_num = i;
- CPRINTS(
- ctx,
- "validate_payload_regions: image descriptor in region %d\n",
- i);
- // The descriptor can't span regions.
- if (ctx->descriptor.descriptor_area_size > byte_count ||
- !(region->region_attributes & IMAGE_REGION_STATIC))
- {
- CPRINTS(
- ctx,
- "validate_payload_regions: descriptor must reside in "
- "static region\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- }
- }
- if (byte_count != image_size)
- {
- CPRINTS(ctx, "validate_payload_regions: invalid image size\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
-
- rv = get_hash_digest_size(ctx->descriptor.hash_type, &digest_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
-
- rv = intf->read(ctx, hash_offset,
- MEMBER_SIZE(struct hash_sha256, hash_magic) +
- digest_size,
- magic_and_digest);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(
- ctx,
+ CPRINTS(ctx,
"validate_payload_regions: failed to read hash from flash\n");
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- if (*(uint32_t*)magic_and_digest != HASH_MAGIC)
- {
- CPRINTS(ctx, "validate_payload_regions: bad hash magic\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- rv = intf->hash_init(ctx, ctx->descriptor.hash_type);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- for (i = 0; i < region_count; i++)
- {
- uint32_t hash_start, hash_size;
- region = image_regions->image_regions + i;
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ if (*(uint32_t*)magic_and_digest != HASH_MAGIC)
+ {
+ CPRINTS(ctx, "validate_payload_regions: bad hash magic\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+ rv = intf->hash_init(ctx, ctx->descriptor.hash_type);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ for (i = 0; i < region_count; i++)
+ {
+ uint32_t hash_start, hash_size;
+ region = image_regions->image_regions + i;
- if (!(region->region_attributes & IMAGE_REGION_STATIC))
+ if (!(region->region_attributes & IMAGE_REGION_STATIC))
+ {
+ continue;
+ }
+ hash_start = region->region_offset;
+ hash_size = region->region_size;
+
+ // Skip the descriptor.
+ do
+ {
+ if (i == d_region_num)
{
- continue;
+ hash_size = d_offset - hash_start;
}
- hash_start = region->region_offset;
- hash_size = region->region_size;
- // Skip the descriptor.
- do
+ if (!hash_size)
{
- if (i == d_region_num)
- {
- hash_size = d_offset - hash_start;
- }
-
- if (!hash_size)
- {
- hash_start += ctx->descriptor.descriptor_area_size;
- hash_size = (region->region_offset + region->region_size -
- hash_start);
- }
- CPRINTS("validate_payload_regions: hashing %s (%x - %x)\n",
- (const char*)region->region_name, hash_start,
- hash_start + hash_size);
- // Read the image_region array.
- rv = read_and_hash_update(ctx, intf, hash_start, hash_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
- hash_start += hash_size;
- } while (hash_start != region->region_offset + region->region_size);
- }
- rv = intf->hash_final((void*)ctx, (uint8_t*)dcrypto_digest);
-
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
-
- if (memcmp(magic_and_digest +
- MEMBER_SIZE(struct hash_sha256, hash_magic),
- dcrypto_digest, digest_size))
- {
- CPRINTS(ctx, "validate_payload_regions: invalid hash\n");
- return LIBCR51SIGN_ERROR_INVALID_HASH;
- }
- // Image is valid.
- return LIBCR51SIGN_SUCCESS;
- }
-
- // Create empty image_regions to pass to validate_payload_regions
- // Support validate_payload_regions_helper to remove image_regions as a
- // required input.
-
- static failure_reason
- allocate_and_validate_payload_regions(const struct libcr51sign_ctx* ctx,
- struct libcr51sign_intf* intf,
- uint32_t d_offset)
- {
- struct libcr51sign_validated_regions image_regions;
- return validate_payload_regions(ctx, intf, d_offset, &image_regions);
- }
-
- // Wrapper around validate_payload_regions to allow nullptr for
- // image_regions. Calls allocate_and_validate_payload_regions when
- // image_regions is nullptr to create placer holder image_regions.
-
- static failure_reason validate_payload_regions_helper(
- const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
- uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
- {
- if (image_regions)
- {
- return validate_payload_regions(ctx, intf, d_offset, image_regions);
- }
-
- return allocate_and_validate_payload_regions(ctx, intf, d_offset);
- }
-
- // Check if the given signature_scheme is supported.
- // Returns nonzero on error, zero on success
-
- static failure_reason
- is_signature_scheme_supported(enum signature_scheme scheme)
- {
- switch (scheme)
- {
- case SIGNATURE_RSA2048_PKCS15:
- case SIGNATURE_RSA3072_PKCS15:
- case SIGNATURE_RSA4096_PKCS15:
- case SIGNATURE_RSA4096_PKCS15_SHA512:
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
- }
- }
-
- // Returns size of signature struct size in |size|
- // Returns nonzero on error, zero on success
-
- static failure_reason
- get_signature_struct_size(enum signature_scheme scheme, uint32_t* size)
- {
- switch (scheme)
- {
- case SIGNATURE_RSA2048_PKCS15:
- *size = sizeof(struct signature_rsa2048_pkcs15);
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA3072_PKCS15:
- *size = sizeof(struct signature_rsa3072_pkcs15);
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA4096_PKCS15:
- case SIGNATURE_RSA4096_PKCS15_SHA512:
- *size = sizeof(struct signature_rsa4096_pkcs15);
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
- }
- }
-
- static failure_reason
- get_signature_field_offset(enum signature_scheme scheme,
- uint32_t* offset)
- {
- switch (scheme)
- {
- case SIGNATURE_RSA2048_PKCS15:
- *offset = offsetof(struct signature_rsa2048_pkcs15, signature);
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA3072_PKCS15:
- *offset = offsetof(struct signature_rsa3072_pkcs15, signature);
- return LIBCR51SIGN_SUCCESS;
- case SIGNATURE_RSA4096_PKCS15:
- case SIGNATURE_RSA4096_PKCS15_SHA512:
- *offset = offsetof(struct signature_rsa4096_pkcs15, signature);
- return LIBCR51SIGN_SUCCESS;
- default:
- return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
- }
- }
-
- // Validates the signature (of type scheme) read from "device" at
- //"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of
- // EEPROM area "data_offset:data_size".
-
- static failure_reason validate_signature(
- const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
- uint32_t data_offset, uint32_t data_size, enum signature_scheme scheme,
- uint32_t raw_signature_offset)
- {
- uint8_t signature[LIBCR51SIGN_MAX_SIGNATURE_SIZE];
- uint16_t key_size;
- uint32_t digest_size;
- uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
- int rv;
- enum hash_type hash_type;
-
- if (!intf->hash_init)
- {
- CPRINTS(ctx, "validate_signature: missing hash_init\n");
- return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
- }
- rv = get_hash_type_from_signature(scheme, &hash_type);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(
- ctx,
- "validate_payload_regions: hash_type from signature failed\n");
- return rv;
- }
- rv = intf->hash_init(ctx, hash_type);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- rv = read_and_hash_update(ctx, intf, data_offset, data_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "validate_signature: hash_update failed\n");
- return rv;
- }
- if (!intf->hash_final)
- {
- CPRINTS(ctx, "validate_signature: missing hash_final\n");
- return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
- }
- rv = intf->hash_final((void*)ctx, dcrypto_digest);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx,
- "validate_signature: hash_final failed (status = %d)\n",
- rv);
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- rv = get_key_size(scheme, &key_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
-
- rv = intf->read(ctx, raw_signature_offset, key_size, signature);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(
- ctx,
- "validate_signature: failed to read signature (status = %d)\n",
- rv);
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- if (!intf->verify_signature)
- {
- CPRINTS(ctx, "validate_signature: missing verify_signature\n");
- return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
- }
- rv = get_hash_digest_size(hash_type, &digest_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
- rv = intf->verify_signature(ctx, scheme, signature, key_size,
- dcrypto_digest, digest_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx,
- "validate_signature: verification failed (status = %d)\n",
- rv);
- return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
- }
- CPRINTS(ctx, "validate_signature: verification succeeded\n");
- return LIBCR51SIGN_SUCCESS;
- }
-
- // Sanity checks the image descriptor & validates its signature.
- // This function does not validate the image_region array or image hash.
- //
- //@param[in] ctx context which describes the image and holds opaque private
- // data for the user of the library
- //@param[in] intf function pointers which interface to the current system
- // and environment
- //@param offset Absolute image descriptor flash offset.
- //@param relative_offset Image descriptor offset relative to image start.
- //@param max_size Maximum size of the flash space in bytes.
- //@param descriptor Output pointer to an image_descriptor struct
-
- static failure_reason validate_descriptor(
- const struct libcr51sign_ctx* ctx, const struct libcr51sign_intf* intf,
- uint32_t offset, uint32_t relative_offset, uint32_t max_size)
- {
- uint32_t max_descriptor_size, signed_size, signature_scheme,
- signature_offset;
- uint32_t signature_struct_offset, signature_struct_size,
- hash_struct_size;
- int rv;
-
- max_descriptor_size = max_size - relative_offset;
- if (max_size < relative_offset ||
- max_descriptor_size < sizeof(struct image_descriptor))
- {
- CPRINTS(ctx, "validate_descriptor: invalid arguments\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
-
- rv = intf->read(ctx, offset, sizeof(ctx->descriptor),
- (uint8_t*)&ctx->descriptor);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "validate_descriptor: failed to read descriptor\n");
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- }
- if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
- ctx->descriptor.descriptor_offset != relative_offset ||
- ctx->descriptor.region_count == 0 ||
- ctx->descriptor.descriptor_area_size > max_descriptor_size ||
- ctx->descriptor.image_size > max_size)
- {
- CPRINTS(ctx, "validate_descriptor: invalid descriptor\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- if (intf->image_size_valid == NULL)
- {
- // Preserve original behavior of requiring exact image_size match if
- // no operator is provided.
- if (ctx->descriptor.image_size != max_size)
- {
- CPRINTS(ctx, "validate_descriptor: invalid image size\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ hash_start += ctx->descriptor.descriptor_area_size;
+ hash_size =
+ (region->region_offset + region->region_size - hash_start);
}
- }
- else if (!intf->image_size_valid(ctx->descriptor.image_size))
- {
- CPRINTS(ctx, "validate_descriptor: invalid image size\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- if (ctx->descriptor.image_type != IMAGE_DEV &&
- ctx->descriptor.image_type != IMAGE_PROD &&
- ctx->descriptor.image_type != IMAGE_BREAKOUT &&
- ctx->descriptor.image_type != IMAGE_TEST &&
- ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY)
- {
- CPRINTS(ctx, "validate_descriptor: bad image type\n");
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- // Although the image_descriptor struct supports unauthenticated
- // images, Haven will not allow it.
- // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently.
-
- signature_scheme = ctx->descriptor.signature_scheme;
-
- rv = is_signature_scheme_supported(signature_scheme);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
- rv = is_hash_type_supported(ctx->descriptor.hash_type);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "validate_payload_regions: invalid hash type\n");
- return rv;
- }
- if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION ||
- ctx->descriptor.region_count > LIBCR51SIGN_MAX_REGION_COUNT)
- {
- CPRINTS(ctx, "validate_descriptor: unsupported descriptor\n");
- return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
- }
- rv = get_signature_struct_size(signature_scheme,
- &signature_struct_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
-
- // Compute the size of the signed portion of the image descriptor.
- signed_size = sizeof(struct image_descriptor) +
- ctx->descriptor.region_count *
- sizeof(struct image_region);
- rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
- signed_size += hash_struct_size;
- if (ctx->descriptor.denylist_size)
- {
- signed_size += sizeof(struct denylist);
- signed_size += ctx->descriptor.denylist_size *
- sizeof(struct denylist_record);
- }
- if (ctx->descriptor.blob_size)
- {
- signed_size += sizeof(struct blob);
- // Previous additions are guaranteed not to overflow.
- if (ctx->descriptor.blob_size >
- ctx->descriptor.descriptor_area_size - signed_size)
- {
- CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)\n",
- ctx->descriptor.blob_size);
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- signed_size += ctx->descriptor.blob_size;
- }
- if (signature_struct_size >
- ctx->descriptor.descriptor_area_size - signed_size)
- {
- CPRINTS(ctx,
- "validate_descriptor: invalid descriptor area size "
- "(expected = 0x%x, actual = 0x%x)\n",
- ctx->descriptor.descriptor_area_size,
- signed_size + signature_struct_size);
- return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
- }
- signature_struct_offset = signed_size;
- // Omit the actual signature.
- rv = get_signature_field_offset(signature_scheme, &signature_offset);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
- signed_size += signature_offset;
-
- // Lookup key & validate transition.
- rv = validate_transition(ctx, intf, offset + signature_struct_offset);
-
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- return rv;
- }
- return validate_signature(ctx, intf, offset, signed_size,
- signature_scheme, offset + signed_size);
- }
-
- // Scans the external EEPROM for a magic value at "alignment" boundaries.
- //
- //@param device Handle to the external EEPROM.
- //@param magic 8-byte pattern to search for.
- //@param start_offset Offset to begin searching at.
- //@param limit Exclusive address (e.g. EEPROM size).
- //@param alignment Alignment boundaries (POW2) to search on.
- //@param header_offset Location to place the new header offset.
- //@return LIBCR51SIGN_SUCCESS (or non-zero on error).
-
- int scan_for_magic_8(const struct libcr51sign_ctx* ctx,
- const struct libcr51sign_intf* intf, uint64_t magic,
- uint32_t start_offset, uint32_t limit,
- uint32_t alignment, uint32_t* header_offset)
- {
- uint64_t read_data;
- uint32_t offset;
- int rv;
-
- if (limit <= start_offset || limit > ctx->end_offset ||
- limit < sizeof(magic) || !POWER_OF_TWO(alignment))
- {
- return LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
- }
-
- if (!intf->read)
- {
- CPRINTS(ctx, "scan_for_magic_8: missing intf->read\n");
- return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
- }
- // Align start_offset to the next valid boundary.
- start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment;
- for (offset = start_offset; offset < limit - sizeof(magic);
- offset += alignment)
- {
- rv = intf->read((void*)ctx, offset, sizeof(read_data),
- (uint8_t*)&read_data);
+ CPRINTS("validate_payload_regions: hashing %s (%x - %x)\n",
+ (const char*)region->region_name, hash_start,
+ hash_start + hash_size);
+ // Read the image_region array.
+ rv = read_and_hash_update(ctx, intf, hash_start, hash_size);
if (rv != LIBCR51SIGN_SUCCESS)
{
return rv;
}
- if (read_data == magic)
- {
- if (header_offset)
- {
- *header_offset = offset;
- }
- return LIBCR51SIGN_SUCCESS;
- }
- }
- // Failed to locate magic.
- return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC;
+ hash_start += hash_size;
+ } while (hash_start != region->region_offset + region->region_size);
+ }
+ rv = intf->hash_final((void*)ctx, (uint8_t*)dcrypto_digest);
+
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
}
- // Check whether the signature on the image is valid.
- // Validates the authenticity of an EEPROM image. Scans for & validates the
- // signature on the image descriptor. If the descriptor validates, hashes
- // the rest of the image to verify its integrity.
- //
- // @param[in] ctx - context which describes the image and holds opaque
- // private
- // data for the user of the library
- // @param[in] intf - function pointers which interface to the current system
- // and environment
- // @param[out] image_regions - image_region pointer to an array for the
- // output
- //
- // @return nonzero on error, zero on success
-
- failure_reason libcr51sign_validate(
- const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
- struct libcr51sign_validated_regions* image_regions)
+ if (memcmp(magic_and_digest + MEMBER_SIZE(struct hash_sha256, hash_magic),
+ dcrypto_digest, digest_size))
{
- uint32_t image_limit = 0;
- int rv, rv_first_desc = LIBCR51SIGN_SUCCESS;
- uint32_t descriptor_offset;
+ CPRINTS(ctx, "validate_payload_regions: invalid hash\n");
+ return LIBCR51SIGN_ERROR_INVALID_HASH;
+ }
+ // Image is valid.
+ return LIBCR51SIGN_SUCCESS;
+}
- if (!ctx)
+// Create empty image_regions to pass to validate_payload_regions
+// Support validate_payload_regions_helper to remove image_regions as a
+// required input.
+
+static failure_reason
+ allocate_and_validate_payload_regions(const struct libcr51sign_ctx* ctx,
+ struct libcr51sign_intf* intf,
+ uint32_t d_offset)
+{
+ struct libcr51sign_validated_regions image_regions;
+ return validate_payload_regions(ctx, intf, d_offset, &image_regions);
+}
+
+// Wrapper around validate_payload_regions to allow nullptr for
+// image_regions. Calls allocate_and_validate_payload_regions when
+// image_regions is nullptr to create placer holder image_regions.
+
+static failure_reason validate_payload_regions_helper(
+ const struct libcr51sign_ctx* ctx, struct libcr51sign_intf* intf,
+ uint32_t d_offset, struct libcr51sign_validated_regions* image_regions)
+{
+ if (image_regions)
+ {
+ return validate_payload_regions(ctx, intf, d_offset, image_regions);
+ }
+
+ return allocate_and_validate_payload_regions(ctx, intf, d_offset);
+}
+
+// Check if the given signature_scheme is supported.
+// Returns nonzero on error, zero on success
+
+static failure_reason
+ is_signature_scheme_supported(enum signature_scheme scheme)
+{
+ switch (scheme)
+ {
+ case SIGNATURE_RSA2048_PKCS15:
+ case SIGNATURE_RSA3072_PKCS15:
+ case SIGNATURE_RSA4096_PKCS15:
+ case SIGNATURE_RSA4096_PKCS15_SHA512:
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
+ }
+}
+
+// Returns size of signature struct size in |size|
+// Returns nonzero on error, zero on success
+
+static failure_reason get_signature_struct_size(enum signature_scheme scheme,
+ uint32_t* size)
+{
+ switch (scheme)
+ {
+ case SIGNATURE_RSA2048_PKCS15:
+ *size = sizeof(struct signature_rsa2048_pkcs15);
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA3072_PKCS15:
+ *size = sizeof(struct signature_rsa3072_pkcs15);
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA4096_PKCS15:
+ case SIGNATURE_RSA4096_PKCS15_SHA512:
+ *size = sizeof(struct signature_rsa4096_pkcs15);
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
+ }
+}
+
+static failure_reason get_signature_field_offset(enum signature_scheme scheme,
+ uint32_t* offset)
+{
+ switch (scheme)
+ {
+ case SIGNATURE_RSA2048_PKCS15:
+ *offset = offsetof(struct signature_rsa2048_pkcs15, signature);
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA3072_PKCS15:
+ *offset = offsetof(struct signature_rsa3072_pkcs15, signature);
+ return LIBCR51SIGN_SUCCESS;
+ case SIGNATURE_RSA4096_PKCS15:
+ case SIGNATURE_RSA4096_PKCS15_SHA512:
+ *offset = offsetof(struct signature_rsa4096_pkcs15, signature);
+ return LIBCR51SIGN_SUCCESS;
+ default:
+ return LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME;
+ }
+}
+
+// Validates the signature (of type scheme) read from "device" at
+//"raw_signature_offset" with "public_key" over a SHA256/SHA512 digest of
+// EEPROM area "data_offset:data_size".
+
+static failure_reason validate_signature(const struct libcr51sign_ctx* ctx,
+ const struct libcr51sign_intf* intf,
+ uint32_t data_offset,
+ uint32_t data_size,
+ enum signature_scheme scheme,
+ uint32_t raw_signature_offset)
+{
+ uint8_t signature[LIBCR51SIGN_MAX_SIGNATURE_SIZE];
+ uint16_t key_size;
+ uint32_t digest_size;
+ uint8_t dcrypto_digest[LIBCR51SIGN_SHA512_DIGEST_SIZE];
+ int rv;
+ enum hash_type hash_type;
+
+ if (!intf->hash_init)
+ {
+ CPRINTS(ctx, "validate_signature: missing hash_init\n");
+ return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ }
+ rv = get_hash_type_from_signature(scheme, &hash_type);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx,
+ "validate_payload_regions: hash_type from signature failed\n");
+ return rv;
+ }
+ rv = intf->hash_init(ctx, hash_type);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ rv = read_and_hash_update(ctx, intf, data_offset, data_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_signature: hash_update failed\n");
+ return rv;
+ }
+ if (!intf->hash_final)
+ {
+ CPRINTS(ctx, "validate_signature: missing hash_final\n");
+ return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ }
+ rv = intf->hash_final((void*)ctx, dcrypto_digest);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_signature: hash_final failed (status = %d)\n",
+ rv);
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ rv = get_key_size(scheme, &key_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+
+ rv = intf->read(ctx, raw_signature_offset, key_size, signature);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx,
+ "validate_signature: failed to read signature (status = %d)\n",
+ rv);
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ if (!intf->verify_signature)
+ {
+ CPRINTS(ctx, "validate_signature: missing verify_signature\n");
+ return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ }
+ rv = get_hash_digest_size(hash_type, &digest_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+ rv = intf->verify_signature(ctx, scheme, signature, key_size,
+ dcrypto_digest, digest_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_signature: verification failed (status = %d)\n",
+ rv);
+ return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
+ }
+ CPRINTS(ctx, "validate_signature: verification succeeded\n");
+ return LIBCR51SIGN_SUCCESS;
+}
+
+// Sanity checks the image descriptor & validates its signature.
+// This function does not validate the image_region array or image hash.
+//
+//@param[in] ctx context which describes the image and holds opaque private
+// data for the user of the library
+//@param[in] intf function pointers which interface to the current system
+// and environment
+//@param offset Absolute image descriptor flash offset.
+//@param relative_offset Image descriptor offset relative to image start.
+//@param max_size Maximum size of the flash space in bytes.
+//@param descriptor Output pointer to an image_descriptor struct
+
+static failure_reason validate_descriptor(const struct libcr51sign_ctx* ctx,
+ const struct libcr51sign_intf* intf,
+ uint32_t offset,
+ uint32_t relative_offset,
+ uint32_t max_size)
+{
+ uint32_t max_descriptor_size, signed_size, signature_scheme,
+ signature_offset;
+ uint32_t signature_struct_offset, signature_struct_size, hash_struct_size;
+ int rv;
+
+ max_descriptor_size = max_size - relative_offset;
+ if (max_size < relative_offset ||
+ max_descriptor_size < sizeof(struct image_descriptor))
+ {
+ CPRINTS(ctx, "validate_descriptor: invalid arguments\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+
+ rv = intf->read(ctx, offset, sizeof(ctx->descriptor),
+ (uint8_t*)&ctx->descriptor);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_descriptor: failed to read descriptor\n");
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ }
+ if (ctx->descriptor.descriptor_magic != DESCRIPTOR_MAGIC ||
+ ctx->descriptor.descriptor_offset != relative_offset ||
+ ctx->descriptor.region_count == 0 ||
+ ctx->descriptor.descriptor_area_size > max_descriptor_size ||
+ ctx->descriptor.image_size > max_size)
+ {
+ CPRINTS(ctx, "validate_descriptor: invalid descriptor\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+ if (intf->image_size_valid == NULL)
+ {
+ // Preserve original behavior of requiring exact image_size match if
+ // no operator is provided.
+ if (ctx->descriptor.image_size != max_size)
{
- CPRINTS(ctx, "Missing context\n");
- return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
+ CPRINTS(ctx, "validate_descriptor: invalid image size\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
}
- else if (!intf)
+ }
+ else if (!intf->image_size_valid(ctx->descriptor.image_size))
+ {
+ CPRINTS(ctx, "validate_descriptor: invalid image size\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+ if (ctx->descriptor.image_type != IMAGE_DEV &&
+ ctx->descriptor.image_type != IMAGE_PROD &&
+ ctx->descriptor.image_type != IMAGE_BREAKOUT &&
+ ctx->descriptor.image_type != IMAGE_TEST &&
+ ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY)
+ {
+ CPRINTS(ctx, "validate_descriptor: bad image type\n");
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+ // Although the image_descriptor struct supports unauthenticated
+ // images, Haven will not allow it.
+ // Haven only supports SHA256 + RSA2048/RSA3072_PKCS15 currently.
+
+ signature_scheme = ctx->descriptor.signature_scheme;
+
+ rv = is_signature_scheme_supported(signature_scheme);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+ rv = is_hash_type_supported(ctx->descriptor.hash_type);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate_payload_regions: invalid hash type\n");
+ return rv;
+ }
+ if (ctx->descriptor.descriptor_major > MAX_MAJOR_VERSION ||
+ ctx->descriptor.region_count > LIBCR51SIGN_MAX_REGION_COUNT)
+ {
+ CPRINTS(ctx, "validate_descriptor: unsupported descriptor\n");
+ return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
+ }
+ rv = get_signature_struct_size(signature_scheme, &signature_struct_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+
+ // Compute the size of the signed portion of the image descriptor.
+ signed_size = sizeof(struct image_descriptor) +
+ ctx->descriptor.region_count * sizeof(struct image_region);
+ rv = get_hash_struct_size(ctx->descriptor.hash_type, &hash_struct_size);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+ signed_size += hash_struct_size;
+ if (ctx->descriptor.denylist_size)
+ {
+ signed_size += sizeof(struct denylist);
+ signed_size += ctx->descriptor.denylist_size *
+ sizeof(struct denylist_record);
+ }
+ if (ctx->descriptor.blob_size)
+ {
+ signed_size += sizeof(struct blob);
+ // Previous additions are guaranteed not to overflow.
+ if (ctx->descriptor.blob_size >
+ ctx->descriptor.descriptor_area_size - signed_size)
{
- CPRINTS(ctx, "Missing interface\n");
- return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)\n",
+ ctx->descriptor.blob_size);
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
}
+ signed_size += ctx->descriptor.blob_size;
+ }
+ if (signature_struct_size >
+ ctx->descriptor.descriptor_area_size - signed_size)
+ {
+ CPRINTS(ctx,
+ "validate_descriptor: invalid descriptor area size "
+ "(expected = 0x%x, actual = 0x%x)\n",
+ ctx->descriptor.descriptor_area_size,
+ signed_size + signature_struct_size);
+ return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
+ }
+ signature_struct_offset = signed_size;
+ // Omit the actual signature.
+ rv = get_signature_field_offset(signature_scheme, &signature_offset);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+ signed_size += signature_offset;
- rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset,
- ctx->end_offset, DESCRIPTOR_ALIGNMENT,
- &descriptor_offset);
- while (rv == LIBCR51SIGN_SUCCESS)
+ // Lookup key & validate transition.
+ rv = validate_transition(ctx, intf, offset + signature_struct_offset);
+
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ return rv;
+ }
+ return validate_signature(ctx, intf, offset, signed_size, signature_scheme,
+ offset + signed_size);
+}
+
+// Scans the external EEPROM for a magic value at "alignment" boundaries.
+//
+//@param device Handle to the external EEPROM.
+//@param magic 8-byte pattern to search for.
+//@param start_offset Offset to begin searching at.
+//@param limit Exclusive address (e.g. EEPROM size).
+//@param alignment Alignment boundaries (POW2) to search on.
+//@param header_offset Location to place the new header offset.
+//@return LIBCR51SIGN_SUCCESS (or non-zero on error).
+
+int scan_for_magic_8(const struct libcr51sign_ctx* ctx,
+ const struct libcr51sign_intf* intf, uint64_t magic,
+ uint32_t start_offset, uint32_t limit, uint32_t alignment,
+ uint32_t* header_offset)
+{
+ uint64_t read_data;
+ uint32_t offset;
+ int rv;
+
+ if (limit <= start_offset || limit > ctx->end_offset ||
+ limit < sizeof(magic) || !POWER_OF_TWO(alignment))
+ {
+ return LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (!intf->read)
+ {
+ CPRINTS(ctx, "scan_for_magic_8: missing intf->read\n");
+ return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ }
+ // Align start_offset to the next valid boundary.
+ start_offset = ((start_offset - 1) & ~(alignment - 1)) + alignment;
+ for (offset = start_offset; offset < limit - sizeof(magic);
+ offset += alignment)
+ {
+ rv = intf->read((void*)ctx, offset, sizeof(read_data),
+ (uint8_t*)&read_data);
+ if (rv != LIBCR51SIGN_SUCCESS)
{
- CPRINTS(ctx, "validate: potential image descriptor found @%x\n",
- descriptor_offset);
- // Validation is split into 2 functions to minimize
- // stack usage.
-
- rv = validate_descriptor(ctx, intf, descriptor_offset,
- descriptor_offset - ctx->start_offset,
- ctx->end_offset - ctx->start_offset);
- if (rv != LIBCR51SIGN_SUCCESS)
+ return rv;
+ }
+ if (read_data == magic)
+ {
+ if (header_offset)
{
- CPRINTS(ctx, "validate: validate_descriptor() failed ec%d\n",
- rv);
+ *header_offset = offset;
}
+ return LIBCR51SIGN_SUCCESS;
+ }
+ }
+ // Failed to locate magic.
+ return LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC;
+}
+// Check whether the signature on the image is valid.
+// Validates the authenticity of an EEPROM image. Scans for & validates the
+// signature on the image descriptor. If the descriptor validates, hashes
+// the rest of the image to verify its integrity.
+//
+// @param[in] ctx - context which describes the image and holds opaque
+// private
+// data for the user of the library
+// @param[in] intf - function pointers which interface to the current system
+// and environment
+// @param[out] image_regions - image_region pointer to an array for the
+// output
+//
+// @return nonzero on error, zero on success
+
+failure_reason
+ libcr51sign_validate(const struct libcr51sign_ctx* ctx,
+ struct libcr51sign_intf* intf,
+ struct libcr51sign_validated_regions* image_regions)
+{
+ uint32_t image_limit = 0;
+ int rv, rv_first_desc = LIBCR51SIGN_SUCCESS;
+ uint32_t descriptor_offset;
+
+ if (!ctx)
+ {
+ CPRINTS(ctx, "Missing context\n");
+ return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
+ }
+ else if (!intf)
+ {
+ CPRINTS(ctx, "Missing interface\n");
+ return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
+ }
+
+ rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, ctx->start_offset,
+ ctx->end_offset, DESCRIPTOR_ALIGNMENT,
+ &descriptor_offset);
+ while (rv == LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate: potential image descriptor found @%x\n",
+ descriptor_offset);
+ // Validation is split into 2 functions to minimize
+ // stack usage.
+
+ rv = validate_descriptor(ctx, intf, descriptor_offset,
+ descriptor_offset - ctx->start_offset,
+ ctx->end_offset - ctx->start_offset);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "validate: validate_descriptor() failed ec%d\n", rv);
+ }
+
+ if (rv == LIBCR51SIGN_SUCCESS)
+ {
+ rv = validate_payload_regions_helper(ctx, intf, descriptor_offset,
+ image_regions);
if (rv == LIBCR51SIGN_SUCCESS)
{
- rv = validate_payload_regions_helper(
- ctx, intf, descriptor_offset, image_regions);
- if (rv == LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "validate: success!\n");
- return rv;
- }
- CPRINTS(ctx,
- "validate: validate_payload_regions() failed ec%d\n",
- rv);
+ CPRINTS(ctx, "validate: success!\n");
+ return rv;
}
- // Store the first desc fail reason if any
- if (rv != LIBCR51SIGN_SUCCESS &&
- rv_first_desc == LIBCR51SIGN_SUCCESS)
- rv_first_desc = rv;
-
- // scan_for_magic_8() will round up to the next aligned boundary.
- descriptor_offset++;
- image_limit = ctx->end_offset - ctx->start_offset;
- rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC,
- descriptor_offset, image_limit,
- DESCRIPTOR_ALIGNMENT, &descriptor_offset);
+ CPRINTS(ctx, "validate: validate_payload_regions() failed ec%d\n",
+ rv);
}
- CPRINTS(ctx, "validate: failed to validate image ec%d\n", rv);
- // If desc validation failed for some reason then return that reason
- if (rv_first_desc != LIBCR51SIGN_SUCCESS)
- return rv_first_desc;
- else
- return rv;
+ // Store the first desc fail reason if any
+ if (rv != LIBCR51SIGN_SUCCESS && rv_first_desc == LIBCR51SIGN_SUCCESS)
+ rv_first_desc = rv;
+
+ // scan_for_magic_8() will round up to the next aligned boundary.
+ descriptor_offset++;
+ image_limit = ctx->end_offset - ctx->start_offset;
+ rv = scan_for_magic_8(ctx, intf, DESCRIPTOR_MAGIC, descriptor_offset,
+ image_limit, DESCRIPTOR_ALIGNMENT,
+ &descriptor_offset);
}
+ CPRINTS(ctx, "validate: failed to validate image ec%d\n", rv);
+ // If desc validation failed for some reason then return that reason
+ if (rv_first_desc != LIBCR51SIGN_SUCCESS)
+ return rv_first_desc;
+ else
+ return rv;
+}
- // @func to returns the libcr51sign error code as a string
- // @param[in] ec - Error code
- // @return error code in string format
+// @func to returns the libcr51sign error code as a string
+// @param[in] ec - Error code
+// @return error code in string format
- const char* libcr51sign_errorcode_to_string(failure_reason ec)
+const char* libcr51sign_errorcode_to_string(failure_reason ec)
+{
+ switch (ec)
{
- switch (ec)
- {
- case LIBCR51SIGN_SUCCESS:
- return "Success";
- case LIBCR51SIGN_ERROR_RUNTIME_FAILURE:
- return "Runtime Error Failure";
- case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR:
- return "Unsupported descriptor";
- case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR:
- return "Invalid descriptor";
- case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY:
- return "Invalid image family";
- case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED:
- return "Image type disallowed";
- case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED:
- return "Dev downgrade disallowed";
- case LIBCR51SIGN_ERROR_UNTRUSTED_KEY:
- return "Untrusted key";
- case LIBCR51SIGN_ERROR_INVALID_SIGNATURE:
- return "Invalid signature";
- case LIBCR51SIGN_ERROR_INVALID_HASH:
- return "Invalid hash";
- case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE:
- return "Invalid hash type";
- case LIBCR51SIGN_ERROR_INVALID_ARGUMENT:
- return "Invalid Argument";
- case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC:
- return "Failed to locate descriptor";
- case LIBCR51SIGN_ERROR_INVALID_CONTEXT:
- return "Invalid context";
- case LIBCR51SIGN_ERROR_INVALID_INTERFACE:
- return "Invalid interface";
- case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME:
- return "Invalid signature scheme";
- case LIBCR51SIGN_ERROR_INVALID_REGION_INPUT:
- return "Invalid image region input";
- case LIBCR51SIGN_ERROR_INVALID_REGION_SIZE:
- return "Invalid image region size";
- default:
- return "Unknown error";
- }
+ case LIBCR51SIGN_SUCCESS:
+ return "Success";
+ case LIBCR51SIGN_ERROR_RUNTIME_FAILURE:
+ return "Runtime Error Failure";
+ case LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR:
+ return "Unsupported descriptor";
+ case LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR:
+ return "Invalid descriptor";
+ case LIBCR51SIGN_ERROR_INVALID_IMAGE_FAMILY:
+ return "Invalid image family";
+ case LIBCR51SIGN_ERROR_IMAGE_TYPE_DISALLOWED:
+ return "Image type disallowed";
+ case LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED:
+ return "Dev downgrade disallowed";
+ case LIBCR51SIGN_ERROR_UNTRUSTED_KEY:
+ return "Untrusted key";
+ case LIBCR51SIGN_ERROR_INVALID_SIGNATURE:
+ return "Invalid signature";
+ case LIBCR51SIGN_ERROR_INVALID_HASH:
+ return "Invalid hash";
+ case LIBCR51SIGN_ERROR_INVALID_HASH_TYPE:
+ return "Invalid hash type";
+ case LIBCR51SIGN_ERROR_INVALID_ARGUMENT:
+ return "Invalid Argument";
+ case LIBCR51SIGN_ERROR_FAILED_TO_LOCATE_MAGIC:
+ return "Failed to locate descriptor";
+ case LIBCR51SIGN_ERROR_INVALID_CONTEXT:
+ return "Invalid context";
+ case LIBCR51SIGN_ERROR_INVALID_INTERFACE:
+ return "Invalid interface";
+ case LIBCR51SIGN_ERROR_INVALID_SIG_SCHEME:
+ return "Invalid signature scheme";
+ case LIBCR51SIGN_ERROR_INVALID_REGION_INPUT:
+ return "Invalid image region input";
+ case LIBCR51SIGN_ERROR_INVALID_REGION_SIZE:
+ return "Invalid image region size";
+ default:
+ return "Unknown error";
}
+}
#ifdef __cplusplus
} // extern "C"
diff --git a/subprojects/libcr51sign/src/libcr51sign_support.c b/subprojects/libcr51sign/src/libcr51sign_support.c
index ce5103d..3118909 100644
--- a/subprojects/libcr51sign/src/libcr51sign_support.c
+++ b/subprojects/libcr51sign/src/libcr51sign_support.c
@@ -31,205 +31,205 @@
#define CPRINTS(ctx, ...) fprintf(stderr, __VA_ARGS__)
#endif
- // @func hash_init get ready to compute a hash
- //
- // @param[in] ctx - context struct
- // @param[in] hash_type - type of hash function to use
- //
- // @return nonzero on error, zero on success
+// @func hash_init get ready to compute a hash
+//
+// @param[in] ctx - context struct
+// @param[in] hash_type - type of hash function to use
+//
+// @return nonzero on error, zero on success
- int hash_init(const void* ctx, enum hash_type type)
- {
- struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
- struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
- hash_context->hash_type = type;
- if (type == HASH_SHA2_256) // SHA256_Init returns 1
- SHA256_Init(&hash_context->sha256_ctx);
- else if (type == HASH_SHA2_512)
- SHA512_Init(&hash_context->sha512_ctx);
- else
- return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+int hash_init(const void* ctx, enum hash_type type)
+{
+ struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
+ struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
+ hash_context->hash_type = type;
+ if (type == HASH_SHA2_256) // SHA256_Init returns 1
+ SHA256_Init(&hash_context->sha256_ctx);
+ else if (type == HASH_SHA2_512)
+ SHA512_Init(&hash_context->sha512_ctx);
+ else
+ return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+ return LIBCR51SIGN_SUCCESS;
+}
+
+// @func hash_update add data to the hash
+//
+// @param[in] ctx - context struct
+// @param[in] buf - data to add to hash
+// @param[in] count - number of bytes of data to add
+//
+// @return nonzero on error, zero on success
+
+int hash_update(void* ctx, const uint8_t* data, size_t size)
+{
+ if (size == 0)
return LIBCR51SIGN_SUCCESS;
- }
+ struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
+ struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
- // @func hash_update add data to the hash
- //
- // @param[in] ctx - context struct
- // @param[in] buf - data to add to hash
- // @param[in] count - number of bytes of data to add
- //
- // @return nonzero on error, zero on success
+ if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1
+ SHA256_Update(&hash_context->sha256_ctx, data, size);
+ else if (hash_context->hash_type == HASH_SHA2_512)
+ SHA512_Update(&hash_context->sha512_ctx, data, size);
+ else
+ return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
- int hash_update(void* ctx, const uint8_t* data, size_t size)
- {
- if (size == 0)
- return LIBCR51SIGN_SUCCESS;
- struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
- struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
+ return LIBCR51SIGN_SUCCESS;
+}
- if (hash_context->hash_type == HASH_SHA2_256) // SHA256_Update returns 1
- SHA256_Update(&hash_context->sha256_ctx, data, size);
- else if (hash_context->hash_type == HASH_SHA2_512)
- SHA512_Update(&hash_context->sha512_ctx, data, size);
- else
- return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+// @func hash_final finish hash calculation
+//
+// @param[in] ctx - context struct
+// @param[out] hash - buffer to write hash to (guaranteed to be big enough)
+//
+// @return nonzero on error, zero on success
+int hash_final(void* ctx, uint8_t* hash)
+{
+ int rv;
+ struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
+ struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
+
+ if (hash_context->hash_type == HASH_SHA2_256)
+ rv = SHA256_Final(hash, &hash_context->sha256_ctx);
+ else if (hash_context->hash_type == HASH_SHA2_512)
+ rv = SHA512_Final(hash, &hash_context->sha512_ctx);
+ else
+ return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+
+ if (rv)
return LIBCR51SIGN_SUCCESS;
- }
+ else
+ return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+}
- // @func hash_final finish hash calculation
- //
- // @param[in] ctx - context struct
- // @param[out] hash - buffer to write hash to (guaranteed to be big enough)
- //
- // @return nonzero on error, zero on success
+// @func verify check that the signature is valid for given hashed data
+//
+// @param[in] ctx - context struct
+// @param[in] scheme - type of signature, hash, etc.
+// @param[in] sig - signature blob
+// @param[in] sig_len - length of signature in bytes
+// @param[in] data - pre-hashed data to verify
+// @param[in] data_len - length of hashed data in bytes
+//
+// verify_signature expects RSA public key file path in ctx->key_ring
+// @return nonzero on error, zero on success
- int hash_final(void* ctx, uint8_t* hash)
+int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
+ const uint8_t* sig, size_t sig_len, const uint8_t* data,
+ size_t data_len)
+{
+ // By default returns error.
+ int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
+
+ CPRINTS(ctx, "sig_len %zu sig: ", sig_len);
+ for (size_t i = 0; i < sig_len; i++)
{
- int rv;
- struct libcr51sign_ctx* context = (struct libcr51sign_ctx*)ctx;
- struct hash_ctx* hash_context = (struct hash_ctx*)context->priv;
-
- if (hash_context->hash_type == HASH_SHA2_256)
- rv = SHA256_Final(hash, &hash_context->sha256_ctx);
- else if (hash_context->hash_type == HASH_SHA2_512)
- rv = SHA512_Final(hash, &hash_context->sha512_ctx);
- else
- return LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
-
- if (rv)
- return LIBCR51SIGN_SUCCESS;
- else
- return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ CPRINTS(ctx, "%x", sig[i]);
}
+ CPRINTS(ctx, "\n");
- // @func verify check that the signature is valid for given hashed data
- //
- // @param[in] ctx - context struct
- // @param[in] scheme - type of signature, hash, etc.
- // @param[in] sig - signature blob
- // @param[in] sig_len - length of signature in bytes
- // @param[in] data - pre-hashed data to verify
- // @param[in] data_len - length of hashed data in bytes
- //
- // verify_signature expects RSA public key file path in ctx->key_ring
- // @return nonzero on error, zero on success
-
- int verify_signature(const void* ctx, enum signature_scheme sig_scheme,
- const uint8_t* sig, size_t sig_len,
- const uint8_t* data, size_t data_len)
+ struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
+ FILE* fp = fopen(lctx->keyring, "r");
+ RSA *rsa = NULL, *pub_rsa = NULL;
+ EVP_PKEY* pkey = NULL;
+ BIO* bio = BIO_new(BIO_s_mem());
+ if (!fp)
{
- // By default returns error.
- int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
-
- CPRINTS(ctx, "sig_len %zu sig: ", sig_len);
- for (size_t i = 0; i < sig_len; i++)
- {
- CPRINTS(ctx, "%x", sig[i]);
- }
- CPRINTS(ctx, "\n");
-
- struct libcr51sign_ctx* lctx = (struct libcr51sign_ctx*)ctx;
- FILE* fp = fopen(lctx->keyring, "r");
- RSA *rsa = NULL, *pub_rsa = NULL;
- EVP_PKEY* pkey = NULL;
- BIO* bio = BIO_new(BIO_s_mem());
- if (!fp)
- {
- CPRINTS(ctx, "fopen failed\n");
- goto clean_up;
- }
-
- pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
- if (!pkey)
- {
- CPRINTS(ctx, "Read public key failed\n");
- goto clean_up;
- }
-
- rsa = EVP_PKEY_get1_RSA(pkey);
- if (!rsa)
- {
- goto clean_up;
- }
- pub_rsa = RSAPublicKey_dup(rsa);
- if (!RSA_print(bio, pub_rsa, 2))
- {
- CPRINTS(ctx, "RSA print failed\n");
- }
- if (!pub_rsa)
- {
- CPRINTS(ctx, "no pub RSA\n");
- goto clean_up;
- }
- CPRINTS(ctx, "public RSA\n");
- char buffer[1024];
- while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
- {
- CPRINTS(ctx, " %s", buffer);
- }
- enum hash_type hash_type;
- rv = get_hash_type_from_signature(sig_scheme, &hash_type);
- if (rv != LIBCR51SIGN_SUCCESS)
- {
- CPRINTS(ctx, "Invalid hash_type!\n");
- goto clean_up;
- }
- int hash_nid = -1;
- if (hash_type == HASH_SHA2_256)
- {
- hash_nid = NID_sha256;
- }
- else if (hash_type == HASH_SHA2_512)
- {
- hash_nid = NID_sha512;
- }
- else
- {
- rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
- goto clean_up;
- }
-
- int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
- // OpenSSL RSA_verify returns 1 on success and 0 on failure
- if (!ret)
- {
- CPRINTS(ctx, "OPENSSL_ERROR: %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
- goto clean_up;
- }
- rv = LIBCR51SIGN_SUCCESS;
- CPRINTS(ctx, "sig: ");
- for (size_t i = 0; i < sig_len; i++)
- {
- CPRINTS(ctx, "%x", sig[i]);
- }
- CPRINTS(ctx, "\n");
-
- CPRINTS(ctx, "data: ");
- for (size_t i = 0; i < data_len; i++)
- {
- CPRINTS(ctx, "%x", data[i]);
- }
- CPRINTS(ctx, "\n");
-
- const unsigned rsa_size = RSA_size(pub_rsa);
- CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
-
- clean_up:
- if (fp)
- {
- fclose(fp);
- }
- EVP_PKEY_free(pkey);
- RSA_free(rsa);
- RSA_free(pub_rsa);
- BIO_free(bio);
- return rv;
+ CPRINTS(ctx, "fopen failed\n");
+ goto clean_up;
}
+ pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
+ if (!pkey)
+ {
+ CPRINTS(ctx, "Read public key failed\n");
+ goto clean_up;
+ }
+
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (!rsa)
+ {
+ goto clean_up;
+ }
+ pub_rsa = RSAPublicKey_dup(rsa);
+ if (!RSA_print(bio, pub_rsa, 2))
+ {
+ CPRINTS(ctx, "RSA print failed\n");
+ }
+ if (!pub_rsa)
+ {
+ CPRINTS(ctx, "no pub RSA\n");
+ goto clean_up;
+ }
+ CPRINTS(ctx, "public RSA\n");
+ char buffer[1024];
+ while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
+ {
+ CPRINTS(ctx, " %s", buffer);
+ }
+ enum hash_type hash_type;
+ rv = get_hash_type_from_signature(sig_scheme, &hash_type);
+ if (rv != LIBCR51SIGN_SUCCESS)
+ {
+ CPRINTS(ctx, "Invalid hash_type!\n");
+ goto clean_up;
+ }
+ int hash_nid = -1;
+ if (hash_type == HASH_SHA2_256)
+ {
+ hash_nid = NID_sha256;
+ }
+ else if (hash_type == HASH_SHA2_512)
+ {
+ hash_nid = NID_sha512;
+ }
+ else
+ {
+ rv = LIBCR51SIGN_ERROR_INVALID_HASH_TYPE;
+ goto clean_up;
+ }
+
+ int ret = RSA_verify(hash_nid, data, data_len, sig, sig_len, pub_rsa);
+ // OpenSSL RSA_verify returns 1 on success and 0 on failure
+ if (!ret)
+ {
+ CPRINTS(ctx, "OPENSSL_ERROR: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ rv = LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
+ goto clean_up;
+ }
+ rv = LIBCR51SIGN_SUCCESS;
+ CPRINTS(ctx, "sig: ");
+ for (size_t i = 0; i < sig_len; i++)
+ {
+ CPRINTS(ctx, "%x", sig[i]);
+ }
+ CPRINTS(ctx, "\n");
+
+ CPRINTS(ctx, "data: ");
+ for (size_t i = 0; i < data_len; i++)
+ {
+ CPRINTS(ctx, "%x", data[i]);
+ }
+ CPRINTS(ctx, "\n");
+
+ const unsigned rsa_size = RSA_size(pub_rsa);
+ CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
+
+clean_up:
+ if (fp)
+ {
+ fclose(fp);
+ }
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ RSA_free(pub_rsa);
+ BIO_free(bio);
+ return rv;
+}
+
#ifdef __cplusplus
} // extern "C"
#endif