Bug Summary

File:src/usr.bin/ssh/ssh/../ssh-rsa.c
Warning:line 636, column 2
Value stored to 'ret' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ssh-rsa.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.bin/ssh/ssh/.. -D WITH_OPENSSL -D WITH_ZLIB -D WITH_DSA -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/ssh/ssh/../ssh-rsa.c
1/* $OpenBSD: ssh-rsa.c,v 1.79 2023/03/05 05:34:09 dtucker Exp $ */
2/*
3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4 *
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.
8 *
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.
16 */
17
18#include <sys/types.h>
19
20#include <openssl/evp.h>
21#include <openssl/err.h>
22
23#include <string.h>
24
25#include "sshbuf.h"
26#include "ssherr.h"
27#define SSHKEY_INTERNAL
28#include "sshkey.h"
29#include "digest.h"
30#include "log.h"
31
32static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
33
34static u_int
35ssh_rsa_size(const struct sshkey *key)
36{
37 const BIGNUM *rsa_n;
38
39 if (key->rsa == NULL((void *)0))
40 return 0;
41 RSA_get0_key(key->rsa, &rsa_n, NULL((void *)0), NULL((void *)0));
42 return BN_num_bits(rsa_n);
43}
44
45static int
46ssh_rsa_alloc(struct sshkey *k)
47{
48 if ((k->rsa = RSA_new()) == NULL((void *)0))
49 return SSH_ERR_ALLOC_FAIL-2;
50 return 0;
51}
52
53static void
54ssh_rsa_cleanup(struct sshkey *k)
55{
56 RSA_free(k->rsa);
57 k->rsa = NULL((void *)0);
58}
59
60static int
61ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
62{
63 const BIGNUM *rsa_e_a, *rsa_n_a;
64 const BIGNUM *rsa_e_b, *rsa_n_b;
65
66 if (a->rsa == NULL((void *)0) || b->rsa == NULL((void *)0))
67 return 0;
68 RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL((void *)0));
69 RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL((void *)0));
70 if (rsa_e_a == NULL((void *)0) || rsa_e_b == NULL((void *)0))
71 return 0;
72 if (rsa_n_a == NULL((void *)0) || rsa_n_b == NULL((void *)0))
73 return 0;
74 if (BN_cmp(rsa_e_a, rsa_e_b) != 0)
75 return 0;
76 if (BN_cmp(rsa_n_a, rsa_n_b) != 0)
77 return 0;
78 return 1;
79}
80
81static int
82ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
83 enum sshkey_serialize_rep opts)
84{
85 int r;
86 const BIGNUM *rsa_n, *rsa_e;
87
88 if (key->rsa == NULL((void *)0))
89 return SSH_ERR_INVALID_ARGUMENT-10;
90 RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL((void *)0));
91 if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
92 (r = sshbuf_put_bignum2(b, rsa_n)) != 0)
93 return r;
94
95 return 0;
96}
97
98static int
99ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
100 enum sshkey_serialize_rep opts)
101{
102 int r;
103 const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
104
105 RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
106 RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
107 RSA_get0_crt_params(key->rsa, NULL((void *)0), NULL((void *)0), &rsa_iqmp);
108
109 if (!sshkey_is_cert(key)) {
110 /* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */
111 if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
112 (r = sshbuf_put_bignum2(b, rsa_e)) != 0)
113 return r;
114 }
115 if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
116 (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
117 (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
118 (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
119 return r;
120
121 return 0;
122}
123
124static int
125ssh_rsa_generate(struct sshkey *k, int bits)
126{
127 RSA *private = NULL((void *)0);
128 BIGNUM *f4 = NULL((void *)0);
129 int ret = SSH_ERR_INTERNAL_ERROR-1;
130
131 if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE1024 ||
132 bits > SSHBUF_MAX_BIGNUM(16384 / 8) * 8)
133 return SSH_ERR_KEY_LENGTH-56;
134 if ((private = RSA_new()) == NULL((void *)0) || (f4 = BN_new()) == NULL((void *)0)) {
135 ret = SSH_ERR_ALLOC_FAIL-2;
136 goto out;
137 }
138 if (!BN_set_word(f4, RSA_F40x10001L) ||
139 !RSA_generate_key_ex(private, bits, f4, NULL((void *)0))) {
140 ret = SSH_ERR_LIBCRYPTO_ERROR-22;
141 goto out;
142 }
143 k->rsa = private;
144 private = NULL((void *)0);
145 ret = 0;
146 out:
147 RSA_free(private);
148 BN_free(f4);
149 return ret;
150}
151
152static int
153ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to)
154{
155 const BIGNUM *rsa_n, *rsa_e;
156 BIGNUM *rsa_n_dup = NULL((void *)0), *rsa_e_dup = NULL((void *)0);
157 int r = SSH_ERR_INTERNAL_ERROR-1;
158
159 RSA_get0_key(from->rsa, &rsa_n, &rsa_e, NULL((void *)0));
160 if ((rsa_n_dup = BN_dup(rsa_n)) == NULL((void *)0) ||
161 (rsa_e_dup = BN_dup(rsa_e)) == NULL((void *)0)) {
162 r = SSH_ERR_ALLOC_FAIL-2;
163 goto out;
164 }
165 if (!RSA_set0_key(to->rsa, rsa_n_dup, rsa_e_dup, NULL((void *)0))) {
166 r = SSH_ERR_LIBCRYPTO_ERROR-22;
167 goto out;
168 }
169 rsa_n_dup = rsa_e_dup = NULL((void *)0); /* transferred */
170 /* success */
171 r = 0;
172 out:
173 BN_clear_free(rsa_n_dup);
174 BN_clear_free(rsa_e_dup);
175 return r;
176}
177
178static int
179ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
180 struct sshkey *key)
181{
182 int ret = SSH_ERR_INTERNAL_ERROR-1;
183 BIGNUM *rsa_n = NULL((void *)0), *rsa_e = NULL((void *)0);
184
185 if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
186 sshbuf_get_bignum2(b, &rsa_n) != 0) {
187 ret = SSH_ERR_INVALID_FORMAT-4;
188 goto out;
189 }
190 if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL((void *)0))) {
191 ret = SSH_ERR_LIBCRYPTO_ERROR-22;
192 goto out;
193 }
194 rsa_n = rsa_e = NULL((void *)0); /* transferred */
195 if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
196 goto out;
197#ifdef DEBUG_PK
198 RSA_print_fp(stderr(&__sF[2]), key->rsa, 8);
199#endif
200 /* success */
201 ret = 0;
202 out:
203 BN_clear_free(rsa_n);
204 BN_clear_free(rsa_e);
205 return ret;
206}
207
208static int
209ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
210 struct sshkey *key)
211{
212 int r;
213 BIGNUM *rsa_n = NULL((void *)0), *rsa_e = NULL((void *)0), *rsa_d = NULL((void *)0);
214 BIGNUM *rsa_iqmp = NULL((void *)0), *rsa_p = NULL((void *)0), *rsa_q = NULL((void *)0);
215
216 /* Note: can't reuse ssh_rsa_deserialize_public: e, n vs. n, e */
217 if (!sshkey_is_cert(key)) {
218 if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 ||
219 (r = sshbuf_get_bignum2(b, &rsa_e)) != 0)
220 goto out;
221 if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL((void *)0))) {
222 r = SSH_ERR_LIBCRYPTO_ERROR-22;
223 goto out;
224 }
225 rsa_n = rsa_e = NULL((void *)0); /* transferred */
226 }
227 if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 ||
228 (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 ||
229 (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
230 (r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
231 goto out;
232 if (!RSA_set0_key(key->rsa, NULL((void *)0), NULL((void *)0), rsa_d)) {
233 r = SSH_ERR_LIBCRYPTO_ERROR-22;
234 goto out;
235 }
236 rsa_d = NULL((void *)0); /* transferred */
237 if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) {
238 r = SSH_ERR_LIBCRYPTO_ERROR-22;
239 goto out;
240 }
241 rsa_p = rsa_q = NULL((void *)0); /* transferred */
242 if ((r = sshkey_check_rsa_length(key, 0)) != 0)
243 goto out;
244 if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
245 goto out;
246 if (RSA_blinding_on(key->rsa, NULL((void *)0)) != 1) {
247 r = SSH_ERR_LIBCRYPTO_ERROR-22;
248 goto out;
249 }
250 /* success */
251 r = 0;
252 out:
253 BN_clear_free(rsa_n);
254 BN_clear_free(rsa_e);
255 BN_clear_free(rsa_d);
256 BN_clear_free(rsa_p);
257 BN_clear_free(rsa_q);
258 BN_clear_free(rsa_iqmp);
259 return r;
260}
261
262static const char *
263rsa_hash_alg_ident(int hash_alg)
264{
265 switch (hash_alg) {
266 case SSH_DIGEST_SHA11:
267 return "ssh-rsa";
268 case SSH_DIGEST_SHA2562:
269 return "rsa-sha2-256";
270 case SSH_DIGEST_SHA5124:
271 return "rsa-sha2-512";
272 }
273 return NULL((void *)0);
274}
275
276/*
277 * Returns the hash algorithm ID for a given algorithm identifier as used
278 * inside the signature blob,
279 */
280static int
281rsa_hash_id_from_ident(const char *ident)
282{
283 if (strcmp(ident, "ssh-rsa") == 0)
284 return SSH_DIGEST_SHA11;
285 if (strcmp(ident, "rsa-sha2-256") == 0)
286 return SSH_DIGEST_SHA2562;
287 if (strcmp(ident, "rsa-sha2-512") == 0)
288 return SSH_DIGEST_SHA5124;
289 return -1;
290}
291
292/*
293 * Return the hash algorithm ID for the specified key name. This includes
294 * all the cases of rsa_hash_id_from_ident() but also the certificate key
295 * types.
296 */
297static int
298rsa_hash_id_from_keyname(const char *alg)
299{
300 int r;
301
302 if ((r = rsa_hash_id_from_ident(alg)) != -1)
303 return r;
304 if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
305 return SSH_DIGEST_SHA11;
306 if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
307 return SSH_DIGEST_SHA2562;
308 if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
309 return SSH_DIGEST_SHA5124;
310 return -1;
311}
312
313static int
314rsa_hash_alg_nid(int type)
315{
316 switch (type) {
317 case SSH_DIGEST_SHA11:
318 return NID_sha164;
319 case SSH_DIGEST_SHA2562:
320 return NID_sha256672;
321 case SSH_DIGEST_SHA5124:
322 return NID_sha512674;
323 default:
324 return -1;
325 }
326}
327
328int
329ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
330{
331 const BIGNUM *rsa_p, *rsa_q, *rsa_d;
332 BIGNUM *aux = NULL((void *)0), *d_consttime = NULL((void *)0);
333 BIGNUM *rsa_dmq1 = NULL((void *)0), *rsa_dmp1 = NULL((void *)0), *rsa_iqmp = NULL((void *)0);
334 BN_CTX *ctx = NULL((void *)0);
335 int r;
336
337 if (key == NULL((void *)0) || key->rsa == NULL((void *)0) ||
338 sshkey_type_plain(key->type) != KEY_RSA)
339 return SSH_ERR_INVALID_ARGUMENT-10;
340
341 RSA_get0_key(key->rsa, NULL((void *)0), NULL((void *)0), &rsa_d);
342 RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
343
344 if ((ctx = BN_CTX_new()) == NULL((void *)0))
345 return SSH_ERR_ALLOC_FAIL-2;
346 if ((aux = BN_new()) == NULL((void *)0) ||
347 (rsa_dmq1 = BN_new()) == NULL((void *)0) ||
348 (rsa_dmp1 = BN_new()) == NULL((void *)0))
349 return SSH_ERR_ALLOC_FAIL-2;
350 if ((d_consttime = BN_dup(rsa_d)) == NULL((void *)0) ||
351 (rsa_iqmp = BN_dup(iqmp)) == NULL((void *)0)) {
352 r = SSH_ERR_ALLOC_FAIL-2;
353 goto out;
354 }
355 BN_set_flags(aux, BN_FLG_CONSTTIME0x04);
356 BN_set_flags(d_consttime, BN_FLG_CONSTTIME0x04);
357
358 if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
359 (BN_mod(rsa_dmq1, d_consttime, aux, ctx)BN_div(((void *)0),(rsa_dmq1),(d_consttime),(aux),(ctx)) == 0) ||
360 (BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
361 (BN_mod(rsa_dmp1, d_consttime, aux, ctx)BN_div(((void *)0),(rsa_dmp1),(d_consttime),(aux),(ctx)) == 0)) {
362 r = SSH_ERR_LIBCRYPTO_ERROR-22;
363 goto out;
364 }
365 if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
366 r = SSH_ERR_LIBCRYPTO_ERROR-22;
367 goto out;
368 }
369 rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL((void *)0); /* transferred */
370 /* success */
371 r = 0;
372 out:
373 BN_clear_free(aux);
374 BN_clear_free(d_consttime);
375 BN_clear_free(rsa_dmp1);
376 BN_clear_free(rsa_dmq1);
377 BN_clear_free(rsa_iqmp);
378 BN_CTX_free(ctx);
379 return r;
380}
381
382/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
383static int
384ssh_rsa_sign(struct sshkey *key,
385 u_char **sigp, size_t *lenp,
386 const u_char *data, size_t datalen,
387 const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
388{
389 const BIGNUM *rsa_n;
390 u_char digest[SSH_DIGEST_MAX_LENGTH64], *sig = NULL((void *)0);
391 size_t slen = 0;
392 u_int hlen, len;
393 int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR-1;
394 struct sshbuf *b = NULL((void *)0);
395
396 if (lenp != NULL((void *)0))
397 *lenp = 0;
398 if (sigp != NULL((void *)0))
399 *sigp = NULL((void *)0);
400
401 if (alg == NULL((void *)0) || strlen(alg) == 0)
402 hash_alg = SSH_DIGEST_SHA11;
403 else
404 hash_alg = rsa_hash_id_from_keyname(alg);
405 if (key == NULL((void *)0) || key->rsa == NULL((void *)0) || hash_alg == -1 ||
406 sshkey_type_plain(key->type) != KEY_RSA)
407 return SSH_ERR_INVALID_ARGUMENT-10;
408 RSA_get0_key(key->rsa, &rsa_n, NULL((void *)0), NULL((void *)0));
409 if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE1024)
410 return SSH_ERR_KEY_LENGTH-56;
411 slen = RSA_size(key->rsa);
412 if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM(16384 / 8))
413 return SSH_ERR_INVALID_ARGUMENT-10;
414
415 /* hash the data */
416 nid = rsa_hash_alg_nid(hash_alg);
417 if ((hlen = ssh_digest_bytes(hash_alg)) == 0)
418 return SSH_ERR_INTERNAL_ERROR-1;
419 if ((ret = ssh_digest_memory(hash_alg, data, datalen,
420 digest, sizeof(digest))) != 0)
421 goto out;
422
423 if ((sig = malloc(slen)) == NULL((void *)0)) {
424 ret = SSH_ERR_ALLOC_FAIL-2;
425 goto out;
426 }
427
428 if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) {
429 ret = SSH_ERR_LIBCRYPTO_ERROR-22;
430 goto out;
431 }
432 if (len < slen) {
433 size_t diff = slen - len;
434 memmove(sig + diff, sig, len);
435 explicit_bzero(sig, diff);
436 } else if (len > slen) {
437 ret = SSH_ERR_INTERNAL_ERROR-1;
438 goto out;
439 }
440 /* encode signature */
441 if ((b = sshbuf_new()) == NULL((void *)0)) {
442 ret = SSH_ERR_ALLOC_FAIL-2;
443 goto out;
444 }
445 if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
446 (ret = sshbuf_put_string(b, sig, slen)) != 0)
447 goto out;
448 len = sshbuf_len(b);
449 if (sigp != NULL((void *)0)) {
450 if ((*sigp = malloc(len)) == NULL((void *)0)) {
451 ret = SSH_ERR_ALLOC_FAIL-2;
452 goto out;
453 }
454 memcpy(*sigp, sshbuf_ptr(b), len);
455 }
456 if (lenp != NULL((void *)0))
457 *lenp = len;
458 ret = 0;
459 out:
460 explicit_bzero(digest, sizeof(digest));
461 freezero(sig, slen);
462 sshbuf_free(b);
463 return ret;
464}
465
466static int
467ssh_rsa_verify(const struct sshkey *key,
468 const u_char *sig, size_t siglen,
469 const u_char *data, size_t dlen, const char *alg, u_int compat,
470 struct sshkey_sig_details **detailsp)
471{
472 const BIGNUM *rsa_n;
473 char *sigtype = NULL((void *)0);
474 int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR-1;
475 size_t len = 0, diff, modlen, hlen;
476 struct sshbuf *b = NULL((void *)0);
477 u_char digest[SSH_DIGEST_MAX_LENGTH64], *osigblob, *sigblob = NULL((void *)0);
478
479 if (key == NULL((void *)0) || key->rsa == NULL((void *)0) ||
480 sshkey_type_plain(key->type) != KEY_RSA ||
481 sig == NULL((void *)0) || siglen == 0)
482 return SSH_ERR_INVALID_ARGUMENT-10;
483 RSA_get0_key(key->rsa, &rsa_n, NULL((void *)0), NULL((void *)0));
484 if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE1024)
485 return SSH_ERR_KEY_LENGTH-56;
486
487 if ((b = sshbuf_from(sig, siglen)) == NULL((void *)0))
488 return SSH_ERR_ALLOC_FAIL-2;
489 if (sshbuf_get_cstring(b, &sigtype, NULL((void *)0)) != 0) {
490 ret = SSH_ERR_INVALID_FORMAT-4;
491 goto out;
492 }
493 if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
494 ret = SSH_ERR_KEY_TYPE_MISMATCH-13;
495 goto out;
496 }
497 /*
498 * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
499 * legacy reasons, but otherwise the signature type should match.
500 */
501 if (alg != NULL((void *)0) && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
502 if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
503 ret = SSH_ERR_INVALID_ARGUMENT-10;
504 goto out;
505 }
506 if (hash_alg != want_alg) {
507 ret = SSH_ERR_SIGNATURE_INVALID-21;
508 goto out;
509 }
510 }
511 if (sshbuf_get_string(b, &sigblob, &len) != 0) {
512 ret = SSH_ERR_INVALID_FORMAT-4;
513 goto out;
514 }
515 if (sshbuf_len(b) != 0) {
516 ret = SSH_ERR_UNEXPECTED_TRAILING_DATA-23;
517 goto out;
518 }
519 /* RSA_verify expects a signature of RSA_size */
520 modlen = RSA_size(key->rsa);
521 if (len > modlen) {
522 ret = SSH_ERR_KEY_BITS_MISMATCH-11;
523 goto out;
524 } else if (len < modlen) {
525 diff = modlen - len;
526 osigblob = sigblob;
527 if ((sigblob = realloc(sigblob, modlen)) == NULL((void *)0)) {
528 sigblob = osigblob; /* put it back for clear/free */
529 ret = SSH_ERR_ALLOC_FAIL-2;
530 goto out;
531 }
532 memmove(sigblob + diff, sigblob, len);
533 explicit_bzero(sigblob, diff);
534 len = modlen;
535 }
536 if ((hlen = ssh_digest_bytes(hash_alg)) == 0) {
537 ret = SSH_ERR_INTERNAL_ERROR-1;
538 goto out;
539 }
540 if ((ret = ssh_digest_memory(hash_alg, data, dlen,
541 digest, sizeof(digest))) != 0)
542 goto out;
543
544 ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len,
545 key->rsa);
546 out:
547 freezero(sigblob, len);
548 free(sigtype);
549 sshbuf_free(b);
550 explicit_bzero(digest, sizeof(digest));
551 return ret;
552}
553
554/*
555 * See:
556 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
557 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
558 */
559
560/*
561 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
562 * oiw(14) secsig(3) algorithms(2) 26 }
563 */
564static const u_char id_sha1[] = {
565 0x30, 0x21, /* type Sequence, length 0x21 (33) */
566 0x30, 0x09, /* type Sequence, length 0x09 */
567 0x06, 0x05, /* type OID, length 0x05 */
568 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
569 0x05, 0x00, /* NULL */
570 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
571};
572
573/*
574 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
575 * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
576 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
577 * id-sha256(1) }
578 */
579static const u_char id_sha256[] = {
580 0x30, 0x31, /* type Sequence, length 0x31 (49) */
581 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
582 0x06, 0x09, /* type OID, length 0x09 */
583 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
584 0x05, 0x00, /* NULL */
585 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
586};
587
588/*
589 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
590 * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
591 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
592 * id-sha256(3) }
593 */
594static const u_char id_sha512[] = {
595 0x30, 0x51, /* type Sequence, length 0x51 (81) */
596 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
597 0x06, 0x09, /* type OID, length 0x09 */
598 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
599 0x05, 0x00, /* NULL */
600 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
601};
602
603static int
604rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
605{
606 switch (hash_alg) {
607 case SSH_DIGEST_SHA11:
608 *oidp = id_sha1;
609 *oidlenp = sizeof(id_sha1);
610 break;
611 case SSH_DIGEST_SHA2562:
612 *oidp = id_sha256;
613 *oidlenp = sizeof(id_sha256);
614 break;
615 case SSH_DIGEST_SHA5124:
616 *oidp = id_sha512;
617 *oidlenp = sizeof(id_sha512);
618 break;
619 default:
620 return SSH_ERR_INVALID_ARGUMENT-10;
621 }
622 return 0;
623}
624
625static int
626openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
627 u_char *sigbuf, size_t siglen, RSA *rsa)
628{
629 size_t rsasize = 0, oidlen = 0, hlen = 0;
630 int ret, len, oidmatch, hashmatch;
631 const u_char *oid = NULL((void *)0);
632 u_char *decrypted = NULL((void *)0);
633
634 if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
635 return ret;
636 ret = SSH_ERR_INTERNAL_ERROR-1;
Value stored to 'ret' is never read
637 hlen = ssh_digest_bytes(hash_alg);
638 if (hashlen != hlen) {
639 ret = SSH_ERR_INVALID_ARGUMENT-10;
640 goto done;
641 }
642 rsasize = RSA_size(rsa);
643 if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM(16384 / 8) ||
644 siglen == 0 || siglen > rsasize) {
645 ret = SSH_ERR_INVALID_ARGUMENT-10;
646 goto done;
647 }
648 if ((decrypted = malloc(rsasize)) == NULL((void *)0)) {
649 ret = SSH_ERR_ALLOC_FAIL-2;
650 goto done;
651 }
652 if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
653 RSA_PKCS1_PADDING1)) < 0) {
654 ret = SSH_ERR_LIBCRYPTO_ERROR-22;
655 goto done;
656 }
657 if (len < 0 || (size_t)len != hlen + oidlen) {
658 ret = SSH_ERR_INVALID_FORMAT-4;
659 goto done;
660 }
661 oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
662 hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
663 if (!oidmatch || !hashmatch) {
664 ret = SSH_ERR_SIGNATURE_INVALID-21;
665 goto done;
666 }
667 ret = 0;
668done:
669 freezero(decrypted, rsasize);
670 return ret;
671}
672
673static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
674 /* .size = */ ssh_rsa_size,
675 /* .alloc = */ ssh_rsa_alloc,
676 /* .cleanup = */ ssh_rsa_cleanup,
677 /* .equal = */ ssh_rsa_equal,
678 /* .ssh_serialize_public = */ ssh_rsa_serialize_public,
679 /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
680 /* .ssh_serialize_private = */ ssh_rsa_serialize_private,
681 /* .ssh_deserialize_private = */ ssh_rsa_deserialize_private,
682 /* .generate = */ ssh_rsa_generate,
683 /* .copy_public = */ ssh_rsa_copy_public,
684 /* .sign = */ ssh_rsa_sign,
685 /* .verify = */ ssh_rsa_verify,
686};
687
688const struct sshkey_impl sshkey_rsa_impl = {
689 /* .name = */ "ssh-rsa",
690 /* .shortname = */ "RSA",
691 /* .sigalg = */ NULL((void *)0),
692 /* .type = */ KEY_RSA,
693 /* .nid = */ 0,
694 /* .cert = */ 0,
695 /* .sigonly = */ 0,
696 /* .keybits = */ 0,
697 /* .funcs = */ &sshkey_rsa_funcs,
698};
699
700const struct sshkey_impl sshkey_rsa_cert_impl = {
701 /* .name = */ "ssh-rsa-cert-v01@openssh.com",
702 /* .shortname = */ "RSA-CERT",
703 /* .sigalg = */ NULL((void *)0),
704 /* .type = */ KEY_RSA_CERT,
705 /* .nid = */ 0,
706 /* .cert = */ 1,
707 /* .sigonly = */ 0,
708 /* .keybits = */ 0,
709 /* .funcs = */ &sshkey_rsa_funcs,
710};
711
712/* SHA2 signature algorithms */
713
714const struct sshkey_impl sshkey_rsa_sha256_impl = {
715 /* .name = */ "rsa-sha2-256",
716 /* .shortname = */ "RSA",
717 /* .sigalg = */ NULL((void *)0),
718 /* .type = */ KEY_RSA,
719 /* .nid = */ 0,
720 /* .cert = */ 0,
721 /* .sigonly = */ 1,
722 /* .keybits = */ 0,
723 /* .funcs = */ &sshkey_rsa_funcs,
724};
725
726const struct sshkey_impl sshkey_rsa_sha512_impl = {
727 /* .name = */ "rsa-sha2-512",
728 /* .shortname = */ "RSA",
729 /* .sigalg = */ NULL((void *)0),
730 /* .type = */ KEY_RSA,
731 /* .nid = */ 0,
732 /* .cert = */ 0,
733 /* .sigonly = */ 1,
734 /* .keybits = */ 0,
735 /* .funcs = */ &sshkey_rsa_funcs,
736};
737
738const struct sshkey_impl sshkey_rsa_sha256_cert_impl = {
739 /* .name = */ "rsa-sha2-256-cert-v01@openssh.com",
740 /* .shortname = */ "RSA-CERT",
741 /* .sigalg = */ "rsa-sha2-256",
742 /* .type = */ KEY_RSA_CERT,
743 /* .nid = */ 0,
744 /* .cert = */ 1,
745 /* .sigonly = */ 1,
746 /* .keybits = */ 0,
747 /* .funcs = */ &sshkey_rsa_funcs,
748};
749
750const struct sshkey_impl sshkey_rsa_sha512_cert_impl = {
751 /* .name = */ "rsa-sha2-512-cert-v01@openssh.com",
752 /* .shortname = */ "RSA-CERT",
753 /* .sigalg = */ "rsa-sha2-512",
754 /* .type = */ KEY_RSA_CERT,
755 /* .nid = */ 0,
756 /* .cert = */ 1,
757 /* .sigonly = */ 1,
758 /* .keybits = */ 0,
759 /* .funcs = */ &sshkey_rsa_funcs,
760};