Allow multiple IDN xn-- indicators

Update the X509v3 name parsing to allow multiple xn-- international
domain name indicators in a name.  Previously, only allowed one at
the beginning of a name, which was wrong.

(Imported from upstream's 31d1d3741f16bd80ec25f72dcdbf6bbdc5664374)

Change-Id: I93f1db7a5920305569af23f9f2b30ab5cc226521
Reviewed-on: https://boringssl-review.googlesource.com/13984
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
index b603274..fe7787b 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -824,32 +824,16 @@
                 return NULL;
             star = &p[i];
             state &= ~LABEL_START;
-        } else if ((state & LABEL_START) != 0) {
-            /*
-             * At the start of a label, skip any "xn--" and
-             * remain in the LABEL_START state, but set the
-             * IDNA label state
-             */
-            if ((state & LABEL_IDNA) == 0 && len - i >= 4
-                && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0) {
-                i += 3;
-                state |= LABEL_IDNA;
-                continue;
-            }
-            /* Labels must start with a letter or digit */
-            state &= ~LABEL_START;
-            if (('a' <= p[i] && p[i] <= 'z')
-                || ('A' <= p[i] && p[i] <= 'Z')
-                || ('0' <= p[i] && p[i] <= '9'))
-                continue;
-            return NULL;
         } else if (('a' <= p[i] && p[i] <= 'z')
                    || ('A' <= p[i] && p[i] <= 'Z')
                    || ('0' <= p[i] && p[i] <= '9')) {
-            state &= LABEL_IDNA;
-            continue;
+            if ((state & LABEL_START) != 0
+                && len - i >= 4
+                && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
+                state |= LABEL_IDNA;
+            state &= ~(LABEL_HYPHEN | LABEL_START);
         } else if (p[i] == '.') {
-            if (state & (LABEL_HYPHEN | LABEL_START))
+            if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
                 return NULL;
             state = LABEL_START;
             ++dots;