diff options
Diffstat (limited to 'src/lib/asn1')
-rw-r--r-- | src/lib/asn1/asn1_alt_name.cpp | 13 | ||||
-rw-r--r-- | src/lib/asn1/asn1_str.cpp | 132 | ||||
-rw-r--r-- | src/lib/asn1/asn1_str.h | 16 | ||||
-rw-r--r-- | src/lib/asn1/asn1_time.cpp | 11 | ||||
-rw-r--r-- | src/lib/asn1/info.txt | 2 |
5 files changed, 62 insertions, 112 deletions
diff --git a/src/lib/asn1/asn1_alt_name.cpp b/src/lib/asn1/asn1_alt_name.cpp index 7bd4cd494..940312886 100644 --- a/src/lib/asn1/asn1_alt_name.cpp +++ b/src/lib/asn1/asn1_alt_name.cpp @@ -11,7 +11,6 @@ #include <botan/ber_dec.h> #include <botan/oids.h> #include <botan/internal/stl_util.h> -#include <botan/charset.h> #include <botan/parsing.h> #include <botan/loadstor.h> @@ -133,7 +132,7 @@ void encode_entries(DER_Encoder& encoder, if(type == "RFC822" || type == "DNS" || type == "URI") { ASN1_String asn1_string(i->second, IA5_STRING); - encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859()); + encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.value()); } else if(type == "IP") { @@ -218,13 +217,9 @@ void AlternativeName::decode_from(BER_Decoder& source) } else if(tag == 1 || tag == 2 || tag == 6) { - const std::string value = Charset::transcode(ASN1::to_string(obj), - LATIN1_CHARSET, - LOCAL_CHARSET); - - if(tag == 1) add_attribute("RFC822", value); - if(tag == 2) add_attribute("DNS", value); - if(tag == 6) add_attribute("URI", value); + if(tag == 1) add_attribute("RFC822", ASN1::to_string(obj)); + if(tag == 2) add_attribute("DNS", ASN1::to_string(obj)); + if(tag == 6) add_attribute("URI", ASN1::to_string(obj)); } else if(tag == 7) { diff --git a/src/lib/asn1/asn1_str.cpp b/src/lib/asn1/asn1_str.cpp index 070acbebd..d90aa215b 100644 --- a/src/lib/asn1/asn1_str.cpp +++ b/src/lib/asn1/asn1_str.cpp @@ -10,9 +10,6 @@ #include <botan/ber_dec.h> #include <botan/charset.h> -#include <codecvt> -#include <locale> - namespace Botan { namespace { @@ -20,8 +17,7 @@ namespace { /* * Choose an encoding for the string */ -ASN1_Tag choose_encoding(const std::string& str, - const std::string& type) +ASN1_Tag choose_encoding(const std::string& str) { static const uint8_t IS_PRINTABLE[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -51,63 +47,49 @@ ASN1_Tag choose_encoding(const std::string& str, { if(!IS_PRINTABLE[static_cast<uint8_t>(str[i])]) { - if(type == "utf8") return UTF8_STRING; - if(type == "latin1") return T61_STRING; - throw Invalid_Argument("choose_encoding: Bad string type " + type); + return UTF8_STRING; } } return PRINTABLE_STRING; } -} - -template <typename CharT, class AllocT> -static std::string ucsX_to_utf8(const std::vector<byte, AllocT> &ucsX) +void assert_is_string_type(ASN1_Tag tag) { - if (ucsX.size() % sizeof(CharT) != 0) + if(tag != NUMERIC_STRING && + tag != PRINTABLE_STRING && + tag != VISIBLE_STRING && + tag != T61_STRING && + tag != IA5_STRING && + tag != UTF8_STRING && + tag != BMP_STRING && + tag != UNIVERSAL_STRING) { - throw Invalid_Argument("cannot decode UCS string (wrong byte count)"); + throw Invalid_Argument("ASN1_String: Unknown string type " + + std::to_string(tag)); } - - union - { - const byte *as_char; - const CharT *as_wide_char; - }; - - as_char = ucsX.data(); - const size_t wide_char_count = ucsX.size() / sizeof(CharT); - - using converter_t = std::codecvt_utf8<CharT, 0x10ffff, std::consume_header>; - std::wstring_convert<converter_t, CharT> convert; - return convert.to_bytes(as_wide_char, as_wide_char + wide_char_count); } +} + /* * Create an ASN1_String */ ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : m_utf8_str(str), m_tag(t) { - if(m_tag == DIRECTORY_STRING) - m_tag = choose_encoding(m_utf8_str, "utf8"); - - if(m_tag != NUMERIC_STRING && - m_tag != PRINTABLE_STRING && - m_tag != VISIBLE_STRING && - m_tag != T61_STRING && - m_tag != IA5_STRING && - m_tag != UTF8_STRING && - m_tag != BMP_STRING && - m_tag != UNIVERSAL_STRING) - throw Invalid_Argument("ASN1_String: Unknown string type " + - std::to_string(m_tag)); + { + m_tag = choose_encoding(m_utf8_str); + } + + assert_is_string_type(m_tag); } /* * Create an ASN1_String */ -ASN1_String::ASN1_String(const std::string& str) : m_utf8_str(str), m_tag(choose_encoding(m_utf8_str, "utf8")) +ASN1_String::ASN1_String(const std::string& str) : + m_utf8_str(str), + m_tag(choose_encoding(m_utf8_str)) {} /* @@ -115,23 +97,7 @@ ASN1_String::ASN1_String(const std::string& str) : m_utf8_str(str), m_tag(choose */ std::string ASN1_String::iso_8859() const { - return Charset::transcode(m_utf8_str, LATIN1_CHARSET, UTF8_CHARSET); - } - -/* -* Return this string in UTF-8 encoding -*/ -std::string ASN1_String::value() const - { - return m_utf8_str; - } - -/* -* Return the type of this string object -*/ -ASN1_Tag ASN1_String::tagging() const - { - return m_tag; + return utf8_to_latin1(m_utf8_str); } /* @@ -139,7 +105,15 @@ ASN1_Tag ASN1_String::tagging() const */ void ASN1_String::encode_into(DER_Encoder& encoder) const { - encoder.add_object(tagging(), UNIVERSAL, m_utf8_str); + if(m_data.empty()) + { + encoder.add_object(tagging(), UNIVERSAL, m_utf8_str); + } + else + { + // If this string was decoded, reserialize using original encoding + encoder.add_object(tagging(), UNIVERSAL, m_data.data(), m_data.size()); + } } /* @@ -149,39 +123,23 @@ void ASN1_String::decode_from(BER_Decoder& source) { BER_Object obj = source.get_next_object(); -#if defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS) - // using char32_t and char16_t (as suggested by the standard) leads to linker - // errors on MSVC 2015 and 2017. This workaround was suggested here: - // https://social.msdn.microsoft.com/Forums/vstudio/en-US/ - // 8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error - using utf32_type = int32_t; - using utf16_type = wchar_t; -#else - using utf32_type = char32_t; - using utf16_type = char16_t; -#endif - - if(obj.type_tag == UTF8_STRING) - { - *this = ASN1_String(ASN1::to_string(obj), obj.type_tag); - } - else if(obj.type_tag == BMP_STRING) + assert_is_string_type(obj.type_tag); + + m_tag = obj.type_tag; + m_data.assign(obj.value.begin(), obj.value.end()); + + if(m_tag == BMP_STRING) { - *this = ASN1_String(ucsX_to_utf8<utf16_type>(obj.value), obj.type_tag); + m_utf8_str = ucs2_to_utf8(m_data.data(), m_data.size()); } - else if(obj.type_tag == UNIVERSAL_STRING) + else if(m_tag == UNIVERSAL_STRING) { - *this = ASN1_String(ucsX_to_utf8<utf32_type>(obj.value), obj.type_tag); + m_utf8_str = ucs4_to_utf8(m_data.data(), m_data.size()); } - else // IA5_STRING - international ASCII characters - // T61_STRING - pretty much ASCII - // PRINTABLE_STRING - ASCII subset (a-z, A-Z, ' () +,-.?:/= and SPACE) - // VISIBLE_STRING - visible ASCII subset - // NUMERIC_STRING - ASCII subset (0-9 and SPACE) + else { - *this = ASN1_String( - Charset::transcode(ASN1::to_string(obj), UTF8_CHARSET, LATIN1_CHARSET), - obj.type_tag); + // All other supported string types are UTF-8 or some subset thereof + m_utf8_str = ASN1::to_string(obj); } } diff --git a/src/lib/asn1/asn1_str.h b/src/lib/asn1/asn1_str.h index 3ad82582e..f19265494 100644 --- a/src/lib/asn1/asn1_str.h +++ b/src/lib/asn1/asn1_str.h @@ -13,7 +13,8 @@ namespace Botan { /** -* Simple String +* ASN.1 string type +* This class normalizes all inputs to a UTF-8 std::string */ class BOTAN_PUBLIC_API(2,0) ASN1_String final : public ASN1_Object { @@ -21,14 +22,17 @@ class BOTAN_PUBLIC_API(2,0) ASN1_String final : public ASN1_Object void encode_into(class DER_Encoder&) const override; void decode_from(class BER_Decoder&) override; - std::string value() const; - std::string iso_8859() const; + ASN1_Tag tagging() const { return m_tag; } + + const std::string& value() const { return m_utf8_str; } - ASN1_Tag tagging() const; + std::string BOTAN_DEPRECATED("Use value() to get UTF-8 string instead") + iso_8859() const; - explicit ASN1_String(const std::string& = ""); - ASN1_String(const std::string&, ASN1_Tag); + explicit ASN1_String(const std::string& utf8 = ""); + ASN1_String(const std::string& utf8, ASN1_Tag tag); private: + std::vector<uint8_t> m_data; std::string m_utf8_str; ASN1_Tag m_tag; }; diff --git a/src/lib/asn1/asn1_time.cpp b/src/lib/asn1/asn1_time.cpp index 2cd225915..f6a0c414e 100644 --- a/src/lib/asn1/asn1_time.cpp +++ b/src/lib/asn1/asn1_time.cpp @@ -8,7 +8,6 @@ #include <botan/asn1_time.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/charset.h> #include <botan/exceptn.h> #include <botan/parsing.h> #include <botan/calendar.h> @@ -41,20 +40,14 @@ void X509_Time::encode_into(DER_Encoder& der) const if(m_tag != GENERALIZED_TIME && m_tag != UTC_TIME) throw Invalid_Argument("X509_Time: Bad encoding tag"); - der.add_object(m_tag, UNIVERSAL, - Charset::transcode(to_string(), - LOCAL_CHARSET, - LATIN1_CHARSET)); + der.add_object(m_tag, UNIVERSAL, to_string()); } void X509_Time::decode_from(BER_Decoder& source) { BER_Object ber_time = source.get_next_object(); - set_to(Charset::transcode(ASN1::to_string(ber_time), - LATIN1_CHARSET, - LOCAL_CHARSET), - ber_time.type_tag); + set_to(ASN1::to_string(ber_time), ber_time.type_tag); } std::string X509_Time::to_string() const diff --git a/src/lib/asn1/info.txt b/src/lib/asn1/info.txt index 4b3689f45..4772e1ca7 100644 --- a/src/lib/asn1/info.txt +++ b/src/lib/asn1/info.txt @@ -1,5 +1,5 @@ <defines> -ASN1 -> 20161102 +ASN1 -> 20171109 </defines> <requires> |