Clean up bssl::PEM_read_bio_inner.

Fixes signed integer overflow on PEM data > 2 GiB, missing error
descriptions on the error stack, randomly oversized allocations for no
explained reason, and replaces explicit memory management by UniquePtr.

Also, equally report an error of PEM_R_BAD_END_LINE if a headerless PEM
has a non-final line of length other than 64. The headerful PEM parsing
already does the same.

Change-Id: I6a205fe692a052f19ef15f1b09b098856a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/94327
Commit-Queue: Rudolf Polzer <rpolzer@google.com>
Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Xiangfei Ding <xfding@google.com>
diff --git a/crypto/err/pem.errordata b/crypto/err/pem.errordata
index 0856f74..d1292ae 100644
--- a/crypto/err/pem.errordata
+++ b/crypto/err/pem.errordata
@@ -14,3 +14,4 @@
 PEM,113,UNSUPPORTED_CIPHER
 PEM,114,UNSUPPORTED_ENCRYPTION
 PEM,115,UNSUPPORTED_PROC_TYPE_VERSION
+PEM,116,NO_DATA
diff --git a/crypto/pem/pem_lib.cc b/crypto/pem/pem_lib.cc
index c2ff10b..bbe9abd 100644
--- a/crypto/pem/pem_lib.cc
+++ b/crypto/pem/pem_lib.cc
@@ -546,27 +546,22 @@
 
 int bssl::PEM_read_bio_inner(BIO *bp, UniquePtr<char> *name,
                              UniquePtr<char> *header, Array<uint8_t> *data) {
-  EVP_ENCODE_CTX ctx;
-  int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
-  char buf[256];
-  BUF_MEM *nameB;
-  BUF_MEM *headerB;
-  BUF_MEM *dataB, *tmpB;
-
-  nameB = BUF_MEM_new();
-  headerB = BUF_MEM_new();
-  dataB = BUF_MEM_new();
+  bssl::UniquePtr<BUF_MEM> nameB(BUF_MEM_new());
+  bssl::UniquePtr<BUF_MEM> headerB(BUF_MEM_new());
+  bssl::UniquePtr<BUF_MEM> dataB(BUF_MEM_new());
   if ((nameB == nullptr) || (headerB == nullptr) || (dataB == nullptr)) {
-    goto err;
+    OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
 
+  char buf[256];  // 254 characters + newline + \0.
   buf[254] = '\0';
+  // Invariant: buf[254] < ' '. It may get overwritten by '\n' or '\0' only.
   for (;;) {
-    i = BIO_gets(bp, buf, 254);
-
+    int i = BIO_gets(bp, buf, 254);
     if (i <= 0) {
       OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE);
-      goto err;
+      return 0;
     }
 
     while ((i >= 0) && (buf[i] <= ' ')) {
@@ -581,139 +576,125 @@
       if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0) {
         continue;
       }
-      if (!BUF_MEM_grow(nameB, i + 9)) {
-        goto err;
+      if (!BUF_MEM_grow(nameB.get(), i - 5)) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+        return 0;
       }
       OPENSSL_memcpy(nameB->data, &(buf[11]), i - 6);
       nameB->data[i - 6] = '\0';
       break;
     }
   }
-  hl = 0;
-  if (!BUF_MEM_grow(headerB, 256)) {
-    goto err;
+
+  size_t hl = 0;
+  if (!BUF_MEM_grow(headerB.get(), 256)) {
+    OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
   headerB->data[0] = '\0';
-  for (;;) {
-    i = BIO_gets(bp, buf, 254);
-    if (i <= 0) {
-      break;
-    }
 
-    while ((i >= 0) && (buf[i] <= ' ')) {
-      i--;
-    }
-    buf[++i] = '\n';
-    buf[++i] = '\0';
-
-    if (buf[0] == '\n') {
-      break;
-    }
-    if (!BUF_MEM_grow(headerB, hl + i + 9)) {
-      goto err;
-    }
-    if (strncmp(buf, "-----END ", 9) == 0) {
-      nohead = 1;
-      break;
-    }
-    OPENSSL_memcpy(&(headerB->data[hl]), buf, i);
-    headerB->data[hl + i] = '\0';
-    hl += i;
-  }
-
-  bl = 0;
-  if (!BUF_MEM_grow(dataB, 1024)) {
-    goto err;
+  size_t bl = 0;
+  if (!BUF_MEM_grow(dataB.get(), 1024)) {
+    OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+    return 0;
   }
   dataB->data[0] = '\0';
-  if (!nohead) {
+
+  bool failed = false;  // Set to true (and error put into queue) on failure.
+  auto read_until_end = [&](BUF_MEM *out, size_t &out_len,
+                            bool stop_at_newline) {
+    // Invariant: buf[254] < ' '. It may get overwritten by '\n' or '\0' only.
     for (;;) {
-      i = BIO_gets(bp, buf, 254);
+      int i = BIO_gets(bp, buf, 254);
       if (i <= 0) {
         break;
       }
-
       while ((i >= 0) && (buf[i] <= ' ')) {
         i--;
       }
       buf[++i] = '\n';
       buf[++i] = '\0';
 
-      if (i != 65) {
-        end = 1;
+      if (stop_at_newline && buf[0] == '\n') {
+        // End of header, start of body.
+        return true;
       }
       if (strncmp(buf, "-----END ", 9) == 0) {
-        break;
+        return false;
       }
-      if (i > 65) {
-        break;
+      if (static_cast<size_t>(i) > SIZE_MAX - hl - 1) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_OVERFLOW);
+        failed = true;
+        return false;
       }
-      if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
-        goto err;
+      size_t new_len = out_len + i;
+      if (!BUF_MEM_grow(out, new_len + 1)) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+        failed = true;
+        return false;
       }
-      OPENSSL_memcpy(&(dataB->data[bl]), buf, i);
-      dataB->data[bl + i] = '\0';
-      bl += i;
-      if (end) {
-        buf[0] = '\0';
-        i = BIO_gets(bp, buf, 254);
-        if (i <= 0) {
-          break;
-        }
-
-        while ((i >= 0) && (buf[i] <= ' ')) {
-          i--;
-        }
-        buf[++i] = '\n';
-        buf[++i] = '\0';
-
-        break;
-      }
+      OPENSSL_memcpy(&(out->data[out_len]), buf, i);
+      out->data[new_len] = '\0';
+      out_len = new_len;
     }
+    return false;
+  };
+
+  if (read_until_end(headerB.get(), hl, /*stop_at_newline=*/true)) {
+    read_until_end(dataB.get(), bl, /*stop_at_newline=*/false);
   } else {
-    tmpB = headerB;
-    headerB = dataB;
-    dataB = tmpB;
-    bl = hl;
+    // Actually we've read the body, as there is no header.
+    std::swap(hl, bl);
+    std::swap(headerB, dataB);
   }
-  i = strlen(nameB->data);
+  if (failed) {
+    return 0;
+  }
+
+  size_t name_len = strlen(nameB->data);
   if ((strncmp(buf, "-----END ", 9) != 0) ||
-      (strncmp(nameB->data, &(buf[9]), i) != 0) ||
-      (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
+      (strncmp(&(buf[9]), nameB->data, name_len) != 0) ||
+      (strncmp(&(buf[9 + name_len]), "-----\n", 6) != 0)) {
     OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE);
-    goto err;
+    return 0;
   }
 
+  EVP_ENCODE_CTX ctx;
   EVP_DecodeInit(&ctx);
-  i = EVP_DecodeUpdate(&ctx, (unsigned char *)dataB->data, &bl,
+  int decoded_length;
+  int status =
+      EVP_DecodeUpdate(&ctx, (unsigned char *)dataB->data, &decoded_length,
                        (unsigned char *)dataB->data, bl);
-  if (i < 0) {
+  if (status < 0) {
     OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
-    goto err;
+    return 0;
   }
-  i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
-  if (i < 0) {
+  int k;
+  status = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
+  if (status < 0) {
     OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
-    goto err;
+    return 0;
   }
-  bl += k;
+  if (k > INT_MAX - decoded_length) {
+    OPENSSL_PUT_ERROR(PEM, ERR_R_OVERFLOW);
+    return 0;
+  }
+  decoded_length += k;
 
-  if (bl == 0) {
-    goto err;
+  if (decoded_length == 0) {
+    OPENSSL_PUT_ERROR(PEM, PEM_R_NO_DATA);
+    return 0;
   }
+
   // Transfer ownership of buffers
   name->reset(nameB->data);
+  nameB->data = nullptr;
   header->reset(headerB->data);
-  data->Reset((uint8_t *)dataB->data, bl);
-  OPENSSL_free(nameB);
-  OPENSSL_free(headerB);
-  OPENSSL_free(dataB);
+  headerB->data = nullptr;
+  data->Reset((uint8_t *)dataB->data, decoded_length);
+  dataB->data = nullptr;
+
   return 1;
-err:
-  BUF_MEM_free(nameB);
-  BUF_MEM_free(headerB);
-  BUF_MEM_free(dataB);
-  return 0;
 }
 
 int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
diff --git a/crypto/pem/pem_test.cc b/crypto/pem/pem_test.cc
index 24ffd62..2947154 100644
--- a/crypto/pem/pem_test.cc
+++ b/crypto/pem/pem_test.cc
@@ -437,4 +437,81 @@
   }
 }
 
+TEST(PEMTest, ParsingErrorsAndSuccesses) {
+  const struct {
+    const char *name;
+    const char *pem;
+    int err_reason;
+    const char *want_name = nullptr;
+    const char *want_header = nullptr;
+    const char *want_body = nullptr;
+  } kTests[] = {
+      {"WithHeadersOK",
+       "-----BEGIN BEST-----\nX-Hdr: h\n\nYmFzZTY0\n-----END BEST-----",  //
+       0, "BEST", "X-Hdr: h\n", "base64"},
+      {"NoHeadersNoBlankLineOK",
+       "-----BEGIN FEST-----\nYmFzZTY0\n-----END FEST-----",  //
+       0, "FEST", "", "base64"},
+      {"WithHeadersWeirdLineSplitOK",
+       "-----BEGIN JEST-----\nX-Hdr: h\n\nYmF\nzZTY0\n-----END JEST-----",  //
+       0, "JEST", "X-Hdr: h\n", "base64"},
+      {"NoHeadersNoBlankLineWeirdLineSplitOK",
+       "-----BEGIN LEST-----\nYmF\nzZTY0\n-----END LEST-----",  //
+       0, "LEST", "", "base64"},
+      {"WithHeadersAndRubbishOK",
+       "a\n-----BEGIN TEST-----\nX-Hdr: h\n\nYmFzZTY0\n-----END TEST-----\nb",
+       0, "TEST", "X-Hdr: h\n", "base64"},
+      {"NoHeadersNoBlankLineButRubbishOK",
+       "a\n-----BEGIN ZEST-----\nYmFzZTY0\n-----END ZEST-----\nb",  //
+       0, "ZEST", "", "base64"},
+      {"Empty", "",  //
+       PEM_R_NO_START_LINE},
+      {"NoStart",           //
+       "Not a PEM file\n",  //
+       PEM_R_NO_START_LINE},
+      {"TruncatedBeforeStart",  //
+       "-----BEGIN ",           //
+       PEM_R_NO_START_LINE},
+      {"TruncatedAfterStart",     //
+       "-----BEGIN TEST-----\n",  //
+       PEM_R_BAD_END_LINE},
+      {"MismatchedEnd",                                //
+       "-----BEGIN TEST-----\n-----END OTHER-----\n",  //
+       PEM_R_BAD_END_LINE},
+      {"MismatchedEndLonger",                          //
+       "-----BEGIN TEST-----\n-----END TEST1-----\n",  //
+       PEM_R_BAD_END_LINE},
+      {"NoData",                                      //
+       "-----BEGIN TEST-----\n-----END TEST-----\n",  //
+       PEM_R_NO_DATA},
+      {"NoDataButHeaders",                                        //
+       "-----BEGIN TEST-----\nX-Hdr: h\n\n-----END TEST-----\n",  //
+       PEM_R_NO_DATA},
+      {"InvalidBase64",  //
+       "-----BEGIN TEST-----\n!!!!\n-----END TEST-----\n",
+       PEM_R_BAD_BASE64_DECODE},
+  };
+
+  for (const auto &t : kTests) {
+    SCOPED_TRACE(t.name);
+    bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(t.pem, -1));
+    char *name, *header;
+    uint8_t *data;
+    long len;
+    if (PEM_read_bio(bio.get(), &name, &header, &data, &len)) {
+      EXPECT_EQ(t.err_reason, 0);
+      EXPECT_EQ(Bytes(name), Bytes(t.want_name));
+      EXPECT_EQ(Bytes(header), Bytes(t.want_header));
+      EXPECT_EQ(Bytes(data, len), Bytes(t.want_body));
+      OPENSSL_free(name);
+      OPENSSL_free(header);
+      OPENSSL_free(data);
+    } else {
+      EXPECT_NE(t.err_reason, 0);
+      EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_PEM, t.err_reason));
+      ERR_clear_error();
+    }
+  }
+}
+
 }  // namespace
diff --git a/gen/crypto/err_data.cc b/gen/crypto/err_data.cc
index 7b4cefb..e20e7e7 100644
--- a/gen/crypto/err_data.cc
+++ b/gen/crypto/err_data.cc
@@ -80,54 +80,54 @@
     0xc3b00f7,
     0xc3b8921,
     0x10320892,
-    0x1032970a,
-    0x10331716,
-    0x1033972f,
-    0x10341742,
+    0x10329712,
+    0x1033171e,
+    0x10339737,
+    0x1034174a,
     0x10348fd3,
     0x10350d1f,
-    0x10359755,
-    0x1036177f,
-    0x10369792,
-    0x103717b1,
-    0x103797ca,
-    0x103817df,
-    0x103897fd,
-    0x1039180c,
-    0x10399828,
-    0x103a1843,
-    0x103a9852,
-    0x103b186e,
-    0x103b9889,
-    0x103c18af,
+    0x1035975d,
+    0x10361787,
+    0x1036979a,
+    0x103717b9,
+    0x103797d2,
+    0x103817e7,
+    0x10389805,
+    0x10391814,
+    0x10399830,
+    0x103a184b,
+    0x103a985a,
+    0x103b1876,
+    0x103b9891,
+    0x103c18b7,
     0x103c80f7,
-    0x103d18c0,
-    0x103d98d4,
-    0x103e18f3,
-    0x103e9902,
-    0x103f1919,
-    0x103f992c,
+    0x103d18c8,
+    0x103d98dc,
+    0x103e18fb,
+    0x103e990a,
+    0x103f1921,
+    0x103f9934,
     0x10400ce3,
-    0x1040993f,
-    0x1041195d,
-    0x10419970,
-    0x1042198a,
-    0x1042999a,
-    0x104319ae,
-    0x104399c4,
-    0x104419dc,
-    0x104499f1,
-    0x10451a05,
-    0x10459a17,
+    0x10409947,
+    0x10411965,
+    0x10419978,
+    0x10421992,
+    0x104299a2,
+    0x104319b6,
+    0x104399cc,
+    0x104419e4,
+    0x104499f9,
+    0x10451a0d,
+    0x10459a1f,
     0x10460635,
     0x1046899a,
-    0x10471a2c,
-    0x10479a43,
-    0x10481a58,
-    0x10489a66,
+    0x10471a34,
+    0x10479a4b,
+    0x10481a60,
+    0x10489a6e,
     0x10490f1f,
-    0x104998a0,
-    0x104a176a,
+    0x104998a8,
+    0x104a1772,
     0x14320cb3,
     0x14328cd4,
     0x14330ce3,
@@ -196,6 +196,7 @@
     0x243893f3,
     0x24391406,
     0x2439941d,
+    0x243a143b,
     0x28320d13,
     0x28328d2b,
     0x28330ce3,
@@ -205,51 +206,51 @@
     0x283500f7,
     0x28358cc1,
     0x2836099a,
-    0x2c3234c6,
-    0x2c32943b,
-    0x2c3334d4,
-    0x2c33b4e6,
-    0x2c3434fa,
-    0x2c34b50c,
-    0x2c353527,
-    0x2c35b539,
-    0x2c363569,
+    0x2c3234ce,
+    0x2c329443,
+    0x2c3334dc,
+    0x2c33b4ee,
+    0x2c343502,
+    0x2c34b514,
+    0x2c35352f,
+    0x2c35b541,
+    0x2c363571,
     0x2c36833a,
-    0x2c373576,
-    0x2c37b5a2,
-    0x2c3835e0,
-    0x2c38b5f7,
-    0x2c393615,
-    0x2c39b625,
-    0x2c3a3637,
-    0x2c3ab64b,
-    0x2c3b365c,
-    0x2c3bb67b,
-    0x2c3c144d,
-    0x2c3c9463,
-    0x2c3d36c0,
-    0x2c3d947c,
-    0x2c3e36ea,
-    0x2c3eb6f8,
-    0x2c3f3710,
-    0x2c3fb728,
-    0x2c403752,
+    0x2c37357e,
+    0x2c37b5aa,
+    0x2c3835e8,
+    0x2c38b5ff,
+    0x2c39361d,
+    0x2c39b62d,
+    0x2c3a363f,
+    0x2c3ab653,
+    0x2c3b3664,
+    0x2c3bb683,
+    0x2c3c1455,
+    0x2c3c946b,
+    0x2c3d36c8,
+    0x2c3d9484,
+    0x2c3e36f2,
+    0x2c3eb700,
+    0x2c3f3718,
+    0x2c3fb730,
+    0x2c40375a,
     0x2c409330,
-    0x2c413763,
-    0x2c41b776,
+    0x2c41376b,
+    0x2c41b77e,
     0x2c4212f6,
-    0x2c42b787,
+    0x2c42b78f,
     0x2c43076d,
-    0x2c43b66d,
-    0x2c4435b5,
-    0x2c44b735,
-    0x2c45354c,
-    0x2c45b588,
-    0x2c463605,
-    0x2c46b68f,
-    0x2c4736a4,
-    0x2c47b6dd,
-    0x2c4835c7,
+    0x2c43b675,
+    0x2c4435bd,
+    0x2c44b73d,
+    0x2c453554,
+    0x2c45b590,
+    0x2c46360d,
+    0x2c46b697,
+    0x2c4736ac,
+    0x2c47b6e5,
+    0x2c4835cf,
     0x30320000,
     0x30328015,
     0x3033001f,
@@ -389,274 +390,274 @@
     0x3c418e13,
     0x3c420f1f,
     0x3c428ea9,
-    0x40321ad2,
-    0x40329ae8,
-    0x40331b16,
-    0x40339b20,
-    0x40341b37,
-    0x40349b55,
-    0x40351b65,
-    0x40359b77,
-    0x40361b84,
-    0x40369b90,
-    0x40371ba5,
-    0x40379bb7,
-    0x40381bc2,
-    0x40389bd4,
+    0x40321ada,
+    0x40329af0,
+    0x40331b1e,
+    0x40339b28,
+    0x40341b3f,
+    0x40349b5d,
+    0x40351b6d,
+    0x40359b7f,
+    0x40361b8c,
+    0x40369b98,
+    0x40371bad,
+    0x40379bbf,
+    0x40381bca,
+    0x40389bdc,
     0x40390fd3,
-    0x40399be4,
-    0x403a1bf7,
-    0x403a9c18,
-    0x403b1c29,
-    0x403b9c39,
+    0x40399bec,
+    0x403a1bff,
+    0x403a9c20,
+    0x403b1c31,
+    0x403b9c41,
     0x403c0071,
     0x403c8090,
-    0x403d1c9a,
-    0x403d9cb0,
-    0x403e1cbf,
-    0x403e9cf7,
-    0x403f1d11,
-    0x403f9d39,
-    0x40401d4e,
-    0x40409d62,
-    0x40411d9d,
-    0x40419db8,
-    0x40421dd1,
-    0x40429de4,
-    0x40431df8,
-    0x40439e26,
-    0x40441e3d,
+    0x403d1ca2,
+    0x403d9cb8,
+    0x403e1cc7,
+    0x403e9cff,
+    0x403f1d19,
+    0x403f9d41,
+    0x40401d56,
+    0x40409d6a,
+    0x40411da5,
+    0x40419dc0,
+    0x40421dd9,
+    0x40429dec,
+    0x40431e00,
+    0x40439e2e,
+    0x40441e45,
     0x404480b9,
-    0x40451e52,
-    0x40459e64,
-    0x40461e88,
-    0x40469ea8,
-    0x40471eb6,
-    0x40479edd,
-    0x40481f5e,
-    0x4048a018,
-    0x4049202f,
-    0x4049a049,
-    0x404a2060,
-    0x404aa07e,
-    0x404b2096,
-    0x404ba0c3,
-    0x404c20d9,
-    0x404ca0eb,
-    0x404d210c,
-    0x404da145,
-    0x404e2159,
-    0x404ea166,
-    0x404f2251,
-    0x404fa2c7,
-    0x40502383,
-    0x4050a397,
-    0x405123e4,
-    0x405223f4,
-    0x4052a424,
-    0x4053243c,
-    0x4053a44f,
-    0x40542464,
-    0x4054a487,
-    0x405524b2,
-    0x4055a4ef,
-    0x40562514,
-    0x4056a52d,
-    0x40572545,
-    0x4057a558,
-    0x4058256d,
-    0x4058a594,
-    0x405925c3,
-    0x4059a603,
-    0x405aa617,
-    0x405b262f,
-    0x405ba640,
-    0x405c2653,
-    0x405ca6a8,
-    0x405d26b5,
-    0x405da6da,
-    0x405e2718,
+    0x40451e5a,
+    0x40459e6c,
+    0x40461e90,
+    0x40469eb0,
+    0x40471ebe,
+    0x40479ee5,
+    0x40481f66,
+    0x4048a020,
+    0x40492037,
+    0x4049a051,
+    0x404a2068,
+    0x404aa086,
+    0x404b209e,
+    0x404ba0cb,
+    0x404c20e1,
+    0x404ca0f3,
+    0x404d2114,
+    0x404da14d,
+    0x404e2161,
+    0x404ea16e,
+    0x404f2259,
+    0x404fa2cf,
+    0x4050238b,
+    0x4050a39f,
+    0x405123ec,
+    0x405223fc,
+    0x4052a42c,
+    0x40532444,
+    0x4053a457,
+    0x4054246c,
+    0x4054a48f,
+    0x405524ba,
+    0x4055a4f7,
+    0x4056251c,
+    0x4056a535,
+    0x4057254d,
+    0x4057a560,
+    0x40582575,
+    0x4058a59c,
+    0x405925cb,
+    0x4059a60b,
+    0x405aa61f,
+    0x405b2637,
+    0x405ba648,
+    0x405c265b,
+    0x405ca6b0,
+    0x405d26bd,
+    0x405da6e2,
+    0x405e2720,
     0x405e8afe,
-    0x405f2748,
-    0x405fa755,
-    0x40602763,
-    0x4060a785,
-    0x406127f9,
-    0x4061a831,
-    0x40622848,
-    0x4062a859,
-    0x406328a6,
-    0x4063a8bb,
-    0x406428d2,
-    0x4064a8fe,
-    0x40652919,
-    0x4065a930,
-    0x40662948,
-    0x4066a972,
-    0x4067299d,
-    0x4067a9e2,
-    0x40682a2a,
-    0x4068aa4b,
-    0x40692a7d,
-    0x4069aaab,
-    0x406a2acc,
-    0x406aaaec,
-    0x406b2c74,
-    0x406bac97,
-    0x406c2cad,
-    0x406cafb7,
-    0x406d2fe6,
-    0x406db00e,
-    0x406e303c,
-    0x406eb089,
-    0x406f30e2,
-    0x406fb11a,
-    0x4070312d,
-    0x4070b14a,
+    0x405f2750,
+    0x405fa75d,
+    0x4060276b,
+    0x4060a78d,
+    0x40612801,
+    0x4061a839,
+    0x40622850,
+    0x4062a861,
+    0x406328ae,
+    0x4063a8c3,
+    0x406428da,
+    0x4064a906,
+    0x40652921,
+    0x4065a938,
+    0x40662950,
+    0x4066a97a,
+    0x406729a5,
+    0x4067a9ea,
+    0x40682a32,
+    0x4068aa53,
+    0x40692a85,
+    0x4069aab3,
+    0x406a2ad4,
+    0x406aaaf4,
+    0x406b2c7c,
+    0x406bac9f,
+    0x406c2cb5,
+    0x406cafbf,
+    0x406d2fee,
+    0x406db016,
+    0x406e3044,
+    0x406eb091,
+    0x406f30ea,
+    0x406fb122,
+    0x40703135,
+    0x4070b152,
     0x4071084d,
-    0x4071b15c,
-    0x4072316f,
-    0x4072b1a5,
-    0x407331bd,
-    0x40739665,
-    0x407431d1,
-    0x4074b1eb,
-    0x407531fc,
-    0x4075b210,
-    0x4076321e,
+    0x4071b164,
+    0x40723177,
+    0x4072b1ad,
+    0x407331c5,
+    0x4073966d,
+    0x407431d9,
+    0x4074b1f3,
+    0x40753204,
+    0x4075b218,
+    0x40763226,
     0x407693f3,
-    0x4077325b,
-    0x4077b2b7,
-    0x407832d2,
-    0x4078b30b,
-    0x40793322,
-    0x4079b338,
-    0x407a3364,
-    0x407ab377,
-    0x407b338c,
-    0x407bb39e,
-    0x407c33cf,
-    0x407cb3d8,
-    0x407d2a66,
-    0x407da2ef,
-    0x407e32e7,
-    0x407ea5a4,
-    0x407f1eca,
-    0x407fa0ad,
-    0x40802261,
-    0x40809ef2,
-    0x40812412,
-    0x4081a1b4,
-    0x40823027,
-    0x40829c45,
-    0x4083257f,
-    0x4083a8e3,
-    0x40841f16,
-    0x4084a5dc,
-    0x40852664,
-    0x4085a7c0,
-    0x408626fa,
-    0x4086a33b,
-    0x4087306d,
-    0x4087a80e,
-    0x40881c83,
-    0x4088a9f5,
-    0x40891cd2,
-    0x40899c5f,
-    0x408a2ce5,
-    0x408a9a7d,
-    0x408b33b3,
-    0x408bb0f7,
-    0x408c268a,
-    0x408d1ffe,
-    0x408d9f48,
-    0x408e212e,
-    0x408ea4cf,
-    0x408f2a09,
-    0x408fa7dc,
-    0x409029be,
-    0x4090a6cc,
-    0x40912ccd,
-    0x40919ab5,
-    0x40921d1f,
-    0x4092b0a8,
-    0x40933188,
-    0x4093a34c,
-    0x40941f2a,
-    0x4094acfe,
-    0x4095286a,
-    0x4095b344,
-    0x40963054,
-    0x4096a27a,
-    0x409723cc,
-    0x4097a17d,
-    0x40981d7f,
-    0x4098a87e,
-    0x409930c4,
-    0x4099a4fc,
-    0x409a2495,
-    0x409a9a99,
-    0x409b1f84,
-    0x409b9faf,
-    0x409c3299,
-    0x409c9fd7,
-    0x409d2236,
-    0x409da1ca,
-    0x409e1e10,
-    0x409ea2af,
-    0x409f2297,
-    0x409f9f77,
-    0x40a022d7,
-    0x40a0a197,
-    0x40a121e5,
-    0x40a1a5f0,
-    0x40a22368,
-    0x40a2a739,
-    0x40a327ad,
-    0x40a3b27d,
-    0x40a423b2,
-    0x40a4a1fc,
-    0x40a51f06,
-    0x40a5a309,
-    0x40a62674,
-    0x40a6a21e,
-    0x40a73243,
-    0x40a7a406,
-    0x40a82324,
-    0x41f42b9f,
-    0x41f92c31,
-    0x41fe2b24,
-    0x41feadda,
-    0x41ff2f08,
-    0x42032bb8,
-    0x42082bda,
-    0x4208ac16,
-    0x42092b08,
-    0x4209ac50,
-    0x420a2b5f,
-    0x420aab3f,
-    0x420b2b7f,
-    0x420babf8,
-    0x420c2f24,
-    0x420cad0e,
-    0x420d2dc1,
-    0x420dadf8,
-    0x42122e2b,
-    0x42172eeb,
-    0x4217ae6d,
-    0x421c2e8f,
-    0x421f2e4a,
-    0x42212f9c,
-    0x42262ece,
-    0x422b2f7a,
-    0x422bad9c,
-    0x422c2f5c,
-    0x422cad4f,
-    0x422d2d28,
-    0x422daf3b,
-    0x422e2d7b,
-    0x42302eaa,
-    0x4230ae12,
+    0x40773263,
+    0x4077b2bf,
+    0x407832da,
+    0x4078b313,
+    0x4079332a,
+    0x4079b340,
+    0x407a336c,
+    0x407ab37f,
+    0x407b3394,
+    0x407bb3a6,
+    0x407c33d7,
+    0x407cb3e0,
+    0x407d2a6e,
+    0x407da2f7,
+    0x407e32ef,
+    0x407ea5ac,
+    0x407f1ed2,
+    0x407fa0b5,
+    0x40802269,
+    0x40809efa,
+    0x4081241a,
+    0x4081a1bc,
+    0x4082302f,
+    0x40829c4d,
+    0x40832587,
+    0x4083a8eb,
+    0x40841f1e,
+    0x4084a5e4,
+    0x4085266c,
+    0x4085a7c8,
+    0x40862702,
+    0x4086a343,
+    0x40873075,
+    0x4087a816,
+    0x40881c8b,
+    0x4088a9fd,
+    0x40891cda,
+    0x40899c67,
+    0x408a2ced,
+    0x408a9a85,
+    0x408b33bb,
+    0x408bb0ff,
+    0x408c2692,
+    0x408d2006,
+    0x408d9f50,
+    0x408e2136,
+    0x408ea4d7,
+    0x408f2a11,
+    0x408fa7e4,
+    0x409029c6,
+    0x4090a6d4,
+    0x40912cd5,
+    0x40919abd,
+    0x40921d27,
+    0x4092b0b0,
+    0x40933190,
+    0x4093a354,
+    0x40941f32,
+    0x4094ad06,
+    0x40952872,
+    0x4095b34c,
+    0x4096305c,
+    0x4096a282,
+    0x409723d4,
+    0x4097a185,
+    0x40981d87,
+    0x4098a886,
+    0x409930cc,
+    0x4099a504,
+    0x409a249d,
+    0x409a9aa1,
+    0x409b1f8c,
+    0x409b9fb7,
+    0x409c32a1,
+    0x409c9fdf,
+    0x409d223e,
+    0x409da1d2,
+    0x409e1e18,
+    0x409ea2b7,
+    0x409f229f,
+    0x409f9f7f,
+    0x40a022df,
+    0x40a0a19f,
+    0x40a121ed,
+    0x40a1a5f8,
+    0x40a22370,
+    0x40a2a741,
+    0x40a327b5,
+    0x40a3b285,
+    0x40a423ba,
+    0x40a4a204,
+    0x40a51f0e,
+    0x40a5a311,
+    0x40a6267c,
+    0x40a6a226,
+    0x40a7324b,
+    0x40a7a40e,
+    0x40a8232c,
+    0x41f42ba7,
+    0x41f92c39,
+    0x41fe2b2c,
+    0x41feade2,
+    0x41ff2f10,
+    0x42032bc0,
+    0x42082be2,
+    0x4208ac1e,
+    0x42092b10,
+    0x4209ac58,
+    0x420a2b67,
+    0x420aab47,
+    0x420b2b87,
+    0x420bac00,
+    0x420c2f2c,
+    0x420cad16,
+    0x420d2dc9,
+    0x420dae00,
+    0x42122e33,
+    0x42172ef3,
+    0x4217ae75,
+    0x421c2e97,
+    0x421f2e52,
+    0x42212fa4,
+    0x42262ed6,
+    0x422b2f82,
+    0x422bada4,
+    0x422c2f64,
+    0x422cad57,
+    0x422d2d30,
+    0x422daf43,
+    0x422e2d83,
+    0x42302eb2,
+    0x4230ae1a,
     0x44320778,
     0x44328787,
     0x44330793,
@@ -674,109 +675,109 @@
     0x4439084d,
     0x4439885b,
     0x443a086e,
-    0x4832143b,
-    0x4832944d,
-    0x48331463,
-    0x4833947c,
-    0x4c3214b9,
-    0x4c3294c9,
-    0x4c3314dc,
-    0x4c3394fc,
+    0x48321443,
+    0x48329455,
+    0x4833146b,
+    0x48339484,
+    0x4c3214c1,
+    0x4c3294d1,
+    0x4c3314e4,
+    0x4c339504,
     0x4c3400b9,
     0x4c3480f7,
-    0x4c351508,
-    0x4c359516,
-    0x4c361532,
-    0x4c369558,
-    0x4c371567,
-    0x4c379575,
-    0x4c38158a,
-    0x4c389596,
-    0x4c3915b6,
-    0x4c3995e0,
-    0x4c3a15f9,
-    0x4c3a9612,
+    0x4c351510,
+    0x4c35951e,
+    0x4c36153a,
+    0x4c369560,
+    0x4c37156f,
+    0x4c37957d,
+    0x4c381592,
+    0x4c38959e,
+    0x4c3915be,
+    0x4c3995e8,
+    0x4c3a1601,
+    0x4c3a961a,
     0x4c3b0635,
-    0x4c3b962b,
-    0x4c3c163d,
-    0x4c3c964c,
-    0x4c3d1665,
+    0x4c3b9633,
+    0x4c3c1645,
+    0x4c3c9654,
+    0x4c3d166d,
     0x4c3d8d06,
-    0x4c3e16d2,
-    0x4c3e9674,
-    0x4c3f16f4,
+    0x4c3e16da,
+    0x4c3e967c,
+    0x4c3f16fc,
     0x4c3f93f3,
-    0x4c40168a,
-    0x4c4094a5,
-    0x4c4116c2,
-    0x4c419545,
-    0x4c4216ae,
-    0x4c42948d,
-    0x50323799,
-    0x5032b7a8,
-    0x503337b3,
-    0x5033b7c3,
-    0x503437dc,
-    0x5034b7f6,
-    0x50353804,
-    0x5035b81a,
-    0x5036382c,
-    0x5036b842,
-    0x5037385b,
-    0x5037b86e,
-    0x50383886,
-    0x5038b897,
-    0x503938ac,
-    0x5039b8c0,
-    0x503a38e0,
-    0x503ab8f6,
-    0x503b390e,
-    0x503bb920,
-    0x503c393c,
-    0x503cb953,
-    0x503d396c,
-    0x503db982,
-    0x503e398f,
-    0x503eb9a5,
-    0x503f39b7,
+    0x4c401692,
+    0x4c4094ad,
+    0x4c4116ca,
+    0x4c41954d,
+    0x4c4216b6,
+    0x4c429495,
+    0x503237a1,
+    0x5032b7b0,
+    0x503337bb,
+    0x5033b7cb,
+    0x503437e4,
+    0x5034b7fe,
+    0x5035380c,
+    0x5035b822,
+    0x50363834,
+    0x5036b84a,
+    0x50373863,
+    0x5037b876,
+    0x5038388e,
+    0x5038b89f,
+    0x503938b4,
+    0x5039b8c8,
+    0x503a38e8,
+    0x503ab8fe,
+    0x503b3916,
+    0x503bb928,
+    0x503c3944,
+    0x503cb95b,
+    0x503d3974,
+    0x503db98a,
+    0x503e3997,
+    0x503eb9ad,
+    0x503f39bf,
     0x503f83b3,
-    0x504039ca,
-    0x5040b9da,
-    0x504139f4,
-    0x5041ba03,
-    0x50423a1d,
-    0x5042ba3a,
-    0x50433a4a,
-    0x5043ba5a,
-    0x50443a77,
+    0x504039d2,
+    0x5040b9e2,
+    0x504139fc,
+    0x5041ba0b,
+    0x50423a25,
+    0x5042ba42,
+    0x50433a52,
+    0x5043ba62,
+    0x50443a7f,
     0x50448469,
-    0x50453a8b,
-    0x5045baa9,
-    0x50463abc,
-    0x5046bad2,
-    0x50473ae4,
-    0x5047baf9,
-    0x50483b1f,
-    0x5048bb2d,
-    0x50493b40,
-    0x5049bb55,
-    0x504a3b6b,
-    0x504abb7b,
-    0x504b3b9b,
-    0x504bbbae,
-    0x504c3bd1,
-    0x504cbbff,
-    0x504d3c2c,
-    0x504dbc49,
-    0x504e3c64,
-    0x504ebc80,
-    0x504f3c92,
-    0x504fbca9,
-    0x50503cb8,
+    0x50453a93,
+    0x5045bab1,
+    0x50463ac4,
+    0x5046bada,
+    0x50473aec,
+    0x5047bb01,
+    0x50483b27,
+    0x5048bb35,
+    0x50493b48,
+    0x5049bb5d,
+    0x504a3b73,
+    0x504abb83,
+    0x504b3ba3,
+    0x504bbbb6,
+    0x504c3bd9,
+    0x504cbc07,
+    0x504d3c34,
+    0x504dbc51,
+    0x504e3c6c,
+    0x504ebc88,
+    0x504f3c9a,
+    0x504fbcb1,
+    0x50503cc0,
     0x50508729,
-    0x50513ccb,
-    0x5051ba69,
-    0x50523c11,
+    0x50513cd3,
+    0x5051ba71,
+    0x50523c19,
     0x58321011,
     0x68320fd3,
     0x68328d2b,
@@ -819,21 +820,21 @@
     0x783e0aed,
     0x783e8a9f,
     0x7c32130c,
-    0x80321558,
+    0x80321560,
     0x80328090,
-    0x80333495,
+    0x8033349d,
     0x803380b9,
-    0x803434a4,
-    0x8034b40c,
-    0x8035342a,
-    0x8035b4b8,
-    0x8036346c,
-    0x8036b41b,
-    0x8037345e,
-    0x8037b3f9,
-    0x8038347f,
-    0x8038b43b,
-    0x80393450,
+    0x803434ac,
+    0x8034b414,
+    0x80353432,
+    0x8035b4c0,
+    0x80363474,
+    0x8036b423,
+    0x80373466,
+    0x8037b401,
+    0x80383487,
+    0x8038b443,
+    0x80393458,
     0x84320bb0,
     0x84328bc9,
 };
@@ -1111,6 +1112,7 @@
     "UNSUPPORTED_CIPHER\0"
     "UNSUPPORTED_ENCRYPTION\0"
     "UNSUPPORTED_PROC_TYPE_VERSION\0"
+    "NO_DATA\0"
     "BAD_PKCS7_VERSION\0"
     "NOT_PKCS7_SIGNED_DATA\0"
     "NO_CERTIFICATES_INCLUDED\0"
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index 6827b5d..5a4c2ab 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -465,5 +465,6 @@
 #define PEM_R_UNSUPPORTED_CIPHER 113
 #define PEM_R_UNSUPPORTED_ENCRYPTION 114
 #define PEM_R_UNSUPPORTED_PROC_TYPE_VERSION 115
+#define PEM_R_NO_DATA 116
 
 #endif  // OPENSSL_HEADER_PEM_H
diff --git a/rust/bssl-x509/src/errors.rs b/rust/bssl-x509/src/errors.rs
index 3d63d28..dfb5e46 100644
--- a/rust/bssl-x509/src/errors.rs
+++ b/rust/bssl-x509/src/errors.rs
@@ -14,7 +14,7 @@
 
 //! X.509 certificate verification errors.
 
-use core::ffi::{CStr, c_char};
+use core::ffi::{c_char, CStr};
 use core::fmt::{self, Debug, Display};
 
 use bssl_macros::bssl_enum;
@@ -282,6 +282,8 @@
         UnsupportedEncryption = bssl_sys::PEM_R_UNSUPPORTED_ENCRYPTION as i32,
         /// `PEM_R_UNSUPPORTED_PROC_TYPE_VERSION`
         UnsupportedProcTypeVersion = bssl_sys::PEM_R_UNSUPPORTED_PROC_TYPE_VERSION as i32,
+        /// `PEM_R_NO_DATA`
+        NoData = bssl_sys::PEM_R_NO_DATA as i32,
     }
 }