libcr51sign: Sync with latest code

Change-Id: Id3de25f3b112aa84d4b2342f606a60bb049487c8
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h b/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h
index d56fc05..8a673b2 100644
--- a/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h
+++ b/subprojects/libcr51sign/include/libcr51sign/libcr51sign.h
@@ -167,6 +167,9 @@
         //         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
diff --git a/subprojects/libcr51sign/src/libcr51sign.c b/subprojects/libcr51sign/src/libcr51sign.c
index d89c88d..b9be35e 100644
--- a/subprojects/libcr51sign/src/libcr51sign.c
+++ b/subprojects/libcr51sign/src/libcr51sign.c
@@ -190,12 +190,12 @@
         if (rv != LIBCR51SIGN_SUCCESS)
         {
             CPRINTS(ctx,
-                    "validate_transition: failed to read signature struct");
+                    "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");
+            CPRINTS(ctx, "validate_transition: bad signature magic\n");
             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
         }
 
@@ -203,26 +203,26 @@
             ctx->descriptor.image_family != IMAGE_FAMILY_ALL &&
             ctx->current_image_family != IMAGE_FAMILY_ALL)
         {
-            CPRINTS(ctx, "validate_transition: invalid image family");
+            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");
+            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");
+            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())
             {
-                CPRINTS(ctx, "validate_transition: illegal image type");
+                CPRINTS(ctx, "validate_transition: illegal image type\n");
                 return LIBCR51SIGN_ERROR_DEV_DOWNGRADE_DISALLOWED;
             }
         }
@@ -249,7 +249,7 @@
         {
             if (!intf->hash_update)
             {
-                CPRINTS(ctx, "read_and_hash_update: missing hash_update");
+                CPRINTS(ctx, "read_and_hash_update: missing hash_update\n");
                 return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
             }
             do
@@ -295,7 +295,7 @@
 
         if (image_regions == NULL)
         {
-            CPRINTS(ctx, "Missing image region input");
+            CPRINTS(ctx, "Missing image region input\n");
             return LIBCR51SIGN_ERROR_INVALID_REGION_INPUT;
         }
 
@@ -311,7 +311,7 @@
         {
             CPRINTS(ctx, "validate_payload_regions: "
                          "ctx->descriptor.region_count is greater "
-                         "than LIBCR51SIGN_MAX_REGION_COUNT");
+                         "than LIBCR51SIGN_MAX_REGION_COUNT\n");
             return LIBCR51SIGN_ERROR_INVALID_REGION_SIZE;
         }
 
@@ -324,7 +324,7 @@
         if (rv != LIBCR51SIGN_SUCCESS)
         {
             CPRINTS(ctx,
-                    "validate_payload_regions: failed to read region array");
+                    "validate_payload_regions: failed to read region array\n");
             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
         }
 
@@ -334,21 +334,21 @@
             region = image_regions->image_regions + i;
 
             CPRINTS(ctx,
-                    "validate_payload_regions: region #%d \"%s\" (%x - %x)", i,
-                    (const char*)region->region_name, region->region_offset,
+                    "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");
+                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");
+                CPRINTS(ctx,
+                        "validate_payload_regions: invalid region array\n");
                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
             }
             byte_count += region->region_size;
@@ -358,7 +358,7 @@
                 d_region_num = i;
                 CPRINTS(
                     ctx,
-                    "validate_payload_regions: image descriptor in region %d",
+                    "validate_payload_regions: image descriptor in region %d\n",
                     i);
                 // The descriptor can't span regions.
                 if (ctx->descriptor.descriptor_area_size > byte_count ||
@@ -367,14 +367,14 @@
                     CPRINTS(
                         ctx,
                         "validate_payload_regions: descriptor must reside in "
-                        "static region");
+                        "static region\n");
                     return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
                 }
             }
         }
         if (byte_count != image_size)
         {
-            CPRINTS(ctx, "validate_payload_regions: invalid image size");
+            CPRINTS(ctx, "validate_payload_regions: invalid image size\n");
             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
         }
 
@@ -390,19 +390,20 @@
                         magic_and_digest);
         if (rv != LIBCR51SIGN_SUCCESS)
         {
-            CPRINTS(ctx,
-                    "validate_payload_regions: failed to read hash from flash");
+            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");
+            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");
+            CPRINTS(ctx, "validate_payload_regions: hash_init failed\n");
             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
         }
         for (i = 0; i < region_count; i++)
@@ -431,7 +432,7 @@
                     hash_size = (region->region_offset + region->region_size -
                                  hash_start);
                 }
-                CPRINTS("validate_payload_regions: hashing %s (%x - %x)",
+                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.
@@ -454,7 +455,7 @@
                        MEMBER_SIZE(struct hash_sha256, hash_magic),
                    dcrypto_digest, digest_size))
         {
-            CPRINTS(ctx, "validate_payload_regions: invalid hash");
+            CPRINTS(ctx, "validate_payload_regions: invalid hash\n");
             return LIBCR51SIGN_ERROR_INVALID_HASH;
         }
         // Image is valid.
@@ -570,7 +571,7 @@
 
         if (!intf->hash_init)
         {
-            CPRINTS(ctx, "validate_signature: missing hash_init");
+            CPRINTS(ctx, "validate_signature: missing hash_init\n");
             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
         }
         rv = get_hash_type_from_signature(scheme, &hash_type);
@@ -578,30 +579,31 @@
         {
             CPRINTS(
                 ctx,
-                "validate_payload_regions: hash_type from signature failed");
+                "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");
+            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");
+            CPRINTS(ctx, "validate_signature: hash_update failed\n");
             return rv;
         }
         if (!intf->hash_final)
         {
-            CPRINTS(ctx, "validate_signature: missing 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)",
+            CPRINTS(ctx,
+                    "validate_signature: hash_final failed (status = %d)\n",
                     rv);
             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
         }
@@ -616,13 +618,13 @@
         {
             CPRINTS(
                 ctx,
-                "validate_signature: failed to read signature (status = %d)",
+                "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");
+            CPRINTS(ctx, "validate_signature: missing verify_signature\n");
             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
         }
         rv = get_hash_digest_size(hash_type, &digest_size);
@@ -635,11 +637,11 @@
         if (rv != LIBCR51SIGN_SUCCESS)
         {
             CPRINTS(ctx,
-                    "validate_signature: verification failed (status = %d)",
+                    "validate_signature: verification failed (status = %d)\n",
                     rv);
             return LIBCR51SIGN_ERROR_INVALID_SIGNATURE;
         }
-        CPRINTS(ctx, "validate_signature: verification succeeded");
+        CPRINTS(ctx, "validate_signature: verification succeeded\n");
         return LIBCR51SIGN_SUCCESS;
     }
 
@@ -652,12 +654,12 @@
     // and environment
     //@param offset  Absolute image descriptor flash offset.
     //@param relative_offset  Image descriptor offset relative to image start.
-    //@param image_size  Image size in bytes.
+    //@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 image_size)
+        uint32_t offset, uint32_t relative_offset, uint32_t max_size)
     {
         uint32_t max_descriptor_size, signed_size, signature_scheme,
             signature_offset;
@@ -665,11 +667,11 @@
             hash_struct_size;
         int rv;
 
-        max_descriptor_size = image_size - relative_offset;
-        if (image_size < relative_offset ||
+        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");
+            CPRINTS(ctx, "validate_descriptor: invalid arguments\n");
             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
         }
 
@@ -677,16 +679,31 @@
                         (uint8_t*)&ctx->descriptor);
         if (rv != LIBCR51SIGN_SUCCESS)
         {
-            CPRINTS(ctx, "validate_descriptor: failed to read descriptor");
+            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 != image_size)
+            ctx->descriptor.image_size > max_size)
         {
-            CPRINTS(ctx, "validate_descriptor: invalid descriptor");
+            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;
+            }
+        }
+        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 &&
@@ -695,7 +712,7 @@
             ctx->descriptor.image_type != IMAGE_TEST &&
             ctx->descriptor.image_type != IMAGE_UNSIGNED_INTEGRITY)
         {
-            CPRINTS(ctx, "validate_descriptor: bad image type");
+            CPRINTS(ctx, "validate_descriptor: bad image type\n");
             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
         }
         // Although the image_descriptor struct supports unauthenticated
@@ -712,13 +729,13 @@
         rv = is_hash_type_supported(ctx->descriptor.hash_type);
         if (rv != LIBCR51SIGN_SUCCESS)
         {
-            CPRINTS(ctx, "validate_payload_regions: invalid hash type");
+            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");
+            CPRINTS(ctx, "validate_descriptor: unsupported descriptor\n");
             return LIBCR51SIGN_ERROR_UNSUPPORTED_DESCRIPTOR;
         }
         rv =
@@ -751,7 +768,7 @@
             if (ctx->descriptor.blob_size >
                 ctx->descriptor.descriptor_area_size - signed_size)
             {
-                CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)",
+                CPRINTS(ctx, "validate_descriptor: invalid blob size (0x%x)\n",
                         ctx->descriptor.blob_size);
                 return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
             }
@@ -762,7 +779,7 @@
         {
             CPRINTS(ctx,
                     "validate_descriptor: invalid descriptor area size "
-                    "(expected = 0x%x, actual = 0x%x)",
+                    "(expected = 0x%x, actual = 0x%x)\n",
                     ctx->descriptor.descriptor_area_size,
                     signed_size + signature_struct_size);
             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
@@ -814,7 +831,7 @@
 
         if (!intf->read)
         {
-            CPRINTS(ctx, "scan_for_magic_8: missing 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.
@@ -866,12 +883,12 @@
 
         if (!ctx)
         {
-            CPRINTS(ctx, "MIssing context");
+            CPRINTS(ctx, "Missing context\n");
             return LIBCR51SIGN_ERROR_INVALID_CONTEXT;
         }
         else if (!intf)
         {
-            CPRINTS(ctx, "Missing interface");
+            CPRINTS(ctx, "Missing interface\n");
             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
         }
 
@@ -880,7 +897,7 @@
                               &descriptor_offset);
         while (rv == LIBCR51SIGN_SUCCESS)
         {
-            CPRINTS(ctx, "validate: potential image descriptor found @%x ",
+            CPRINTS(ctx, "validate: potential image descriptor found @%x\n",
                     descriptor_offset);
             // Validation is split into 2 functions to minimize
             // stack usage.
@@ -890,7 +907,7 @@
                                      ctx->end_offset - ctx->start_offset);
             if (rv != LIBCR51SIGN_SUCCESS)
             {
-                CPRINTS(ctx, "validate: validate_descriptor() failed ec%d ",
+                CPRINTS(ctx, "validate: validate_descriptor() failed ec%d\n",
                         rv);
             }
 
@@ -900,11 +917,11 @@
                     ctx, intf, descriptor_offset, image_regions);
                 if (rv == LIBCR51SIGN_SUCCESS)
                 {
-                    CPRINTS(ctx, "validate: success!");
+                    CPRINTS(ctx, "validate: success!\n");
                     return rv;
                 }
                 CPRINTS(ctx,
-                        "validate: validate_payload_regions() failed ec%d ",
+                        "validate: validate_payload_regions() failed ec%d\n",
                         rv);
             }
             // Store the first desc fail reason if any
@@ -919,7 +936,7 @@
                                   descriptor_offset, image_limit,
                                   DESCRIPTOR_ALIGNMENT, &descriptor_offset);
         }
-        CPRINTS(ctx, "validate: failed to validate image ec%d ", 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;
diff --git a/subprojects/libcr51sign/src/libcr51sign_support.c b/subprojects/libcr51sign/src/libcr51sign_support.c
index 4e9c517..6dddf23 100644
--- a/subprojects/libcr51sign/src/libcr51sign_support.c
+++ b/subprojects/libcr51sign/src/libcr51sign_support.c
@@ -122,11 +122,12 @@
         // By default returns error.
         int rv = LIBCR51SIGN_ERROR_INVALID_ARGUMENT;
 
-        CPRINTS(ctx, "\n sig_len %zu sig: ", sig_len);
+        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");
@@ -135,14 +136,14 @@
         BIO* bio = BIO_new(BIO_s_mem());
         if (!fp)
         {
-            CPRINTS(ctx, "\n fopen failed: ");
+            CPRINTS(ctx, "fopen failed\n");
             goto clean_up;
         }
 
         pkey = PEM_read_PUBKEY(fp, 0, 0, 0);
         if (!pkey)
         {
-            CPRINTS(ctx, "\n Read public key failed: ");
+            CPRINTS(ctx, "Read public key failed\n");
             goto clean_up;
         }
 
@@ -154,14 +155,14 @@
         pub_rsa = RSAPublicKey_dup(rsa);
         if (!RSA_print(bio, pub_rsa, 2))
         {
-            CPRINTS(ctx, "\n RSA print failed ");
+            CPRINTS(ctx, "RSA print failed\n");
         }
         if (!pub_rsa)
         {
-            CPRINTS(ctx, "\n no pub rsa: ");
+            CPRINTS(ctx, "no pub RSA\n");
             goto clean_up;
         }
-        CPRINTS(ctx, "\n public rsa \n");
+        CPRINTS(ctx, "public RSA\n");
         char buffer[1024];
         while (BIO_read(bio, buffer, sizeof(buffer) - 1) > 0)
         {
@@ -171,7 +172,7 @@
         rv = get_hash_type_from_signature(sig_scheme, &hash_type);
         if (rv != LIBCR51SIGN_SUCCESS)
         {
-            CPRINTS(ctx, "\n Invalid hash_type! \n");
+            CPRINTS(ctx, "Invalid hash_type!\n");
             goto clean_up;
         }
         int hash_nid = -1;
@@ -193,25 +194,28 @@
         // OpenSSL RSA_verify returns 1 on success and 0 on failure
         if (!ret)
         {
-            CPRINTS(ctx, "\n OPENSSL_ERROR: %s \n",
+            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, "\n sig: ");
+        CPRINTS(ctx, "sig: ");
         for (size_t i = 0; i < sig_len; i++)
         {
             CPRINTS(ctx, "%x", sig[i]);
         }
+        CPRINTS(ctx, "\n");
 
-        CPRINTS(ctx, "\n data: ");
+        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, "\n rsa size %d sig_len %d", rsa_size, (uint32_t)sig_len);
+        CPRINTS(ctx, "rsa size %d sig_len %d\n", rsa_size, (uint32_t)sig_len);
 
     clean_up:
         if (fp)