xref: /freebsd-src/crypto/openssl/demos/signature/EVP_Signature_demo.c (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1*e0c4386eSCy Schubert /*-
2*e0c4386eSCy Schubert  * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
3*e0c4386eSCy Schubert  *
4*e0c4386eSCy Schubert  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e0c4386eSCy Schubert  * this file except in compliance with the License.  You can obtain a copy
6*e0c4386eSCy Schubert  * in the file LICENSE in the source distribution or at
7*e0c4386eSCy Schubert  * https://www.openssl.org/source/license.html
8*e0c4386eSCy Schubert  */
9*e0c4386eSCy Schubert 
10*e0c4386eSCy Schubert /*
11*e0c4386eSCy Schubert  * An example that uses the EVP_MD*, EVP_DigestSign* and EVP_DigestVerify*
12*e0c4386eSCy Schubert  * methods to calculate and verify a signature of two static buffers.
13*e0c4386eSCy Schubert  */
14*e0c4386eSCy Schubert 
15*e0c4386eSCy Schubert #include <string.h>
16*e0c4386eSCy Schubert #include <stdio.h>
17*e0c4386eSCy Schubert #include <openssl/err.h>
18*e0c4386eSCy Schubert #include <openssl/evp.h>
19*e0c4386eSCy Schubert #include <openssl/decoder.h>
20*e0c4386eSCy Schubert #include "EVP_Signature_demo.h"
21*e0c4386eSCy Schubert 
22*e0c4386eSCy Schubert /*
23*e0c4386eSCy Schubert  * This demonstration will calculate and verify a signature of data using
24*e0c4386eSCy Schubert  * the soliloquy from Hamlet scene 1 act 3
25*e0c4386eSCy Schubert  */
26*e0c4386eSCy Schubert 
27*e0c4386eSCy Schubert static const char *hamlet_1 =
28*e0c4386eSCy Schubert     "To be, or not to be, that is the question,\n"
29*e0c4386eSCy Schubert     "Whether tis nobler in the minde to suffer\n"
30*e0c4386eSCy Schubert     "The slings and arrowes of outragious fortune,\n"
31*e0c4386eSCy Schubert     "Or to take Armes again in a sea of troubles,\n"
32*e0c4386eSCy Schubert ;
33*e0c4386eSCy Schubert static const char *hamlet_2 =
34*e0c4386eSCy Schubert     "And by opposing, end them, to die to sleep;\n"
35*e0c4386eSCy Schubert     "No more, and by a sleep, to say we end\n"
36*e0c4386eSCy Schubert     "The heart-ache, and the thousand natural shocks\n"
37*e0c4386eSCy Schubert     "That flesh is heir to? tis a consumation\n"
38*e0c4386eSCy Schubert ;
39*e0c4386eSCy Schubert 
40*e0c4386eSCy Schubert /*
41*e0c4386eSCy Schubert  * For demo_sign, load EC private key priv_key from priv_key_der[].
42*e0c4386eSCy Schubert  * For demo_verify, load EC public key pub_key from pub_key_der[].
43*e0c4386eSCy Schubert  */
get_key(OSSL_LIB_CTX * libctx,const char * propq,int public)44*e0c4386eSCy Schubert static EVP_PKEY *get_key(OSSL_LIB_CTX *libctx, const char *propq, int public)
45*e0c4386eSCy Schubert {
46*e0c4386eSCy Schubert     OSSL_DECODER_CTX *dctx = NULL;
47*e0c4386eSCy Schubert     EVP_PKEY  *pkey = NULL;
48*e0c4386eSCy Schubert     int selection;
49*e0c4386eSCy Schubert     const unsigned char *data;
50*e0c4386eSCy Schubert     size_t data_len;
51*e0c4386eSCy Schubert 
52*e0c4386eSCy Schubert     if (public) {
53*e0c4386eSCy Schubert         selection = EVP_PKEY_PUBLIC_KEY;
54*e0c4386eSCy Schubert         data =  pub_key_der;
55*e0c4386eSCy Schubert         data_len = sizeof(pub_key_der);
56*e0c4386eSCy Schubert     } else {
57*e0c4386eSCy Schubert         selection =  EVP_PKEY_KEYPAIR;
58*e0c4386eSCy Schubert         data = priv_key_der;
59*e0c4386eSCy Schubert         data_len = sizeof(priv_key_der);
60*e0c4386eSCy Schubert     }
61*e0c4386eSCy Schubert     dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC",
62*e0c4386eSCy Schubert                                          selection, libctx, propq);
63*e0c4386eSCy Schubert     (void)OSSL_DECODER_from_data(dctx, &data, &data_len);
64*e0c4386eSCy Schubert     OSSL_DECODER_CTX_free(dctx);
65*e0c4386eSCy Schubert     if (pkey == NULL)
66*e0c4386eSCy Schubert         fprintf(stderr, "Failed to load %s key.\n", public ? "public" : "private");
67*e0c4386eSCy Schubert     return pkey;
68*e0c4386eSCy Schubert }
69*e0c4386eSCy Schubert 
demo_sign(OSSL_LIB_CTX * libctx,const char * sig_name,size_t * sig_out_len,unsigned char ** sig_out_value)70*e0c4386eSCy Schubert static int demo_sign(OSSL_LIB_CTX *libctx,  const char *sig_name,
71*e0c4386eSCy Schubert                      size_t *sig_out_len, unsigned char **sig_out_value)
72*e0c4386eSCy Schubert {
73*e0c4386eSCy Schubert     int result = 0, public = 0;
74*e0c4386eSCy Schubert     size_t sig_len;
75*e0c4386eSCy Schubert     unsigned char *sig_value = NULL;
76*e0c4386eSCy Schubert     const char *propq = NULL;
77*e0c4386eSCy Schubert     EVP_MD_CTX *sign_context = NULL;
78*e0c4386eSCy Schubert     EVP_PKEY *priv_key = NULL;
79*e0c4386eSCy Schubert 
80*e0c4386eSCy Schubert     /* Get private key */
81*e0c4386eSCy Schubert     priv_key = get_key(libctx, propq, public);
82*e0c4386eSCy Schubert     if (priv_key == NULL) {
83*e0c4386eSCy Schubert         fprintf(stderr, "Get private key failed.\n");
84*e0c4386eSCy Schubert         goto cleanup;
85*e0c4386eSCy Schubert     }
86*e0c4386eSCy Schubert     /*
87*e0c4386eSCy Schubert      * Make a message signature context to hold temporary state
88*e0c4386eSCy Schubert      * during signature creation
89*e0c4386eSCy Schubert      */
90*e0c4386eSCy Schubert     sign_context = EVP_MD_CTX_new();
91*e0c4386eSCy Schubert     if (sign_context == NULL) {
92*e0c4386eSCy Schubert         fprintf(stderr, "EVP_MD_CTX_new failed.\n");
93*e0c4386eSCy Schubert         goto cleanup;
94*e0c4386eSCy Schubert     }
95*e0c4386eSCy Schubert     /*
96*e0c4386eSCy Schubert      * Initialize the sign context to use the fetched
97*e0c4386eSCy Schubert      * sign provider.
98*e0c4386eSCy Schubert      */
99*e0c4386eSCy Schubert     if (!EVP_DigestSignInit_ex(sign_context, NULL, sig_name,
100*e0c4386eSCy Schubert                               libctx, NULL, priv_key, NULL)) {
101*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestSignInit_ex failed.\n");
102*e0c4386eSCy Schubert         goto cleanup;
103*e0c4386eSCy Schubert     }
104*e0c4386eSCy Schubert     /*
105*e0c4386eSCy Schubert      * EVP_DigestSignUpdate() can be called several times on the same context
106*e0c4386eSCy Schubert      * to include additional data.
107*e0c4386eSCy Schubert      */
108*e0c4386eSCy Schubert     if (!EVP_DigestSignUpdate(sign_context, hamlet_1, strlen(hamlet_1))) {
109*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestSignUpdate(hamlet_1) failed.\n");
110*e0c4386eSCy Schubert         goto cleanup;
111*e0c4386eSCy Schubert     }
112*e0c4386eSCy Schubert     if (!EVP_DigestSignUpdate(sign_context, hamlet_2, strlen(hamlet_2))) {
113*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestSignUpdate(hamlet_2) failed.\n");
114*e0c4386eSCy Schubert         goto cleanup;
115*e0c4386eSCy Schubert     }
116*e0c4386eSCy Schubert     /* Call EVP_DigestSignFinal to get signature length sig_len */
117*e0c4386eSCy Schubert     if (!EVP_DigestSignFinal(sign_context, NULL, &sig_len)) {
118*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestSignFinal failed.\n");
119*e0c4386eSCy Schubert         goto cleanup;
120*e0c4386eSCy Schubert     }
121*e0c4386eSCy Schubert     if (sig_len <= 0) {
122*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestSignFinal returned invalid signature length.\n");
123*e0c4386eSCy Schubert         goto cleanup;
124*e0c4386eSCy Schubert     }
125*e0c4386eSCy Schubert     sig_value = OPENSSL_malloc(sig_len);
126*e0c4386eSCy Schubert     if (sig_value == NULL) {
127*e0c4386eSCy Schubert         fprintf(stderr, "No memory.\n");
128*e0c4386eSCy Schubert         goto cleanup;
129*e0c4386eSCy Schubert     }
130*e0c4386eSCy Schubert     if (!EVP_DigestSignFinal(sign_context, sig_value, &sig_len)) {
131*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestSignFinal failed.\n");
132*e0c4386eSCy Schubert         goto cleanup;
133*e0c4386eSCy Schubert     }
134*e0c4386eSCy Schubert     *sig_out_len = sig_len;
135*e0c4386eSCy Schubert     *sig_out_value = sig_value;
136*e0c4386eSCy Schubert     fprintf(stdout, "Generating signature:\n");
137*e0c4386eSCy Schubert     BIO_dump_indent_fp(stdout, sig_value, sig_len, 2);
138*e0c4386eSCy Schubert     fprintf(stdout, "\n");
139*e0c4386eSCy Schubert     result = 1;
140*e0c4386eSCy Schubert 
141*e0c4386eSCy Schubert cleanup:
142*e0c4386eSCy Schubert     /* OpenSSL free functions will ignore NULL arguments */
143*e0c4386eSCy Schubert     if (!result)
144*e0c4386eSCy Schubert         OPENSSL_free(sig_value);
145*e0c4386eSCy Schubert     EVP_PKEY_free(priv_key);
146*e0c4386eSCy Schubert     EVP_MD_CTX_free(sign_context);
147*e0c4386eSCy Schubert     return result;
148*e0c4386eSCy Schubert }
149*e0c4386eSCy Schubert 
demo_verify(OSSL_LIB_CTX * libctx,const char * sig_name,size_t sig_len,unsigned char * sig_value)150*e0c4386eSCy Schubert static int demo_verify(OSSL_LIB_CTX *libctx, const char *sig_name,
151*e0c4386eSCy Schubert                        size_t sig_len, unsigned char *sig_value)
152*e0c4386eSCy Schubert {
153*e0c4386eSCy Schubert     int result = 0, public = 1;
154*e0c4386eSCy Schubert     const char *propq = NULL;
155*e0c4386eSCy Schubert     EVP_MD_CTX *verify_context = NULL;
156*e0c4386eSCy Schubert     EVP_PKEY *pub_key = NULL;
157*e0c4386eSCy Schubert 
158*e0c4386eSCy Schubert     /*
159*e0c4386eSCy Schubert      * Make a verify signature context to hold temporary state
160*e0c4386eSCy Schubert      * during signature verification
161*e0c4386eSCy Schubert      */
162*e0c4386eSCy Schubert     verify_context = EVP_MD_CTX_new();
163*e0c4386eSCy Schubert     if (verify_context == NULL) {
164*e0c4386eSCy Schubert         fprintf(stderr, "EVP_MD_CTX_new failed.\n");
165*e0c4386eSCy Schubert         goto cleanup;
166*e0c4386eSCy Schubert     }
167*e0c4386eSCy Schubert     /* Get public key */
168*e0c4386eSCy Schubert     pub_key = get_key(libctx, propq, public);
169*e0c4386eSCy Schubert     if (pub_key == NULL) {
170*e0c4386eSCy Schubert         fprintf(stderr, "Get public key failed.\n");
171*e0c4386eSCy Schubert         goto cleanup;
172*e0c4386eSCy Schubert     }
173*e0c4386eSCy Schubert     /* Verify */
174*e0c4386eSCy Schubert     if (!EVP_DigestVerifyInit_ex(verify_context, NULL, sig_name,
175*e0c4386eSCy Schubert                                 libctx, NULL, pub_key, NULL)) {
176*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestVerifyInit failed.\n");
177*e0c4386eSCy Schubert         goto cleanup;
178*e0c4386eSCy Schubert     }
179*e0c4386eSCy Schubert     /*
180*e0c4386eSCy Schubert      * EVP_DigestVerifyUpdate() can be called several times on the same context
181*e0c4386eSCy Schubert      * to include additional data.
182*e0c4386eSCy Schubert      */
183*e0c4386eSCy Schubert     if (!EVP_DigestVerifyUpdate(verify_context, hamlet_1, strlen(hamlet_1))) {
184*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestVerifyUpdate(hamlet_1) failed.\n");
185*e0c4386eSCy Schubert         goto cleanup;
186*e0c4386eSCy Schubert     }
187*e0c4386eSCy Schubert     if (!EVP_DigestVerifyUpdate(verify_context, hamlet_2, strlen(hamlet_2))) {
188*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestVerifyUpdate(hamlet_2) failed.\n");
189*e0c4386eSCy Schubert         goto cleanup;
190*e0c4386eSCy Schubert     }
191*e0c4386eSCy Schubert     if (EVP_DigestVerifyFinal(verify_context, sig_value, sig_len) <= 0) {
192*e0c4386eSCy Schubert         fprintf(stderr, "EVP_DigestVerifyFinal failed.\n");
193*e0c4386eSCy Schubert         goto cleanup;
194*e0c4386eSCy Schubert     }
195*e0c4386eSCy Schubert     fprintf(stdout, "Signature verified.\n");
196*e0c4386eSCy Schubert     result = 1;
197*e0c4386eSCy Schubert 
198*e0c4386eSCy Schubert cleanup:
199*e0c4386eSCy Schubert     /* OpenSSL free functions will ignore NULL arguments */
200*e0c4386eSCy Schubert     EVP_PKEY_free(pub_key);
201*e0c4386eSCy Schubert     EVP_MD_CTX_free(verify_context);
202*e0c4386eSCy Schubert     return result;
203*e0c4386eSCy Schubert }
204*e0c4386eSCy Schubert 
main(void)205*e0c4386eSCy Schubert int main(void)
206*e0c4386eSCy Schubert {
207*e0c4386eSCy Schubert     OSSL_LIB_CTX *libctx = NULL;
208*e0c4386eSCy Schubert     const char *sig_name = "SHA3-512";
209*e0c4386eSCy Schubert     size_t sig_len = 0;
210*e0c4386eSCy Schubert     unsigned char *sig_value = NULL;
211*e0c4386eSCy Schubert     int result = 0;
212*e0c4386eSCy Schubert 
213*e0c4386eSCy Schubert     libctx = OSSL_LIB_CTX_new();
214*e0c4386eSCy Schubert     if (libctx == NULL) {
215*e0c4386eSCy Schubert         fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
216*e0c4386eSCy Schubert         goto cleanup;
217*e0c4386eSCy Schubert     }
218*e0c4386eSCy Schubert     if (!demo_sign(libctx, sig_name, &sig_len, &sig_value)) {
219*e0c4386eSCy Schubert         fprintf(stderr, "demo_sign failed.\n");
220*e0c4386eSCy Schubert         goto cleanup;
221*e0c4386eSCy Schubert     }
222*e0c4386eSCy Schubert     if (!demo_verify(libctx, sig_name, sig_len, sig_value)) {
223*e0c4386eSCy Schubert         fprintf(stderr, "demo_verify failed.\n");
224*e0c4386eSCy Schubert         goto cleanup;
225*e0c4386eSCy Schubert     }
226*e0c4386eSCy Schubert     result = 1;
227*e0c4386eSCy Schubert 
228*e0c4386eSCy Schubert cleanup:
229*e0c4386eSCy Schubert     if (result != 1)
230*e0c4386eSCy Schubert         ERR_print_errors_fp(stderr);
231*e0c4386eSCy Schubert     /* OpenSSL free functions will ignore NULL arguments */
232*e0c4386eSCy Schubert     OSSL_LIB_CTX_free(libctx);
233*e0c4386eSCy Schubert     OPENSSL_free(sig_value);
234*e0c4386eSCy Schubert     return result == 0;
235*e0c4386eSCy Schubert }
236