Botan  2.7.0
Crypto and TLS for C++11
asn1_str.cpp
Go to the documentation of this file.
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  {
22  static const uint8_t IS_PRINTABLE[256] = {
23  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
26  0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
27  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
28  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
29  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
30  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
31  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
32  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
33  0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44  0x00, 0x00, 0x00, 0x00 };
45 
46  for(size_t i = 0; i != str.size(); ++i)
47  {
48  if(!IS_PRINTABLE[static_cast<uint8_t>(str[i])])
49  {
50  return UTF8_STRING;
51  }
52  }
53  return PRINTABLE_STRING;
54  }
55 
56 void assert_is_string_type(ASN1_Tag tag)
57  {
59  {
60  throw Invalid_Argument("ASN1_String: Unknown string type " +
61  std::to_string(tag));
62  }
63  }
64 
65 }
66 
67 //static
69  {
70  return (tag == NUMERIC_STRING ||
71  tag == PRINTABLE_STRING ||
72  tag == VISIBLE_STRING ||
73  tag == T61_STRING ||
74  tag == IA5_STRING ||
75  tag == UTF8_STRING ||
76  tag == BMP_STRING ||
77  tag == UNIVERSAL_STRING);
78  }
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  {
86  if(m_tag == DIRECTORY_STRING)
87  {
88  m_tag = choose_encoding(m_utf8_str);
89  }
90 
91  assert_is_string_type(m_tag);
92  }
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  {}
101 
102 /*
103 * Return this string in ISO 8859-1 encoding
104 */
105 std::string ASN1_String::iso_8859() const
106  {
107  return utf8_to_latin1(m_utf8_str);
108  }
109 
110 /*
111 * DER encode an ASN1_String
112 */
114  {
115  if(m_data.empty())
116  {
117  encoder.add_object(tagging(), UNIVERSAL, m_utf8_str);
118  }
119  else
120  {
121  // If this string was decoded, reserialize using original encoding
122  encoder.add_object(tagging(), UNIVERSAL, m_data.data(), m_data.size());
123  }
124  }
125 
126 /*
127 * Decode a BER encoded ASN1_String
128 */
130  {
131  BER_Object obj = source.get_next_object();
132 
133  assert_is_string_type(obj.type());
134 
135  m_tag = obj.type();
136  m_data.assign(obj.bits(), obj.bits() + obj.length());
137 
138  if(m_tag == BMP_STRING)
139  {
140  m_utf8_str = ucs2_to_utf8(m_data.data(), m_data.size());
141  }
142  else if(m_tag == UNIVERSAL_STRING)
143  {
144  m_utf8_str = ucs4_to_utf8(m_data.data(), m_data.size());
145  }
146  else
147  {
148  // All other supported string types are UTF-8 or some subset thereof
149  m_utf8_str = ASN1::to_string(obj);
150  }
151  }
152 
153 }
std::string iso_8859() const
Definition: asn1_str.cpp:105
void decode_from(class BER_Decoder &) override
Definition: asn1_str.cpp:129
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const uint8_t rep[], size_t length)
Definition: der_enc.cpp:249
static bool is_string_type(ASN1_Tag tag)
Definition: asn1_str.cpp:68
std::string ucs4_to_utf8(const uint8_t ucs4[], size_t len)
Definition: charset.cpp:78
void encode_into(class DER_Encoder &) const override
Definition: asn1_str.cpp:113
std::string utf8_to_latin1(const std::string &utf8)
Definition: charset.cpp:98
std::string ucs2_to_utf8(const uint8_t ucs2[], size_t len)
Definition: charset.cpp:61
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
ASN1_Tag
Definition: asn1_obj.h:22
ASN1_Tag type() const
Definition: asn1_obj.h:115
size_t length() const
Definition: asn1_obj.h:120
Definition: alg_id.cpp:13
ASN1_String(const std::string &utf8="")
Definition: asn1_str.cpp:97
BER_Object get_next_object()
Definition: ber_dec.cpp:237
const uint8_t * bits() const
Definition: asn1_obj.h:118
ASN1_Tag tagging() const
Definition: asn1_str.h:25