mirror of git://anongit.mindrot.org/openssh.git
upstream: add cert->signature_type field and keep it in sync with
certificate signature wrt loading and certification operations; ok markus@ OpenBSD-Commit-ID: e8b8b9f76b66707a0cd926109c4383db8f664df3
This commit is contained in:
parent
357128ac48
commit
a70fd4ad7b
93
sshkey.c
93
sshkey.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshkey.c,v 1.66 2018/07/03 13:20:25 djm Exp $ */
|
/* $OpenBSD: sshkey.c,v 1.67 2018/09/12 01:31:30 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||||
|
@ -78,6 +78,7 @@ int sshkey_private_serialize_opt(const struct sshkey *key,
|
||||||
struct sshbuf *buf, enum sshkey_serialize_rep);
|
struct sshbuf *buf, enum sshkey_serialize_rep);
|
||||||
static int sshkey_from_blob_internal(struct sshbuf *buf,
|
static int sshkey_from_blob_internal(struct sshbuf *buf,
|
||||||
struct sshkey **keyp, int allow_cert);
|
struct sshkey **keyp, int allow_cert);
|
||||||
|
static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
|
||||||
|
|
||||||
/* Supported key types */
|
/* Supported key types */
|
||||||
struct keytype {
|
struct keytype {
|
||||||
|
@ -453,6 +454,7 @@ cert_free(struct sshkey_cert *cert)
|
||||||
free(cert->principals[i]);
|
free(cert->principals[i]);
|
||||||
free(cert->principals);
|
free(cert->principals);
|
||||||
sshkey_free(cert->signature_key);
|
sshkey_free(cert->signature_key);
|
||||||
|
free(cert->signature_type);
|
||||||
freezero(cert, sizeof(*cert));
|
freezero(cert, sizeof(*cert));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,6 +474,7 @@ cert_new(void)
|
||||||
cert->key_id = NULL;
|
cert->key_id = NULL;
|
||||||
cert->principals = NULL;
|
cert->principals = NULL;
|
||||||
cert->signature_key = NULL;
|
cert->signature_key = NULL;
|
||||||
|
cert->signature_type = NULL;
|
||||||
return cert;
|
return cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1695,54 +1698,68 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
|
||||||
u_int i;
|
u_int i;
|
||||||
const struct sshkey_cert *from;
|
const struct sshkey_cert *from;
|
||||||
struct sshkey_cert *to;
|
struct sshkey_cert *to;
|
||||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
int r = SSH_ERR_INTERNAL_ERROR;
|
||||||
|
|
||||||
if (to_key->cert != NULL) {
|
if (to_key == NULL || (from = from_key->cert) == NULL)
|
||||||
cert_free(to_key->cert);
|
|
||||||
to_key->cert = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((from = from_key->cert) == NULL)
|
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
if ((to = to_key->cert = cert_new()) == NULL)
|
if ((to = cert_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
|
||||||
if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
|
if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
|
||||||
(ret = sshbuf_putb(to->critical, from->critical)) != 0 ||
|
(r = sshbuf_putb(to->critical, from->critical)) != 0 ||
|
||||||
(ret = sshbuf_putb(to->extensions, from->extensions)) != 0)
|
(r = sshbuf_putb(to->extensions, from->extensions)) != 0)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
to->serial = from->serial;
|
to->serial = from->serial;
|
||||||
to->type = from->type;
|
to->type = from->type;
|
||||||
if (from->key_id == NULL)
|
if (from->key_id == NULL)
|
||||||
to->key_id = NULL;
|
to->key_id = NULL;
|
||||||
else if ((to->key_id = strdup(from->key_id)) == NULL)
|
else if ((to->key_id = strdup(from->key_id)) == NULL) {
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
to->valid_after = from->valid_after;
|
to->valid_after = from->valid_after;
|
||||||
to->valid_before = from->valid_before;
|
to->valid_before = from->valid_before;
|
||||||
if (from->signature_key == NULL)
|
if (from->signature_key == NULL)
|
||||||
to->signature_key = NULL;
|
to->signature_key = NULL;
|
||||||
else if ((ret = sshkey_from_private(from->signature_key,
|
else if ((r = sshkey_from_private(from->signature_key,
|
||||||
&to->signature_key)) != 0)
|
&to->signature_key)) != 0)
|
||||||
return ret;
|
goto out;
|
||||||
|
if (from->signature_type != NULL &&
|
||||||
if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS)
|
(to->signature_type = strdup(from->signature_type)) == NULL) {
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
|
||||||
|
r = SSH_ERR_INVALID_ARGUMENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (from->nprincipals > 0) {
|
if (from->nprincipals > 0) {
|
||||||
if ((to->principals = calloc(from->nprincipals,
|
if ((to->principals = calloc(from->nprincipals,
|
||||||
sizeof(*to->principals))) == NULL)
|
sizeof(*to->principals))) == NULL) {
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
for (i = 0; i < from->nprincipals; i++) {
|
for (i = 0; i < from->nprincipals; i++) {
|
||||||
to->principals[i] = strdup(from->principals[i]);
|
to->principals[i] = strdup(from->principals[i]);
|
||||||
if (to->principals[i] == NULL) {
|
if (to->principals[i] == NULL) {
|
||||||
to->nprincipals = i;
|
to->nprincipals = i;
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
to->nprincipals = from->nprincipals;
|
to->nprincipals = from->nprincipals;
|
||||||
return 0;
|
|
||||||
|
/* success */
|
||||||
|
cert_free(to_key->cert);
|
||||||
|
to_key->cert = to;
|
||||||
|
to = NULL;
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
cert_free(to);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1954,6 +1971,8 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
|
||||||
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
|
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
|
||||||
sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
|
sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -2531,7 +2550,8 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
|
||||||
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
|
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
|
||||||
size_t i, ca_len, sig_len;
|
size_t i, ca_len, sig_len;
|
||||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||||
struct sshbuf *cert;
|
struct sshbuf *cert = NULL;
|
||||||
|
char *sigtype = NULL;
|
||||||
|
|
||||||
if (k == NULL || k->cert == NULL ||
|
if (k == NULL || k->cert == NULL ||
|
||||||
k->cert->certblob == NULL || ca == NULL)
|
k->cert->certblob == NULL || ca == NULL)
|
||||||
|
@ -2541,6 +2561,16 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
|
||||||
if (!sshkey_type_is_valid_ca(ca->type))
|
if (!sshkey_type_is_valid_ca(ca->type))
|
||||||
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
|
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no alg specified as argument but a signature_type was set,
|
||||||
|
* then prefer that. If both were specified, then they must match.
|
||||||
|
*/
|
||||||
|
if (alg == NULL)
|
||||||
|
alg = k->cert->signature_type;
|
||||||
|
else if (k->cert->signature_type != NULL &&
|
||||||
|
strcmp(alg, k->cert->signature_type) != 0)
|
||||||
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
|
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
|
||||||
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
|
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
|
||||||
|
|
||||||
|
@ -2629,7 +2659,17 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
|
||||||
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
|
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
|
||||||
sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
|
sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
/* Check and update signature_type against what was actually used */
|
||||||
|
if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
|
||||||
|
goto out;
|
||||||
|
if (alg != NULL && strcmp(alg, sigtype) != 0) {
|
||||||
|
ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (k->cert->signature_type == NULL) {
|
||||||
|
k->cert->signature_type = sigtype;
|
||||||
|
sigtype = NULL;
|
||||||
|
}
|
||||||
/* Append signature and we are done */
|
/* Append signature and we are done */
|
||||||
if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
|
if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2639,6 +2679,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
|
||||||
sshbuf_reset(cert);
|
sshbuf_reset(cert);
|
||||||
free(sig_blob);
|
free(sig_blob);
|
||||||
free(ca_blob);
|
free(ca_blob);
|
||||||
|
free(sigtype);
|
||||||
sshbuf_free(principals);
|
sshbuf_free(principals);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
3
sshkey.h
3
sshkey.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshkey.h,v 1.26 2018/07/03 13:20:25 djm Exp $ */
|
/* $OpenBSD: sshkey.h,v 1.27 2018/09/12 01:31:30 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
|
@ -102,6 +102,7 @@ struct sshkey_cert {
|
||||||
struct sshbuf *critical;
|
struct sshbuf *critical;
|
||||||
struct sshbuf *extensions;
|
struct sshbuf *extensions;
|
||||||
struct sshkey *signature_key;
|
struct sshkey *signature_key;
|
||||||
|
char *signature_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX opaquify? */
|
/* XXX opaquify? */
|
||||||
|
|
Loading…
Reference in New Issue