version 1.130, 2022/10/28 00:43:08 |
version 1.131, 2022/10/28 00:43:30 |
|
|
} |
} |
} |
} |
|
|
|
/* Return the cert equivalent to a plain key type */ |
|
static int |
|
sshkey_type_certified(int type) |
|
{ |
|
switch (type) { |
|
case KEY_RSA: |
|
return KEY_RSA_CERT; |
|
case KEY_DSA: |
|
return KEY_DSA_CERT; |
|
case KEY_ECDSA: |
|
return KEY_ECDSA_CERT; |
|
case KEY_ECDSA_SK: |
|
return KEY_ECDSA_SK_CERT; |
|
case KEY_ED25519: |
|
return KEY_ED25519_CERT; |
|
case KEY_ED25519_SK: |
|
return KEY_ED25519_SK_CERT; |
|
case KEY_XMSS: |
|
return KEY_XMSS_CERT; |
|
default: |
|
return -1; |
|
} |
|
} |
|
|
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
/* XXX: these are really begging for a table-driven approach */ |
/* XXX: these are really begging for a table-driven approach */ |
int |
int |
|
|
{ |
{ |
int newtype; |
int newtype; |
|
|
switch (k->type) { |
if ((newtype = sshkey_type_certified(k->type)) == -1) |
#ifdef WITH_OPENSSL |
|
case KEY_RSA: |
|
newtype = KEY_RSA_CERT; |
|
break; |
|
case KEY_DSA: |
|
newtype = KEY_DSA_CERT; |
|
break; |
|
case KEY_ECDSA: |
|
newtype = KEY_ECDSA_CERT; |
|
break; |
|
case KEY_ECDSA_SK: |
|
newtype = KEY_ECDSA_SK_CERT; |
|
break; |
|
#endif /* WITH_OPENSSL */ |
|
case KEY_ED25519_SK: |
|
newtype = KEY_ED25519_SK_CERT; |
|
break; |
|
case KEY_ED25519: |
|
newtype = KEY_ED25519_CERT; |
|
break; |
|
#ifdef WITH_XMSS |
|
case KEY_XMSS: |
|
newtype = KEY_XMSS_CERT; |
|
break; |
|
#endif /* WITH_XMSS */ |
|
default: |
|
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
} |
|
if ((k->cert = cert_new()) == NULL) |
if ((k->cert = cert_new()) == NULL) |
return SSH_ERR_ALLOC_FAIL; |
return SSH_ERR_ALLOC_FAIL; |
k->type = newtype; |
k->type = newtype; |
|
|
const char *sk_provider, const char *sk_pin, |
const char *sk_provider, const char *sk_pin, |
sshkey_certify_signer *signer, void *signer_ctx) |
sshkey_certify_signer *signer, void *signer_ctx) |
{ |
{ |
|
const struct sshkey_impl *impl; |
struct sshbuf *principals = NULL; |
struct sshbuf *principals = NULL; |
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 = NULL; |
struct sshbuf *cert = NULL; |
char *sigtype = NULL; |
char *sigtype = NULL; |
#ifdef WITH_OPENSSL |
|
const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; |
|
#endif /* WITH_OPENSSL */ |
|
|
|
if (k == NULL || k->cert == NULL || |
if (k == NULL || k->cert == NULL || |
k->cert->certblob == NULL || ca == NULL) |
k->cert->certblob == NULL || ca == NULL) |
|
|
return SSH_ERR_KEY_TYPE_UNKNOWN; |
return SSH_ERR_KEY_TYPE_UNKNOWN; |
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 ((impl = sshkey_impl_from_key(k)) == NULL) |
|
return SSH_ERR_INTERNAL_ERROR; |
|
|
/* |
/* |
* If no alg specified as argument but a signature_type was set, |
* If no alg specified as argument but a signature_type was set, |
|
|
if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) |
if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) |
goto out; |
goto out; |
|
|
/* XXX this substantially duplicates to_blob(); refactor */ |
/* Public key next */ |
switch (k->type) { |
if ((ret = impl->funcs->serialize_public(k, cert, |
#ifdef WITH_OPENSSL |
SSHKEY_SERIALIZE_DEFAULT)) != 0) |
case KEY_DSA_CERT: |
|
DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); |
|
DSA_get0_key(k->dsa, &dsa_pub_key, NULL); |
|
if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0) |
|
goto out; |
|
break; |
|
case KEY_ECDSA_CERT: |
|
case KEY_ECDSA_SK_CERT: |
|
if ((ret = sshbuf_put_cstring(cert, |
|
sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || |
|
(ret = sshbuf_put_ec(cert, |
|
EC_KEY_get0_public_key(k->ecdsa), |
|
EC_KEY_get0_group(k->ecdsa))) != 0) |
|
goto out; |
|
if (k->type == KEY_ECDSA_SK_CERT) { |
|
if ((ret = sshbuf_put_cstring(cert, |
|
k->sk_application)) != 0) |
|
goto out; |
|
} |
|
break; |
|
case KEY_RSA_CERT: |
|
RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); |
|
if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, rsa_n)) != 0) |
|
goto out; |
|
break; |
|
#endif /* WITH_OPENSSL */ |
|
case KEY_ED25519_CERT: |
|
case KEY_ED25519_SK_CERT: |
|
if ((ret = sshbuf_put_string(cert, |
|
k->ed25519_pk, ED25519_PK_SZ)) != 0) |
|
goto out; |
|
if (k->type == KEY_ED25519_SK_CERT) { |
|
if ((ret = sshbuf_put_cstring(cert, |
|
k->sk_application)) != 0) |
|
goto out; |
|
} |
|
break; |
|
#ifdef WITH_XMSS |
|
case KEY_XMSS_CERT: |
|
if (k->xmss_name == NULL) { |
|
ret = SSH_ERR_INVALID_ARGUMENT; |
|
goto out; |
|
} |
|
if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) || |
|
(ret = sshbuf_put_string(cert, |
|
k->xmss_pk, sshkey_xmss_pklen(k))) != 0) |
|
goto out; |
|
break; |
|
#endif /* WITH_XMSS */ |
|
default: |
|
ret = SSH_ERR_INVALID_ARGUMENT; |
|
goto out; |
goto out; |
} |
|
|
|
|
/* Then remaining cert fields */ |
if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 || |
if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 || |
(ret = sshbuf_put_u32(cert, k->cert->type)) != 0 || |
(ret = sshbuf_put_u32(cert, k->cert->type)) != 0 || |
(ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0) |
(ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0) |