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