├── LICENSE
├── README.md
└── code
├── CompliConfig.xsd
├── CompliXML.xsd
├── common.h
├── compli_v2.rc
├── compli_v2.vcxproj
├── internal_base64.h
├── internal_basicfuncs.h
├── internal_basictypes.h
├── internal_transformfuncs.h
├── internal_utf8stream.h
├── main_file.cpp
├── resource.h
├── stage10.xslt
├── type_bitstring.h
├── type_boolean.h
├── type_date_times.h
├── type_datetimes.h
├── type_eoc.h
├── type_integer.h
├── type_null.h
├── type_objid.h
├── type_octetstring.h
├── type_real.h
├── type_sequence.h
├── type_set.h
└── type_strings.h
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2018, Yury Strozhevsky
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | In 2012 before I have written [my article](http://www.strozhevsky.com/free_docs/asn1_in_simple_words.pdf) I inspected several existing implementations of ASN.1 coder/decoder functionality. It was sad, but I found few (frankly speaking sometime not a few) mistakes in such programs delivering on a market. Of course I wrote all the mistakes to developers. But at the same time I understud that there is no freely available ASN.1 coder/decoder. Yes, there are many of such implementations but there is no implementation for all ASN.1:2008 data type together with BER encoding rules. So, I decided to create one :) Also the coder/decoder gave me a greate help on creating [my ASN.1:2008 test suite](https://github.com/YuryStrozhevsky/ASN1-2008-free-test-suite).
4 |
5 | ## Words about BER (Basic Encoding Rules)
6 |
7 | Almost all specialists know about ASN.1, some of them know about DER (Distinguished Encoding Rules). DER is using widely in crypto and all other stuf. But only less part of the specialist working with ASN.1 know that DER is a simple set of restrictions on a bigger set of rules - BER. That is it - BER is much bigger than DER. These are a really "basic ASN.1 rules", DER is a secondary sub-set of these rules. Please keep it in mind, take a look at my code and get all knowledge about a real (not cutted) ASN.1 power!
8 |
9 | ## ASN1js project
10 |
11 | In 2014 I made a project [ASN1js](https://github.com/GlobalSign/ASN1.js). This is an ASN.1 BER encoder/decoder on JavaScript language. In fact all code for [ASN1js](https://github.com/GlobalSign/ASN1.js) is a "porting" from this project code, from C++ to JavaScript. Also the same was using inside [PKIjs](https://github.com/GlobalSign/PKI.js) project. [ASN1js](https://github.com/GlobalSign/ASN1.js) has many improvements related to ASN.1 schema validation. Also because of JavaScript [ASN1js](https://github.com/GlobalSign/ASN1.js) has some limitations and slightly diferent code structure. For the moment I have a plans to back-port all [ASN1js](https://github.com/GlobalSign/ASN1.js) improvements to C++ project. Coming soon!
12 |
13 | ## Features of C++ ASN.1:2008 BER coder/encoder
14 |
15 | * Really BER coder/decoder (hence DER and CER will be processed as well);
16 | * Three formats of input/output data:
17 | * Binary raw data;
18 | * BASE-64 encoded binary raw data;
19 | * XER-like XML files;
20 | * Working with all datatypes from latest ASN.1:2008 standard;
21 | * Fully object-oriented C++ code;
22 | * Layered code, can be easily extended;
23 | * A bulk mode (working with many files at once);
24 | * Special XML format (input and output) can help to understand all details of ASN. in a structured form;
25 | * Output XML files may be used as an input for backward encoding into BER;
26 | * All XML structures described in well-documented XSD;
27 |
28 | ## Usage
29 |
30 | Firstly you need to create a configuration file. Schema for configuration file is inside "code/CompliConfig.xsd". Example of such configuration:
31 | ```xml
32 |
33 |
34 |
35 |
36 | BER
37 | example.ber
38 |
39 |
40 | XML
41 | example.xml
42 |
43 |
44 |
45 | ```
46 |
47 | There could be many "file_group" regions (and hence many files). Possible formats:
48 | * BER
49 | * BER64
50 | * XML
51 |
52 | Usually output of the program is XML. But please keep in mind - the output XML may be used as an input! Yes, you can parse BER (DER, CER) ASN.1 binary data, get XML file, change in this XML file whatever you want and encode it back to binary. Is not it funny? :) Schema for output/input XML is in "code/CompliXML.xsd".
53 |
54 | ## Limitations
55 |
56 | * Windows-only project;
57 | * MSXML6 library need to be installed;
58 |
59 | ## License
60 |
61 | Copyright (c) 2014, [Yury Strozhevsky](http://www.strozhevsky.com/)
62 | All rights reserved.
63 |
64 | Redistribution and use in source and binary forms, with or without
65 | modification, are permitted provided that the following conditions are met:
66 |
67 | * Redistributions of source code must retain the above copyright notice, this
68 | list of conditions and the following disclaimer.
69 |
70 | * Redistributions in binary form must reproduce the above copyright notice,
71 | this list of conditions and the following disclaimer in the documentation
72 | and/or other materials provided with the distribution.
73 |
74 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
75 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
77 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
78 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
80 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
81 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
82 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
83 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/code/CompliConfig.xsd:
--------------------------------------------------------------------------------
1 | Root element of configuration
2 |
--------------------------------------------------------------------------------
/code/common.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/common.h
--------------------------------------------------------------------------------
/code/compli_v2.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/compli_v2.rc
--------------------------------------------------------------------------------
/code/compli_v2.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {C1E3155E-BDC1-43F2-8F92-5EFDA6A1433C}
23 | Win32Proj
24 | compli_v2
25 |
26 |
27 |
28 | Application
29 | true
30 | Unicode
31 | v110
32 |
33 |
34 | Application
35 | true
36 | Unicode
37 | v110
38 |
39 |
40 | Application
41 | false
42 | true
43 | Unicode
44 | v110
45 |
46 |
47 | Application
48 | false
49 | true
50 | Unicode
51 | v110
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 | AllRules.ruleset
72 | true
73 | false
74 |
75 |
76 | true
77 |
78 |
79 | false
80 |
81 |
82 | false
83 |
84 |
85 |
86 |
87 |
88 | Level3
89 | Disabled
90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
91 | true
92 | true
93 |
94 |
95 | Console
96 | true
97 | true
98 |
99 |
100 | true
101 |
102 |
103 |
104 |
105 |
106 |
107 | Level3
108 | Disabled
109 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
110 |
111 |
112 | Console
113 | true
114 | true
115 |
116 |
117 |
118 |
119 | Level3
120 |
121 |
122 | MaxSpeed
123 | true
124 | true
125 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
126 |
127 |
128 | Console
129 | true
130 | true
131 | true
132 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
133 |
134 |
135 |
136 |
137 |
138 |
139 | Level3
140 |
141 |
142 | MaxSpeed
143 | true
144 | true
145 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
146 |
147 |
148 | Console
149 | true
150 | true
151 | true
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
--------------------------------------------------------------------------------
/code/internal_base64.h:
--------------------------------------------------------------------------------
1 | #ifndef _43602737_A607_4BE4_8C34_199C2CA3F292
2 | #define _43602737_A607_4BE4_8C34_199C2CA3F292
3 | //***************************************************************************
4 | template< class _in, class _out >
5 | void base64_encode( _in _in_iterator, _in _end_of_in, _out _out_iterator )
6 | {
7 | int BLOCK = 192;
8 |
9 | std::vector< char > buf;
10 | buf.reserve( BLOCK );
11 |
12 | int count;
13 | int string_len=0;
14 | int len;
15 |
16 | while(_in_iterator!=_end_of_in)
17 | {
18 | buf.clear();
19 | count=0;
20 |
21 | for( ; ( ( _in_iterator != _end_of_in ) && ( count < BLOCK ) ); _in_iterator++, count++ )
22 | buf.push_back( *_in_iterator );
23 |
24 | if( count < BLOCK )
25 | buf.resize( count );
26 |
27 | len = 0;
28 |
29 | len = Base64EncodeGetRequiredLength( buf.size(),
30 | ( _in_iterator == _end_of_in ) ? ATL_BASE64_FLAG_NOCRLF : ( ATL_BASE64_FLAG_NOPAD | ATL_BASE64_FLAG_NOCRLF )
31 | );
32 |
33 | LPSTR temp_string = static_cast< LPSTR >( malloc( len + 1 ) );
34 | if( !temp_string )
35 | return;
36 | ZeroMemory( temp_string, len + 1 );
37 |
38 | Base64Encode( reinterpret_cast< const BYTE* >( &buf[ 0 ] ),
39 | buf.size(),
40 | temp_string,
41 | &len,
42 | ( _in_iterator == _end_of_in ) ? ATL_BASE64_FLAG_NOCRLF : ( ATL_BASE64_FLAG_NOPAD | ATL_BASE64_FLAG_NOCRLF )
43 | );
44 |
45 | for( unsigned int i = 0; i < strlen( temp_string ); i++ )
46 | {
47 | _out_iterator = temp_string[ i ];
48 | string_len++;
49 | if( string_len > 59 )
50 | {
51 | string_len = 0;
52 | _out_iterator = '\r';
53 | _out_iterator = '\n';
54 | }
55 | }
56 |
57 | ZeroMemory( temp_string, len + 1 );
58 | free( temp_string );
59 | }
60 |
61 | _out_iterator = '\r';
62 | _out_iterator = '\n';
63 | }
64 | //***************************************************************************
65 | template< class _in, class _out >
66 | void base64_decode( _in _in_iterator, _in _end_of_in, _out _out_iterator )
67 | {
68 | std::vector< char > string_vector;
69 |
70 | int BLOCK = 1024;
71 |
72 | std::vector< char > buf;
73 | buf.reserve( BLOCK );
74 |
75 | int count;
76 | int string_len = 0;
77 |
78 | while( _in_iterator != _end_of_in )
79 | {
80 | buf.clear();
81 | count = 0;
82 |
83 | for(; ( ( _in_iterator != _end_of_in ) && ( count < BLOCK ) ); ++_in_iterator, count++ )
84 | buf.push_back( *_in_iterator );
85 |
86 | if( count < BLOCK )
87 | buf.resize( count );
88 |
89 | #pragma warning( push )
90 | #pragma warning( disable: 6309 )
91 | string_len = 0;
92 | Base64Decode( ( LPCSTR )&buf[ 0 ],
93 | buf.size(),
94 | NULL,
95 | &string_len
96 | );
97 | string_vector.resize( string_len );
98 | Base64Decode( ( LPCSTR )&buf[0],
99 | buf.size(),
100 | ( BYTE* )&string_vector[0],
101 | &string_len
102 | );
103 | #pragma warning( pop )
104 |
105 | std::copy( string_vector.begin(), string_vector.end(), _out_iterator );
106 | }
107 | }
108 | //***************************************************************************
109 | #endif
--------------------------------------------------------------------------------
/code/internal_basicfuncs.h:
--------------------------------------------------------------------------------
1 | #ifndef _870E69C1_1A78_42FD_93E5_5BA828575D99
2 | #define _870E69C1_1A78_42FD_93E5_5BA828575D99
3 | //**************************************************************************
4 | template< class T, class V >
5 | T value_init( T stream,
6 | unsigned long long max_block_len,
7 | BASIC_type** ret_info,
8 | inform_block* inf_block,
9 | length_block* len_block )
10 | {
11 | delete (*ret_info); // delete previously created "BASIC_type" object instance
12 |
13 | V* type = new V();
14 |
15 | type->inf_block = inf_block;
16 | type->len_block = len_block;
17 |
18 | type->add_warnings( inf_block );
19 | type->add_warnings( len_block );
20 |
21 | T end = type->decode_value( stream,
22 | ( len_block->is_indefinite_form ) ? max_block_len : len_block->length );
23 |
24 | (*ret_info) = type;
25 |
26 | return end;
27 | }
28 | //**************************************************************************
29 | template< typename T >
30 | T type_init( T stream,
31 | unsigned long long max_block_len,
32 | BASIC_type** ret_info )
33 | {
34 | (*ret_info) = new BASIC_type(); // in case we will not find any specific value decoding
35 |
36 | if( stream == T() )
37 | {
38 | sprintf_s( (*ret_info)->error, 255, "NULL stream is unaccepted" );
39 | return T();
40 | }
41 |
42 | if( !max_block_len ) // No error, just return empty type
43 | return T();
44 |
45 | //--------------------------------
46 | inform_block* inf_block = new inform_block();
47 |
48 | T end = inf_block->decode_value( stream, max_block_len );
49 | if( inf_block->error[ 0 ] != 0x00 )
50 | {
51 | sprintf_s( (*ret_info)->error, 255, inf_block->error );
52 |
53 | delete inf_block;
54 |
55 | return end;
56 | }
57 |
58 | max_block_len -= inf_block->block_length;
59 |
60 | length_block* len_block = new length_block();
61 |
62 | end = len_block->decode_value( end, max_block_len );
63 | if( len_block->error[ 0 ] != 0x00 ) // Give a chance to process in case of zero-length value block
64 | {
65 | sprintf_s( (*ret_info)->error, 255, len_block->error );
66 |
67 | delete inf_block;
68 | delete len_block;
69 |
70 | return end;
71 | }
72 |
73 | max_block_len -= len_block->block_length;
74 |
75 | // Check for usign indefinite length form in encoding for primitive types
76 | if( ( inf_block->tag_class == 1 ) &&
77 | ( len_block->is_indefinite_form ) )
78 | {
79 | switch( inf_block->tag_number )
80 | {
81 | case 1: // BOOLEAN
82 | case 2: // INTEGER
83 | case 5: // NULL
84 | case 6: // OBJECT IDENTIFIER
85 | case 9: // REAL
86 | case 14: // TIME
87 | case 23:
88 | case 24:
89 | case 31:
90 | case 32:
91 | case 33:
92 | case 34:
93 | sprintf_s( (*ret_info)->error, 255, "Indefinite length form used for primitive type" );
94 |
95 | delete inf_block;
96 | delete len_block;
97 |
98 | return T();
99 | default:
100 | ;
101 | }
102 | }
103 |
104 | //--------------------------------
105 |
106 | switch( inf_block->tag_class )
107 | {
108 | case 1: // UNIVERSAL
109 | if( ( inf_block->tag_number >= 37 ) && ( !inf_block->is_too_long_tag ) )
110 | {
111 | sprintf_s( (*ret_info)->error, 255, "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard" );
112 | return T();
113 | }
114 |
115 | switch( inf_block->tag_number )
116 | {
117 | case 0: // Hopefuly EOC_type (end-of-content)
118 | if( inf_block->is_constructed || len_block->length )
119 | {
120 | sprintf_s( (*ret_info)->error, 255, "Type [UNIVERSAL 0] is reserved" );
121 | return T();
122 | }
123 |
124 | return value_init< T, EOC_type >( end,
125 | max_block_len,
126 | ret_info,
127 | inf_block,
128 | len_block );
129 | break;
130 | case 1: // BOOLEAN
131 | return value_init< T, BOOLEAN_type >( end,
132 | max_block_len,
133 | ret_info,
134 | inf_block,
135 | len_block );
136 | break;
137 | case 2: // INTEGER
138 | return value_init< T, INTEGER_type >( end,
139 | max_block_len,
140 | ret_info,
141 | inf_block,
142 | len_block );
143 | break;
144 | case 3: // BITSTRING
145 | return value_init< T, BITSTRING_type >( end,
146 | max_block_len,
147 | ret_info,
148 | inf_block,
149 | len_block );
150 | break;
151 | case 4: // OCTETSTRING
152 | return value_init< T, OCTETSTRING_type >( end,
153 | max_block_len,
154 | ret_info,
155 | inf_block,
156 | len_block );
157 | break;
158 | case 5: // NULL
159 | return value_init< T, NULL_type >( end,
160 | max_block_len,
161 | ret_info,
162 | inf_block,
163 | len_block );
164 | break;
165 | case 6: // OBJECT IDENTIFIER
166 | return value_init< T, OID_type >( end,
167 | max_block_len,
168 | ret_info,
169 | inf_block,
170 | len_block );
171 | break;
172 | case 7: // OBJECT DESCRIPTOR
173 | return value_init< T, OBJECTDESCRIPTOR_type >( end,
174 | max_block_len,
175 | ret_info,
176 | inf_block,
177 | len_block );
178 | break;
179 | case 8: // EXTERNAL TYPE
180 | return value_init< T, EXTERNAL_type >( end,
181 | max_block_len,
182 | ret_info,
183 | inf_block,
184 | len_block );
185 | break;
186 | case 9: // REAL
187 | return value_init< T, REAL_type >( end,
188 | max_block_len,
189 | ret_info,
190 | inf_block,
191 | len_block );
192 | break;
193 | case 10: // ENUMERATED
194 | return value_init< T, ENUMERATED_type >( end,
195 | max_block_len,
196 | ret_info,
197 | inf_block,
198 | len_block );
199 | break;
200 | case 11: // EMBEDDED PDV
201 | return value_init< T, EMBEDDEDPDV_type >( end,
202 | max_block_len,
203 | ret_info,
204 | inf_block,
205 | len_block );
206 | break;
207 | case 12: // UTF8STRING
208 | return value_init< T, UTF8STRING_type >( end,
209 | max_block_len,
210 | ret_info,
211 | inf_block,
212 | len_block );
213 | break;
214 | case 13: // RELATIVE OBJECT IDENTIFIER
215 | return value_init< T, ROID_type >( end,
216 | max_block_len,
217 | ret_info,
218 | inf_block,
219 | len_block );
220 | break;
221 | case 14: // TIME
222 | return value_init< T, TIME_type >( end,
223 | max_block_len,
224 | ret_info,
225 | inf_block,
226 | len_block );
227 | break;
228 | case 15:
229 | sprintf_s( (*ret_info)->error, 255, "[UNIVERSAL 15] is reserved by ASN.1 standard" );
230 | return T();
231 |
232 | break;
233 | case 16: // SEQUENCE
234 | return value_init< T, SEQUENCE_type >( end,
235 | max_block_len,
236 | ret_info,
237 | inf_block,
238 | len_block );
239 | break;
240 | case 17: // SET
241 | return value_init< T, SET_type >( end,
242 | max_block_len,
243 | ret_info,
244 | inf_block,
245 | len_block );
246 | break;
247 | case 18: // NUMERICSTRING
248 | return value_init< T, NUMERICSTRING_type >( end,
249 | max_block_len,
250 | ret_info,
251 | inf_block,
252 | len_block );
253 | break;
254 | case 19: // PRINTABLESTRING
255 | return value_init< T, PRINTABLESTRING_type >( end,
256 | max_block_len,
257 | ret_info,
258 | inf_block,
259 | len_block );
260 | break;
261 | case 20: // TELETEXSTRING
262 | return value_init< T, TELETEXSTRING_type >( end,
263 | max_block_len,
264 | ret_info,
265 | inf_block,
266 | len_block );
267 | break;
268 | case 21: // VIDEOTEXSTRING
269 | return value_init< T, VIDEOTEXSTRING_type >( end,
270 | max_block_len,
271 | ret_info,
272 | inf_block,
273 | len_block );
274 | break;
275 | case 22: // IA5STRING
276 | return value_init< T, IA5STRING_type >( end,
277 | max_block_len,
278 | ret_info,
279 | inf_block,
280 | len_block );
281 | break;
282 | case 23: // UTCTIME
283 | return value_init< T, UTCTIME_type >( end,
284 | max_block_len,
285 | ret_info,
286 | inf_block,
287 | len_block );
288 | break;
289 | case 24: // GENERALIZEDTIME
290 | return value_init< T, GENERALIZEDTIME_type >( end,
291 | max_block_len,
292 | ret_info,
293 | inf_block,
294 | len_block );
295 | break;
296 | case 25: // GRAPHICSTRING
297 | return value_init< T, GRAPHICSTRING_type >( end,
298 | max_block_len,
299 | ret_info,
300 | inf_block,
301 | len_block );
302 | break;
303 | case 26: // VISIBLESTRING
304 | return value_init< T, VISIBLESTRING_type >( end,
305 | max_block_len,
306 | ret_info,
307 | inf_block,
308 | len_block );
309 | break;
310 | case 27: // GENERALSTRING
311 | return value_init< T, GENERALSTRING_type >( end,
312 | max_block_len,
313 | ret_info,
314 | inf_block,
315 | len_block );
316 | break;
317 | case 28: // UNIVERSALSTRING
318 | return value_init< T, UNIVERSALSTRING_type >( end,
319 | max_block_len,
320 | ret_info,
321 | inf_block,
322 | len_block );
323 | break;
324 | case 29: // CHARACTERSTRING
325 | return value_init< T, CHARACTERSTRING_type >( end,
326 | max_block_len,
327 | ret_info,
328 | inf_block,
329 | len_block );
330 | break;
331 | case 30: // BMPSTRING
332 | return value_init< T, BMPSTRING_type >( end,
333 | max_block_len,
334 | ret_info,
335 | inf_block,
336 | len_block );
337 | break;
338 | case 31: // DATE
339 | return value_init< T, DATE_type >( end,
340 | max_block_len,
341 | ret_info,
342 | inf_block,
343 | len_block );
344 | break;
345 | case 32: // TIME-OF-DAY
346 | return value_init< T, TIMEOFDAY_type >( end,
347 | max_block_len,
348 | ret_info,
349 | inf_block,
350 | len_block );
351 | break;
352 | case 33: // DATE-TIME
353 | return value_init< T, DATETIME_type >( end,
354 | max_block_len,
355 | ret_info,
356 | inf_block,
357 | len_block );
358 | break;
359 | case 34: // DURATION
360 | return value_init< T, DURATION_type >( end,
361 | max_block_len,
362 | ret_info,
363 | inf_block,
364 | len_block );
365 | break;
366 | case 35: // OID INTERNATIONALIZED
367 | return value_init< T, OIDINTER_type >( end,
368 | max_block_len,
369 | ret_info,
370 | inf_block,
371 | len_block );
372 | break;
373 | case 36: // RELATIVE OID INTERNATIONALIZED
374 | return value_init< T, ROIDINTER_type >( end,
375 | max_block_len,
376 | ret_info,
377 | inf_block,
378 | len_block );
379 | break;
380 | default: // Decoding for unknown types
381 | if( inf_block->is_constructed )
382 | return value_init< T, CONSTRUCTED_type >( end,
383 | max_block_len,
384 | ret_info,
385 | inf_block,
386 | len_block );
387 | else
388 | return value_init< T, PRIMITIVE_type< unsigned char* > >( end,
389 | max_block_len,
390 | ret_info,
391 | inf_block,
392 | len_block );
393 | }
394 | break;
395 | case 2: // APPLICATION
396 | case 3: // CONTEXT-SPECIFIC
397 | case 4: // PRIVATE
398 | default: // Decoding for unknown types
399 | if( inf_block->is_constructed )
400 | return value_init< T, CONSTRUCTED_type >( end,
401 | max_block_len,
402 | ret_info,
403 | inf_block,
404 | len_block );
405 | else
406 | return value_init< T, PRIMITIVE_type< unsigned char* > >( end,
407 | max_block_len,
408 | ret_info,
409 | inf_block,
410 | len_block );
411 | }
412 |
413 | return end;
414 | }
415 | //**************************************************************************
416 | #endif
--------------------------------------------------------------------------------
/code/internal_transformfuncs.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/internal_transformfuncs.h
--------------------------------------------------------------------------------
/code/internal_utf8stream.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Yury Strozhevsky .
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | */
26 | #ifndef _A5290D64_13FD_48B5_B618_C63F11DC2446
27 | #define _A5290D64_13FD_48B5_B618_C63F11DC2446
28 | //**************************************************************************
29 | // Came from http://www.rsdn.ru/forum/cpp/1948543.1.aspx
30 | //**************************************************************************
31 | /** Conversion facet that allows to read Unicode files in UTF-8 encoding */
32 | class utf8_conversion
33 | : public std::codecvt
34 | {
35 | protected:
36 |
37 | result do_in(std::mbstate_t& state,
38 | const char* from, const char* from_end, const char*& from_next,
39 | wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const;
40 |
41 | result do_out(std::mbstate_t& state,
42 | const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
43 | char* to, char* to_limit, char*& to_next) const;
44 |
45 | bool do_always_noconv() const throw() { return false; }
46 | int do_encoding() const throw() { return 2; }
47 | };
48 | //**************************************************************************
49 | typedef unsigned char uchar;
50 | //**************************************************************************
51 | inline unsigned char
52 | take_6_bits(unsigned value, size_t right_position)
53 | {
54 | return uchar((value >> right_position) & 63);
55 | }
56 | //**************************************************************************
57 | inline int
58 | most_signifant_bit_position(unsigned value)
59 | {
60 | int result(0);
61 |
62 | int half = 16;
63 | for(; half > 0; half >>= 1) {
64 | if (1u << (result + half) <= value ) result += half;
65 | }
66 | return result + 1;
67 | }
68 | //**************************************************************************
69 | utf8_conversion::result
70 | utf8_conversion::do_in(mbstate_t&,
71 | const char* from, const char* from_end, const char*& from_next,
72 | wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const
73 | {
74 | from_next = from;
75 | to_next = to;
76 |
77 | for(; to_next < to_limit && from_next < from_end; ++to_next) {
78 |
79 | if (uchar(*from_next) < 0x80) *to_next = uchar(*from_next++);
80 | else {
81 |
82 | // 111zxxxx : z = 0 xxxx are data bits
83 | int zero_bit_pos = most_signifant_bit_position(~*from_next);
84 | int extra_bytes = 7 - zero_bit_pos;
85 |
86 | if (from_end - from_next < extra_bytes + 1)
87 | return partial;
88 |
89 | *to_next = uchar(*from_next++) & ( ( ( 1 << zero_bit_pos ) - 1) - 1);
90 |
91 | for (;extra_bytes--; ++from_next) {
92 | *to_next = *to_next << 6 | uchar(*from_next) & 63;
93 | }
94 | }
95 | }
96 | return ok;
97 | }
98 | //**************************************************************************
99 | utf8_conversion::result
100 | utf8_conversion::do_out(mbstate_t&,
101 | const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
102 | char* to, char* to_limit, char*& to_next) const
103 | {
104 | from_next = from;
105 | to_next = to;
106 |
107 | for (;from_next < from_end; ++from_next) {
108 |
109 | unsigned symbol = *from_next;
110 |
111 | if (symbol < 0x7F) {
112 | if (to_next < to_limit)
113 | *to_next++ = (unsigned char)symbol;
114 | else
115 | return ok;
116 | } else {
117 |
118 | int msb_pos = most_signifant_bit_position(symbol);
119 | int extra_bytes = msb_pos / 6;
120 |
121 | if (to_limit - to_next >= extra_bytes + 1) {
122 |
123 | *to_next = uchar(0xFF80 >> extra_bytes);
124 | *to_next++ |= take_6_bits(symbol, extra_bytes*6);
125 |
126 | for(;extra_bytes--;)
127 | *to_next++ = 0x80 | take_6_bits(symbol, extra_bytes*6);
128 | }
129 | else
130 | return ok;
131 | }
132 | }
133 | return ok;
134 | }
135 | //**************************************************************************
136 | namespace std
137 | {
138 | template inline
140 | basic_ostream<_Elem, _Traits>&
141 | __CLRCALL_OR_CDECL endlu(basic_ostream<_Elem, _Traits>& _Ostr)
142 | { // insert newline and flush stream
143 | _Ostr.put(_Ostr.widen('\r'));
144 | _Ostr.put(_Ostr.widen('\n'));
145 | _Ostr.flush();
146 | return (_Ostr);
147 | }
148 | };
149 | //**************************************************************************
150 | class no_conversion
151 | : public std::codecvt
152 | {
153 | protected:
154 |
155 | result do_in(std::mbstate_t& state,
156 | const char* from, const char* from_end, const char*& from_next,
157 | wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const { return noconv; };
158 |
159 | result do_out(std::mbstate_t& state,
160 | const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next,
161 | char* to, char* to_limit, char*& to_next) const { return noconv; };
162 |
163 | bool do_always_noconv() const throw() { return true; }
164 | int do_encoding() const throw() { return 2; }
165 | };
166 | //**************************************************************************
167 | #endif
--------------------------------------------------------------------------------
/code/main_file.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Yury Strozhevsky .
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 | * SUCH DAMAGE.
25 | */
26 |
27 | #include
28 |
29 | #include
30 | #include
31 |
32 | #include
33 | #include
34 |
35 | #import
36 |
37 | #include
38 | #include
39 | #include