Bug Summary

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