Merge pull request #7823 from SlugFiller/mbedtls-2.28

Support compilation using CLang on Windows
diff --git a/ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt b/ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt
new file mode 100644
index 0000000..ded9b2d
--- /dev/null
+++ b/ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix crypt_and_hash decryption fail when used with a stream cipher
+     mode of operation due to the input not being multiple of block size.
+     Resolves #7417.
diff --git a/ChangeLog.d/fix-string-to-names-retcode.txt b/ChangeLog.d/fix-string-to-names-retcode.txt
new file mode 100644
index 0000000..ac4b3d1
--- /dev/null
+++ b/ChangeLog.d/fix-string-to-names-retcode.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix a bug in which mbedtls_x509_string_to_names() would return success
+     when given a invalid name string if it did not contain '=' or ','.
diff --git a/library/x509_create.c b/library/x509_create.c
index 50db956..cdfc82a 100644
--- a/library/x509_create.c
+++ b/library/x509_create.c
@@ -125,7 +125,7 @@
 
 int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
 {
-    int ret = 0;
+    int ret = MBEDTLS_ERR_X509_INVALID_NAME;
     const char *s = name, *c = s;
     const char *end = s + strlen(s);
     const char *oid = NULL;
@@ -177,6 +177,9 @@
 
             s = c + 1;
             in_tag = 1;
+
+            /* Successfully parsed one name, update ret to success */
+            ret = 0;
         }
 
         if (!in_tag && s != c + 1) {
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index 434c609..98253c6 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -92,6 +92,9 @@
     const mbedtls_md_info_t *md_info;
     mbedtls_cipher_context_t cipher_ctx;
     mbedtls_md_context_t md_ctx;
+    mbedtls_cipher_mode_t cipher_mode;
+    unsigned int cipher_block_size;
+    unsigned char md_size;
 #if defined(_WIN32_WCE)
     long filesize, offset;
 #elif defined(_WIN32)
@@ -240,6 +243,9 @@
         goto exit;
     }
 
+    md_size = mbedtls_md_get_size(md_info);
+    cipher_block_size = mbedtls_cipher_get_block_size(&cipher_ctx);
+
     if (mode == MODE_ENCRYPT) {
         /*
          * Generate the initialization vector as:
@@ -332,9 +338,9 @@
         /*
          * Encrypt and write the ciphertext.
          */
-        for (offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size(&cipher_ctx)) {
-            ilen = ((unsigned int) filesize - offset > mbedtls_cipher_get_block_size(&cipher_ctx)) ?
-                   mbedtls_cipher_get_block_size(&cipher_ctx) : (unsigned int) (filesize - offset);
+        for (offset = 0; offset < filesize; offset += cipher_block_size) {
+            ilen = ((unsigned int) filesize - offset > cipher_block_size) ?
+                   cipher_block_size : (unsigned int) (filesize - offset);
 
             if (fread(buffer, 1, ilen, fin) != ilen) {
                 mbedtls_fprintf(stderr, "fread(%ld bytes) failed\n", (long) ilen);
@@ -379,8 +385,8 @@
             goto exit;
         }
 
-        if (fwrite(digest, 1, mbedtls_md_get_size(md_info), fout) != mbedtls_md_get_size(md_info)) {
-            mbedtls_fprintf(stderr, "fwrite(%d bytes) failed\n", mbedtls_md_get_size(md_info));
+        if (fwrite(digest, 1, md_size, fout) != md_size) {
+            mbedtls_fprintf(stderr, "fwrite(%d bytes) failed\n", md_size);
             goto exit;
         }
     }
@@ -395,12 +401,12 @@
          *      N*16 .. (N+1)*16 - 1    Encrypted Block #N
          *  (N+1)*16 .. (N+1)*16 + n    Hash(ciphertext)
          */
-        if (filesize < 16 + mbedtls_md_get_size(md_info)) {
+        if (filesize < 16 + md_size) {
             mbedtls_fprintf(stderr, "File too short to be encrypted.\n");
             goto exit;
         }
 
-        if (mbedtls_cipher_get_block_size(&cipher_ctx) == 0) {
+        if (cipher_block_size == 0) {
             mbedtls_fprintf(stderr, "Invalid cipher block size: 0. \n");
             goto exit;
         }
@@ -408,18 +414,21 @@
         /*
          * Check the file size.
          */
-        if (cipher_info->mode != MBEDTLS_MODE_GCM &&
-            ((filesize - mbedtls_md_get_size(md_info)) %
-             mbedtls_cipher_get_block_size(&cipher_ctx)) != 0) {
+        cipher_mode = cipher_info->mode;
+        if (cipher_mode != MBEDTLS_MODE_GCM &&
+            cipher_mode != MBEDTLS_MODE_CTR &&
+            cipher_mode != MBEDTLS_MODE_CFB &&
+            cipher_mode != MBEDTLS_MODE_OFB &&
+            ((filesize - md_size) % cipher_block_size) != 0) {
             mbedtls_fprintf(stderr, "File content not a multiple of the block size (%u).\n",
-                            mbedtls_cipher_get_block_size(&cipher_ctx));
+                            cipher_block_size);
             goto exit;
         }
 
         /*
          * Subtract the IV + HMAC length.
          */
-        filesize -= (16 + mbedtls_md_get_size(md_info));
+        filesize -= (16 + md_size);
 
         /*
          * Read the IV and original filesize modulo 16.
@@ -481,13 +490,13 @@
         /*
          * Decrypt and write the plaintext.
          */
-        for (offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size(&cipher_ctx)) {
-            ilen = ((unsigned int) filesize - offset > mbedtls_cipher_get_block_size(&cipher_ctx)) ?
-                   mbedtls_cipher_get_block_size(&cipher_ctx) : (unsigned int) (filesize - offset);
+        for (offset = 0; offset < filesize; offset += cipher_block_size) {
+            ilen = ((unsigned int) filesize - offset > cipher_block_size) ?
+                   cipher_block_size : (unsigned int) (filesize - offset);
 
             if (fread(buffer, 1, ilen, fin) != ilen) {
                 mbedtls_fprintf(stderr, "fread(%u bytes) failed\n",
-                                mbedtls_cipher_get_block_size(&cipher_ctx));
+                                cipher_block_size);
                 goto exit;
             }
 
@@ -515,14 +524,14 @@
             goto exit;
         }
 
-        if (fread(buffer, 1, mbedtls_md_get_size(md_info), fin) != mbedtls_md_get_size(md_info)) {
-            mbedtls_fprintf(stderr, "fread(%d bytes) failed\n", mbedtls_md_get_size(md_info));
+        if (fread(buffer, 1, md_size, fin) != md_size) {
+            mbedtls_fprintf(stderr, "fread(%d bytes) failed\n", md_size);
             goto exit;
         }
 
         /* Use constant-time buffer comparison */
         diff = 0;
-        for (i = 0; i < mbedtls_md_get_size(md_info); i++) {
+        for (i = 0; i < md_size; i++) {
             diff |= digest[i] ^ buffer[i];
         }
 
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index 2fc7143..999c05f 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -133,5 +133,8 @@
 X509 String to Names #6 (Escape at end)
 mbedtls_x509_string_to_names:"C=NL, O=Offspark\\":"":MBEDTLS_ERR_X509_INVALID_NAME
 
+X509 String to Names #6 (Invalid, no '=' or ',')
+mbedtls_x509_string_to_names:"ABC123":"":MBEDTLS_ERR_X509_INVALID_NAME
+
 Check max serial length
 x509_set_serial_check: