"Fossies" - the Fresh Open Source Software Archive

Member "openssl-1.1.1g/apps/rsa.c" (21 Apr 2020, 9522 Bytes) of package /linux/misc/openssl-1.1.1g.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rsa.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.1.1f_vs_1.1.1g.

    1 /*
    2  * Copyright 1995-2020 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 <openssl/opensslconf.h>
   11 #include <stdio.h>
   12 #include <stdlib.h>
   13 #include <string.h>
   14 #include <time.h>
   15 #include "apps.h"
   16 #include "progs.h"
   17 #include <openssl/bio.h>
   18 #include <openssl/err.h>
   19 #include <openssl/rsa.h>
   20 #include <openssl/evp.h>
   21 #include <openssl/x509.h>
   22 #include <openssl/pem.h>
   23 #include <openssl/bn.h>
   24 
   25 typedef enum OPTION_choice {
   26     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
   27     OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
   28     OPT_PUBIN, OPT_PUBOUT, OPT_PASSOUT, OPT_PASSIN,
   29     OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT,
   30     /* Do not change the order here; see case statements below */
   31     OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
   32     OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER
   33 } OPTION_CHOICE;
   34 
   35 const OPTIONS rsa_options[] = {
   36     {"help", OPT_HELP, '-', "Display this summary"},
   37     {"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"},
   38     {"outform", OPT_OUTFORM, 'f', "Output format, one of DER PEM PVK"},
   39     {"in", OPT_IN, 's', "Input file"},
   40     {"out", OPT_OUT, '>', "Output file"},
   41     {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
   42     {"pubout", OPT_PUBOUT, '-', "Output a public key"},
   43     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
   44     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
   45     {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"},
   46     {"RSAPublicKey_out", OPT_RSAPUBKEY_OUT, '-', "Output is an RSAPublicKey"},
   47     {"noout", OPT_NOOUT, '-', "Don't print key out"},
   48     {"text", OPT_TEXT, '-', "Print the key in text"},
   49     {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
   50     {"check", OPT_CHECK, '-', "Verify key consistency"},
   51     {"", OPT_CIPHER, '-', "Any supported cipher"},
   52 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
   53     {"pvk-strong", OPT_PVK_STRONG, '-', "Enable 'Strong' PVK encoding level (default)"},
   54     {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
   55     {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
   56 #endif
   57 #ifndef OPENSSL_NO_ENGINE
   58     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
   59 #endif
   60     {NULL}
   61 };
   62 
   63 int rsa_main(int argc, char **argv)
   64 {
   65     ENGINE *e = NULL;
   66     BIO *out = NULL;
   67     RSA *rsa = NULL;
   68     const EVP_CIPHER *enc = NULL;
   69     char *infile = NULL, *outfile = NULL, *prog;
   70     char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
   71     int i, private = 0;
   72     int informat = FORMAT_PEM, outformat = FORMAT_PEM, text = 0, check = 0;
   73     int noout = 0, modulus = 0, pubin = 0, pubout = 0, ret = 1;
   74 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
   75     int pvk_encr = 2;
   76 #endif
   77     OPTION_CHOICE o;
   78 
   79     prog = opt_init(argc, argv, rsa_options);
   80     while ((o = opt_next()) != OPT_EOF) {
   81         switch (o) {
   82         case OPT_EOF:
   83         case OPT_ERR:
   84  opthelp:
   85             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
   86             goto end;
   87         case OPT_HELP:
   88             opt_help(rsa_options);
   89             ret = 0;
   90             goto end;
   91         case OPT_INFORM:
   92             if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
   93                 goto opthelp;
   94             break;
   95         case OPT_IN:
   96             infile = opt_arg();
   97             break;
   98         case OPT_OUTFORM:
   99             if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
  100                 goto opthelp;
  101             break;
  102         case OPT_OUT:
  103             outfile = opt_arg();
  104             break;
  105         case OPT_PASSIN:
  106             passinarg = opt_arg();
  107             break;
  108         case OPT_PASSOUT:
  109             passoutarg = opt_arg();
  110             break;
  111         case OPT_ENGINE:
  112             e = setup_engine(opt_arg(), 0);
  113             break;
  114         case OPT_PUBIN:
  115             pubin = 1;
  116             break;
  117         case OPT_PUBOUT:
  118             pubout = 1;
  119             break;
  120         case OPT_RSAPUBKEY_IN:
  121             pubin = 2;
  122             break;
  123         case OPT_RSAPUBKEY_OUT:
  124             pubout = 2;
  125             break;
  126         case OPT_PVK_STRONG:    /* pvk_encr:= 2 */
  127         case OPT_PVK_WEAK:      /* pvk_encr:= 1 */
  128         case OPT_PVK_NONE:      /* pvk_encr:= 0 */
  129 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
  130             pvk_encr = (o - OPT_PVK_NONE);
  131 #endif
  132             break;
  133         case OPT_NOOUT:
  134             noout = 1;
  135             break;
  136         case OPT_TEXT:
  137             text = 1;
  138             break;
  139         case OPT_MODULUS:
  140             modulus = 1;
  141             break;
  142         case OPT_CHECK:
  143             check = 1;
  144             break;
  145         case OPT_CIPHER:
  146             if (!opt_cipher(opt_unknown(), &enc))
  147                 goto opthelp;
  148             break;
  149         }
  150     }
  151     argc = opt_num_rest();
  152     if (argc != 0)
  153         goto opthelp;
  154 
  155     private = (text && !pubin) || (!pubout && !noout) ? 1 : 0;
  156 
  157     if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
  158         BIO_printf(bio_err, "Error getting passwords\n");
  159         goto end;
  160     }
  161     if (check && pubin) {
  162         BIO_printf(bio_err, "Only private keys can be checked\n");
  163         goto end;
  164     }
  165 
  166     {
  167         EVP_PKEY *pkey;
  168 
  169         if (pubin) {
  170             int tmpformat = -1;
  171             if (pubin == 2) {
  172                 if (informat == FORMAT_PEM)
  173                     tmpformat = FORMAT_PEMRSA;
  174                 else if (informat == FORMAT_ASN1)
  175                     tmpformat = FORMAT_ASN1RSA;
  176             } else {
  177                 tmpformat = informat;
  178             }
  179 
  180             pkey = load_pubkey(infile, tmpformat, 1, passin, e, "Public Key");
  181         } else {
  182             pkey = load_key(infile, informat, 1, passin, e, "Private Key");
  183         }
  184 
  185         if (pkey != NULL)
  186             rsa = EVP_PKEY_get1_RSA(pkey);
  187         EVP_PKEY_free(pkey);
  188     }
  189 
  190     if (rsa == NULL) {
  191         ERR_print_errors(bio_err);
  192         goto end;
  193     }
  194 
  195     out = bio_open_owner(outfile, outformat, private);
  196     if (out == NULL)
  197         goto end;
  198 
  199     if (text) {
  200         assert(pubin || private);
  201         if (!RSA_print(out, rsa, 0)) {
  202             perror(outfile);
  203             ERR_print_errors(bio_err);
  204             goto end;
  205         }
  206     }
  207 
  208     if (modulus) {
  209         const BIGNUM *n;
  210         RSA_get0_key(rsa, &n, NULL, NULL);
  211         BIO_printf(out, "Modulus=");
  212         BN_print(out, n);
  213         BIO_printf(out, "\n");
  214     }
  215 
  216     if (check) {
  217         int r = RSA_check_key_ex(rsa, NULL);
  218 
  219         if (r == 1) {
  220             BIO_printf(out, "RSA key ok\n");
  221         } else if (r == 0) {
  222             unsigned long err;
  223 
  224             while ((err = ERR_peek_error()) != 0 &&
  225                    ERR_GET_LIB(err) == ERR_LIB_RSA &&
  226                    ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY_EX &&
  227                    ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) {
  228                 BIO_printf(out, "RSA key error: %s\n",
  229                            ERR_reason_error_string(err));
  230                 ERR_get_error(); /* remove err from error stack */
  231             }
  232         } else if (r == -1) {
  233             ERR_print_errors(bio_err);
  234             goto end;
  235         }
  236     }
  237 
  238     if (noout) {
  239         ret = 0;
  240         goto end;
  241     }
  242     BIO_printf(bio_err, "writing RSA key\n");
  243     if (outformat == FORMAT_ASN1) {
  244         if (pubout || pubin) {
  245             if (pubout == 2)
  246                 i = i2d_RSAPublicKey_bio(out, rsa);
  247             else
  248                 i = i2d_RSA_PUBKEY_bio(out, rsa);
  249         } else {
  250             assert(private);
  251             i = i2d_RSAPrivateKey_bio(out, rsa);
  252         }
  253     } else if (outformat == FORMAT_PEM) {
  254         if (pubout || pubin) {
  255             if (pubout == 2)
  256                 i = PEM_write_bio_RSAPublicKey(out, rsa);
  257             else
  258                 i = PEM_write_bio_RSA_PUBKEY(out, rsa);
  259         } else {
  260             assert(private);
  261             i = PEM_write_bio_RSAPrivateKey(out, rsa,
  262                                             enc, NULL, 0, NULL, passout);
  263         }
  264 #ifndef OPENSSL_NO_DSA
  265     } else if (outformat == FORMAT_MSBLOB || outformat == FORMAT_PVK) {
  266         EVP_PKEY *pk;
  267         pk = EVP_PKEY_new();
  268         if (pk == NULL)
  269             goto end;
  270 
  271         EVP_PKEY_set1_RSA(pk, rsa);
  272         if (outformat == FORMAT_PVK) {
  273             if (pubin) {
  274                 BIO_printf(bio_err, "PVK form impossible with public key input\n");
  275                 EVP_PKEY_free(pk);
  276                 goto end;
  277             }
  278             assert(private);
  279 # ifdef OPENSSL_NO_RC4
  280             BIO_printf(bio_err, "PVK format not supported\n");
  281             EVP_PKEY_free(pk);
  282             goto end;
  283 # else
  284             i = i2b_PVK_bio(out, pk, pvk_encr, 0, passout);
  285 # endif
  286         } else if (pubin || pubout) {
  287             i = i2b_PublicKey_bio(out, pk);
  288         } else {
  289             assert(private);
  290             i = i2b_PrivateKey_bio(out, pk);
  291         }
  292         EVP_PKEY_free(pk);
  293 #endif
  294     } else {
  295         BIO_printf(bio_err, "bad output format specified for outfile\n");
  296         goto end;
  297     }
  298     if (i <= 0) {
  299         BIO_printf(bio_err, "unable to write key\n");
  300         ERR_print_errors(bio_err);
  301     } else {
  302         ret = 0;
  303     }
  304  end:
  305     release_engine(e);
  306     BIO_free_all(out);
  307     RSA_free(rsa);
  308     OPENSSL_free(passin);
  309     OPENSSL_free(passout);
  310     return ret;
  311 }