int ssh_rsa_verify(RSA *key, u_char *signature, u_int signaturelen, u_char *data, u_int datalen) { const EVP_MD *evp_md; EVP_MD_CTX md; // char *ktype; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen, modlen; // int rlen, ret, nid; int ret, nid; char *ptr; OpenSSL_add_all_digests(); if (key == NULL) { return -2; } if (BN_num_bits(key->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { return -3; } //debug_print(41, signature, signaturelen); ptr = signature; // step1 len = get_uint32_MSBfirst(ptr); ptr += 4; if (strncmp("ssh-rsa", ptr, len) != 0) { return -4; } ptr += len; // step2 len = get_uint32_MSBfirst(ptr); ptr += 4; sigblob = ptr; ptr += len; #if 0 rlen = get_uint32_MSBfirst(ptr); if (rlen != 0) { return -1; } #endif /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key); if (len > modlen) { return -5; } else if (len < modlen) { u_int diff = modlen - len; sigblob = realloc(sigblob, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } /* sha1 the data */ // nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; nid = NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { //error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); return -6; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); //free(sigblob); //debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
int ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen, modlen; int rlen, ret, nid; if (key == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || key->rsa == NULL) { error("ssh_rsa_verify: no RSA key"); return -1; } if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_string(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { error("ssh_rsa_verify: cannot handle type %s", ktype); buffer_free(&b); xfree(ktype); return -1; } xfree(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); xfree(sigblob); return -1; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { error("ssh_rsa_verify: len %u > modlen %u", len, modlen); xfree(sigblob); return -1; } else if (len < modlen) { u_int diff = modlen - len; debug("ssh_rsa_verify: add padding: modlen %u > len %u", modlen, len); sigblob = xrealloc(sigblob, 1, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); xfree(sigblob); return -1; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); xfree(sigblob); debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
int ssh_rsa_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t datalen) { char *ktype = NULL; int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; size_t len, diff, modlen, dlen; struct sshbuf *b = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; if (key == NULL || key->rsa == NULL || sshkey_type_plain(key->type) != KEY_RSA || BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) { ret = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (sshbuf_get_string(b, &sigblob, &len) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { ret = SSH_ERR_KEY_BITS_MISMATCH; goto out; } else if (len < modlen) { diff = modlen - len; osigblob = sigblob; if ((sigblob = realloc(sigblob, modlen)) == NULL) { sigblob = osigblob; /* put it back for clear/free */ ret = SSH_ERR_ALLOC_FAIL; goto out; } memmove(sigblob + diff, sigblob, len); explicit_bzero(sigblob, diff); len = modlen; } if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } if ((ret = ssh_digest_memory(hash_alg, data, datalen, digest, sizeof(digest))) != 0) goto out; ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, key->rsa); out: if (sigblob != NULL) { explicit_bzero(sigblob, len); free(sigblob); } free(ktype); sshbuf_free(b); explicit_bzero(digest, sizeof(digest)); return ret; }
int ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char *sigblob; u_int len, modlen; #ifdef USE_LEGACY_RSA_VERIFY u_char digest[EVP_MAX_MD_SIZE]; u_int dlen; #endif int rlen, ret, nid; if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { error("ssh_rsa_verify: no RSA key"); return -1; } if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_cstring(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { error("ssh_rsa_verify: cannot handle type %s", ktype); buffer_free(&b); xfree(ktype); return -1; } xfree(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); xfree(sigblob); return -1; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { error("ssh_rsa_verify: len %u > modlen %u", len, modlen); xfree(sigblob); return -1; } else if (len < modlen) { u_int diff = modlen - len; debug("ssh_rsa_verify: add padding: modlen %u > len %u", modlen, len); sigblob = xrealloc(sigblob, 1, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); xfree(sigblob); return -1; } #ifdef USE_LEGACY_RSA_VERIFY EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); #else /*ndef USE_LEGACY_RSA_VERIFY*/ { EVP_PKEY *pkey; ret = -1; pkey = EVP_PKEY_new(); if (pkey == NULL) { error("%s: out of memory", __func__); goto done; } EVP_PKEY_set1_RSA(pkey, key->rsa); ssh_EVP_MD_CTX_init(&md); ret = ssh_EVP_VerifyInit(&md, evp_md); if (ret <= 0) { char ebuf[256]; error("%s: EVP_VerifyInit fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } ret = ssh_EVP_VerifyUpdate(&md, data, datalen); if (ret <= 0) { char ebuf[256]; error("%s: EVP_VerifyUpdate fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } ret = EVP_VerifyFinal(&md, sigblob, len, pkey); if (ret <= 0) { char ebuf[256]; error("%s: EVP_VerifyFinal fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } clean: ssh_EVP_MD_CTX_cleanup(&md); done: if (pkey != NULL) EVP_PKEY_free(pkey); } #endif /*ndef USE_LEGACY_RSA_VERIFY*/ memset(sigblob, 's', len); xfree(sigblob); debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
int ssh_rsa_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t datalen, const char *alg) { const BIGNUM *rsa_n; char *sigtype = NULL; int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; size_t len = 0, diff, modlen, dlen; struct sshbuf *b = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; if (key == NULL || key->rsa == NULL || sshkey_type_plain(key->type) != KEY_RSA || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_KEY_LENGTH; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) { ret = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } /* * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for * legacy reasons, but otherwise the signature type should match. */ if (alg != NULL && strcmp(alg, "*****@*****.**") != 0) { if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) { ret = SSH_ERR_INVALID_ARGUMENT; goto out; } if (hash_alg != want_alg) { ret = SSH_ERR_SIGNATURE_INVALID; goto out; } } if (sshbuf_get_string(b, &sigblob, &len) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { ret = SSH_ERR_KEY_BITS_MISMATCH; goto out; } else if (len < modlen) { diff = modlen - len; osigblob = sigblob; if ((sigblob = realloc(sigblob, modlen)) == NULL) { sigblob = osigblob; /* put it back for clear/free */ ret = SSH_ERR_ALLOC_FAIL; goto out; } memmove(sigblob + diff, sigblob, len); explicit_bzero(sigblob, diff); len = modlen; } if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } if ((ret = ssh_digest_memory(hash_alg, data, datalen, digest, sizeof(digest))) != 0) goto out; ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, key->rsa); out: freezero(sigblob, len); free(sigtype); sshbuf_free(b); explicit_bzero(digest, sizeof(digest)); return ret; }
int ssh_rsa_verify(const struct sshkey *key, const u_char *signature, size_t signaturelen, const u_char *data, size_t datalen, u_int compat) { struct sshbuf *b = NULL; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char digest[EVP_MAX_MD_SIZE], *osigblob, *sigblob = NULL; size_t len, diff, modlen; u_int dlen; int nid, ret = SSH_ERR_INTERNAL_ERROR; if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00) || BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_from(signature, signaturelen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (strcmp("ssh-rsa", ktype) != 0) { ret = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (sshbuf_get_string(b, &sigblob, &len) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { ret = SSH_ERR_KEY_BITS_MISMATCH; goto out; } else if (len < modlen) { diff = modlen - len; osigblob = sigblob; if ((sigblob = realloc(sigblob, modlen)) == NULL) { free(osigblob); ret = SSH_ERR_ALLOC_FAIL; goto out; } memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (compat & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (EVP_DigestInit(&md, evp_md) != 1 || EVP_DigestUpdate(&md, data, datalen) != 1 || EVP_DigestFinal(&md, digest, &dlen) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); out: if (sigblob != NULL) { memset(sigblob, 's', len); free(sigblob); } if (ktype != NULL) free(ktype); if (b != NULL) sshbuf_free(b); bzero(digest, sizeof(digest)); bzero(&md, sizeof(md)); return ret; }