/* asn1Coding.c --- program to generate a DER coding of an ASN1 definition. * Copyright (C) 2002-2014 Free Software Foundation, Inc. * * This file is part of LIBTASN1. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include #include #define program_name "asn1Coding" /* This feature is available in gcc versions 2.5 and later. */ #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) #define ATTR_NO_RETRUN #else #define ATTR_NO_RETRUN __attribute__ ((__noreturn__)) #endif ATTR_NO_RETRUN static void usage (int status) { if (status != EXIT_SUCCESS) fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else { printf ("\ Usage: %s [OPTION] DEFINITIONS ASSIGNMENTS\n", program_name); printf ("\ Generates a DER encoding of ASN.1 DEFINITIONS file\n\ and ASSIGNMENTS file with value assignments.\n\ \n"); printf ("\ Mandatory arguments to long options are mandatory for short options too.\n\ -c, --check checks the syntax only\n\ -o, --output=FILE output file\n\ -h, --help display this help and exit\n\ -v, --version output version information and exit\n"); printf ("Report bugs to "PACKAGE_BUGREPORT); } exit (status); } #define ASSIGNMENT_SUCCESS 1 #define ASSIGNMENT_ERROR 2 #define ASSIGNMENT_EOF 3 static int readAssignment (FILE * file, char *varName, char *value) { int ret; ret = fscanf (file, "%s", varName); if (ret == EOF) return ASSIGNMENT_EOF; if (!strcmp (varName, "''")) varName[0] = 0; ret = fscanf (file, "%s", value); if (ret == EOF) return ASSIGNMENT_ERROR; return ASSIGNMENT_SUCCESS; } static void createFileName (char *inputFileName, char **outputFileName) { char *char_p, *slash_p, *dot_p; /* searching the last '/' and '.' in inputFileAssignmentName */ char_p = inputFileName; slash_p = inputFileName; while ((char_p = strchr (char_p, '/'))) { char_p++; slash_p = char_p; } char_p = slash_p; dot_p = inputFileName + strlen (inputFileName); while ((char_p = strchr (char_p, '.'))) { dot_p = char_p; char_p++; } /* outputFileName= inputFileName + .out */ *outputFileName = (char *) malloc (dot_p - inputFileName + 1 + strlen (".out")); if (*outputFileName == NULL) { fprintf(stderr, "Memory error\n"); exit(1); } memcpy (*outputFileName, inputFileName, dot_p - inputFileName); (*outputFileName)[dot_p - inputFileName] = 0; strcat (*outputFileName, ".out"); return; } int main (int argc, char *argv[]) { static const struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {"check", no_argument, 0, 'c'}, {"output", required_argument, 0, 'o'}, {0, 0, 0, 0} }; int option_index = 0; int option_result; char *outputFileName = NULL; char *inputFileAsnName = NULL; char *inputFileAssignmentName = NULL; int checkSyntaxOnly = 0; asn1_node definitions = NULL; asn1_node structure = NULL; char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; int asn1_result = ASN1_SUCCESS; FILE *outputFile; FILE *inputFile; char varName[1024]; char value[1024]; unsigned char *der = NULL; int der_len; int k; int last_ra; opterr = 0; /* disable error messages from getopt */ while (1) { option_result = getopt_long (argc, argv, "hvco:", long_options, &option_index); if (option_result == -1) break; switch (option_result) { case 'h': /* HELP */ free (outputFileName); usage (EXIT_SUCCESS); break; case 'v': /* VERSION */ printf(program_name" "PACKAGE" " VERSION"\n"); printf("Copyright (C) 2017-2019 Free Software Foundation, Inc.\n\n"); printf("Written by Fabio Fiorina\n"); free (outputFileName); exit (0); break; case 'c': /* CHECK SYNTAX */ checkSyntaxOnly = 1; break; case 'o': /* OUTPUT */ assert(optarg != NULL); outputFileName = strdup(optarg); if (outputFileName == NULL) { fprintf(stderr, "Memory error\n"); exit(1); } break; case '?': /* UNKNOW OPTION */ free (outputFileName); fprintf (stderr, "asn1Coding: option '%s' not recognized or without argument.\n\n", argv[optind - 1]); usage (EXIT_FAILURE); break; default: fprintf (stderr, "asn1Coding: ?? getopt returned character code Ox%x ??\n", (unsigned)option_result); } } if (optind == argc || optind == argc - 1) { free (outputFileName); fputs ("asn1Coding: input files missing\n", stderr); usage (EXIT_FAILURE); } inputFileAsnName = strdup(argv[optind]); if (inputFileAsnName == NULL) { fprintf(stderr, "Memory error\n"); exit(1); } inputFileAssignmentName = strdup(argv[optind+1]); if (inputFileAssignmentName == NULL) { fprintf(stderr, "Memory error\n"); exit(1); } asn1_result = asn1_parser2tree (inputFileAsnName, &definitions, errorDescription); switch (asn1_result) { case ASN1_SUCCESS: fputs ("Parse: done.\n", stderr); break; case ASN1_FILE_NOT_FOUND: fprintf (stderr, "asn1Coding: FILE %s NOT FOUND\n", inputFileAsnName); break; case ASN1_SYNTAX_ERROR: case ASN1_IDENTIFIER_NOT_FOUND: case ASN1_NAME_TOO_LONG: fprintf (stderr, "asn1Coding: %s\n", errorDescription); break; default: fprintf (stderr, "libtasn1 ERROR: %s\n", asn1_strerror (asn1_result)); } if (asn1_result != ASN1_SUCCESS) { free (inputFileAsnName); free (inputFileAssignmentName); exit (1); } inputFile = fopen (inputFileAssignmentName, "r"); if (inputFile == NULL) { fprintf (stderr, "asn1Coding: file '%s' not found\n", inputFileAssignmentName); free (inputFileAsnName); free (inputFileAssignmentName); exit (1); } putc ('\n', stderr); while ((last_ra = readAssignment (inputFile, varName, value)) == ASSIGNMENT_SUCCESS) { fprintf (stderr, "var=%s, value=%s\n", varName, value); if (structure == NULL) { asn1_result = asn1_create_element (definitions, value, &structure); } else { if (strcmp(value, "(NULL)") == 0) asn1_result = asn1_write_value (structure, varName, NULL, 0); else asn1_result = asn1_write_value (structure, varName, value, 0); } if (asn1_result != ASN1_SUCCESS) { fprintf (stderr, "libtasn1 ERROR: %s\n", asn1_strerror (asn1_result)); asn1_delete_structure (&definitions); asn1_delete_structure (&structure); free (inputFileAsnName); free (inputFileAssignmentName); fclose (inputFile); exit (1); } } if (last_ra != ASSIGNMENT_EOF) { fprintf (stderr, "asn1Coding: error reading assignment file\n"); exit (1); } fclose (inputFile); putc ('\n', stderr); asn1_print_structure (stderr, structure, "", ASN1_PRINT_NAME_TYPE_VALUE); der_len = 0; asn1_result = asn1_der_coding (structure, "", NULL, &der_len, errorDescription); if (asn1_result == ASN1_MEM_ERROR) { der = malloc (der_len); if (der == NULL) { fprintf(stderr, "Memory error\n"); exit(1); } asn1_result = asn1_der_coding (structure, "", der, &der_len, errorDescription); } fprintf (stderr, "\nCoding: %s\n\n", asn1_strerror (asn1_result)); if (asn1_result != ASN1_SUCCESS) { fprintf (stderr, "asn1Coding: %s\n", errorDescription); free (der); asn1_delete_structure (&definitions); asn1_delete_structure (&structure); free (inputFileAsnName); free (inputFileAssignmentName); exit (1); } /* Print the 'Certificate1' DER encoding */ fprintf (stderr, "-----------------\nNumber of bytes=%i\n", der_len); for (k = 0; k < der_len; k++) fprintf (stderr, "%02x ", der[k]); fputs ("\n-----------------\n", stderr); asn1_delete_structure (&definitions); asn1_delete_structure (&structure); if (!checkSyntaxOnly) { if (outputFileName == NULL) createFileName (inputFileAssignmentName, &outputFileName); fprintf (stderr, "\nOutputFile=%s\n", outputFileName); outputFile = fopen (outputFileName, "w"); if (outputFile == NULL) { fprintf (stderr, "asn1Coding: output file '%s' not available\n", outputFileName); free (der); free (inputFileAsnName); free (inputFileAssignmentName); free (outputFileName); exit (1); } for (k = 0; k < der_len; k++) fprintf (outputFile, "%c", der[k]); fclose (outputFile); fputs ("\nWriting: done.\n", stderr); } free (der); free (inputFileAsnName); free (inputFileAssignmentName); free (outputFileName); exit (0); }