Move some ASN1 printing functions to crypto/asn1.
For some reason, ASN1_STRING_print was not in the same file as
ASN1_STRING_print_ex, but X509_print. Although it also behaves very
differently from ASN1_STRING_print_ex, so that's a little interesting.
Change-Id: I3f88f8943c8e36426eedafa7e350a787881d0c74
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48775
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
index 2e9f08a..2394939 100644
--- a/crypto/asn1/a_strex.c
+++ b/crypto/asn1/a_strex.c
@@ -56,6 +56,7 @@
#include <openssl/asn1.h>
+#include <ctype.h>
#include <inttypes.h>
#include <string.h>
@@ -445,3 +446,179 @@
*out = stmp.data;
return stmp.length;
}
+
+int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
+{
+ int i, n;
+ char buf[80];
+ const char *p;
+
+ if (v == NULL)
+ return (0);
+ n = 0;
+ p = (const char *)v->data;
+ for (i = 0; i < v->length; i++) {
+ if ((p[i] > '~') || ((p[i] < ' ') &&
+ (p[i] != '\n') && (p[i] != '\r')))
+ buf[n] = '.';
+ else
+ buf[n] = p[i];
+ n++;
+ if (n >= 80) {
+ if (BIO_write(bp, buf, n) <= 0)
+ return (0);
+ n = 0;
+ }
+ }
+ if (n > 0)
+ if (BIO_write(bp, buf, n) <= 0)
+ return (0);
+ return (1);
+}
+
+int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
+{
+ if (tm->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_print(bp, tm);
+ if (tm->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_print(bp, tm);
+ BIO_write(bp, "Bad time value", 14);
+ return (0);
+}
+
+static const char *const mon[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
+{
+ char *v;
+ int gmt = 0;
+ int i;
+ int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
+ char *f = NULL;
+ int f_len = 0;
+
+ i = tm->length;
+ v = (char *)tm->data;
+
+ if (i < 12)
+ goto err;
+ if (v[i - 1] == 'Z')
+ gmt = 1;
+ for (i = 0; i < 12; i++)
+ if ((v[i] > '9') || (v[i] < '0'))
+ goto err;
+ y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] -
+ '0');
+ M = (v[4] - '0') * 10 + (v[5] - '0');
+ if ((M > 12) || (M < 1))
+ goto err;
+ d = (v[6] - '0') * 10 + (v[7] - '0');
+ h = (v[8] - '0') * 10 + (v[9] - '0');
+ m = (v[10] - '0') * 10 + (v[11] - '0');
+ if (tm->length >= 14 &&
+ (v[12] >= '0') && (v[12] <= '9') &&
+ (v[13] >= '0') && (v[13] <= '9')) {
+ s = (v[12] - '0') * 10 + (v[13] - '0');
+ /* Check for fractions of seconds. */
+ if (tm->length >= 15 && v[14] == '.') {
+ int l = tm->length;
+ f = &v[14]; /* The decimal point. */
+ f_len = 1;
+ while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
+ ++f_len;
+ }
+ }
+
+ if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+ mon[M - 1], d, h, m, s, f_len, f, y,
+ (gmt) ? " GMT" : "") <= 0)
+ return (0);
+ else
+ return (1);
+ err:
+ BIO_write(bp, "Bad time value", 14);
+ return (0);
+}
+
+// consume_two_digits is a helper function for ASN1_UTCTIME_print. If |*v|,
+// assumed to be |*len| bytes long, has two leading digits, updates |*out| with
+// their value, updates |v| and |len|, and returns one. Otherwise, returns
+// zero.
+static int consume_two_digits(int* out, const char **v, int *len) {
+ if (*len < 2|| !isdigit((*v)[0]) || !isdigit((*v)[1])) {
+ return 0;
+ }
+ *out = ((*v)[0] - '0') * 10 + ((*v)[1] - '0');
+ *len -= 2;
+ *v += 2;
+ return 1;
+}
+
+// consume_zulu_timezone is a helper function for ASN1_UTCTIME_print. If |*v|,
+// assumed to be |*len| bytes long, starts with "Z" then it updates |*v| and
+// |*len| and returns one. Otherwise returns zero.
+static int consume_zulu_timezone(const char **v, int *len) {
+ if (*len == 0 || (*v)[0] != 'Z') {
+ return 0;
+ }
+
+ *len -= 1;
+ *v += 1;
+ return 1;
+}
+
+int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) {
+ const char *v = (const char *)tm->data;
+ int len = tm->length;
+ int Y = 0, M = 0, D = 0, h = 0, m = 0, s = 0;
+
+ // YYMMDDhhmm are required to be present.
+ if (!consume_two_digits(&Y, &v, &len) ||
+ !consume_two_digits(&M, &v, &len) ||
+ !consume_two_digits(&D, &v, &len) ||
+ !consume_two_digits(&h, &v, &len) ||
+ !consume_two_digits(&m, &v, &len)) {
+ goto err;
+ }
+ // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires seconds
+ // to be present, but historically this code has forgiven its absence.
+ consume_two_digits(&s, &v, &len);
+
+ // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, specifies this
+ // interpretation of the year.
+ if (Y < 50) {
+ Y += 2000;
+ } else {
+ Y += 1900;
+ }
+ if (M > 12 || M == 0) {
+ goto err;
+ }
+ if (D > 31 || D == 0) {
+ goto err;
+ }
+ if (h > 23 || m > 59 || s > 60) {
+ goto err;
+ }
+
+ // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires the "Z"
+ // to be present, but historically this code has forgiven its absence.
+ const int is_gmt = consume_zulu_timezone(&v, &len);
+
+ // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, does not permit
+ // the specification of timezones using the +hhmm / -hhmm syntax, which is
+ // the only other thing that might legitimately be found at the end.
+ if (len) {
+ goto err;
+ }
+
+ return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", mon[M - 1], D, h, m, s, Y,
+ is_gmt ? " GMT" : "") > 0;
+
+err:
+ BIO_write(bp, "Bad time value", 14);
+ return 0;
+}
diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c
index ac743f6..7c32a87 100644
--- a/crypto/x509/t_x509.c
+++ b/crypto/x509/t_x509.c
@@ -54,7 +54,6 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
-#include <ctype.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/digest.h>
@@ -316,182 +315,6 @@
return 1;
}
-int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
-{
- int i, n;
- char buf[80];
- const char *p;
-
- if (v == NULL)
- return (0);
- n = 0;
- p = (const char *)v->data;
- for (i = 0; i < v->length; i++) {
- if ((p[i] > '~') || ((p[i] < ' ') &&
- (p[i] != '\n') && (p[i] != '\r')))
- buf[n] = '.';
- else
- buf[n] = p[i];
- n++;
- if (n >= 80) {
- if (BIO_write(bp, buf, n) <= 0)
- return (0);
- n = 0;
- }
- }
- if (n > 0)
- if (BIO_write(bp, buf, n) <= 0)
- return (0);
- return (1);
-}
-
-int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
-{
- if (tm->type == V_ASN1_UTCTIME)
- return ASN1_UTCTIME_print(bp, tm);
- if (tm->type == V_ASN1_GENERALIZEDTIME)
- return ASN1_GENERALIZEDTIME_print(bp, tm);
- BIO_write(bp, "Bad time value", 14);
- return (0);
-}
-
-static const char *const mon[12] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
-{
- char *v;
- int gmt = 0;
- int i;
- int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
- char *f = NULL;
- int f_len = 0;
-
- i = tm->length;
- v = (char *)tm->data;
-
- if (i < 12)
- goto err;
- if (v[i - 1] == 'Z')
- gmt = 1;
- for (i = 0; i < 12; i++)
- if ((v[i] > '9') || (v[i] < '0'))
- goto err;
- y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] -
- '0');
- M = (v[4] - '0') * 10 + (v[5] - '0');
- if ((M > 12) || (M < 1))
- goto err;
- d = (v[6] - '0') * 10 + (v[7] - '0');
- h = (v[8] - '0') * 10 + (v[9] - '0');
- m = (v[10] - '0') * 10 + (v[11] - '0');
- if (tm->length >= 14 &&
- (v[12] >= '0') && (v[12] <= '9') &&
- (v[13] >= '0') && (v[13] <= '9')) {
- s = (v[12] - '0') * 10 + (v[13] - '0');
- /* Check for fractions of seconds. */
- if (tm->length >= 15 && v[14] == '.') {
- int l = tm->length;
- f = &v[14]; /* The decimal point. */
- f_len = 1;
- while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
- ++f_len;
- }
- }
-
- if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
- mon[M - 1], d, h, m, s, f_len, f, y,
- (gmt) ? " GMT" : "") <= 0)
- return (0);
- else
- return (1);
- err:
- BIO_write(bp, "Bad time value", 14);
- return (0);
-}
-
-// consume_two_digits is a helper function for ASN1_UTCTIME_print. If |*v|,
-// assumed to be |*len| bytes long, has two leading digits, updates |*out| with
-// their value, updates |v| and |len|, and returns one. Otherwise, returns
-// zero.
-static int consume_two_digits(int* out, const char **v, int *len) {
- if (*len < 2|| !isdigit((*v)[0]) || !isdigit((*v)[1])) {
- return 0;
- }
- *out = ((*v)[0] - '0') * 10 + ((*v)[1] - '0');
- *len -= 2;
- *v += 2;
- return 1;
-}
-
-// consume_zulu_timezone is a helper function for ASN1_UTCTIME_print. If |*v|,
-// assumed to be |*len| bytes long, starts with "Z" then it updates |*v| and
-// |*len| and returns one. Otherwise returns zero.
-static int consume_zulu_timezone(const char **v, int *len) {
- if (*len == 0 || (*v)[0] != 'Z') {
- return 0;
- }
-
- *len -= 1;
- *v += 1;
- return 1;
-}
-
-int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) {
- const char *v = (const char *)tm->data;
- int len = tm->length;
- int Y = 0, M = 0, D = 0, h = 0, m = 0, s = 0;
-
- // YYMMDDhhmm are required to be present.
- if (!consume_two_digits(&Y, &v, &len) ||
- !consume_two_digits(&M, &v, &len) ||
- !consume_two_digits(&D, &v, &len) ||
- !consume_two_digits(&h, &v, &len) ||
- !consume_two_digits(&m, &v, &len)) {
- goto err;
- }
- // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires seconds
- // to be present, but historically this code has forgiven its absence.
- consume_two_digits(&s, &v, &len);
-
- // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, specifies this
- // interpretation of the year.
- if (Y < 50) {
- Y += 2000;
- } else {
- Y += 1900;
- }
- if (M > 12 || M == 0) {
- goto err;
- }
- if (D > 31 || D == 0) {
- goto err;
- }
- if (h > 23 || m > 59 || s > 60) {
- goto err;
- }
-
- // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires the "Z"
- // to be present, but historically this code has forgiven its absence.
- const int is_gmt = consume_zulu_timezone(&v, &len);
-
- // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, does not permit
- // the specification of timezones using the +hhmm / -hhmm syntax, which is
- // the only other thing that might legitimately be found at the end.
- if (len) {
- goto err;
- }
-
- return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", mon[M - 1], D, h, m, s, Y,
- is_gmt ? " GMT" : "") > 0;
-
-err:
- BIO_write(bp, "Bad time value", 14);
- return 0;
-}
-
int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
{
char *s, *c, *b;