Replace UTF8_putc with cbb_add_utf8.

cbb_add_utf8 is CBB-based, so it is bounds-checked.

Change-Id: Ib30272255894d7d3a35a164a5eefcdce9e8e7991
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/54646
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index d769efd..1f6dedc 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -217,7 +217,6 @@
   asn1/a_time.c
   asn1/a_type.c
   asn1/a_utctm.c
-  asn1/a_utf8.c
   asn1/asn1_lib.c
   asn1/asn1_par.c
   asn1/asn_pack.c
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
index fd08b02..c996acc 100644
--- a/crypto/asn1/a_strex.c
+++ b/crypto/asn1/a_strex.c
@@ -167,12 +167,17 @@
     }
     const int is_last = CBS_len(&cbs) == 0;
     if (flags & ASN1_STRFLGS_UTF8_CONVERT) {
-      unsigned char utfbuf[6];
-      int utflen;
-      utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
-      for (int i = 0; i < utflen; i++) {
-        int len = do_esc_char(utfbuf[i], flags, quotes, out, is_first && i == 0,
-                              is_last && i == utflen - 1);
+      uint8_t utf8_buf[6];
+      CBB utf8_cbb;
+      CBB_init_fixed(&utf8_cbb, utf8_buf, sizeof(utf8_buf));
+      if (!cbb_add_utf8(&utf8_cbb, c)) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
+        return 1;
+      }
+      size_t utf8_len = CBB_len(&utf8_cbb);
+      for (size_t i = 0; i < utf8_len; i++) {
+        int len = do_esc_char(utf8_buf[i], flags, quotes, out,
+                              is_first && i == 0, is_last && i == utf8_len - 1);
         if (len < 0) {
           return -1;
         }
diff --git a/crypto/asn1/a_utf8.c b/crypto/asn1/a_utf8.c
deleted file mode 100644
index 02c1d56..0000000
--- a/crypto/asn1/a_utf8.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-#include "internal.h"
-
-// UTF8 utilities
-
-// This takes a character 'value' and writes the UTF8 encoded value in 'str'
-// where 'str' is a buffer containing 'len' characters. Returns the number of
-// characters written or -1 if 'len' is too small. 'str' can be set to NULL
-// in which case it just returns the number of characters. It will need at
-// most 6 characters.
-
-int UTF8_putc(unsigned char *str, int len, uint32_t value) {
-  if (!str) {
-    len = 6;  // Maximum we will need
-  } else if (len <= 0) {
-    return -1;
-  }
-  if (value < 0x80) {
-    if (str) {
-      *str = (unsigned char)value;
-    }
-    return 1;
-  }
-  if (value < 0x800) {
-    if (len < 2) {
-      return -1;
-    }
-    if (str) {
-      *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
-      *str = (unsigned char)((value & 0x3f) | 0x80);
-    }
-    return 2;
-  }
-  if (value < 0x10000) {
-    if (len < 3) {
-      return -1;
-    }
-    if (str) {
-      *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
-      *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-      *str = (unsigned char)((value & 0x3f) | 0x80);
-    }
-    return 3;
-  }
-  if (value < 0x200000) {
-    if (len < 4) {
-      return -1;
-    }
-    if (str) {
-      *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
-      *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-      *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-      *str = (unsigned char)((value & 0x3f) | 0x80);
-    }
-    return 4;
-  }
-  if (value < 0x4000000) {
-    if (len < 5) {
-      return -1;
-    }
-    if (str) {
-      *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
-      *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
-      *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-      *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-      *str = (unsigned char)((value & 0x3f) | 0x80);
-    }
-    return 5;
-  }
-  if (len < 6) {
-    return -1;
-  }
-  if (str) {
-    *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
-    *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
-    *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
-    *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-    *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-    *str = (unsigned char)((value & 0x3f) | 0x80);
-  }
-  return 6;
-}
diff --git a/crypto/asn1/internal.h b/crypto/asn1/internal.h
index 3d78dd6..882b5fb 100644
--- a/crypto/asn1/internal.h
+++ b/crypto/asn1/internal.h
@@ -156,8 +156,6 @@
 void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
                             int combine);
 
-int UTF8_putc(unsigned char *str, int len, uint32_t value);
-
 int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
 void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it);