[BACK]Return to asn1pars.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/asn1pars.c, Revision 1.1

1.1     ! jsing       1: /* $OpenBSD: asn1pars.c,v 1.27 2014/07/14 00:35:10 deraadt Exp $ */
        !             2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This package is an SSL implementation written
        !             6:  * by Eric Young (eay@cryptsoft.com).
        !             7:  * The implementation was written so as to conform with Netscapes SSL.
        !             8:  *
        !             9:  * This library is free for commercial and non-commercial use as long as
        !            10:  * the following conditions are aheared to.  The following conditions
        !            11:  * apply to all code found in this distribution, be it the RC4, RSA,
        !            12:  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
        !            13:  * included with this distribution is covered by the same copyright terms
        !            14:  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
        !            15:  *
        !            16:  * Copyright remains Eric Young's, and as such any Copyright notices in
        !            17:  * the code are not to be removed.
        !            18:  * If this package is used in a product, Eric Young should be given attribution
        !            19:  * as the author of the parts of the library used.
        !            20:  * This can be in the form of a textual message at program startup or
        !            21:  * in documentation (online or textual) provided with the package.
        !            22:  *
        !            23:  * Redistribution and use in source and binary forms, with or without
        !            24:  * modification, are permitted provided that the following conditions
        !            25:  * are met:
        !            26:  * 1. Redistributions of source code must retain the copyright
        !            27:  *    notice, this list of conditions and the following disclaimer.
        !            28:  * 2. Redistributions in binary form must reproduce the above copyright
        !            29:  *    notice, this list of conditions and the following disclaimer in the
        !            30:  *    documentation and/or other materials provided with the distribution.
        !            31:  * 3. All advertising materials mentioning features or use of this software
        !            32:  *    must display the following acknowledgement:
        !            33:  *    "This product includes cryptographic software written by
        !            34:  *     Eric Young (eay@cryptsoft.com)"
        !            35:  *    The word 'cryptographic' can be left out if the rouines from the library
        !            36:  *    being used are not cryptographic related :-).
        !            37:  * 4. If you include any Windows specific code (or a derivative thereof) from
        !            38:  *    the apps directory (application code) you must include an acknowledgement:
        !            39:  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
        !            40:  *
        !            41:  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
        !            42:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            43:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            44:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            45:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            46:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            47:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            48:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            49:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            50:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            51:  * SUCH DAMAGE.
        !            52:  *
        !            53:  * The licence and distribution terms for any publically available version or
        !            54:  * derivative of this code cannot be changed.  i.e. this code cannot simply be
        !            55:  * copied and put under another distribution licence
        !            56:  * [including the GNU Public Licence.]
        !            57:  */
        !            58:
        !            59: /* A nice addition from Dr Stephen Henson <steve@openssl.org> to
        !            60:  * add the -strparse option which parses nested binary structures
        !            61:  */
        !            62:
        !            63: #include <stdio.h>
        !            64: #include <stdlib.h>
        !            65: #include <limits.h>
        !            66: #include <string.h>
        !            67:
        !            68: #include "apps.h"
        !            69:
        !            70: #include <openssl/err.h>
        !            71: #include <openssl/evp.h>
        !            72: #include <openssl/pem.h>
        !            73: #include <openssl/x509.h>
        !            74:
        !            75: /* -inform arg - input format - default PEM (DER or PEM)
        !            76:  * -in arg     - input file - default stdin
        !            77:  * -i          - indent the details by depth
        !            78:  * -offset     - where in the file to start
        !            79:  * -length     - how many bytes to use
        !            80:  * -oid file   - extra oid description file
        !            81:  */
        !            82:
        !            83: int asn1parse_main(int, char **);
        !            84:
        !            85: static int do_generate(BIO * bio, char *genstr, char *genconf, BUF_MEM * buf);
        !            86:
        !            87: int
        !            88: asn1parse_main(int argc, char **argv)
        !            89: {
        !            90:        int i, badops = 0, offset = 0, ret = 1, j;
        !            91:        unsigned int length = 0;
        !            92:        long num, tmplen;
        !            93:        BIO *in = NULL, *out = NULL, *b64 = NULL, *derout = NULL;
        !            94:        int informat, indent = 0, noout = 0, dump = 0;
        !            95:        char *infile = NULL, *str = NULL, *prog, *oidfile = NULL, *derfile = NULL;
        !            96:        char *genstr = NULL, *genconf = NULL;
        !            97:        const char *errstr = NULL;
        !            98:        unsigned char *tmpbuf;
        !            99:        const unsigned char *ctmpbuf;
        !           100:        BUF_MEM *buf = NULL;
        !           101:        STACK_OF(OPENSSL_STRING) * osk = NULL;
        !           102:        ASN1_TYPE *at = NULL;
        !           103:
        !           104:        informat = FORMAT_PEM;
        !           105:
        !           106:        prog = argv[0];
        !           107:        argc--;
        !           108:        argv++;
        !           109:        if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
        !           110:                BIO_printf(bio_err, "Memory allocation failure\n");
        !           111:                goto end;
        !           112:        }
        !           113:        while (argc >= 1) {
        !           114:                if (strcmp(*argv, "-inform") == 0) {
        !           115:                        if (--argc < 1)
        !           116:                                goto bad;
        !           117:                        informat = str2fmt(*(++argv));
        !           118:                } else if (strcmp(*argv, "-in") == 0) {
        !           119:                        if (--argc < 1)
        !           120:                                goto bad;
        !           121:                        infile = *(++argv);
        !           122:                } else if (strcmp(*argv, "-out") == 0) {
        !           123:                        if (--argc < 1)
        !           124:                                goto bad;
        !           125:                        derfile = *(++argv);
        !           126:                } else if (strcmp(*argv, "-i") == 0) {
        !           127:                        indent = 1;
        !           128:                } else if (strcmp(*argv, "-noout") == 0)
        !           129:                        noout = 1;
        !           130:                else if (strcmp(*argv, "-oid") == 0) {
        !           131:                        if (--argc < 1)
        !           132:                                goto bad;
        !           133:                        oidfile = *(++argv);
        !           134:                } else if (strcmp(*argv, "-offset") == 0) {
        !           135:                        if (--argc < 1)
        !           136:                                goto bad;
        !           137:                        offset = strtonum(*(++argv), 0, INT_MAX, &errstr);
        !           138:                        if (errstr)
        !           139:                                goto bad;
        !           140:                } else if (strcmp(*argv, "-length") == 0) {
        !           141:                        if (--argc < 1)
        !           142:                                goto bad;
        !           143:                        length = strtonum(*(++argv), 1, UINT_MAX, &errstr);
        !           144:                        if (errstr)
        !           145:                                goto bad;
        !           146:                } else if (strcmp(*argv, "-dump") == 0) {
        !           147:                        dump = -1;
        !           148:                } else if (strcmp(*argv, "-dlimit") == 0) {
        !           149:                        if (--argc < 1)
        !           150:                                goto bad;
        !           151:                        dump = strtonum(*(++argv), 1, INT_MAX, &errstr);
        !           152:                        if (errstr)
        !           153:                                goto bad;
        !           154:                } else if (strcmp(*argv, "-strparse") == 0) {
        !           155:                        if (--argc < 1)
        !           156:                                goto bad;
        !           157:                        sk_OPENSSL_STRING_push(osk, *(++argv));
        !           158:                } else if (strcmp(*argv, "-genstr") == 0) {
        !           159:                        if (--argc < 1)
        !           160:                                goto bad;
        !           161:                        genstr = *(++argv);
        !           162:                } else if (strcmp(*argv, "-genconf") == 0) {
        !           163:                        if (--argc < 1)
        !           164:                                goto bad;
        !           165:                        genconf = *(++argv);
        !           166:                } else {
        !           167:                        BIO_printf(bio_err, "unknown option %s\n", *argv);
        !           168:                        badops = 1;
        !           169:                        break;
        !           170:                }
        !           171:                argc--;
        !           172:                argv++;
        !           173:        }
        !           174:
        !           175:        if (badops) {
        !           176: bad:
        !           177:                BIO_printf(bio_err, "%s [options] <infile\n", prog);
        !           178:                BIO_printf(bio_err, "where options are\n");
        !           179:                BIO_printf(bio_err, " -inform arg   input format - one of DER PEM\n");
        !           180:                BIO_printf(bio_err, " -in arg       input file\n");
        !           181:                BIO_printf(bio_err, " -out arg      output file (output format is always DER\n");
        !           182:                BIO_printf(bio_err, " -noout arg    don't produce any output\n");
        !           183:                BIO_printf(bio_err, " -offset arg   offset into file\n");
        !           184:                BIO_printf(bio_err, " -length arg   length of section in file\n");
        !           185:                BIO_printf(bio_err, " -i            indent entries\n");
        !           186:                BIO_printf(bio_err, " -dump         dump unknown data in hex form\n");
        !           187:                BIO_printf(bio_err, " -dlimit arg   dump the first arg bytes of unknown data in hex form\n");
        !           188:                BIO_printf(bio_err, " -oid file     file of extra oid definitions\n");
        !           189:                BIO_printf(bio_err, " -strparse offset\n");
        !           190:                BIO_printf(bio_err, "               a series of these can be used to 'dig' into multiple\n");
        !           191:                BIO_printf(bio_err, "               ASN1 blob wrappings\n");
        !           192:                BIO_printf(bio_err, " -genstr str   string to generate ASN1 structure from\n");
        !           193:                BIO_printf(bio_err, " -genconf file file to generate ASN1 structure from\n");
        !           194:                goto end;
        !           195:        }
        !           196:        ERR_load_crypto_strings();
        !           197:
        !           198:        in = BIO_new(BIO_s_file());
        !           199:        out = BIO_new(BIO_s_file());
        !           200:        if ((in == NULL) || (out == NULL)) {
        !           201:                ERR_print_errors(bio_err);
        !           202:                goto end;
        !           203:        }
        !           204:        BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
        !           205:
        !           206:        if (oidfile != NULL) {
        !           207:                if (BIO_read_filename(in, oidfile) <= 0) {
        !           208:                        BIO_printf(bio_err, "problems opening %s\n", oidfile);
        !           209:                        ERR_print_errors(bio_err);
        !           210:                        goto end;
        !           211:                }
        !           212:                OBJ_create_objects(in);
        !           213:        }
        !           214:        if (infile == NULL)
        !           215:                BIO_set_fp(in, stdin, BIO_NOCLOSE);
        !           216:        else {
        !           217:                if (BIO_read_filename(in, infile) <= 0) {
        !           218:                        perror(infile);
        !           219:                        goto end;
        !           220:                }
        !           221:        }
        !           222:
        !           223:        if (derfile) {
        !           224:                if (!(derout = BIO_new_file(derfile, "wb"))) {
        !           225:                        BIO_printf(bio_err, "problems opening %s\n", derfile);
        !           226:                        ERR_print_errors(bio_err);
        !           227:                        goto end;
        !           228:                }
        !           229:        }
        !           230:        if ((buf = BUF_MEM_new()) == NULL)
        !           231:                goto end;
        !           232:        if (!BUF_MEM_grow(buf, BUFSIZ * 8))
        !           233:                goto end;       /* Pre-allocate :-) */
        !           234:
        !           235:        if (genstr || genconf) {
        !           236:                num = do_generate(bio_err, genstr, genconf, buf);
        !           237:                if (num < 0) {
        !           238:                        ERR_print_errors(bio_err);
        !           239:                        goto end;
        !           240:                }
        !           241:        } else {
        !           242:
        !           243:                if (informat == FORMAT_PEM) {
        !           244:                        BIO *tmp;
        !           245:
        !           246:                        if ((b64 = BIO_new(BIO_f_base64())) == NULL)
        !           247:                                goto end;
        !           248:                        BIO_push(b64, in);
        !           249:                        tmp = in;
        !           250:                        in = b64;
        !           251:                        b64 = tmp;
        !           252:                }
        !           253:                num = 0;
        !           254:                for (;;) {
        !           255:                        if (!BUF_MEM_grow(buf, (int) num + BUFSIZ))
        !           256:                                goto end;
        !           257:                        i = BIO_read(in, &(buf->data[num]), BUFSIZ);
        !           258:                        if (i <= 0)
        !           259:                                break;
        !           260:                        num += i;
        !           261:                }
        !           262:        }
        !           263:        str = buf->data;
        !           264:
        !           265:        /* If any structs to parse go through in sequence */
        !           266:
        !           267:        if (sk_OPENSSL_STRING_num(osk)) {
        !           268:                tmpbuf = (unsigned char *) str;
        !           269:                tmplen = num;
        !           270:                for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {
        !           271:                        ASN1_TYPE *atmp;
        !           272:                        int typ;
        !           273:                        j = strtonum(sk_OPENSSL_STRING_value(osk, i),
        !           274:                            1, INT_MAX, &errstr);
        !           275:                        if (errstr) {
        !           276:                                BIO_printf(bio_err,
        !           277:                                    "'%s' is an invalid number: %s\n",
        !           278:                                    sk_OPENSSL_STRING_value(osk, i), errstr);
        !           279:                                continue;
        !           280:                        }
        !           281:                        tmpbuf += j;
        !           282:                        tmplen -= j;
        !           283:                        atmp = at;
        !           284:                        ctmpbuf = tmpbuf;
        !           285:                        at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);
        !           286:                        ASN1_TYPE_free(atmp);
        !           287:                        if (!at) {
        !           288:                                BIO_printf(bio_err, "Error parsing structure\n");
        !           289:                                ERR_print_errors(bio_err);
        !           290:                                goto end;
        !           291:                        }
        !           292:                        typ = ASN1_TYPE_get(at);
        !           293:                        if ((typ == V_ASN1_OBJECT) ||
        !           294:                            (typ == V_ASN1_NULL)) {
        !           295:                                BIO_printf(bio_err, "Can't parse %s type\n",
        !           296:                                    typ == V_ASN1_NULL ? "NULL" : "OBJECT");
        !           297:                                ERR_print_errors(bio_err);
        !           298:                                goto end;
        !           299:                        }
        !           300:                        /* hmm... this is a little evil but it works */
        !           301:                        tmpbuf = at->value.asn1_string->data;
        !           302:                        tmplen = at->value.asn1_string->length;
        !           303:                }
        !           304:                str = (char *) tmpbuf;
        !           305:                num = tmplen;
        !           306:        }
        !           307:        if (offset >= num) {
        !           308:                BIO_printf(bio_err, "Error: offset too large\n");
        !           309:                goto end;
        !           310:        }
        !           311:        num -= offset;
        !           312:
        !           313:        if ((length == 0) || ((long) length > num))
        !           314:                length = (unsigned int) num;
        !           315:        if (derout) {
        !           316:                if (BIO_write(derout, str + offset, length) != (int) length) {
        !           317:                        BIO_printf(bio_err, "Error writing output\n");
        !           318:                        ERR_print_errors(bio_err);
        !           319:                        goto end;
        !           320:                }
        !           321:        }
        !           322:        if (!noout &&
        !           323:            !ASN1_parse_dump(out, (unsigned char *) &(str[offset]), length,
        !           324:                indent, dump)) {
        !           325:                ERR_print_errors(bio_err);
        !           326:                goto end;
        !           327:        }
        !           328:        ret = 0;
        !           329: end:
        !           330:        BIO_free(derout);
        !           331:        if (in != NULL)
        !           332:                BIO_free(in);
        !           333:        if (out != NULL)
        !           334:                BIO_free_all(out);
        !           335:        if (b64 != NULL)
        !           336:                BIO_free(b64);
        !           337:        if (ret != 0)
        !           338:                ERR_print_errors(bio_err);
        !           339:        if (buf != NULL)
        !           340:                BUF_MEM_free(buf);
        !           341:        if (at != NULL)
        !           342:                ASN1_TYPE_free(at);
        !           343:        if (osk != NULL)
        !           344:                sk_OPENSSL_STRING_free(osk);
        !           345:        OBJ_cleanup();
        !           346:
        !           347:        return (ret);
        !           348: }
        !           349:
        !           350: static int
        !           351: do_generate(BIO * bio, char *genstr, char *genconf, BUF_MEM * buf)
        !           352: {
        !           353:        CONF *cnf = NULL;
        !           354:        int len;
        !           355:        long errline;
        !           356:        unsigned char *p;
        !           357:        ASN1_TYPE *atyp = NULL;
        !           358:
        !           359:        if (genconf) {
        !           360:                cnf = NCONF_new(NULL);
        !           361:                if (!NCONF_load(cnf, genconf, &errline))
        !           362:                        goto conferr;
        !           363:                if (!genstr)
        !           364:                        genstr = NCONF_get_string(cnf, "default", "asn1");
        !           365:                if (!genstr) {
        !           366:                        BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf);
        !           367:                        goto err;
        !           368:                }
        !           369:        }
        !           370:        atyp = ASN1_generate_nconf(genstr, cnf);
        !           371:        NCONF_free(cnf);
        !           372:        cnf = NULL;
        !           373:
        !           374:        if (!atyp)
        !           375:                return -1;
        !           376:
        !           377:        len = i2d_ASN1_TYPE(atyp, NULL);
        !           378:
        !           379:        if (len <= 0)
        !           380:                goto err;
        !           381:
        !           382:        if (!BUF_MEM_grow(buf, len))
        !           383:                goto err;
        !           384:
        !           385:        p = (unsigned char *) buf->data;
        !           386:
        !           387:        i2d_ASN1_TYPE(atyp, &p);
        !           388:
        !           389:        ASN1_TYPE_free(atyp);
        !           390:        return len;
        !           391:
        !           392: conferr:
        !           393:
        !           394:        if (errline > 0)
        !           395:                BIO_printf(bio, "Error on line %ld of config file '%s'\n",
        !           396:                    errline, genconf);
        !           397:        else
        !           398:                BIO_printf(bio, "Error loading config file '%s'\n", genconf);
        !           399:
        !           400: err:
        !           401:        NCONF_free(cnf);
        !           402:        ASN1_TYPE_free(atyp);
        !           403:
        !           404:        return -1;
        !           405:
        !           406: }