Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/apps/ec.c
34870 views
1
/*
2
* Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
3
*
4
* Licensed under the Apache License 2.0 (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 <string.h>
11
#include <openssl/opensslconf.h>
12
#include <openssl/evp.h>
13
#include <openssl/encoder.h>
14
#include <openssl/decoder.h>
15
#include <openssl/core_names.h>
16
#include <openssl/core_dispatch.h>
17
#include <openssl/params.h>
18
#include <openssl/err.h>
19
20
#include "apps.h"
21
#include "progs.h"
22
#include "ec_common.h"
23
24
typedef enum OPTION_choice {
25
OPT_COMMON,
26
OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
27
OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT,
28
OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER,
29
OPT_NO_PUBLIC, OPT_CHECK, OPT_PROV_ENUM
30
} OPTION_CHOICE;
31
32
const OPTIONS ec_options[] = {
33
OPT_SECTION("General"),
34
{"help", OPT_HELP, '-', "Display this summary"},
35
#ifndef OPENSSL_NO_ENGINE
36
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
37
#endif
38
39
OPT_SECTION("Input"),
40
{"in", OPT_IN, 's', "Input file"},
41
{"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
42
{"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
43
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
44
{"check", OPT_CHECK, '-', "check key consistency"},
45
{"", OPT_CIPHER, '-', "Any supported cipher"},
46
{"param_enc", OPT_PARAM_ENC, 's',
47
"Specifies the way the ec parameters are encoded"},
48
{"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
49
50
OPT_SECTION("Output"),
51
{"out", OPT_OUT, '>', "Output file"},
52
{"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
53
{"noout", OPT_NOOUT, '-', "Don't print key out"},
54
{"text", OPT_TEXT, '-', "Print the key"},
55
{"param_out", OPT_PARAM_OUT, '-', "Print the elliptic curve parameters"},
56
{"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
57
{"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"},
58
{"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
59
60
OPT_PROV_OPTIONS,
61
{NULL}
62
};
63
64
int ec_main(int argc, char **argv)
65
{
66
OSSL_ENCODER_CTX *ectx = NULL;
67
OSSL_DECODER_CTX *dctx = NULL;
68
EVP_PKEY_CTX *pctx = NULL;
69
EVP_PKEY *eckey = NULL;
70
BIO *out = NULL;
71
ENGINE *e = NULL;
72
EVP_CIPHER *enc = NULL;
73
char *infile = NULL, *outfile = NULL, *ciphername = NULL, *prog;
74
char *passin = NULL, *passout = NULL, *passinarg = NULL, *passoutarg = NULL;
75
OPTION_CHOICE o;
76
int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, text = 0, noout = 0;
77
int pubin = 0, pubout = 0, param_out = 0, ret = 1, private = 0;
78
int check = 0;
79
char *asn1_encoding = NULL;
80
char *point_format = NULL;
81
int no_public = 0;
82
83
opt_set_unknown_name("cipher");
84
prog = opt_init(argc, argv, ec_options);
85
while ((o = opt_next()) != OPT_EOF) {
86
switch (o) {
87
case OPT_EOF:
88
case OPT_ERR:
89
opthelp:
90
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
91
goto end;
92
case OPT_HELP:
93
opt_help(ec_options);
94
ret = 0;
95
goto end;
96
case OPT_INFORM:
97
if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
98
goto opthelp;
99
break;
100
case OPT_IN:
101
infile = opt_arg();
102
break;
103
case OPT_OUTFORM:
104
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
105
goto opthelp;
106
break;
107
case OPT_OUT:
108
outfile = opt_arg();
109
break;
110
case OPT_NOOUT:
111
noout = 1;
112
break;
113
case OPT_TEXT:
114
text = 1;
115
break;
116
case OPT_PARAM_OUT:
117
param_out = 1;
118
break;
119
case OPT_PUBIN:
120
pubin = 1;
121
break;
122
case OPT_PUBOUT:
123
pubout = 1;
124
break;
125
case OPT_PASSIN:
126
passinarg = opt_arg();
127
break;
128
case OPT_PASSOUT:
129
passoutarg = opt_arg();
130
break;
131
case OPT_ENGINE:
132
e = setup_engine(opt_arg(), 0);
133
break;
134
case OPT_CIPHER:
135
ciphername = opt_unknown();
136
break;
137
case OPT_CONV_FORM:
138
point_format = opt_arg();
139
if (!opt_string(point_format, point_format_options))
140
goto opthelp;
141
break;
142
case OPT_PARAM_ENC:
143
asn1_encoding = opt_arg();
144
if (!opt_string(asn1_encoding, asn1_encoding_options))
145
goto opthelp;
146
break;
147
case OPT_NO_PUBLIC:
148
no_public = 1;
149
break;
150
case OPT_CHECK:
151
check = 1;
152
break;
153
case OPT_PROV_CASES:
154
if (!opt_provider(o))
155
goto end;
156
break;
157
}
158
}
159
160
/* No extra arguments. */
161
if (!opt_check_rest_arg(NULL))
162
goto opthelp;
163
164
if (!opt_cipher(ciphername, &enc))
165
goto opthelp;
166
private = !pubin && (text || (!param_out && !pubout));
167
168
if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
169
BIO_printf(bio_err, "Error getting passwords\n");
170
goto end;
171
}
172
173
BIO_printf(bio_err, "read EC key\n");
174
175
if (pubin)
176
eckey = load_pubkey(infile, informat, 1, passin, e, "public key");
177
else
178
eckey = load_key(infile, informat, 1, passin, e, "private key");
179
180
if (eckey == NULL) {
181
BIO_printf(bio_err, "unable to load Key\n");
182
goto end;
183
}
184
185
out = bio_open_owner(outfile, outformat, private);
186
if (out == NULL)
187
goto end;
188
189
if (point_format
190
&& !EVP_PKEY_set_utf8_string_param(
191
eckey, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
192
point_format)) {
193
BIO_printf(bio_err, "unable to set point conversion format\n");
194
goto end;
195
}
196
197
if (asn1_encoding != NULL
198
&& !EVP_PKEY_set_utf8_string_param(
199
eckey, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
200
BIO_printf(bio_err, "unable to set asn1 encoding format\n");
201
goto end;
202
}
203
204
if (no_public) {
205
if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0)) {
206
BIO_printf(bio_err, "unable to disable public key encoding\n");
207
goto end;
208
}
209
} else {
210
if (!EVP_PKEY_set_int_param(eckey, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 1)) {
211
BIO_printf(bio_err, "unable to enable public key encoding\n");
212
goto end;
213
}
214
}
215
216
if (text) {
217
assert(pubin || private);
218
if ((pubin && EVP_PKEY_print_public(out, eckey, 0, NULL) <= 0)
219
|| (!pubin && EVP_PKEY_print_private(out, eckey, 0, NULL) <= 0)) {
220
BIO_printf(bio_err, "unable to print EC key\n");
221
goto end;
222
}
223
}
224
225
if (check) {
226
pctx = EVP_PKEY_CTX_new_from_pkey(NULL, eckey, NULL);
227
if (pctx == NULL) {
228
BIO_printf(bio_err, "unable to check EC key\n");
229
goto end;
230
}
231
if (EVP_PKEY_check(pctx) <= 0)
232
BIO_printf(bio_err, "EC Key Invalid!\n");
233
else
234
BIO_printf(bio_err, "EC Key valid.\n");
235
ERR_print_errors(bio_err);
236
}
237
238
if (!noout) {
239
int selection;
240
const char *output_type = outformat == FORMAT_ASN1 ? "DER" : "PEM";
241
const char *output_structure = "type-specific";
242
243
BIO_printf(bio_err, "writing EC key\n");
244
if (param_out) {
245
selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
246
} else if (pubin || pubout) {
247
selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
248
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
249
output_structure = "SubjectPublicKeyInfo";
250
} else {
251
selection = OSSL_KEYMGMT_SELECT_ALL;
252
assert(private);
253
}
254
255
ectx = OSSL_ENCODER_CTX_new_for_pkey(eckey, selection,
256
output_type, output_structure,
257
NULL);
258
if (enc != NULL) {
259
OSSL_ENCODER_CTX_set_cipher(ectx, EVP_CIPHER_get0_name(enc), NULL);
260
/* Default passphrase prompter */
261
OSSL_ENCODER_CTX_set_passphrase_ui(ectx, get_ui_method(), NULL);
262
if (passout != NULL)
263
/* When passout given, override the passphrase prompter */
264
OSSL_ENCODER_CTX_set_passphrase(ectx,
265
(const unsigned char *)passout,
266
strlen(passout));
267
}
268
if (!OSSL_ENCODER_to_bio(ectx, out)) {
269
BIO_printf(bio_err, "unable to write EC key\n");
270
goto end;
271
}
272
}
273
274
ret = 0;
275
end:
276
if (ret != 0)
277
ERR_print_errors(bio_err);
278
BIO_free_all(out);
279
EVP_PKEY_free(eckey);
280
EVP_CIPHER_free(enc);
281
OSSL_ENCODER_CTX_free(ectx);
282
OSSL_DECODER_CTX_free(dctx);
283
EVP_PKEY_CTX_free(pctx);
284
release_engine(e);
285
if (passin != NULL)
286
OPENSSL_clear_free(passin, strlen(passin));
287
if (passout != NULL)
288
OPENSSL_clear_free(passout, strlen(passout));
289
return ret;
290
}
291
292