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
generate_dsa_params(OSSL_LIB_CTX * libctx,EVP_PKEY ** p_params)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, ¶ms) <= 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
generate_dsa_key(OSSL_LIB_CTX * libctx,EVP_PKEY * params,EVP_PKEY ** p_pkey)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
extract_public_key(const EVP_PKEY * pkey,OSSL_PARAM ** p_public_key)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
extract_keypair(const EVP_PKEY * pkey,OSSL_PARAM ** p_keypair)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
demo_sign(OSSL_LIB_CTX * libctx,size_t * p_sig_len,unsigned char ** p_sig_value,OSSL_PARAM keypair[])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
demo_verify(OSSL_LIB_CTX * libctx,size_t sig_len,unsigned char * sig_value,OSSL_PARAM public_key[])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
main(void)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, ¶ms) != 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