/src/botan/src/lib/asn1/asn1_str.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Simple ASN.1 String Types |
3 | | * (C) 1999-2007 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #include <botan/asn1_str.h> |
9 | | #include <botan/der_enc.h> |
10 | | #include <botan/ber_dec.h> |
11 | | #include <botan/charset.h> |
12 | | |
13 | | namespace Botan { |
14 | | |
15 | | namespace { |
16 | | |
17 | | /* |
18 | | * Choose an encoding for the string |
19 | | */ |
20 | | ASN1_Tag choose_encoding(const std::string& str) |
21 | 116k | { |
22 | 116k | static const uint8_t IS_PRINTABLE[256] = { |
23 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
24 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
25 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
26 | 116k | 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, |
27 | 116k | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, |
28 | 116k | 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
29 | 116k | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
30 | 116k | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, |
31 | 116k | 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
32 | 116k | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
33 | 116k | 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
34 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
35 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
36 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
37 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
38 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
39 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
40 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
41 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
42 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
43 | 116k | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
44 | 116k | 0x00, 0x00, 0x00, 0x00 }; |
45 | 116k | |
46 | 116k | for(size_t i = 0; i != str.size(); ++i) |
47 | 0 | { |
48 | 0 | if(!IS_PRINTABLE[static_cast<uint8_t>(str[i])]) |
49 | 0 | { |
50 | 0 | return UTF8_STRING; |
51 | 0 | } |
52 | 0 | } |
53 | 116k | return PRINTABLE_STRING; |
54 | 116k | } |
55 | | |
56 | | void assert_is_string_type(ASN1_Tag tag) |
57 | 118k | { |
58 | 118k | if(!ASN1_String::is_string_type(tag)) |
59 | 450 | { |
60 | 450 | throw Invalid_Argument("ASN1_String: Unknown string type " + |
61 | 450 | std::to_string(tag)); |
62 | 450 | } |
63 | 118k | } |
64 | | |
65 | | } |
66 | | |
67 | | //static |
68 | | bool ASN1_String::is_string_type(ASN1_Tag tag) |
69 | 159k | { |
70 | 159k | return (tag == NUMERIC_STRING || |
71 | 157k | tag == PRINTABLE_STRING || |
72 | 125k | tag == VISIBLE_STRING || |
73 | 110k | tag == T61_STRING || |
74 | 107k | tag == IA5_STRING || |
75 | 102k | tag == UTF8_STRING || |
76 | 46.3k | tag == BMP_STRING || |
77 | 41.4k | tag == UNIVERSAL_STRING); |
78 | 159k | } |
79 | | |
80 | | |
81 | | /* |
82 | | * Create an ASN1_String |
83 | | */ |
84 | | ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : m_utf8_str(str), m_tag(t) |
85 | 2.28k | { |
86 | 2.28k | if(m_tag == DIRECTORY_STRING) |
87 | 0 | { |
88 | 0 | m_tag = choose_encoding(m_utf8_str); |
89 | 0 | } |
90 | 2.28k | |
91 | 2.28k | assert_is_string_type(m_tag); |
92 | 2.28k | } |
93 | | |
94 | | /* |
95 | | * Create an ASN1_String |
96 | | */ |
97 | | ASN1_String::ASN1_String(const std::string& str) : |
98 | | m_utf8_str(str), |
99 | | m_tag(choose_encoding(m_utf8_str)) |
100 | 116k | {} |
101 | | |
102 | | /* |
103 | | * Return this string in ISO 8859-1 encoding |
104 | | */ |
105 | | std::string ASN1_String::iso_8859() const |
106 | 0 | { |
107 | 0 | return utf8_to_latin1(m_utf8_str); |
108 | 0 | } |
109 | | |
110 | | /* |
111 | | * DER encode an ASN1_String |
112 | | */ |
113 | | void ASN1_String::encode_into(DER_Encoder& encoder) const |
114 | 936 | { |
115 | 936 | if(m_data.empty()) |
116 | 936 | { |
117 | 936 | encoder.add_object(tagging(), UNIVERSAL, m_utf8_str); |
118 | 936 | } |
119 | 0 | else |
120 | 0 | { |
121 | | // If this string was decoded, reserialize using original encoding |
122 | 0 | encoder.add_object(tagging(), UNIVERSAL, m_data.data(), m_data.size()); |
123 | 0 | } |
124 | 936 | } |
125 | | |
126 | | /* |
127 | | * Decode a BER encoded ASN1_String |
128 | | */ |
129 | | void ASN1_String::decode_from(BER_Decoder& source) |
130 | 116k | { |
131 | 116k | BER_Object obj = source.get_next_object(); |
132 | 116k | |
133 | 116k | assert_is_string_type(obj.type()); |
134 | 116k | |
135 | 116k | m_tag = obj.type(); |
136 | 116k | m_data.assign(obj.bits(), obj.bits() + obj.length()); |
137 | 116k | |
138 | 116k | if(m_tag == BMP_STRING) |
139 | 3.82k | { |
140 | 3.82k | m_utf8_str = ucs2_to_utf8(m_data.data(), m_data.size()); |
141 | 3.82k | } |
142 | 112k | else if(m_tag == UNIVERSAL_STRING) |
143 | 3.27k | { |
144 | 3.27k | m_utf8_str = ucs4_to_utf8(m_data.data(), m_data.size()); |
145 | 3.27k | } |
146 | 109k | else |
147 | 109k | { |
148 | | // All other supported string types are UTF-8 or some subset thereof |
149 | 109k | m_utf8_str = ASN1::to_string(obj); |
150 | 109k | } |
151 | 116k | } |
152 | | |
153 | | } |