Bug Summary

File:src/usr.bin/ssh/ssh-keygen/../sshsig.c
Warning:line 896, column 9
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sshsig.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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-keygen/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/ssh/ssh-keygen/.. -D WITH_OPENSSL -D WITH_ZLIB -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh-keygen/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c
1/* $OpenBSD: sshsig.c,v 1.27 2022/01/05 04:02:42 djm Exp $ */
2/*
3 * Copyright (c) 2019 Google LLC
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 <stdio.h>
19#include <stdlib.h>
20#include <stdarg.h>
21#include <errno(*__errno()).h>
22#include <string.h>
23#include <unistd.h>
24
25#include "authfd.h"
26#include "authfile.h"
27#include "log.h"
28#include "misc.h"
29#include "sshbuf.h"
30#include "sshsig.h"
31#include "ssherr.h"
32#include "sshkey.h"
33#include "match.h"
34#include "digest.h"
35
36#define SIG_VERSION0x01 0x01
37#define MAGIC_PREAMBLE"SSHSIG" "SSHSIG"
38#define MAGIC_PREAMBLE_LEN(sizeof("SSHSIG") - 1) (sizeof(MAGIC_PREAMBLE"SSHSIG") - 1)
39#define BEGIN_SIGNATURE"-----BEGIN SSH SIGNATURE-----\n" "-----BEGIN SSH SIGNATURE-----\n"
40#define END_SIGNATURE"-----END SSH SIGNATURE-----" "-----END SSH SIGNATURE-----"
41#define RSA_SIGN_ALG"rsa-sha2-512" "rsa-sha2-512" /* XXX maybe make configurable */
42#define RSA_SIGN_ALLOWED"rsa-sha2-512,rsa-sha2-256" "rsa-sha2-512,rsa-sha2-256"
43#define HASHALG_DEFAULT"sha512" "sha512" /* XXX maybe make configurable */
44#define HASHALG_ALLOWED"sha256,sha512" "sha256,sha512"
45
46int
47sshsig_armor(const struct sshbuf *blob, struct sshbuf **out)
48{
49 struct sshbuf *buf = NULL((void *)0);
50 int r = SSH_ERR_INTERNAL_ERROR-1;
51
52 *out = NULL((void *)0);
53
54 if ((buf = sshbuf_new()) == NULL((void *)0)) {
55 error_f("sshbuf_new failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 55, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshbuf_new failed"
)
;
56 r = SSH_ERR_ALLOC_FAIL-2;
57 goto out;
58 }
59
60 if ((r = sshbuf_put(buf, BEGIN_SIGNATURE"-----BEGIN SSH SIGNATURE-----\n",
61 sizeof(BEGIN_SIGNATURE"-----BEGIN SSH SIGNATURE-----\n")-1)) != 0) {
62 error_fr(r, "sshbuf_putf")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 62, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshbuf_putf")
;
63 goto out;
64 }
65
66 if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) {
67 error_fr(r, "base64 encode signature")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 67, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "base64 encode signature"
)
;
68 goto out;
69 }
70
71 if ((r = sshbuf_put(buf, END_SIGNATURE"-----END SSH SIGNATURE-----",
72 sizeof(END_SIGNATURE"-----END SSH SIGNATURE-----")-1)) != 0 ||
73 (r = sshbuf_put_u8(buf, '\n')) != 0) {
74 error_fr(r, "sshbuf_put")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 74, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshbuf_put")
;
75 goto out;
76 }
77 /* success */
78 *out = buf;
79 buf = NULL((void *)0); /* transferred */
80 r = 0;
81 out:
82 sshbuf_free(buf);
83 return r;
84}
85
86int
87sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out)
88{
89 int r;
90 size_t eoffset = 0;
91 struct sshbuf *buf = NULL((void *)0);
92 struct sshbuf *sbuf = NULL((void *)0);
93 char *b64 = NULL((void *)0);
94
95 if ((sbuf = sshbuf_fromb(sig)) == NULL((void *)0)) {
96 error_f("sshbuf_fromb failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 96, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshbuf_fromb failed"
)
;
97 return SSH_ERR_ALLOC_FAIL-2;
98 }
99
100 if ((r = sshbuf_cmp(sbuf, 0,
101 BEGIN_SIGNATURE"-----BEGIN SSH SIGNATURE-----\n", sizeof(BEGIN_SIGNATURE"-----BEGIN SSH SIGNATURE-----\n")-1)) != 0) {
102 error("Couldn't parse signature: missing header")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 102, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't parse signature: missing header"
)
;
103 goto done;
104 }
105
106 if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE"-----BEGIN SSH SIGNATURE-----\n")-1)) != 0) {
107 error_fr(r, "consume")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 107, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "consume")
;
108 goto done;
109 }
110
111 if ((r = sshbuf_find(sbuf, 0, "\n" END_SIGNATURE"-----END SSH SIGNATURE-----",
112 sizeof("\n" END_SIGNATURE"-----END SSH SIGNATURE-----")-1, &eoffset)) != 0) {
113 error("Couldn't parse signature: missing footer")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 113, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't parse signature: missing footer"
)
;
114 goto done;
115 }
116
117 if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) {
118 error_fr(r, "consume")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 118, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "consume")
;
119 goto done;
120 }
121
122 if ((b64 = sshbuf_dup_string(sbuf)) == NULL((void *)0)) {
123 error_f("sshbuf_dup_string failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 123, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshbuf_dup_string failed"
)
;
124 r = SSH_ERR_ALLOC_FAIL-2;
125 goto done;
126 }
127
128 if ((buf = sshbuf_new()) == NULL((void *)0)) {
129 error_f("sshbuf_new() failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 129, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshbuf_new() failed"
)
;
130 r = SSH_ERR_ALLOC_FAIL-2;
131 goto done;
132 }
133
134 if ((r = sshbuf_b64tod(buf, b64)) != 0) {
135 error_fr(r, "decode base64")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 135, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "decode base64")
;
136 goto done;
137 }
138
139 /* success */
140 *out = buf;
141 r = 0;
142 buf = NULL((void *)0); /* transferred */
143done:
144 sshbuf_free(buf);
145 sshbuf_free(sbuf);
146 free(b64);
147 return r;
148}
149
150static int
151sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
152 const char *sk_provider, const char *sk_pin, const struct sshbuf *h_message,
153 const char *sig_namespace, struct sshbuf **out,
154 sshsig_signer *signer, void *signer_ctx)
155{
156 int r;
157 size_t slen = 0;
158 u_char *sig = NULL((void *)0);
159 struct sshbuf *blob = NULL((void *)0);
160 struct sshbuf *tosign = NULL((void *)0);
161 const char *sign_alg = NULL((void *)0);
162
163 if ((tosign = sshbuf_new()) == NULL((void *)0) ||
164 (blob = sshbuf_new()) == NULL((void *)0)) {
165 error_f("sshbuf_new failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 165, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshbuf_new failed"
)
;
166 r = SSH_ERR_ALLOC_FAIL-2;
167 goto done;
168 }
169
170 if ((r = sshbuf_put(tosign, MAGIC_PREAMBLE"SSHSIG", MAGIC_PREAMBLE_LEN(sizeof("SSHSIG") - 1))) != 0 ||
171 (r = sshbuf_put_cstring(tosign, sig_namespace)) != 0 ||
172 (r = sshbuf_put_string(tosign, NULL((void *)0), 0)) != 0 || /* reserved */
173 (r = sshbuf_put_cstring(tosign, hashalg)) != 0 ||
174 (r = sshbuf_put_stringb(tosign, h_message)) != 0) {
175 error_fr(r, "assemble message to sign")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 175, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "assemble message to sign"
)
;
176 goto done;
177 }
178
179 /* If using RSA keys then default to a good signature algorithm */
180 if (sshkey_type_plain(key->type) == KEY_RSA)
181 sign_alg = RSA_SIGN_ALG"rsa-sha2-512";
182
183 if (signer != NULL((void *)0)) {
184 if ((r = signer(key, &sig, &slen,
185 sshbuf_ptr(tosign), sshbuf_len(tosign),
186 sign_alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) {
187 error_r(r, "Couldn't sign message (signer)")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 187, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't sign message (signer)"
)
;
188 goto done;
189 }
190 } else {
191 if ((r = sshkey_sign(key, &sig, &slen,
192 sshbuf_ptr(tosign), sshbuf_len(tosign),
193 sign_alg, sk_provider, sk_pin, 0)) != 0) {
194 error_r(r, "Couldn't sign message")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 194, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't sign message"
)
;
195 goto done;
196 }
197 }
198
199 if ((r = sshbuf_put(blob, MAGIC_PREAMBLE"SSHSIG", MAGIC_PREAMBLE_LEN(sizeof("SSHSIG") - 1))) != 0 ||
200 (r = sshbuf_put_u32(blob, SIG_VERSION0x01)) != 0 ||
201 (r = sshkey_puts(key, blob)) != 0 ||
202 (r = sshbuf_put_cstring(blob, sig_namespace)) != 0 ||
203 (r = sshbuf_put_string(blob, NULL((void *)0), 0)) != 0 || /* reserved */
204 (r = sshbuf_put_cstring(blob, hashalg)) != 0 ||
205 (r = sshbuf_put_string(blob, sig, slen)) != 0) {
206 error_fr(r, "assemble signature object")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 206, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "assemble signature object"
)
;
207 goto done;
208 }
209
210 if (out != NULL((void *)0)) {
211 *out = blob;
212 blob = NULL((void *)0);
213 }
214 r = 0;
215done:
216 free(sig);
217 sshbuf_free(blob);
218 sshbuf_free(tosign);
219 return r;
220}
221
222/* Check preamble and version. */
223static int
224sshsig_parse_preamble(struct sshbuf *buf)
225{
226 int r = SSH_ERR_INTERNAL_ERROR-1;
227 uint32_t sversion;
228
229 if ((r = sshbuf_cmp(buf, 0, MAGIC_PREAMBLE"SSHSIG", MAGIC_PREAMBLE_LEN(sizeof("SSHSIG") - 1))) != 0 ||
230 (r = sshbuf_consume(buf, (sizeof(MAGIC_PREAMBLE"SSHSIG")-1))) != 0 ||
231 (r = sshbuf_get_u32(buf, &sversion)) != 0) {
232 error("Couldn't verify signature: invalid format")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 232, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't verify signature: invalid format"
)
;
233 return r;
234 }
235
236 if (sversion > SIG_VERSION0x01) {
237 error("Signature version %lu is larger than supported "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 238, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Signature version %lu is larger than supported "
"version %u", (unsigned long)sversion, 0x01)
238 "version %u", (unsigned long)sversion, SIG_VERSION)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 238, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Signature version %lu is larger than supported "
"version %u", (unsigned long)sversion, 0x01)
;
239 return SSH_ERR_INVALID_FORMAT-4;
240 }
241 return 0;
242}
243
244static int
245sshsig_check_hashalg(const char *hashalg)
246{
247 if (hashalg == NULL((void *)0) ||
248 match_pattern_list(hashalg, HASHALG_ALLOWED"sha256,sha512", 0) == 1)
249 return 0;
250 error_f("unsupported hash algorithm \"%.100s\"", hashalg)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 250, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "unsupported hash algorithm \"%.100s\""
, hashalg)
;
251 return SSH_ERR_SIGN_ALG_UNSUPPORTED-58;
252}
253
254static int
255sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp)
256{
257 struct sshbuf *buf = NULL((void *)0);
258 char *hashalg = NULL((void *)0);
259 int r = SSH_ERR_INTERNAL_ERROR-1;
260
261 if (hashalgp != NULL((void *)0))
262 *hashalgp = NULL((void *)0);
263 if ((buf = sshbuf_fromb(signature)) == NULL((void *)0))
264 return SSH_ERR_ALLOC_FAIL-2;
265 if ((r = sshsig_parse_preamble(buf)) != 0)
266 goto done;
267 if ((r = sshbuf_get_string_direct(buf, NULL((void *)0), NULL((void *)0))) != 0 ||
268 (r = sshbuf_get_string_direct(buf, NULL((void *)0), NULL((void *)0))) != 0 ||
269 (r = sshbuf_get_string(buf, NULL((void *)0), NULL((void *)0))) != 0 ||
270 (r = sshbuf_get_cstring(buf, &hashalg, NULL((void *)0))) != 0 ||
271 (r = sshbuf_get_string_direct(buf, NULL((void *)0), NULL((void *)0))) != 0) {
272 error_fr(r, "parse signature object")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 272, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse signature object"
)
;
273 goto done;
274 }
275
276 /* success */
277 r = 0;
278 *hashalgp = hashalg;
279 hashalg = NULL((void *)0);
280 done:
281 free(hashalg);
282 sshbuf_free(buf);
283 return r;
284}
285
286static int
287sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
288 const struct sshbuf *h_message, const char *expect_namespace,
289 struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details)
290{
291 int r = SSH_ERR_INTERNAL_ERROR-1;
292 struct sshbuf *buf = NULL((void *)0), *toverify = NULL((void *)0);
293 struct sshkey *key = NULL((void *)0);
294 const u_char *sig;
295 char *got_namespace = NULL((void *)0), *sigtype = NULL((void *)0), *sig_hashalg = NULL((void *)0);
296 size_t siglen;
297
298 debug_f("verify message length %zu", sshbuf_len(h_message))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 298, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "verify message length %zu"
, sshbuf_len(h_message))
;
299 if (sig_details != NULL((void *)0))
300 *sig_details = NULL((void *)0);
301 if (sign_keyp != NULL((void *)0))
302 *sign_keyp = NULL((void *)0);
303
304 if ((toverify = sshbuf_new()) == NULL((void *)0)) {
305 error_f("sshbuf_new failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 305, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshbuf_new failed"
)
;
306 r = SSH_ERR_ALLOC_FAIL-2;
307 goto done;
308 }
309 if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE"SSHSIG",
310 MAGIC_PREAMBLE_LEN(sizeof("SSHSIG") - 1))) != 0 ||
311 (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 ||
312 (r = sshbuf_put_string(toverify, NULL((void *)0), 0)) != 0 || /* reserved */
313 (r = sshbuf_put_cstring(toverify, hashalg)) != 0 ||
314 (r = sshbuf_put_stringb(toverify, h_message)) != 0) {
315 error_fr(r, "assemble message to verify")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 315, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "assemble message to verify"
)
;
316 goto done;
317 }
318
319 if ((r = sshsig_parse_preamble(signature)) != 0)
320 goto done;
321
322 if ((r = sshkey_froms(signature, &key)) != 0 ||
323 (r = sshbuf_get_cstring(signature, &got_namespace, NULL((void *)0))) != 0 ||
324 (r = sshbuf_get_string(signature, NULL((void *)0), NULL((void *)0))) != 0 ||
325 (r = sshbuf_get_cstring(signature, &sig_hashalg, NULL((void *)0))) != 0 ||
326 (r = sshbuf_get_string_direct(signature, &sig, &siglen)) != 0) {
327 error_fr(r, "parse signature object")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 327, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse signature object"
)
;
328 goto done;
329 }
330
331 if (sshbuf_len(signature) != 0) {
332 error("Signature contains trailing data")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 332, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Signature contains trailing data"
)
;
333 r = SSH_ERR_INVALID_FORMAT-4;
334 goto done;
335 }
336
337 if (strcmp(expect_namespace, got_namespace) != 0) {
338 error("Couldn't verify signature: namespace does not match")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 338, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't verify signature: namespace does not match"
)
;
339 debug_f("expected namespace \"%s\" received \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 340, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "expected namespace \"%s\" received \"%s\""
, expect_namespace, got_namespace)
340 expect_namespace, got_namespace)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 340, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "expected namespace \"%s\" received \"%s\""
, expect_namespace, got_namespace)
;
341 r = SSH_ERR_SIGNATURE_INVALID-21;
342 goto done;
343 }
344 if (strcmp(hashalg, sig_hashalg) != 0) {
345 error("Couldn't verify signature: hash algorithm mismatch")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 345, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't verify signature: hash algorithm mismatch"
)
;
346 debug_f("expected algorithm \"%s\" received \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 347, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "expected algorithm \"%s\" received \"%s\""
, hashalg, sig_hashalg)
347 hashalg, sig_hashalg)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 347, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "expected algorithm \"%s\" received \"%s\""
, hashalg, sig_hashalg)
;
348 r = SSH_ERR_SIGNATURE_INVALID-21;
349 goto done;
350 }
351 /* Ensure that RSA keys use an acceptable signature algorithm */
352 if (sshkey_type_plain(key->type) == KEY_RSA) {
353 if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) {
354 error_r(r, "Couldn't verify signature: unable to get "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 355, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't verify signature: unable to get "
"signature type")
355 "signature type")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 355, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't verify signature: unable to get "
"signature type")
;
356 goto done;
357 }
358 if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED"rsa-sha2-512,rsa-sha2-256", 0) != 1) {
359 error("Couldn't verify signature: unsupported RSA "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 360, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't verify signature: unsupported RSA "
"signature algorithm %s", sigtype)
360 "signature algorithm %s", sigtype)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 360, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Couldn't verify signature: unsupported RSA "
"signature algorithm %s", sigtype)
;
361 r = SSH_ERR_SIGN_ALG_UNSUPPORTED-58;
362 goto done;
363 }
364 }
365 if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify),
366 sshbuf_len(toverify), NULL((void *)0), 0, sig_details)) != 0) {
367 error_r(r, "Signature verification failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 367, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Signature verification failed"
)
;
368 goto done;
369 }
370
371 /* success */
372 r = 0;
373 if (sign_keyp != NULL((void *)0)) {
374 *sign_keyp = key;
375 key = NULL((void *)0); /* transferred */
376 }
377done:
378 free(got_namespace);
379 free(sigtype);
380 free(sig_hashalg);
381 sshbuf_free(buf);
382 sshbuf_free(toverify);
383 sshkey_free(key);
384 return r;
385}
386
387static int
388hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
389{
390 char *hex, hash[SSH_DIGEST_MAX_LENGTH64];
391 int alg, r = SSH_ERR_INTERNAL_ERROR-1;
392 struct sshbuf *b = NULL((void *)0);
393
394 *bp = NULL((void *)0);
395 memset(hash, 0, sizeof(hash));
396
397 if ((r = sshsig_check_hashalg(hashalg)) != 0)
398 return r;
399 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
400 error_f("can't look up hash algorithm %s", hashalg)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 400, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "can't look up hash algorithm %s"
, hashalg)
;
401 return SSH_ERR_INTERNAL_ERROR-1;
402 }
403 if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) {
404 error_fr(r, "ssh_digest_buffer")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 404, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "ssh_digest_buffer"
)
;
405 return r;
406 }
407 if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL((void *)0)) {
408 debug3_f("final hash: %s", hex)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 408, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "final hash: %s",
hex)
;
409 freezero(hex, strlen(hex));
410 }
411 if ((b = sshbuf_new()) == NULL((void *)0)) {
412 r = SSH_ERR_ALLOC_FAIL-2;
413 goto out;
414 }
415 if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
416 error_fr(r, "sshbuf_put")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 416, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshbuf_put")
;
417 goto out;
418 }
419 *bp = b;
420 b = NULL((void *)0); /* transferred */
421 /* success */
422 r = 0;
423 out:
424 sshbuf_free(b);
425 explicit_bzero(hash, sizeof(hash));
426 return r;
427}
428
429int
430sshsig_signb(struct sshkey *key, const char *hashalg,
431 const char *sk_provider, const char *sk_pin,
432 const struct sshbuf *message, const char *sig_namespace,
433 struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
434{
435 struct sshbuf *b = NULL((void *)0);
436 int r = SSH_ERR_INTERNAL_ERROR-1;
437
438 if (hashalg == NULL((void *)0))
439 hashalg = HASHALG_DEFAULT"sha512";
440 if (out != NULL((void *)0))
441 *out = NULL((void *)0);
442 if ((r = hash_buffer(message, hashalg, &b)) != 0) {
443 error_fr(r, "hash buffer")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 443, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hash buffer")
;
444 goto out;
445 }
446 if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b,
447 sig_namespace, out, signer, signer_ctx)) != 0)
448 goto out;
449 /* success */
450 r = 0;
451 out:
452 sshbuf_free(b);
453 return r;
454}
455
456int
457sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
458 const char *expect_namespace, struct sshkey **sign_keyp,
459 struct sshkey_sig_details **sig_details)
460{
461 struct sshbuf *b = NULL((void *)0);
462 int r = SSH_ERR_INTERNAL_ERROR-1;
463 char *hashalg = NULL((void *)0);
464
465 if (sig_details != NULL((void *)0))
466 *sig_details = NULL((void *)0);
467 if (sign_keyp != NULL((void *)0))
468 *sign_keyp = NULL((void *)0);
469 if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
470 return r;
471 debug_f("signature made with hash \"%s\"", hashalg)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 471, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "signature made with hash \"%s\""
, hashalg)
;
472 if ((r = hash_buffer(message, hashalg, &b)) != 0) {
473 error_fr(r, "hash buffer")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 473, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hash buffer")
;
474 goto out;
475 }
476 if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
477 sign_keyp, sig_details)) != 0)
478 goto out;
479 /* success */
480 r = 0;
481 out:
482 sshbuf_free(b);
483 free(hashalg);
484 return r;
485}
486
487static int
488hash_file(int fd, const char *hashalg, struct sshbuf **bp)
489{
490 char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH64];
491 ssize_t n, total = 0;
492 struct ssh_digest_ctx *ctx;
493 int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR-1;
494 struct sshbuf *b = NULL((void *)0);
495
496 *bp = NULL((void *)0);
497 memset(hash, 0, sizeof(hash));
498
499 if ((r = sshsig_check_hashalg(hashalg)) != 0)
500 return r;
501 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
502 error_f("can't look up hash algorithm %s", hashalg)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 502, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "can't look up hash algorithm %s"
, hashalg)
;
503 return SSH_ERR_INTERNAL_ERROR-1;
504 }
505 if ((ctx = ssh_digest_start(alg)) == NULL((void *)0)) {
506 error_f("ssh_digest_start failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 506, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "ssh_digest_start failed"
)
;
507 return SSH_ERR_INTERNAL_ERROR-1;
508 }
509 for (;;) {
510 if ((n = read(fd, rbuf, sizeof(rbuf))) == -1) {
511 if (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35)
512 continue;
513 oerrno = errno(*__errno());
514 error_f("read: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 514, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "read: %s", strerror
((*__errno())))
;
515 ssh_digest_free(ctx);
516 errno(*__errno()) = oerrno;
517 r = SSH_ERR_SYSTEM_ERROR-24;
518 goto out;
519 } else if (n == 0) {
520 debug2_f("hashed %zu bytes", total)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 520, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "hashed %zu bytes"
, total)
;
521 break; /* EOF */
522 }
523 total += (size_t)n;
524 if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) {
525 error_fr(r, "ssh_digest_update")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 525, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "ssh_digest_update"
)
;
526 goto out;
527 }
528 }
529 if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) {
530 error_fr(r, "ssh_digest_final")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 530, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "ssh_digest_final")
;
531 goto out;
532 }
533 if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL((void *)0)) {
534 debug3_f("final hash: %s", hex)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 534, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "final hash: %s",
hex)
;
535 freezero(hex, strlen(hex));
536 }
537 if ((b = sshbuf_new()) == NULL((void *)0)) {
538 r = SSH_ERR_ALLOC_FAIL-2;
539 goto out;
540 }
541 if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
542 error_fr(r, "sshbuf_put")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 542, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshbuf_put")
;
543 goto out;
544 }
545 *bp = b;
546 b = NULL((void *)0); /* transferred */
547 /* success */
548 r = 0;
549 out:
550 sshbuf_free(b);
551 ssh_digest_free(ctx);
552 explicit_bzero(hash, sizeof(hash));
553 return r;
554}
555
556int
557sshsig_sign_fd(struct sshkey *key, const char *hashalg,
558 const char *sk_provider, const char *sk_pin,
559 int fd, const char *sig_namespace, struct sshbuf **out,
560 sshsig_signer *signer, void *signer_ctx)
561{
562 struct sshbuf *b = NULL((void *)0);
563 int r = SSH_ERR_INTERNAL_ERROR-1;
564
565 if (hashalg == NULL((void *)0))
566 hashalg = HASHALG_DEFAULT"sha512";
567 if (out != NULL((void *)0))
568 *out = NULL((void *)0);
569 if ((r = hash_file(fd, hashalg, &b)) != 0) {
570 error_fr(r, "hash_file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 570, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hash_file")
;
571 return r;
572 }
573 if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b,
574 sig_namespace, out, signer, signer_ctx)) != 0)
575 goto out;
576 /* success */
577 r = 0;
578 out:
579 sshbuf_free(b);
580 return r;
581}
582
583int
584sshsig_verify_fd(struct sshbuf *signature, int fd,
585 const char *expect_namespace, struct sshkey **sign_keyp,
586 struct sshkey_sig_details **sig_details)
587{
588 struct sshbuf *b = NULL((void *)0);
589 int r = SSH_ERR_INTERNAL_ERROR-1;
590 char *hashalg = NULL((void *)0);
591
592 if (sig_details != NULL((void *)0))
593 *sig_details = NULL((void *)0);
594 if (sign_keyp != NULL((void *)0))
595 *sign_keyp = NULL((void *)0);
596 if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
597 return r;
598 debug_f("signature made with hash \"%s\"", hashalg)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 598, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "signature made with hash \"%s\""
, hashalg)
;
599 if ((r = hash_file(fd, hashalg, &b)) != 0) {
600 error_fr(r, "hash_file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 600, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hash_file")
;
601 goto out;
602 }
603 if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
604 sign_keyp, sig_details)) != 0)
605 goto out;
606 /* success */
607 r = 0;
608 out:
609 sshbuf_free(b);
610 free(hashalg);
611 return r;
612}
613
614struct sshsigopt {
615 int ca;
616 char *namespaces;
617 uint64_t valid_after, valid_before;
618};
619
620struct sshsigopt *
621sshsigopt_parse(const char *opts, const char *path, u_long linenum,
622 const char **errstrp)
623{
624 struct sshsigopt *ret;
625 int r;
626 char *opt;
627 const char *errstr = NULL((void *)0);
628
629 if ((ret = calloc(1, sizeof(*ret))) == NULL((void *)0))
630 return NULL((void *)0);
631 if (opts == NULL((void *)0) || *opts == '\0')
632 return ret; /* Empty options yields empty options :) */
633
634 while (*opts && *opts != ' ' && *opts != '\t') {
635 /* flag options */
636 if ((r = opt_flag("cert-authority", 0, &opts)) != -1) {
637 ret->ca = 1;
638 } else if (opt_match(&opts, "namespaces")) {
639 if (ret->namespaces != NULL((void *)0)) {
640 errstr = "multiple \"namespaces\" clauses";
641 goto fail;
642 }
643 ret->namespaces = opt_dequote(&opts, &errstr);
644 if (ret->namespaces == NULL((void *)0))
645 goto fail;
646 } else if (opt_match(&opts, "valid-after")) {
647 if (ret->valid_after != 0) {
648 errstr = "multiple \"valid-after\" clauses";
649 goto fail;
650 }
651 if ((opt = opt_dequote(&opts, &errstr)) == NULL((void *)0))
652 goto fail;
653 if (parse_absolute_time(opt, &ret->valid_after) != 0 ||
654 ret->valid_after == 0) {
655 free(opt);
656 errstr = "invalid \"valid-after\" time";
657 goto fail;
658 }
659 free(opt);
660 } else if (opt_match(&opts, "valid-before")) {
661 if (ret->valid_before != 0) {
662 errstr = "multiple \"valid-before\" clauses";
663 goto fail;
664 }
665 if ((opt = opt_dequote(&opts, &errstr)) == NULL((void *)0))
666 goto fail;
667 if (parse_absolute_time(opt, &ret->valid_before) != 0 ||
668 ret->valid_before == 0) {
669 free(opt);
670 errstr = "invalid \"valid-before\" time";
671 goto fail;
672 }
673 free(opt);
674 }
675 /*
676 * Skip the comma, and move to the next option
677 * (or break out if there are no more).
678 */
679 if (*opts == '\0' || *opts == ' ' || *opts == '\t')
680 break; /* End of options. */
681 /* Anything other than a comma is an unknown option */
682 if (*opts != ',') {
683 errstr = "unknown key option";
684 goto fail;
685 }
686 opts++;
687 if (*opts == '\0') {
688 errstr = "unexpected end-of-options";
689 goto fail;
690 }
691 }
692 /* final consistency check */
693 if (ret->valid_after != 0 && ret->valid_before != 0 &&
694 ret->valid_before <= ret->valid_after) {
695 errstr = "\"valid-before\" time is before \"valid-after\"";
696 goto fail;
697 }
698 /* success */
699 return ret;
700 fail:
701 if (errstrp != NULL((void *)0))
702 *errstrp = errstr;
703 sshsigopt_free(ret);
704 return NULL((void *)0);
705}
706
707void
708sshsigopt_free(struct sshsigopt *opts)
709{
710 if (opts == NULL((void *)0))
711 return;
712 free(opts->namespaces);
713 free(opts);
714}
715
716static int
717parse_principals_key_and_options(const char *path, u_long linenum, char *line,
718 const char *required_principal, char **principalsp, struct sshkey **keyp,
719 struct sshsigopt **sigoptsp)
720{
721 char *opts = NULL((void *)0), *tmp, *cp, *principals = NULL((void *)0);
722 const char *reason = NULL((void *)0);
723 struct sshsigopt *sigopts = NULL((void *)0);
724 struct sshkey *key = NULL((void *)0);
725 int r = SSH_ERR_INTERNAL_ERROR-1;
726
727 if (principalsp != NULL((void *)0))
728 *principalsp = NULL((void *)0);
729 if (sigoptsp != NULL((void *)0))
730 *sigoptsp = NULL((void *)0);
731 if (keyp != NULL((void *)0))
732 *keyp = NULL((void *)0);
733
734 cp = line;
735 cp = cp + strspn(cp, " \t"); /* skip leading whitespace */
736 if (*cp == '#' || *cp == '\0')
737 return SSH_ERR_KEY_NOT_FOUND-46; /* blank or all-comment line */
738
739 /* format: identity[,identity...] [option[,option...]] key */
740 if ((tmp = strdelimw(&cp)) == NULL((void *)0)) {
741 error("%s:%lu: invalid line", path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 741, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: invalid line"
, path, linenum)
;
742 r = SSH_ERR_INVALID_FORMAT-4;
743 goto out;
744 }
745 if ((principals = strdup(tmp)) == NULL((void *)0)) {
746 error_f("strdup failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 746, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "strdup failed")
;
747 r = SSH_ERR_ALLOC_FAIL-2;
748 goto out;
749 }
750 /*
751 * Bail out early if we're looking for a particular principal and this
752 * line does not list it.
753 */
754 if (required_principal != NULL((void *)0)) {
755 if (match_pattern_list(required_principal,
756 principals, 0) != 1) {
757 /* principal didn't match */
758 r = SSH_ERR_KEY_NOT_FOUND-46;
759 goto out;
760 }
761 debug_f("%s:%lu: matched principal \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 762, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched principal \"%s\""
, path, linenum, required_principal)
762 path, linenum, required_principal)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 762, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched principal \"%s\""
, path, linenum, required_principal)
;
763 }
764
765 if ((key = sshkey_new(KEY_UNSPEC)) == NULL((void *)0)) {
766 error_f("sshkey_new failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 766, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "sshkey_new failed"
)
;
767 r = SSH_ERR_ALLOC_FAIL-2;
768 goto out;
769 }
770 if (sshkey_read(key, &cp) != 0) {
771 /* no key? Check for options */
772 opts = cp;
773 if (sshkey_advance_past_options(&cp) != 0) {
774 error("%s:%lu: invalid options", path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 774, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: invalid options"
, path, linenum)
;
775 r = SSH_ERR_INVALID_FORMAT-4;
776 goto out;
777 }
778 *cp++ = '\0';
779 skip_space(&cp);
780 if (sshkey_read(key, &cp) != 0) {
781 error("%s:%lu: invalid key", path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 781, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: invalid key"
, path, linenum)
;
782 r = SSH_ERR_INVALID_FORMAT-4;
783 goto out;
784 }
785 }
786 debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 786, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s:%lu: options %s"
, path, linenum, opts == ((void *)0) ? "" : opts)
;
787 if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL((void *)0)) {
788 error("%s:%lu: bad options: %s", path, linenum, reason)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 788, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: bad options: %s"
, path, linenum, reason)
;
789 r = SSH_ERR_INVALID_FORMAT-4;
790 goto out;
791 }
792 /* success */
793 if (principalsp != NULL((void *)0)) {
794 *principalsp = principals;
795 principals = NULL((void *)0); /* transferred */
796 }
797 if (sigoptsp != NULL((void *)0)) {
798 *sigoptsp = sigopts;
799 sigopts = NULL((void *)0); /* transferred */
800 }
801 if (keyp != NULL((void *)0)) {
802 *keyp = key;
803 key = NULL((void *)0); /* transferred */
804 }
805 r = 0;
806 out:
807 free(principals);
808 sshsigopt_free(sigopts);
809 sshkey_free(key);
810 return r;
811}
812
813static int
814cert_filter_principals(const char *path, u_long linenum,
815 char **principalsp, const struct sshkey *cert, uint64_t verify_time)
816{
817 char *cp, *oprincipals, *principals;
818 const char *reason;
819 struct sshbuf *nprincipals;
820 int r = SSH_ERR_INTERNAL_ERROR-1, success = 0;
821
822 oprincipals = principals = *principalsp;
823 *principalsp = NULL((void *)0);
824
825 if ((nprincipals = sshbuf_new()) == NULL((void *)0)) {
826 r = SSH_ERR_ALLOC_FAIL-2;
827 goto out;
828 }
829
830 while ((cp = strsep(&principals, ",")) != NULL((void *)0) && *cp != '\0') {
831 if (strcspn(cp, "!?*") != strlen(cp)) {
832 debug("%s:%lu: principal \"%s\" not authorized: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 833, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: principal \"%s\" not authorized: "
"contains wildcards", path, linenum, cp)
833 "contains wildcards", path, linenum, cp)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 833, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: principal \"%s\" not authorized: "
"contains wildcards", path, linenum, cp)
;
834 continue;
835 }
836 /* Check against principals list in certificate */
837 if ((r = sshkey_cert_check_authority(cert, 0, 1, 0,
838 verify_time, cp, &reason)) != 0) {
839 debug("%s:%lu: principal \"%s\" not authorized: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 840, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: principal \"%s\" not authorized: %s"
, path, linenum, cp, reason)
840 path, linenum, cp, reason)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 840, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: principal \"%s\" not authorized: %s"
, path, linenum, cp, reason)
;
841 continue;
842 }
843 if ((r = sshbuf_putf(nprincipals, "%s%s",
844 sshbuf_len(nprincipals) != 0 ? "," : "", cp)) != 0) {
845 error_f("buffer error")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 845, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "buffer error")
;
846 goto out;
847 }
848 }
849 if (sshbuf_len(nprincipals) == 0) {
850 error("%s:%lu: no valid principals found", path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 850, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: no valid principals found"
, path, linenum)
;
851 r = SSH_ERR_KEY_CERT_INVALID-25;
852 goto out;
853 }
854 if ((principals = sshbuf_dup_string(nprincipals)) == NULL((void *)0)) {
855 error_f("buffer error")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 855, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "buffer error")
;
856 goto out;
857 }
858 /* success */
859 success = 1;
860 *principalsp = principals;
861 out:
862 sshbuf_free(nprincipals);
863 free(oprincipals);
864 return success ? 0 : r;
865}
866
867static int
868check_allowed_keys_line(const char *path, u_long linenum, char *line,
869 const struct sshkey *sign_key, const char *principal,
870 const char *sig_namespace, uint64_t verify_time, char **principalsp)
871{
872 struct sshkey *found_key = NULL((void *)0);
873 char *principals = NULL((void *)0);
874 int r, success = 0;
875 const char *reason = NULL((void *)0);
876 struct sshsigopt *sigopts = NULL((void *)0);
877 char tvalid[64], tverify[64];
878
879 if (principalsp != NULL((void *)0))
880 *principalsp = NULL((void *)0);
881
882 /* Parse the line */
883 if ((r = parse_principals_key_and_options(path, linenum, line,
884 principal, &principals, &found_key, &sigopts)) != 0) {
885 /* error already logged */
886 goto done;
887 }
888
889 if (!sigopts->ca && sshkey_equal(found_key, sign_key)) {
890 /* Exact match of key */
891 debug("%s:%lu: matched key", path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 891, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched key"
, path, linenum)
;
892 } else if (sigopts->ca && sshkey_is_cert(sign_key) &&
893 sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
894 if (principal) {
895 /* Match certificate CA key with specified principal */
896 if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0,
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
897 verify_time, principal, &reason)) != 0) {
898 error("%s:%lu: certificate not authorized: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 899, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: certificate not authorized: %s"
, path, linenum, reason)
899 path, linenum, reason)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 899, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: certificate not authorized: %s"
, path, linenum, reason)
;
900 goto done;
901 }
902 debug("%s:%lu: matched certificate CA key",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 903, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched certificate CA key"
, path, linenum)
903 path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 903, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched certificate CA key"
, path, linenum)
;
904 } else {
905 /* No principal specified - find all matching ones */
906 if ((r = cert_filter_principals(path, linenum,
907 &principals, sign_key, verify_time)) != 0) {
908 /* error already displayed */
909 debug_r(r, "%s:%lu: cert_filter_principals",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 910, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "%s:%lu: cert_filter_principals"
, path, linenum)
910 path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 910, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "%s:%lu: cert_filter_principals"
, path, linenum)
;
911 goto done;
912 }
913 debug("%s:%lu: matched certificate CA key",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 914, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched certificate CA key"
, path, linenum)
914 path, linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 914, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%lu: matched certificate CA key"
, path, linenum)
;
915 }
916 } else {
917 /* Didn't match key */
918 goto done;
919 }
920
921 /* Check whether options preclude the use of this key */
922 if (sigopts->namespaces != NULL((void *)0) && sig_namespace != NULL((void *)0) &&
923 match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) {
924 error("%s:%lu: key is not permitted for use in signature "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 925, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key is not permitted for use in signature "
"namespace \"%s\"", path, linenum, sig_namespace)
925 "namespace \"%s\"", path, linenum, sig_namespace)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 925, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key is not permitted for use in signature "
"namespace \"%s\"", path, linenum, sig_namespace)
;
926 goto done;
927 }
928
929 /* check key time validity */
930 format_absolute_time((uint64_t)verify_time, tverify, sizeof(tverify));
931 if (sigopts->valid_after != 0 &&
932 (uint64_t)verify_time < sigopts->valid_after) {
933 format_absolute_time(sigopts->valid_after,
934 tvalid, sizeof(tvalid));
935 error("%s:%lu: key is not yet valid: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 937, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key is not yet valid: "
"verify time %s < valid-after %s", path, linenum, tverify
, tvalid)
936 "verify time %s < valid-after %s", path, linenum,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 937, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key is not yet valid: "
"verify time %s < valid-after %s", path, linenum, tverify
, tvalid)
937 tverify, tvalid)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 937, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key is not yet valid: "
"verify time %s < valid-after %s", path, linenum, tverify
, tvalid)
;
938 goto done;
939 }
940 if (sigopts->valid_before != 0 &&
941 (uint64_t)verify_time > sigopts->valid_before) {
942 format_absolute_time(sigopts->valid_before,
943 tvalid, sizeof(tvalid));
944 error("%s:%lu: key has expired: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 946, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key has expired: "
"verify time %s > valid-before %s", path, linenum, tverify
, tvalid)
945 "verify time %s > valid-before %s", path, linenum,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 946, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key has expired: "
"verify time %s > valid-before %s", path, linenum, tverify
, tvalid)
946 tverify, tvalid)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 946, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s:%lu: key has expired: "
"verify time %s > valid-before %s", path, linenum, tverify
, tvalid)
;
947 goto done;
948 }
949 success = 1;
950
951 done:
952 if (success && principalsp != NULL((void *)0)) {
953 *principalsp = principals;
954 principals = NULL((void *)0); /* transferred */
955 }
956 free(principals);
957 sshkey_free(found_key);
958 sshsigopt_free(sigopts);
959 return success ? 0 : SSH_ERR_KEY_NOT_FOUND-46;
960}
961
962int
963sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
964 const char *principal, const char *sig_namespace, uint64_t verify_time)
965{
966 FILE *f = NULL((void *)0);
967 char *line = NULL((void *)0);
968 size_t linesize = 0;
969 u_long linenum = 0;
970 int r = SSH_ERR_INTERNAL_ERROR-1, oerrno;
971
972 /* Check key and principal against file */
973 if ((f = fopen(path, "r")) == NULL((void *)0)) {
974 oerrno = errno(*__errno());
975 error("Unable to open allowed keys file \"%s\": %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 976, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to open allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
976 path, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 976, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to open allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
;
977 errno(*__errno()) = oerrno;
978 return SSH_ERR_SYSTEM_ERROR-24;
979 }
980
981 while (getline(&line, &linesize, f) != -1) {
982 linenum++;
983 r = check_allowed_keys_line(path, linenum, line, sign_key,
984 principal, sig_namespace, verify_time, NULL((void *)0));
985 free(line);
986 line = NULL((void *)0);
987 linesize = 0;
988 if (r == SSH_ERR_KEY_NOT_FOUND-46)
989 continue;
990 else if (r == 0) {
991 /* success */
992 fclose(f);
993 return 0;
994 } else
995 break;
996 }
997 /* Either we hit an error parsing or we simply didn't find the key */
998 fclose(f);
999 free(line);
1000 return r == 0 ? SSH_ERR_KEY_NOT_FOUND-46 : r;
1001}
1002
1003int
1004sshsig_find_principals(const char *path, const struct sshkey *sign_key,
1005 uint64_t verify_time, char **principals)
1006{
1007 FILE *f = NULL((void *)0);
1008 char *line = NULL((void *)0);
1009 size_t linesize = 0;
1010 u_long linenum = 0;
1011 int r = SSH_ERR_INTERNAL_ERROR-1, oerrno;
1012
1013 if ((f = fopen(path, "r")) == NULL((void *)0)) {
1014 oerrno = errno(*__errno());
1015 error("Unable to open allowed keys file \"%s\": %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 1016, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to open allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
1016 path, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 1016, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to open allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
;
1017 errno(*__errno()) = oerrno;
1018 return SSH_ERR_SYSTEM_ERROR-24;
1019 }
1020
1021 r = SSH_ERR_KEY_NOT_FOUND-46;
1022 while (getline(&line, &linesize, f) != -1) {
1023 linenum++;
1024 r = check_allowed_keys_line(path, linenum, line,
1025 sign_key, NULL((void *)0), NULL((void *)0), verify_time, principals);
1026 free(line);
1027 line = NULL((void *)0);
1028 linesize = 0;
1029 if (r == SSH_ERR_KEY_NOT_FOUND-46)
1030 continue;
1031 else if (r == 0) {
1032 /* success */
1033 fclose(f);
1034 return 0;
1035 } else
1036 break;
1037 }
1038 free(line);
1039 /* Either we hit an error parsing or we simply didn't find the key */
1040 if (ferror(f)(!__isthreaded ? (((f)->_flags & 0x0040) != 0) : (ferror
)(f))
!= 0) {
1041 oerrno = errno(*__errno());
1042 fclose(f);
1043 error("Unable to read allowed keys file \"%s\": %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 1044, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to read allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
1044 path, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 1044, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to read allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
;
1045 errno(*__errno()) = oerrno;
1046 return SSH_ERR_SYSTEM_ERROR-24;
1047 }
1048 fclose(f);
1049 return r == 0 ? SSH_ERR_KEY_NOT_FOUND-46 : r;
1050}
1051
1052int
1053sshsig_match_principals(const char *path, const char *principal,
1054 char ***principalsp, size_t *nprincipalsp)
1055{
1056 FILE *f = NULL((void *)0);
1057 char *found, *line = NULL((void *)0), **principals = NULL((void *)0), **tmp;
1058 size_t i, nprincipals = 0, linesize = 0;
1059 u_long linenum = 0;
1060 int oerrno = 0, r, ret = 0;
1061
1062 if (principalsp != NULL((void *)0))
1063 *principalsp = NULL((void *)0);
1064 if (nprincipalsp != NULL((void *)0))
1065 *nprincipalsp = 0;
1066
1067 /* Check key and principal against file */
1068 if ((f = fopen(path, "r")) == NULL((void *)0)) {
1069 oerrno = errno(*__errno());
1070 error("Unable to open allowed keys file \"%s\": %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 1071, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to open allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
1071 path, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../sshsig.c", __func__
, 1071, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to open allowed keys file \"%s\": %s"
, path, strerror((*__errno())))
;
1072 errno(*__errno()) = oerrno;
1073 return SSH_ERR_SYSTEM_ERROR-24;
1074 }
1075
1076 while (getline(&line, &linesize, f) != -1) {
1077 linenum++;
1078 /* Parse the line */
1079 if ((r = parse_principals_key_and_options(path, linenum, line,
1080 principal, &found, NULL((void *)0), NULL((void *)0))) != 0) {
1081 if (r == SSH_ERR_KEY_NOT_FOUND-46)
1082 continue;
1083 ret = r;
1084 oerrno = errno(*__errno());
1085 break; /* unexpected error */
1086 }
1087 if ((tmp = recallocarray(principals, nprincipals,
1088 nprincipals + 1, sizeof(*principals))) == NULL((void *)0)) {
1089 ret = SSH_ERR_ALLOC_FAIL-2;
1090 free(found);
1091 break;
1092 }
1093 principals = tmp;
1094 principals[nprincipals++] = found; /* transferred */
1095 free(line);
1096 line = NULL((void *)0);
1097 linesize = 0;
1098 }
1099 fclose(f);
1100
1101 if (ret == 0) {
1102 if (nprincipals == 0)
1103 ret = SSH_ERR_KEY_NOT_FOUND-46;
1104 if (principalsp != NULL((void *)0)) {
1105 *principalsp = principals;
1106 principals = NULL((void *)0); /* transferred */
1107 }
1108 if (nprincipalsp != 0) {
1109 *nprincipalsp = nprincipals;
1110 nprincipals = 0;
1111 }
1112 }
1113
1114 for (i = 0; i < nprincipals; i++)
1115 free(principals[i]);
1116 free(principals);
1117
1118 errno(*__errno()) = oerrno;
1119 return ret;
1120}
1121
1122int
1123sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey)
1124{
1125 struct sshkey *pk = NULL((void *)0);
1126 int r = SSH_ERR_SIGNATURE_INVALID-21;
1127
1128 if (pubkey == NULL((void *)0))
1129 return SSH_ERR_INTERNAL_ERROR-1;
1130 if ((r = sshsig_parse_preamble(signature)) != 0)
1131 return r;
1132 if ((r = sshkey_froms(signature, &pk)) != 0)
1133 return r;
1134
1135 *pubkey = pk;
1136 pk = NULL((void *)0);
1137 return 0;
1138}