Implement ASN1_STRING_print_ex_fp, etc., with file BIOs.

No sense in implementing a BIO/FILE abstraction when BIO is itself a
FILE abstraction. Follow-up CLs will unwind the char_io abstraction and
then split the ASN1 and X509 bits of this file.

Change-Id: I00aaf2fbab44abdd88252ceb5feb071ad126a0b2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48772
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/a_strex.c b/crypto/x509/a_strex.c
index 7e93387..4dee74d 100644
--- a/crypto/x509/a_strex.c
+++ b/crypto/x509/a_strex.c
@@ -88,15 +88,6 @@
     return 1;
 }
 
-static int send_fp_chars(void *arg, const void *buf, int len)
-{
-    if (!arg)
-        return 1;
-    if (fwrite(buf, 1, len, arg) != (unsigned int)len)
-        return 0;
-    return 1;
-}
-
 typedef int char_io (void *arg, const void *buf, int len);
 
 /*
@@ -595,17 +586,18 @@
 int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
                           unsigned long flags)
 {
-    if (flags == XN_FLAG_COMPAT) {
-        BIO *btmp;
-        int ret;
-        btmp = BIO_new_fp(fp, BIO_NOCLOSE);
-        if (!btmp)
+    BIO *bio = NULL;
+    if (fp != NULL) {
+        /* If |fp| is NULL, this function returns the number of bytes without
+         * writing. */
+        bio = BIO_new_fp(fp, BIO_NOCLOSE);
+        if (bio == NULL) {
             return -1;
-        ret = X509_NAME_print(btmp, nm, indent);
-        BIO_free(btmp);
-        return ret;
+        }
     }
-    return do_name_ex(send_fp_chars, fp, nm, indent, flags);
+    int ret = X509_NAME_print_ex(bio, nm, indent, flags);
+    BIO_free(bio);
+    return ret;
 }
 
 int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
@@ -615,7 +607,18 @@
 
 int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
 {
-    return do_print_ex(send_fp_chars, fp, flags, str);
+    BIO *bio = NULL;
+    if (fp != NULL) {
+        /* If |fp| is NULL, this function returns the number of bytes without
+         * writing. */
+        bio = BIO_new_fp(fp, BIO_NOCLOSE);
+        if (bio == NULL) {
+            return -1;
+        }
+    }
+    int ret = ASN1_STRING_print_ex(bio, str, flags);
+    BIO_free(bio);
+    return ret;
 }
 
 /*