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>
grpc-202302
David Benjamin 3 years ago
parent 0dcbc6e14a
commit 07a6628e4b
  1. 177
      crypto/asn1/a_strex.c
  2. 177
      crypto/x509/t_x509.c

@ -56,6 +56,7 @@
#include <openssl/asn1.h>
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
@ -445,3 +446,179 @@ int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
*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;
}

@ -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 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
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;

Loading…
Cancel
Save