Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/demos/pkey/EVP_PKEY_EC_keygen.c
34907 views
1
/*-
2
* Copyright 2021-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
/*
11
* Example showing how to generate an EC key and extract values from the
12
* generated key.
13
*/
14
15
#include <string.h>
16
#include <stdio.h>
17
#include <openssl/err.h>
18
#include <openssl/evp.h>
19
#include <openssl/core_names.h>
20
21
static int get_key_values(EVP_PKEY *pkey);
22
23
/*
24
* The following code shows how to generate an EC key from a curve name
25
* with additional parameters. If only the curve name is required then the
26
* simple helper can be used instead i.e. Either
27
* pkey = EVP_EC_gen(curvename); OR
28
* pkey = EVP_PKEY_Q_keygen(libctx, propq, "EC", curvename);
29
*/
30
static EVP_PKEY *do_ec_keygen(void)
31
{
32
/*
33
* The libctx and propq can be set if required, they are included here
34
* to show how they are passed to EVP_PKEY_CTX_new_from_name().
35
*/
36
OSSL_LIB_CTX *libctx = NULL;
37
const char *propq = NULL;
38
EVP_PKEY *key = NULL;
39
OSSL_PARAM params[3];
40
EVP_PKEY_CTX *genctx = NULL;
41
const char *curvename = "P-256";
42
int use_cofactordh = 1;
43
44
genctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq);
45
if (genctx == NULL) {
46
fprintf(stderr, "EVP_PKEY_CTX_new_from_name() failed\n");
47
goto cleanup;
48
}
49
50
if (EVP_PKEY_keygen_init(genctx) <= 0) {
51
fprintf(stderr, "EVP_PKEY_keygen_init() failed\n");
52
goto cleanup;
53
}
54
55
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
56
(char *)curvename, 0);
57
/*
58
* This is an optional parameter.
59
* For many curves where the cofactor is 1, setting this has no effect.
60
*/
61
params[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
62
&use_cofactordh);
63
params[2] = OSSL_PARAM_construct_end();
64
if (!EVP_PKEY_CTX_set_params(genctx, params)) {
65
fprintf(stderr, "EVP_PKEY_CTX_set_params() failed\n");
66
goto cleanup;
67
}
68
69
fprintf(stdout, "Generating EC key\n\n");
70
if (EVP_PKEY_generate(genctx, &key) <= 0) {
71
fprintf(stderr, "EVP_PKEY_generate() failed\n");
72
goto cleanup;
73
}
74
cleanup:
75
EVP_PKEY_CTX_free(genctx);
76
return key;
77
}
78
79
/*
80
* The following code shows how retrieve key data from the generated
81
* EC key. See doc/man7/EVP_PKEY-EC.pod for more information.
82
*
83
* EVP_PKEY_print_private() could also be used to display the values.
84
*/
85
static int get_key_values(EVP_PKEY *pkey)
86
{
87
int ret = 0;
88
char out_curvename[80];
89
unsigned char out_pubkey[80];
90
unsigned char out_privkey[80];
91
BIGNUM *out_priv = NULL;
92
size_t out_pubkey_len, out_privkey_len = 0;
93
94
if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
95
out_curvename, sizeof(out_curvename),
96
NULL)) {
97
fprintf(stderr, "Failed to get curve name\n");
98
goto cleanup;
99
}
100
101
if (!EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
102
out_pubkey, sizeof(out_pubkey),
103
&out_pubkey_len)) {
104
fprintf(stderr, "Failed to get public key\n");
105
goto cleanup;
106
}
107
108
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &out_priv)) {
109
fprintf(stderr, "Failed to get private key\n");
110
goto cleanup;
111
}
112
113
out_privkey_len = BN_bn2bin(out_priv, out_privkey);
114
if (out_privkey_len <= 0 || out_privkey_len > sizeof(out_privkey)) {
115
fprintf(stderr, "BN_bn2bin failed\n");
116
goto cleanup;
117
}
118
119
fprintf(stdout, "Curve name: %s\n", out_curvename);
120
fprintf(stdout, "Public key:\n");
121
BIO_dump_indent_fp(stdout, out_pubkey, out_pubkey_len, 2);
122
fprintf(stdout, "Private Key:\n");
123
BIO_dump_indent_fp(stdout, out_privkey, out_privkey_len, 2);
124
125
ret = 1;
126
cleanup:
127
/* Zeroize the private key data when we free it */
128
BN_clear_free(out_priv);
129
return ret;
130
}
131
132
int main(void)
133
{
134
int ret = EXIT_FAILURE;
135
EVP_PKEY *pkey;
136
137
pkey = do_ec_keygen();
138
if (pkey == NULL)
139
goto cleanup;
140
141
if (!get_key_values(pkey))
142
goto cleanup;
143
144
/*
145
* At this point we can write out the generated key using
146
* i2d_PrivateKey() and i2d_PublicKey() if required.
147
*/
148
ret = EXIT_SUCCESS;
149
cleanup:
150
if (ret != EXIT_SUCCESS)
151
ERR_print_errors_fp(stderr);
152
153
EVP_PKEY_free(pkey);
154
return ret;
155
}
156
157