mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-26 07:15:36 +02:00
upstream: sshsig tweaks and improvements from and suggested by
Markus ok markus/me OpenBSD-Commit-ID: ea4f46ad5a16b27af96e08c4877423918c4253e9
This commit is contained in:
parent
2a9c9f7272
commit
d637c4aee6
@ -8,9 +8,9 @@ At present, only detached and armored signatures are supported.
|
|||||||
The Armored SSH signatures consist of a header, a base64
|
The Armored SSH signatures consist of a header, a base64
|
||||||
encoded blob, and a footer.
|
encoded blob, and a footer.
|
||||||
|
|
||||||
The header is the string “-----BEGIN SSH SIGNATURE-----”
|
The header is the string "-----BEGIN SSH SIGNATURE-----"
|
||||||
followed by a newline. The footer is the string
|
followed by a newline. The footer is the string
|
||||||
“-----END SSH SIGNATURE-----” immediately after a newline.
|
"-----END SSH SIGNATURE-----" immediately after a newline.
|
||||||
|
|
||||||
The header MUST be present at the start of every signature.
|
The header MUST be present at the start of every signature.
|
||||||
Files containing the signature MUST start with the header.
|
Files containing the signature MUST start with the header.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: ssh-keygen.1,v 1.163 2019/09/03 08:34:19 djm Exp $
|
.\" $OpenBSD: ssh-keygen.1,v 1.164 2019/09/03 08:35:27 djm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -986,7 +986,7 @@ Indicates that this key is accepted as a certificate authority (CA) and
|
|||||||
that certificates signed by this CA may be accepted for verification.
|
that certificates signed by this CA may be accepted for verification.
|
||||||
.It Cm namespaces="namespace-list"
|
.It Cm namespaces="namespace-list"
|
||||||
Specifies a pattern-list of namespaces that are accepted for this key.
|
Specifies a pattern-list of namespaces that are accepted for this key.
|
||||||
If this option is present, the the signature namespace embedded in the
|
If this option is present, the signature namespace embedded in the
|
||||||
signature object and presented on the verification command-line must
|
signature object and presented on the verification command-line must
|
||||||
match the specified list before the key will be considered acceptable.
|
match the specified list before the key will be considered acceptable.
|
||||||
.El
|
.El
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-keygen.c,v 1.344 2019/09/03 08:34:19 djm Exp $ */
|
/* $OpenBSD: ssh-keygen.c,v 1.345 2019/09/03 08:35:27 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
180
sshsig.c
180
sshsig.c
@ -230,7 +230,7 @@ sshsig_parse_preamble(struct sshbuf *buf)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sversion < SIG_VERSION) {
|
if (sversion > SIG_VERSION) {
|
||||||
error("Signature version %lu is larger than supported "
|
error("Signature version %lu is larger than supported "
|
||||||
"version %u", (unsigned long)sversion, SIG_VERSION);
|
"version %u", (unsigned long)sversion, SIG_VERSION);
|
||||||
return SSH_ERR_INVALID_FORMAT;
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
@ -241,7 +241,8 @@ sshsig_parse_preamble(struct sshbuf *buf)
|
|||||||
static int
|
static int
|
||||||
sshsig_check_hashalg(const char *hashalg)
|
sshsig_check_hashalg(const char *hashalg)
|
||||||
{
|
{
|
||||||
if (match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1)
|
if (hashalg == NULL ||
|
||||||
|
match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1)
|
||||||
return 0;
|
return 0;
|
||||||
error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg);
|
error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg);
|
||||||
return SSH_ERR_SIGN_ALG_UNSUPPORTED;
|
return SSH_ERR_SIGN_ALG_UNSUPPORTED;
|
||||||
@ -268,8 +269,6 @@ sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp)
|
|||||||
error("Couldn't parse signature blob: %s", ssh_err(r));
|
error("Couldn't parse signature blob: %s", ssh_err(r));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((r = sshsig_check_hashalg(hashalg)) != 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
r = 0;
|
r = 0;
|
||||||
@ -293,6 +292,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
|
|||||||
char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL;
|
char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL;
|
||||||
size_t siglen;
|
size_t siglen;
|
||||||
|
|
||||||
|
debug("%s: verify message length %zu", __func__, sshbuf_len(h_message));
|
||||||
if (sign_keyp != NULL)
|
if (sign_keyp != NULL)
|
||||||
*sign_keyp = NULL;
|
*sign_keyp = NULL;
|
||||||
|
|
||||||
@ -301,9 +301,6 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
|
|||||||
r = SSH_ERR_ALLOC_FAIL;
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((r = sshsig_check_hashalg(hashalg)) != 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE,
|
if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE,
|
||||||
MAGIC_PREAMBLE_LEN)) != 0 ||
|
MAGIC_PREAMBLE_LEN)) != 0 ||
|
||||||
(r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 ||
|
(r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 ||
|
||||||
@ -382,36 +379,65 @@ done:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
sshsig_sign_message(struct sshkey *key, const char *hashalg,
|
hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
|
||||||
const struct sshbuf *message, const char *sig_namespace,
|
|
||||||
struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
|
|
||||||
{
|
{
|
||||||
u_char hash[SSH_DIGEST_MAX_LENGTH];
|
char *hex, hash[SSH_DIGEST_MAX_LENGTH];
|
||||||
struct sshbuf *b = NULL;
|
|
||||||
int alg, r = SSH_ERR_INTERNAL_ERROR;
|
int alg, r = SSH_ERR_INTERNAL_ERROR;
|
||||||
|
struct sshbuf *b = NULL;
|
||||||
|
|
||||||
if (out != NULL)
|
*bp = NULL;
|
||||||
*out = NULL;
|
memset(hash, 0, sizeof(hash));
|
||||||
if (hashalg == NULL)
|
|
||||||
hashalg = HASHALG_DEFAULT;
|
|
||||||
|
|
||||||
if ((r = sshsig_check_hashalg(hashalg)) != 0)
|
if ((r = sshsig_check_hashalg(hashalg)) != 0)
|
||||||
return r;
|
return r;
|
||||||
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
|
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
|
||||||
error("%s: can't look up hash algorithm %s",
|
error("%s: can't look up hash algorithm %s",
|
||||||
__func__, HASHALG_DEFAULT);
|
__func__, hashalg);
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
return SSH_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
if ((r = ssh_digest_buffer(alg, message, hash, sizeof(hash))) != 0) {
|
if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) {
|
||||||
error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r));
|
error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
|
if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
|
||||||
error("%s: sshbuf_from failed", __func__);
|
debug3("%s: final hash: %s", __func__, hex);
|
||||||
|
freezero(hex, strlen(hex));
|
||||||
|
}
|
||||||
|
if ((b = sshbuf_new()) == NULL) {
|
||||||
r = SSH_ERR_ALLOC_FAIL;
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
|
||||||
|
error("%s: sshbuf_put: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
*bp = b;
|
||||||
|
b = NULL; /* transferred */
|
||||||
|
/* success */
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
sshbuf_free(b);
|
||||||
|
explicit_bzero(hash, sizeof(hash));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sshsig_signb(struct sshkey *key, const char *hashalg,
|
||||||
|
const struct sshbuf *message, const char *sig_namespace,
|
||||||
|
struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
|
||||||
|
{
|
||||||
|
struct sshbuf *b = NULL;
|
||||||
|
int r = SSH_ERR_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
if (hashalg == NULL)
|
||||||
|
hashalg = HASHALG_DEFAULT;
|
||||||
|
if (out != NULL)
|
||||||
|
*out = NULL;
|
||||||
|
if ((r = hash_buffer(message, hashalg, &b)) != 0) {
|
||||||
|
error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out,
|
if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out,
|
||||||
signer, signer_ctx)) != 0)
|
signer, signer_ctx)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
@ -419,17 +445,15 @@ sshsig_sign_message(struct sshkey *key, const char *hashalg,
|
|||||||
r = 0;
|
r = 0;
|
||||||
out:
|
out:
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
explicit_bzero(hash, sizeof(hash));
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sshsig_verify_message(struct sshbuf *signature, const struct sshbuf *message,
|
sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
|
||||||
const char *expect_namespace, struct sshkey **sign_keyp)
|
const char *expect_namespace, struct sshkey **sign_keyp)
|
||||||
{
|
{
|
||||||
u_char hash[SSH_DIGEST_MAX_LENGTH];
|
|
||||||
struct sshbuf *b = NULL;
|
struct sshbuf *b = NULL;
|
||||||
int alg, r = SSH_ERR_INTERNAL_ERROR;
|
int r = SSH_ERR_INTERNAL_ERROR;
|
||||||
char *hashalg = NULL;
|
char *hashalg = NULL;
|
||||||
|
|
||||||
if (sign_keyp != NULL)
|
if (sign_keyp != NULL)
|
||||||
@ -437,18 +461,9 @@ sshsig_verify_message(struct sshbuf *signature, const struct sshbuf *message,
|
|||||||
|
|
||||||
if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
|
if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
|
||||||
return r;
|
return r;
|
||||||
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
|
debug("%s: signature made with hash \"%s\"", __func__, hashalg);
|
||||||
error("%s: can't look up hash algorithm %s",
|
if ((r = hash_buffer(message, hashalg, &b)) != 0) {
|
||||||
__func__, HASHALG_DEFAULT);
|
error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
if ((r = ssh_digest_buffer(alg, message, hash, sizeof(hash))) != 0) {
|
|
||||||
error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
|
|
||||||
error("%s: sshbuf_from failed", __func__);
|
|
||||||
r = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
|
if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
|
||||||
@ -459,20 +474,29 @@ sshsig_verify_message(struct sshbuf *signature, const struct sshbuf *message,
|
|||||||
out:
|
out:
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
free(hashalg);
|
free(hashalg);
|
||||||
explicit_bzero(hash, sizeof(hash));
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hash_file(int fd, int hashalg, u_char *hash, size_t hashlen)
|
hash_file(int fd, const char *hashalg, struct sshbuf **bp)
|
||||||
{
|
{
|
||||||
char *hex, rbuf[8192];
|
char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH];
|
||||||
ssize_t n, total = 0;
|
ssize_t n, total = 0;
|
||||||
struct ssh_digest_ctx *ctx;
|
struct ssh_digest_ctx *ctx;
|
||||||
int r, oerrno;
|
int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR;
|
||||||
|
struct sshbuf *b = NULL;
|
||||||
|
|
||||||
memset(hash, 0, hashlen);
|
*bp = NULL;
|
||||||
if ((ctx = ssh_digest_start(hashalg)) == NULL) {
|
memset(hash, 0, sizeof(hash));
|
||||||
|
|
||||||
|
if ((r = sshsig_check_hashalg(hashalg)) != 0)
|
||||||
|
return r;
|
||||||
|
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
|
||||||
|
error("%s: can't look up hash algorithm %s",
|
||||||
|
__func__, hashalg);
|
||||||
|
return SSH_ERR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
if ((ctx = ssh_digest_start(alg)) == NULL) {
|
||||||
error("%s: ssh_digest_start failed", __func__);
|
error("%s: ssh_digest_start failed", __func__);
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
return SSH_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
@ -484,7 +508,8 @@ hash_file(int fd, int hashalg, u_char *hash, size_t hashlen)
|
|||||||
error("%s: read: %s", __func__, strerror(errno));
|
error("%s: read: %s", __func__, strerror(errno));
|
||||||
ssh_digest_free(ctx);
|
ssh_digest_free(ctx);
|
||||||
errno = oerrno;
|
errno = oerrno;
|
||||||
return SSH_ERR_SYSTEM_ERROR;
|
r = SSH_ERR_SYSTEM_ERROR;
|
||||||
|
goto out;
|
||||||
} else if (n == 0) {
|
} else if (n == 0) {
|
||||||
debug2("%s: hashed %zu bytes", __func__, total);
|
debug2("%s: hashed %zu bytes", __func__, total);
|
||||||
break; /* EOF */
|
break; /* EOF */
|
||||||
@ -493,20 +518,33 @@ hash_file(int fd, int hashalg, u_char *hash, size_t hashlen)
|
|||||||
if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) {
|
if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) {
|
||||||
error("%s: ssh_digest_update: %s",
|
error("%s: ssh_digest_update: %s",
|
||||||
__func__, ssh_err(r));
|
__func__, ssh_err(r));
|
||||||
ssh_digest_free(ctx);
|
goto out;
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((r = ssh_digest_final(ctx, hash, hashlen)) != 0) {
|
if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) {
|
||||||
error("%s: ssh_digest_final: %s", __func__, ssh_err(r));
|
error("%s: ssh_digest_final: %s", __func__, ssh_err(r));
|
||||||
ssh_digest_free(ctx);
|
goto out;
|
||||||
}
|
}
|
||||||
if ((hex = tohex(hash, hashlen)) != NULL) {
|
if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
|
||||||
debug3("%s: final hash: %s", __func__, hex);
|
debug3("%s: final hash: %s", __func__, hex);
|
||||||
freezero(hex, strlen(hex));
|
freezero(hex, strlen(hex));
|
||||||
}
|
}
|
||||||
|
if ((b = sshbuf_new()) == NULL) {
|
||||||
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
|
||||||
|
error("%s: sshbuf_put: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
*bp = b;
|
||||||
|
b = NULL; /* transferred */
|
||||||
/* success */
|
/* success */
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
sshbuf_free(b);
|
||||||
ssh_digest_free(ctx);
|
ssh_digest_free(ctx);
|
||||||
|
explicit_bzero(hash, sizeof(hash));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,31 +553,17 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg,
|
|||||||
int fd, const char *sig_namespace, struct sshbuf **out,
|
int fd, const char *sig_namespace, struct sshbuf **out,
|
||||||
sshsig_signer *signer, void *signer_ctx)
|
sshsig_signer *signer, void *signer_ctx)
|
||||||
{
|
{
|
||||||
u_char hash[SSH_DIGEST_MAX_LENGTH];
|
|
||||||
struct sshbuf *b = NULL;
|
struct sshbuf *b = NULL;
|
||||||
int alg, r = SSH_ERR_INTERNAL_ERROR;
|
int r = SSH_ERR_INTERNAL_ERROR;
|
||||||
|
|
||||||
if (out != NULL)
|
|
||||||
*out = NULL;
|
|
||||||
if (hashalg == NULL)
|
if (hashalg == NULL)
|
||||||
hashalg = HASHALG_DEFAULT;
|
hashalg = HASHALG_DEFAULT;
|
||||||
|
if (out != NULL)
|
||||||
if ((r = sshsig_check_hashalg(hashalg)) != 0)
|
*out = NULL;
|
||||||
return r;
|
if ((r = hash_file(fd, hashalg, &b)) != 0) {
|
||||||
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
|
|
||||||
error("%s: can't look up hash algorithm %s",
|
|
||||||
__func__, HASHALG_DEFAULT);
|
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
if ((r = hash_file(fd, alg, hash, sizeof(hash))) != 0) {
|
|
||||||
error("%s: hash_file failed: %s", __func__, ssh_err(r));
|
error("%s: hash_file failed: %s", __func__, ssh_err(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
|
|
||||||
error("%s: sshbuf_from failed", __func__);
|
|
||||||
r = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out,
|
if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out,
|
||||||
signer, signer_ctx)) != 0)
|
signer, signer_ctx)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
@ -547,7 +571,6 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg,
|
|||||||
r = 0;
|
r = 0;
|
||||||
out:
|
out:
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
explicit_bzero(hash, sizeof(hash));
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,9 +578,8 @@ int
|
|||||||
sshsig_verify_fd(struct sshbuf *signature, int fd,
|
sshsig_verify_fd(struct sshbuf *signature, int fd,
|
||||||
const char *expect_namespace, struct sshkey **sign_keyp)
|
const char *expect_namespace, struct sshkey **sign_keyp)
|
||||||
{
|
{
|
||||||
u_char hash[SSH_DIGEST_MAX_LENGTH];
|
|
||||||
struct sshbuf *b = NULL;
|
struct sshbuf *b = NULL;
|
||||||
int alg, r = SSH_ERR_INTERNAL_ERROR;
|
int r = SSH_ERR_INTERNAL_ERROR;
|
||||||
char *hashalg = NULL;
|
char *hashalg = NULL;
|
||||||
|
|
||||||
if (sign_keyp != NULL)
|
if (sign_keyp != NULL)
|
||||||
@ -565,18 +587,9 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
|
|||||||
|
|
||||||
if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
|
if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
|
||||||
return r;
|
return r;
|
||||||
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
|
debug("%s: signature made with hash \"%s\"", __func__, hashalg);
|
||||||
error("%s: can't look up hash algorithm %s",
|
if ((r = hash_file(fd, hashalg, &b)) != 0) {
|
||||||
__func__, HASHALG_DEFAULT);
|
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
if ((r = hash_file(fd, alg, hash, sizeof(hash))) != 0) {
|
|
||||||
error("%s: hash_file failed: %s", __func__, ssh_err(r));
|
error("%s: hash_file failed: %s", __func__, ssh_err(r));
|
||||||
return r;
|
|
||||||
}
|
|
||||||
if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
|
|
||||||
error("%s: sshbuf_from failed", __func__);
|
|
||||||
r = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
|
if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
|
||||||
@ -587,7 +600,6 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
|
|||||||
out:
|
out:
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
free(hashalg);
|
free(hashalg);
|
||||||
explicit_bzero(hash, sizeof(hash));
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,14 +781,14 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
|
|||||||
linenum++;
|
linenum++;
|
||||||
r = check_allowed_keys_line(path, linenum, line, sign_key,
|
r = check_allowed_keys_line(path, linenum, line, sign_key,
|
||||||
principal, sig_namespace);
|
principal, sig_namespace);
|
||||||
|
free(line);
|
||||||
|
line = NULL;
|
||||||
if (r == SSH_ERR_KEY_NOT_FOUND)
|
if (r == SSH_ERR_KEY_NOT_FOUND)
|
||||||
continue;
|
continue;
|
||||||
else if (r == 0) {
|
else if (r == 0) {
|
||||||
/* success */
|
/* success */
|
||||||
fclose(f);
|
fclose(f);
|
||||||
free(line);
|
|
||||||
return 0;
|
return 0;
|
||||||
/* XXX continue and check revocation? */
|
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
28
sshsig.h
28
sshsig.h
@ -23,15 +23,28 @@ struct sshkey;
|
|||||||
typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
|
typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
|
||||||
const u_char *, size_t, const char *, u_int, void *);
|
const u_char *, size_t, const char *, u_int, void *);
|
||||||
|
|
||||||
|
/* Buffer-oriented API */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a detached SSH signature for a given message.
|
* Creates a detached SSH signature for a given buffer.
|
||||||
* Returns 0 on success or a negative SSH_ERR_* error code on failure.
|
* Returns 0 on success or a negative SSH_ERR_* error code on failure.
|
||||||
* out is populated with the detached signature, or NULL on failure.
|
* out is populated with the detached signature, or NULL on failure.
|
||||||
*/
|
*/
|
||||||
int sshsig_sign_message(struct sshkey *key, const char *hashalg,
|
int sshsig_signb(struct sshkey *key, const char *hashalg,
|
||||||
const struct sshbuf *message, const char *sig_namespace,
|
const struct sshbuf *message, const char *sig_namespace,
|
||||||
struct sshbuf **out, sshsig_signer *signer, void *signer_ctx);
|
struct sshbuf **out, sshsig_signer *signer, void *signer_ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verifies that a detached signature is valid and optionally returns key
|
||||||
|
* used to sign via argument.
|
||||||
|
* Returns 0 on success or a negative SSH_ERR_* error code on failure.
|
||||||
|
*/
|
||||||
|
int sshsig_verifyb(struct sshbuf *signature,
|
||||||
|
const struct sshbuf *message, const char *sig_namespace,
|
||||||
|
struct sshkey **sign_keyp);
|
||||||
|
|
||||||
|
/* File/FD-oriented API */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a detached SSH signature for a given file.
|
* Creates a detached SSH signature for a given file.
|
||||||
* Returns 0 on success or a negative SSH_ERR_* error code on failure.
|
* Returns 0 on success or a negative SSH_ERR_* error code on failure.
|
||||||
@ -41,15 +54,6 @@ int sshsig_sign_fd(struct sshkey *key, const char *hashalg,
|
|||||||
int fd, const char *sig_namespace, struct sshbuf **out,
|
int fd, const char *sig_namespace, struct sshbuf **out,
|
||||||
sshsig_signer *signer, void *signer_ctx);
|
sshsig_signer *signer, void *signer_ctx);
|
||||||
|
|
||||||
/*
|
|
||||||
* Verifies that a detached signature is valid and optionally returns key
|
|
||||||
* used to sign via argument.
|
|
||||||
* Returns 0 on success or a negative SSH_ERR_* error code on failure.
|
|
||||||
*/
|
|
||||||
int sshsig_verify_message(struct sshbuf *signature,
|
|
||||||
const struct sshbuf *message, const char *sig_namespace,
|
|
||||||
struct sshkey **sign_keyp);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verifies that a detached signature over a file is valid and optionally
|
* Verifies that a detached signature over a file is valid and optionally
|
||||||
* returns key used to sign via argument.
|
* returns key used to sign via argument.
|
||||||
@ -58,6 +62,8 @@ int sshsig_verify_message(struct sshbuf *signature,
|
|||||||
int sshsig_verify_fd(struct sshbuf *signature, int fd,
|
int sshsig_verify_fd(struct sshbuf *signature, int fd,
|
||||||
const char *sig_namespace, struct sshkey **sign_keyp);
|
const char *sig_namespace, struct sshkey **sign_keyp);
|
||||||
|
|
||||||
|
/* Utility functions */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a base64 encoded "ASCII armoured" version of a raw signature.
|
* Return a base64 encoded "ASCII armoured" version of a raw signature.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user