Botan  2.1.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 #include <botan/parsing.h>
13 
14 namespace Botan {
15 
16 namespace {
17 
18 /*
19 * Choose an encoding for the string
20 */
21 ASN1_Tag choose_encoding(const std::string& str,
22  const std::string& type)
23  {
24  static const uint8_t IS_PRINTABLE[256] = {
25  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
28  0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
29  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
30  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
31  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
32  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
33  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
34  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
35  0x01, 0x01, 0x01, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46  0x00, 0x00, 0x00, 0x00 };
47 
48  for(size_t i = 0; i != str.size(); ++i)
49  {
50  if(!IS_PRINTABLE[static_cast<uint8_t>(str[i])])
51  {
52  if(type == "utf8") return UTF8_STRING;
53  if(type == "latin1") return T61_STRING;
54  throw Invalid_Argument("choose_encoding: Bad string type " + type);
55  }
56  }
57  return PRINTABLE_STRING;
58  }
59 
60 }
61 
62 /*
63 * Create an ASN1_String
64 */
65 ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : m_iso_8859_str(Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET)), m_tag(t)
66  {
67 
68  if(m_tag == DIRECTORY_STRING)
69  m_tag = choose_encoding(m_iso_8859_str, "latin1");
70 
71  if(m_tag != NUMERIC_STRING &&
72  m_tag != PRINTABLE_STRING &&
73  m_tag != VISIBLE_STRING &&
74  m_tag != T61_STRING &&
75  m_tag != IA5_STRING &&
76  m_tag != UTF8_STRING &&
77  m_tag != BMP_STRING)
78  throw Invalid_Argument("ASN1_String: Unknown string type " +
79  std::to_string(m_tag));
80  }
81 
82 /*
83 * Create an ASN1_String
84 */
85 ASN1_String::ASN1_String(const std::string& str) : m_iso_8859_str(Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET)), m_tag(choose_encoding(m_iso_8859_str, "latin1"))
86  {}
87 
88 /*
89 * Return this string in ISO 8859-1 encoding
90 */
91 std::string ASN1_String::iso_8859() const
92  {
93  return m_iso_8859_str;
94  }
95 
96 /*
97 * Return this string in local encoding
98 */
99 std::string ASN1_String::value() const
100  {
101  return Charset::transcode(m_iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET);
102  }
103 
104 /*
105 * Return the type of this string object
106 */
108  {
109  return m_tag;
110  }
111 
112 /*
113 * DER encode an ASN1_String
114 */
116  {
117  std::string value = iso_8859();
118  if(tagging() == UTF8_STRING)
120  encoder.add_object(tagging(), UNIVERSAL, value);
121  }
122 
123 /*
124 * Decode a BER encoded ASN1_String
125 */
127  {
128  BER_Object obj = source.get_next_object();
129 
130  Character_Set charset_is;
131 
132  if(obj.type_tag == BMP_STRING)
133  charset_is = UCS2_CHARSET;
134  else if(obj.type_tag == UTF8_STRING)
135  charset_is = UTF8_CHARSET;
136  else
137  charset_is = LATIN1_CHARSET;
138 
139  *this = ASN1_String(
141  obj.type_tag);
142  }
143 
144 }
void decode_from(class BER_Decoder &) override
Definition: asn1_str.cpp:126
ASN1_Tag tagging() const
Definition: asn1_str.cpp:107
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const uint8_t rep[], size_t length)
Definition: der_enc.cpp:381
std::string value() const
Definition: asn1_str.cpp:99
void encode_into(class DER_Encoder &) const override
Definition: asn1_str.cpp:115
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
MechanismType type
Character_Set
Definition: charset.h:19
std::string transcode(const std::string &str, Character_Set to, Character_Set from)
Definition: charset.cpp:103
ASN1_String(const std::string &="")
Definition: asn1_str.cpp:85
ASN1_Tag
Definition: asn1_obj.h:22
Definition: alg_id.cpp:13
BER_Object get_next_object()
Definition: ber_dec.cpp:210
std::string iso_8859() const
Definition: asn1_str.cpp:91
ASN1_Tag type_tag
Definition: asn1_obj.h:91