Upgrade to libtasn1 4.19.0
[platform/upstream/libtasn1.git] / src / asn1Decoding.c
1 /* asn1Decoding.c ---  program to generate an ASN1 type from a DER coding.
2  * Copyright (C) 2002-2022 Free Software Foundation, Inc.
3  *
4  * This file is part of LIBTASN1.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <getopt.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #include <libtasn1.h>
32
33 #include "benchmark.h"
34
35 #include "progname.h"
36 #include "read-file.h"
37 #include "version-etc.h"
38
39 static int decode (asn1_node definitions, const char *typeName, void *der,
40                    int der_len, int benchmark, int strict);
41
42 /* This feature is available in gcc versions 2.5 and later.  */
43 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
44 # define ATTR_NO_RETRUN
45 #else
46 # define ATTR_NO_RETRUN __attribute__ ((__noreturn__))
47 #endif
48
49 ATTR_NO_RETRUN static void
50 usage (int status)
51 {
52   if (status != EXIT_SUCCESS)
53     fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
54   else
55     {
56       printf ("\
57 Usage: %s [OPTION] DEFINITIONS ENCODED ASN1TYPE\n", program_name);
58       printf ("\
59 Decodes DER data in ENCODED file, for the ASN1TYPE element\n\
60 described in ASN.1 DEFINITIONS file, and print decoded structures.\n\
61 \n");
62       printf ("\
63   -b, --benchmark       perform a benchmark on decoding\n\
64   -s, --strict          use strict DER decoding\n\
65   -t, --no-time-strict  use strict DER decoding but not in time fields\n\
66   -h, --help            display this help and exit\n\
67   -v, --version         output version information and exit\n");
68       emit_bug_reporting_address ();
69     }
70   exit (status);
71 }
72
73 int
74 main (int argc, char *argv[])
75 {
76   static const struct option long_options[] = {
77     {"help", no_argument, 0, 'h'},
78     {"strict", no_argument, 0, 's'},
79     {"no-time-strict", no_argument, 0, 't'},
80     {"debug", no_argument, 0, 'd'},
81     {"benchmark", no_argument, 0, 'b'},
82     {"version", no_argument, 0, 'v'},
83     {0, 0, 0, 0}
84   };
85   int option_index = 0;
86   int option_result;
87   char *inputFileAsnName = NULL;
88   char *inputFileDerName = NULL;
89   char *typeName = NULL;
90   asn1_node definitions = NULL;
91   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
92   int asn1_result = ASN1_SUCCESS;
93   unsigned char *der;
94   int der_len = 0, benchmark = 0;
95   int flags = 0, debug = 0;
96   /* FILE *outputFile; */
97
98   set_program_name (argv[0]);
99
100   opterr = 0;                   /* disable error messages from getopt */
101
102   while (1)
103     {
104
105       option_result =
106         getopt_long (argc, argv, "hbdsvtc", long_options, &option_index);
107
108       if (option_result == -1)
109         break;
110
111       switch (option_result)
112         {
113         case 'h':               /* HELP */
114           usage (EXIT_SUCCESS);
115           break;
116         case 'b':
117           benchmark = 1;
118           break;
119         case 'd':
120           debug = 1;
121           break;
122         case 's':
123         case 't':
124           flags |= ASN1_DECODE_FLAG_STRICT_DER;
125           if (option_result == 't')
126             flags |= ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME;
127           break;
128         case 'v':               /* VERSION */
129           version_etc (stdout, program_name, PACKAGE, VERSION,
130                        "Fabio Fiorina", NULL);
131           exit (0);
132           break;
133         case '?':               /* UNKNOW OPTION */
134           fprintf (stderr,
135                    "asn1Decoding: option '%s' not recognized or without argument.\n\n",
136                    argv[optind - 1]);
137           usage (EXIT_FAILURE);
138           break;
139         default:
140           fprintf (stderr,
141                    "asn1Decoding: ?? getopt returned character code Ox%x ??\n",
142                    (unsigned) option_result);
143         }
144     }
145
146   if (optind == argc || optind == argc - 1 || optind == argc - 2)
147     {
148       fprintf (stderr, "asn1Decoding: input files or ASN.1 type "
149                "name missing\n");
150       usage (EXIT_FAILURE);
151     }
152
153   inputFileAsnName = strdup (argv[optind]);
154   inputFileDerName = strdup (argv[optind + 1]);
155   typeName = strdup (argv[optind + 2]);
156
157   if (!(inputFileAsnName && inputFileDerName && typeName))
158     {
159       fprintf (stderr, "allocation failed\n");
160       free (inputFileAsnName);
161       free (inputFileDerName);
162       free (typeName);
163       exit (1);
164     }
165
166   asn1_result =
167     asn1_parser2tree (inputFileAsnName, &definitions, errorDescription);
168
169   switch (asn1_result)
170     {
171     case ASN1_SUCCESS:
172       fprintf (stderr, "Parse: done.\n");
173       break;
174     case ASN1_FILE_NOT_FOUND:
175       fprintf (stderr, "asn1Decoding: FILE %s NOT FOUND\n", inputFileAsnName);
176       break;
177     case ASN1_SYNTAX_ERROR:
178     case ASN1_IDENTIFIER_NOT_FOUND:
179     case ASN1_NAME_TOO_LONG:
180       fprintf (stderr, "asn1Decoding: %s\n", errorDescription);
181       break;
182     default:
183       fprintf (stderr, "libtasn1 ERROR: %s\n", asn1_strerror (asn1_result));
184     }
185
186   if (asn1_result != ASN1_SUCCESS)
187     {
188       free (inputFileAsnName);
189       free (inputFileDerName);
190       free (typeName);
191       exit (1);
192     }
193
194
195   {
196     size_t tmplen;
197     der = (unsigned char *) read_file (inputFileDerName, RF_BINARY, &tmplen);
198     der_len = tmplen;
199   }
200
201   /* read_binary_file() returns a buffer with more data than required,
202    * with this reallocation we ensure that memory accesses outside the
203    * boundaries are detected */
204   if (der != NULL && debug != 0)
205     der = realloc (der, der_len);
206
207   if (der == NULL)
208     {
209       fprintf (stderr, "asn1Decoding: could not read '%s'\n",
210                inputFileDerName);
211       asn1_delete_structure (&definitions);
212
213       free (inputFileAsnName);
214       free (inputFileDerName);
215       free (typeName);
216       exit (1);
217     }
218
219  /*****************************************/
220   /* ONLY FOR TEST                         */
221  /*****************************************/
222   /*
223      der_len=0;
224      outputFile=fopen("data.p12","w");
225      while(fscanf(inputFile,"%c",der+der_len) != EOF)
226      {
227      if((der_len>=0x11) && (der_len<=(0xe70)))
228      fprintf(outputFile,"%c",der[der_len]);
229      der_len++;
230      }
231      fclose(outputFile);
232      fclose(inputFile);
233    */
234
235   if (decode (definitions, typeName, der, der_len, benchmark, flags) !=
236       ASN1_SUCCESS)
237     {
238       asn1_delete_structure (&definitions);
239       free (inputFileAsnName);
240       free (inputFileDerName);
241       free (typeName);
242       free (der);
243       exit (1);
244     }
245
246   asn1_delete_structure (&definitions);
247
248   free (der);
249
250   free (inputFileAsnName);
251   free (inputFileDerName);
252   free (typeName);
253
254   if (asn1_result != ASN1_SUCCESS)
255     exit (1);
256
257   exit (0);
258 }
259
260 static int
261 simple_decode (asn1_node definitions, const char *typeName, void *der,
262                int der_len, int benchmark, int flags)
263 {
264
265   int asn1_result;
266   asn1_node structure = NULL;
267   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
268
269   asn1_result = asn1_create_element (definitions, typeName, &structure);
270
271   /* asn1_print_structure(stdout,structure,"",ASN1_PRINT_ALL); */
272
273
274   if (asn1_result != ASN1_SUCCESS)
275     {
276       fprintf (stderr, "Structure creation: %s\n",
277                asn1_strerror (asn1_result));
278       asn1_delete_structure (&structure);
279       return asn1_result;
280     }
281
282   if (flags != 0)
283     asn1_result =
284       asn1_der_decoding2 (&structure, der, &der_len, flags, errorDescription);
285   else
286     asn1_result =
287       asn1_der_decoding (&structure, der, der_len, errorDescription);
288
289   if (!benchmark)
290     fprintf (stderr, "\nDecoding: %s\n", asn1_strerror (asn1_result));
291   if (asn1_result != ASN1_SUCCESS)
292     {
293       fprintf (stderr, "asn1Decoding: %s\n", errorDescription);
294       asn1_delete_structure (&structure);
295       return asn1_result;
296     }
297
298   if (!benchmark)
299     {
300       fprintf (stderr, "\nDECODING RESULT:\n");
301       asn1_print_structure (stdout, structure, "",
302                             ASN1_PRINT_NAME_TYPE_VALUE);
303     }
304   asn1_delete_structure (&structure);
305   return ASN1_SUCCESS;
306 }
307
308 static int
309 decode (asn1_node definitions, const char *typeName, void *der, int der_len,
310         int benchmark, int flags)
311 {
312   struct benchmark_st st;
313
314   if (benchmark == 0)
315     return simple_decode (definitions, typeName, der, der_len, benchmark,
316                           flags);
317   else
318     {
319       start_benchmark (&st);
320
321       do
322         {
323           simple_decode (definitions, typeName, der, der_len, benchmark,
324                          flags);
325           st.size++;
326         }
327       while (benchmark_must_finish == 0);
328
329       stop_benchmark (&st, "structures");
330       fprintf (stdout, "\n");
331
332     }
333   return ASN1_SUCCESS;
334 }