1*3d9fd9fcSEd Maste /* $OpenBSD: ssh-rsa.c,v 1.80 2024/08/15 00:51:51 djm Exp $ */
21e8db6e2SBrian Feldman /*
3d95e11bfSDag-Erling Smørgrav * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
41e8db6e2SBrian Feldman *
5d95e11bfSDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any
6d95e11bfSDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above
7d95e11bfSDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies.
81e8db6e2SBrian Feldman *
9d95e11bfSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10d95e11bfSDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11d95e11bfSDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12d95e11bfSDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13d95e11bfSDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14d95e11bfSDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15d95e11bfSDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161e8db6e2SBrian Feldman */
17761efaa7SDag-Erling Smørgrav
181e8db6e2SBrian Feldman #include "includes.h"
19761efaa7SDag-Erling Smørgrav
20bc5531deSDag-Erling Smørgrav #ifdef WITH_OPENSSL
21bc5531deSDag-Erling Smørgrav
22761efaa7SDag-Erling Smørgrav #include <sys/types.h>
231e8db6e2SBrian Feldman
241e8db6e2SBrian Feldman #include <openssl/evp.h>
251e8db6e2SBrian Feldman #include <openssl/err.h>
261e8db6e2SBrian Feldman
27761efaa7SDag-Erling Smørgrav #include <stdarg.h>
28761efaa7SDag-Erling Smørgrav #include <string.h>
29761efaa7SDag-Erling Smørgrav
30a0ee8cc6SDag-Erling Smørgrav #include "sshbuf.h"
31a0ee8cc6SDag-Erling Smørgrav #include "ssherr.h"
32a0ee8cc6SDag-Erling Smørgrav #define SSHKEY_INTERNAL
33a0ee8cc6SDag-Erling Smørgrav #include "sshkey.h"
34f7167e0eSDag-Erling Smørgrav #include "digest.h"
3547dd1d1bSDag-Erling Smørgrav #include "log.h"
361e8db6e2SBrian Feldman
372a01feabSEd Maste #include "openbsd-compat/openssl-compat.h"
382a01feabSEd Maste
39f374ba41SEd Maste static u_int
ssh_rsa_size(const struct sshkey * k)40*3d9fd9fcSEd Maste ssh_rsa_size(const struct sshkey *k)
41f374ba41SEd Maste {
42*3d9fd9fcSEd Maste if (k->pkey == NULL)
43f374ba41SEd Maste return 0;
44*3d9fd9fcSEd Maste return EVP_PKEY_bits(k->pkey);
45f374ba41SEd Maste }
46f374ba41SEd Maste
47f374ba41SEd Maste static int
ssh_rsa_alloc(struct sshkey * k)48f374ba41SEd Maste ssh_rsa_alloc(struct sshkey *k)
49f374ba41SEd Maste {
50*3d9fd9fcSEd Maste if ((k->pkey = EVP_PKEY_new()) == NULL)
51f374ba41SEd Maste return SSH_ERR_ALLOC_FAIL;
52f374ba41SEd Maste return 0;
53f374ba41SEd Maste }
54f374ba41SEd Maste
55f374ba41SEd Maste static void
ssh_rsa_cleanup(struct sshkey * k)56f374ba41SEd Maste ssh_rsa_cleanup(struct sshkey *k)
57f374ba41SEd Maste {
58*3d9fd9fcSEd Maste EVP_PKEY_free(k->pkey);
59*3d9fd9fcSEd Maste k->pkey = NULL;
60f374ba41SEd Maste }
61f374ba41SEd Maste
62f374ba41SEd Maste static int
ssh_rsa_equal(const struct sshkey * a,const struct sshkey * b)63f374ba41SEd Maste ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
64f374ba41SEd Maste {
65*3d9fd9fcSEd Maste if (a->pkey == NULL || b->pkey == NULL)
66f374ba41SEd Maste return 0;
67*3d9fd9fcSEd Maste return EVP_PKEY_cmp(a->pkey, b->pkey) == 1;
68f374ba41SEd Maste }
69f374ba41SEd Maste
70f374ba41SEd Maste static int
ssh_rsa_serialize_public(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)71f374ba41SEd Maste ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
72f374ba41SEd Maste enum sshkey_serialize_rep opts)
73f374ba41SEd Maste {
74f374ba41SEd Maste int r;
75f374ba41SEd Maste const BIGNUM *rsa_n, *rsa_e;
76*3d9fd9fcSEd Maste const RSA *rsa;
77f374ba41SEd Maste
78*3d9fd9fcSEd Maste if (key->pkey == NULL)
79f374ba41SEd Maste return SSH_ERR_INVALID_ARGUMENT;
80*3d9fd9fcSEd Maste if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL)
81*3d9fd9fcSEd Maste return SSH_ERR_LIBCRYPTO_ERROR;
82*3d9fd9fcSEd Maste
83*3d9fd9fcSEd Maste RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
84f374ba41SEd Maste if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
85f374ba41SEd Maste (r = sshbuf_put_bignum2(b, rsa_n)) != 0)
86f374ba41SEd Maste return r;
87f374ba41SEd Maste
88f374ba41SEd Maste return 0;
89f374ba41SEd Maste }
90f374ba41SEd Maste
91f374ba41SEd Maste static int
ssh_rsa_serialize_private(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)92f374ba41SEd Maste ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
93f374ba41SEd Maste enum sshkey_serialize_rep opts)
94f374ba41SEd Maste {
95f374ba41SEd Maste int r;
96f374ba41SEd Maste const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
97*3d9fd9fcSEd Maste const RSA *rsa;
98f374ba41SEd Maste
99*3d9fd9fcSEd Maste if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL)
100*3d9fd9fcSEd Maste return SSH_ERR_LIBCRYPTO_ERROR;
101*3d9fd9fcSEd Maste RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
102*3d9fd9fcSEd Maste RSA_get0_factors(rsa, &rsa_p, &rsa_q);
103*3d9fd9fcSEd Maste RSA_get0_crt_params(rsa, NULL, NULL, &rsa_iqmp);
104f374ba41SEd Maste
105f374ba41SEd Maste if (!sshkey_is_cert(key)) {
106f374ba41SEd Maste /* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */
107f374ba41SEd Maste if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
108f374ba41SEd Maste (r = sshbuf_put_bignum2(b, rsa_e)) != 0)
109f374ba41SEd Maste return r;
110f374ba41SEd Maste }
111f374ba41SEd Maste if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
112f374ba41SEd Maste (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
113f374ba41SEd Maste (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
114f374ba41SEd Maste (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
115f374ba41SEd Maste return r;
116f374ba41SEd Maste
117f374ba41SEd Maste return 0;
118f374ba41SEd Maste }
119f374ba41SEd Maste
120f374ba41SEd Maste static int
ssh_rsa_generate(struct sshkey * k,int bits)121f374ba41SEd Maste ssh_rsa_generate(struct sshkey *k, int bits)
122f374ba41SEd Maste {
123*3d9fd9fcSEd Maste EVP_PKEY_CTX *ctx = NULL;
124*3d9fd9fcSEd Maste EVP_PKEY *res = NULL;
125*3d9fd9fcSEd Maste
126f374ba41SEd Maste int ret = SSH_ERR_INTERNAL_ERROR;
127f374ba41SEd Maste
128f374ba41SEd Maste if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
129f374ba41SEd Maste bits > SSHBUF_MAX_BIGNUM * 8)
130f374ba41SEd Maste return SSH_ERR_KEY_LENGTH;
131*3d9fd9fcSEd Maste
132*3d9fd9fcSEd Maste if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
133f374ba41SEd Maste ret = SSH_ERR_ALLOC_FAIL;
134f374ba41SEd Maste goto out;
135f374ba41SEd Maste }
136*3d9fd9fcSEd Maste if (EVP_PKEY_keygen_init(ctx) <= 0) {
137f374ba41SEd Maste ret = SSH_ERR_LIBCRYPTO_ERROR;
138f374ba41SEd Maste goto out;
139f374ba41SEd Maste }
140*3d9fd9fcSEd Maste if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) {
141*3d9fd9fcSEd Maste ret = SSH_ERR_KEY_LENGTH;
142*3d9fd9fcSEd Maste goto out;
143*3d9fd9fcSEd Maste }
144*3d9fd9fcSEd Maste if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) {
145*3d9fd9fcSEd Maste ret = SSH_ERR_LIBCRYPTO_ERROR;
146*3d9fd9fcSEd Maste goto out;
147*3d9fd9fcSEd Maste }
148*3d9fd9fcSEd Maste /* success */
149*3d9fd9fcSEd Maste k->pkey = res;
150f374ba41SEd Maste ret = 0;
151f374ba41SEd Maste out:
152*3d9fd9fcSEd Maste EVP_PKEY_CTX_free(ctx);
153f374ba41SEd Maste return ret;
154f374ba41SEd Maste }
155f374ba41SEd Maste
156f374ba41SEd Maste static int
ssh_rsa_copy_public(const struct sshkey * from,struct sshkey * to)157f374ba41SEd Maste ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to)
158f374ba41SEd Maste {
159f374ba41SEd Maste const BIGNUM *rsa_n, *rsa_e;
160f374ba41SEd Maste BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
161f374ba41SEd Maste int r = SSH_ERR_INTERNAL_ERROR;
162*3d9fd9fcSEd Maste const RSA *rsa_from;
163*3d9fd9fcSEd Maste RSA *rsa_to = NULL;
164f374ba41SEd Maste
165*3d9fd9fcSEd Maste if ((rsa_from = EVP_PKEY_get0_RSA(from->pkey)) == NULL ||
166*3d9fd9fcSEd Maste (rsa_to = RSA_new()) == NULL)
167*3d9fd9fcSEd Maste return SSH_ERR_LIBCRYPTO_ERROR;
168*3d9fd9fcSEd Maste
169*3d9fd9fcSEd Maste RSA_get0_key(rsa_from, &rsa_n, &rsa_e, NULL);
170f374ba41SEd Maste if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
171f374ba41SEd Maste (rsa_e_dup = BN_dup(rsa_e)) == NULL) {
172f374ba41SEd Maste r = SSH_ERR_ALLOC_FAIL;
173f374ba41SEd Maste goto out;
174f374ba41SEd Maste }
175*3d9fd9fcSEd Maste if (!RSA_set0_key(rsa_to, rsa_n_dup, rsa_e_dup, NULL)) {
176f374ba41SEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
177f374ba41SEd Maste goto out;
178f374ba41SEd Maste }
179f374ba41SEd Maste rsa_n_dup = rsa_e_dup = NULL; /* transferred */
180*3d9fd9fcSEd Maste
181*3d9fd9fcSEd Maste if (EVP_PKEY_set1_RSA(to->pkey, rsa_to) != 1) {
182*3d9fd9fcSEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
183*3d9fd9fcSEd Maste goto out;
184*3d9fd9fcSEd Maste }
185f374ba41SEd Maste /* success */
186f374ba41SEd Maste r = 0;
187f374ba41SEd Maste out:
188*3d9fd9fcSEd Maste RSA_free(rsa_to);
189f374ba41SEd Maste BN_clear_free(rsa_n_dup);
190f374ba41SEd Maste BN_clear_free(rsa_e_dup);
191f374ba41SEd Maste return r;
192f374ba41SEd Maste }
193f374ba41SEd Maste
194f374ba41SEd Maste static int
ssh_rsa_deserialize_public(const char * ktype,struct sshbuf * b,struct sshkey * key)195f374ba41SEd Maste ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
196f374ba41SEd Maste struct sshkey *key)
197f374ba41SEd Maste {
198f374ba41SEd Maste int ret = SSH_ERR_INTERNAL_ERROR;
199f374ba41SEd Maste BIGNUM *rsa_n = NULL, *rsa_e = NULL;
200*3d9fd9fcSEd Maste RSA *rsa = NULL;
201*3d9fd9fcSEd Maste
202*3d9fd9fcSEd Maste if ((rsa = RSA_new()) == NULL)
203*3d9fd9fcSEd Maste return SSH_ERR_LIBCRYPTO_ERROR;
204f374ba41SEd Maste
205f374ba41SEd Maste if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
206f374ba41SEd Maste sshbuf_get_bignum2(b, &rsa_n) != 0) {
207f374ba41SEd Maste ret = SSH_ERR_INVALID_FORMAT;
208f374ba41SEd Maste goto out;
209f374ba41SEd Maste }
210*3d9fd9fcSEd Maste if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
211f374ba41SEd Maste ret = SSH_ERR_LIBCRYPTO_ERROR;
212f374ba41SEd Maste goto out;
213f374ba41SEd Maste }
214f374ba41SEd Maste rsa_n = rsa_e = NULL; /* transferred */
215*3d9fd9fcSEd Maste if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
216*3d9fd9fcSEd Maste ret = SSH_ERR_LIBCRYPTO_ERROR;
217*3d9fd9fcSEd Maste goto out;
218*3d9fd9fcSEd Maste }
219f374ba41SEd Maste if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
220f374ba41SEd Maste goto out;
221f374ba41SEd Maste #ifdef DEBUG_PK
222*3d9fd9fcSEd Maste RSA_print_fp(stderr, rsa, 8);
223f374ba41SEd Maste #endif
224f374ba41SEd Maste /* success */
225f374ba41SEd Maste ret = 0;
226f374ba41SEd Maste out:
227*3d9fd9fcSEd Maste RSA_free(rsa);
228f374ba41SEd Maste BN_clear_free(rsa_n);
229f374ba41SEd Maste BN_clear_free(rsa_e);
230f374ba41SEd Maste return ret;
231f374ba41SEd Maste }
232f374ba41SEd Maste
233f374ba41SEd Maste static int
ssh_rsa_deserialize_private(const char * ktype,struct sshbuf * b,struct sshkey * key)234f374ba41SEd Maste ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
235f374ba41SEd Maste struct sshkey *key)
236f374ba41SEd Maste {
237f374ba41SEd Maste int r;
238f374ba41SEd Maste BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
239f374ba41SEd Maste BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
240*3d9fd9fcSEd Maste BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL;
241*3d9fd9fcSEd Maste RSA *rsa = NULL;
242f374ba41SEd Maste
243*3d9fd9fcSEd Maste if (sshkey_is_cert(key)) {
244*3d9fd9fcSEd Maste /* sshkey_private_deserialize already has pubkey from cert */
245*3d9fd9fcSEd Maste if ((rsa = EVP_PKEY_get1_RSA(key->pkey)) == NULL) {
246*3d9fd9fcSEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
247*3d9fd9fcSEd Maste goto out;
248*3d9fd9fcSEd Maste }
249*3d9fd9fcSEd Maste } else {
250*3d9fd9fcSEd Maste if ((rsa = RSA_new()) == NULL) {
251*3d9fd9fcSEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
252*3d9fd9fcSEd Maste goto out;
253*3d9fd9fcSEd Maste }
254f374ba41SEd Maste /* Note: can't reuse ssh_rsa_deserialize_public: e,n vs. n,e */
255f374ba41SEd Maste if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 ||
256f374ba41SEd Maste (r = sshbuf_get_bignum2(b, &rsa_e)) != 0)
257f374ba41SEd Maste goto out;
258*3d9fd9fcSEd Maste if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
259f374ba41SEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
260f374ba41SEd Maste goto out;
261f374ba41SEd Maste }
262f374ba41SEd Maste rsa_n = rsa_e = NULL; /* transferred */
263f374ba41SEd Maste }
264f374ba41SEd Maste if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 ||
265f374ba41SEd Maste (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 ||
266f374ba41SEd Maste (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
267f374ba41SEd Maste (r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
268f374ba41SEd Maste goto out;
269*3d9fd9fcSEd Maste if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q,
270*3d9fd9fcSEd Maste rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0)
271*3d9fd9fcSEd Maste goto out;
272*3d9fd9fcSEd Maste if (!RSA_set0_key(rsa, NULL, NULL, rsa_d)) {
273f374ba41SEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
274f374ba41SEd Maste goto out;
275f374ba41SEd Maste }
276f374ba41SEd Maste rsa_d = NULL; /* transferred */
277*3d9fd9fcSEd Maste if (!RSA_set0_factors(rsa, rsa_p, rsa_q)) {
278f374ba41SEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
279f374ba41SEd Maste goto out;
280f374ba41SEd Maste }
281f374ba41SEd Maste rsa_p = rsa_q = NULL; /* transferred */
282*3d9fd9fcSEd Maste if (!RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
283f374ba41SEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
284f374ba41SEd Maste goto out;
285f374ba41SEd Maste }
286*3d9fd9fcSEd Maste rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL;
287*3d9fd9fcSEd Maste if (RSA_blinding_on(rsa, NULL) != 1) {
288*3d9fd9fcSEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
289*3d9fd9fcSEd Maste goto out;
290*3d9fd9fcSEd Maste }
291*3d9fd9fcSEd Maste if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
292*3d9fd9fcSEd Maste r = SSH_ERR_LIBCRYPTO_ERROR;
293*3d9fd9fcSEd Maste goto out;
294*3d9fd9fcSEd Maste }
295*3d9fd9fcSEd Maste if ((r = sshkey_check_rsa_length(key, 0)) != 0)
296*3d9fd9fcSEd Maste goto out;
297f374ba41SEd Maste /* success */
298f374ba41SEd Maste r = 0;
299f374ba41SEd Maste out:
300*3d9fd9fcSEd Maste RSA_free(rsa);
301f374ba41SEd Maste BN_clear_free(rsa_n);
302f374ba41SEd Maste BN_clear_free(rsa_e);
303f374ba41SEd Maste BN_clear_free(rsa_d);
304f374ba41SEd Maste BN_clear_free(rsa_p);
305f374ba41SEd Maste BN_clear_free(rsa_q);
306f374ba41SEd Maste BN_clear_free(rsa_iqmp);
307*3d9fd9fcSEd Maste BN_clear_free(rsa_dmp1);
308*3d9fd9fcSEd Maste BN_clear_free(rsa_dmq1);
309f374ba41SEd Maste return r;
310f374ba41SEd Maste }
311f374ba41SEd Maste
312acc1a9efSDag-Erling Smørgrav static const char *
rsa_hash_alg_ident(int hash_alg)313acc1a9efSDag-Erling Smørgrav rsa_hash_alg_ident(int hash_alg)
314acc1a9efSDag-Erling Smørgrav {
315acc1a9efSDag-Erling Smørgrav switch (hash_alg) {
316acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA1:
317acc1a9efSDag-Erling Smørgrav return "ssh-rsa";
318acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA256:
319acc1a9efSDag-Erling Smørgrav return "rsa-sha2-256";
320acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA512:
321acc1a9efSDag-Erling Smørgrav return "rsa-sha2-512";
322acc1a9efSDag-Erling Smørgrav }
323acc1a9efSDag-Erling Smørgrav return NULL;
324acc1a9efSDag-Erling Smørgrav }
325acc1a9efSDag-Erling Smørgrav
326190cef3dSDag-Erling Smørgrav /*
327190cef3dSDag-Erling Smørgrav * Returns the hash algorithm ID for a given algorithm identifier as used
328190cef3dSDag-Erling Smørgrav * inside the signature blob,
329190cef3dSDag-Erling Smørgrav */
330acc1a9efSDag-Erling Smørgrav static int
rsa_hash_id_from_ident(const char * ident)331190cef3dSDag-Erling Smørgrav rsa_hash_id_from_ident(const char *ident)
332acc1a9efSDag-Erling Smørgrav {
333190cef3dSDag-Erling Smørgrav if (strcmp(ident, "ssh-rsa") == 0)
334acc1a9efSDag-Erling Smørgrav return SSH_DIGEST_SHA1;
335acc1a9efSDag-Erling Smørgrav if (strcmp(ident, "rsa-sha2-256") == 0)
336acc1a9efSDag-Erling Smørgrav return SSH_DIGEST_SHA256;
337acc1a9efSDag-Erling Smørgrav if (strcmp(ident, "rsa-sha2-512") == 0)
338acc1a9efSDag-Erling Smørgrav return SSH_DIGEST_SHA512;
339acc1a9efSDag-Erling Smørgrav return -1;
340acc1a9efSDag-Erling Smørgrav }
341acc1a9efSDag-Erling Smørgrav
342190cef3dSDag-Erling Smørgrav /*
343190cef3dSDag-Erling Smørgrav * Return the hash algorithm ID for the specified key name. This includes
344190cef3dSDag-Erling Smørgrav * all the cases of rsa_hash_id_from_ident() but also the certificate key
345190cef3dSDag-Erling Smørgrav * types.
346190cef3dSDag-Erling Smørgrav */
347190cef3dSDag-Erling Smørgrav static int
rsa_hash_id_from_keyname(const char * alg)348190cef3dSDag-Erling Smørgrav rsa_hash_id_from_keyname(const char *alg)
349190cef3dSDag-Erling Smørgrav {
350190cef3dSDag-Erling Smørgrav int r;
351190cef3dSDag-Erling Smørgrav
352190cef3dSDag-Erling Smørgrav if ((r = rsa_hash_id_from_ident(alg)) != -1)
353190cef3dSDag-Erling Smørgrav return r;
354190cef3dSDag-Erling Smørgrav if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
355190cef3dSDag-Erling Smørgrav return SSH_DIGEST_SHA1;
356190cef3dSDag-Erling Smørgrav if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
357190cef3dSDag-Erling Smørgrav return SSH_DIGEST_SHA256;
358190cef3dSDag-Erling Smørgrav if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
359190cef3dSDag-Erling Smørgrav return SSH_DIGEST_SHA512;
360190cef3dSDag-Erling Smørgrav return -1;
361190cef3dSDag-Erling Smørgrav }
362190cef3dSDag-Erling Smørgrav
3634f52dfbbSDag-Erling Smørgrav int
ssh_rsa_complete_crt_parameters(const BIGNUM * rsa_d,const BIGNUM * rsa_p,const BIGNUM * rsa_q,const BIGNUM * rsa_iqmp,BIGNUM ** rsa_dmp1,BIGNUM ** rsa_dmq1)364*3d9fd9fcSEd Maste ssh_rsa_complete_crt_parameters(const BIGNUM *rsa_d, const BIGNUM *rsa_p,
365*3d9fd9fcSEd Maste const BIGNUM *rsa_q, const BIGNUM *rsa_iqmp, BIGNUM **rsa_dmp1,
366*3d9fd9fcSEd Maste BIGNUM **rsa_dmq1)
3674f52dfbbSDag-Erling Smørgrav {
3682a01feabSEd Maste BIGNUM *aux = NULL, *d_consttime = NULL;
3694f52dfbbSDag-Erling Smørgrav BN_CTX *ctx = NULL;
3704f52dfbbSDag-Erling Smørgrav int r;
3714f52dfbbSDag-Erling Smørgrav
372*3d9fd9fcSEd Maste *rsa_dmq1 = *rsa_dmp1 = NULL;
3734f52dfbbSDag-Erling Smørgrav if ((ctx = BN_CTX_new()) == NULL)
3744f52dfbbSDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL;
3752a01feabSEd Maste if ((aux = BN_new()) == NULL ||
376*3d9fd9fcSEd Maste (*rsa_dmq1 = BN_new()) == NULL ||
377*3d9fd9fcSEd Maste (*rsa_dmp1 = BN_new()) == NULL)
3782a01feabSEd Maste return SSH_ERR_ALLOC_FAIL;
379*3d9fd9fcSEd Maste if ((d_consttime = BN_dup(rsa_d)) == NULL) {
3804f52dfbbSDag-Erling Smørgrav r = SSH_ERR_ALLOC_FAIL;
3814f52dfbbSDag-Erling Smørgrav goto out;
3824f52dfbbSDag-Erling Smørgrav }
38347dd1d1bSDag-Erling Smørgrav BN_set_flags(aux, BN_FLG_CONSTTIME);
3842a01feabSEd Maste BN_set_flags(d_consttime, BN_FLG_CONSTTIME);
3854f52dfbbSDag-Erling Smørgrav
3862a01feabSEd Maste if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
387*3d9fd9fcSEd Maste (BN_mod(*rsa_dmq1, d_consttime, aux, ctx) == 0) ||
3882a01feabSEd Maste (BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
389*3d9fd9fcSEd Maste (BN_mod(*rsa_dmp1, d_consttime, aux, ctx) == 0)) {
3904f52dfbbSDag-Erling Smørgrav r = SSH_ERR_LIBCRYPTO_ERROR;
3914f52dfbbSDag-Erling Smørgrav goto out;
3924f52dfbbSDag-Erling Smørgrav }
3932a01feabSEd Maste /* success */
3944f52dfbbSDag-Erling Smørgrav r = 0;
3954f52dfbbSDag-Erling Smørgrav out:
3964f52dfbbSDag-Erling Smørgrav BN_clear_free(aux);
3972a01feabSEd Maste BN_clear_free(d_consttime);
3984f52dfbbSDag-Erling Smørgrav BN_CTX_free(ctx);
3994f52dfbbSDag-Erling Smørgrav return r;
4004f52dfbbSDag-Erling Smørgrav }
4014f52dfbbSDag-Erling Smørgrav
4021e8db6e2SBrian Feldman /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
403f374ba41SEd Maste static int
ssh_rsa_sign(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)404f374ba41SEd Maste ssh_rsa_sign(struct sshkey *key,
405f374ba41SEd Maste u_char **sigp, size_t *lenp,
406f374ba41SEd Maste const u_char *data, size_t datalen,
407f374ba41SEd Maste const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
4081e8db6e2SBrian Feldman {
409*3d9fd9fcSEd Maste u_char *sig = NULL;
410*3d9fd9fcSEd Maste size_t diff, len = 0;
411*3d9fd9fcSEd Maste int slen = 0;
412*3d9fd9fcSEd Maste int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
413a0ee8cc6SDag-Erling Smørgrav struct sshbuf *b = NULL;
4141e8db6e2SBrian Feldman
415a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL)
416a0ee8cc6SDag-Erling Smørgrav *lenp = 0;
417a0ee8cc6SDag-Erling Smørgrav if (sigp != NULL)
418a0ee8cc6SDag-Erling Smørgrav *sigp = NULL;
419a0ee8cc6SDag-Erling Smørgrav
420f374ba41SEd Maste if (alg == NULL || strlen(alg) == 0)
421acc1a9efSDag-Erling Smørgrav hash_alg = SSH_DIGEST_SHA1;
422acc1a9efSDag-Erling Smørgrav else
423f374ba41SEd Maste hash_alg = rsa_hash_id_from_keyname(alg);
424*3d9fd9fcSEd Maste
425*3d9fd9fcSEd Maste if (key == NULL || key->pkey == NULL || hash_alg == -1 ||
4264f52dfbbSDag-Erling Smørgrav sshkey_type_plain(key->type) != KEY_RSA)
427a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
428*3d9fd9fcSEd Maste slen = EVP_PKEY_size(key->pkey);
429a0ee8cc6SDag-Erling Smørgrav if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
430a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
431*3d9fd9fcSEd Maste if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE)
432*3d9fd9fcSEd Maste return SSH_ERR_KEY_LENGTH;
433f7167e0eSDag-Erling Smørgrav
434*3d9fd9fcSEd Maste if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sig, &len,
435*3d9fd9fcSEd Maste data, datalen)) < 0)
436a0ee8cc6SDag-Erling Smørgrav goto out;
437*3d9fd9fcSEd Maste if (len < (size_t)slen) {
438*3d9fd9fcSEd Maste diff = slen - len;
4391e8db6e2SBrian Feldman memmove(sig + diff, sig, len);
440b83788ffSDag-Erling Smørgrav explicit_bzero(sig, diff);
441*3d9fd9fcSEd Maste } else if (len > (size_t)slen) {
442a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INTERNAL_ERROR;
443a0ee8cc6SDag-Erling Smørgrav goto out;
4441e8db6e2SBrian Feldman }
445*3d9fd9fcSEd Maste
4461e8db6e2SBrian Feldman /* encode signature */
447a0ee8cc6SDag-Erling Smørgrav if ((b = sshbuf_new()) == NULL) {
448a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL;
449a0ee8cc6SDag-Erling Smørgrav goto out;
450a0ee8cc6SDag-Erling Smørgrav }
451acc1a9efSDag-Erling Smørgrav if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
452a0ee8cc6SDag-Erling Smørgrav (ret = sshbuf_put_string(b, sig, slen)) != 0)
453a0ee8cc6SDag-Erling Smørgrav goto out;
454a0ee8cc6SDag-Erling Smørgrav len = sshbuf_len(b);
455a0ee8cc6SDag-Erling Smørgrav if (sigp != NULL) {
456a0ee8cc6SDag-Erling Smørgrav if ((*sigp = malloc(len)) == NULL) {
457a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL;
458a0ee8cc6SDag-Erling Smørgrav goto out;
459a0ee8cc6SDag-Erling Smørgrav }
460a0ee8cc6SDag-Erling Smørgrav memcpy(*sigp, sshbuf_ptr(b), len);
461a0ee8cc6SDag-Erling Smørgrav }
4624b17dab0SDag-Erling Smørgrav if (lenp != NULL)
4634b17dab0SDag-Erling Smørgrav *lenp = len;
464a0ee8cc6SDag-Erling Smørgrav ret = 0;
465a0ee8cc6SDag-Erling Smørgrav out:
46647dd1d1bSDag-Erling Smørgrav freezero(sig, slen);
467a0ee8cc6SDag-Erling Smørgrav sshbuf_free(b);
468557f75e5SDag-Erling Smørgrav return ret;
4691e8db6e2SBrian Feldman }
4701e8db6e2SBrian Feldman
471f374ba41SEd Maste static int
ssh_rsa_verify(const struct sshkey * key,const u_char * sig,size_t siglen,const u_char * data,size_t dlen,const char * alg,u_int compat,struct sshkey_sig_details ** detailsp)472a0ee8cc6SDag-Erling Smørgrav ssh_rsa_verify(const struct sshkey *key,
473f374ba41SEd Maste const u_char *sig, size_t siglen,
474f374ba41SEd Maste const u_char *data, size_t dlen, const char *alg, u_int compat,
475f374ba41SEd Maste struct sshkey_sig_details **detailsp)
4761e8db6e2SBrian Feldman {
47747dd1d1bSDag-Erling Smørgrav char *sigtype = NULL;
478190cef3dSDag-Erling Smørgrav int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
479*3d9fd9fcSEd Maste size_t len = 0, diff, modlen, rsasize;
480a0ee8cc6SDag-Erling Smørgrav struct sshbuf *b = NULL;
481a0ee8cc6SDag-Erling Smørgrav u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
4821e8db6e2SBrian Feldman
483*3d9fd9fcSEd Maste if (key == NULL || key->pkey == NULL ||
484a0ee8cc6SDag-Erling Smørgrav sshkey_type_plain(key->type) != KEY_RSA ||
485076ad2f8SDag-Erling Smørgrav sig == NULL || siglen == 0)
486a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
487*3d9fd9fcSEd Maste if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE)
4884f52dfbbSDag-Erling Smørgrav return SSH_ERR_KEY_LENGTH;
489f7167e0eSDag-Erling Smørgrav
490acc1a9efSDag-Erling Smørgrav if ((b = sshbuf_from(sig, siglen)) == NULL)
491a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL;
49247dd1d1bSDag-Erling Smørgrav if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
493a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_FORMAT;
494a0ee8cc6SDag-Erling Smørgrav goto out;
4951e8db6e2SBrian Feldman }
496190cef3dSDag-Erling Smørgrav if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
497190cef3dSDag-Erling Smørgrav ret = SSH_ERR_KEY_TYPE_MISMATCH;
498190cef3dSDag-Erling Smørgrav goto out;
499190cef3dSDag-Erling Smørgrav }
500190cef3dSDag-Erling Smørgrav /*
501190cef3dSDag-Erling Smørgrav * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
502190cef3dSDag-Erling Smørgrav * legacy reasons, but otherwise the signature type should match.
503190cef3dSDag-Erling Smørgrav */
504190cef3dSDag-Erling Smørgrav if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
505190cef3dSDag-Erling Smørgrav if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
506190cef3dSDag-Erling Smørgrav ret = SSH_ERR_INVALID_ARGUMENT;
507190cef3dSDag-Erling Smørgrav goto out;
508190cef3dSDag-Erling Smørgrav }
509190cef3dSDag-Erling Smørgrav if (hash_alg != want_alg) {
51047dd1d1bSDag-Erling Smørgrav ret = SSH_ERR_SIGNATURE_INVALID;
51147dd1d1bSDag-Erling Smørgrav goto out;
51247dd1d1bSDag-Erling Smørgrav }
5131e8db6e2SBrian Feldman }
514a0ee8cc6SDag-Erling Smørgrav if (sshbuf_get_string(b, &sigblob, &len) != 0) {
515a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_FORMAT;
516a0ee8cc6SDag-Erling Smørgrav goto out;
517a0ee8cc6SDag-Erling Smørgrav }
518a0ee8cc6SDag-Erling Smørgrav if (sshbuf_len(b) != 0) {
519a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
520a0ee8cc6SDag-Erling Smørgrav goto out;
5211e8db6e2SBrian Feldman }
522545d5ecaSDag-Erling Smørgrav /* RSA_verify expects a signature of RSA_size */
523*3d9fd9fcSEd Maste modlen = EVP_PKEY_size(key->pkey);
524545d5ecaSDag-Erling Smørgrav if (len > modlen) {
525a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_KEY_BITS_MISMATCH;
526a0ee8cc6SDag-Erling Smørgrav goto out;
527545d5ecaSDag-Erling Smørgrav } else if (len < modlen) {
528a0ee8cc6SDag-Erling Smørgrav diff = modlen - len;
529a0ee8cc6SDag-Erling Smørgrav osigblob = sigblob;
530a0ee8cc6SDag-Erling Smørgrav if ((sigblob = realloc(sigblob, modlen)) == NULL) {
531a0ee8cc6SDag-Erling Smørgrav sigblob = osigblob; /* put it back for clear/free */
532a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL;
533a0ee8cc6SDag-Erling Smørgrav goto out;
534a0ee8cc6SDag-Erling Smørgrav }
535545d5ecaSDag-Erling Smørgrav memmove(sigblob + diff, sigblob, len);
536b83788ffSDag-Erling Smørgrav explicit_bzero(sigblob, diff);
537545d5ecaSDag-Erling Smørgrav len = modlen;
538545d5ecaSDag-Erling Smørgrav }
539*3d9fd9fcSEd Maste
540*3d9fd9fcSEd Maste rsasize = EVP_PKEY_size(key->pkey);
541*3d9fd9fcSEd Maste if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
542*3d9fd9fcSEd Maste len == 0 || len > rsasize) {
543*3d9fd9fcSEd Maste ret = SSH_ERR_INVALID_ARGUMENT;
544a0ee8cc6SDag-Erling Smørgrav goto out;
5451e8db6e2SBrian Feldman }
546*3d9fd9fcSEd Maste ret = sshkey_pkey_digest_verify(key->pkey, hash_alg, data, dlen,
547*3d9fd9fcSEd Maste sigblob, len);
5481e8db6e2SBrian Feldman
549a0ee8cc6SDag-Erling Smørgrav out:
55047dd1d1bSDag-Erling Smørgrav freezero(sigblob, len);
55147dd1d1bSDag-Erling Smørgrav free(sigtype);
552a0ee8cc6SDag-Erling Smørgrav sshbuf_free(b);
553a0ee8cc6SDag-Erling Smørgrav explicit_bzero(digest, sizeof(digest));
5541e8db6e2SBrian Feldman return ret;
5551e8db6e2SBrian Feldman }
5564b17dab0SDag-Erling Smørgrav
557f374ba41SEd Maste static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
558f374ba41SEd Maste /* .size = */ ssh_rsa_size,
559f374ba41SEd Maste /* .alloc = */ ssh_rsa_alloc,
560f374ba41SEd Maste /* .cleanup = */ ssh_rsa_cleanup,
561f374ba41SEd Maste /* .equal = */ ssh_rsa_equal,
562f374ba41SEd Maste /* .ssh_serialize_public = */ ssh_rsa_serialize_public,
563f374ba41SEd Maste /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
564f374ba41SEd Maste /* .ssh_serialize_private = */ ssh_rsa_serialize_private,
565f374ba41SEd Maste /* .ssh_deserialize_private = */ ssh_rsa_deserialize_private,
566f374ba41SEd Maste /* .generate = */ ssh_rsa_generate,
567f374ba41SEd Maste /* .copy_public = */ ssh_rsa_copy_public,
568f374ba41SEd Maste /* .sign = */ ssh_rsa_sign,
569f374ba41SEd Maste /* .verify = */ ssh_rsa_verify,
570f374ba41SEd Maste };
571f374ba41SEd Maste
572f374ba41SEd Maste const struct sshkey_impl sshkey_rsa_impl = {
573f374ba41SEd Maste /* .name = */ "ssh-rsa",
574f374ba41SEd Maste /* .shortname = */ "RSA",
575f374ba41SEd Maste /* .sigalg = */ NULL,
576f374ba41SEd Maste /* .type = */ KEY_RSA,
577f374ba41SEd Maste /* .nid = */ 0,
578f374ba41SEd Maste /* .cert = */ 0,
579f374ba41SEd Maste /* .sigonly = */ 0,
580f374ba41SEd Maste /* .keybits = */ 0,
581f374ba41SEd Maste /* .funcs = */ &sshkey_rsa_funcs,
582f374ba41SEd Maste };
583f374ba41SEd Maste
584f374ba41SEd Maste const struct sshkey_impl sshkey_rsa_cert_impl = {
585f374ba41SEd Maste /* .name = */ "ssh-rsa-cert-v01@openssh.com",
586f374ba41SEd Maste /* .shortname = */ "RSA-CERT",
587f374ba41SEd Maste /* .sigalg = */ NULL,
588f374ba41SEd Maste /* .type = */ KEY_RSA_CERT,
589f374ba41SEd Maste /* .nid = */ 0,
590f374ba41SEd Maste /* .cert = */ 1,
591f374ba41SEd Maste /* .sigonly = */ 0,
592f374ba41SEd Maste /* .keybits = */ 0,
593f374ba41SEd Maste /* .funcs = */ &sshkey_rsa_funcs,
594f374ba41SEd Maste };
595f374ba41SEd Maste
596f374ba41SEd Maste /* SHA2 signature algorithms */
597f374ba41SEd Maste
598f374ba41SEd Maste const struct sshkey_impl sshkey_rsa_sha256_impl = {
599f374ba41SEd Maste /* .name = */ "rsa-sha2-256",
600f374ba41SEd Maste /* .shortname = */ "RSA",
601f374ba41SEd Maste /* .sigalg = */ NULL,
602f374ba41SEd Maste /* .type = */ KEY_RSA,
603f374ba41SEd Maste /* .nid = */ 0,
604f374ba41SEd Maste /* .cert = */ 0,
605f374ba41SEd Maste /* .sigonly = */ 1,
606f374ba41SEd Maste /* .keybits = */ 0,
607f374ba41SEd Maste /* .funcs = */ &sshkey_rsa_funcs,
608f374ba41SEd Maste };
609f374ba41SEd Maste
610f374ba41SEd Maste const struct sshkey_impl sshkey_rsa_sha512_impl = {
611f374ba41SEd Maste /* .name = */ "rsa-sha2-512",
612f374ba41SEd Maste /* .shortname = */ "RSA",
613f374ba41SEd Maste /* .sigalg = */ NULL,
614f374ba41SEd Maste /* .type = */ KEY_RSA,
615f374ba41SEd Maste /* .nid = */ 0,
616f374ba41SEd Maste /* .cert = */ 0,
617f374ba41SEd Maste /* .sigonly = */ 1,
618f374ba41SEd Maste /* .keybits = */ 0,
619f374ba41SEd Maste /* .funcs = */ &sshkey_rsa_funcs,
620f374ba41SEd Maste };
621f374ba41SEd Maste
622f374ba41SEd Maste const struct sshkey_impl sshkey_rsa_sha256_cert_impl = {
623f374ba41SEd Maste /* .name = */ "rsa-sha2-256-cert-v01@openssh.com",
624f374ba41SEd Maste /* .shortname = */ "RSA-CERT",
625f374ba41SEd Maste /* .sigalg = */ "rsa-sha2-256",
626f374ba41SEd Maste /* .type = */ KEY_RSA_CERT,
627f374ba41SEd Maste /* .nid = */ 0,
628f374ba41SEd Maste /* .cert = */ 1,
629f374ba41SEd Maste /* .sigonly = */ 1,
630f374ba41SEd Maste /* .keybits = */ 0,
631f374ba41SEd Maste /* .funcs = */ &sshkey_rsa_funcs,
632f374ba41SEd Maste };
633f374ba41SEd Maste
634f374ba41SEd Maste const struct sshkey_impl sshkey_rsa_sha512_cert_impl = {
635f374ba41SEd Maste /* .name = */ "rsa-sha2-512-cert-v01@openssh.com",
636f374ba41SEd Maste /* .shortname = */ "RSA-CERT",
637f374ba41SEd Maste /* .sigalg = */ "rsa-sha2-512",
638f374ba41SEd Maste /* .type = */ KEY_RSA_CERT,
639f374ba41SEd Maste /* .nid = */ 0,
640f374ba41SEd Maste /* .cert = */ 1,
641f374ba41SEd Maste /* .sigonly = */ 1,
642f374ba41SEd Maste /* .keybits = */ 0,
643f374ba41SEd Maste /* .funcs = */ &sshkey_rsa_funcs,
644f374ba41SEd Maste };
645bc5531deSDag-Erling Smørgrav #endif /* WITH_OPENSSL */
646