Merge remote-tracking branch 'aosp/upstream-main' into HEAD

Bug: 268592034
Test: mmm external/open-dice
Change-Id: If2f8dea90582da00103b58f1639414b01e2e7467
diff --git a/include/dice/android/bcc.h b/include/dice/android/bcc.h
index 06f9fcb..366c51f 100644
--- a/include/dice/android/bcc.h
+++ b/include/dice/android/bcc.h
@@ -40,7 +40,10 @@
   uint64_t component_version;
 } BccConfigValues;
 
-// Formats a configuration descriptor following the BCC's specification.
+// Formats a configuration descriptor following the BCC's specification. On
+// success, |actual_size| is set to the number of bytes used. If
+// kDiceResultBufferTooSmall is returned |actual_size| will be set to the
+// required size of the buffer.
 DiceResult BccFormatConfigDescriptor(const BccConfigValues* input_values,
                                      size_t buffer_size, uint8_t* buffer,
                                      size_t* actual_size);
@@ -52,7 +55,10 @@
 // the BCC handover format, use BccHandoverMainFlow instead.
 //
 // Given a full set of input values along with the current BCC and CDI values,
-// computes the next CDI values and matching updated BCC.
+// computes the next CDI values and matching updated BCC. On success,
+// |actual_size| is set to the number of bytes used. If
+// kDiceResultBufferTooSmall is returned |actual_size| will be set to the
+// required size of the buffer.
 DiceResult BccMainFlow(void* context,
                        const uint8_t current_cdi_attest[DICE_CDI_SIZE],
                        const uint8_t current_cdi_seal[DICE_CDI_SIZE],
@@ -68,7 +74,9 @@
 // combine the BCC and CDIs in a single CBOR object.
 //
 // Given a full set of input values and the current BCC handover data, computes
-// the next BCC handover data.
+// the next BCC handover data. On success, |actual_size| is set to the number
+// of bytes used. If kDiceResultBufferTooSmall is returned |actual_size| will
+// be set to the required size of the buffer.
 //
 // Using a CBOR object to bundle is one option for passing the values passed
 // between boot stages. This function can take the current boot stage's bundle
diff --git a/include/dice/known_test_values.h b/include/dice/known_test_values.h
index c3a052b..cb0925b 100644
--- a/include/dice/known_test_values.h
+++ b/include/dice/known_test_values.h
@@ -54,8 +54,7 @@
 //                     5c:8d
 //         X509v3 extensions:
 //             X509v3 Authority Key Identifier:
-//                 keyid:7A:06:EE:E4:1B:78:9F:48:63:D8:6B:87:78:B1:A2:01:A6:FE:DD:56
-//
+//                 7A:06:EE:E4:1B:78:9F:48:63:D8:6B:87:78:B1:A2:01:A6:FE:DD:56
 //             X509v3 Subject Key Identifier:
 //                 67:C2:2A:88:59:06:2B:98:68:18:E8:E7:2B:0B:CD:9F:59:34:9C:89
 //             X509v3 Key Usage: critical
@@ -86,10 +85,11 @@
 //   209:d=2  hl=2 l=   1 prim:   ENUMERATED        :00
 //
 //     Signature Algorithm: ED25519
-//          70:23:a8:a3:78:fe:5f:8c:8d:83:49:95:ff:ee:e6:12:39:9c:
-//          4d:a0:49:f6:4b:4f:f7:02:1e:9f:97:0c:bd:3b:7f:94:78:26:
-//          09:fe:f2:91:7c:a4:dd:90:07:cc:95:a8:bc:4a:f4:84:69:ec:
-//          24:a4:9e:b7:01:0e:81:3a:a3:0a
+//     Signature Value:
+//         70:23:a8:a3:78:fe:5f:8c:8d:83:49:95:ff:ee:e6:12:39:9c:
+//         4d:a0:49:f6:4b:4f:f7:02:1e:9f:97:0c:bd:3b:7f:94:78:26:
+//         09:fe:f2:91:7c:a4:dd:90:07:cc:95:a8:bc:4a:f4:84:69:ec:
+//         24:a4:9e:b7:01:0e:81:3a:a3:0a
 constexpr uint8_t kExpectedX509Ed25519Cert_ZeroInput[638] = {
     0x30, 0x82, 0x02, 0x7a, 0x30, 0x82, 0x02, 0x2c, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x67, 0xc2, 0x2a, 0x88, 0x59, 0x06, 0x2b, 0x98, 0x68,
@@ -171,8 +171,7 @@
 //                 NIST CURVE: P-256
 //         X509v3 extensions:
 //             X509v3 Authority Key Identifier:
-//                 keyid:4C:51:4D:88:DB:0F:81:D5:7B:EB:96:17:7E:3D:7E:A4:AA:58:1E:66
-//
+//                 4C:51:4D:88:DB:0F:81:D5:7B:EB:96:17:7E:3D:7E:A4:AA:58:1E:66
 //             X509v3 Subject Key Identifier:
 //                 7C:7D:C0:A3:C1:E7:8D:4E:68:BC:C1:A2:32:9E:F9:1C:A8:12:44:91
 //             X509v3 Key Usage: critical
@@ -203,10 +202,11 @@
 //   209:d=2  hl=2 l=   1 prim:   ENUMERATED        :00
 //
 //     Signature Algorithm: ecdsa-with-SHA512
-//          30:44:02:20:5c:20:d4:32:af:59:4b:44:fc:49:e5:d4:5d:b6:
-//          fe:9c:ac:55:02:74:8b:66:c8:8c:f5:9a:70:8a:97:3c:bc:e0:
-//          02:20:66:83:d1:78:8c:75:44:83:90:c7:1e:d7:4c:98:1f:10:
-//          7f:14:6a:45:c0:1c:48:99:ce:6e:8f:6d:d3:dc:f3:93
+//     Signature Value:
+//         30:44:02:20:5c:20:d4:32:af:59:4b:44:fc:49:e5:d4:5d:b6:
+//         fe:9c:ac:55:02:74:8b:66:c8:8c:f5:9a:70:8a:97:3c:bc:e0:
+//         02:20:66:83:d1:78:8c:75:44:83:90:c7:1e:d7:4c:98:1f:10:
+//         7f:14:6a:45:c0:1c:48:99:ce:6e:8f:6d:d3:dc:f3:93
 constexpr uint8_t kExpectedX509P256Cert_ZeroInput[705] = {
     0x30, 0x82, 0x02, 0xbd, 0x30, 0x82, 0x02, 0x62, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x7c, 0x7d, 0xc0, 0xa3, 0xc1, 0xe7, 0x8d, 0x4e, 0x68,
@@ -349,15 +349,15 @@
     0xfc, 0xe0, 0x3c, 0xdc, 0x5d, 0x1b, 0x58, 0x16, 0x69, 0xdd, 0x44, 0x24,
     0x67, 0xbf, 0x21, 0xd7, 0x47, 0xf3, 0x13, 0xd1, 0x47, 0x6c, 0x4b, 0xd3,
     0x05, 0xb5, 0x29, 0xa0, 0xf1, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20,
-    0x58, 0x60, 0xb0, 0xb7, 0x0f, 0x47, 0xfa, 0xba, 0xca, 0x05, 0x16, 0x4f,
-    0x1e, 0xd1, 0x73, 0x15, 0x94, 0x17, 0xcd, 0x6b, 0x3c, 0x0e, 0x18, 0x77,
-    0xc0, 0x6e, 0x53, 0x97, 0xf2, 0x03, 0xb9, 0xbb, 0x82, 0xde, 0xe0, 0x2d,
-    0xb3, 0xc8, 0x0e, 0x7a, 0x5e, 0xb0, 0x74, 0x15, 0xbe, 0x25, 0x6a, 0x7c,
-    0x90, 0x30, 0x80, 0x0c, 0x90, 0x20, 0x00, 0xc5, 0x42, 0xbf, 0xf7, 0x4e,
-    0x1b, 0xd8, 0xe2, 0xe4, 0x32, 0xd5, 0xf3, 0x8e, 0x1e, 0x59, 0x9f, 0x1e,
-    0x71, 0x8e, 0xc3, 0x2e, 0x50, 0x8a, 0xa0, 0x02, 0xa4, 0xd3, 0xe6, 0x8c,
-    0x68, 0xbb, 0x5e, 0x33, 0xfd, 0x81, 0x12, 0xa7, 0xdc, 0x68, 0xc7, 0x7a,
-    0x4b, 0xfa};
+    0x58, 0x60, 0x2b, 0xe7, 0xe6, 0xee, 0xd2, 0x40, 0xa4, 0xf6, 0x2b, 0x30,
+    0xda, 0x0d, 0x60, 0x89, 0xa4, 0x0c, 0x99, 0xa6, 0x95, 0x85, 0x77, 0xae,
+    0xe8, 0x7f, 0xcd, 0x66, 0x81, 0xca, 0xd1, 0x5c, 0x56, 0xcf, 0x62, 0x05,
+    0xa8, 0xb8, 0x66, 0x66, 0x46, 0x39, 0xc7, 0x9a, 0x7a, 0x47, 0xe4, 0x64,
+    0xee, 0x36, 0xd9, 0x40, 0x8d, 0xd4, 0x88, 0x82, 0xbf, 0x24, 0x70, 0x56,
+    0x03, 0x23, 0x6a, 0x45, 0x39, 0x38, 0xa2, 0xdd, 0x02, 0x18, 0x7e, 0x72,
+    0x89, 0xe5, 0xf9, 0x38, 0xfe, 0xef, 0x50, 0xf4, 0x31, 0xae, 0xb4, 0xbe,
+    0x33, 0xb2, 0x22, 0xd4, 0x34, 0x16, 0xa6, 0x53, 0x49, 0xe1, 0x54, 0x1a,
+    0x9d, 0x3e};
 
 constexpr uint8_t kExpectedCdiAttest_HashOnlyInput[32] = {
     0x08, 0x4e, 0xf4, 0x06, 0xc6, 0x9b, 0xa7, 0x4b, 0x1e, 0x24, 0xd0,
@@ -390,8 +390,7 @@
 //                     9a:5a
 //         X509v3 extensions:
 //             X509v3 Authority Key Identifier:
-//                 keyid:47:57:08:EB:3B:42:6F:38:6C:FC:E8:F3:BA:F5:43:90:46:27:8D:FA
-//
+//                 47:57:08:EB:3B:42:6F:38:6C:FC:E8:F3:BA:F5:43:90:46:27:8D:FA
 //             X509v3 Subject Key Identifier:
 //                 0D:04:0E:2F:46:00:52:A5:31:1C:1B:91:DB:F9:B4:40:83:32:EC:29
 //             X509v3 Key Usage: critical
@@ -422,10 +421,11 @@
 //   209:d=2  hl=2 l=   1 prim:   ENUMERATED        :00
 //
 //     Signature Algorithm: ED25519
-//          27:68:51:a1:be:41:b7:90:03:8d:ce:ce:9c:35:9c:69:ff:f7:
-//          7c:14:fb:8d:59:06:71:cf:39:d8:c9:8e:95:79:70:f2:8f:89:
-//          af:4d:92:a7:40:c8:fb:85:2a:7c:21:3d:09:8a:d4:f2:25:96:
-//          cd:f6:29:06:73:98:db:70:74:08
+//     Signature Value:
+//         27:68:51:a1:be:41:b7:90:03:8d:ce:ce:9c:35:9c:69:ff:f7:
+//         7c:14:fb:8d:59:06:71:cf:39:d8:c9:8e:95:79:70:f2:8f:89:
+//         af:4d:92:a7:40:c8:fb:85:2a:7c:21:3d:09:8a:d4:f2:25:96:
+//         cd:f6:29:06:73:98:db:70:74:08
 constexpr uint8_t kExpectedX509Ed25519Cert_HashOnlyInput[638] = {
     0x30, 0x82, 0x02, 0x7a, 0x30, 0x82, 0x02, 0x2c, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x0d, 0x04, 0x0e, 0x2f, 0x46, 0x00, 0x52, 0xa5, 0x31,
@@ -507,8 +507,7 @@
 //                 NIST CURVE: P-256
 //         X509v3 extensions:
 //             X509v3 Authority Key Identifier:
-//                 keyid:1B:E5:68:79:33:DB:3D:9C:D5:FC:A7:29:E8:1D:66:85:46:5A:7B:F1
-//
+//                 1B:E5:68:79:33:DB:3D:9C:D5:FC:A7:29:E8:1D:66:85:46:5A:7B:F1
 //             X509v3 Subject Key Identifier:
 //                 68:49:58:D9:AE:A7:2E:BF:7C:06:AF:20:03:B6:44:47:82:4A:62:71
 //             X509v3 Key Usage: critical
@@ -539,10 +538,11 @@
 //   209:d=2  hl=2 l=   1 prim:   ENUMERATED        :00
 //
 //     Signature Algorithm: ecdsa-with-SHA512
-//          30:46:02:21:00:d0:ff:60:84:d4:74:47:eb:f4:29:86:c5:2a:
-//          12:01:f9:7e:5b:ab:fd:fe:d3:11:75:bc:26:63:71:57:2b:b1:
-//          c8:02:21:00:e0:16:72:65:b0:4a:92:ca:c6:c9:e2:0f:50:f0:
-//          1c:70:01:64:a7:8d:7d:51:e9:59:fe:e6:7f:31:28:30:04:04
+//     Signature Value:
+//         30:46:02:21:00:d0:ff:60:84:d4:74:47:eb:f4:29:86:c5:2a:
+//         12:01:f9:7e:5b:ab:fd:fe:d3:11:75:bc:26:63:71:57:2b:b1:
+//         c8:02:21:00:e0:16:72:65:b0:4a:92:ca:c6:c9:e2:0f:50:f0:
+//         1c:70:01:64:a7:8d:7d:51:e9:59:fe:e6:7f:31:28:30:04:04
 constexpr uint8_t kExpectedX509P256Cert_HashOnlyInput[707] = {
     0x30, 0x82, 0x02, 0xbf, 0x30, 0x82, 0x02, 0x62, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x68, 0x49, 0x58, 0xd9, 0xae, 0xa7, 0x2e, 0xbf, 0x7c,
@@ -685,15 +685,15 @@
     0x5c, 0x90, 0xfb, 0x4b, 0x6d, 0x96, 0x42, 0x77, 0xe2, 0xf6, 0x58, 0x3d,
     0x37, 0xa7, 0x3d, 0x2e, 0xca, 0xd1, 0x2c, 0xa4, 0xd4, 0xa7, 0xaf, 0x25,
     0xc3, 0xb2, 0xe7, 0x34, 0xf5, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20,
-    0x58, 0x60, 0x84, 0x9a, 0x2e, 0x89, 0xeb, 0x6d, 0x61, 0x93, 0xe0, 0x0e,
-    0xb9, 0x57, 0xc6, 0x84, 0x08, 0x28, 0x77, 0xeb, 0x9e, 0x39, 0xad, 0x74,
-    0x78, 0xf3, 0x8f, 0xf7, 0xdf, 0xfa, 0xa2, 0xbf, 0x01, 0x4f, 0x94, 0x1a,
-    0xa1, 0x27, 0xaa, 0x93, 0x57, 0xe4, 0x49, 0x07, 0xb9, 0xd7, 0x49, 0xdb,
-    0x73, 0x1e, 0xa1, 0x7e, 0xf1, 0x19, 0x87, 0x8e, 0x5a, 0x89, 0xb7, 0x02,
-    0x19, 0x13, 0xdb, 0x20, 0x3f, 0x5f, 0x49, 0xc9, 0xb7, 0xcf, 0x52, 0xc3,
-    0xd2, 0xf7, 0x90, 0x52, 0xf7, 0xaa, 0x39, 0x66, 0x78, 0x7a, 0x5b, 0xb3,
-    0xa7, 0xe9, 0x33, 0xc6, 0x4f, 0xe6, 0x78, 0xf3, 0x4b, 0x51, 0xf1, 0xed,
-    0x15, 0xeb};
+    0x58, 0x60, 0xd3, 0xbc, 0x6f, 0x53, 0x2c, 0x6a, 0x35, 0x3b, 0x2d, 0x7c,
+    0x4f, 0x1e, 0x1f, 0x06, 0xcf, 0x52, 0x87, 0xc2, 0xbe, 0x1c, 0x2c, 0xd1,
+    0x12, 0xd8, 0x13, 0x8e, 0xe4, 0xc8, 0x15, 0x65, 0x89, 0x97, 0xba, 0xc4,
+    0x80, 0xd2, 0xaf, 0xd2, 0xd0, 0xf8, 0x4b, 0xa1, 0xf6, 0x24, 0x5a, 0xd2,
+    0x25, 0x59, 0x7e, 0xb5, 0x6d, 0xe2, 0xae, 0x0a, 0x37, 0x4d, 0x50, 0x31,
+    0x8e, 0xc3, 0x21, 0xee, 0xf4, 0xf6, 0x7f, 0x16, 0xfd, 0xa3, 0x06, 0x27,
+    0x56, 0x0f, 0x74, 0xb7, 0xf8, 0x4c, 0xba, 0xb0, 0xc5, 0x93, 0xce, 0xe3,
+    0x24, 0x9c, 0x04, 0xdb, 0xac, 0x26, 0x14, 0xc6, 0x05, 0x04, 0xdb, 0x49,
+    0x5f, 0xe0};
 
 constexpr uint8_t kExpectedCdiAttest_DescriptorInput[32] = {
     0x20, 0xd5, 0x0c, 0x68, 0x5a, 0xd9, 0xe2, 0xdf, 0x77, 0x60, 0x78,
@@ -726,8 +726,7 @@
 //                     62:20
 //         X509v3 extensions:
 //             X509v3 Authority Key Identifier:
-//                 keyid:47:57:08:EB:3B:42:6F:38:6C:FC:E8:F3:BA:F5:43:90:46:27:8D:FA
-//
+//                 47:57:08:EB:3B:42:6F:38:6C:FC:E8:F3:BA:F5:43:90:46:27:8D:FA
 //             X509v3 Subject Key Identifier:
 //                 52:1F:03:5C:21:E3:2F:16:74:1C:1E:AE:6B:DE:D9:3C:E3:21:E0:DF
 //             X509v3 Key Usage: critical
@@ -779,10 +778,11 @@
 //   427:d=2  hl=2 l=   1 prim:   ENUMERATED        :00
 //
 //     Signature Algorithm: ED25519
-//          23:23:66:8c:b2:de:08:0a:fa:96:01:3f:5c:f3:87:ac:33:e0:
-//          d0:86:9b:f5:6b:df:2c:6e:9e:63:a5:5c:dd:d4:55:27:df:7e:
-//          6f:ad:6a:95:99:fd:0f:91:a9:44:25:42:c4:02:c5:ed:2a:b3:
-//          72:23:4e:79:76:f9:13:6e:f7:00
+//     Signature Value:
+//         23:23:66:8c:b2:de:08:0a:fa:96:01:3f:5c:f3:87:ac:33:e0:
+//         d0:86:9b:f5:6b:df:2c:6e:9e:63:a5:5c:dd:d4:55:27:df:7e:
+//         6f:ad:6a:95:99:fd:0f:91:a9:44:25:42:c4:02:c5:ed:2a:b3:
+//         72:23:4e:79:76:f9:13:6e:f7:00
 constexpr uint8_t kExpectedX509Ed25519Cert_DescriptorInput[858] = {
     0x30, 0x82, 0x03, 0x56, 0x30, 0x82, 0x03, 0x08, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x52, 0x1f, 0x03, 0x5c, 0x21, 0xe3, 0x2f, 0x16, 0x74,
@@ -882,8 +882,7 @@
 //                 NIST CURVE: P-256
 //         X509v3 extensions:
 //             X509v3 Authority Key Identifier:
-//                 keyid:1B:E5:68:79:33:DB:3D:9C:D5:FC:A7:29:E8:1D:66:85:46:5A:7B:F1
-//
+//                 1B:E5:68:79:33:DB:3D:9C:D5:FC:A7:29:E8:1D:66:85:46:5A:7B:F1
 //             X509v3 Subject Key Identifier:
 //                 2C:0D:E9:55:C4:FA:08:2C:2C:3A:0B:40:66:59:AF:A1:C1:C0:84:6C
 //             X509v3 Key Usage: critical
@@ -935,10 +934,11 @@
 //   427:d=2  hl=2 l=   1 prim:   ENUMERATED        :00
 //
 //     Signature Algorithm: ecdsa-with-SHA512
-//          30:46:02:21:00:a9:57:7d:ac:e0:80:8e:1c:7a:e1:4d:7d:2a:
-//          52:d2:5e:fb:5a:7d:45:1e:fa:67:17:04:9e:b3:05:c2:34:f0:
-//          7a:02:21:00:b7:3a:31:25:ae:1d:2b:06:8b:ba:44:d9:3a:bf:
-//          8b:e2:3f:89:e2:a6:14:0c:fa:c2:b1:dd:0c:0a:78:ac:60:19
+//     Signature Value:
+//         30:46:02:21:00:a9:57:7d:ac:e0:80:8e:1c:7a:e1:4d:7d:2a:
+//         52:d2:5e:fb:5a:7d:45:1e:fa:67:17:04:9e:b3:05:c2:34:f0:
+//         7a:02:21:00:b7:3a:31:25:ae:1d:2b:06:8b:ba:44:d9:3a:bf:
+//         8b:e2:3f:89:e2:a6:14:0c:fa:c2:b1:dd:0c:0a:78:ac:60:19
 constexpr uint8_t kExpectedX509P256Cert_DescriptorInput[927] = {
     0x30, 0x82, 0x03, 0x9b, 0x30, 0x82, 0x03, 0x3e, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x2c, 0x0d, 0xe9, 0x55, 0xc4, 0xfa, 0x08, 0x2c, 0x2c,
@@ -1138,14 +1138,14 @@
     0xb2, 0xc1, 0xc6, 0x6f, 0xb4, 0x16, 0xa4, 0x78, 0x76, 0x73, 0x6f, 0xcb,
     0xf5, 0x7d, 0x26, 0xc2, 0x37, 0xe9, 0x58, 0x98, 0xeb, 0xef, 0x11, 0x7c,
     0x8d, 0x1d, 0x4b, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x60,
-    0x12, 0xa5, 0xb9, 0xc3, 0xbf, 0x06, 0x10, 0x7d, 0x22, 0x4b, 0xc1, 0xd2,
-    0x58, 0xce, 0xd8, 0x4c, 0x42, 0x48, 0x69, 0x58, 0xf0, 0x83, 0x4a, 0x54,
-    0x39, 0x90, 0xec, 0x10, 0xef, 0x76, 0x2e, 0xb0, 0x33, 0x82, 0x6f, 0x93,
-    0x2b, 0xc3, 0xb2, 0xc4, 0x6a, 0xcb, 0xde, 0x4c, 0x21, 0x62, 0x56, 0x07,
-    0xc7, 0xb1, 0xd6, 0xde, 0xff, 0x95, 0x2c, 0xce, 0xbf, 0x3c, 0x0b, 0xdc,
-    0xd0, 0xc5, 0x39, 0x6d, 0xc3, 0x59, 0x23, 0x7b, 0x54, 0x11, 0xf4, 0xb1,
-    0x33, 0x66, 0x94, 0x47, 0x3c, 0x14, 0x99, 0x0a, 0xca, 0xa9, 0x84, 0xf4,
-    0xc9, 0x24, 0xfd, 0x11, 0xe7, 0xcc, 0x37, 0x6f, 0x12, 0x2b, 0x1a, 0xa7};
+    0x6d, 0x1f, 0xb6, 0xd3, 0x9f, 0xfa, 0xaa, 0x73, 0xcf, 0x2d, 0x59, 0x99,
+    0x9d, 0xef, 0x0f, 0x20, 0xc4, 0xeb, 0x31, 0x99, 0xa8, 0x9c, 0xae, 0xeb,
+    0x85, 0x02, 0x34, 0x51, 0x24, 0x1a, 0x68, 0xc9, 0xfd, 0x87, 0xfd, 0x3d,
+    0xc8, 0xe4, 0x88, 0x16, 0x8a, 0x31, 0x67, 0xa5, 0x95, 0xec, 0x2d, 0x4d,
+    0x41, 0x08, 0x52, 0x3c, 0x26, 0x44, 0x3f, 0xca, 0xc8, 0xa3, 0x79, 0xc5,
+    0x56, 0x40, 0xc0, 0x62, 0x0d, 0x5c, 0xd4, 0xcf, 0x69, 0x22, 0x05, 0x94,
+    0xf2, 0x66, 0xcb, 0x1e, 0x8a, 0xdf, 0x98, 0xc4, 0xcd, 0x26, 0x4b, 0xd5,
+    0xc6, 0x3d, 0x08, 0xf5, 0x5a, 0xa7, 0xde, 0x21, 0xbe, 0x5d, 0x04, 0x94};
 
 }  // namespace test
 }  // namespace dice
diff --git a/include/dice/ops/trait/cose.h b/include/dice/ops/trait/cose.h
index 63404a5..78cb838 100644
--- a/include/dice/ops/trait/cose.h
+++ b/include/dice/ops/trait/cose.h
@@ -28,8 +28,10 @@
 extern "C" {
 #endif
 
-// Encodes a public key into |buffer| as a COSE_Key structure, setting
-// |encoded_size| to the number of bytes used.
+// Encodes a public key into |buffer| as a COSE_Key structure. On success,
+// |encoded_size| is set to the number of bytes used. If
+// kDiceResultBufferTooSmall is returned |encoded_size| will be set to the
+// required size of the buffer.
 DiceResult DiceCoseEncodePublicKey(
     void* context, const uint8_t public_key[DICE_PUBLIC_KEY_SIZE],
     size_t buffer_size, uint8_t* buffer, size_t* encoded_size);
@@ -39,8 +41,9 @@
 // the result.
 //
 // |buffer| is used to hold the intermediate To-Be-Signed (TBS) structure and
-// then the final result. |encoded_size| is set to the size of the final result
-// in |buffer|.
+// then the final result. On success, |encoded_size| is set to the size of the
+// final result in |buffer|. If kDiceResultBufferTooSmall is returned,
+// |encoded_size| will be set to the required size of the buffer.
 DiceResult DiceCoseSignAndEncodeSign1(
     void* context, const uint8_t* payload, size_t payload_size,
     const uint8_t* aad, size_t aad_size,
diff --git a/src/android/bcc.c b/src/android/bcc.c
index 5dd8620..262e6d3 100644
--- a/src/android/bcc.c
+++ b/src/android/bcc.c
@@ -18,9 +18,9 @@
 
 #include "dice/cbor_reader.h"
 #include "dice/cbor_writer.h"
-#include "dice/ops/trait/cose.h"
 #include "dice/dice.h"
 #include "dice/ops.h"
+#include "dice/ops/trait/cose.h"
 
 // Completely gratuitous bit twiddling.
 static size_t PopulationCount(uint32_t n) {
@@ -57,10 +57,10 @@
     CborWriteInt(kResettableLabel, &out);
     CborWriteNull(&out);
   }
+  *actual_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *actual_size = CborOutSize(&out);
   return kDiceResultOk;
 }
 
@@ -111,22 +111,20 @@
   CborWriteArray(bcc_item_count + 1, &out);
   if (CborOutOverflowed(&out) ||
       bcc_items_size > buffer_size - CborOutSize(&out)) {
-    return kDiceResultBufferTooSmall;
+    // Continue with an empty buffer to measure the required size.
+    buffer_size = 0;
+  } else {
+    memcpy(buffer + CborOutSize(&out), bcc + bcc_items_offset, bcc_items_size);
+    buffer += CborOutSize(&out) + bcc_items_size;
+    buffer_size -= CborOutSize(&out) + bcc_items_size;
   }
-  memcpy(buffer + CborOutSize(&out), bcc + bcc_items_offset, bcc_items_size);
 
   size_t certificate_size;
-  result =
-      DiceMainFlow(context, current_cdi_attest, current_cdi_seal, input_values,
-                   buffer_size - (CborOutSize(&out) + bcc_items_size),
-                   buffer + CborOutSize(&out) + bcc_items_size,
-                   &certificate_size, next_cdi_attest, next_cdi_seal);
-  if (result != kDiceResultOk) {
-    return result;
-  }
-
+  result = DiceMainFlow(context, current_cdi_attest, current_cdi_seal,
+                        input_values, buffer_size, buffer, &certificate_size,
+                        next_cdi_attest, next_cdi_seal);
   *actual_size = CborOutSize(&out) + bcc_items_size + certificate_size;
-  return kDiceResultOk;
+  return result;
 }
 
 static DiceResult BccMainFlowWithNewBcc(
@@ -157,31 +155,35 @@
   struct CborOut out;
   CborOutInit(buffer, buffer_size, &out);
   CborWriteArray(2, &out);
-  if (CborOutOverflowed(&out)) {
-    result = kDiceResultBufferTooSmall;
-    goto out;
-  }
   size_t encoded_size_used = CborOutSize(&out);
-  buffer += encoded_size_used;
-  buffer_size -= encoded_size_used;
+  if (CborOutOverflowed(&out)) {
+    // Continue with an empty buffer to measure the required size.
+    buffer_size = 0;
+  } else {
+    buffer += encoded_size_used;
+    buffer_size -= encoded_size_used;
+  }
 
   size_t encoded_pub_key_size = 0;
   result = DiceCoseEncodePublicKey(context, attestation_public_key, buffer_size,
                                    buffer, &encoded_pub_key_size);
-  if (result != kDiceResultOk) {
+  if (result == kDiceResultOk) {
+    buffer += encoded_pub_key_size;
+    buffer_size -= encoded_pub_key_size;
+  } else if (result == kDiceResultBufferTooSmall) {
+    // Continue with an empty buffer to measure the required size.
+    buffer_size = 0;
+  } else {
     goto out;
   }
 
-  buffer += encoded_pub_key_size;
-  buffer_size -= encoded_pub_key_size;
-
   result = DiceMainFlow(context, current_cdi_attest, current_cdi_seal,
                         input_values, buffer_size, buffer, bcc_size,
                         next_cdi_attest, next_cdi_seal);
+  *bcc_size += encoded_size_used + encoded_pub_key_size;
   if (result != kDiceResultOk) {
     return result;
   }
-  *bcc_size += encoded_size_used + encoded_pub_key_size;
 
 out:
   DiceClearMemory(context, sizeof(current_cdi_private_key_seed),
@@ -224,30 +226,34 @@
   uint8_t* next_cdi_seal = CborAllocBstr(DICE_CDI_SIZE, &out);
   CborWriteInt(kBccLabel, &out);
 
-  if (CborOutOverflowed(&out) || !next_cdi_attest || !next_cdi_seal) {
-    return kDiceResultBufferTooSmall;
+  uint8_t ignored_cdi_attest[DICE_CDI_SIZE];
+  uint8_t ignored_cdi_seal[DICE_CDI_SIZE];
+  if (CborOutOverflowed(&out)) {
+    // Continue with an empty buffer and placeholders for the output CDIs to
+    // measure the required size.
+    buffer_size = 0;
+    next_cdi_attest = ignored_cdi_attest;
+    next_cdi_seal = ignored_cdi_seal;
+  } else {
+    buffer += CborOutSize(&out);
+    buffer_size -= CborOutSize(&out);
   }
 
   if (bcc_size != 0) {
     // If BCC is present in the bcc_handover, append the next certificate to the
     // existing BCC.
     result = BccMainFlow(context, current_cdi_attest, current_cdi_seal, bcc,
-                         bcc_size, input_values, buffer_size - CborOutSize(&out),
-                         buffer + CborOutSize(&out), &bcc_size, next_cdi_attest,
-                         next_cdi_seal);
+                         bcc_size, input_values, buffer_size, buffer, &bcc_size,
+                         next_cdi_attest, next_cdi_seal);
   } else {
-    // If BCC is not present in the bcc_handover, construct BCC from the public key
-    // derived from the current CDI attest and the next CDI certificate.
+    // If BCC is not present in the bcc_handover, construct BCC from the public
+    // key derived from the current CDI attest and the next CDI certificate.
     result = BccMainFlowWithNewBcc(
         context, current_cdi_attest, current_cdi_seal, input_values,
-        buffer_size - CborOutSize(&out), buffer + CborOutSize(&out), &bcc_size,
-        next_cdi_attest, next_cdi_seal);
-  }
-  if (result != kDiceResultOk) {
-      return result;
+        buffer_size, buffer, &bcc_size, next_cdi_attest, next_cdi_seal);
   }
   *actual_size = CborOutSize(&out) + bcc_size;
-  return kDiceResultOk;
+  return result;
 }
 
 DiceResult BccHandoverParse(const uint8_t* bcc_handover,
diff --git a/src/android/bcc_test.cc b/src/android/bcc_test.cc
index 0c45e06..ba062b9 100644
--- a/src/android/bcc_test.cc
+++ b/src/android/bcc_test.cc
@@ -31,6 +31,15 @@
   EXPECT_EQ(0xa0, buffer[0]);
 }
 
+TEST(BccConfigTest, NoInputsMeasurement) {
+  BccConfigValues input_values = {};
+  size_t buffer_size;
+  DiceResult result =
+      BccFormatConfigDescriptor(&input_values, 0, NULL, &buffer_size);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
+  EXPECT_EQ(1u, buffer_size);
+}
+
 TEST(BccConfigTest, AllInputs) {
   BccConfigValues input_values = {
       .inputs = BCC_INPUT_COMPONENT_NAME | BCC_INPUT_COMPONENT_VERSION |
@@ -38,18 +47,21 @@
       .component_name = "Test Component Name",
       .component_version = 0x232a13dec90f42b5,
   };
-  uint8_t buffer[256];
   size_t buffer_size;
-  DiceResult result = BccFormatConfigDescriptor(&input_values, sizeof(buffer),
-                                                buffer, &buffer_size);
-  EXPECT_EQ(kDiceResultOk, result);
+  DiceResult result =
+      BccFormatConfigDescriptor(&input_values, 0, NULL, &buffer_size);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
+  std::vector<uint8_t> buffer(buffer_size);
   const uint8_t expected[] = {
       0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x73, 'T',  'e',  's',  't',  ' ',
       'C',  'o',  'm',  'p',  'o',  'n',  'e',  'n',  't',  ' ',  'N',  'a',
       'm',  'e',  0x3a, 0x00, 0x01, 0x11, 0x72, 0x1b, 0x23, 0x2a, 0x13, 0xde,
       0xc9, 0x0f, 0x42, 0xb5, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6};
+  EXPECT_EQ(sizeof(expected), buffer.size());
+  result = BccFormatConfigDescriptor(&input_values, buffer.size(),
+                                     buffer.data(), &buffer_size);
   EXPECT_EQ(sizeof(expected), buffer_size);
-  EXPECT_EQ(0, memcmp(expected, buffer, buffer_size));
+  EXPECT_EQ(0, memcmp(expected, buffer.data(), buffer.size()));
 }
 
 TEST(BccTest, PreservesPreviousEntries) {
@@ -68,19 +80,24 @@
   const uint8_t fake_cdi_attest[DICE_CDI_SIZE] = {};
   const uint8_t fake_cdi_seal[DICE_CDI_SIZE] = {};
   DiceInputValues input_values = {};
-  uint8_t next_bcc[2048] = {};
   size_t next_bcc_size;
   uint8_t next_cdi_attest[DICE_CDI_SIZE];
   uint8_t next_cdi_seal[DICE_CDI_SIZE];
-  DiceResult result =
+  DiceResult result = BccMainFlow(
+      /*context=*/NULL, fake_cdi_attest, fake_cdi_seal, bcc, sizeof(bcc),
+      &input_values, 0, NULL, &next_bcc_size, next_cdi_attest, next_cdi_seal);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
+  EXPECT_GT(next_bcc_size, sizeof(bcc));
+  std::vector<uint8_t> next_bcc(next_bcc_size);
+  result =
       BccMainFlow(/*context=*/NULL, fake_cdi_attest, fake_cdi_seal, bcc,
-                  sizeof(bcc), &input_values, sizeof(next_bcc), next_bcc,
+                  sizeof(bcc), &input_values, next_bcc.size(), next_bcc.data(),
                   &next_bcc_size, next_cdi_attest, next_cdi_seal);
   EXPECT_EQ(kDiceResultOk, result);
-  EXPECT_GT(next_bcc_size, sizeof(bcc));
+  EXPECT_EQ(next_bcc_size, next_bcc.size());
   EXPECT_EQ(0x84, next_bcc[0]);
-  EXPECT_NE(0, memcmp(next_bcc + 1, bcc + 1, sizeof(bcc) - 1));
-  EXPECT_EQ(0, memcmp(next_bcc + 1, bcc + 1, sizeof(bcc) - 8 - 1));
+  EXPECT_NE(0, memcmp(next_bcc.data() + 1, bcc + 1, sizeof(bcc) - 1));
+  EXPECT_EQ(0, memcmp(next_bcc.data() + 1, bcc + 1, sizeof(bcc) - 8 - 1));
 }
 
 TEST(BccHandoverTest, PreservesPreviousEntries) {
@@ -100,18 +117,24 @@
       // 8-bytes of trailing data that aren't part of the BCC.
       0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40};
   DiceInputValues input_values = {};
-  uint8_t next_bcc_handover[2048] = {};
   size_t next_bcc_handover_size;
   DiceResult result = BccHandoverMainFlow(
-      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
-      sizeof(next_bcc_handover), next_bcc_handover, &next_bcc_handover_size);
-  EXPECT_EQ(kDiceResultOk, result);
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0,
+      NULL, &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
   EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover));
+  std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size);
+  result = BccHandoverMainFlow(
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
+      next_bcc_handover.size(), next_bcc_handover.data(),
+      &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultOk, result);
+  EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size());
   EXPECT_EQ(0xa3, next_bcc_handover[0]);
   EXPECT_EQ(0x83, next_bcc_handover[72]);
-  EXPECT_NE(0, memcmp(next_bcc_handover + 73, bcc_handover + 73,
+  EXPECT_NE(0, memcmp(next_bcc_handover.data() + 73, bcc_handover + 73,
                       sizeof(bcc_handover) - 73));
-  EXPECT_EQ(0, memcmp(next_bcc_handover + 73, bcc_handover + 73,
+  EXPECT_EQ(0, memcmp(next_bcc_handover.data() + 73, bcc_handover + 73,
                       sizeof(bcc_handover) - 8 - 73));
 }
 
@@ -129,13 +152,19 @@
       // 8-bytes of trailing data that aren't part of the BCC.
       0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40};
   DiceInputValues input_values = {};
-  uint8_t next_bcc_handover[1024] = {};
   size_t next_bcc_handover_size;
   DiceResult result = BccHandoverMainFlow(
-      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
-      sizeof(next_bcc_handover), next_bcc_handover, &next_bcc_handover_size);
-  EXPECT_EQ(kDiceResultOk, result);
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0,
+      NULL, &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
   EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover));
+  std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size);
+  result = BccHandoverMainFlow(
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
+      next_bcc_handover.size(), next_bcc_handover.data(),
+      &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultOk, result);
+  EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size());
   EXPECT_EQ(0xa3, next_bcc_handover[0]);
 }
 
@@ -155,13 +184,19 @@
       // 8-bytes of trailing data that aren't part of the BCC.
       0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40};
   DiceInputValues input_values = {};
-  uint8_t next_bcc_handover[1024] = {};
   size_t next_bcc_handover_size;
   DiceResult result = BccHandoverMainFlow(
-      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
-      sizeof(next_bcc_handover), next_bcc_handover, &next_bcc_handover_size);
-  EXPECT_EQ(kDiceResultOk, result);
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0,
+      NULL, &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
   EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover));
+  std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size);
+  result = BccHandoverMainFlow(
+      /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values,
+      next_bcc_handover.size(), next_bcc_handover.data(),
+      &next_bcc_handover_size);
+  EXPECT_EQ(kDiceResultOk, result);
+  EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size());
   EXPECT_EQ(0xa3, next_bcc_handover[0]);
 }
 
diff --git a/src/boringssl_ecdsa_utils.c b/src/boringssl_ecdsa_utils.c
index 9513cd4..ef31812 100644
--- a/src/boringssl_ecdsa_utils.c
+++ b/src/boringssl_ecdsa_utils.c
@@ -36,7 +36,7 @@
                 unsigned int out_len) {
   int ret = 0;
 
-  if (out_len > 64 || out_len < 0) {
+  if (out_len != 64) {
     goto out;
   }
   HMAC_CTX ctx;
@@ -82,15 +82,21 @@
   return ret;
 }
 
-// Algorithm from section 3.2 of IETF RFC6979
+// Algorithm from section 3.2 of IETF RFC6979; limited to generating up to 64
+// byte private keys.
 static BIGNUM *derivePrivateKey(const EC_GROUP *group, const uint8_t *seed,
-                                size_t seed_size, uint8_t *private_key,
-                                size_t private_key_len) {
+                                size_t seed_size, size_t private_key_len) {
   BIGNUM *candidate = NULL;
   uint8_t v[64];
   uint8_t k[64];
+  uint8_t temp[64];
   memset(v, 1, 64);
   memset(k, 0, 64);
+  memset(temp, 0, 64);
+
+  if (private_key_len > 64) {
+    goto err;
+  }
 
   if (1 != hmac3(k, v, 0x00, seed, (unsigned int)seed_size, k)) {
     goto err;
@@ -105,13 +111,13 @@
     if (1 != hmac(k, v, v, sizeof(v))) {
       goto err;
     }
-    if (1 != hmac(k, v, private_key, private_key_len)) {
+    if (1 != hmac(k, v, temp, sizeof(temp))) {
       goto err;
     }
     if (1 != hmac3(k, v, 0x00, NULL, 0, k)) {
       goto err;
     }
-    candidate = BN_bin2bn(private_key, private_key_len, NULL);
+    candidate = BN_bin2bn(temp, private_key_len, NULL);
     if (!candidate) {
       goto err;
     }
@@ -148,8 +154,7 @@
     goto out;
   }
 
-  pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE, private_key,
-                                P384_PRIVATE_KEY_SIZE);
+  pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE, P384_PRIVATE_KEY_SIZE);
   if (!pD) {
     goto out;
   }
diff --git a/src/cbor_cert_op.c b/src/cbor_cert_op.c
index 5df1583..d0670de 100644
--- a/src/cbor_cert_op.c
+++ b/src/cbor_cert_op.c
@@ -44,10 +44,10 @@
   // Add the algorithm.
   CborWriteInt(kCoseHeaderAlgLabel, &out);
   CborWriteInt(DICE_COSE_KEY_ALG_VALUE, &out);
+  *encoded_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *encoded_size = CborOutSize(&out);
   return kDiceResultOk;
 }
 
@@ -69,10 +69,10 @@
   CborWriteBstr(aad_size, aad, &out);
   // Payload from COSE_Sign1.
   CborWriteBstr(payload_size, payload, &out);
+  *encoded_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *encoded_size = CborOutSize(&out);
   return kDiceResultOk;
 }
 
@@ -94,10 +94,10 @@
   CborWriteBstr(payload_size, payload, &out);
   // Signature.
   CborWriteBstr(/*num_elements=*/DICE_SIGNATURE_SIZE, signature, &out);
+  *encoded_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *encoded_size = CborOutSize(&out);
   return kDiceResultOk;
 }
 
@@ -118,7 +118,7 @@
                                      protected_attributes,
                                      &protected_attributes_size);
   if (result != kDiceResultOk) {
-    return result;
+    return kDiceResultPlatformError;
   }
 
   // Construct a To-Be-Signed (TBS) structure based on the relevant fields of
@@ -127,6 +127,14 @@
                          payload, payload_size, aad, aad_size, buffer_size,
                          buffer, encoded_size);
   if (result != kDiceResultOk) {
+    // Check how big the buffer needs to be in total.
+    size_t final_encoded_size = 0;
+    EncodeCoseSign1(protected_attributes, protected_attributes_size, payload,
+                    payload_size, /*signature=*/NULL, /*buffer_size=*/0,
+                    /*buffer=*/NULL, &final_encoded_size);
+    if (*encoded_size < final_encoded_size) {
+      *encoded_size = final_encoded_size;
+    }
     return result;
   }
 
@@ -239,10 +247,10 @@
   // Add the key usage.
   CborWriteInt(kKeyUsageLabel, &out);
   CborWriteBstr(/*data_size=*/1, &key_usage, &out);
+  *encoded_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *encoded_size = CborOutSize(&out);
   return kDiceResultOk;
 }
 
@@ -308,6 +316,7 @@
       context, subject_public_key, sizeof(encoded_public_key),
       encoded_public_key, &encoded_public_key_size);
   if (result != kDiceResultOk) {
+    result = kDiceResultPlatformError;
     goto out;
   }
 
diff --git a/src/cbor_cert_op_test.cc b/src/cbor_cert_op_test.cc
index cb41c5c..94a437b 100644
--- a/src/cbor_cert_op_test.cc
+++ b/src/cbor_cert_op_test.cc
@@ -53,6 +53,22 @@
                       next_state.certificate, next_state.certificate_size));
 }
 
+TEST(DiceOpsTest, KnownAnswerZeroInputMeasurement) {
+  DiceStateForTest current_state = {};
+  DiceStateForTest next_state = {};
+  DiceInputValues input_values = {};
+  ASSERT_LE(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput) / 2,
+            sizeof(next_state.certificate));
+  DiceResult result = DiceMainFlow(
+      NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
+      sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput) / 2,
+      next_state.certificate, &next_state.certificate_size,
+      next_state.cdi_attest, next_state.cdi_seal);
+  EXPECT_EQ(kDiceResultBufferTooSmall, result);
+  EXPECT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput),
+            next_state.certificate_size);
+}
+
 TEST(DiceOpsTest, KnownAnswerHashOnlyInput) {
   DiceStateForTest current_state = {};
   DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
diff --git a/src/cbor_ed25519_cert_op.c b/src/cbor_ed25519_cert_op.c
index a461ae1..a2c5fbf 100644
--- a/src/cbor_ed25519_cert_op.c
+++ b/src/cbor_ed25519_cert_op.c
@@ -61,9 +61,10 @@
   // Add the public key.
   CborWriteInt(kCoseOkpXLabel, &out);
   CborWriteBstr(/*data_size=*/DICE_PUBLIC_KEY_SIZE, public_key, &out);
+
+  *encoded_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *encoded_size = CborOutSize(&out);
   return kDiceResultOk;
 }
diff --git a/src/cbor_p384_cert_op.c b/src/cbor_p384_cert_op.c
index de078b6..a263573 100644
--- a/src/cbor_p384_cert_op.c
+++ b/src/cbor_p384_cert_op.c
@@ -72,9 +72,9 @@
   CborWriteBstr(/*data_size=*/DICE_PUBLIC_KEY_SIZE / 2,
                 &public_key[DICE_PUBLIC_KEY_SIZE / 2], &out);
 
+  *encoded_size = CborOutSize(&out);
   if (CborOutOverflowed(&out)) {
     return kDiceResultBufferTooSmall;
   }
-  *encoded_size = CborOutSize(&out);
   return kDiceResultOk;
 }