Annotation of src/usr.bin/ssh/ssh-rsa.c, Revision 1.69
1.69 ! djm 1: /* $OpenBSD: ssh-rsa.c,v 1.68 2018/09/13 02:08:33 djm Exp $ */
1.1 markus 2: /*
1.30 markus 3: * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
1.1 markus 4: *
1.30 markus 5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 markus 8: *
1.30 markus 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 markus 16: */
1.39 deraadt 17:
18: #include <sys/types.h>
1.5 markus 19:
20: #include <openssl/evp.h>
21: #include <openssl/err.h>
1.38 stevesk 22:
23: #include <string.h>
1.1 markus 24:
1.52 djm 25: #include "sshbuf.h"
1.8 markus 26: #include "compat.h"
1.52 djm 27: #include "ssherr.h"
28: #define SSHKEY_INTERNAL
29: #include "sshkey.h"
1.50 djm 30: #include "digest.h"
1.64 djm 31: #include "log.h"
1.1 markus 32:
1.52 djm 33: static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
1.25 markus 34:
1.69 ! djm 35: static u_int
! 36: ssh_rsa_size(const struct sshkey *key)
! 37: {
! 38: const BIGNUM *rsa_n;
! 39:
! 40: if (key->rsa == NULL)
! 41: return 0;
! 42: RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
! 43: return BN_num_bits(rsa_n);
! 44: }
! 45:
! 46: static int
! 47: ssh_rsa_alloc(struct sshkey *k)
! 48: {
! 49: if ((k->rsa = RSA_new()) == NULL)
! 50: return SSH_ERR_ALLOC_FAIL;
! 51: return 0;
! 52: }
! 53:
! 54: static void
! 55: ssh_rsa_cleanup(struct sshkey *k)
! 56: {
! 57: RSA_free(k->rsa);
! 58: k->rsa = NULL;
! 59: }
! 60:
1.55 markus 61: static const char *
62: rsa_hash_alg_ident(int hash_alg)
63: {
64: switch (hash_alg) {
65: case SSH_DIGEST_SHA1:
66: return "ssh-rsa";
67: case SSH_DIGEST_SHA256:
68: return "rsa-sha2-256";
69: case SSH_DIGEST_SHA512:
70: return "rsa-sha2-512";
71: }
72: return NULL;
73: }
74:
1.67 djm 75: /*
76: * Returns the hash algorithm ID for a given algorithm identifier as used
77: * inside the signature blob,
78: */
1.55 markus 79: static int
1.67 djm 80: rsa_hash_id_from_ident(const char *ident)
1.55 markus 81: {
1.67 djm 82: if (strcmp(ident, "ssh-rsa") == 0)
1.55 markus 83: return SSH_DIGEST_SHA1;
84: if (strcmp(ident, "rsa-sha2-256") == 0)
85: return SSH_DIGEST_SHA256;
86: if (strcmp(ident, "rsa-sha2-512") == 0)
87: return SSH_DIGEST_SHA512;
88: return -1;
89: }
90:
1.67 djm 91: /*
92: * Return the hash algorithm ID for the specified key name. This includes
93: * all the cases of rsa_hash_id_from_ident() but also the certificate key
94: * types.
95: */
96: static int
97: rsa_hash_id_from_keyname(const char *alg)
98: {
99: int r;
100:
101: if ((r = rsa_hash_id_from_ident(alg)) != -1)
102: return r;
103: if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
104: return SSH_DIGEST_SHA1;
105: if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
106: return SSH_DIGEST_SHA256;
107: if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
108: return SSH_DIGEST_SHA512;
109: return -1;
110: }
111:
1.55 markus 112: static int
113: rsa_hash_alg_nid(int type)
114: {
115: switch (type) {
116: case SSH_DIGEST_SHA1:
117: return NID_sha1;
118: case SSH_DIGEST_SHA256:
119: return NID_sha256;
120: case SSH_DIGEST_SHA512:
121: return NID_sha512;
122: default:
123: return -1;
124: }
1.62 djm 125: }
126:
127: int
1.68 djm 128: ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
1.62 djm 129: {
1.68 djm 130: const BIGNUM *rsa_p, *rsa_q, *rsa_d;
131: BIGNUM *aux = NULL, *d_consttime = NULL;
132: BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL;
1.62 djm 133: BN_CTX *ctx = NULL;
134: int r;
135:
136: if (key == NULL || key->rsa == NULL ||
137: sshkey_type_plain(key->type) != KEY_RSA)
138: return SSH_ERR_INVALID_ARGUMENT;
139:
1.68 djm 140: RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
141: RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
142:
1.62 djm 143: if ((ctx = BN_CTX_new()) == NULL)
144: return SSH_ERR_ALLOC_FAIL;
1.68 djm 145: if ((aux = BN_new()) == NULL ||
146: (rsa_dmq1 = BN_new()) == NULL ||
147: (rsa_dmp1 = BN_new()) == NULL)
148: return SSH_ERR_ALLOC_FAIL;
149: if ((d_consttime = BN_dup(rsa_d)) == NULL ||
150: (rsa_iqmp = BN_dup(iqmp)) == NULL) {
1.62 djm 151: r = SSH_ERR_ALLOC_FAIL;
152: goto out;
153: }
1.66 jsing 154: BN_set_flags(aux, BN_FLG_CONSTTIME);
1.68 djm 155: BN_set_flags(d_consttime, BN_FLG_CONSTTIME);
1.62 djm 156:
1.68 djm 157: if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
158: (BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) ||
159: (BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
160: (BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) {
161: r = SSH_ERR_LIBCRYPTO_ERROR;
162: goto out;
163: }
164: if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
1.62 djm 165: r = SSH_ERR_LIBCRYPTO_ERROR;
166: goto out;
167: }
1.68 djm 168: rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */
169: /* success */
1.62 djm 170: r = 0;
171: out:
172: BN_clear_free(aux);
1.68 djm 173: BN_clear_free(d_consttime);
174: BN_clear_free(rsa_dmp1);
175: BN_clear_free(rsa_dmq1);
176: BN_clear_free(rsa_iqmp);
1.62 djm 177: BN_CTX_free(ctx);
178: return r;
1.55 markus 179: }
180:
1.1 markus 181: /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
182: int
1.52 djm 183: ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
1.55 markus 184: const u_char *data, size_t datalen, const char *alg_ident)
1.1 markus 185: {
1.68 djm 186: const BIGNUM *rsa_n;
1.52 djm 187: u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
1.65 jsing 188: size_t slen = 0;
1.52 djm 189: u_int dlen, len;
1.55 markus 190: int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
1.52 djm 191: struct sshbuf *b = NULL;
192:
193: if (lenp != NULL)
194: *lenp = 0;
195: if (sigp != NULL)
196: *sigp = NULL;
197:
1.60 djm 198: if (alg_ident == NULL || strlen(alg_ident) == 0)
1.56 markus 199: hash_alg = SSH_DIGEST_SHA1;
200: else
1.67 djm 201: hash_alg = rsa_hash_id_from_keyname(alg_ident);
1.55 markus 202: if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
1.61 djm 203: sshkey_type_plain(key->type) != KEY_RSA)
1.52 djm 204: return SSH_ERR_INVALID_ARGUMENT;
1.68 djm 205: RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
206: if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
1.61 djm 207: return SSH_ERR_KEY_LENGTH;
1.52 djm 208: slen = RSA_size(key->rsa);
209: if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
210: return SSH_ERR_INVALID_ARGUMENT;
1.47 djm 211:
1.50 djm 212: /* hash the data */
1.55 markus 213: nid = rsa_hash_alg_nid(hash_alg);
1.52 djm 214: if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
215: return SSH_ERR_INTERNAL_ERROR;
216: if ((ret = ssh_digest_memory(hash_alg, data, datalen,
217: digest, sizeof(digest))) != 0)
218: goto out;
219:
220: if ((sig = malloc(slen)) == NULL) {
221: ret = SSH_ERR_ALLOC_FAIL;
222: goto out;
1.50 djm 223: }
1.1 markus 224:
1.52 djm 225: if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
226: ret = SSH_ERR_LIBCRYPTO_ERROR;
227: goto out;
1.1 markus 228: }
229: if (len < slen) {
1.52 djm 230: size_t diff = slen - len;
1.1 markus 231: memmove(sig + diff, sig, len);
1.51 djm 232: explicit_bzero(sig, diff);
1.1 markus 233: } else if (len > slen) {
1.52 djm 234: ret = SSH_ERR_INTERNAL_ERROR;
235: goto out;
1.1 markus 236: }
237: /* encode signature */
1.52 djm 238: if ((b = sshbuf_new()) == NULL) {
239: ret = SSH_ERR_ALLOC_FAIL;
240: goto out;
241: }
1.55 markus 242: if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
1.52 djm 243: (ret = sshbuf_put_string(b, sig, slen)) != 0)
244: goto out;
245: len = sshbuf_len(b);
246: if (sigp != NULL) {
247: if ((*sigp = malloc(len)) == NULL) {
248: ret = SSH_ERR_ALLOC_FAIL;
249: goto out;
250: }
251: memcpy(*sigp, sshbuf_ptr(b), len);
252: }
1.23 markus 253: if (lenp != NULL)
254: *lenp = len;
1.52 djm 255: ret = 0;
256: out:
257: explicit_bzero(digest, sizeof(digest));
1.65 jsing 258: freezero(sig, slen);
1.58 mmcc 259: sshbuf_free(b);
1.53 djm 260: return ret;
1.1 markus 261: }
262:
263: int
1.52 djm 264: ssh_rsa_verify(const struct sshkey *key,
1.63 djm 265: const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
266: const char *alg)
1.1 markus 267: {
1.68 djm 268: const BIGNUM *rsa_n;
1.63 djm 269: char *sigtype = NULL;
1.67 djm 270: int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
1.65 jsing 271: size_t len = 0, diff, modlen, dlen;
1.52 djm 272: struct sshbuf *b = NULL;
273: u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
274:
275: if (key == NULL || key->rsa == NULL ||
276: sshkey_type_plain(key->type) != KEY_RSA ||
1.59 djm 277: sig == NULL || siglen == 0)
1.52 djm 278: return SSH_ERR_INVALID_ARGUMENT;
1.68 djm 279: RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
280: if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
1.61 djm 281: return SSH_ERR_KEY_LENGTH;
1.52 djm 282:
1.55 markus 283: if ((b = sshbuf_from(sig, siglen)) == NULL)
1.52 djm 284: return SSH_ERR_ALLOC_FAIL;
1.63 djm 285: if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
1.52 djm 286: ret = SSH_ERR_INVALID_FORMAT;
287: goto out;
288: }
1.67 djm 289: if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
290: ret = SSH_ERR_KEY_TYPE_MISMATCH;
1.63 djm 291: goto out;
292: }
1.67 djm 293: /*
294: * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
295: * legacy reasons, but otherwise the signature type should match.
296: */
297: if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
298: if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
299: ret = SSH_ERR_INVALID_ARGUMENT;
300: goto out;
301: }
302: if (hash_alg != want_alg) {
303: ret = SSH_ERR_SIGNATURE_INVALID;
304: goto out;
305: }
1.1 markus 306: }
1.52 djm 307: if (sshbuf_get_string(b, &sigblob, &len) != 0) {
308: ret = SSH_ERR_INVALID_FORMAT;
309: goto out;
310: }
311: if (sshbuf_len(b) != 0) {
312: ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
313: goto out;
1.19 markus 314: }
315: /* RSA_verify expects a signature of RSA_size */
316: modlen = RSA_size(key->rsa);
317: if (len > modlen) {
1.52 djm 318: ret = SSH_ERR_KEY_BITS_MISMATCH;
319: goto out;
1.19 markus 320: } else if (len < modlen) {
1.52 djm 321: diff = modlen - len;
322: osigblob = sigblob;
323: if ((sigblob = realloc(sigblob, modlen)) == NULL) {
324: sigblob = osigblob; /* put it back for clear/free */
325: ret = SSH_ERR_ALLOC_FAIL;
326: goto out;
327: }
1.19 markus 328: memmove(sigblob + diff, sigblob, len);
1.51 djm 329: explicit_bzero(sigblob, diff);
1.19 markus 330: len = modlen;
1.1 markus 331: }
1.50 djm 332: if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
1.52 djm 333: ret = SSH_ERR_INTERNAL_ERROR;
334: goto out;
1.7 markus 335: }
1.52 djm 336: if ((ret = ssh_digest_memory(hash_alg, data, datalen,
337: digest, sizeof(digest))) != 0)
338: goto out;
1.1 markus 339:
1.50 djm 340: ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
341: key->rsa);
1.52 djm 342: out:
1.65 jsing 343: freezero(sigblob, len);
1.63 djm 344: free(sigtype);
1.58 mmcc 345: sshbuf_free(b);
1.51 djm 346: explicit_bzero(digest, sizeof(digest));
1.25 markus 347: return ret;
348: }
349:
350: /*
351: * See:
352: * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
353: * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
354: */
1.55 markus 355:
1.25 markus 356: /*
357: * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
358: * oiw(14) secsig(3) algorithms(2) 26 }
359: */
360: static const u_char id_sha1[] = {
361: 0x30, 0x21, /* type Sequence, length 0x21 (33) */
362: 0x30, 0x09, /* type Sequence, length 0x09 */
363: 0x06, 0x05, /* type OID, length 0x05 */
364: 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
365: 0x05, 0x00, /* NULL */
366: 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
367: };
368:
1.55 markus 369: /*
370: * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
371: * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
372: * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
373: * id-sha256(1) }
374: */
375: static const u_char id_sha256[] = {
376: 0x30, 0x31, /* type Sequence, length 0x31 (49) */
377: 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
378: 0x06, 0x09, /* type OID, length 0x09 */
379: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
380: 0x05, 0x00, /* NULL */
381: 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
382: };
383:
384: /*
385: * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
386: * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
387: * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
388: * id-sha256(3) }
389: */
390: static const u_char id_sha512[] = {
391: 0x30, 0x51, /* type Sequence, length 0x51 (81) */
392: 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
393: 0x06, 0x09, /* type OID, length 0x09 */
394: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
395: 0x05, 0x00, /* NULL */
396: 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
397: };
398:
399: static int
400: rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
401: {
402: switch (hash_alg) {
403: case SSH_DIGEST_SHA1:
404: *oidp = id_sha1;
405: *oidlenp = sizeof(id_sha1);
406: break;
407: case SSH_DIGEST_SHA256:
408: *oidp = id_sha256;
409: *oidlenp = sizeof(id_sha256);
410: break;
411: case SSH_DIGEST_SHA512:
412: *oidp = id_sha512;
413: *oidlenp = sizeof(id_sha512);
414: break;
415: default:
416: return SSH_ERR_INVALID_ARGUMENT;
417: }
418: return 0;
419: }
420:
1.25 markus 421: static int
1.52 djm 422: openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
423: u_char *sigbuf, size_t siglen, RSA *rsa)
1.25 markus 424: {
1.54 djm 425: size_t rsasize = 0, oidlen = 0, hlen = 0;
426: int ret, len, oidmatch, hashmatch;
1.25 markus 427: const u_char *oid = NULL;
428: u_char *decrypted = NULL;
429:
1.55 markus 430: if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
431: return ret;
1.52 djm 432: ret = SSH_ERR_INTERNAL_ERROR;
1.55 markus 433: hlen = ssh_digest_bytes(hash_alg);
1.25 markus 434: if (hashlen != hlen) {
1.52 djm 435: ret = SSH_ERR_INVALID_ARGUMENT;
1.25 markus 436: goto done;
437: }
438: rsasize = RSA_size(rsa);
1.52 djm 439: if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
440: siglen == 0 || siglen > rsasize) {
441: ret = SSH_ERR_INVALID_ARGUMENT;
442: goto done;
443: }
444: if ((decrypted = malloc(rsasize)) == NULL) {
445: ret = SSH_ERR_ALLOC_FAIL;
1.25 markus 446: goto done;
447: }
448: if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
449: RSA_PKCS1_PADDING)) < 0) {
1.52 djm 450: ret = SSH_ERR_LIBCRYPTO_ERROR;
1.25 markus 451: goto done;
452: }
1.52 djm 453: if (len < 0 || (size_t)len != hlen + oidlen) {
454: ret = SSH_ERR_INVALID_FORMAT;
1.25 markus 455: goto done;
456: }
1.44 djm 457: oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
458: hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
1.52 djm 459: if (!oidmatch || !hashmatch) {
460: ret = SSH_ERR_SIGNATURE_INVALID;
1.25 markus 461: goto done;
462: }
1.52 djm 463: ret = 0;
464: done:
1.65 jsing 465: freezero(decrypted, rsasize);
1.1 markus 466: return ret;
467: }
1.69 ! djm 468:
! 469: static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
! 470: /* .size = */ ssh_rsa_size,
! 471: /* .alloc = */ ssh_rsa_alloc,
! 472: /* .cleanup = */ ssh_rsa_cleanup,
! 473: };
! 474:
! 475: const struct sshkey_impl sshkey_rsa_impl = {
! 476: /* .name = */ "ssh-rsa",
! 477: /* .shortname = */ "RSA",
! 478: /* .sigalg = */ NULL,
! 479: /* .type = */ KEY_RSA,
! 480: /* .nid = */ 0,
! 481: /* .cert = */ 0,
! 482: /* .sigonly = */ 0,
! 483: /* .keybits = */ 0,
! 484: /* .funcs = */ &sshkey_rsa_funcs,
! 485: };
! 486:
! 487: const struct sshkey_impl sshkey_rsa_cert_impl = {
! 488: /* .name = */ "ssh-rsa-cert-v01@openssh.com",
! 489: /* .shortname = */ "RSA-CERT",
! 490: /* .sigalg = */ NULL,
! 491: /* .type = */ KEY_RSA_CERT,
! 492: /* .nid = */ 0,
! 493: /* .cert = */ 1,
! 494: /* .sigonly = */ 0,
! 495: /* .keybits = */ 0,
! 496: /* .funcs = */ &sshkey_rsa_funcs,
! 497: };
! 498:
! 499: /* SHA2 signature algorithms */
! 500:
! 501: const struct sshkey_impl sshkey_rsa_sha256_impl = {
! 502: /* .name = */ "rsa-sha2-256",
! 503: /* .shortname = */ "RSA",
! 504: /* .sigalg = */ NULL,
! 505: /* .type = */ KEY_RSA,
! 506: /* .nid = */ 0,
! 507: /* .cert = */ 0,
! 508: /* .sigonly = */ 1,
! 509: /* .keybits = */ 0,
! 510: /* .funcs = */ &sshkey_rsa_funcs,
! 511: };
! 512:
! 513: const struct sshkey_impl sshkey_rsa_sha512_impl = {
! 514: /* .name = */ "rsa-sha2-512",
! 515: /* .shortname = */ "RSA",
! 516: /* .sigalg = */ NULL,
! 517: /* .type = */ KEY_RSA,
! 518: /* .nid = */ 0,
! 519: /* .cert = */ 0,
! 520: /* .sigonly = */ 1,
! 521: /* .keybits = */ 0,
! 522: /* .funcs = */ &sshkey_rsa_funcs,
! 523: };
! 524:
! 525: const struct sshkey_impl sshkey_rsa_sha256_cert_impl = {
! 526: /* .name = */ "rsa-sha2-256-cert-v01@openssh.com",
! 527: /* .shortname = */ "RSA-CERT",
! 528: /* .sigalg = */ "rsa-sha2-256",
! 529: /* .type = */ KEY_RSA_CERT,
! 530: /* .nid = */ 0,
! 531: /* .cert = */ 1,
! 532: /* .sigonly = */ 1,
! 533: /* .keybits = */ 0,
! 534: /* .funcs = */ &sshkey_rsa_funcs,
! 535: };
! 536:
! 537: const struct sshkey_impl sshkey_rsa_sha512_cert_impl = {
! 538: /* .name = */ "rsa-sha2-512-cert-v01@openssh.com",
! 539: /* .shortname = */ "RSA-CERT",
! 540: /* .sigalg = */ "rsa-sha2-512",
! 541: /* .type = */ KEY_RSA_CERT,
! 542: /* .nid = */ 0,
! 543: /* .cert = */ 1,
! 544: /* .sigonly = */ 1,
! 545: /* .keybits = */ 0,
! 546: /* .funcs = */ &sshkey_rsa_funcs,
! 547: };