Coverage Report

Created: 2024-11-29 06:10

/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,2020 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/asn1_obj.h>
9
10
#include <botan/ber_dec.h>
11
#include <botan/der_enc.h>
12
#include <botan/internal/charset.h>
13
#include <botan/internal/ct_utils.h>
14
#include <botan/internal/fmt.h>
15
16
namespace Botan {
17
18
namespace {
19
20
/*
21
* Choose an encoding for the string
22
*/
23
148k
ASN1_Type choose_encoding(std::string_view str) {
24
148k
   auto all_printable = CT::Mask<uint8_t>::set();
25
26
148k
   for(size_t i = 0; i != str.size(); ++i) {
27
0
      const uint8_t c = static_cast<uint8_t>(str[i]);
28
29
0
      auto is_alpha_lower = CT::Mask<uint8_t>::is_within_range(c, 'a', 'z');
30
0
      auto is_alpha_upper = CT::Mask<uint8_t>::is_within_range(c, 'A', 'Z');
31
0
      auto is_decimal = CT::Mask<uint8_t>::is_within_range(c, '0', '9');
32
33
0
      auto is_print_punc = CT::Mask<uint8_t>::is_any_of(c, {' ', '(', ')', '+', ',', '-', '.', '/', ':', '=', '?'});
34
35
0
      auto is_printable = is_alpha_lower | is_alpha_upper | is_decimal | is_print_punc;
36
37
0
      all_printable &= is_printable;
38
0
   }
39
40
148k
   if(all_printable.as_bool()) {
41
148k
      return ASN1_Type::PrintableString;
42
148k
   } else {
43
0
      return ASN1_Type::Utf8String;
44
0
   }
45
148k
}
46
47
346k
bool is_utf8_subset_string_type(ASN1_Type tag) {
48
346k
   return (tag == ASN1_Type::NumericString || tag == ASN1_Type::PrintableString || tag == ASN1_Type::VisibleString ||
49
346k
           tag == ASN1_Type::Ia5String || tag == ASN1_Type::Utf8String);
50
346k
}
51
52
190k
bool is_asn1_string_type(ASN1_Type tag) {
53
190k
   return (is_utf8_subset_string_type(tag) || tag == ASN1_Type::TeletexString || tag == ASN1_Type::BmpString ||
54
190k
           tag == ASN1_Type::UniversalString);
55
190k
}
56
57
}  // namespace
58
59
//static
60
44.7k
bool ASN1_String::is_string_type(ASN1_Type tag) {
61
44.7k
   return is_asn1_string_type(tag);
62
44.7k
}
63
64
155k
ASN1_String::ASN1_String(std::string_view str, ASN1_Type t) : m_utf8_str(str), m_tag(t) {
65
155k
   if(!is_utf8_subset_string_type(m_tag)) {
66
22
      throw Invalid_Argument("ASN1_String only supports encoding to UTF-8 or a UTF-8 subset");
67
22
   }
68
155k
}
69
70
148k
ASN1_String::ASN1_String(std::string_view str) : ASN1_String(str, choose_encoding(str)) {}
71
72
/*
73
* DER encode an ASN1_String
74
*/
75
0
void ASN1_String::encode_into(DER_Encoder& encoder) const {
76
0
   if(m_data.empty()) {
77
0
      BOTAN_ASSERT_NOMSG(is_utf8_subset_string_type(tagging()));
78
0
      encoder.add_object(tagging(), ASN1_Class::Universal, m_utf8_str);
79
0
   } else {
80
      // If this string was decoded, reserialize using original encoding
81
0
      encoder.add_object(tagging(), ASN1_Class::Universal, m_data.data(), m_data.size());
82
0
   }
83
0
}
84
85
/*
86
* Decode a BER encoded ASN1_String
87
*/
88
146k
void ASN1_String::decode_from(BER_Decoder& source) {
89
146k
   BER_Object obj = source.get_next_object();
90
91
146k
   if(!is_asn1_string_type(obj.type())) {
92
1.11k
      auto typ = static_cast<uint32_t>(obj.type());
93
1.11k
      throw Decoding_Error(fmt("ASN1_String: Unknown string type {}", typ));
94
1.11k
   }
95
96
145k
   m_tag = obj.type();
97
145k
   m_data.assign(obj.bits(), obj.bits() + obj.length());
98
99
145k
   if(m_tag == ASN1_Type::BmpString) {
100
8.54k
      m_utf8_str = ucs2_to_utf8(m_data.data(), m_data.size());
101
136k
   } else if(m_tag == ASN1_Type::UniversalString) {
102
4.06k
      m_utf8_str = ucs4_to_utf8(m_data.data(), m_data.size());
103
132k
   } else if(m_tag == ASN1_Type::TeletexString) {
104
      /*
105
      TeletexString is nominally ITU T.61 not ISO-8859-1 but it seems
106
      the majority of implementations actually used that charset here.
107
      */
108
16.4k
      m_utf8_str = latin1_to_utf8(m_data.data(), m_data.size());
109
116k
   } else {
110
      // All other supported string types are UTF-8 or some subset thereof
111
116k
      m_utf8_str = ASN1::to_string(obj);
112
116k
   }
113
145k
}
114
115
}  // namespace Botan