Botan 3.2.0
Crypto and TLS for C&
asn1_obj.cpp
Go to the documentation of this file.
1/*
2* ASN.1 Internals
3* (C) 1999-2007,2018 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/data_src.h>
11#include <botan/der_enc.h>
12#include <botan/internal/fmt.h>
13#include <botan/internal/stl_util.h>
14#include <sstream>
15
16namespace Botan {
17
18std::vector<uint8_t> ASN1_Object::BER_encode() const {
19 std::vector<uint8_t> output;
20 DER_Encoder der(output);
21 this->encode_into(der);
22 return output;
23}
24
25/*
26* Check a type invariant on BER data
27*/
28void BER_Object::assert_is_a(ASN1_Type expected_type_tag, ASN1_Class expected_class_tag, std::string_view descr) const {
29 if(this->is_a(expected_type_tag, expected_class_tag) == false) {
30 std::stringstream msg;
31
32 msg << "Tag mismatch when decoding " << descr << " got ";
33
34 if(m_class_tag == ASN1_Class::NoObject && m_type_tag == ASN1_Type::NoObject) {
35 msg << "EOF";
36 } else {
37 if(m_class_tag == ASN1_Class::Universal || m_class_tag == ASN1_Class::Constructed) {
38 msg << asn1_tag_to_string(m_type_tag);
39 } else {
40 msg << std::to_string(static_cast<uint32_t>(m_type_tag));
41 }
42
43 msg << "/" << asn1_class_to_string(m_class_tag);
44 }
45
46 msg << " expected ";
47
48 if(expected_class_tag == ASN1_Class::Universal || expected_class_tag == ASN1_Class::Constructed) {
49 msg << asn1_tag_to_string(expected_type_tag);
50 } else {
51 msg << std::to_string(static_cast<uint32_t>(expected_type_tag));
52 }
53
54 msg << "/" << asn1_class_to_string(expected_class_tag);
55
56 throw BER_Decoding_Error(msg.str());
57 }
58}
59
60bool BER_Object::is_a(ASN1_Type expected_type_tag, ASN1_Class expected_class_tag) const {
61 return (m_type_tag == expected_type_tag && m_class_tag == expected_class_tag);
62}
63
64bool BER_Object::is_a(int expected_type_tag, ASN1_Class expected_class_tag) const {
65 return is_a(ASN1_Type(expected_type_tag), expected_class_tag);
66}
67
68void BER_Object::set_tagging(ASN1_Type type_tag, ASN1_Class class_tag) {
69 m_type_tag = type_tag;
70 m_class_tag = class_tag;
71}
72
74 switch(type) {
76 return "UNIVERSAL";
78 return "CONSTRUCTED";
80 return "CONTEXT_SPECIFIC";
82 return "APPLICATION";
84 return "PRIVATE";
86 return "NO_OBJECT";
87 default:
88 return "CLASS(" + std::to_string(static_cast<size_t>(type)) + ")";
89 }
90}
91
92std::string asn1_tag_to_string(ASN1_Type type) {
93 switch(type) {
95 return "SEQUENCE";
96
97 case ASN1_Type::Set:
98 return "SET";
99
101 return "PRINTABLE STRING";
102
104 return "NUMERIC STRING";
105
107 return "IA5 STRING";
108
110 return "T61 STRING";
111
113 return "UTF8 STRING";
114
116 return "VISIBLE STRING";
117
119 return "BMP STRING";
120
122 return "UNIVERSAL STRING";
123
125 return "UTC TIME";
126
128 return "GENERALIZED TIME";
129
131 return "OCTET STRING";
132
134 return "BIT STRING";
135
137 return "ENUMERATED";
138
140 return "INTEGER";
141
142 case ASN1_Type::Null:
143 return "NULL";
144
146 return "OBJECT";
147
149 return "BOOLEAN";
150
152 return "NO_OBJECT";
153
154 default:
155 return "TAG(" + std::to_string(static_cast<uint32_t>(type)) + ")";
156 }
157}
158
159/*
160* BER Decoding Exceptions
161*/
162BER_Decoding_Error::BER_Decoding_Error(std::string_view str) : Decoding_Error(fmt("BER: {}", str)) {}
163
164BER_Bad_Tag::BER_Bad_Tag(std::string_view str, uint32_t tagging) : BER_Decoding_Error(fmt("{}: {}", str, tagging)) {}
165
166namespace ASN1 {
167
168/*
169* Put some arbitrary bytes into a SEQUENCE
170*/
171std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& contents) {
172 return ASN1::put_in_sequence(contents.data(), contents.size());
173}
174
175std::vector<uint8_t> put_in_sequence(const uint8_t bits[], size_t len) {
176 std::vector<uint8_t> output;
177 DER_Encoder(output).start_sequence().raw_bytes(bits, len).end_cons();
178 return output;
179}
180
181/*
182* Convert a BER object into a string object
183*/
184std::string to_string(const BER_Object& obj) {
185 return std::string(cast_uint8_ptr_to_char(obj.bits()), obj.length());
186}
187
188/*
189* Do heuristic tests for BER data
190*/
191bool maybe_BER(DataSource& source) {
192 uint8_t first_u8;
193 if(!source.peek_byte(first_u8)) {
194 BOTAN_ASSERT_EQUAL(source.read_byte(first_u8), 0, "Expected EOF");
195 throw Stream_IO_Error("ASN1::maybe_BER: Source was empty");
196 }
197
198 const auto cons_seq = static_cast<uint8_t>(ASN1_Class::Constructed) | static_cast<uint8_t>(ASN1_Type::Sequence);
199 if(first_u8 == cons_seq) {
200 return true;
201 }
202 return false;
203}
204
205} // namespace ASN1
206
207} // namespace Botan
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition assert.h:68
virtual void encode_into(DER_Encoder &to) const =0
std::vector< uint8_t > BER_encode() const
Definition asn1_obj.cpp:18
BER_Bad_Tag(std::string_view msg, uint32_t tagging)
Definition asn1_obj.cpp:164
BER_Decoding_Error(std::string_view)
Definition asn1_obj.cpp:162
size_t length() const
Definition asn1_obj.h:152
const uint8_t * bits() const
Definition asn1_obj.h:150
bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const
Definition asn1_obj.cpp:60
ASN1_Type type_tag() const
Definition asn1_obj.h:142
void assert_is_a(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view descr="object") const
Definition asn1_obj.cpp:28
ASN1_Class class_tag() const
Definition asn1_obj.h:144
DER_Encoder & start_sequence()
Definition der_enc.h:65
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition der_enc.cpp:207
DER_Encoder & end_cons()
Definition der_enc.cpp:171
size_t peek_byte(uint8_t &out) const
Definition data_src.cpp:32
size_t read_byte(uint8_t &out)
Definition data_src.cpp:25
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition asn1_obj.cpp:171
bool maybe_BER(DataSource &source)
Definition asn1_obj.cpp:191
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:184
std::string asn1_tag_to_string(ASN1_Type type)
Definition asn1_obj.cpp:92
ASN1_Class
Definition asn1_obj.h:28
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:43
std::string asn1_class_to_string(ASN1_Class type)
Definition asn1_obj.cpp:73
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition mem_ops.h:181