pki: RSA signatures with SHA2 hash algorithms (RFC 8332)

* This change introduces a new API to request signature using
   one key and different hash algorithms. This is used only with
   RSA keys, that used to have SHA1 hardcoded, but the new
   algorithsms allow to use the SHA2 hashes, if the extension
   is negotiated.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2018-08-07 15:04:45 +02:00
committed by Andreas Schneider
parent 3ca7e1eea9
commit 1f08aabe43
5 changed files with 209 additions and 31 deletions

View File

@@ -1181,23 +1181,43 @@ fail:
*
* @param[in] privkey The private rsa key to use for signing.
*
* @param[in] hash_type The hash algorithm to use.
*
* @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)
static ssh_string _RSA_do_sign_hash(const unsigned char *digest,
int dlen,
RSA *privkey,
enum ssh_digest_e hash_type)
{
ssh_string sig_blob;
unsigned char *sig;
unsigned int slen;
int ok;
int nid = 0;
switch (hash_type) {
case SSH_DIGEST_SHA1:
case SSH_DIGEST_AUTO:
nid = NID_sha1;
break;
case SSH_DIGEST_SHA256:
nid = NID_sha256;
break;
case SSH_DIGEST_SHA512:
nid = NID_sha512;
break;
default:
SSH_LOG(SSH_LOG_WARN, "Incomplatible hash type");
return NULL;
}
sig = malloc(RSA_size(privkey));
if (sig == NULL) {
return NULL;
}
ok = RSA_sign(NID_sha1, digest, dlen, sig, &slen, privkey);
ok = RSA_sign(nid, digest, dlen, sig, &slen, privkey);
if (!ok) {
SAFE_FREE(sig);
return NULL;
@@ -1216,6 +1236,26 @@ static ssh_string _RSA_do_sign(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 };
@@ -1686,18 +1726,27 @@ int pki_signature_verify(ssh_session session,
return SSH_OK;
}
ssh_signature pki_do_sign(const ssh_key privkey,
const unsigned char *hash,
size_t hlen) {
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 sig;
int rc;
/* Only RSA supports different signature algorithm types now */
if (privkey->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 = privkey->type;
sig->hash_type = hash_type;
sig->type_c = privkey->type_c;
switch(privkey->type) {
@@ -1720,7 +1769,8 @@ ssh_signature pki_do_sign(const ssh_key privkey,
break;
case SSH_KEYTYPE_RSA:
case SSH_KEYTYPE_RSA1:
sig->rsa_sig = _RSA_do_sign(hash, hlen, privkey->rsa);
sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type);
sig->rsa_sig = _RSA_do_sign_hash(hash, hlen, privkey->rsa, hash_type);
if (sig->rsa_sig == NULL) {
ssh_signature_free(sig);
return NULL;