pki: Support RSA SHA2 signatures of sessionid for server
This involves mostly creation of host keys proofs but needs to follow the same procedure as the client authentication signatures. At the same time, the SHA2 extension is enabled in the pkd so we are able to atomicaly provide correct signatures and pass tests. Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Этот коммит содержится в:
родитель
5d13006650
Коммит
b4c8bd9fe4
@ -99,6 +99,7 @@ void ssh_key_clean (ssh_key key);
|
||||
const char *
|
||||
ssh_key_get_signature_algorithm(ssh_session session,
|
||||
enum ssh_keytypes_e type);
|
||||
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name);
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_signature ssh_signature_new(void);
|
||||
|
@ -104,9 +104,12 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen);
|
||||
#define pki_do_sign_sessionid(key, hash, hlen) \
|
||||
pki_do_sign_sessionid_hash(key, hash, hlen, SSH_DIGEST_AUTO)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig,
|
||||
const unsigned char *hash, size_t hlen);
|
||||
int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig,
|
||||
|
33
src/pki.c
33
src/pki.c
@ -357,7 +357,7 @@ ssh_key_get_signature_algorithm(ssh_session session,
|
||||
*
|
||||
* @return The enum ssh key algorithm type.
|
||||
*/
|
||||
static enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) {
|
||||
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) {
|
||||
if (name == NULL) {
|
||||
return SSH_KEYTYPE_UNKNOWN;
|
||||
}
|
||||
@ -2033,21 +2033,36 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
sig = NULL;
|
||||
}
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
SHACTX ctx;
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->type: %d", sig->type);
|
||||
return NULL;
|
||||
}
|
||||
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
sha1_final(hash, ctx);
|
||||
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
ssh_print_hexa("Hash being signed", hash, hlen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
|
||||
sig = pki_do_sign_sessionid_hash(privkey, hash, hlen, hash_type);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1236,26 +1236,6 @@ static ssh_string _RSA_do_sign_hash(const unsigned char *digest,
|
||||
return sig_blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Compute a digital signature.
|
||||
*
|
||||
* @param[in] digest The message digest.
|
||||
*
|
||||
* @param[in] dlen The length of the digest.
|
||||
*
|
||||
* @param[in] privkey The private rsa key to use for signing.
|
||||
*
|
||||
* @return A newly allocated rsa sig blob or NULL on error.
|
||||
*/
|
||||
static ssh_string _RSA_do_sign(const unsigned char *digest,
|
||||
int dlen,
|
||||
RSA *privkey)
|
||||
{
|
||||
return _RSA_do_sign_hash(digest, dlen, privkey, SSH_DIGEST_AUTO);
|
||||
}
|
||||
|
||||
static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
|
||||
{
|
||||
char buffer[40] = { 0 };
|
||||
@ -1813,16 +1793,24 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
@ -1836,7 +1824,8 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
sig->rsa_sig = _RSA_do_sign(hash, hlen, key->rsa);
|
||||
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
|
||||
sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, key->rsa, hash_type);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
|
@ -2199,19 +2199,28 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
unsigned char ghash[hlen + 1];
|
||||
const char *hash_c = NULL;
|
||||
ssh_signature sig;
|
||||
gcry_sexp_t sexp;
|
||||
gcry_error_t err;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
@ -2238,9 +2247,25 @@ ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA1:
|
||||
hash_c = "sha1";
|
||||
break;
|
||||
case SSH_DIGEST_SHA256:
|
||||
hash_c = "sha256";
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
hash_c = "sha512";
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Incomplatible key algorithm");
|
||||
return NULL;
|
||||
}
|
||||
err = gcry_sexp_build(&sexp,
|
||||
NULL,
|
||||
"(data(flags pkcs1)(hash sha1 %b))",
|
||||
"(data(flags pkcs1)(hash %s %b))",
|
||||
hash_c,
|
||||
hlen,
|
||||
hash);
|
||||
if (err) {
|
||||
|
@ -1127,22 +1127,32 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key, const unsigned char
|
||||
*hash, size_t hlen)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
ssh_signature sig = NULL;
|
||||
int rc;
|
||||
|
||||
/* Only RSA supports different signature algorithm types now */
|
||||
if (key->type != SSH_KEYTYPE_RSA && hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Incompatible signature algorithm passed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig = ssh_signature_new();
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sig->type = key->type;
|
||||
sig->type_c = key->type_c;
|
||||
|
||||
switch (key->type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
sig->rsa_sig = rsa_do_sign_hash(hash, hlen, key->rsa, SSH_DIGEST_AUTO);
|
||||
sig->type_c = ssh_key_signature_to_char(key->type, hash_type);
|
||||
sig->rsa_sig = rsa_do_sign_hash(hash, hlen, key->rsa, hash_type);
|
||||
if (sig->rsa_sig == NULL) {
|
||||
ssh_signature_free(sig);
|
||||
return NULL;
|
||||
|
@ -509,7 +509,7 @@ int crypt_set_algorithms_server(ssh_session session){
|
||||
}
|
||||
|
||||
method = session->next_crypto->kex_methods[SSH_HOSTKEYS];
|
||||
session->srv.hostkey = ssh_key_type_from_name(method);
|
||||
session->srv.hostkey = ssh_key_type_from_signature_name(method);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
#define OPENSSH_BINARY "ssh"
|
||||
#define OPENSSH_KEYGEN "ssh-keygen"
|
||||
|
||||
#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,ssh-rsa"
|
||||
#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,ssh-rsa"
|
||||
#define OPENSSH_HOSTKEY_ALGOS_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"
|
||||
#define OPENSSH_PKACCEPTED_DEFAULT "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"
|
||||
|
||||
#if HAVE_ECC
|
||||
#define OPENSSH_HOSTKEY_ALGOS_ECDSA ",ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user