1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00
putty-source/windows/utils/cryptoapi.c

90 lines
2.5 KiB
C

/*
* windows/utils/cryptoapi.c: implementation of cryptoapi.h.
*/
#include "putty.h"
#include "putty.h"
#include "ssh.h"
#include "cryptoapi.h"
DEF_WINDOWS_FUNCTION(CryptProtectMemory);
bool got_crypt(void)
{
static bool attempted = false;
static bool successful;
static HMODULE crypt;
if (!attempted) {
attempted = true;
crypt = load_system32_dll("crypt32.dll");
successful = crypt &&
GET_WINDOWS_FUNCTION(crypt, CryptProtectMemory);
}
return successful;
}
char *capi_obfuscate_string(const char *realname)
{
char *cryptdata;
int cryptlen;
unsigned char digest[32];
char retbuf[65];
int i;
cryptlen = strlen(realname) + 1;
cryptlen += CRYPTPROTECTMEMORY_BLOCK_SIZE - 1;
cryptlen /= CRYPTPROTECTMEMORY_BLOCK_SIZE;
cryptlen *= CRYPTPROTECTMEMORY_BLOCK_SIZE;
cryptdata = snewn(cryptlen, char);
memset(cryptdata, 0, cryptlen);
strcpy(cryptdata, realname);
/*
* CRYPTPROTECTMEMORY_CROSS_PROCESS causes CryptProtectMemory to
* use the same key in all processes with this user id, meaning
* that the next PuTTY process calling this function with the same
* input will get the same data.
*
* (Contrast with CryptProtectData, which invents a new session
* key every time since its API permits returning more data than
* was input, so calling _that_ and hashing the output would not
* be stable.)
*
* We don't worry too much if this doesn't work for some reason.
* Omitting this step still has _some_ privacy value (in that
* another user can test-hash things to confirm guesses as to
* where you might be connecting to, but cannot invert SHA-256 in
* the absence of any plausible guess). So we don't abort if we
* can't call CryptProtectMemory at all, or if it fails.
*/
if (got_crypt())
p_CryptProtectMemory(cryptdata, cryptlen,
CRYPTPROTECTMEMORY_CROSS_PROCESS);
/*
* We don't want to give away the length of the hostname either,
* so having got it back out of CryptProtectMemory we now hash it.
*/
{
ssh_hash *h = ssh_hash_new(&ssh_sha256);
put_string(h, cryptdata, cryptlen);
ssh_hash_final(h, digest);
}
sfree(cryptdata);
/*
* Finally, make printable.
*/
for (i = 0; i < 32; i++) {
sprintf(retbuf + 2*i, "%02x", digest[i]);
/* the last of those will also write the trailing NUL */
}
return dupstr(retbuf);
}