Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/demos/signature/EVP_ED_Signature_demo.c
34890 views
1
/*-
2
* Copyright 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
* This demonstration will calculate and verify an ED25519 signature of
12
* a message using EVP_DigestSign() and EVP_DigestVerify().
13
*/
14
15
#include <string.h>
16
#include <stdio.h>
17
#include <openssl/err.h>
18
#include <openssl/evp.h>
19
#include <openssl/core_names.h>
20
21
/* A test message to be signed (TBS) */
22
static const unsigned char hamlet[] =
23
"To be, or not to be, that is the question,\n"
24
"Whether tis nobler in the minde to suffer\n"
25
"The slings and arrowes of outragious fortune,\n"
26
"Or to take Armes again in a sea of troubles,\n";
27
28
static int demo_sign(EVP_PKEY *priv,
29
const unsigned char *tbs, size_t tbs_len,
30
OSSL_LIB_CTX *libctx,
31
unsigned char **sig_out_value,
32
size_t *sig_out_len)
33
{
34
int ret = 0;
35
size_t sig_len;
36
unsigned char *sig_value = NULL;
37
EVP_MD_CTX *sign_context = NULL;
38
39
/* Create a signature context */
40
sign_context = EVP_MD_CTX_new();
41
if (sign_context == NULL) {
42
fprintf(stderr, "EVP_MD_CTX_new failed.\n");
43
goto cleanup;
44
}
45
46
/*
47
* Initialize the sign context using an ED25519 private key
48
* Notice that the digest name must NOT be used.
49
* In this demo we don't specify any additional parameters via
50
* OSSL_PARAM, which means it will use default values.
51
* For more information, refer to doc/man7/EVP_SIGNATURE-ED25519.pod
52
* "ED25519 and ED448 Signature Parameters"
53
*/
54
if (!EVP_DigestSignInit_ex(sign_context, NULL, NULL, libctx, NULL, priv, NULL)) {
55
fprintf(stderr, "EVP_DigestSignInit_ex failed.\n");
56
goto cleanup;
57
}
58
59
/* Calculate the required size for the signature by passing a NULL buffer. */
60
if (!EVP_DigestSign(sign_context, NULL, &sig_len, tbs, tbs_len)) {
61
fprintf(stderr, "EVP_DigestSign using NULL buffer failed.\n");
62
goto cleanup;
63
}
64
sig_value = OPENSSL_malloc(sig_len);
65
if (sig_value == NULL) {
66
fprintf(stderr, "OPENSSL_malloc failed.\n");
67
goto cleanup;
68
}
69
fprintf(stdout, "Generating signature:\n");
70
if (!EVP_DigestSign(sign_context, sig_value, &sig_len, tbs, tbs_len)) {
71
fprintf(stderr, "EVP_DigestSign failed.\n");
72
goto cleanup;
73
}
74
*sig_out_len = sig_len;
75
*sig_out_value = sig_value;
76
BIO_dump_indent_fp(stdout, sig_value, sig_len, 2);
77
fprintf(stdout, "\n");
78
ret = 1;
79
80
cleanup:
81
if (!ret)
82
OPENSSL_free(sig_value);
83
EVP_MD_CTX_free(sign_context);
84
return ret;
85
}
86
87
static int demo_verify(EVP_PKEY *pub,
88
const unsigned char *tbs, size_t tbs_len,
89
const unsigned char *sig_value, size_t sig_len,
90
OSSL_LIB_CTX *libctx)
91
{
92
int ret = 0;
93
EVP_MD_CTX *verify_context = NULL;
94
95
/*
96
* Make a verify signature context to hold temporary state
97
* during signature verification
98
*/
99
verify_context = EVP_MD_CTX_new();
100
if (verify_context == NULL) {
101
fprintf(stderr, "EVP_MD_CTX_new failed.\n");
102
goto cleanup;
103
}
104
/* Initialize the verify context with a ED25519 public key */
105
if (!EVP_DigestVerifyInit_ex(verify_context, NULL, NULL,
106
libctx, NULL, pub, NULL)) {
107
fprintf(stderr, "EVP_DigestVerifyInit_ex failed.\n");
108
goto cleanup;
109
}
110
/*
111
* ED25519 only supports the one shot interface using EVP_DigestVerify()
112
* The streaming EVP_DigestVerifyUpdate() API is not supported.
113
*/
114
if (!EVP_DigestVerify(verify_context, sig_value, sig_len,
115
tbs, tbs_len)) {
116
fprintf(stderr, "EVP_DigestVerify() failed.\n");
117
goto cleanup;
118
}
119
fprintf(stdout, "Signature verified.\n");
120
ret = 1;
121
122
cleanup:
123
EVP_MD_CTX_free(verify_context);
124
return ret;
125
}
126
127
static int create_key(OSSL_LIB_CTX *libctx,
128
EVP_PKEY **privout, EVP_PKEY **pubout)
129
{
130
int ret = 0;
131
EVP_PKEY *priv = NULL, *pub = NULL;
132
unsigned char pubdata[32];
133
size_t pubdata_len = 0;
134
135
/*
136
* In this demo we just create a keypair, and extract the
137
* public key. We could also use EVP_PKEY_new_raw_private_key_ex()
138
* to create a key from raw data.
139
*/
140
priv = EVP_PKEY_Q_keygen(libctx, NULL, "ED25519");
141
if (priv == NULL) {
142
fprintf(stderr, "EVP_PKEY_Q_keygen() failed\n");
143
goto end;
144
}
145
146
if (!EVP_PKEY_get_octet_string_param(priv,
147
OSSL_PKEY_PARAM_PUB_KEY,
148
pubdata,
149
sizeof(pubdata),
150
&pubdata_len)) {
151
fprintf(stderr, "EVP_PKEY_get_octet_string_param() failed\n");
152
goto end;
153
}
154
pub = EVP_PKEY_new_raw_public_key_ex(libctx, "ED25519", NULL, pubdata, pubdata_len);
155
if (pub == NULL) {
156
fprintf(stderr, "EVP_PKEY_new_raw_public_key_ex() failed\n");
157
goto end;
158
}
159
ret = 1;
160
end:
161
if (ret) {
162
*pubout = pub;
163
*privout = priv;
164
} else {
165
EVP_PKEY_free(priv);
166
}
167
return ret;
168
}
169
170
int main(void)
171
{
172
OSSL_LIB_CTX *libctx = NULL;
173
size_t sig_len = 0;
174
unsigned char *sig_value = NULL;
175
int ret = EXIT_FAILURE;
176
EVP_PKEY *priv = NULL, *pub = NULL;
177
178
libctx = OSSL_LIB_CTX_new();
179
if (libctx == NULL) {
180
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
181
goto cleanup;
182
}
183
if (!create_key(libctx, &priv, &pub)) {
184
fprintf(stderr, "Failed to create key.\n");
185
goto cleanup;
186
}
187
188
if (!demo_sign(priv, hamlet, sizeof(hamlet), libctx,
189
&sig_value, &sig_len)) {
190
fprintf(stderr, "demo_sign failed.\n");
191
goto cleanup;
192
}
193
if (!demo_verify(pub, hamlet, sizeof(hamlet),
194
sig_value, sig_len, libctx)) {
195
fprintf(stderr, "demo_verify failed.\n");
196
goto cleanup;
197
}
198
ret = EXIT_SUCCESS;
199
200
cleanup:
201
if (ret != EXIT_SUCCESS)
202
ERR_print_errors_fp(stderr);
203
EVP_PKEY_free(pub);
204
EVP_PKEY_free(priv);
205
OSSL_LIB_CTX_free(libctx);
206
OPENSSL_free(sig_value);
207
return ret;
208
}
209
210