]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/signature/eddsa.c
Teach EdDSA signature algorithms about AlgorithmIdentifiers
[thirdparty/openssl.git] / providers / implementations / signature / eddsa.c
1 /*
2 * Copyright 2020 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 <openssl/crypto.h>
11 #include <openssl/core_dispatch.h>
12 #include <openssl/core_names.h>
13 #include <openssl/err.h>
14 #include <openssl/params.h>
15 #include <openssl/evp.h>
16 #include <openssl/err.h>
17 #include "internal/nelem.h"
18 #include "internal/sizes.h"
19 #include "prov/providercommon.h"
20 #include "prov/implementations.h"
21 #include "prov/providercommonerr.h"
22 #include "prov/provider_ctx.h"
23 #include "prov/der_ecx.h"
24 #include "crypto/ecx.h"
25
26 static OSSL_FUNC_signature_newctx_fn eddsa_newctx;
27 static OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init;
28 static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
29 static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
30 static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
31 static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
32 static OSSL_FUNC_signature_freectx_fn eddsa_freectx;
33 static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
34 static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
35 static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
36
37 typedef struct {
38 OPENSSL_CTX *libctx;
39 ECX_KEY *key;
40
41 /* The Algorithm Identifier of the signature algorithm */
42 unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
43 unsigned char *aid;
44 size_t aid_len;
45 } PROV_EDDSA_CTX;
46
47 static void *eddsa_newctx(void *provctx, const char *propq_unused)
48 {
49 PROV_EDDSA_CTX *peddsactx;
50
51 if (!ossl_prov_is_running())
52 return NULL;
53
54 peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
55 if (peddsactx == NULL) {
56 PROVerr(0, ERR_R_MALLOC_FAILURE);
57 return NULL;
58 }
59
60 peddsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
61
62 return peddsactx;
63 }
64
65 static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
66 void *vedkey)
67 {
68 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
69 ECX_KEY *edkey = (ECX_KEY *)vedkey;
70 WPACKET pkt;
71 int ret;
72
73 if (!ossl_prov_is_running())
74 return 0;
75
76 if (mdname != NULL && mdname[0] != '\0') {
77 PROVerr(0, PROV_R_INVALID_DIGEST);
78 return 0;
79 }
80
81 if (!ecx_key_up_ref(edkey)) {
82 PROVerr(0, ERR_R_INTERNAL_ERROR);
83 return 0;
84 }
85
86 /*
87 * TODO(3.0) Should we care about DER writing errors?
88 * All it really means is that for some reason, there's no
89 * AlgorithmIdentifier to be had, but the operation itself is
90 * still valid, just as long as it's not used to construct
91 * anything that needs an AlgorithmIdentifier.
92 */
93 peddsactx->aid_len = 0;
94 ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
95 switch (edkey->type) {
96 case ECX_KEY_TYPE_ED25519:
97 ret = ret && DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
98 break;
99 case ECX_KEY_TYPE_ED448:
100 ret = ret && DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
101 break;
102 default:
103 /* Should never happen */
104 PROVerr(0, ERR_R_INTERNAL_ERROR);
105 return 0;
106 }
107 if (ret && WPACKET_finish(&pkt)) {
108 WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
109 peddsactx->aid = WPACKET_get_curr(&pkt);
110 }
111 WPACKET_cleanup(&pkt);
112
113 peddsactx->key = edkey;
114
115 return 1;
116 }
117
118 int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
119 size_t *siglen, size_t sigsize,
120 const unsigned char *tbs, size_t tbslen)
121 {
122 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
123 const ECX_KEY *edkey = peddsactx->key;
124
125 if (!ossl_prov_is_running())
126 return 0;
127
128 if (sigret == NULL) {
129 *siglen = ED25519_SIGSIZE;
130 return 1;
131 }
132 if (sigsize < ED25519_SIGSIZE) {
133 PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
134 return 0;
135 }
136
137 if (ED25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
138 peddsactx->libctx, NULL) == 0) {
139 PROVerr(0, PROV_R_FAILED_TO_SIGN);
140 return 0;
141 }
142 *siglen = ED25519_SIGSIZE;
143 return 1;
144 }
145
146 int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
147 size_t *siglen, size_t sigsize,
148 const unsigned char *tbs, size_t tbslen)
149 {
150 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
151 const ECX_KEY *edkey = peddsactx->key;
152
153 if (!ossl_prov_is_running())
154 return 0;
155
156 if (sigret == NULL) {
157 *siglen = ED448_SIGSIZE;
158 return 1;
159 }
160 if (sigsize < ED448_SIGSIZE) {
161 PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
162 return 0;
163 }
164
165 if (ED448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey,
166 edkey->privkey, NULL, 0) == 0) {
167 PROVerr(0, PROV_R_FAILED_TO_SIGN);
168 return 0;
169 }
170 *siglen = ED448_SIGSIZE;
171 return 1;
172 }
173
174 int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
175 size_t siglen, const unsigned char *tbs,
176 size_t tbslen)
177 {
178 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
179 const ECX_KEY *edkey = peddsactx->key;
180
181 if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
182 return 0;
183
184 return ED25519_verify(tbs, tbslen, sig, edkey->pubkey, peddsactx->libctx,
185 NULL);
186 }
187
188 int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
189 size_t siglen, const unsigned char *tbs,
190 size_t tbslen)
191 {
192 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
193 const ECX_KEY *edkey = peddsactx->key;
194
195 if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
196 return 0;
197
198 return ED448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
199 NULL, 0);
200 }
201
202 static void eddsa_freectx(void *vpeddsactx)
203 {
204 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
205
206 ecx_key_free(peddsactx->key);
207
208 OPENSSL_free(peddsactx);
209 }
210
211 static void *eddsa_dupctx(void *vpeddsactx)
212 {
213 PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
214 PROV_EDDSA_CTX *dstctx;
215
216 if (!ossl_prov_is_running())
217 return NULL;
218
219 dstctx = OPENSSL_zalloc(sizeof(*srcctx));
220 if (dstctx == NULL)
221 return NULL;
222
223 *dstctx = *srcctx;
224 dstctx->key = NULL;
225
226 if (srcctx->key != NULL && !ecx_key_up_ref(srcctx->key)) {
227 PROVerr(0, ERR_R_INTERNAL_ERROR);
228 goto err;
229 }
230 dstctx->key = srcctx->key;
231
232 return dstctx;
233 err:
234 eddsa_freectx(dstctx);
235 return NULL;
236 }
237
238 static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
239 {
240 PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
241 OSSL_PARAM *p;
242
243 if (peddsactx == NULL || params == NULL)
244 return 0;
245
246 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
247 if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
248 peddsactx->aid_len))
249 return 0;
250
251 return 1;
252 }
253
254 static const OSSL_PARAM known_gettable_ctx_params[] = {
255 OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
256 OSSL_PARAM_END
257 };
258
259 static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *provctx)
260 {
261 return known_gettable_ctx_params;
262 }
263
264 const OSSL_DISPATCH ed25519_signature_functions[] = {
265 { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
266 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
267 (void (*)(void))eddsa_digest_signverify_init },
268 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
269 (void (*)(void))ed25519_digest_sign },
270 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
271 (void (*)(void))eddsa_digest_signverify_init },
272 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
273 (void (*)(void))ed25519_digest_verify },
274 { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
275 { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
276 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
277 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
278 (void (*)(void))eddsa_gettable_ctx_params },
279 { 0, NULL }
280 };
281
282 const OSSL_DISPATCH ed448_signature_functions[] = {
283 { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
284 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
285 (void (*)(void))eddsa_digest_signverify_init },
286 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
287 (void (*)(void))ed448_digest_sign },
288 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
289 (void (*)(void))eddsa_digest_signverify_init },
290 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
291 (void (*)(void))ed448_digest_verify },
292 { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
293 { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
294 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
295 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
296 (void (*)(void))eddsa_gettable_ctx_params },
297 { 0, NULL }
298 };