Home | History | Annotate | Line # | Download | only in apps
      1 /*
      2  * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <stdio.h>
     11 #include <string.h>
     12 #include "apps.h"
     13 #include "progs.h"
     14 #include <openssl/pem.h>
     15 #include <openssl/err.h>
     16 #include <openssl/evp.h>
     17 
     18 typedef enum OPTION_choice {
     19     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     20     OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT,
     21     OPT_ENGINE, OPT_CHECK
     22 } OPTION_CHOICE;
     23 
     24 const OPTIONS pkeyparam_options[] = {
     25     {"help", OPT_HELP, '-', "Display this summary"},
     26     {"in", OPT_IN, '<', "Input file"},
     27     {"out", OPT_OUT, '>', "Output file"},
     28     {"text", OPT_TEXT, '-', "Print parameters as text"},
     29     {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"},
     30 #ifndef OPENSSL_NO_ENGINE
     31     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
     32 #endif
     33     {"check", OPT_CHECK, '-', "Check key param consistency"},
     34     {NULL}
     35 };
     36 
     37 int pkeyparam_main(int argc, char **argv)
     38 {
     39     ENGINE *e = NULL;
     40     BIO *in = NULL, *out = NULL;
     41     EVP_PKEY *pkey = NULL;
     42     int text = 0, noout = 0, ret = 1, check = 0;
     43     OPTION_CHOICE o;
     44     char *infile = NULL, *outfile = NULL, *prog;
     45 
     46     prog = opt_init(argc, argv, pkeyparam_options);
     47     while ((o = opt_next()) != OPT_EOF) {
     48         switch (o) {
     49         case OPT_EOF:
     50         case OPT_ERR:
     51  opthelp:
     52             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
     53             goto end;
     54         case OPT_HELP:
     55             opt_help(pkeyparam_options);
     56             ret = 0;
     57             goto end;
     58         case OPT_IN:
     59             infile = opt_arg();
     60             break;
     61         case OPT_OUT:
     62             outfile = opt_arg();
     63             break;
     64         case OPT_ENGINE:
     65             e = setup_engine(opt_arg(), 0);
     66             break;
     67         case OPT_TEXT:
     68             text = 1;
     69             break;
     70         case OPT_NOOUT:
     71             noout = 1;
     72             break;
     73         case OPT_CHECK:
     74             check = 1;
     75             break;
     76         }
     77     }
     78     argc = opt_num_rest();
     79     if (argc != 0)
     80         goto opthelp;
     81 
     82     in = bio_open_default(infile, 'r', FORMAT_PEM);
     83     if (in == NULL)
     84         goto end;
     85     out = bio_open_default(outfile, 'w', FORMAT_PEM);
     86     if (out == NULL)
     87         goto end;
     88     pkey = PEM_read_bio_Parameters(in, NULL);
     89     if (pkey == NULL) {
     90         BIO_printf(bio_err, "Error reading parameters\n");
     91         ERR_print_errors(bio_err);
     92         goto end;
     93     }
     94 
     95     if (check) {
     96         int r;
     97         EVP_PKEY_CTX *ctx;
     98 
     99         ctx = EVP_PKEY_CTX_new(pkey, e);
    100         if (ctx == NULL) {
    101             ERR_print_errors(bio_err);
    102             goto end;
    103         }
    104 
    105         r = EVP_PKEY_param_check(ctx);
    106 
    107         if (r == 1) {
    108             BIO_printf(out, "Parameters are valid\n");
    109         } else {
    110             /*
    111              * Note: at least for RSA keys if this function returns
    112              * -1, there will be no error reasons.
    113              */
    114             unsigned long err;
    115 
    116             BIO_printf(out, "Parameters are invalid\n");
    117 
    118             while ((err = ERR_peek_error()) != 0) {
    119                 BIO_printf(out, "Detailed error: %s\n",
    120                            ERR_reason_error_string(err));
    121                 ERR_get_error(); /* remove err from error stack */
    122             }
    123         }
    124         EVP_PKEY_CTX_free(ctx);
    125     }
    126 
    127     if (!noout)
    128         PEM_write_bio_Parameters(out, pkey);
    129 
    130     if (text)
    131         EVP_PKEY_print_params(out, pkey, 0, NULL);
    132 
    133     ret = 0;
    134 
    135  end:
    136     EVP_PKEY_free(pkey);
    137     release_engine(e);
    138     BIO_free_all(out);
    139     BIO_free(in);
    140 
    141     return ret;
    142 }
    143