mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Add checking to ASN.1 IA5, UTF8, Printable strings
This commit is contained in:
@@ -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)
|
||||
|
||||
131
src/asn1.c
131
src/asn1.c
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user