Add checking to ASN.1 IA5, UTF8, Printable strings

This commit is contained in:
Zhi Guan
2023-01-13 17:20:09 +08:00
parent fd88d8cad6
commit e54b4ae182
5 changed files with 135 additions and 15 deletions

View File

@@ -169,7 +169,6 @@ 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_utf8_string_check(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)
@@ -177,7 +176,6 @@ 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_printable_string_check(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);
@@ -186,7 +184,6 @@ 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_ia5_string_check(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)
@@ -194,6 +191,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)

View File

@@ -113,12 +113,73 @@ int asn1_tag_is_cstring(int tag)
return 0;
}
int asn1_utf8_string_check(const char *a, size_t alen)
/*
utf-8 character encoding
1-byte: 0xxxxxxx
2-byte: 110xxxxx 10xxxxxx
3-byte: 1110xxxx 10xxxxxx 10xxxxxx
4-byte: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
int asn1_utf8char_from_bytes(uint32_t *c, const uint8_t **pin, size_t *pinlen)
{
uint32_t utf8char;
const uint8_t *in = *pin;
size_t inlen = *pinlen;
uint32_t utf8char_len, i;
if (!inlen) {
return 0;
}
if ((in[0] & 0x80) == 0x00) {
utf8char_len = 1;
} else if ((in[0] & 0xe0) == 0xc0) {
utf8char_len = 2;
} else if ((in[0] & 0xf0) == 0xe0) {
utf8char_len = 3;
} else if ((in[0] & 0xf8) == 0xf0) {
utf8char_len = 4;
} else {
//error_print();
return -1;
}
if (inlen < utf8char_len) {
//error_print();
return -1;
}
utf8char = in[0];
for (i = 1; i < utf8char_len; i++) {
if ((in[i] & 0x60) != 0x80) {
//error_print();
return -1;
}
utf8char = (utf8char << 8) | in[i];
}
*c = utf8char;
(*pin) += utf8char_len;
(*pinlen) -= utf8char_len;
return 1;
}
static int asn1_char_is_printable(int a)
int asn1_string_is_utf8_string(const char *a, size_t alen)
{
uint32_t utf8char;
if (!a || !alen) {
return 0;
}
while (alen) {
if (asn1_utf8char_from_bytes(&utf8char, (const uint8_t **)&a, &alen) != 1) {
return 0;
}
}
return 1;
}
int asn1_char_is_printable(int a)
{
if (isalpha(a) || isdigit(a)) {
return 1;
@@ -132,6 +193,7 @@ static int asn1_char_is_printable(int a)
return 0;
}
/*
int asn1_printable_string_check(const char *a, size_t alen)
{
size_t i;
@@ -143,6 +205,18 @@ int asn1_printable_string_check(const char *a, size_t alen)
}
return 1;
}
*/
int asn1_string_is_printable_string(const char *a, size_t alen)
{
size_t i;
for (i = 0; i < alen; i++) {
if (asn1_char_is_printable(a[i]) != 1) {
return 0;
}
}
return 1;
}
int asn1_printable_string_case_ignore_match(const char *a, size_t alen,
const char *b, size_t blen)
@@ -177,8 +251,14 @@ int asn1_printable_string_case_ignore_match(const char *a, size_t alen,
return 1;
}
int asn1_ia5_string_check(const char *a, size_t alen)
int asn1_string_is_ia5_string(const char *a, size_t alen)
{
size_t i;
for (i = 0; i < alen; i++) {
if (!isascii(a[i])) {
return 0;
}
}
return 1;
}
@@ -1314,17 +1394,56 @@ int asn1_string_from_der(int tag, const char **a, size_t *alen, const uint8_t **
int asn1_utf8_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen)
{
return asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen);
int ret;
if ((ret = asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (!(*a) || !(*alen)) {
error_print();
return -1;
}
if (asn1_string_is_utf8_string(*a, *alen) != 1) {
error_print();
return -1;
}
return 1;
}
int asn1_printable_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen)
{
return asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen);
int ret;
if ((ret = asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (!(*a) || !(*alen)) {
error_print();
return -1;
}
if (asn1_string_is_printable_string(*a, *alen) != 1) {
error_print();
return -1;
}
return 1;
}
int asn1_ia5_string_from_der_ex(int tag, const char **a, size_t *alen, const uint8_t **in, size_t *inlen)
{
return asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen);
int ret;
if ((ret = asn1_type_from_der(tag, (const uint8_t **)a, alen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (!(*a) || !(*alen)) {
error_print();
return -1;
}
if (asn1_string_is_ia5_string(*a, *alen) != 1) {
error_print();
return -1;
}
return 1;
}
int asn1_utc_time_from_der_ex(int tag, time_t *t, const uint8_t **pin, size_t *pinlen)

View File

@@ -528,7 +528,7 @@ static size_t _strlen(const char *s) { return s ? strlen(s) : 0; }
static int x509_name_tag(const char *str)
{
if (str) {
if (asn1_printable_string_check(str, strlen(str)) == 1)
if (asn1_string_is_printable_string(str, strlen(str)) == 1)
return ASN1_TAG_PrintableString;
else return ASN1_TAG_UTF8String;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
@@ -527,7 +527,7 @@ int x509_general_names_add_general_name(uint8_t *gns, size_t *gnslen, size_t max
case X509_gn_rfc822_name:
case X509_gn_dns_name:
case X509_gn_uniform_resource_identifier:
if (asn1_ia5_string_check((char *)d, dlen) != 1) {
if (asn1_string_is_ia5_string((char *)d, dlen) != 1) {
error_print();
return -1;
}

View File

@@ -370,7 +370,7 @@ static int test_asn1_printable_string(void)
char *tests[] = {
"hello",
"world",
"Just do it!",
"Just do it", // string "Just do it!" include invalid '!'
};
uint8_t buf[256];
uint8_t *p = buf;
@@ -408,12 +408,12 @@ static int test_asn1_printable_string(void)
static int test_asn1_printable_string_check(void)
{
char *printable_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
if (asn1_printable_string_check(printable_str, strlen(printable_str)) != 1) {
if (asn1_string_is_printable_string(printable_str, strlen(printable_str)) != 1) {
error_print();
return -1;
}
if (asn1_printable_string_check("a*b", 3) == 1) {
if (asn1_string_is_printable_string("a*b", 3) == 1) {
error_print();
return -1;
}