mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-08 08:58:00 +00:00
Access all hashes and MACs through the standard API.
All the hash-specific state structures, and the functions that directly accessed them, are now local to the source files implementing the hashes themselves. Everywhere we previously used those types or functions, we're now using the standard ssh_hash or ssh2_mac API. The 'simple' functions (hmacmd5_simple, SHA_Simple etc) are now a pair of wrappers in sshauxcrypt.c, each of which takes an algorithm structure and can do the same conceptual thing regardless of what it is.
This commit is contained in:
parent
acdcf2bfaa
commit
0d2d20aad0
21
cproxy.c
21
cproxy.c
@ -18,22 +18,15 @@
|
||||
static void hmacmd5_chap(const unsigned char *challenge, int challen,
|
||||
const char *passwd, unsigned char *response)
|
||||
{
|
||||
struct hmacmd5_context *hmacmd5_ctx;
|
||||
int pwlen;
|
||||
ptrlen key = ptrlen_from_asciz(passwd);
|
||||
unsigned char md5buf[16];
|
||||
|
||||
hmacmd5_ctx = hmacmd5_make_context();
|
||||
|
||||
pwlen = strlen(passwd);
|
||||
if (pwlen>64) {
|
||||
unsigned char md5buf[16];
|
||||
MD5Simple(passwd, pwlen, md5buf);
|
||||
hmacmd5_key(hmacmd5_ctx, md5buf, 16);
|
||||
} else {
|
||||
hmacmd5_key(hmacmd5_ctx, passwd, pwlen);
|
||||
if (key.len > 64) {
|
||||
hash_simple(&ssh_md5, key, md5buf);
|
||||
key = make_ptrlen(md5buf, 16);
|
||||
}
|
||||
|
||||
hmacmd5_do_hmac(hmacmd5_ctx, challenge, challen, response);
|
||||
hmacmd5_free_context(hmacmd5_ctx);
|
||||
mac_simple(&ssh_hmac_md5, key, make_ptrlen(challenge, challen), response);
|
||||
smemclr(md5buf, sizeof(md5buf));
|
||||
}
|
||||
|
||||
void proxy_socks5_offerencryptedauth(BinarySink *bs)
|
||||
|
129
import.c
129
import.c
@ -495,6 +495,36 @@ static bool openssh_pem_encrypted(const Filename *filename)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void openssh_pem_derivekey(
|
||||
ptrlen passphrase, const void *iv, uint8_t *keybuf)
|
||||
{
|
||||
/*
|
||||
* Derive the encryption key for a PEM key file from the
|
||||
* passphrase and iv/salt:
|
||||
*
|
||||
* - let block A equal MD5(passphrase || iv)
|
||||
* - let block B equal MD5(A || passphrase || iv)
|
||||
* - block C would be MD5(B || passphrase || iv) and so on
|
||||
* - encryption key is the first N bytes of A || B
|
||||
*
|
||||
* (Note that only 8 bytes of the iv are used for key
|
||||
* derivation, even when the key is encrypted with AES and
|
||||
* hence there are 16 bytes available.)
|
||||
*/
|
||||
ssh_hash *h;
|
||||
|
||||
h = ssh_hash_new(&ssh_md5);
|
||||
put_datapl(h, passphrase);
|
||||
put_data(h, iv, 8);
|
||||
ssh_hash_final(h, keybuf);
|
||||
|
||||
h = ssh_hash_new(&ssh_md5);
|
||||
put_data(h, keybuf, 16);
|
||||
put_datapl(h, passphrase);
|
||||
put_data(h, iv, 8);
|
||||
ssh_hash_final(h, keybuf + 16);
|
||||
}
|
||||
|
||||
static ssh2_userkey *openssh_pem_read(
|
||||
const Filename *filename, const char *passphrase, const char **errmsg_p)
|
||||
{
|
||||
@ -514,34 +544,11 @@ static ssh2_userkey *openssh_pem_read(
|
||||
return NULL;
|
||||
|
||||
if (key->encrypted) {
|
||||
/*
|
||||
* Derive encryption key from passphrase and iv/salt:
|
||||
*
|
||||
* - let block A equal MD5(passphrase || iv)
|
||||
* - let block B equal MD5(A || passphrase || iv)
|
||||
* - block C would be MD5(B || passphrase || iv) and so on
|
||||
* - encryption key is the first N bytes of A || B
|
||||
*
|
||||
* (Note that only 8 bytes of the iv are used for key
|
||||
* derivation, even when the key is encrypted with AES and
|
||||
* hence there are 16 bytes available.)
|
||||
*/
|
||||
struct MD5Context md5c;
|
||||
unsigned char keybuf[32];
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
put_data(&md5c, key->iv, 8);
|
||||
MD5Final(keybuf, &md5c);
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, keybuf, 16);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
put_data(&md5c, key->iv, 8);
|
||||
MD5Final(keybuf+16, &md5c);
|
||||
openssh_pem_derivekey(ptrlen_from_asciz(passphrase), key->iv, keybuf);
|
||||
|
||||
/*
|
||||
* Now decrypt the key blob.
|
||||
* Decrypt the key blob.
|
||||
*/
|
||||
if (key->encryption == OP_E_3DES)
|
||||
des3_decrypt_pubkey_ossh(keybuf, key->iv,
|
||||
@ -554,7 +561,6 @@ static ssh2_userkey *openssh_pem_read(
|
||||
ssh_cipher_free(cipher);
|
||||
}
|
||||
|
||||
smemclr(&md5c, sizeof(md5c));
|
||||
smemclr(keybuf, sizeof(keybuf));
|
||||
}
|
||||
|
||||
@ -981,7 +987,6 @@ static bool openssh_pem_write(
|
||||
* old-style 3DES.
|
||||
*/
|
||||
if (passphrase) {
|
||||
struct MD5Context md5c;
|
||||
unsigned char keybuf[32];
|
||||
int origlen, outlen, pad, i;
|
||||
|
||||
@ -1008,26 +1013,11 @@ static bool openssh_pem_write(
|
||||
put_padding(outblob, pad, pad);
|
||||
|
||||
/*
|
||||
* Invent an iv. Then derive encryption key from passphrase
|
||||
* and iv/salt:
|
||||
*
|
||||
* - let block A equal MD5(passphrase || iv)
|
||||
* - let block B equal MD5(A || passphrase || iv)
|
||||
* - block C would be MD5(B || passphrase || iv) and so on
|
||||
* - encryption key is the first N bytes of A || B
|
||||
* Invent an iv, and derive the encryption key.
|
||||
*/
|
||||
for (i = 0; i < 8; i++) iv[i] = random_byte();
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
put_data(&md5c, iv, 8);
|
||||
MD5Final(keybuf, &md5c);
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, keybuf, 16);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
put_data(&md5c, iv, 8);
|
||||
MD5Final(keybuf+16, &md5c);
|
||||
openssh_pem_derivekey(ptrlen_from_asciz(passphrase), iv, keybuf);
|
||||
|
||||
/*
|
||||
* Now encrypt the key blob.
|
||||
@ -1035,7 +1025,6 @@ static bool openssh_pem_write(
|
||||
des3_encrypt_pubkey_ossh(keybuf, iv,
|
||||
outblob->u, outlen);
|
||||
|
||||
smemclr(&md5c, sizeof(md5c));
|
||||
smemclr(keybuf, sizeof(keybuf));
|
||||
}
|
||||
|
||||
@ -1959,6 +1948,26 @@ static ptrlen BinarySource_get_mp_sshcom_as_string(BinarySource *src)
|
||||
#define get_mp_sshcom_as_string(bs) \
|
||||
BinarySource_get_mp_sshcom_as_string(BinarySource_UPCAST(bs))
|
||||
|
||||
static void sshcom_derivekey(ptrlen passphrase, uint8_t *keybuf)
|
||||
{
|
||||
/*
|
||||
* Derive the encryption key for an ssh.com key file from the
|
||||
* passphrase and iv/salt:
|
||||
*
|
||||
* - let block A equal MD5(passphrase)
|
||||
* - let block B equal MD5(passphrase || A)
|
||||
* - block C would be MD5(passphrase || A || B) and so on
|
||||
* - encryption key is the first N bytes of A || B
|
||||
*/
|
||||
ssh_hash *h;
|
||||
|
||||
h = ssh_hash_new(&ssh_md5);
|
||||
put_datapl(h, passphrase);
|
||||
ssh_hash_final(ssh_hash_copy(h), keybuf);
|
||||
put_data(h, keybuf, 16);
|
||||
ssh_hash_final(h, keybuf + 16);
|
||||
}
|
||||
|
||||
static ssh2_userkey *sshcom_read(
|
||||
const Filename *filename, const char *passphrase, const char **errmsg_p)
|
||||
{
|
||||
@ -2035,7 +2044,6 @@ static ssh2_userkey *sshcom_read(
|
||||
* - block C would be MD5(passphrase || A || B) and so on
|
||||
* - encryption key is the first N bytes of A || B
|
||||
*/
|
||||
struct MD5Context md5c;
|
||||
unsigned char keybuf[32], iv[8];
|
||||
|
||||
if (ciphertext.len % 8 != 0) {
|
||||
@ -2044,14 +2052,7 @@ static ssh2_userkey *sshcom_read(
|
||||
goto error;
|
||||
}
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
MD5Final(keybuf, &md5c);
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
put_data(&md5c, keybuf, 16);
|
||||
MD5Final(keybuf+16, &md5c);
|
||||
sshcom_derivekey(ptrlen_from_asciz(passphrase), keybuf);
|
||||
|
||||
/*
|
||||
* Now decrypt the key blob in place (casting away const from
|
||||
@ -2061,7 +2062,6 @@ static ssh2_userkey *sshcom_read(
|
||||
des3_decrypt_pubkey_ossh(keybuf, iv,
|
||||
(char *)ciphertext.ptr, ciphertext.len);
|
||||
|
||||
smemclr(&md5c, sizeof(md5c));
|
||||
smemclr(keybuf, sizeof(keybuf));
|
||||
|
||||
/*
|
||||
@ -2294,25 +2294,9 @@ static bool sshcom_write(
|
||||
* Encrypt the key.
|
||||
*/
|
||||
if (passphrase) {
|
||||
/*
|
||||
* Derive encryption key from passphrase and iv/salt:
|
||||
*
|
||||
* - let block A equal MD5(passphrase)
|
||||
* - let block B equal MD5(passphrase || A)
|
||||
* - block C would be MD5(passphrase || A || B) and so on
|
||||
* - encryption key is the first N bytes of A || B
|
||||
*/
|
||||
struct MD5Context md5c;
|
||||
unsigned char keybuf[32], iv[8];
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
MD5Final(keybuf, &md5c);
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
put_data(&md5c, keybuf, 16);
|
||||
MD5Final(keybuf+16, &md5c);
|
||||
sshcom_derivekey(ptrlen_from_asciz(passphrase), keybuf);
|
||||
|
||||
/*
|
||||
* Now decrypt the key blob.
|
||||
@ -2320,7 +2304,6 @@ static bool sshcom_write(
|
||||
memset(iv, 0, sizeof(iv));
|
||||
des3_encrypt_pubkey_ossh(keybuf, iv, ciphertext, cipherlen);
|
||||
|
||||
smemclr(&md5c, sizeof(md5c));
|
||||
smemclr(keybuf, sizeof(keybuf));
|
||||
}
|
||||
|
||||
|
13
pageant.c
13
pageant.c
@ -228,7 +228,6 @@ void pageant_handle_msg(BinarySink *bs,
|
||||
ptrlen session_id;
|
||||
unsigned response_type;
|
||||
unsigned char response_md5[16];
|
||||
struct MD5Context md5c;
|
||||
int i;
|
||||
|
||||
plog(logctx, logfn, "request: SSH1_AGENTC_RSA_CHALLENGE");
|
||||
@ -266,11 +265,13 @@ void pageant_handle_msg(BinarySink *bs,
|
||||
}
|
||||
response = rsa_ssh1_decrypt(challenge, key);
|
||||
|
||||
MD5Init(&md5c);
|
||||
for (i = 0; i < 32; i++)
|
||||
put_byte(&md5c, mp_get_byte(response, 31 - i));
|
||||
put_datapl(&md5c, session_id);
|
||||
MD5Final(response_md5, &md5c);
|
||||
{
|
||||
ssh_hash *h = ssh_hash_new(&ssh_md5);
|
||||
for (i = 0; i < 32; i++)
|
||||
put_byte(h, mp_get_byte(response, 31 - i));
|
||||
put_datapl(h, session_id);
|
||||
ssh_hash_final(h, response_md5);
|
||||
}
|
||||
|
||||
put_byte(bs, SSH1_AGENT_RSA_RESPONSE);
|
||||
put_data(bs, response_md5, 16);
|
||||
|
75
ssh.h
75
ssh.h
@ -558,73 +558,8 @@ struct ssh_cipher {
|
||||
const ssh_cipheralg *vt;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t h[4];
|
||||
} MD5_Core_State;
|
||||
|
||||
struct MD5Context {
|
||||
MD5_Core_State core;
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint64_t len;
|
||||
BinarySink_IMPLEMENTATION;
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
void MD5Simple(void const *p, unsigned len, unsigned char output[16]);
|
||||
|
||||
struct hmacmd5_context;
|
||||
struct hmacmd5_context *hmacmd5_make_context(void);
|
||||
void hmacmd5_free_context(struct hmacmd5_context *ctx);
|
||||
void hmacmd5_key(struct hmacmd5_context *ctx, void const *key, int len);
|
||||
void hmacmd5_do_hmac(struct hmacmd5_context *ctx,
|
||||
const void *blk, int len, unsigned char *hmac);
|
||||
|
||||
bool supports_sha_ni(void);
|
||||
|
||||
typedef struct SHA_State {
|
||||
uint32_t h[5];
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint64_t len;
|
||||
void (*sha1)(struct SHA_State * s, const unsigned char *p, int len);
|
||||
BinarySink_IMPLEMENTATION;
|
||||
} SHA_State;
|
||||
void SHA_Init(SHA_State * s);
|
||||
void SHA_Final(SHA_State * s, unsigned char *output);
|
||||
void SHA_Simple(const void *p, int len, unsigned char *output);
|
||||
|
||||
void hmac_sha1_simple(const void *key, int keylen,
|
||||
const void *data, int datalen,
|
||||
unsigned char *output);
|
||||
typedef struct SHA256_State {
|
||||
uint32_t h[8];
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint64_t len;
|
||||
void (*sha256)(struct SHA256_State * s, const unsigned char *p, int len);
|
||||
BinarySink_IMPLEMENTATION;
|
||||
} SHA256_State;
|
||||
void SHA256_Init(SHA256_State * s);
|
||||
void SHA256_Final(SHA256_State * s, unsigned char *output);
|
||||
void SHA256_Simple(const void *p, int len, unsigned char *output);
|
||||
|
||||
typedef struct {
|
||||
uint64_t h[8];
|
||||
unsigned char block[128];
|
||||
int blkused;
|
||||
uint64_t lenhi, lenlo;
|
||||
BinarySink_IMPLEMENTATION;
|
||||
} SHA512_State;
|
||||
#define SHA384_State SHA512_State
|
||||
void SHA512_Init(SHA512_State * s);
|
||||
void SHA512_Final(SHA512_State * s, unsigned char *output);
|
||||
void SHA512_Simple(const void *p, int len, unsigned char *output);
|
||||
void SHA384_Init(SHA384_State * s);
|
||||
void SHA384_Final(SHA384_State * s, unsigned char *output);
|
||||
void SHA384_Simple(const void *p, int len, unsigned char *output);
|
||||
|
||||
struct ssh_cipheralg {
|
||||
ssh_cipher *(*new)(const ssh_cipheralg *alg);
|
||||
void (*free)(ssh_cipher *);
|
||||
@ -704,11 +639,17 @@ struct ssh2_macalg {
|
||||
#define ssh2_mac_genresult(ctx, out) ((ctx)->vt->genresult(ctx, out))
|
||||
#define ssh2_mac_alg(ctx) ((ctx)->vt)
|
||||
|
||||
/* Centralised 'methods' for ssh2_mac, defined in sshmac.c */
|
||||
/* Centralised 'methods' for ssh2_mac, defined in sshmac.c. These run
|
||||
* the MAC in a specifically SSH-2 style, i.e. taking account of a
|
||||
* packet sequence number as well as the data to be authenticated. */
|
||||
bool ssh2_mac_verresult(ssh2_mac *, const void *);
|
||||
void ssh2_mac_generate(ssh2_mac *, void *, int, unsigned long seq);
|
||||
bool ssh2_mac_verify(ssh2_mac *, const void *, int, unsigned long seq);
|
||||
|
||||
/* Use a MAC in its raw form, outside SSH-2 context, to MAC a given
|
||||
* string with a given key in the most obvious way. */
|
||||
void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output);
|
||||
|
||||
struct ssh_hash {
|
||||
const ssh_hashalg *vt;
|
||||
BinarySink_DELEGATE_IMPLEMENTATION;
|
||||
@ -729,6 +670,8 @@ struct ssh_hashalg {
|
||||
#define ssh_hash_free(ctx) ((ctx)->vt->free(ctx))
|
||||
#define ssh_hash_alg(ctx) ((ctx)->vt)
|
||||
|
||||
void hash_simple(const ssh_hashalg *alg, ptrlen data, void *output);
|
||||
|
||||
struct ssh_kex {
|
||||
const char *name, *groupname;
|
||||
enum { KEXTYPE_DH, KEXTYPE_RSA, KEXTYPE_ECDH, KEXTYPE_GSS } main_type;
|
||||
|
@ -306,15 +306,16 @@ static void ssh1_login_server_process_queue(PacketProtocolLayer *ppl)
|
||||
{
|
||||
unsigned char *rsabuf =
|
||||
snewn(s->authkey->bytes, unsigned char);
|
||||
struct MD5Context md5c;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
rsabuf[i] = random_byte();
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, rsabuf, 32);
|
||||
put_data(&md5c, s->session_id, 16);
|
||||
MD5Final(s->auth_rsa_expected_response, &md5c);
|
||||
{
|
||||
ssh_hash *h = ssh_hash_new(&ssh_md5);
|
||||
put_data(h, rsabuf, 32);
|
||||
put_data(h, s->session_id, 16);
|
||||
ssh_hash_final(h, s->auth_rsa_expected_response);
|
||||
}
|
||||
|
||||
if (!rsa_ssh1_encrypt(rsabuf, 32, s->authkey)) {
|
||||
sfree(rsabuf);
|
||||
|
@ -737,11 +737,10 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
||||
}
|
||||
|
||||
{
|
||||
struct MD5Context md5c;
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, buffer, 32);
|
||||
put_data(&md5c, s->session_id, 16);
|
||||
MD5Final(buffer, &md5c);
|
||||
ssh_hash *h = ssh_hash_new(&ssh_md5);
|
||||
put_data(h, buffer, 32);
|
||||
put_data(h, s->session_id, 16);
|
||||
ssh_hash_final(h, buffer);
|
||||
}
|
||||
|
||||
pkt = ssh_bpp_new_pktout(
|
||||
|
@ -1,12 +1,12 @@
|
||||
/*
|
||||
* sshauxcrypt.c: wrapper functions on ciphers for use in other
|
||||
* contexts than the main SSH packet protocol, such as encrypting
|
||||
* private key files and performing XDM-AUTHORIZATION-1.
|
||||
* sshauxcrypt.c: wrapper functions on crypto primitives for use in
|
||||
* other contexts than the main SSH packet protocol, such as
|
||||
* encrypting private key files and performing XDM-AUTHORIZATION-1.
|
||||
*
|
||||
* These all work through the standard cipher APIs, so they don't need
|
||||
* to live in the same actual source files as the ciphers they wrap,
|
||||
* and I think it keeps things tidier to have them out of the way here
|
||||
* instead.
|
||||
* These all work through the standard cipher/hash/MAC APIs, so they
|
||||
* don't need to live in the same actual source files as the ciphers
|
||||
* they wrap, and I think it keeps things tidier to have them out of
|
||||
* the way here instead.
|
||||
*/
|
||||
|
||||
#include "ssh.h"
|
||||
@ -150,3 +150,19 @@ void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
|
||||
ssh_cipher_free(c);
|
||||
}
|
||||
|
||||
void hash_simple(const ssh_hashalg *alg, ptrlen data, void *output)
|
||||
{
|
||||
ssh_hash *hash = ssh_hash_new(alg);
|
||||
put_datapl(hash, data);
|
||||
ssh_hash_final(hash, output);
|
||||
}
|
||||
|
||||
void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output)
|
||||
{
|
||||
ssh2_mac *mac = ssh2_mac_new(alg, NULL);
|
||||
ssh2_mac_setkey(mac, key);
|
||||
ssh2_mac_start(mac);
|
||||
put_datapl(mac, data);
|
||||
ssh2_mac_genresult(mac, output);
|
||||
ssh2_mac_free(mac);
|
||||
}
|
||||
|
12
sshbcrypt.c
12
sshbcrypt.c
@ -54,20 +54,18 @@ void bcrypt_genblock(int counter,
|
||||
const unsigned char *salt, int saltbytes,
|
||||
unsigned char output[32])
|
||||
{
|
||||
SHA512_State shastate;
|
||||
unsigned char hashed_salt[64];
|
||||
|
||||
/* Hash the input salt with the counter value optionally suffixed
|
||||
* to get our real 32-byte salt */
|
||||
SHA512_Init(&shastate);
|
||||
put_data(&shastate, salt, saltbytes);
|
||||
ssh_hash *h = ssh_hash_new(&ssh_sha512);
|
||||
put_data(h, salt, saltbytes);
|
||||
if (counter)
|
||||
put_uint32(&shastate, counter);
|
||||
SHA512_Final(&shastate, hashed_salt);
|
||||
put_uint32(h, counter);
|
||||
ssh_hash_final(h, hashed_salt);
|
||||
|
||||
bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);
|
||||
|
||||
smemclr(&shastate, sizeof(shastate));
|
||||
smemclr(&hashed_salt, sizeof(hashed_salt));
|
||||
}
|
||||
|
||||
@ -82,7 +80,7 @@ void openssh_bcrypt(const char *passphrase,
|
||||
int modulus, residue, i, j, round;
|
||||
|
||||
/* Hash the passphrase to get the bcrypt key material */
|
||||
SHA512_Simple(passphrase, strlen(passphrase), hashed_passphrase);
|
||||
hash_simple(&ssh_sha512, ptrlen_from_asciz(passphrase), hashed_passphrase);
|
||||
|
||||
/* We output key bytes in a scattered fashion to meld all output
|
||||
* key blocks into all parts of the output. To do this, we pick a
|
||||
|
11
sshcommon.c
11
sshcommon.c
@ -1008,15 +1008,14 @@ void ssh1_compute_session_id(
|
||||
unsigned char *session_id, const unsigned char *cookie,
|
||||
RSAKey *hostkey, RSAKey *servkey)
|
||||
{
|
||||
struct MD5Context md5c;
|
||||
ssh_hash *hash = ssh_hash_new(&ssh_md5);
|
||||
|
||||
MD5Init(&md5c);
|
||||
for (size_t i = (mp_get_nbits(hostkey->modulus) + 7) / 8; i-- ;)
|
||||
put_byte(&md5c, mp_get_byte(hostkey->modulus, i));
|
||||
put_byte(hash, mp_get_byte(hostkey->modulus, i));
|
||||
for (size_t i = (mp_get_nbits(servkey->modulus) + 7) / 8; i-- ;)
|
||||
put_byte(&md5c, mp_get_byte(servkey->modulus, i));
|
||||
put_data(&md5c, cookie, 8);
|
||||
MD5Final(session_id, &md5c);
|
||||
put_byte(hash, mp_get_byte(servkey->modulus, i));
|
||||
put_data(hash, cookie, 8);
|
||||
ssh_hash_final(hash, session_id);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
34
sshdss.c
34
sshdss.c
@ -145,7 +145,7 @@ static bool dss_verify(ssh_key *key, ptrlen sig, ptrlen data)
|
||||
/*
|
||||
* Step 2. u1 <- SHA(message) * w mod q.
|
||||
*/
|
||||
SHA_Simple(data.ptr, data.len, hash);
|
||||
hash_simple(&ssh_sha1, data, hash);
|
||||
mp_int *sha = mp_from_bytes_be(make_ptrlen(hash, 20));
|
||||
mp_int *u1 = mp_modmul(sha, w, dss->q);
|
||||
|
||||
@ -206,7 +206,6 @@ static ssh_key *dss_new_priv(const ssh_keyalg *self, ptrlen pub, ptrlen priv)
|
||||
ssh_key *sshk;
|
||||
struct dss_key *dss;
|
||||
ptrlen hash;
|
||||
SHA_State s;
|
||||
unsigned char digest[20];
|
||||
mp_int *ytest;
|
||||
|
||||
@ -227,11 +226,11 @@ static ssh_key *dss_new_priv(const ssh_keyalg *self, ptrlen pub, ptrlen priv)
|
||||
*/
|
||||
hash = get_string(src);
|
||||
if (hash.len == 20) {
|
||||
SHA_Init(&s);
|
||||
put_mp_ssh2(&s, dss->p);
|
||||
put_mp_ssh2(&s, dss->q);
|
||||
put_mp_ssh2(&s, dss->g);
|
||||
SHA_Final(&s, digest);
|
||||
ssh_hash *h = ssh_hash_new(&ssh_sha1);
|
||||
put_mp_ssh2(h, dss->p);
|
||||
put_mp_ssh2(h, dss->q);
|
||||
put_mp_ssh2(h, dss->g);
|
||||
ssh_hash_final(h, digest);
|
||||
if (!smemeq(hash.ptr, digest, 20)) {
|
||||
dss_freekey(&dss->sshk);
|
||||
return NULL;
|
||||
@ -379,24 +378,24 @@ mp_int *dss_gen_k(const char *id_string, mp_int *modulus,
|
||||
* Computer Security Group for helping to argue out all the
|
||||
* fine details.
|
||||
*/
|
||||
SHA512_State ss;
|
||||
ssh_hash *h;
|
||||
unsigned char digest512[64];
|
||||
|
||||
/*
|
||||
* Hash some identifying text plus x.
|
||||
*/
|
||||
SHA512_Init(&ss);
|
||||
put_asciz(&ss, id_string);
|
||||
put_mp_ssh2(&ss, private_key);
|
||||
SHA512_Final(&ss, digest512);
|
||||
h = ssh_hash_new(&ssh_sha512);
|
||||
put_asciz(h, id_string);
|
||||
put_mp_ssh2(h, private_key);
|
||||
ssh_hash_final(h, digest512);
|
||||
|
||||
/*
|
||||
* Now hash that digest plus the message hash.
|
||||
*/
|
||||
SHA512_Init(&ss);
|
||||
put_data(&ss, digest512, sizeof(digest512));
|
||||
put_data(&ss, digest, digest_len);
|
||||
SHA512_Final(&ss, digest512);
|
||||
h = ssh_hash_new(&ssh_sha512);
|
||||
put_data(h, digest512, sizeof(digest512));
|
||||
put_data(h, digest, digest_len);
|
||||
ssh_hash_final(h, digest512);
|
||||
|
||||
/*
|
||||
* Now convert the result into a bignum, and coerce it to the
|
||||
@ -410,7 +409,6 @@ mp_int *dss_gen_k(const char *id_string, mp_int *modulus,
|
||||
mp_free(modminus2);
|
||||
mp_add_integer_into(k, k, 2);
|
||||
|
||||
smemclr(&ss, sizeof(ss));
|
||||
smemclr(digest512, sizeof(digest512));
|
||||
|
||||
return k;
|
||||
@ -422,7 +420,7 @@ static void dss_sign(ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs)
|
||||
unsigned char digest[20];
|
||||
int i;
|
||||
|
||||
SHA_Simple(data.ptr, data.len, digest);
|
||||
hash_simple(&ssh_sha1, data, digest);
|
||||
|
||||
mp_int *k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x,
|
||||
digest, sizeof(digest));
|
||||
|
2
sshecc.c
2
sshecc.c
@ -994,7 +994,7 @@ static void ecdsa_sign(ssh_key *key, ptrlen data,
|
||||
mp_int *k;
|
||||
{
|
||||
unsigned char digest[20];
|
||||
SHA_Simple(data.ptr, data.len, digest);
|
||||
hash_simple(&ssh_sha1, data, digest);
|
||||
k = dss_gen_k(
|
||||
"ECDSA deterministic k generator", ek->curve->w.G_order,
|
||||
ek->privateKey, digest, sizeof(digest));
|
||||
|
12
sshmd5.c
12
sshmd5.c
@ -6,6 +6,18 @@
|
||||
* Simon Tatham.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint32_t h[4];
|
||||
} MD5_Core_State;
|
||||
|
||||
struct MD5Context {
|
||||
MD5_Core_State core;
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint64_t len;
|
||||
BinarySink_IMPLEMENTATION;
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Core MD5 algorithm: processes 16-word blocks into a message digest.
|
||||
*/
|
||||
|
92
sshpubk.c
92
sshpubk.c
@ -31,7 +31,6 @@ static int rsa_ssh1_load_main(FILE * fp, RSAKey *key, bool pub_only,
|
||||
strbuf *buf;
|
||||
int ciphertype;
|
||||
int ret = 0;
|
||||
struct MD5Context md5c;
|
||||
ptrlen comment;
|
||||
BinarySource src[1];
|
||||
|
||||
@ -96,9 +95,7 @@ static int rsa_ssh1_load_main(FILE * fp, RSAKey *key, bool pub_only,
|
||||
if (enclen & 7)
|
||||
goto end;
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
MD5Final(keybuf, &md5c);
|
||||
hash_simple(&ssh_md5, ptrlen_from_asciz(passphrase), keybuf);
|
||||
des3_decrypt_pubkey(keybuf, buf->u + src->pos, enclen);
|
||||
smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
|
||||
}
|
||||
@ -363,12 +360,11 @@ bool rsa_ssh1_savekey(const Filename *filename, RSAKey *key,
|
||||
* Now encrypt the encrypted portion.
|
||||
*/
|
||||
if (passphrase) {
|
||||
struct MD5Context md5c;
|
||||
unsigned char keybuf[16];
|
||||
|
||||
MD5Init(&md5c);
|
||||
put_data(&md5c, passphrase, strlen(passphrase));
|
||||
MD5Final(keybuf, &md5c);
|
||||
ssh_hash *h = ssh_hash_new(&ssh_md5);
|
||||
put_data(h, passphrase, strlen(passphrase));
|
||||
ssh_hash_final(h, keybuf);
|
||||
des3_encrypt_pubkey(keybuf, buf->u + estart, buf->len - estart);
|
||||
smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
|
||||
}
|
||||
@ -588,6 +584,19 @@ const ssh_keyalg *find_pubkey_alg(const char *name)
|
||||
return find_pubkey_alg_len(ptrlen_from_asciz(name));
|
||||
}
|
||||
|
||||
static void ssh2_ppk_derivekey(ptrlen passphrase, uint8_t *key)
|
||||
{
|
||||
ssh_hash *h;
|
||||
h = ssh_hash_new(&ssh_sha1);
|
||||
put_uint32(h, 0);
|
||||
put_datapl(h, passphrase);
|
||||
ssh_hash_final(h, key + 0);
|
||||
h = ssh_hash_new(&ssh_sha1);
|
||||
put_uint32(h, 1);
|
||||
put_datapl(h, passphrase);
|
||||
ssh_hash_final(h, key + 20);
|
||||
}
|
||||
|
||||
ssh2_userkey *ssh2_load_userkey(
|
||||
const Filename *filename, const char *passphrase, const char **errorstr)
|
||||
{
|
||||
@ -708,21 +717,13 @@ ssh2_userkey *ssh2_load_userkey(
|
||||
*/
|
||||
if (cipher) {
|
||||
unsigned char key[40];
|
||||
SHA_State s;
|
||||
|
||||
if (!passphrase)
|
||||
goto error;
|
||||
if (private_blob->len % cipherblk)
|
||||
goto error;
|
||||
|
||||
SHA_Init(&s);
|
||||
put_uint32(&s, 0);
|
||||
put_data(&s, passphrase, passlen);
|
||||
SHA_Final(&s, key + 0);
|
||||
SHA_Init(&s);
|
||||
put_uint32(&s, 1);
|
||||
put_data(&s, passphrase, passlen);
|
||||
SHA_Final(&s, key + 20);
|
||||
ssh2_ppk_derivekey(ptrlen_from_asciz(passphrase), key);
|
||||
aes256_decrypt_pubkey(key, private_blob->u, private_blob->len);
|
||||
}
|
||||
|
||||
@ -752,23 +753,27 @@ ssh2_userkey *ssh2_load_userkey(
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
SHA_State s;
|
||||
ssh_hash *hash;
|
||||
ssh2_mac *mac;
|
||||
unsigned char mackey[20];
|
||||
char header[] = "putty-private-key-file-mac-key";
|
||||
|
||||
SHA_Init(&s);
|
||||
put_data(&s, header, sizeof(header)-1);
|
||||
hash = ssh_hash_new(&ssh_sha1);
|
||||
put_data(hash, header, sizeof(header)-1);
|
||||
if (cipher && passphrase)
|
||||
put_data(&s, passphrase, passlen);
|
||||
SHA_Final(&s, mackey);
|
||||
put_data(hash, passphrase, passlen);
|
||||
ssh_hash_final(hash, mackey);
|
||||
|
||||
hmac_sha1_simple(mackey, 20, macdata->s,
|
||||
macdata->len, binary);
|
||||
mac = ssh2_mac_new(&ssh_hmac_sha1, NULL);
|
||||
ssh2_mac_setkey(mac, make_ptrlen(mackey, 20));
|
||||
ssh2_mac_start(mac);
|
||||
put_data(mac, macdata->s, macdata->len);
|
||||
ssh2_mac_genresult(mac, binary);
|
||||
ssh2_mac_free(mac);
|
||||
|
||||
smemclr(mackey, sizeof(mackey));
|
||||
smemclr(&s, sizeof(s));
|
||||
} else {
|
||||
SHA_Simple(macdata->s, macdata->len, binary);
|
||||
hash_simple(&ssh_sha1, ptrlen_from_strbuf(macdata), binary);
|
||||
}
|
||||
|
||||
if (free_macdata)
|
||||
@ -1241,7 +1246,6 @@ bool ssh2_save_userkey(
|
||||
strbuf *pub_blob, *priv_blob;
|
||||
unsigned char *priv_blob_encrypted;
|
||||
int priv_encrypted_len;
|
||||
int passlen;
|
||||
int cipherblk;
|
||||
int i;
|
||||
const char *cipherstr;
|
||||
@ -1272,7 +1276,7 @@ bool ssh2_save_userkey(
|
||||
memcpy(priv_blob_encrypted, priv_blob->u, priv_blob->len);
|
||||
/* Create padding based on the SHA hash of the unpadded blob. This prevents
|
||||
* too easy a known-plaintext attack on the last block. */
|
||||
SHA_Simple(priv_blob->u, priv_blob->len, priv_mac);
|
||||
hash_simple(&ssh_sha1, ptrlen_from_strbuf(priv_blob), priv_mac);
|
||||
assert(priv_encrypted_len - priv_blob->len < 20);
|
||||
memcpy(priv_blob_encrypted + priv_blob->len, priv_mac,
|
||||
priv_encrypted_len - priv_blob->len);
|
||||
@ -1280,7 +1284,6 @@ bool ssh2_save_userkey(
|
||||
/* Now create the MAC. */
|
||||
{
|
||||
strbuf *macdata;
|
||||
SHA_State s;
|
||||
unsigned char mackey[20];
|
||||
char header[] = "putty-private-key-file-mac-key";
|
||||
|
||||
@ -1291,37 +1294,24 @@ bool ssh2_save_userkey(
|
||||
put_string(macdata, pub_blob->s, pub_blob->len);
|
||||
put_string(macdata, priv_blob_encrypted, priv_encrypted_len);
|
||||
|
||||
SHA_Init(&s);
|
||||
put_data(&s, header, sizeof(header)-1);
|
||||
ssh_hash *h = ssh_hash_new(&ssh_sha1);
|
||||
put_data(h, header, sizeof(header)-1);
|
||||
if (passphrase)
|
||||
put_data(&s, passphrase, strlen(passphrase));
|
||||
SHA_Final(&s, mackey);
|
||||
hmac_sha1_simple(mackey, 20, macdata->s,
|
||||
macdata->len, priv_mac);
|
||||
put_data(h, passphrase, strlen(passphrase));
|
||||
ssh_hash_final(h, mackey);
|
||||
mac_simple(&ssh_hmac_sha1, make_ptrlen(mackey, 20),
|
||||
ptrlen_from_strbuf(macdata), priv_mac);
|
||||
strbuf_free(macdata);
|
||||
smemclr(mackey, sizeof(mackey));
|
||||
smemclr(&s, sizeof(s));
|
||||
}
|
||||
|
||||
if (passphrase) {
|
||||
unsigned char key[40];
|
||||
SHA_State s;
|
||||
|
||||
passlen = strlen(passphrase);
|
||||
|
||||
SHA_Init(&s);
|
||||
put_uint32(&s, 0);
|
||||
put_data(&s, passphrase, passlen);
|
||||
SHA_Final(&s, key + 0);
|
||||
SHA_Init(&s);
|
||||
put_uint32(&s, 1);
|
||||
put_data(&s, passphrase, passlen);
|
||||
SHA_Final(&s, key + 20);
|
||||
aes256_encrypt_pubkey(key, priv_blob_encrypted,
|
||||
priv_encrypted_len);
|
||||
ssh2_ppk_derivekey(ptrlen_from_asciz(passphrase), key);
|
||||
aes256_encrypt_pubkey(key, priv_blob_encrypted, priv_encrypted_len);
|
||||
|
||||
smemclr(key, sizeof(key));
|
||||
smemclr(&s, sizeof(s));
|
||||
}
|
||||
|
||||
fp = f_open(filename, "w", true);
|
||||
@ -1496,7 +1486,7 @@ char *ssh2_fingerprint_blob(const void *blob, int bloblen)
|
||||
/*
|
||||
* The fingerprint hash itself is always just the MD5 of the blob.
|
||||
*/
|
||||
MD5Simple(blob, bloblen, digest);
|
||||
hash_simple(&ssh_md5, make_ptrlen(blob, bloblen), digest);
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(fingerprint_str + i*3, "%02x%s", digest[i], i==15 ? "" : ":");
|
||||
|
||||
|
9
sshrsa.c
9
sshrsa.c
@ -232,7 +232,6 @@ char *rsastr_fmt(RSAKey *key)
|
||||
*/
|
||||
char *rsa_ssh1_fingerprint(RSAKey *key)
|
||||
{
|
||||
struct MD5Context md5c;
|
||||
unsigned char digest[16];
|
||||
strbuf *out;
|
||||
int i;
|
||||
@ -245,12 +244,12 @@ char *rsa_ssh1_fingerprint(RSAKey *key)
|
||||
* between them.
|
||||
*/
|
||||
|
||||
MD5Init(&md5c);
|
||||
ssh_hash *hash = ssh_hash_new(&ssh_md5);
|
||||
for (size_t i = (mp_get_nbits(key->modulus) + 7) / 8; i-- > 0 ;)
|
||||
put_byte(&md5c, mp_get_byte(key->modulus, i));
|
||||
put_byte(hash, mp_get_byte(key->modulus, i));
|
||||
for (size_t i = (mp_get_nbits(key->exponent) + 7) / 8; i-- > 0 ;)
|
||||
put_byte(&md5c, mp_get_byte(key->exponent, i));
|
||||
MD5Final(digest, &md5c);
|
||||
put_byte(hash, mp_get_byte(key->exponent, i));
|
||||
ssh_hash_final(hash, digest);
|
||||
|
||||
out = strbuf_new();
|
||||
strbuf_catf(out, "%d ", mp_get_nbits(key->modulus));
|
||||
|
11
sshsh256.c
11
sshsh256.c
@ -20,8 +20,17 @@
|
||||
#define smallsigma0(x) ( ror((x),7) ^ ror((x),18) ^ shr((x),3) )
|
||||
#define smallsigma1(x) ( ror((x),17) ^ ror((x),19) ^ shr((x),10) )
|
||||
|
||||
typedef struct SHA256_State {
|
||||
uint32_t h[8];
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint64_t len;
|
||||
void (*sha256)(struct SHA256_State * s, const unsigned char *p, int len);
|
||||
BinarySink_IMPLEMENTATION;
|
||||
} SHA256_State;
|
||||
|
||||
static void SHA256_sw(SHA256_State *s, const unsigned char *q, int len);
|
||||
static void SHA256_ni(SHA256_State * s, const unsigned char *q, int len);
|
||||
static void SHA256_ni(SHA256_State *s, const unsigned char *q, int len);
|
||||
|
||||
void SHA256_Core_Init(SHA256_State *s) {
|
||||
s->h[0] = 0x6a09e667;
|
||||
|
@ -11,6 +11,14 @@
|
||||
|
||||
#define BLKSIZE 128
|
||||
|
||||
typedef struct {
|
||||
uint64_t h[8];
|
||||
unsigned char block[128];
|
||||
int blkused;
|
||||
uint64_t lenhi, lenlo;
|
||||
BinarySink_IMPLEMENTATION;
|
||||
} SHA512_State;
|
||||
|
||||
/*
|
||||
* Arithmetic implementations. Note that AND, XOR and NOT can
|
||||
* overlap destination with one source, but the others can't.
|
||||
|
9
sshsha.c
9
sshsha.c
@ -9,6 +9,15 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct SHA_State {
|
||||
uint32_t h[5];
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint64_t len;
|
||||
void (*sha1)(struct SHA_State * s, const unsigned char *p, int len);
|
||||
BinarySink_IMPLEMENTATION;
|
||||
} SHA_State;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Core SHA algorithm: processes 16-word blocks into a message digest.
|
||||
*/
|
||||
|
@ -211,14 +211,13 @@ static char *make_dirname(const char *pi_name, char **logtext)
|
||||
* identifier to produce our actual socket name.
|
||||
*/
|
||||
{
|
||||
SHA256_State sha;
|
||||
unsigned char digest[32];
|
||||
char retbuf[65];
|
||||
|
||||
SHA256_Init(&sha);
|
||||
put_string(&sha, saltbuf, SALT_SIZE);
|
||||
put_stringz(&sha, pi_name);
|
||||
SHA256_Final(&sha, digest);
|
||||
ssh_hash *h = ssh_hash_new(&ssh_sha256);
|
||||
put_string(h, saltbuf, SALT_SIZE);
|
||||
put_stringz(h, pi_name);
|
||||
ssh_hash_final(h, digest);
|
||||
|
||||
/*
|
||||
* And make it printable.
|
||||
|
@ -47,7 +47,6 @@ static char *obfuscate_name(const char *realname)
|
||||
*/
|
||||
char *cryptdata;
|
||||
int cryptlen;
|
||||
SHA256_State sha;
|
||||
unsigned char digest[32];
|
||||
char retbuf[65];
|
||||
int i;
|
||||
@ -87,9 +86,11 @@ static char *obfuscate_name(const char *realname)
|
||||
* 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.
|
||||
*/
|
||||
SHA256_Init(&sha);
|
||||
put_string(&sha, cryptdata, cryptlen);
|
||||
SHA256_Final(&sha, digest);
|
||||
{
|
||||
ssh_hash *h = ssh_hash_new(&ssh_sha256);
|
||||
put_string(h, cryptdata, cryptlen);
|
||||
ssh_hash_final(h, digest);
|
||||
}
|
||||
|
||||
sfree(cryptdata);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user