"Fossies" - the Fresh Open Source Software Archive

Member "openssl-1.1.1g/apps/ecparam.c" (21 Apr 2020, 15005 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 "ecparam.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 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
    3  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
    4  *
    5  * Licensed under the OpenSSL license (the "License").  You may not use
    6  * this file except in compliance with the License.  You can obtain a copy
    7  * in the file LICENSE in the source distribution or at
    8  * https://www.openssl.org/source/license.html
    9  */
   10 
   11 #include <openssl/opensslconf.h>
   12 #include <stdio.h>
   13 #include <stdlib.h>
   14 #include <time.h>
   15 #include <string.h>
   16 #include "apps.h"
   17 #include "progs.h"
   18 #include <openssl/bio.h>
   19 #include <openssl/err.h>
   20 #include <openssl/bn.h>
   21 #include <openssl/ec.h>
   22 #include <openssl/x509.h>
   23 #include <openssl/pem.h>
   24 
   25 typedef enum OPTION_choice {
   26     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
   27     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
   28     OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME,
   29     OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE,
   30     OPT_R_ENUM
   31 } OPTION_CHOICE;
   32 
   33 const OPTIONS ecparam_options[] = {
   34     {"help", OPT_HELP, '-', "Display this summary"},
   35     {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
   36     {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
   37     {"in", OPT_IN, '<', "Input file  - default stdin"},
   38     {"out", OPT_OUT, '>', "Output file - default stdout"},
   39     {"text", OPT_TEXT, '-', "Print the ec parameters in text form"},
   40     {"C", OPT_C, '-', "Print a 'C' function creating the parameters"},
   41     {"check", OPT_CHECK, '-', "Validate the ec parameters"},
   42     {"list_curves", OPT_LIST_CURVES, '-',
   43      "Prints a list of all curve 'short names'"},
   44     {"no_seed", OPT_NO_SEED, '-',
   45      "If 'explicit' parameters are chosen do not use the seed"},
   46     {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"},
   47     {"name", OPT_NAME, 's',
   48      "Use the ec parameters with specified 'short name'"},
   49     {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
   50     {"param_enc", OPT_PARAM_ENC, 's',
   51      "Specifies the way the ec parameters are encoded"},
   52     {"genkey", OPT_GENKEY, '-', "Generate ec key"},
   53     OPT_R_OPTIONS,
   54 #ifndef OPENSSL_NO_ENGINE
   55     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
   56 #endif
   57     {NULL}
   58 };
   59 
   60 static OPT_PAIR forms[] = {
   61     {"compressed", POINT_CONVERSION_COMPRESSED},
   62     {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
   63     {"hybrid", POINT_CONVERSION_HYBRID},
   64     {NULL}
   65 };
   66 
   67 static OPT_PAIR encodings[] = {
   68     {"named_curve", OPENSSL_EC_NAMED_CURVE},
   69     {"explicit", 0},
   70     {NULL}
   71 };
   72 
   73 int ecparam_main(int argc, char **argv)
   74 {
   75     ENGINE *e = NULL;
   76     BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;
   77     BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL;
   78     BIO *in = NULL, *out = NULL;
   79     EC_GROUP *group = NULL;
   80     point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
   81     char *curve_name = NULL;
   82     char *infile = NULL, *outfile = NULL, *prog;
   83     unsigned char *buffer = NULL;
   84     OPTION_CHOICE o;
   85     int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0;
   86     int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
   87     int ret = 1, private = 0;
   88     int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
   89     int text = 0, i, genkey = 0;
   90 
   91     prog = opt_init(argc, argv, ecparam_options);
   92     while ((o = opt_next()) != OPT_EOF) {
   93         switch (o) {
   94         case OPT_EOF:
   95         case OPT_ERR:
   96  opthelp:
   97             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
   98             goto end;
   99         case OPT_HELP:
  100             opt_help(ecparam_options);
  101             ret = 0;
  102             goto end;
  103         case OPT_INFORM:
  104             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
  105                 goto opthelp;
  106             break;
  107         case OPT_IN:
  108             infile = opt_arg();
  109             break;
  110         case OPT_OUTFORM:
  111             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
  112                 goto opthelp;
  113             break;
  114         case OPT_OUT:
  115             outfile = opt_arg();
  116             break;
  117         case OPT_TEXT:
  118             text = 1;
  119             break;
  120         case OPT_C:
  121             C = 1;
  122             break;
  123         case OPT_CHECK:
  124             check = 1;
  125             break;
  126         case OPT_LIST_CURVES:
  127             list_curves = 1;
  128             break;
  129         case OPT_NO_SEED:
  130             no_seed = 1;
  131             break;
  132         case OPT_NOOUT:
  133             noout = 1;
  134             break;
  135         case OPT_NAME:
  136             curve_name = opt_arg();
  137             break;
  138         case OPT_CONV_FORM:
  139             if (!opt_pair(opt_arg(), forms, &new_form))
  140                 goto opthelp;
  141             form = new_form;
  142             new_form = 1;
  143             break;
  144         case OPT_PARAM_ENC:
  145             if (!opt_pair(opt_arg(), encodings, &asn1_flag))
  146                 goto opthelp;
  147             new_asn1_flag = 1;
  148             break;
  149         case OPT_GENKEY:
  150             genkey = 1;
  151             break;
  152         case OPT_R_CASES:
  153             if (!opt_rand(o))
  154                 goto end;
  155             break;
  156         case OPT_ENGINE:
  157             e = setup_engine(opt_arg(), 0);
  158             break;
  159         }
  160     }
  161     argc = opt_num_rest();
  162     if (argc != 0)
  163         goto opthelp;
  164 
  165     private = genkey ? 1 : 0;
  166 
  167     in = bio_open_default(infile, 'r', informat);
  168     if (in == NULL)
  169         goto end;
  170     out = bio_open_owner(outfile, outformat, private);
  171     if (out == NULL)
  172         goto end;
  173 
  174     if (list_curves) {
  175         EC_builtin_curve *curves = NULL;
  176         size_t crv_len = EC_get_builtin_curves(NULL, 0);
  177         size_t n;
  178 
  179         curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
  180         if (!EC_get_builtin_curves(curves, crv_len)) {
  181             OPENSSL_free(curves);
  182             goto end;
  183         }
  184 
  185         for (n = 0; n < crv_len; n++) {
  186             const char *comment;
  187             const char *sname;
  188             comment = curves[n].comment;
  189             sname = OBJ_nid2sn(curves[n].nid);
  190             if (comment == NULL)
  191                 comment = "CURVE DESCRIPTION NOT AVAILABLE";
  192             if (sname == NULL)
  193                 sname = "";
  194 
  195             BIO_printf(out, "  %-10s: ", sname);
  196             BIO_printf(out, "%s\n", comment);
  197         }
  198 
  199         OPENSSL_free(curves);
  200         ret = 0;
  201         goto end;
  202     }
  203 
  204     if (curve_name != NULL) {
  205         int nid;
  206 
  207         /*
  208          * workaround for the SECG curve names secp192r1 and secp256r1 (which
  209          * are the same as the curves prime192v1 and prime256v1 defined in
  210          * X9.62)
  211          */
  212         if (strcmp(curve_name, "secp192r1") == 0) {
  213             BIO_printf(bio_err, "using curve name prime192v1 "
  214                        "instead of secp192r1\n");
  215             nid = NID_X9_62_prime192v1;
  216         } else if (strcmp(curve_name, "secp256r1") == 0) {
  217             BIO_printf(bio_err, "using curve name prime256v1 "
  218                        "instead of secp256r1\n");
  219             nid = NID_X9_62_prime256v1;
  220         } else {
  221             nid = OBJ_sn2nid(curve_name);
  222         }
  223 
  224         if (nid == 0)
  225             nid = EC_curve_nist2nid(curve_name);
  226 
  227         if (nid == 0) {
  228             BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
  229             goto end;
  230         }
  231 
  232         group = EC_GROUP_new_by_curve_name(nid);
  233         if (group == NULL) {
  234             BIO_printf(bio_err, "unable to create curve (%s)\n", curve_name);
  235             goto end;
  236         }
  237         EC_GROUP_set_asn1_flag(group, asn1_flag);
  238         EC_GROUP_set_point_conversion_form(group, form);
  239     } else if (informat == FORMAT_ASN1) {
  240         group = d2i_ECPKParameters_bio(in, NULL);
  241     } else {
  242         group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
  243     }
  244     if (group == NULL) {
  245         BIO_printf(bio_err, "unable to load elliptic curve parameters\n");
  246         ERR_print_errors(bio_err);
  247         goto end;
  248     }
  249 
  250     if (new_form)
  251         EC_GROUP_set_point_conversion_form(group, form);
  252 
  253     if (new_asn1_flag)
  254         EC_GROUP_set_asn1_flag(group, asn1_flag);
  255 
  256     if (no_seed) {
  257         EC_GROUP_set_seed(group, NULL, 0);
  258     }
  259 
  260     if (text) {
  261         if (!ECPKParameters_print(out, group, 0))
  262             goto end;
  263     }
  264 
  265     if (check) {
  266         BIO_printf(bio_err, "checking elliptic curve parameters: ");
  267         if (!EC_GROUP_check(group, NULL)) {
  268             BIO_printf(bio_err, "failed\n");
  269             ERR_print_errors(bio_err);
  270             goto end;
  271         }
  272         BIO_printf(bio_err, "ok\n");
  273 
  274     }
  275 
  276     if (C) {
  277         size_t buf_len = 0, tmp_len = 0;
  278         const EC_POINT *point;
  279         int is_prime, len = 0;
  280         const EC_METHOD *meth = EC_GROUP_method_of(group);
  281 
  282         if ((ec_p = BN_new()) == NULL
  283                 || (ec_a = BN_new()) == NULL
  284                 || (ec_b = BN_new()) == NULL
  285                 || (ec_gen = BN_new()) == NULL
  286                 || (ec_order = BN_new()) == NULL
  287                 || (ec_cofactor = BN_new()) == NULL) {
  288             perror("Can't allocate BN");
  289             goto end;
  290         }
  291 
  292         is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);
  293         if (!is_prime) {
  294             BIO_printf(bio_err, "Can only handle X9.62 prime fields\n");
  295             goto end;
  296         }
  297 
  298         if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL))
  299             goto end;
  300 
  301         if ((point = EC_GROUP_get0_generator(group)) == NULL)
  302             goto end;
  303         if (!EC_POINT_point2bn(group, point,
  304                                EC_GROUP_get_point_conversion_form(group),
  305                                ec_gen, NULL))
  306             goto end;
  307         if (!EC_GROUP_get_order(group, ec_order, NULL))
  308             goto end;
  309         if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))
  310             goto end;
  311 
  312         if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor)
  313             goto end;
  314 
  315         len = BN_num_bits(ec_order);
  316 
  317         if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)
  318             buf_len = tmp_len;
  319         if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)
  320             buf_len = tmp_len;
  321         if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)
  322             buf_len = tmp_len;
  323         if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)
  324             buf_len = tmp_len;
  325         if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)
  326             buf_len = tmp_len;
  327         if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)
  328             buf_len = tmp_len;
  329 
  330         buffer = app_malloc(buf_len, "BN buffer");
  331 
  332         BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n{\n", len);
  333         print_bignum_var(out, ec_p, "ec_p", len, buffer);
  334         print_bignum_var(out, ec_a, "ec_a", len, buffer);
  335         print_bignum_var(out, ec_b, "ec_b", len, buffer);
  336         print_bignum_var(out, ec_gen, "ec_gen", len, buffer);
  337         print_bignum_var(out, ec_order, "ec_order", len, buffer);
  338         print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer);
  339         BIO_printf(out, "    int ok = 0;\n"
  340                         "    EC_GROUP *group = NULL;\n"
  341                         "    EC_POINT *point = NULL;\n"
  342                         "    BIGNUM *tmp_1 = NULL;\n"
  343                         "    BIGNUM *tmp_2 = NULL;\n"
  344                         "    BIGNUM *tmp_3 = NULL;\n"
  345                         "\n");
  346 
  347         BIO_printf(out, "    if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\n"
  348                         "        goto err;\n", len, len);
  349         BIO_printf(out, "    if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\n"
  350                         "        goto err;\n", len, len);
  351         BIO_printf(out, "    if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\n"
  352                         "        goto err;\n", len, len);
  353         BIO_printf(out, "    if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\n"
  354                         "        goto err;\n"
  355                         "\n");
  356         BIO_printf(out, "    /* build generator */\n");
  357         BIO_printf(out, "    if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\n"
  358                         "        goto err;\n", len, len);
  359         BIO_printf(out, "    point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\n");
  360         BIO_printf(out, "    if (point == NULL)\n"
  361                         "        goto err;\n");
  362         BIO_printf(out, "    if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\n"
  363                         "        goto err;\n", len, len);
  364         BIO_printf(out, "    if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\n"
  365                         "        goto err;\n", len, len);
  366         BIO_printf(out, "    if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\n"
  367                         "        goto err;\n"
  368                         "ok = 1;"
  369                         "\n");
  370         BIO_printf(out, "err:\n"
  371                         "    BN_free(tmp_1);\n"
  372                         "    BN_free(tmp_2);\n"
  373                         "    BN_free(tmp_3);\n"
  374                         "    EC_POINT_free(point);\n"
  375                         "    if (!ok) {\n"
  376                         "        EC_GROUP_free(group);\n"
  377                         "        return NULL;\n"
  378                         "    }\n"
  379                         "    return (group);\n"
  380                         "}\n");
  381     }
  382 
  383     if (outformat == FORMAT_ASN1 && genkey)
  384         noout = 1;
  385 
  386     if (!noout) {
  387         if (outformat == FORMAT_ASN1)
  388             i = i2d_ECPKParameters_bio(out, group);
  389         else
  390             i = PEM_write_bio_ECPKParameters(out, group);
  391         if (!i) {
  392             BIO_printf(bio_err, "unable to write elliptic "
  393                        "curve parameters\n");
  394             ERR_print_errors(bio_err);
  395             goto end;
  396         }
  397     }
  398 
  399     if (genkey) {
  400         EC_KEY *eckey = EC_KEY_new();
  401 
  402         if (eckey == NULL)
  403             goto end;
  404 
  405         if (EC_KEY_set_group(eckey, group) == 0) {
  406             BIO_printf(bio_err, "unable to set group when generating key\n");
  407             EC_KEY_free(eckey);
  408             ERR_print_errors(bio_err);
  409             goto end;
  410         }
  411 
  412         if (new_form)
  413             EC_KEY_set_conv_form(eckey, form);
  414 
  415         if (!EC_KEY_generate_key(eckey)) {
  416             BIO_printf(bio_err, "unable to generate key\n");
  417             EC_KEY_free(eckey);
  418             ERR_print_errors(bio_err);
  419             goto end;
  420         }
  421         assert(private);
  422         if (outformat == FORMAT_ASN1)
  423             i = i2d_ECPrivateKey_bio(out, eckey);
  424         else
  425             i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
  426                                            NULL, 0, NULL, NULL);
  427         EC_KEY_free(eckey);
  428     }
  429 
  430     ret = 0;
  431  end:
  432     BN_free(ec_p);
  433     BN_free(ec_a);
  434     BN_free(ec_b);
  435     BN_free(ec_gen);
  436     BN_free(ec_order);
  437     BN_free(ec_cofactor);
  438     OPENSSL_free(buffer);
  439     EC_GROUP_free(group);
  440     release_engine(e);
  441     BIO_free(in);
  442     BIO_free_all(out);
  443     return ret;
  444 }