Refine ASN.1 functions

This commit is contained in:
Zhi Guan
2023-01-15 11:59:53 +08:00
parent b858b01d39
commit 4b75346983
3 changed files with 194 additions and 132 deletions

View File

@@ -106,9 +106,10 @@ DER encoding (d, dlen) to_der
*/
const char *asn1_tag_name(int tag);
int asn1_tag_is_cstring(int tag);
int asn1_tag_to_der(int tag, uint8_t **out, size_t *outlen);
int asn1_tag_from_der(int *tag, const uint8_t **in, size_t *inlen);
int asn1_tag_from_der_readonly(int *tag, const uint8_t **in, size_t *inlen); // read the next tag without changing *in,*inlen
int asn1_tag_is_cstring(int tag);
int asn1_length_to_der(size_t dlen, uint8_t **out, size_t *outlen);
int asn1_length_from_der(size_t *dlen, const uint8_t **in, size_t *inlen);
int asn1_length_is_zero(size_t len);
@@ -118,6 +119,8 @@ int asn1_data_from_der(const uint8_t **d, size_t dlen, const uint8_t **in, size_
int asn1_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int asn1_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int asn1_nonempty_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int asn1_nonempty_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int asn1_any_type_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int asn1_any_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen); // 调用方应保证a,alen为TLV
int asn1_any_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); // 该函数会检查输入是否为TLV
@@ -187,20 +190,40 @@ const char *asn1_null_name(void);
int asn1_null_to_der(uint8_t **out, size_t *outlen);
int asn1_null_from_der(const uint8_t **in, size_t *inlen);
#define ASN1_OID_MIN_NODES 2
#define ASN1_OID_MAX_NODES 32
#define ASN1_OID_MIN_OCTETS 1
#define ASN1_OID_MAX_OCTETS (1 + (ASN1_OID_MAX_NODES - 2) * 5)
int asn1_object_identifier_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen);
int asn1_object_identifier_from_octets(uint32_t *nodes, size_t *nodes_cnt, const uint8_t *in, size_t inlen);
int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt);
int asn1_object_identifier_to_der_ex(int tag, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen);
int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen);
#define asn1_object_identifier_to_der(nodes,nodes_cnt,out,outlen) asn1_object_identifier_to_der_ex(ASN1_TAG_OBJECT_IDENTIFIER,nodes,nodes_cnt,out,outlen)
#define asn1_object_identifier_from_der(nodes,nodes_cnt,in,inlen) asn1_object_identifier_from_der_ex(ASN1_TAG_OBJECT_IDENTIFIER,nodes,nodes_cnt,in,inlen)
#define asn1_implicit_object_identifier_to_der(i,nodes,nodes_cnt,out,outlen) asn1_object_identifier_to_der_ex(ASN1_TAG_IMPLICIT(i),nodes,nodes_cnt,out,outlen)
#define asn1_implicit_object_identifier_from_der(i,nodes,nodes_cnt,in,inlen) asn1_object_identifier_from_der_ex(ASN1_TAG_IMPLICIT(i),nodes,nodes_cnt,in,inlen)
int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt);
int asn1_object_identifier_print(FILE *fp, int fmt, int ind, const char *label, const char *name,
const uint32_t *nodes, size_t nodes_cnt);
typedef struct {
int oid;
char *name;
uint32_t *nodes;
size_t nodes_cnt;
int flags;
char *description;
} ASN1_OID_INFO;
const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t count, const char *name);
const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t count, int oid);
// 如果一个正确解析的OID并不在infos列表中那么仍然返回1但是调用方必须检查返回的info是否为空
int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt,
const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen);
int asn1_oid_info_from_der(const ASN1_OID_INFO **info,
const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen);
#define asn1_enumerated_to_der_ex(tag,val,out,outlen) asn1_int_to_der_ex(tag,val,out,outlen)
#define asn1_enumerated_from_der_ex(tag,val,in,inlen) asn1_int_from_der_ex(tag,val,in,inlen)
#define asn1_enumerated_to_der(val,out,outlen) asn1_int_to_der_ex(ASN1_TAG_ENUMERATED,val,out,outlen)
@@ -208,6 +231,7 @@ int asn1_object_identifier_print(FILE *fp, int fmt, int ind, const char *label,
#define asn1_implicit_enumerated_to_der(i,val,out,outlen) asn1_int_to_der_ex(ASN1_TAG_IMPLICIT(i),val,out,outlen)
#define asn1_implicit_enumerated_from_der(i,val,in,inlen) asn1_int_from_der_ex(ASN1_TAG_IMPLICIT(i),val,in,inlen)
int asn1_string_is_utf8_string(const char *d, size_t dlen);
int asn1_utf8_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen);
int asn1_utf8_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen);
#define asn1_utf8_string_to_der(d,dlen,out,outlen) asn1_utf8_string_to_der_ex(ASN1_TAG_UTF8String,d,dlen,out,outlen)
@@ -215,6 +239,7 @@ int asn1_utf8_string_from_der_ex(int tag, const char **d, size_t *dlen, const ui
#define asn1_implicit_utf8_string_to_der(i,d,dlen,out,outlen) asn1_utf8_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen)
#define asn1_implicit_utf8_string_from_der(i,d,dlen,in,inlen) asn1_utf8_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen)
int asn1_string_is_printable_string(const char *d, size_t dlen);
int asn1_printable_string_case_ignore_match(const char *a, size_t alen, const char *b, size_t blen);
int asn1_printable_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen);
int asn1_printable_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen);
@@ -223,6 +248,7 @@ int asn1_printable_string_from_der_ex(int tag, const char **d, size_t *dlen, con
#define asn1_implicit_printable_string_to_der(i,d,dlen,out,outlen) asn1_printable_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen)
#define asn1_implicit_printable_string_from_der(i,d,dlen,in,inlen) asn1_printable_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen)
int asn1_string_is_ia5_string(const char *d, size_t dlen);
int asn1_ia5_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen);
int asn1_ia5_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen);
#define asn1_ia5_string_to_der(d,dlen,out,outlen) asn1_ia5_string_to_der_ex(ASN1_TAG_IA5String,d,dlen,out,outlen)
@@ -230,14 +256,10 @@ int asn1_ia5_string_from_der_ex(int tag, const char **d, size_t *dlen, const uin
#define asn1_implicit_ia5_string_to_der(i,d,dlen,out,outlen) asn1_ia5_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen)
#define asn1_implicit_ia5_string_from_der(i,d,dlen,in,inlen) asn1_ia5_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen)
int asn1_string_is_printable_string(const char *d, size_t dlen);
int asn1_string_is_ia5_string(const char *d, size_t dlen);
int asn1_string_is_utf8_string(const char *d, size_t dlen);
int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen);
#define ASN1_UTC_TIME_LEN (sizeof("YYMMDDHHMMSSZ")-1)
#define ASN1_GENERALIZED_TIME_LEN (sizeof("YYYYMMDDHHMMSSZ")-1)
#define ASN1_UTC_TIME_STRLEN (sizeof("YYMMDDHHMMSSZ")-1)
#define ASN1_GENERALIZED_TIME_STRLEN (sizeof("YYYYMMDDHHMMSSZ")-1)
int asn1_time_to_str(int utc_time, time_t timestamp, char *str);
int asn1_time_from_str(int utc_time, time_t *timestamp, const char *str);
@@ -256,9 +278,6 @@ int asn1_generalized_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, s
#define asn1_implicit_generalized_time_to_der(i,tv,out,outlen) asn1_generalized_time_to_der_ex(ASN1_TAG_IMPLICIT(i),tv,out,outlen)
#define asn1_implicit_generalized_time_from_der(i,tv,in,inlen) asn1_generalized_time_from_der_ex(ASN1_TAG_IMPLICIT(i),tv,in,inlen)
int asn1_nonempty_type_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int asn1_nonempty_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
#define asn1_sequence_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SEQUENCE,d,dlen,out,outlen)
#define asn1_sequence_from_der(d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_SEQUENCE,d,dlen,in,inlen)
#define asn1_implicit_sequence_to_der(i,d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_EXPLICIT(i),d,dlen,out,outlen)
@@ -267,7 +286,7 @@ int asn1_nonempty_type_from_der(int tag, const uint8_t **d, size_t *dlen, const
#define asn1_sequence_of_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SEQUENCE,d,dlen,out,outlen)
#define asn1_sequence_of_from_der(d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_SEQUENCE,d,dlen,in,inlen)
int asn1_sequence_of_int_to_der(const int *nums, size_t nums_cnt, uint8_t **out, size_t *outlen);
int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, const uint8_t **in, size_t *inlen);
int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, size_t max_nums, const uint8_t **in, size_t *inlen);
int asn1_sequence_of_int_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
#define asn1_set_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SET,d,dlen,out,outlen)
@@ -299,26 +318,11 @@ int asn1_header_to_der(int tag, size_t dlen, uint8_t **out, size_t *outlen);
// d,dlen 是 SEQUENCE OF, SET OF 中的值
int asn1_types_get_count(const uint8_t *d, size_t dlen, int tag, size_t *cnt);
int asn1_types_get_item_by_index(const uint8_t *d, size_t *dlen, int tag,
int asn1_types_get_item_by_index(const uint8_t *d, size_t dlen, int tag,
int index, const uint8_t **item_d, size_t *item_dlen);
typedef struct {
int oid;
char *name;
uint32_t *nodes;
size_t nodes_cnt;
int flags;
char *description;
} ASN1_OID_INFO;
const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t count, const char *name);
const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t count, int oid);
int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt,
const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen);
int asn1_oid_info_from_der(const ASN1_OID_INFO **info,
const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen);
int asn1_check(int expr);

View File

@@ -960,17 +960,13 @@ static void asn1_oid_node_to_base128(uint32_t a, uint8_t **out, size_t *outlen)
}
while (n--) {
if (out && *out)
if (out && *out) {
*(*out)++ = buf[n];
}
(*outlen)++;
}
}
// 实际上我们在解析的时候是不知道具体在哪里结束的
// 解析是有可能出错的如果没有发现最后一个0开头的字节就出错了
// 还有值太大也会出错我们最多读取5个字节
// { 0x81, 0x82 }
// { 0x81, 0x82, 0x83, 0x84, 0x85, 0x06 }
static int asn1_oid_node_from_base128(uint32_t *a, const uint8_t **in, size_t *inlen)
{
uint8_t buf[5];
@@ -1002,27 +998,19 @@ static int asn1_oid_node_from_base128(uint32_t *a, const uint8_t **in, size_t *i
return 1;
}
// change name
int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt)
{
if (a_cnt == b_cnt
&& memcmp(a, b, b_cnt * sizeof(uint32_t)) == 0) {
return 1;
}
return 0;
}
int asn1_object_identifier_to_octets(const uint32_t *nodes, size_t nodes_cnt, uint8_t *out, size_t *outlen)
{
if (!outlen) {
if (!nodes || !outlen) {
error_print();
return -1;
}
if (nodes_cnt < 2 || nodes_cnt > 32) {
if (nodes_cnt < ASN1_OID_MIN_NODES || nodes_cnt > ASN1_OID_MAX_NODES) {
error_print();
return -1;
}
if (out)
if (out) {
*out++ = (uint8_t)(nodes[0] * 40 + nodes[1]);
}
(*outlen) = 1;
nodes += 2;
nodes_cnt -= 2;
@@ -1033,35 +1021,24 @@ int asn1_object_identifier_to_octets(const uint32_t *nodes, size_t nodes_cnt, ui
return 1;
}
// 因为这个函数总是被asn1函数调用的因此给的输入数据长度是已知的
int asn1_object_identifier_from_octets(uint32_t *nodes, size_t *nodes_cnt, const uint8_t *in, size_t inlen)
{
size_t count = 0;
const uint8_t *p = in;
size_t len = inlen;
if (!nodes || !nodes_cnt || !in || inlen <= 0) {
if (!nodes_cnt || !in || !inlen) {
error_print();
return -1;
}
if (inlen < 1) {
error_print();
return -1;
}
// FIXME: 需要支持 nodes = NULL 吗?
if (nodes) {
*nodes++ = (*in) / 40;
*nodes++ = (*in) % 40;
}
in++;
inlen--;
count += 2;
*nodes_cnt = 2;
while (inlen) {
uint32_t val;
if (count > 32) {
if (*nodes_cnt > ASN1_OID_MAX_NODES) {
error_print();
return -1;
}
@@ -1072,33 +1049,42 @@ int asn1_object_identifier_from_octets(uint32_t *nodes, size_t *nodes_cnt, const
if (nodes) {
*nodes++ = val;
}
count++;
(*nodes_cnt)++;
}
*nodes_cnt = count;
return 1;
}
int asn1_object_identifier_to_der_ex(int tag, const uint32_t *nodes, size_t nodes_cnt, uint8_t **out, size_t *outlen)
{
uint8_t octets[32];
uint8_t octets[ASN1_OID_MAX_OCTETS];
size_t octetslen = 0;
if (!outlen) {
error_print();
return -1;
}
if (!nodes) {
if (nodes_cnt) {
error_print();
return -1;
}
return 0;
}
if (out && *out)
*(*out)++ = tag;
(*outlen)++;
asn1_object_identifier_to_octets(nodes, nodes_cnt, octets, &octetslen);
asn1_length_to_der(octetslen, out, outlen);
if (asn1_object_identifier_to_octets(nodes, nodes_cnt, octets, &octetslen) != 1) {
error_print();
return -1;
}
if (out && *out) {
*(*out)++ = tag;
}
(*outlen)++;
(void)asn1_length_to_der(octetslen, out, outlen);
if (out && *out) {
// 注意If out == NULL, *out ==> Segment Fault
memcpy(*out, octets, octetslen);
*out += octetslen;
}
@@ -1113,7 +1099,8 @@ int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_c
size_t len;
const uint8_t *p;
if (!in || !(*in) || !inlen) {
// unlike _from_octets(), _from_der() require output buffer
if (!nodes || !nodes_cnt || !in || !(*in) || !inlen) {
error_print();
return -1;
}
@@ -1131,7 +1118,7 @@ int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_c
error_print();
return -1;
}
if (len == 0) {
if (len < ASN1_OID_MIN_OCTETS) {
error_print();
return -1;
}
@@ -1147,6 +1134,19 @@ int asn1_object_identifier_from_der_ex(int tag, uint32_t *nodes, size_t *nodes_c
return 1;
}
int asn1_object_identifier_equ(const uint32_t *a, size_t a_cnt, const uint32_t *b, size_t b_cnt)
{
if (!a || a_cnt < ASN1_OID_MIN_NODES || a_cnt > ASN1_OID_MAX_NODES
|| !b || b_cnt < ASN1_OID_MIN_NODES || b_cnt > ASN1_OID_MAX_NODES) {
error_print();
return 0; // _equ() should return 1 or 0
}
if (a_cnt != b_cnt || memcmp(a, b, b_cnt * sizeof(uint32_t))) {
return 0;
}
return 1;
}
int asn1_object_identifier_print(FILE *fp, int format, int indent, const char *label, const char *name,
const uint32_t *nodes, size_t nodes_cnt)
{
@@ -1163,10 +1163,15 @@ int asn1_object_identifier_print(FILE *fp, int format, int indent, const char *l
return 1;
}
const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t count, const char *name)
const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t infos_cnt, const char *name)
{
size_t i;
for (i = 0; i < count; i++) {
if (!infos || !infos_cnt || !name) {
error_print();
return NULL;
}
for (i = 0; i < infos_cnt; i++) {
if (strcmp(infos[i].name, name) == 0) {
return &infos[i];
}
@@ -1174,10 +1179,15 @@ const ASN1_OID_INFO *asn1_oid_info_from_name(const ASN1_OID_INFO *infos, size_t
return NULL;
}
const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t count, int oid)
const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t infos_cnt, int oid)
{
size_t i;
for (i = 0; i < count; i++) {
if (!infos || !infos_cnt || oid <= 0) {
error_print();
return NULL;
}
for (i = 0; i < infos_cnt; i++) {
if (infos[i].oid == oid) {
return &infos[i];
}
@@ -1185,34 +1195,39 @@ const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t c
return NULL;
}
// 如果一个正确解析的OID并不在infos列表中那么仍然返回1但是调用方必须检查返回的info是否为空
int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt,
const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen)
const ASN1_OID_INFO *infos, size_t infos_cnt, const uint8_t **in, size_t *inlen)
{
int ret;
size_t i;
if (!info) {
error_print();
return -1;
}
if ((ret = asn1_object_identifier_from_der(nodes, nodes_cnt, in, inlen)) != 1) {
if (ret < 0) error_print();
else *info = NULL;
return ret;
}
*info = NULL;
for (i = 0; i < count; i++) {
for (i = 0; i < infos_cnt; i++) {
if (*nodes_cnt == infos[i].nodes_cnt
&& memcmp(nodes, infos[i].nodes, (*nodes_cnt) * sizeof(int)) == 0) {
*info = &infos[i];
goto end;
return 1;
}
}
end:
// OID with correct encoding but in the (infos, infos_cnt) list
*info = NULL;
return 1;
}
// 和ex版本不同的是如果在infos列表中未找到OID返回错误
int asn1_oid_info_from_der(const ASN1_OID_INFO **info, const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen)
{
int ret;
uint32_t nodes[32];
uint32_t nodes[ASN1_OID_MAX_NODES];
size_t nodes_cnt;
if ((ret = asn1_oid_info_from_der_ex(info, nodes, &nodes_cnt, infos, count, in, inlen)) != 1) {
@@ -1227,16 +1242,6 @@ int asn1_oid_info_from_der(const ASN1_OID_INFO **info, const ASN1_OID_INFO *info
return 1;
}
int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen)
{
format_print(fp, fmt, ind, "%s: ", label);
while (dlen--) {
fprintf(fp, "%c", *d++);
}
fprintf(fp, "\n");
return 1;
}
/*
utf-8 character encoding
1-byte: 0xxxxxxx
@@ -1264,19 +1269,19 @@ static int asn1_utf8char_from_bytes(uint32_t *c, const uint8_t **pin, size_t *pi
} else if ((in[0] & 0xf8) == 0xf0) {
utf8char_len = 4;
} else {
//error_print();
//error_print(); // disable error_print for _is_ compare
return -1;
}
if (inlen < utf8char_len) {
//error_print();
//error_print(); // disable error_print for _is_ compare
return -1;
}
utf8char = in[0];
for (i = 1; i < utf8char_len; i++) {
if ((in[i] & 0x60) != 0x80) {
//error_print();
//error_print(); // disable error_print for _is_ compare
return -1;
}
utf8char = (utf8char << 8) | in[i];
@@ -1427,16 +1432,6 @@ int asn1_printable_string_from_der_ex(int tag, const char **a, size_t *alen, con
return 1;
}
// asn1_oid_from_octets 不返回错误值,只返回 OID_undef
// 但是数据编码仍可能是非法的
// 如果返回 OID_undef需要通过 asn1_object_identifier_from_octets 判断格式是否正确
// 显然这个函数并不合适因为在整个gmssl中我们不提供完整的ASN.1数据库无法从一个OID中给出解析
int asn1_string_is_ia5_string(const char *a, size_t alen)
{
size_t i;
@@ -1481,8 +1476,15 @@ int asn1_ia5_string_from_der_ex(int tag, const char **a, size_t *alen, const uin
return 1;
}
int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen)
{
format_print(fp, fmt, ind, "%s: ", label);
while (dlen--) {
fprintf(fp, "%c", *d++);
}
fprintf(fp, "\n");
return 1;
}
static int is_leap_year(int year) {
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0;
@@ -1627,7 +1629,7 @@ int asn1_time_to_str(int utc_time, time_t timestamp, char *str)
int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen)
{
char buf[ASN1_UTC_TIME_LEN + 1] = {0};
char buf[ASN1_UTC_TIME_STRLEN + 1] = {0};
int utc_time = 1;
if (!outlen) {
@@ -1644,12 +1646,12 @@ int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen)
*(*out)++ = tag;
}
(*outlen)++;
asn1_length_to_der(ASN1_UTC_TIME_LEN, out, outlen);
asn1_length_to_der(ASN1_UTC_TIME_STRLEN, out, outlen);
if (out && *out) {
memcpy(*out, buf, ASN1_UTC_TIME_LEN);
(*out) += ASN1_UTC_TIME_LEN;
memcpy(*out, buf, ASN1_UTC_TIME_STRLEN);
(*out) += ASN1_UTC_TIME_STRLEN;
}
*outlen += ASN1_UTC_TIME_LEN;
*outlen += ASN1_UTC_TIME_STRLEN;
return 1;
}
@@ -1702,7 +1704,7 @@ int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **in, size_t *in
int asn1_generalized_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen)
{
char buf[ASN1_GENERALIZED_TIME_LEN + 1] = {0};
char buf[ASN1_GENERALIZED_TIME_STRLEN + 1] = {0};
int utc_time = 0;
if (!outlen) {
@@ -1718,12 +1720,12 @@ int asn1_generalized_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *ou
if (out && *out)
*(*out)++ = tag;
(*outlen)++;
asn1_length_to_der(ASN1_GENERALIZED_TIME_LEN, out, outlen);
asn1_length_to_der(ASN1_GENERALIZED_TIME_STRLEN, out, outlen);
if (out && *out) {
memcpy(*out, buf, ASN1_GENERALIZED_TIME_LEN);
(*out) += ASN1_GENERALIZED_TIME_LEN;
memcpy(*out, buf, ASN1_GENERALIZED_TIME_STRLEN);
(*out) += ASN1_GENERALIZED_TIME_STRLEN;
}
*outlen += ASN1_GENERALIZED_TIME_LEN;
*outlen += ASN1_GENERALIZED_TIME_STRLEN;
return 1;
}
@@ -1777,6 +1779,12 @@ int asn1_sequence_of_int_to_der(const int *nums, size_t nums_cnt, uint8_t **out,
{
size_t len = 0;
size_t i;
if (!nums || !nums_cnt || !outlen) {
error_print();
return -1;
}
for (i = 0; i < nums_cnt; i++) {
if (asn1_int_to_der(nums[i], NULL, &len) != 1) {
error_print();
@@ -1796,26 +1804,33 @@ int asn1_sequence_of_int_to_der(const int *nums, size_t nums_cnt, uint8_t **out,
return 1;
}
int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, const uint8_t **in, size_t *inlen)
int asn1_sequence_of_int_from_der(int *nums, size_t *nums_cnt, size_t max_nums, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *d;
size_t dlen;
if (!nums || !nums_cnt || !max_nums) {
error_print();
return -1;
}
*nums_cnt = 0;
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
*nums_cnt = 0;
while (dlen) {
int num;
if (*nums_cnt > max_nums) {
error_print();
return -1;
}
if (asn1_int_from_der(&num, &d, &dlen) != 1) {
error_print();
return -1;
}
if (nums) {
*nums++ = num;
}
*nums++ = num;
(*nums_cnt)++;
}
return 1;
@@ -1838,19 +1853,62 @@ int asn1_sequence_of_int_print(FILE *fp, int fmt, int ind, const char *label, co
int asn1_types_get_count(const uint8_t *d, size_t dlen, int tag, size_t *cnt)
{
error_print();
return -1;
int item_tag;
const uint8_t *item_d;
size_t item_dlen;
if (!d || !cnt) {
error_print();
return -1;
}
*cnt = 0;
while (dlen) {
if (asn1_any_type_from_der(&item_tag, &item_d, &item_dlen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (item_tag != tag) {
error_print();
return -1;
}
(*cnt)++;
}
return 1;
}
int asn1_types_get_item_by_index(const uint8_t *d, size_t *dlen, int tag,
int asn1_types_get_item_by_index(const uint8_t *d, size_t dlen, int tag,
int index, const uint8_t **item_d, size_t *item_dlen)
{
int a_tag;
const uint8_t *a_d;
size_t a_dlen;
int i = 0;
if (!d || !item_d || !item_dlen) {
error_print();
return -1;
}
while (dlen) {
if (asn1_any_type_from_der(&a_tag, &a_d, &a_dlen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (a_tag != tag) {
error_print();
return -1;
}
if (i++ == index) {
*item_d = d;
*item_dlen = dlen;
return 1; // do not check the following
}
}
error_print();
return -1;
}
int asn1_check(int expr)
{
if (expr)

View File

@@ -834,7 +834,7 @@ int x509_notice_reference_from_der(
return ret;
}
if (x509_display_text_from_der(org_tag, org, org_len, &d, &dlen) != 1
|| asn1_sequence_of_int_from_der(notice_numbers, notice_numbers_cnt, &d, &dlen) != 1
|| asn1_sequence_of_int_from_der(notice_numbers, notice_numbers_cnt, X509_MAX_NOTICE_NUMBERS, &d, &dlen) != 1
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;