pem: fix valid data length returned by mbedtls_pem_read_buffer()

ctx->buflen now returns the amount of valid data in ctx->buf.
Unencrypted buffers were already ok, but encrypted ones were
used to return the length of the encrypted buffer, not the
unencrypted one.
This commit fix this behavior for encrypted buffers.

Signed-off-by: Valerio Setti <valerio.setti@nordicsemi.no>
diff --git a/include/mbedtls/pem.h b/include/mbedtls/pem.h
index cc617a9..3c6a28d 100644
--- a/include/mbedtls/pem.h
+++ b/include/mbedtls/pem.h
@@ -73,11 +73,11 @@
  * \param data      source data to look in (must be nul-terminated)
  * \param pwd       password for decryption (can be NULL)
  * \param pwdlen    length of password
- * \param use_len   destination for total length used (set after header is
- *                  correctly read, so unless you get
+ * \param use_len   destination for total length used from data buffer. It is
+ *                  set after header is correctly read, so unless you get
  *                  MBEDTLS_ERR_PEM_BAD_INPUT_DATA or
  *                  MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is
- *                  the length to skip)
+ *                  the length to skip.
  *
  * \note            Attempts to check password correctness by verifying if
  *                  the decrypted text starts with an ASN.1 sequence of
diff --git a/library/pem.c b/library/pem.c
index 539134c..7e7f86f 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -17,6 +17,7 @@
 #include "mbedtls/cipher.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/asn1.h"
 
 #include <string.h>
 
@@ -431,15 +432,20 @@
         }
 
         /*
-         * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
-         * length bytes (allow 4 to be sure) in all known use cases.
-         *
-         * Use that as a heuristic to try to detect password mismatches.
+         * The result will be ASN.1 starting with a SEQUENCE tag. Parse it
+         * with ASN.1 functions in order to:
+         * - Have an heuristic guess about password mismatches.
+         * - Update len variable to the amount of valid data inside buf.
          */
-        if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) {
-            mbedtls_zeroize_and_free(buf, len);
-            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+        unsigned char *p = buf;
+        ret = mbedtls_asn1_get_tag(&p, buf + len, &len,
+                                   MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED);
+        if (ret != 0) {
+            mbedtls_free(buf);
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
         }
+        /* Add also the sequence block (tag + len) to the total amount of valid data. */
+        len += (p - buf);
 #else
         mbedtls_zeroize_and_free(buf, len);
         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;