Fix Trust Token CBOR.

CBOR requires map keys to be sorted by length followed by alphabet,
but only some parsers enforce this requirement.

Change-Id: I63cad4ec27f1509704be7a755b5486b0f4baa800
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40747
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/trust_token/trust_token.c b/crypto/trust_token/trust_token.c
index 186fdbc..bc93562 100644
--- a/crypto/trust_token/trust_token.c
+++ b/crypto/trust_token/trust_token.c
@@ -642,19 +642,25 @@
   static const char kPrivateLabel[] = "private";
   static const char kPublicLabel[] = "public";
 
+  // CBOR requires map keys to be sorted by length then sorted lexically.
+  // https://tools.ietf.org/html/rfc7049#section-3.9
+  assert(strlen(kMetadataLabel) < strlen(kClientDataLabel));
+  assert(strlen(kClientDataLabel) < strlen(kExpiryTimestampLabel));
+  assert(strlen(kPublicLabel) < strlen(kPrivateLabel));
+
   if (!CBB_init(&srr, 0) ||
       !add_cbor_map(&srr, 3) ||  // SRR map
+      !add_cbor_text(&srr, kMetadataLabel, strlen(kMetadataLabel)) ||
+      !add_cbor_map(&srr, 2) ||  // Metadata map
+      !add_cbor_text(&srr, kPublicLabel, strlen(kPublicLabel)) ||
+      !add_cbor_int(&srr, public_metadata) ||
+      !add_cbor_text(&srr, kPrivateLabel, strlen(kPrivateLabel)) ||
+      !add_cbor_int(&srr, private_metadata ^ metadata_obfuscator) ||
       !add_cbor_text(&srr, kClientDataLabel, strlen(kClientDataLabel)) ||
       !CBB_add_bytes(&srr, CBS_data(&client_data), CBS_len(&client_data)) ||
       !add_cbor_text(&srr, kExpiryTimestampLabel,
                      strlen(kExpiryTimestampLabel)) ||
       !add_cbor_int(&srr, redemption_time + lifetime) ||
-      !add_cbor_text(&srr, kMetadataLabel, strlen(kMetadataLabel)) ||
-      !add_cbor_map(&srr, 2) ||  // Metadata map
-      !add_cbor_text(&srr, kPrivateLabel, strlen(kPrivateLabel)) ||
-      !add_cbor_int(&srr, private_metadata ^ metadata_obfuscator) ||
-      !add_cbor_text(&srr, kPublicLabel, strlen(kPublicLabel)) ||
-      !add_cbor_int(&srr, public_metadata) ||
       !CBB_finish(&srr, &srr_buf, &srr_len)) {
     OPENSSL_PUT_ERROR(TRUST_TOKEN, ERR_R_MALLOC_FAILURE);
     goto err;
diff --git a/crypto/trust_token/trust_token_test.cc b/crypto/trust_token/trust_token_test.cc
index b9bd69e..1d3f543 100644
--- a/crypto/trust_token/trust_token_test.cc
+++ b/crypto/trust_token/trust_token_test.cc
@@ -203,7 +203,7 @@
   ASSERT_TRUE(tokens);
 
   for (TRUST_TOKEN *token : tokens.get()) {
-    const uint8_t kClientData[] = "TEST CLIENT DATA";
+    const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
     uint64_t kRedemptionTime = 13374242;
 
     uint8_t *redeem_msg = NULL, *redeem_resp = NULL;
@@ -244,7 +244,7 @@
   ASSERT_TRUE(tokens);
 
   for (TRUST_TOKEN *token : tokens.get()) {
-    const uint8_t kClientData[] = "TEST CLIENT DATA";
+    const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
     uint64_t kRedemptionTime = 13374242;
 
     uint8_t *redeem_msg = NULL, *redeem_resp = NULL;
@@ -360,15 +360,15 @@
   ASSERT_TRUE(tokens);
 
   for (TRUST_TOKEN *token : tokens.get()) {
-    const uint8_t kClientData[] = "TEST CLIENT DATA";
+    const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
     uint64_t kRedemptionTime = 13374242;
 
     const uint8_t kExpectedSRR[] =
-        "\xa3\x6b\x63\x6c\x69\x65\x6e\x74\x2d\x64\x61\x74\x61\x54\x45\x53\x54"
-        "\x20\x43\x4c\x49\x45\x4e\x54\x20\x44\x41\x54\x41\x70\x65\x78\x70\x69"
-        "\x72\x79\x2d\x74\x69\x6d\x65\x73\x74\x61\x6d\x70\x1a\x00\xcc\x15\x7a"
-        "\x68\x6d\x65\x74\x61\x64\x61\x74\x61\xa2\x67\x70\x72\x69\x76\x61\x74"
-        "\x65\x00\x66\x70\x75\x62\x6c\x69\x63\x00";
+        "\xa3\x68\x6d\x65\x74\x61\x64\x61\x74\x61\xa2\x66\x70\x75\x62\x6c\x69"
+        "\x63\x00\x67\x70\x72\x69\x76\x61\x74\x65\x00\x6b\x63\x6c\x69\x65\x6e"
+        "\x74\x2d\x64\x61\x74\x61\x70\x54\x45\x53\x54\x20\x43\x4c\x49\x45\x4e"
+        "\x54\x20\x44\x41\x54\x41\x70\x65\x78\x70\x69\x72\x79\x2d\x74\x69\x6d"
+        "\x65\x73\x74\x61\x6d\x70\x1a\x00\xcc\x15\x7a";
 
     uint8_t *redeem_msg = NULL, *redeem_resp = NULL;
     ASSERT_TRUE(TRUST_TOKEN_CLIENT_begin_redemption(
@@ -400,13 +400,13 @@
     uint8_t private_metadata;
     ASSERT_TRUE(TRUST_TOKEN_decode_private_metadata(
         &private_metadata, metadata_key, sizeof(metadata_key), kClientData,
-        sizeof(kClientData) - 1, srr[srr_len - 9]));
-    ASSERT_EQ(srr[srr_len - 1], std::get<0>(GetParam()));
+        sizeof(kClientData) - 1, srr[27]));
+    ASSERT_EQ(srr[18], std::get<0>(GetParam()));
     ASSERT_EQ(private_metadata, std::get<1>(GetParam()));
 
     // Clear out the metadata bits.
-    srr[srr_len - 9] = 0;
-    srr[srr_len - 1] = 0;
+    srr[18] = 0;
+    srr[27] = 0;
 
     ASSERT_TRUE(sizeof(kExpectedSRR) - 1 == srr_len);
     ASSERT_EQ(OPENSSL_memcmp(kExpectedSRR, srr, srr_len), 0);