diff --git a/include/libssh/pki.h b/include/libssh/pki.h index ce7d5007..29041920 100644 --- a/include/libssh/pki.h +++ b/include/libssh/pki.h @@ -83,6 +83,8 @@ ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf, ssh_string ssh_pki_do_sign_agent(ssh_session session, struct ssh_buffer_struct *buf, const ssh_key pubkey); +ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session, + const ssh_key privkey); /* Temporary functions, to be removed after migration to ssh_key */ ssh_public_key ssh_pki_convert_key_to_publickey(ssh_key key); diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h index f89bfdf4..e86a96c4 100644 --- a/include/libssh/pki_priv.h +++ b/include/libssh/pki_priv.h @@ -59,4 +59,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, /* SSH Signing Functions */ struct signature_struct *pki_do_sign(const ssh_key privatekey, const unsigned char *hash); +ssh_signature pki_do_sign_sessionid(const ssh_key key, + const unsigned char *hash); #endif /* PKI_PRIV_H_ */ diff --git a/src/pki.c b/src/pki.c index 675d221f..f209fe47 100644 --- a/src/pki.c +++ b/src/pki.c @@ -1081,6 +1081,49 @@ ssh_string ssh_pki_do_sign_agent(ssh_session session, } #endif /* _WIN32 */ +#ifdef WITH_SERVER +ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session, + const ssh_key privkey) +{ + struct ssh_crypto_struct *crypto = + session->current_crypto ? session->current_crypto : + session->next_crypto; + unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; + ssh_signature sig; + ssh_string sig_blob; + SHACTX ctx; + int rc; + + if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) { + return NULL; + } + + ctx = sha1_init(); + if (ctx == NULL) { + return NULL; + } + sha1_update(ctx, crypto->session_id, SHA_DIGEST_LEN); + sha1_final(hash + 1, ctx); + hash[0] = 0; + +#ifdef DEBUG_CRYPTO + ssh_print_hexa("Hash being signed", hash + 1, SHA_DIGEST_LEN); +#endif + + sig = pki_do_sign_sessionid(privkey, hash); + if (sig == NULL) { + return NULL; + } + + rc = ssh_pki_export_signature_blob(sig, &sig_blob); + ssh_signature_free(sig); + if (rc < 0) { + return NULL; + } + + return sig_blob; +} +#endif /* WITH_SERVER */ /** * @} diff --git a/src/pki_crypto.c b/src/pki_crypto.c index 3e53a3cc..18ac876b 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -716,4 +716,41 @@ struct signature_struct *pki_do_sign(ssh_key privatekey, return sign; } +#ifdef WITH_SERVER +ssh_signature pki_do_sign_sessionid(const ssh_key key, + const unsigned char *hash) +{ + ssh_signature sig; + + sig = ssh_signature_new(); + if (sig == NULL) { + return NULL; + } + sig->type = key->type; + + switch(key->type) { + case SSH_KEYTYPE_DSS: + sig->dsa_sig = DSA_do_sign(hash + 1, SHA_DIGEST_LEN, key->dsa); + if (sig->dsa_sig == NULL) { + ssh_signature_free(sig); + return NULL; + } + break; + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: + sig->rsa_sig = _RSA_do_sign(hash + 1, SHA_DIGEST_LEN, key->rsa); + if (sig->rsa_sig == NULL) { + ssh_signature_free(sig); + return NULL; + } + break; + case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_UNKNOWN: + return NULL; + } + + return sig; +} +#endif /* WITH_SERVER */ + #endif /* _PKI_CRYPTO_H */ diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c index 1bcfae2c..9e554677 100644 --- a/src/pki_gcrypt.c +++ b/src/pki_gcrypt.c @@ -1355,6 +1355,64 @@ struct signature_struct *pki_do_sign(ssh_key privatekey, return sign; } +#ifdef WITH_SERVER +ssh_signature pki_do_sign_sessionid(const ssh_key key, + const unsigned char *hash) +{ + ssh_signature sig; + gcry_sexp_t sexp; + gcry_error_t err; + + sig = ssh_signature_new(); + if (sig == NULL) { + return NULL; + } + sig->type = key->type; + + switch(key->type) { + case SSH_KEYTYPE_DSS: + err = gcry_sexp_build(&sexp, + NULL, + "%b", + SHA_DIGEST_LEN + 1, + hash); + if (err) { + ssh_signature_free(sig); + return NULL; + } + err = gcry_pk_sign(&sig->dsa_sig, sexp, key->dsa); + gcry_sexp_release(sexp); + if (err) { + ssh_signature_free(sig); + return NULL; + } + break; + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: + err = gcry_sexp_build(&sexp, + NULL, + "(data(flags pkcs1)(hash sha1 %b))", + SHA_DIGEST_LEN, + hash + 1); + if (err) { + ssh_signature_free(sig); + return NULL; + } + err = gcry_pk_sign(&sig->rsa_sig, sexp, key->rsa); + gcry_sexp_release(sexp); + if (err) { + ssh_signature_free(sig); + return NULL; + } + break; + case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_UNKNOWN: + return NULL; + } + + return sig; +} +#endif /* WITH_SERVER */ #endif /* HAVE_LIBGCRYPT */ /**