diff --git a/include/gmssl/asn1.h b/include/gmssl/asn1.h index 4a756307..212ec334 100644 --- a/include/gmssl/asn1.h +++ b/include/gmssl/asn1.h @@ -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. @@ -178,6 +178,7 @@ int asn1_utf8_string_from_der_ex(int tag, const char **d, size_t *dlen, const ui #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); #define asn1_printable_string_to_der(d,dlen,out,outlen) asn1_printable_string_to_der_ex(ASN1_TAG_PrintableString,d,dlen,out,outlen) diff --git a/src/asn1.c b/src/asn1.c index 19667607..735b73fe 100644 --- a/src/asn1.c +++ b/src/asn1.c @@ -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. @@ -118,8 +118,62 @@ int asn1_utf8_string_check(const char *a, size_t alen) return 1; } +static int asn1_char_is_printable(int a) +{ + if (isalpha(a) || isdigit(a)) { + return 1; + } + switch (a) { + case ' ': case '\'': case '(': case ')': + case '+': case ',': case '-': case '.': + case '/': case ':': case '=': case '?': + return 1; + } + return 0; +} + int asn1_printable_string_check(const char *a, size_t alen) { + size_t i; + for (i = 0; i < alen; i++) { + if (asn1_char_is_printable(a[i]) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int asn1_printable_string_case_ignore_match(const char *a, size_t alen, + const char *b, size_t blen) +{ + // remove leading and suffix space chars + while (alen && *a == ' ') { + a++; + alen--; + } + while (alen && a[alen - 1] == ' ') { + alen--; + } + + // remove leading and suffix space chars + while (blen && *b == ' ') { + b++; + blen--; + } + while (blen && b[blen - 1] == ' ') { + blen--; + } + + if (alen != blen) { + return 0; + } + // case insensitive compare + while (alen--) { + if (toupper(*a) != toupper(*b)) { + return 0; + } + } return 1; } diff --git a/tests/asn1test.c b/tests/asn1test.c index 6b5b829a..a55b383f 100644 --- a/tests/asn1test.c +++ b/tests/asn1test.c @@ -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. @@ -405,6 +405,58 @@ static int test_asn1_printable_string(void) return 1; } +static int test_asn1_printable_string_check(void) +{ + char *printable_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?"; + if (asn1_printable_string_check(printable_str, strlen(printable_str)) != 1) { + error_print(); + return -1; + } + + if (asn1_printable_string_check("a*b", 3) == 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_asn1_printable_string_case_ignore_match(void) +{ + if (asn1_printable_string_case_ignore_match("HELLO", 5, "WORLD", 5) == 1) { + error_print(); + return -1; + } + + if (asn1_printable_string_case_ignore_match("HELLO", 5, "HELLO", 5) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match("HELLO", 5, "hello", 5) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" HELLO", 7, "hello", 5) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" HELLO", 7, "hello ", 8) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" A2b ", 5, " a2B ", 7) != 1) { + error_print(); + return -1; + } + if (asn1_printable_string_case_ignore_match(" ", 5, " ", 7) != 1) { + error_print(); + return -1; + } + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int test_asn1_utf8_string(void) { char *tests[] = { @@ -642,6 +694,7 @@ int main(void) if (test_asn1_null() != 1) goto err; if (test_asn1_object_identifier() != 1) goto err; if (test_asn1_printable_string() != 1) goto err; + if (test_asn1_printable_string_case_ignore_match() != 1) goto err; if (test_asn1_utf8_string() != 1) goto err; if (test_asn1_ia5_string() != 1) goto err; if (test_asn1_time() != 1) goto err;