print ASN.1 time and ASCII tranlation

This commit is contained in:
Frank Morgner 2017-11-13 15:12:43 +01:00
parent 8de544653c
commit baa709ff74
1 changed files with 156 additions and 70 deletions

View File

@ -22,11 +22,12 @@
#include "config.h" #include "config.h"
#endif #endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h> #include <assert.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "internal.h" #include "internal.h"
#include "asn1.h" #include "asn1.h"
@ -144,40 +145,79 @@ void sc_copy_asn1_entry(const struct sc_asn1_entry *src,
dest->name = NULL; dest->name = NULL;
} }
static void sc_asn1_print_octet_string(const u8 * buf, size_t buflen) static void print_indent(size_t depth)
{ {
size_t i; for (; depth > 0; depth--) {
putchar(' ');
}
}
for (i = 0; i < buflen; i++) static void print_hex(const u8 * buf, size_t buflen, size_t depth)
printf("%02X", buf[i]); {
size_t lines_len = buflen * 5 + 128;
char *lines = malloc(lines_len);
char *line = lines;
if (buf == NULL || buflen == 0 || lines == NULL)
return;
sc_hex_dump(buf, buflen, lines, lines_len);
while (*line != '\0') {
char *line_end = strchr(line, '\n');
ptrdiff_t width = line_end - line;
if (!line_end || width <= 1) {
/* don't print empty lines */
break;
}
if (buflen > 8) {
putchar('\n');
print_indent(depth);
} else {
printf(": ");
}
printf("%.*s", (int) width, line);
line = line_end + 1;
}
free(lines);
}
static void print_ascii(const u8 * buf, size_t buflen)
{
for (; 0 < buflen; buflen--, buf++) {
if (isprint(*buf))
printf("%c", *buf);
else
putchar('.');
}
}
static void sc_asn1_print_octet_string(const u8 * buf, size_t buflen, size_t depth)
{
print_hex(buf, buflen, depth);
} }
static void sc_asn1_print_utf8string(const u8 * buf, size_t buflen) static void sc_asn1_print_utf8string(const u8 * buf, size_t buflen)
{ {
size_t i; /* FIXME UTF-8 is not ASCII */
print_ascii(buf, buflen);
for (i = 0; i < buflen; i++)
printf("%c", buf[i]);
} }
static void sc_asn1_print_integer(const u8 * buf, size_t buflen) static void sc_asn1_print_integer(const u8 * buf, size_t buflen)
{ {
#ifndef _WIN32 size_t a = 0;
long long a = 0;
#else
__int64 a = 0;
#endif
size_t i;
if (buflen > sizeof(a)) { if (buflen > sizeof(a)) {
printf("too long"); printf("0x%s", sc_dump_hex(buf, buflen));
return; } else {
size_t i;
for (i = 0; i < buflen; i++) {
a <<= 8;
a |= buf[i];
}
printf("%"SC_FORMAT_LEN_SIZE_T"u", a);
} }
for (i = 0; i < buflen; i++) {
a <<= 8;
a |= buf[i];
}
printf("%lld", a);
} }
static void sc_asn1_print_boolean(const u8 * buf, size_t buflen) static void sc_asn1_print_boolean(const u8 * buf, size_t buflen)
@ -191,7 +231,7 @@ static void sc_asn1_print_boolean(const u8 * buf, size_t buflen)
printf("false"); printf("false");
} }
static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen) static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen, size_t depth)
{ {
#ifndef _WIN32 #ifndef _WIN32
long long a = 0; long long a = 0;
@ -201,16 +241,16 @@ static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen)
int r, i; int r, i;
if (buflen > sizeof(a) + 1) { if (buflen > sizeof(a) + 1) {
printf("too long"); print_hex(buf, buflen, depth);
return; } else {
} r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a));
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a)); if (r < 0) {
if (r < 0) { printf("decode error");
printf("decode error"); return;
return; }
} for (i = r - 1; i >= 0; i--) {
for (i = r - 1; i >= 0; i--) { printf("%c", ((a >> i) & 1) ? '1' : '0');
printf("%c", ((a >> i) & 1) ? '1' : '0'); }
} }
} }
@ -223,7 +263,7 @@ static void openssl_print_object_sn(const char *s)
if (obj) { if (obj) {
int nid = OBJ_obj2nid(obj); int nid = OBJ_obj2nid(obj);
if (nid != NID_undef) { if (nid != NID_undef) {
printf("%s ", OBJ_nid2sn(nid)); printf(", %s", OBJ_nid2sn(nid));
} }
ASN1_OBJECT_free(obj); ASN1_OBJECT_free(obj);
} }
@ -237,33 +277,71 @@ static void openssl_print_object_sn(const char *s)
static void sc_asn1_print_object_id(const u8 * buf, size_t buflen) static void sc_asn1_print_object_id(const u8 * buf, size_t buflen)
{ {
struct sc_object_id oid; struct sc_object_id oid;
int i = 0; const char *sbuf;
char tmp[12];
char sbuf[(sizeof tmp)*SC_MAX_OBJECT_ID_OCTETS];
if (sc_asn1_decode_object_id(buf, buflen, &oid)) { if (sc_asn1_decode_object_id(buf, buflen, &oid)) {
printf("decode error"); printf("decode error");
return; return;
} }
sbuf[0] = 0; sbuf = sc_dump_oid(&oid);
for (i = 0; (i < SC_MAX_OBJECT_ID_OCTETS) && (oid.value[i] != -1); i++) { printf(" %s", sbuf);
openssl_print_object_sn(sbuf);
}
if (i) static void sc_asn1_print_utctime(const u8 * buf, size_t buflen)
strcat(sbuf, "."); {
sprintf(tmp, "%d", oid.value[i]); if (buflen < 8) {
strcat(sbuf, tmp); printf("Error in decoding.\n");
return;
} }
openssl_print_object_sn(sbuf); print_ascii(buf, 2); /* YY */
printf("%s", sbuf); putchar('-');
print_ascii(buf+2, 2); /* MM */
putchar('-');
print_ascii(buf+4, 2); /* DD */
putchar(' ');
print_ascii(buf+6, 2); /* hh */
buf += 8;
buflen -= 8;
if (buflen >= 2 && isdigit(buf[0]) && isdigit(buf[1])) {
putchar(':');
print_ascii(buf, 2); /* mm */
buf += 2;
buflen -= 2;
}
if (buflen >= 2 && isdigit(buf[0]) && isdigit(buf[1])) {
putchar(':');
print_ascii(buf, 2); /* ss */
buf += 2;
buflen -= 2;
}
if (buflen >= 4 && '.' == buf[0]) {
print_ascii(buf, 4); /* fff */
buf += 4;
buflen -= 4;
}
if (buflen >= 1 && 'Z' == buf[0]) {
printf(" UTC");
} else if (buflen >= 5 && ('-' == buf[0] || '+' == buf[0])) {
putchar(' ');
print_ascii(buf, 3); /* +/-hh */
putchar(':');
print_ascii(buf+3, 2); /* mm */
}
} }
static void sc_asn1_print_generalizedtime(const u8 * buf, size_t buflen) static void sc_asn1_print_generalizedtime(const u8 * buf, size_t buflen)
{ {
size_t ii; if (buflen < 8) {
for (ii=0; ii<buflen; ii++) printf("Error in decoding.\n");
printf("%c", *(buf + ii)); return;
}
print_ascii(buf, 2);
sc_asn1_print_utctime(buf + 2, buflen - 2);
} }
static void print_tags_recursive(const u8 * buf0, const u8 * buf, static void print_tags_recursive(const u8 * buf0, const u8 * buf,
@ -295,9 +373,7 @@ static void print_tags_recursive(const u8 * buf0, const u8 * buf,
printf("Zero tag, finishing\n"); printf("Zero tag, finishing\n");
break; break;
} }
for (i = 0; i < depth; i++) { print_indent(depth);
putchar(' ');
}
/* let i be the length of the tag in bytes */ /* let i be the length of the tag in bytes */
for (i = 1; i < sizeof tag - 1; i++) { for (i = 1; i < sizeof tag - 1; i++) {
if (!(tag >> 8*i)) if (!(tag >> 8*i))
@ -312,9 +388,12 @@ static void print_tags_recursive(const u8 * buf0, const u8 * buf,
classes[cla >> 6], classes[cla >> 6],
i == 1 ? tag & SC_ASN1_TAG_PRIMITIVE : tag & (((unsigned int) ~0) >> (i + 1) * 8)); i == 1 ? tag & SC_ASN1_TAG_PRIMITIVE : tag & (((unsigned int) ~0) >> (i + 1) * 8));
} }
printf(" (%"SC_FORMAT_LEN_SIZE_T"u byte%s)", if (!((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_UNIVERSAL
len, && tag == SC_ASN1_TAG_NULL && len == 0)) {
len != 1 ? "s" : ""); printf(" (%"SC_FORMAT_LEN_SIZE_T"u byte%s)",
len,
len != 1 ? "s" : "");
}
if (len + hlen > bytesleft) { if (len + hlen > bytesleft) {
printf(" Illegal length!\n"); printf(" Illegal length!\n");
@ -329,47 +408,54 @@ static void print_tags_recursive(const u8 * buf0, const u8 * buf,
continue; continue;
} }
if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_UNIVERSAL switch (tag) {
&& tag != SC_ASN1_TAG_NULL) {
printf(" [");
switch (tag) {
case SC_ASN1_TAG_BIT_STRING: case SC_ASN1_TAG_BIT_STRING:
sc_asn1_print_bit_string(tagp, len); printf(": ");
sc_asn1_print_bit_string(tagp, len, depth + 2*i + 1);
break; break;
case SC_ASN1_TAG_OCTET_STRING: case SC_ASN1_TAG_OCTET_STRING:
sc_asn1_print_octet_string(tagp, len); sc_asn1_print_octet_string(tagp, len, depth + 2*i + 1);
break; break;
case SC_ASN1_TAG_OBJECT: case SC_ASN1_TAG_OBJECT:
printf(": ");
sc_asn1_print_object_id(tagp, len); sc_asn1_print_object_id(tagp, len);
break; break;
case SC_ASN1_TAG_INTEGER: case SC_ASN1_TAG_INTEGER:
case SC_ASN1_TAG_ENUMERATED: case SC_ASN1_TAG_ENUMERATED:
printf(": ");
sc_asn1_print_integer(tagp, len); sc_asn1_print_integer(tagp, len);
break; break;
case SC_ASN1_TAG_T61STRING: case SC_ASN1_TAG_IA5STRING:
case SC_ASN1_TAG_PRINTABLESTRING: case SC_ASN1_TAG_PRINTABLESTRING:
case SC_ASN1_TAG_T61STRING:
case SC_ASN1_TAG_UTF8STRING: case SC_ASN1_TAG_UTF8STRING:
printf(": ");
sc_asn1_print_utf8string(tagp, len); sc_asn1_print_utf8string(tagp, len);
break; break;
case SC_ASN1_TAG_BOOLEAN: case SC_ASN1_TAG_BOOLEAN:
printf(": ");
sc_asn1_print_boolean(tagp, len); sc_asn1_print_boolean(tagp, len);
break; break;
case SC_ASN1_GENERALIZEDTIME: case SC_ASN1_GENERALIZEDTIME:
printf(": ");
sc_asn1_print_generalizedtime(tagp, len); sc_asn1_print_generalizedtime(tagp, len);
break; break;
} case SC_ASN1_UTCTIME:
printf("]"); printf(": ");
sc_asn1_print_utctime(tagp, len);
break;
} }
if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_APPLICATION) if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_APPLICATION) {
printf(" [%s]", sc_dump_hex(tagp, len)); print_hex(tagp, len, depth + 2*i + 1);
}
if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_CONTEXT) if ((cla & SC_ASN1_TAG_CLASS) == SC_ASN1_TAG_CONTEXT) {
printf(" [%s]", sc_dump_hex(tagp, len)); print_hex(tagp, len, depth + 2*i + 1);
}
putchar('\n'); putchar('\n');
} }
return;
} }
void sc_asn1_print_tags(const u8 * buf, size_t buflen) void sc_asn1_print_tags(const u8 * buf, size_t buflen)