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, ¶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 |
|
---|
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, ¶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 | }
|
---|