Bug Summary

File:src/usr.bin/ssh/ssh-keygen/../sshsig.c
Warning:line 648, column 8
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)
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) {
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
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}