Merge pull request #7868 from gilles-peskine-arm/readme-python3.6

Backport 2.28: officially require Python 3.6
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/ChangeLog.d/fix-tfm-build.txt b/ChangeLog.d/fix-tfm-build.txt
new file mode 100644
index 0000000..a63bc2f
--- /dev/null
+++ b/ChangeLog.d/fix-tfm-build.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix compilation warnings in aes.c for certain combinations
+     of configuration options.
diff --git a/ChangeLog.d/fix-win32-llvm-build.txt b/ChangeLog.d/fix-win32-llvm-build.txt
new file mode 100644
index 0000000..826551c
--- /dev/null
+++ b/ChangeLog.d/fix-win32-llvm-build.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix builds on Windows with clang
diff --git a/library/aes.c b/library/aes.c
index f08a21f..c506709 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -58,6 +58,8 @@
 /*
  * Forward S-box
  */
+#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
+    !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
 static const unsigned char FSb[256] =
 {
     0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
@@ -93,6 +95,8 @@
     0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
     0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
 };
+#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
+          !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
 
 /*
  * Forward tables
@@ -164,6 +168,7 @@
     V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \
     V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C)
 
+#if !defined(MBEDTLS_AES_ENCRYPT_ALT)
 #define V(a, b, c, d) 0x##a##b##c##d
 static const uint32_t FT0[256] = { FT };
 #undef V
@@ -184,8 +189,11 @@
 
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
 
+#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) */
+
 #undef FT
 
+#if !defined(MBEDTLS_AES_DECRYPT_ALT)
 /*
  * Reverse S-box
  */
@@ -224,6 +232,7 @@
     0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
     0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
 };
+#endif /* defined(MBEDTLS_AES_DECRYPT_ALT)) */
 
 /*
  * Reverse tables
@@ -295,6 +304,8 @@
     V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \
     V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0)
 
+#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
+
 #define V(a, b, c, d) 0x##a##b##c##d
 static const uint32_t RT0[256] = { RT };
 #undef V
@@ -315,8 +326,11 @@
 
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
 
+#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
+
 #undef RT
 
+#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
 /*
  * Round constants
  */
@@ -326,31 +340,44 @@
     0x00000010, 0x00000020, 0x00000040, 0x00000080,
     0x0000001B, 0x00000036
 };
+#endif /* !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
 
 #else /* MBEDTLS_AES_ROM_TABLES */
 
 /*
  * Forward S-box & tables
  */
+#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
+    !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
 static unsigned char FSb[256];
+#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
+          !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
+#if !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
 static uint32_t FT0[256];
 #if !defined(MBEDTLS_AES_FEWER_TABLES)
 static uint32_t FT1[256];
 static uint32_t FT2[256];
 static uint32_t FT3[256];
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
+#endif /* !defined(MBEDTLS_AES_ENCRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
 
 /*
  * Reverse S-box & tables
  */
+#if !(defined(MBEDTLS_AES_SETKEY_ENC_ALT) && defined(MBEDTLS_AES_DECRYPT_ALT))
 static unsigned char RSb[256];
+#endif /* !(defined(MBEDTLS_AES_SETKEY_ENC_ALT) && defined(MBEDTLS_AES_DECRYPT_ALT)) */
+
+#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
 static uint32_t RT0[256];
 #if !defined(MBEDTLS_AES_FEWER_TABLES)
 static uint32_t RT1[256];
 static uint32_t RT2[256];
 static uint32_t RT3[256];
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
+#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
 
+#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
 /*
  * Round constants
  */
@@ -428,6 +455,7 @@
 
         x = RSb[i];
 
+#if !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
         RT0[i] = ((uint32_t) MUL(0x0E, x)) ^
                  ((uint32_t) MUL(0x09, x) <<  8) ^
                  ((uint32_t) MUL(0x0D, x) << 16) ^
@@ -438,9 +466,12 @@
         RT2[i] = ROTL8(RT1[i]);
         RT3[i] = ROTL8(RT2[i]);
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
+#endif /* !defined(MBEDTLS_AES_DECRYPT_ALT) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) */
     }
 }
 
+#endif /* !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
+
 #undef ROTL8
 
 #endif /* MBEDTLS_AES_ROM_TABLES */
@@ -521,6 +552,9 @@
     (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
 #define MAY_NEED_TO_ALIGN
 #endif
+
+#if defined(MAY_NEED_TO_ALIGN) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) || \
+    !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
 static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
 {
 #if defined(MAY_NEED_TO_ALIGN)
@@ -557,6 +591,8 @@
 
     return 0;
 }
+#endif /* defined(MAY_NEED_TO_ALIGN) || !defined(MBEDTLS_AES_SETKEY_DEC_ALT) || \
+          !defined(MBEDTLS_AES_SETKEY_ENC_ALT) */
 
 /*
  * AES key schedule (encryption)
diff --git a/library/aesni.c b/library/aesni.c
index c909f65..866b6cb 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -41,6 +41,8 @@
 #if MBEDTLS_AESNI_HAVE_CODE == 2
 #if !defined(_WIN32)
 #include <cpuid.h>
+#else
+#include <intrin.h>
 #endif
 #include <immintrin.h>
 #endif
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 652c5cb..45d9254 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -30,6 +30,7 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
+#include <limits.h>
 #include <string.h>
 
 #if defined(MBEDTLS_FS_IO)
diff --git a/library/entropy.c b/library/entropy.c
index af78acc..e9a7ae6 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -31,6 +31,8 @@
 #include "mbedtls/entropy_poll.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
 
 #include <string.h>
 
diff --git a/library/pkparse.c b/library/pkparse.c
index deaff0b..76fe0c8 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -1235,6 +1235,8 @@
     mbedtls_pem_context pem;
 #endif
 
+    (void) pk_info;
+
     PK_VALIDATE_RET(pk != NULL);
     if (keylen == 0) {
         return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
diff --git a/library/pkwrite.c b/library/pkwrite.c
index 0107f20..88e6855 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -178,6 +178,11 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
+    (void) p;
+    (void) start;
+    (void) key;
+    (void) ret;
+
     PK_VALIDATE_RET(p != NULL);
     PK_VALIDATE_RET(*p != NULL);
     PK_VALIDATE_RET(start != NULL);
@@ -313,6 +318,10 @@
     unsigned char *c;
     size_t len = 0;
 
+    (void) ret;
+    (void) c;
+    (void) key;
+
     PK_VALIDATE_RET(key != NULL);
     if (size == 0) {
         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
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/scripts/code_style.py b/scripts/code_style.py
index c31fb29..7de93b0 100755
--- a/scripts/code_style.py
+++ b/scripts/code_style.py
@@ -22,7 +22,7 @@
 import re
 import subprocess
 import sys
-from typing import FrozenSet, List
+from typing import FrozenSet, List, Optional
 
 UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1"
 CONFIG_FILE = ".uncrustify.cfg"
@@ -63,31 +63,38 @@
     checks = re.findall(CHECK_CALL_RE, content)
     return frozenset(word for s in checks for word in s.split())
 
-def get_src_files() -> List[str]:
+def get_src_files(since: Optional[str]) -> List[str]:
     """
-    Use git ls-files to get a list of the source files
+    Use git to get a list of the source files.
+
+    The optional argument since is a commit, indicating to only list files
+    that have changed since that commit. Without this argument, list all
+    files known to git.
+
+    Only C files are included, and certain files (generated, or 3rdparty)
+    are excluded.
     """
-    git_ls_files_cmd = ["git", "ls-files",
-                        "*.[hc]",
-                        "tests/suites/*.function",
-                        "scripts/data_files/*.fmt"]
+    file_patterns = ["*.[hc]",
+                     "tests/suites/*.function",
+                     "scripts/data_files/*.fmt"]
+    output = subprocess.check_output(["git", "ls-files"] + file_patterns,
+                                     universal_newlines=True)
+    src_files = output.split()
+    if since:
+        output = subprocess.check_output(["git", "diff", "--name-only",
+                                          since, "--"] +
+                                         src_files,
+                                         universal_newlines=True)
+        src_files = output.split()
 
-    result = subprocess.run(git_ls_files_cmd, stdout=subprocess.PIPE,
-                            check=False)
-
-    if result.returncode != 0:
-        print_err("git ls-files returned: " + str(result.returncode))
-        return []
-    else:
-        generated_files = list_generated_files()
-        src_files = str(result.stdout, "utf-8").split()
-        # Don't correct style for third-party files (and, for simplicity,
-        # companion files in the same subtree), or for automatically
-        # generated files (we're correcting the templates instead).
-        src_files = [filename for filename in src_files
-                     if not (filename.startswith("3rdparty/") or
-                             filename in generated_files)]
-        return src_files
+    generated_files = list_generated_files()
+    # Don't correct style for third-party files (and, for simplicity,
+    # companion files in the same subtree), or for automatically
+    # generated files (we're correcting the templates instead).
+    src_files = [filename for filename in src_files
+                 if not (filename.startswith("3rdparty/") or
+                         filename in generated_files)]
+    return src_files
 
 def get_uncrustify_version() -> str:
     """
@@ -182,6 +189,9 @@
     parser.add_argument('-f', '--fix', action='store_true',
                         help=('modify source files to fix the code style '
                               '(default: print diff, do not modify files)'))
+    parser.add_argument('-s', '--since', metavar='COMMIT',
+                        help=('only check files modified since the specified commit'
+                              ' (e.g. --since=HEAD~3 or --since=development)'))
     # --subset is almost useless: it only matters if there are no files
     # ('code_style.py' without arguments checks all files known to Git,
     # 'code_style.py --subset' does nothing). In particular,
@@ -194,7 +204,7 @@
 
     args = parser.parse_args()
 
-    covered = frozenset(get_src_files())
+    covered = frozenset(get_src_files(args.since))
     # We only check files that are known to git
     if args.subset or args.operands:
         src_files = [f for f in args.operands if f in covered]
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index dae54c7..75e5e6b 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -2496,6 +2496,43 @@
     make CC=gcc CFLAGS='-Werror -O1' all test
 }
 
+component_build_aes_variations() { # ~45s
+    msg "build: aes.o for all combinations of relevant config options"
+
+    for a in set unset; do
+    for b in set unset; do
+    for c in set unset; do
+    for d in set unset; do
+    for e in set unset; do
+    for f in set unset; do
+    for g in set unset; do
+        echo ./scripts/config.py $a MBEDTLS_AES_SETKEY_ENC_ALT
+        echo ./scripts/config.py $b MBEDTLS_AES_DECRYPT_ALT
+        echo ./scripts/config.py $c MBEDTLS_AES_ROM_TABLES
+        echo ./scripts/config.py $d MBEDTLS_AES_ENCRYPT_ALT
+        echo ./scripts/config.py $e MBEDTLS_AES_SETKEY_DEC_ALT
+        echo ./scripts/config.py $f MBEDTLS_AES_FEWER_TABLES
+        echo ./scripts/config.py $g MBEDTLS_PADLOCK_C
+
+        ./scripts/config.py $a MBEDTLS_AES_SETKEY_ENC_ALT
+        ./scripts/config.py $b MBEDTLS_AES_DECRYPT_ALT
+        ./scripts/config.py $c MBEDTLS_AES_ROM_TABLES
+        ./scripts/config.py $d MBEDTLS_AES_ENCRYPT_ALT
+        ./scripts/config.py $e MBEDTLS_AES_SETKEY_DEC_ALT
+        ./scripts/config.py $f MBEDTLS_AES_FEWER_TABLES
+        ./scripts/config.py $g MBEDTLS_PADLOCK_C
+
+        rm -f library/aes.o
+        make -C library aes.o CC="clang" CFLAGS="-O0 -std=c99 -Werror -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral -Wshadow -Wasm-operand-widths -Wunused"
+    done
+    done
+    done
+    done
+    done
+    done
+    done
+}
+
 component_test_no_platform () {
     # Full configuration build, without platform support, file IO and net sockets.
     # This should catch missing mbedtls_printf definitions, and by disabling file
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: