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