Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/demos/signature/rsa_pss_direct.c
110864 views
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
#include <stdio.h>
11
#include <stdlib.h>
12
#include <openssl/core_names.h>
13
#include <openssl/evp.h>
14
#include <openssl/rsa.h>
15
#include <openssl/params.h>
16
#include <openssl/err.h>
17
#include <openssl/bio.h>
18
#include "rsa_pss.h"
19
20
/*
21
* The digest to be signed. This should be the output of a hash function.
22
* Here we sign an all-zeroes digest for demonstration purposes.
23
*/
24
static const unsigned char test_digest[32] = { 0 };
25
26
/* A property query used for selecting algorithm implementations. */
27
static const char *propq = NULL;
28
29
/*
30
* This function demonstrates RSA signing of a SHA-256 digest using the PSS
31
* padding scheme. You must already have hashed the data you want to sign.
32
* For a higher-level demonstration which does the hashing for you, see
33
* rsa_pss_hash.c.
34
*
35
* For more information, see RFC 8017 section 9.1. The digest passed in
36
* (test_digest above) corresponds to the 'mHash' value.
37
*/
38
static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len)
39
{
40
int ret = 0;
41
EVP_PKEY *pkey = NULL;
42
EVP_PKEY_CTX *ctx = NULL;
43
EVP_MD *md = NULL;
44
const unsigned char *ppriv_key = NULL;
45
46
*sig = NULL;
47
48
/* Load DER-encoded RSA private key. */
49
ppriv_key = rsa_priv_key;
50
pkey = d2i_PrivateKey_ex(EVP_PKEY_RSA, NULL, &ppriv_key,
51
sizeof(rsa_priv_key), libctx, propq);
52
if (pkey == NULL) {
53
fprintf(stderr, "Failed to load private key\n");
54
goto end;
55
}
56
57
/* Fetch hash algorithm we want to use. */
58
md = EVP_MD_fetch(libctx, "SHA256", propq);
59
if (md == NULL) {
60
fprintf(stderr, "Failed to fetch hash algorithm\n");
61
goto end;
62
}
63
64
/* Create signing context. */
65
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
66
if (ctx == NULL) {
67
fprintf(stderr, "Failed to create signing context\n");
68
goto end;
69
}
70
71
/* Initialize context for signing and set options. */
72
if (EVP_PKEY_sign_init(ctx) == 0) {
73
fprintf(stderr, "Failed to initialize signing context\n");
74
goto end;
75
}
76
77
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) == 0) {
78
fprintf(stderr, "Failed to configure padding\n");
79
goto end;
80
}
81
82
if (EVP_PKEY_CTX_set_signature_md(ctx, md) == 0) {
83
fprintf(stderr, "Failed to configure digest type\n");
84
goto end;
85
}
86
87
/* Determine length of signature. */
88
if (EVP_PKEY_sign(ctx, NULL, sig_len,
89
test_digest, sizeof(test_digest))
90
== 0) {
91
fprintf(stderr, "Failed to get signature length\n");
92
goto end;
93
}
94
95
/* Allocate memory for signature. */
96
*sig = OPENSSL_malloc(*sig_len);
97
if (*sig == NULL) {
98
fprintf(stderr, "Failed to allocate memory for signature\n");
99
goto end;
100
}
101
102
/* Generate signature. */
103
if (EVP_PKEY_sign(ctx, *sig, sig_len,
104
test_digest, sizeof(test_digest))
105
!= 1) {
106
fprintf(stderr, "Failed to sign\n");
107
goto end;
108
}
109
110
ret = 1;
111
end:
112
EVP_PKEY_CTX_free(ctx);
113
EVP_PKEY_free(pkey);
114
EVP_MD_free(md);
115
116
if (ret == 0)
117
OPENSSL_free(*sig);
118
119
return ret;
120
}
121
122
/*
123
* This function demonstrates verification of an RSA signature over a SHA-256
124
* digest using the PSS signature scheme.
125
*/
126
static int verify(OSSL_LIB_CTX *libctx, const unsigned char *sig, size_t sig_len)
127
{
128
int ret = 0;
129
const unsigned char *ppub_key = NULL;
130
EVP_PKEY *pkey = NULL;
131
EVP_PKEY_CTX *ctx = NULL;
132
EVP_MD *md = NULL;
133
134
/* Load DER-encoded RSA public key. */
135
ppub_key = rsa_pub_key;
136
pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ppub_key, sizeof(rsa_pub_key));
137
if (pkey == NULL) {
138
fprintf(stderr, "Failed to load public key\n");
139
goto end;
140
}
141
142
/* Fetch hash algorithm we want to use. */
143
md = EVP_MD_fetch(libctx, "SHA256", propq);
144
if (md == NULL) {
145
fprintf(stderr, "Failed to fetch hash algorithm\n");
146
goto end;
147
}
148
149
/* Create verification context. */
150
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
151
if (ctx == NULL) {
152
fprintf(stderr, "Failed to create verification context\n");
153
goto end;
154
}
155
156
/* Initialize context for verification and set options. */
157
if (EVP_PKEY_verify_init(ctx) == 0) {
158
fprintf(stderr, "Failed to initialize verification context\n");
159
goto end;
160
}
161
162
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) == 0) {
163
fprintf(stderr, "Failed to configure padding\n");
164
goto end;
165
}
166
167
if (EVP_PKEY_CTX_set_signature_md(ctx, md) == 0) {
168
fprintf(stderr, "Failed to configure digest type\n");
169
goto end;
170
}
171
172
/* Verify signature. */
173
if (EVP_PKEY_verify(ctx, sig, sig_len,
174
test_digest, sizeof(test_digest))
175
== 0) {
176
fprintf(stderr, "Failed to verify signature; "
177
"signature may be invalid\n");
178
goto end;
179
}
180
181
ret = 1;
182
end:
183
EVP_PKEY_CTX_free(ctx);
184
EVP_PKEY_free(pkey);
185
EVP_MD_free(md);
186
return ret;
187
}
188
189
int main(int argc, char **argv)
190
{
191
int ret = EXIT_FAILURE;
192
OSSL_LIB_CTX *libctx = NULL;
193
unsigned char *sig = NULL;
194
size_t sig_len = 0;
195
196
if (sign(libctx, &sig, &sig_len) == 0)
197
goto end;
198
199
if (verify(libctx, sig, sig_len) == 0)
200
goto end;
201
202
printf("Success\n");
203
204
ret = EXIT_SUCCESS;
205
end:
206
OPENSSL_free(sig);
207
OSSL_LIB_CTX_free(libctx);
208
return ret;
209
}
210
211