137 lines
4.8 KiB
Diff
137 lines
4.8 KiB
Diff
diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c
|
|
index b7a5284fa59fa..7be233db5e0b2 100644
|
|
--- a/crypto/asn1/a_mbstr.c
|
|
+++ b/crypto/asn1/a_mbstr.c
|
|
@@ -123,7 +123,10 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
|
|
return -1;
|
|
}
|
|
|
|
- /* Now work out output format and string type */
|
|
+ /*
|
|
+ * Now work out output format and string type.
|
|
+ * These checks should be in sync with the checks in type_str.
|
|
+ */
|
|
outform = MBSTRING_ASC;
|
|
if (mask & B_ASN1_NUMERICSTRING)
|
|
str_type = V_ASN1_NUMERICSTRING;
|
|
@@ -191,7 +194,11 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
|
|
|
|
case MBSTRING_UTF8:
|
|
outlen = 0;
|
|
- traverse_string(in, len, inform, out_utf8, &outlen);
|
|
+ ret = traverse_string(in, len, inform, out_utf8, &outlen);
|
|
+ if (ret < 0) {
|
|
+ ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING);
|
|
+ return -1;
|
|
+ }
|
|
cpyfunc = cpy_utf8;
|
|
break;
|
|
}
|
|
@@ -286,9 +293,29 @@ static int out_utf8(unsigned long value, void *arg)
|
|
|
|
static int type_str(unsigned long value, void *arg)
|
|
{
|
|
- unsigned long types = *((unsigned long *)arg);
|
|
+ unsigned long usable_types = *((unsigned long *)arg);
|
|
+ unsigned long types = usable_types;
|
|
const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
|
|
|
|
+ /*
|
|
+ * Clear out all the types which are not checked later. If any of those
|
|
+ * is present in the mask, then the UTF8 type will be added and checked
|
|
+ * below.
|
|
+ */
|
|
+ types &= B_ASN1_NUMERICSTRING | B_ASN1_PRINTABLESTRING
|
|
+ | B_ASN1_IA5STRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING
|
|
+ | B_ASN1_UNIVERSALSTRING | B_ASN1_UTF8STRING;
|
|
+
|
|
+ /*
|
|
+ * If any other types were in the input mask, they're effectively treated
|
|
+ * as UTF8
|
|
+ */
|
|
+ if (types != usable_types)
|
|
+ types |= B_ASN1_UTF8STRING;
|
|
+
|
|
+ /*
|
|
+ * These checks should be in sync with ASN1_mbstring_ncopy.
|
|
+ */
|
|
if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
|
|
|| native == ' '))
|
|
types &= ~B_ASN1_NUMERICSTRING;
|
|
@@ -356,6 +383,8 @@ static int cpy_utf8(unsigned long value, void *arg)
|
|
p = arg;
|
|
/* We already know there is enough room so pass 0xff as the length */
|
|
ret = UTF8_putc(*p, 0xff, value);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
*p += ret;
|
|
return 1;
|
|
}
|
|
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
|
|
index 17f7372026c3b..01e2269444cba 100644
|
|
--- a/crypto/asn1/a_strex.c
|
|
+++ b/crypto/asn1/a_strex.c
|
|
@@ -198,8 +198,10 @@ static int do_buf(unsigned char *buf, int buflen,
|
|
orflags = CHARTYPE_LAST_ESC_2253;
|
|
if (type & BUF_TYPE_CONVUTF8) {
|
|
unsigned char utfbuf[6];
|
|
- int utflen;
|
|
- utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
|
+ int utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
|
+
|
|
+ if (utflen < 0)
|
|
+ return -1; /* error happened with UTF8 */
|
|
for (i = 0; i < utflen; i++) {
|
|
/*
|
|
* We don't need to worry about setting orflags correctly
|
|
diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c
|
|
index 50adce6b26fd2..8b5f2909e8d96 100644
|
|
--- a/crypto/pkcs12/p12_utl.c
|
|
+++ b/crypto/pkcs12/p12_utl.c
|
|
@@ -213,6 +213,11 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen)
|
|
/* re-run the loop emitting UTF-8 string */
|
|
for (asclen = 0, i = 0; i < unilen; ) {
|
|
j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i);
|
|
+ /* when UTF8_putc fails */
|
|
+ if (j < 0) {
|
|
+ OPENSSL_free(asctmp);
|
|
+ return NULL;
|
|
+ }
|
|
if (j == 4) i += 4;
|
|
else i += 2;
|
|
asclen += j;
|
|
diff --git a/test/asn1_internal_test.c b/test/asn1_internal_test.c
|
|
index e08e2a11be9b7..56af2b369b4dd 100644
|
|
--- a/test/asn1_internal_test.c
|
|
+++ b/test/asn1_internal_test.c
|
|
@@ -554,6 +554,22 @@ static int posix_time_test(void)
|
|
return 1;
|
|
}
|
|
|
|
+static int test_mbstring_ncopy(void)
|
|
+{
|
|
+ ASN1_STRING *str = NULL;
|
|
+ const unsigned char in[] = { 0xFF, 0xFE, 0xFF, 0xFE };
|
|
+ int inlen = 4;
|
|
+ int inform = MBSTRING_UNIV;
|
|
+
|
|
+ if (!TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_GENERALSTRING, 0, 0), -1)
|
|
+ || !TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_VISIBLESTRING, 0, 0), -1)
|
|
+ || !TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_VIDEOTEXSTRING, 0, 0), -1)
|
|
+ || !TEST_int_eq(ASN1_mbstring_ncopy(&str, in, inlen, inform, B_ASN1_GENERALIZEDTIME, 0, 0), -1))
|
|
+ return 0;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
int setup_tests(void)
|
|
{
|
|
ADD_TEST(test_tbl_standard);
|
|
@@ -565,5 +581,6 @@ int setup_tests(void)
|
|
ADD_TEST(test_unicode_range);
|
|
ADD_TEST(test_obj_create);
|
|
ADD_TEST(test_obj_nid_undef);
|
|
+ ADD_TEST(test_mbstring_ncopy);
|
|
return 1;
|
|
}
|