mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-02 01:17:52 +03:00
pki_crypto: pad RSA signature blobs
Pad RSA signature blobs to the expected RSA signature length when processing via 'pki_signature_to_blob'. Some clients, notably PuTTY, may send unpadded RSA signatures during the public key exchange: before this change, one can sometimes observe failure in signature validation when using PuTTY's 'plink' client, along these lines: ssh_packet_process: ssh_packet_process: Dispatching handler for packet type 50 ssh_packet_userauth_request: ssh_packet_userauth_request: Auth request for service ssh-connection, method publickey for user 'foo' ssh_pki_signature_verify_blob: ssh_pki_signature_verify_blob: Going to verify a ssh-rsa type signature pki_signature_verify: pki_signature_verify: RSA error: error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length ssh_packet_userauth_request: ssh_packet_userauth_request: Received an invalid signature from peer For cross-reference this issue once also existed between PuTTY and OpenSSH: http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/rsa-verify-failed.html http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh-rsa.c?rev=1.19;content-type=text%2Fx-cvsweb-markup With the fix I am unable to reproduce the above failure mode when testing with 'plink'. Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Andreas Schneider
parent
9fff70fa41
commit
465816f4a0
@@ -1188,6 +1188,61 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
|||||||
return sig_blob;
|
return sig_blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey,
|
||||||
|
const ssh_string sig_blob,
|
||||||
|
ssh_signature sig)
|
||||||
|
{
|
||||||
|
uint32_t pad_len = 0;
|
||||||
|
char *blob_orig;
|
||||||
|
char *blob_padded_data;
|
||||||
|
ssh_string sig_blob_padded;
|
||||||
|
|
||||||
|
size_t len = ssh_string_len(sig_blob);
|
||||||
|
size_t rsalen= RSA_size(pubkey->rsa);
|
||||||
|
|
||||||
|
if (len > rsalen) {
|
||||||
|
ssh_pki_log("Signature is too big: %lu > %lu",
|
||||||
|
(unsigned long)len, (unsigned long)rsalen);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CRYPTO
|
||||||
|
ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
|
||||||
|
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (len == rsalen) {
|
||||||
|
sig->rsa_sig = ssh_string_copy(sig_blob);
|
||||||
|
} else {
|
||||||
|
/* pad the blob to the expected rsalen size */
|
||||||
|
ssh_pki_log("RSA signature len %lu < %lu",
|
||||||
|
(unsigned long)len, (unsigned long)rsalen);
|
||||||
|
|
||||||
|
pad_len = rsalen - len;
|
||||||
|
|
||||||
|
sig_blob_padded = ssh_string_new(rsalen);
|
||||||
|
if (sig_blob_padded == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_padded_data = (char *) ssh_string_data(sig_blob_padded);
|
||||||
|
blob_orig = (char *) ssh_string_data(sig_blob);
|
||||||
|
|
||||||
|
/* front-pad the buffer with zeroes */
|
||||||
|
BURN_BUFFER(blob_padded_data, pad_len);
|
||||||
|
/* fill the rest with the actual signature blob */
|
||||||
|
memcpy(blob_padded_data + pad_len, blob_orig, len);
|
||||||
|
|
||||||
|
sig->rsa_sig = sig_blob_padded;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
ssh_signature_free(sig);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||||
const ssh_string sig_blob,
|
const ssh_string sig_blob,
|
||||||
enum ssh_keytypes_e type)
|
enum ssh_keytypes_e type)
|
||||||
@@ -1196,7 +1251,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
|||||||
ssh_string r;
|
ssh_string r;
|
||||||
ssh_string s;
|
ssh_string s;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t rsalen;
|
|
||||||
|
|
||||||
sig = ssh_signature_new();
|
sig = ssh_signature_new();
|
||||||
if (sig == NULL) {
|
if (sig == NULL) {
|
||||||
@@ -1260,29 +1314,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
|||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_RSA:
|
case SSH_KEYTYPE_RSA:
|
||||||
case SSH_KEYTYPE_RSA1:
|
case SSH_KEYTYPE_RSA1:
|
||||||
rsalen = RSA_size(pubkey->rsa);
|
sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig);
|
||||||
|
|
||||||
if (len > rsalen) {
|
|
||||||
ssh_pki_log("Signature is to big size: %lu",
|
|
||||||
(unsigned long)len);
|
|
||||||
ssh_signature_free(sig);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len < rsalen) {
|
|
||||||
ssh_pki_log("RSA signature len %lu < %lu",
|
|
||||||
(unsigned long)len, (unsigned long)rsalen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
|
||||||
ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
|
|
||||||
ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
|
|
||||||
#endif
|
|
||||||
sig->rsa_sig = ssh_string_copy(sig_blob);
|
|
||||||
if (sig->rsa_sig == NULL) {
|
|
||||||
ssh_signature_free(sig);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SSH_KEYTYPE_ECDSA:
|
case SSH_KEYTYPE_ECDSA:
|
||||||
#ifdef HAVE_OPENSSL_ECC
|
#ifdef HAVE_OPENSSL_ECC
|
||||||
|
|||||||
Reference in New Issue
Block a user