Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/demos/signature/EVP_DSA_Signature_demo.c
112997 views
1
/*-
2
* Copyright 2022-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
* An example that uses the EVP_PKEY*, EVP_DigestSign* and EVP_DigestVerify*
12
* methods to calculate public/private DSA keypair and to sign and verify
13
* two static buffers.
14
*/
15
16
#include <string.h>
17
#include <stdio.h>
18
#include <openssl/err.h>
19
#include <openssl/evp.h>
20
#include <openssl/decoder.h>
21
#include <openssl/dsa.h>
22
23
/*
24
* This demonstration will calculate and verify a signature of data using
25
* the soliloquy from Hamlet scene 1 act 3
26
*/
27
28
static const char *hamlet_1 = "To be, or not to be, that is the question,\n"
29
"Whether tis nobler in the minde to suffer\n"
30
"The slings and arrowes of outragious fortune,\n"
31
"Or to take Armes again in a sea of troubles,\n";
32
static const char *hamlet_2 = "And by opposing, end them, to die to sleep;\n"
33
"No more, and by a sleep, to say we end\n"
34
"The heart-ache, and the thousand natural shocks\n"
35
"That flesh is heir to? tis a consumation\n";
36
37
static const char ALG[] = "DSA";
38
static const char DIGEST[] = "SHA256";
39
static const int NUMBITS = 2048;
40
static const char *const PROPQUERY = NULL;
41
42
static int generate_dsa_params(OSSL_LIB_CTX *libctx,
43
EVP_PKEY **p_params)
44
{
45
int ret = 0;
46
47
EVP_PKEY_CTX *pkey_ctx = NULL;
48
EVP_PKEY *params = NULL;
49
50
pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY);
51
if (pkey_ctx == NULL)
52
goto end;
53
54
if (EVP_PKEY_paramgen_init(pkey_ctx) <= 0)
55
goto end;
56
57
if (EVP_PKEY_CTX_set_dsa_paramgen_bits(pkey_ctx, NUMBITS) <= 0)
58
goto end;
59
if (EVP_PKEY_paramgen(pkey_ctx, &params) <= 0)
60
goto end;
61
if (params == NULL)
62
goto end;
63
64
ret = 1;
65
end:
66
if (ret != 1) {
67
EVP_PKEY_free(params);
68
params = NULL;
69
}
70
EVP_PKEY_CTX_free(pkey_ctx);
71
*p_params = params;
72
fprintf(stdout, "Params:\n");
73
EVP_PKEY_print_params_fp(stdout, params, 4, NULL);
74
fprintf(stdout, "\n");
75
76
return ret;
77
}
78
79
static int generate_dsa_key(OSSL_LIB_CTX *libctx,
80
EVP_PKEY *params,
81
EVP_PKEY **p_pkey)
82
{
83
int ret = 0;
84
85
EVP_PKEY_CTX *ctx = NULL;
86
EVP_PKEY *pkey = NULL;
87
88
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, params,
89
NULL);
90
if (ctx == NULL)
91
goto end;
92
if (EVP_PKEY_keygen_init(ctx) <= 0)
93
goto end;
94
95
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
96
goto end;
97
if (pkey == NULL)
98
goto end;
99
100
ret = 1;
101
end:
102
if (ret != 1) {
103
EVP_PKEY_free(pkey);
104
pkey = NULL;
105
}
106
EVP_PKEY_CTX_free(ctx);
107
*p_pkey = pkey;
108
fprintf(stdout, "Generating public/private key pair:\n");
109
EVP_PKEY_print_public_fp(stdout, pkey, 4, NULL);
110
fprintf(stdout, "\n");
111
EVP_PKEY_print_private_fp(stdout, pkey, 4, NULL);
112
fprintf(stdout, "\n");
113
EVP_PKEY_print_params_fp(stdout, pkey, 4, NULL);
114
fprintf(stdout, "\n");
115
116
return ret;
117
}
118
119
static int extract_public_key(const EVP_PKEY *pkey,
120
OSSL_PARAM **p_public_key)
121
{
122
int ret = 0;
123
OSSL_PARAM *public_key = NULL;
124
125
if (EVP_PKEY_todata(pkey, EVP_PKEY_PUBLIC_KEY, &public_key) != 1)
126
goto end;
127
128
ret = 1;
129
end:
130
if (ret != 1) {
131
OSSL_PARAM_free(public_key);
132
public_key = NULL;
133
}
134
*p_public_key = public_key;
135
136
return ret;
137
}
138
139
static int extract_keypair(const EVP_PKEY *pkey,
140
OSSL_PARAM **p_keypair)
141
{
142
int ret = 0;
143
OSSL_PARAM *keypair = NULL;
144
145
if (EVP_PKEY_todata(pkey, EVP_PKEY_KEYPAIR, &keypair) != 1)
146
goto end;
147
148
ret = 1;
149
end:
150
if (ret != 1) {
151
OSSL_PARAM_free(keypair);
152
keypair = NULL;
153
}
154
*p_keypair = keypair;
155
156
return ret;
157
}
158
159
static int demo_sign(OSSL_LIB_CTX *libctx,
160
size_t *p_sig_len, unsigned char **p_sig_value,
161
OSSL_PARAM keypair[])
162
{
163
int ret = 0;
164
size_t sig_len = 0;
165
unsigned char *sig_value = NULL;
166
EVP_MD_CTX *ctx = NULL;
167
EVP_PKEY_CTX *pkey_ctx = NULL;
168
EVP_PKEY *pkey = NULL;
169
170
pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY);
171
if (pkey_ctx == NULL)
172
goto end;
173
if (EVP_PKEY_fromdata_init(pkey_ctx) != 1)
174
goto end;
175
if (EVP_PKEY_fromdata(pkey_ctx, &pkey, EVP_PKEY_KEYPAIR, keypair) != 1)
176
goto end;
177
178
ctx = EVP_MD_CTX_create();
179
if (ctx == NULL)
180
goto end;
181
182
if (EVP_DigestSignInit_ex(ctx, NULL, DIGEST, libctx, NULL, pkey, NULL) != 1)
183
goto end;
184
185
if (EVP_DigestSignUpdate(ctx, hamlet_1, sizeof(hamlet_1)) != 1)
186
goto end;
187
188
if (EVP_DigestSignUpdate(ctx, hamlet_2, sizeof(hamlet_2)) != 1)
189
goto end;
190
191
/* Calculate the signature size */
192
if (EVP_DigestSignFinal(ctx, NULL, &sig_len) != 1)
193
goto end;
194
if (sig_len == 0)
195
goto end;
196
197
sig_value = OPENSSL_malloc(sig_len);
198
if (sig_value == NULL)
199
goto end;
200
201
/* Calculate the signature */
202
if (EVP_DigestSignFinal(ctx, sig_value, &sig_len) != 1)
203
goto end;
204
205
ret = 1;
206
end:
207
EVP_MD_CTX_free(ctx);
208
if (ret != 1) {
209
OPENSSL_free(sig_value);
210
sig_len = 0;
211
sig_value = NULL;
212
}
213
*p_sig_len = sig_len;
214
*p_sig_value = sig_value;
215
EVP_PKEY_free(pkey);
216
EVP_PKEY_CTX_free(pkey_ctx);
217
218
fprintf(stdout, "Generating signature:\n");
219
BIO_dump_indent_fp(stdout, sig_value, sig_len, 2);
220
fprintf(stdout, "\n");
221
return ret;
222
}
223
224
static int demo_verify(OSSL_LIB_CTX *libctx,
225
size_t sig_len, unsigned char *sig_value,
226
OSSL_PARAM public_key[])
227
{
228
int ret = 0;
229
EVP_MD_CTX *ctx = NULL;
230
EVP_PKEY_CTX *pkey_ctx = NULL;
231
EVP_PKEY *pkey = NULL;
232
233
pkey_ctx = EVP_PKEY_CTX_new_from_name(libctx, ALG, PROPQUERY);
234
if (pkey_ctx == NULL)
235
goto end;
236
if (EVP_PKEY_fromdata_init(pkey_ctx) != 1)
237
goto end;
238
if (EVP_PKEY_fromdata(pkey_ctx, &pkey, EVP_PKEY_PUBLIC_KEY, public_key) != 1)
239
goto end;
240
241
ctx = EVP_MD_CTX_create();
242
if (ctx == NULL)
243
goto end;
244
245
if (EVP_DigestVerifyInit_ex(ctx, NULL, DIGEST, libctx, NULL, pkey, NULL) != 1)
246
goto end;
247
248
if (EVP_DigestVerifyUpdate(ctx, hamlet_1, sizeof(hamlet_1)) != 1)
249
goto end;
250
251
if (EVP_DigestVerifyUpdate(ctx, hamlet_2, sizeof(hamlet_2)) != 1)
252
goto end;
253
254
if (EVP_DigestVerifyFinal(ctx, sig_value, sig_len) != 1)
255
goto end;
256
257
ret = 1;
258
end:
259
EVP_PKEY_free(pkey);
260
EVP_PKEY_CTX_free(pkey_ctx);
261
EVP_MD_CTX_free(ctx);
262
return ret;
263
}
264
265
int main(void)
266
{
267
int ret = EXIT_FAILURE;
268
OSSL_LIB_CTX *libctx = NULL;
269
EVP_PKEY *params = NULL;
270
EVP_PKEY *pkey = NULL;
271
OSSL_PARAM *public_key = NULL;
272
OSSL_PARAM *keypair = NULL;
273
size_t sig_len = 0;
274
unsigned char *sig_value = NULL;
275
276
libctx = OSSL_LIB_CTX_new();
277
if (libctx == NULL)
278
goto end;
279
280
if (generate_dsa_params(libctx, &params) != 1)
281
goto end;
282
283
if (generate_dsa_key(libctx, params, &pkey) != 1)
284
goto end;
285
286
if (extract_public_key(pkey, &public_key) != 1)
287
goto end;
288
289
if (extract_keypair(pkey, &keypair) != 1)
290
goto end;
291
292
/* The signer signs with his private key, and distributes his public key */
293
if (demo_sign(libctx, &sig_len, &sig_value, keypair) != 1)
294
goto end;
295
296
/* A verifier uses the signers public key to verify the signature */
297
if (demo_verify(libctx, sig_len, sig_value, public_key) != 1)
298
goto end;
299
300
ret = EXIT_SUCCESS;
301
end:
302
if (ret != EXIT_SUCCESS)
303
ERR_print_errors_fp(stderr);
304
305
OPENSSL_free(sig_value);
306
EVP_PKEY_free(params);
307
EVP_PKEY_free(pkey);
308
OSSL_PARAM_free(public_key);
309
OSSL_PARAM_free(keypair);
310
OSSL_LIB_CTX_free(libctx);
311
312
return ret;
313
}
314
315