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