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