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

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

1.1     ! jsing       1: /* $OpenBSD: pkeyutl.c,v 1.14 2014/07/14 00:35:10 deraadt Exp $ */
        !             2: /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
        !             3:  * project 2006.
        !             4:  */
        !             5: /* ====================================================================
        !             6:  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  *
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  *
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in
        !            17:  *    the documentation and/or other materials provided with the
        !            18:  *    distribution.
        !            19:  *
        !            20:  * 3. All advertising materials mentioning features or use of this
        !            21:  *    software must display the following acknowledgment:
        !            22:  *    "This product includes software developed by the OpenSSL Project
        !            23:  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
        !            24:  *
        !            25:  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
        !            26:  *    endorse or promote products derived from this software without
        !            27:  *    prior written permission. For written permission, please contact
        !            28:  *    licensing@OpenSSL.org.
        !            29:  *
        !            30:  * 5. Products derived from this software may not be called "OpenSSL"
        !            31:  *    nor may "OpenSSL" appear in their names without prior written
        !            32:  *    permission of the OpenSSL Project.
        !            33:  *
        !            34:  * 6. Redistributions of any form whatsoever must retain the following
        !            35:  *    acknowledgment:
        !            36:  *    "This product includes software developed by the OpenSSL Project
        !            37:  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
        !            38:  *
        !            39:  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
        !            40:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            41:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            42:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
        !            43:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            44:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            45:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        !            46:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            47:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            48:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            49:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
        !            50:  * OF THE POSSIBILITY OF SUCH DAMAGE.
        !            51:  * ====================================================================
        !            52:  *
        !            53:  * This product includes cryptographic software written by Eric Young
        !            54:  * (eay@cryptsoft.com).  This product includes software written by Tim
        !            55:  * Hudson (tjh@cryptsoft.com).
        !            56:  *
        !            57:  */
        !            58:
        !            59: #include <string.h>
        !            60:
        !            61: #include "apps.h"
        !            62:
        !            63: #include <openssl/err.h>
        !            64: #include <openssl/evp.h>
        !            65: #include <openssl/pem.h>
        !            66:
        !            67: #define KEY_PRIVKEY    1
        !            68: #define KEY_PUBKEY     2
        !            69: #define KEY_CERT       3
        !            70:
        !            71: static void usage(void);
        !            72:
        !            73: static EVP_PKEY_CTX *init_ctx(int *pkeysize,
        !            74:     char *keyfile, int keyform, int key_type,
        !            75:     char *passargin, int pkey_op, ENGINE * e);
        !            76:
        !            77: static int setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform,
        !            78:     const char *file);
        !            79:
        !            80: static int do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
        !            81:     unsigned char *out, size_t * poutlen,
        !            82:     unsigned char *in, size_t inlen);
        !            83:
        !            84: int pkeyutl_main(int argc, char **);
        !            85:
        !            86: int
        !            87: pkeyutl_main(int argc, char **argv)
        !            88: {
        !            89:        BIO *in = NULL, *out = NULL;
        !            90:        char *infile = NULL, *outfile = NULL, *sigfile = NULL;
        !            91:        ENGINE *e = NULL;
        !            92:        int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
        !            93:        int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
        !            94:        char badarg = 0, rev = 0;
        !            95:        char hexdump = 0, asn1parse = 0;
        !            96:        EVP_PKEY_CTX *ctx = NULL;
        !            97:        char *passargin = NULL;
        !            98:        int keysize = -1;
        !            99:
        !           100:        unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
        !           101:        size_t buf_outlen;
        !           102:        int buf_inlen = 0, siglen = -1;
        !           103:
        !           104:        int ret = 1, rv = -1;
        !           105:
        !           106:        argc--;
        !           107:        argv++;
        !           108:
        !           109:        ERR_load_crypto_strings();
        !           110:        OpenSSL_add_all_algorithms();
        !           111:
        !           112:        while (argc >= 1) {
        !           113:                if (!strcmp(*argv, "-in")) {
        !           114:                        if (--argc < 1)
        !           115:                                badarg = 1;
        !           116:                        else
        !           117:                                infile = *(++argv);
        !           118:                } else if (!strcmp(*argv, "-out")) {
        !           119:                        if (--argc < 1)
        !           120:                                badarg = 1;
        !           121:                        else
        !           122:                                outfile = *(++argv);
        !           123:                } else if (!strcmp(*argv, "-sigfile")) {
        !           124:                        if (--argc < 1)
        !           125:                                badarg = 1;
        !           126:                        else
        !           127:                                sigfile = *(++argv);
        !           128:                } else if (!strcmp(*argv, "-inkey")) {
        !           129:                        if (--argc < 1)
        !           130:                                badarg = 1;
        !           131:                        else {
        !           132:                                ctx = init_ctx(&keysize,
        !           133:                                    *(++argv), keyform, key_type,
        !           134:                                    passargin, pkey_op, e);
        !           135:                                if (!ctx) {
        !           136:                                        BIO_puts(bio_err,
        !           137:                                            "Error initializing context\n");
        !           138:                                        ERR_print_errors(bio_err);
        !           139:                                        badarg = 1;
        !           140:                                }
        !           141:                        }
        !           142:                } else if (!strcmp(*argv, "-peerkey")) {
        !           143:                        if (--argc < 1)
        !           144:                                badarg = 1;
        !           145:                        else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
        !           146:                                badarg = 1;
        !           147:                } else if (!strcmp(*argv, "-passin")) {
        !           148:                        if (--argc < 1)
        !           149:                                badarg = 1;
        !           150:                        else
        !           151:                                passargin = *(++argv);
        !           152:                } else if (strcmp(*argv, "-peerform") == 0) {
        !           153:                        if (--argc < 1)
        !           154:                                badarg = 1;
        !           155:                        else
        !           156:                                peerform = str2fmt(*(++argv));
        !           157:                } else if (strcmp(*argv, "-keyform") == 0) {
        !           158:                        if (--argc < 1)
        !           159:                                badarg = 1;
        !           160:                        else
        !           161:                                keyform = str2fmt(*(++argv));
        !           162:                }
        !           163: #ifndef OPENSSL_NO_ENGINE
        !           164:                else if (!strcmp(*argv, "-engine")) {
        !           165:                        if (--argc < 1)
        !           166:                                badarg = 1;
        !           167:                        else
        !           168:                                e = setup_engine(bio_err, *(++argv), 0);
        !           169:                }
        !           170: #endif
        !           171:                else if (!strcmp(*argv, "-pubin"))
        !           172:                        key_type = KEY_PUBKEY;
        !           173:                else if (!strcmp(*argv, "-certin"))
        !           174:                        key_type = KEY_CERT;
        !           175:                else if (!strcmp(*argv, "-asn1parse"))
        !           176:                        asn1parse = 1;
        !           177:                else if (!strcmp(*argv, "-hexdump"))
        !           178:                        hexdump = 1;
        !           179:                else if (!strcmp(*argv, "-sign"))
        !           180:                        pkey_op = EVP_PKEY_OP_SIGN;
        !           181:                else if (!strcmp(*argv, "-verify"))
        !           182:                        pkey_op = EVP_PKEY_OP_VERIFY;
        !           183:                else if (!strcmp(*argv, "-verifyrecover"))
        !           184:                        pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
        !           185:                else if (!strcmp(*argv, "-rev"))
        !           186:                        rev = 1;
        !           187:                else if (!strcmp(*argv, "-encrypt"))
        !           188:                        pkey_op = EVP_PKEY_OP_ENCRYPT;
        !           189:                else if (!strcmp(*argv, "-decrypt"))
        !           190:                        pkey_op = EVP_PKEY_OP_DECRYPT;
        !           191:                else if (!strcmp(*argv, "-derive"))
        !           192:                        pkey_op = EVP_PKEY_OP_DERIVE;
        !           193:                else if (strcmp(*argv, "-pkeyopt") == 0) {
        !           194:                        if (--argc < 1)
        !           195:                                badarg = 1;
        !           196:                        else if (!ctx) {
        !           197:                                BIO_puts(bio_err,
        !           198:                                    "-pkeyopt command before -inkey\n");
        !           199:                                badarg = 1;
        !           200:                        } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) {
        !           201:                                BIO_puts(bio_err, "parameter setting error\n");
        !           202:                                ERR_print_errors(bio_err);
        !           203:                                goto end;
        !           204:                        }
        !           205:                } else
        !           206:                        badarg = 1;
        !           207:                if (badarg) {
        !           208:                        usage();
        !           209:                        goto end;
        !           210:                }
        !           211:                argc--;
        !           212:                argv++;
        !           213:        }
        !           214:
        !           215:        if (!ctx) {
        !           216:                usage();
        !           217:                goto end;
        !           218:        }
        !           219:        if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) {
        !           220:                BIO_puts(bio_err, "Signature file specified for non verify\n");
        !           221:                goto end;
        !           222:        }
        !           223:        if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) {
        !           224:                BIO_puts(bio_err, "No signature file specified for verify\n");
        !           225:                goto end;
        !           226:        }
        !           227:
        !           228:        if (pkey_op != EVP_PKEY_OP_DERIVE) {
        !           229:                if (infile) {
        !           230:                        if (!(in = BIO_new_file(infile, "rb"))) {
        !           231:                                BIO_puts(bio_err,
        !           232:                                    "Error Opening Input File\n");
        !           233:                                ERR_print_errors(bio_err);
        !           234:                                goto end;
        !           235:                        }
        !           236:                } else
        !           237:                        in = BIO_new_fp(stdin, BIO_NOCLOSE);
        !           238:        }
        !           239:        if (outfile) {
        !           240:                if (!(out = BIO_new_file(outfile, "wb"))) {
        !           241:                        BIO_printf(bio_err, "Error Creating Output File\n");
        !           242:                        ERR_print_errors(bio_err);
        !           243:                        goto end;
        !           244:                }
        !           245:        } else {
        !           246:                out = BIO_new_fp(stdout, BIO_NOCLOSE);
        !           247:        }
        !           248:
        !           249:        if (sigfile) {
        !           250:                BIO *sigbio = BIO_new_file(sigfile, "rb");
        !           251:                if (!sigbio) {
        !           252:                        BIO_printf(bio_err, "Can't open signature file %s\n",
        !           253:                            sigfile);
        !           254:                        goto end;
        !           255:                }
        !           256:                siglen = bio_to_mem(&sig, keysize * 10, sigbio);
        !           257:                BIO_free(sigbio);
        !           258:                if (siglen <= 0) {
        !           259:                        BIO_printf(bio_err, "Error reading signature data\n");
        !           260:                        goto end;
        !           261:                }
        !           262:        }
        !           263:        if (in) {
        !           264:                /* Read the input data */
        !           265:                buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
        !           266:                if (buf_inlen <= 0) {
        !           267:                        BIO_printf(bio_err, "Error reading input Data\n");
        !           268:                        exit(1);
        !           269:                }
        !           270:                if (rev) {
        !           271:                        size_t i;
        !           272:                        unsigned char ctmp;
        !           273:                        size_t l = (size_t) buf_inlen;
        !           274:                        for (i = 0; i < l / 2; i++) {
        !           275:                                ctmp = buf_in[i];
        !           276:                                buf_in[i] = buf_in[l - 1 - i];
        !           277:                                buf_in[l - 1 - i] = ctmp;
        !           278:                        }
        !           279:                }
        !           280:        }
        !           281:        if (pkey_op == EVP_PKEY_OP_VERIFY) {
        !           282:                rv = EVP_PKEY_verify(ctx, sig, (size_t) siglen,
        !           283:                    buf_in, (size_t) buf_inlen);
        !           284:                if (rv == 0)
        !           285:                        BIO_puts(out, "Signature Verification Failure\n");
        !           286:                else if (rv == 1)
        !           287:                        BIO_puts(out, "Signature Verified Successfully\n");
        !           288:                if (rv >= 0)
        !           289:                        goto end;
        !           290:        } else {
        !           291:                rv = do_keyop(ctx, pkey_op, NULL, (size_t *) & buf_outlen,
        !           292:                    buf_in, (size_t) buf_inlen);
        !           293:                if (rv > 0) {
        !           294:                        buf_out = malloc(buf_outlen);
        !           295:                        if (!buf_out)
        !           296:                                rv = -1;
        !           297:                        else
        !           298:                                rv = do_keyop(ctx, pkey_op,
        !           299:                                    buf_out, (size_t *) & buf_outlen,
        !           300:                                    buf_in, (size_t) buf_inlen);
        !           301:                }
        !           302:        }
        !           303:
        !           304:        if (rv <= 0) {
        !           305:                BIO_printf(bio_err, "Public Key operation error\n");
        !           306:                ERR_print_errors(bio_err);
        !           307:                goto end;
        !           308:        }
        !           309:        ret = 0;
        !           310:        if (asn1parse) {
        !           311:                if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
        !           312:                        ERR_print_errors(bio_err);
        !           313:        } else if (hexdump)
        !           314:                BIO_dump(out, (char *) buf_out, buf_outlen);
        !           315:        else
        !           316:                BIO_write(out, buf_out, buf_outlen);
        !           317:
        !           318: end:
        !           319:        if (ctx)
        !           320:                EVP_PKEY_CTX_free(ctx);
        !           321:        BIO_free(in);
        !           322:        BIO_free_all(out);
        !           323:        free(buf_in);
        !           324:        free(buf_out);
        !           325:        free(sig);
        !           326:
        !           327:        return ret;
        !           328: }
        !           329:
        !           330: static void
        !           331: usage()
        !           332: {
        !           333:        BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
        !           334:        BIO_printf(bio_err, "-in file        input file\n");
        !           335:        BIO_printf(bio_err, "-out file       output file\n");
        !           336:        BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
        !           337:        BIO_printf(bio_err, "-inkey file     input key\n");
        !           338:        BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
        !           339:        BIO_printf(bio_err, "-pubin          input is a public key\n");
        !           340:        BIO_printf(bio_err, "-certin         input is a certificate carrying a public key\n");
        !           341:        BIO_printf(bio_err, "-pkeyopt X:Y    public key options\n");
        !           342:        BIO_printf(bio_err, "-sign           sign with private key\n");
        !           343:        BIO_printf(bio_err, "-verify         verify with public key\n");
        !           344:        BIO_printf(bio_err, "-verifyrecover  verify with public key, recover original data\n");
        !           345:        BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
        !           346:        BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
        !           347:        BIO_printf(bio_err, "-derive         derive shared secret\n");
        !           348:        BIO_printf(bio_err, "-hexdump        hex dump output\n");
        !           349: #ifndef OPENSSL_NO_ENGINE
        !           350:        BIO_printf(bio_err, "-engine e       use engine e, possibly a hardware device.\n");
        !           351: #endif
        !           352:        BIO_printf(bio_err, "-passin arg     pass phrase source\n");
        !           353:
        !           354: }
        !           355:
        !           356: static EVP_PKEY_CTX *
        !           357: init_ctx(int *pkeysize,
        !           358:     char *keyfile, int keyform, int key_type,
        !           359:     char *passargin, int pkey_op, ENGINE * e)
        !           360: {
        !           361:        EVP_PKEY *pkey = NULL;
        !           362:        EVP_PKEY_CTX *ctx = NULL;
        !           363:        char *passin = NULL;
        !           364:        int rv = -1;
        !           365:        X509 *x;
        !           366:        if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
        !           367:                || (pkey_op == EVP_PKEY_OP_DERIVE))
        !           368:            && (key_type != KEY_PRIVKEY)) {
        !           369:                BIO_printf(bio_err, "A private key is needed for this operation\n");
        !           370:                goto end;
        !           371:        }
        !           372:        if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
        !           373:                BIO_printf(bio_err, "Error getting password\n");
        !           374:                goto end;
        !           375:        }
        !           376:        switch (key_type) {
        !           377:        case KEY_PRIVKEY:
        !           378:                pkey = load_key(bio_err, keyfile, keyform, 0,
        !           379:                    passin, e, "Private Key");
        !           380:                break;
        !           381:
        !           382:        case KEY_PUBKEY:
        !           383:                pkey = load_pubkey(bio_err, keyfile, keyform, 0,
        !           384:                    NULL, e, "Public Key");
        !           385:                break;
        !           386:
        !           387:        case KEY_CERT:
        !           388:                x = load_cert(bio_err, keyfile, keyform,
        !           389:                    NULL, e, "Certificate");
        !           390:                if (x) {
        !           391:                        pkey = X509_get_pubkey(x);
        !           392:                        X509_free(x);
        !           393:                }
        !           394:                break;
        !           395:
        !           396:        }
        !           397:
        !           398:        *pkeysize = EVP_PKEY_size(pkey);
        !           399:
        !           400:        if (!pkey)
        !           401:                goto end;
        !           402:
        !           403:        ctx = EVP_PKEY_CTX_new(pkey, e);
        !           404:
        !           405:        EVP_PKEY_free(pkey);
        !           406:
        !           407:        if (!ctx)
        !           408:                goto end;
        !           409:
        !           410:        switch (pkey_op) {
        !           411:        case EVP_PKEY_OP_SIGN:
        !           412:                rv = EVP_PKEY_sign_init(ctx);
        !           413:                break;
        !           414:
        !           415:        case EVP_PKEY_OP_VERIFY:
        !           416:                rv = EVP_PKEY_verify_init(ctx);
        !           417:                break;
        !           418:
        !           419:        case EVP_PKEY_OP_VERIFYRECOVER:
        !           420:                rv = EVP_PKEY_verify_recover_init(ctx);
        !           421:                break;
        !           422:
        !           423:        case EVP_PKEY_OP_ENCRYPT:
        !           424:                rv = EVP_PKEY_encrypt_init(ctx);
        !           425:                break;
        !           426:
        !           427:        case EVP_PKEY_OP_DECRYPT:
        !           428:                rv = EVP_PKEY_decrypt_init(ctx);
        !           429:                break;
        !           430:
        !           431:        case EVP_PKEY_OP_DERIVE:
        !           432:                rv = EVP_PKEY_derive_init(ctx);
        !           433:                break;
        !           434:        }
        !           435:
        !           436:        if (rv <= 0) {
        !           437:                EVP_PKEY_CTX_free(ctx);
        !           438:                ctx = NULL;
        !           439:        }
        !           440: end:
        !           441:
        !           442:        free(passin);
        !           443:
        !           444:        return ctx;
        !           445:
        !           446:
        !           447: }
        !           448:
        !           449: static int
        !           450: setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform,
        !           451:     const char *file)
        !           452: {
        !           453:        EVP_PKEY *peer = NULL;
        !           454:        int ret;
        !           455:        if (!ctx) {
        !           456:                BIO_puts(err, "-peerkey command before -inkey\n");
        !           457:                return 0;
        !           458:        }
        !           459:        peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
        !           460:
        !           461:        if (!peer) {
        !           462:                BIO_printf(bio_err, "Error reading peer key %s\n", file);
        !           463:                ERR_print_errors(err);
        !           464:                return 0;
        !           465:        }
        !           466:        ret = EVP_PKEY_derive_set_peer(ctx, peer);
        !           467:
        !           468:        EVP_PKEY_free(peer);
        !           469:        if (ret <= 0)
        !           470:                ERR_print_errors(err);
        !           471:        return ret;
        !           472: }
        !           473:
        !           474: static int
        !           475: do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
        !           476:     unsigned char *out, size_t * poutlen,
        !           477:     unsigned char *in, size_t inlen)
        !           478: {
        !           479:        int rv = 0;
        !           480:        switch (pkey_op) {
        !           481:        case EVP_PKEY_OP_VERIFYRECOVER:
        !           482:                rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
        !           483:                break;
        !           484:
        !           485:        case EVP_PKEY_OP_SIGN:
        !           486:                rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
        !           487:                break;
        !           488:
        !           489:        case EVP_PKEY_OP_ENCRYPT:
        !           490:                rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
        !           491:                break;
        !           492:
        !           493:        case EVP_PKEY_OP_DECRYPT:
        !           494:                rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
        !           495:                break;
        !           496:
        !           497:        case EVP_PKEY_OP_DERIVE:
        !           498:                rv = EVP_PKEY_derive(ctx, out, poutlen);
        !           499:                break;
        !           500:
        !           501:        }
        !           502:        return rv;
        !           503: }