diff options
Diffstat (limited to 'lib/x509/common.c')
-rw-r--r-- | lib/x509/common.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c index 6d72338d42..b75cb7055e 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -31,6 +31,7 @@ #include <x509_b64.h> #include "x509_int.h" #include "extras/hex.h" +#include "str.h" #include <common.h> #include <c-ctype.h> @@ -1327,6 +1328,30 @@ static int is_printable(char p) return 0; } +/* ensures that the UTF8 string we write is properly encoded */ +int _gnutls_x509_write_utf8_value(ASN1_TYPE asn_struct, const char *where, + const uint8_t *data, size_t data_size) +{ + int ret, result; + uint8_t *nrm = _gnutls_normalize_u8_nfc(data, data_size); + + if (nrm == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_UTF8_PASSWORD); + + result = asn1_write_value(asn_struct, where, nrm, strlen((char*)nrm)); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + ret = 0; + + cleanup: + gnutls_free(nrm); + return ret; +} + static int write_complex_string(ASN1_TYPE asn_struct, const char *where, const struct oid_to_string *oentry, const uint8_t * data, size_t data_size) @@ -1335,7 +1360,7 @@ static int write_complex_string(ASN1_TYPE asn_struct, const char *where, ASN1_TYPE c2; int result; const char *string_type; - unsigned int i; + unsigned int i, utf8_flag = 0; result = asn1_create_element(_gnutls_get_pkix(), oentry->asn_desc, &c2); @@ -1354,6 +1379,7 @@ static int write_complex_string(ASN1_TYPE asn_struct, const char *where, for (i = 0; i < data_size; i++) { if (!is_printable(data[i])) { string_type = "utf8String"; + utf8_flag = 1; break; } } @@ -1370,11 +1396,19 @@ static int write_complex_string(ASN1_TYPE asn_struct, const char *where, _gnutls_str_cpy(tmp, sizeof(tmp), string_type); - result = asn1_write_value(c2, tmp, data, data_size); - if (result != ASN1_SUCCESS) { - gnutls_assert(); - result = _gnutls_asn2err(result); - goto error; + if (utf8_flag) { + result = _gnutls_x509_write_utf8_value(c2, tmp, data, data_size); + if (result < 0) { + gnutls_assert(); + goto error; + } + } else { + result = asn1_write_value(c2, tmp, data, data_size); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto error; + } } result = |