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