1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Merge branch 'thirdparty_dev' into dev

# Conflicts:
#	source/putty/mpint.c
#	source/putty/ssh.h
#	source/putty/ssh2bpp.c
#	source/putty/sshaes.c

Source commit: c448c97cc3320d5d66590b09dbc4d9ad75b3fa4e
This commit is contained in:
Martin Prikryl
2019-05-07 08:54:00 +00:00
23 changed files with 980 additions and 804 deletions

6
source/putty/defs.h vendored
View File

@@ -105,11 +105,9 @@ typedef struct ssh_compression_alg ssh_compression_alg;
typedef struct ssh2_userkey ssh2_userkey;
typedef struct ssh2_macalg ssh2_macalg;
typedef struct ssh2_mac ssh2_mac;
typedef struct ssh2_cipheralg ssh2_cipheralg;
typedef struct ssh2_cipher ssh2_cipher;
typedef struct ssh_cipheralg ssh_cipheralg;
typedef struct ssh_cipher ssh_cipher;
typedef struct ssh2_ciphers ssh2_ciphers;
typedef struct ssh1_cipheralg ssh1_cipheralg;
typedef struct ssh1_cipher ssh1_cipher;
typedef struct dh_ctx dh_ctx;
typedef struct ecdh_key ecdh_key;

34
source/putty/import.c vendored
View File

@@ -547,11 +547,11 @@ static ssh2_userkey *openssh_pem_read(
des3_decrypt_pubkey_ossh(keybuf, key->iv,
key->keyblob->u, key->keyblob->len);
else {
ssh2_cipher *cipher = ssh2_cipher_new(&ssh_aes128_cbc);
ssh2_cipher_setkey(cipher, keybuf);
ssh2_cipher_setiv(cipher, key->iv);
ssh2_cipher_decrypt(cipher, key->keyblob->u, key->keyblob->len);
ssh2_cipher_free(cipher);
ssh_cipher *cipher = ssh_cipher_new(&ssh_aes128_cbc);
ssh_cipher_setkey(cipher, keybuf);
ssh_cipher_setiv(cipher, key->iv);
ssh_cipher_decrypt(cipher, key->keyblob->u, key->keyblob->len);
ssh_cipher_free(cipher);
}
smemclr(&md5c, sizeof(md5c));
@@ -1388,16 +1388,16 @@ static ssh2_userkey *openssh_new_read(
goto error;
}
{
ssh2_cipher *cipher = ssh2_cipher_new(
ssh_cipher *cipher = ssh_cipher_new(
key->cipher == ON_E_AES256CBC ?
&ssh_aes256_cbc : &ssh_aes256_sdctr);
ssh2_cipher_setkey(cipher, keybuf);
ssh2_cipher_setiv(cipher, keybuf + 32);
ssh_cipher_setkey(cipher, keybuf);
ssh_cipher_setiv(cipher, keybuf + 32);
/* Decrypt the private section in place, casting away
* the const from key->private being a ptrlen */
ssh2_cipher_decrypt(cipher, (char *)key->private.ptr,
key->private.len);
ssh2_cipher_free(cipher);
ssh_cipher_decrypt(cipher, (char *)key->private.ptr,
key->private.len);
ssh_cipher_free(cipher);
}
break;
default:
@@ -1588,17 +1588,17 @@ static bool openssh_new_write(
* material: 32 bytes AES key + 16 bytes iv.
*/
unsigned char keybuf[48];
ssh2_cipher *cipher;
ssh_cipher *cipher;
openssh_bcrypt(passphrase,
bcrypt_salt, sizeof(bcrypt_salt), bcrypt_rounds,
keybuf, sizeof(keybuf));
cipher = ssh2_cipher_new(&ssh_aes256_sdctr);
ssh2_cipher_setkey(cipher, keybuf);
ssh2_cipher_setiv(cipher, keybuf + 32);
ssh2_cipher_encrypt(cipher, cpblob->u, cpblob->len);
ssh2_cipher_free(cipher);
cipher = ssh_cipher_new(&ssh_aes256_sdctr);
ssh_cipher_setkey(cipher, keybuf);
ssh_cipher_setiv(cipher, keybuf + 32);
ssh_cipher_encrypt(cipher, cpblob->u, cpblob->len);
ssh_cipher_free(cipher);
smemclr(keybuf, sizeof(keybuf));
}

36
source/putty/mpint.c vendored
View File

@@ -1172,25 +1172,16 @@ mp_int *mp_rshift_safe(mp_int *x, size_t bits)
/*
* That's done the shifting by words; now we do the shifting by
* bits.
*
* I assume here that register-controlled right shifts are
* time-constant. If they're not, I could replace this with
* another loop over bit positions.
*/
{ // WINSCP
size_t upshift = BIGNUM_INT_BITS - bitshift;
size_t no_shift = (upshift >> BIGNUM_INT_BITS_BITS);
upshift &= ~-(size_t)no_shift;
{ // WINSCP
BignumInt upshifted_mask = ~-(BignumInt)no_shift;
size_t i; // WINSCP
for (i = 0; i < r->nw; i++) {
r->w[i] = (r->w[i] >> bitshift) |
((mp_word(r, i+1) << upshift) & upshifted_mask);
for (bit = 0; bit < BIGNUM_INT_BITS_BITS; bit++) { // WINSCP
unsigned shift = 1 << bit, upshift = BIGNUM_INT_BITS - shift;
BignumInt mask = -(BignumInt)((bitshift >> bit) & 1);
size_t i; // WINSCP
for (i = 0; i < r->nw; i++) {
BignumInt w = ((r->w[i] >> shift) | (mp_word(r, i+1) << upshift));
r->w[i] ^= (r->w[i] ^ w) & mask;
}
}
} // WINSCP
} // WINSCP
return r;
}
@@ -1964,12 +1955,11 @@ void mp_divmod_into(mp_int *n, mp_int *d, mp_int *q_out, mp_int *r_out)
* actual input will be close to a fixed power of two regardless
* of where the MSB was.
*
* I do this in another log n individual passes, not so much
* because I'm worried about the time-invariance of the CPU's
* register-controlled shift operation, but in case the compiler
* code-generates uint64_t shifts out of a variable number of
* smaller-word shift instructions, e.g. by splitting up into
* cases.
* I do this in another log n individual passes, partly in case
* the CPU's register-controlled shift operation isn't
* time-constant, and also in case the compiler code-generates
* uint64_t shifts out of a variable number of smaller-word shift
* instructions, e.g. by splitting up into cases.
*/
for (i = BIGNUM_INT_BITS_BITS; i-- > 0;) {
size_t sl = 1 << i; /* left shift count */

144
source/putty/ssh.h vendored
View File

@@ -520,15 +520,17 @@ void freersakey(RSAKey *key);
#endif // WINSCP_VS
#ifndef WINSCP_VS
unsigned long crc32_compute(const void *s, size_t len);
unsigned long crc32_update(unsigned long crc_input, const void *s, size_t len);
uint32_t crc32_rfc1662(ptrlen data);
uint32_t crc32_ssh1(ptrlen data);
uint32_t crc32_update(uint32_t crc_input, ptrlen data);
/* SSH CRC compensation attack detector */
struct crcda_ctx;
struct crcda_ctx *crcda_make_context(void);
void crcda_free_context(struct crcda_ctx *ctx);
bool detect_attack(struct crcda_ctx *ctx, unsigned char *buf, uint32_t len,
unsigned char *IV);
bool detect_attack(struct crcda_ctx *ctx,
const unsigned char *buf, uint32_t len,
const unsigned char *IV);
/*
* SSH2 RSA key exchange functions
@@ -561,8 +563,8 @@ mp_int *dss_gen_k(const char *id_string,
unsigned char *digest, int digest_len);
#endif
struct ssh2_cipher {
const ssh2_cipheralg *vt;
struct ssh_cipher {
const ssh_cipheralg *vt;
};
#ifndef WINSCP_VS
@@ -645,41 +647,22 @@ 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 ssh1_cipher {
const ssh1_cipheralg *vt;
};
struct ssh1_cipheralg {
ssh1_cipher *(*new)(void);
void (*free)(ssh1_cipher *);
void (*sesskey)(ssh1_cipher *, const void *key);
void (*encrypt)(ssh1_cipher *, void *blk, int len);
void (*decrypt)(ssh1_cipher *, void *blk, int len);
int blksize;
const char *text_name;
};
#define ssh1_cipher_new(alg) ((alg)->new())
#define ssh1_cipher_free(ctx) ((ctx)->vt->free(ctx))
#define ssh1_cipher_sesskey(ctx, key) ((ctx)->vt->sesskey(ctx, key))
#define ssh1_cipher_encrypt(ctx, blk, len) ((ctx)->vt->encrypt(ctx, blk, len))
#define ssh1_cipher_decrypt(ctx, blk, len) ((ctx)->vt->decrypt(ctx, blk, len))
#endif
struct ssh2_cipheralg {
ssh2_cipher *(*new)(const ssh2_cipheralg *alg);
void (*free)(ssh2_cipher *);
void (*setiv)(ssh2_cipher *, const void *iv);
void (*setkey)(ssh2_cipher *, const void *key);
void (*encrypt)(ssh2_cipher *, void *blk, int len);
void (*decrypt)(ssh2_cipher *, void *blk, int len);
struct ssh_cipheralg {
ssh_cipher *(*new)(const ssh_cipheralg *alg);
void (*free)(ssh_cipher *);
void (*setiv)(ssh_cipher *, const void *iv);
void (*setkey)(ssh_cipher *, const void *key);
void (*encrypt)(ssh_cipher *, void *blk, int len);
void (*decrypt)(ssh_cipher *, void *blk, int len);
/* Ignored unless SSH_CIPHER_SEPARATE_LENGTH flag set */
void (*encrypt_length)(ssh2_cipher *, void *blk, int len,
void (*encrypt_length)(ssh_cipher *, void *blk, int len,
unsigned long seq);
void (*decrypt_length)(ssh2_cipher *, void *blk, int len,
void (*decrypt_length)(ssh_cipher *, void *blk, int len,
unsigned long seq);
const char *name;
const char *ssh2_id;
int blksize;
/* real_keybits is the number of bits of entropy genuinely used by
* the cipher scheme; it's used for deciding how big a
@@ -707,21 +690,21 @@ struct ssh2_cipheralg {
#ifndef WINSCP_VS
#define ssh2_cipher_new(alg) ((alg)->new(alg))
#define ssh2_cipher_free(ctx) ((ctx)->vt->free(ctx))
#define ssh2_cipher_setiv(ctx, iv) ((ctx)->vt->setiv(ctx, iv))
#define ssh2_cipher_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key))
#define ssh2_cipher_encrypt(ctx, blk, len) ((ctx)->vt->encrypt(ctx, blk, len))
#define ssh2_cipher_decrypt(ctx, blk, len) ((ctx)->vt->decrypt(ctx, blk, len))
#define ssh2_cipher_encrypt_length(ctx, blk, len, seq) \
#define ssh_cipher_new(alg) ((alg)->new(alg))
#define ssh_cipher_free(ctx) ((ctx)->vt->free(ctx))
#define ssh_cipher_setiv(ctx, iv) ((ctx)->vt->setiv(ctx, iv))
#define ssh_cipher_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key))
#define ssh_cipher_encrypt(ctx, blk, len) ((ctx)->vt->encrypt(ctx, blk, len))
#define ssh_cipher_decrypt(ctx, blk, len) ((ctx)->vt->decrypt(ctx, blk, len))
#define ssh_cipher_encrypt_length(ctx, blk, len, seq) \
((ctx)->vt->encrypt_length(ctx, blk, len, seq))
#define ssh2_cipher_decrypt_length(ctx, blk, len, seq) \
#define ssh_cipher_decrypt_length(ctx, blk, len, seq) \
((ctx)->vt->decrypt_length(ctx, blk, len, seq))
#define ssh2_cipher_alg(ctx) ((ctx)->vt)
#define ssh_cipher_alg(ctx) ((ctx)->vt)
struct ssh2_ciphers {
int nciphers;
const ssh2_cipheralg *const *list;
const ssh_cipheralg *const *list;
};
struct ssh2_mac {
@@ -731,7 +714,7 @@ struct ssh2_mac {
struct ssh2_macalg {
/* Passes in the cipher context */
ssh2_mac *(*new)(const ssh2_macalg *alg, ssh2_cipher *cipher);
ssh2_mac *(*new)(const ssh2_macalg *alg, ssh_cipher *cipher);
void (*free)(ssh2_mac *);
void (*setkey)(ssh2_mac *, ptrlen key);
void (*start)(ssh2_mac *);
@@ -878,36 +861,35 @@ struct ssh2_userkey {
/* The maximum length of any hash algorithm. (bytes) */
#define MAX_HASH_LEN (64) /* longest is SHA-512 */
extern const ssh1_cipheralg ssh1_3des;
extern const ssh1_cipheralg ssh1_des;
extern const ssh1_cipheralg ssh1_blowfish;
extern const ssh2_cipheralg ssh_3des_ssh2_ctr;
extern const ssh2_cipheralg ssh_3des_ssh2;
extern const ssh2_cipheralg ssh_des_ssh2;
extern const ssh2_cipheralg ssh_des_sshcom_ssh2;
extern const ssh2_cipheralg ssh_aes256_sdctr;
extern const ssh2_cipheralg ssh_aes256_sdctr_hw;
extern const ssh2_cipheralg ssh_aes256_sdctr_sw;
extern const ssh2_cipheralg ssh_aes256_cbc;
extern const ssh2_cipheralg ssh_aes256_cbc_hw;
extern const ssh2_cipheralg ssh_aes256_cbc_sw;
extern const ssh2_cipheralg ssh_aes192_sdctr;
extern const ssh2_cipheralg ssh_aes192_sdctr_hw;
extern const ssh2_cipheralg ssh_aes192_sdctr_sw;
extern const ssh2_cipheralg ssh_aes192_cbc;
extern const ssh2_cipheralg ssh_aes192_cbc_hw;
extern const ssh2_cipheralg ssh_aes192_cbc_sw;
extern const ssh2_cipheralg ssh_aes128_sdctr;
extern const ssh2_cipheralg ssh_aes128_sdctr_hw;
extern const ssh2_cipheralg ssh_aes128_sdctr_sw;
extern const ssh2_cipheralg ssh_aes128_cbc;
extern const ssh2_cipheralg ssh_aes128_cbc_hw;
extern const ssh2_cipheralg ssh_aes128_cbc_sw;
extern const ssh2_cipheralg ssh_blowfish_ssh2_ctr;
extern const ssh2_cipheralg ssh_blowfish_ssh2;
extern const ssh2_cipheralg ssh_arcfour256_ssh2;
extern const ssh2_cipheralg ssh_arcfour128_ssh2;
extern const ssh2_cipheralg ssh2_chacha20_poly1305;
extern const ssh_cipheralg ssh_3des_ssh1;
extern const ssh_cipheralg ssh_blowfish_ssh1;
extern const ssh_cipheralg ssh_3des_ssh2_ctr;
extern const ssh_cipheralg ssh_3des_ssh2;
extern const ssh_cipheralg ssh_des;
extern const ssh_cipheralg ssh_des_sshcom_ssh2;
extern const ssh_cipheralg ssh_aes256_sdctr;
extern const ssh_cipheralg ssh_aes256_sdctr_hw;
extern const ssh_cipheralg ssh_aes256_sdctr_sw;
extern const ssh_cipheralg ssh_aes256_cbc;
extern const ssh_cipheralg ssh_aes256_cbc_hw;
extern const ssh_cipheralg ssh_aes256_cbc_sw;
extern const ssh_cipheralg ssh_aes192_sdctr;
extern const ssh_cipheralg ssh_aes192_sdctr_hw;
extern const ssh_cipheralg ssh_aes192_sdctr_sw;
extern const ssh_cipheralg ssh_aes192_cbc;
extern const ssh_cipheralg ssh_aes192_cbc_hw;
extern const ssh_cipheralg ssh_aes192_cbc_sw;
extern const ssh_cipheralg ssh_aes128_sdctr;
extern const ssh_cipheralg ssh_aes128_sdctr_hw;
extern const ssh_cipheralg ssh_aes128_sdctr_sw;
extern const ssh_cipheralg ssh_aes128_cbc;
extern const ssh_cipheralg ssh_aes128_cbc_hw;
extern const ssh_cipheralg ssh_aes128_cbc_sw;
extern const ssh_cipheralg ssh_blowfish_ssh2_ctr;
extern const ssh_cipheralg ssh_blowfish_ssh2;
extern const ssh_cipheralg ssh_arcfour256_ssh2;
extern const ssh_cipheralg ssh_arcfour128_ssh2;
extern const ssh_cipheralg ssh2_chacha20_poly1305;
extern const ssh2_ciphers ssh2_3des;
extern const ssh2_ciphers ssh2_des;
extern const ssh2_ciphers ssh2_aes;
@@ -944,6 +926,14 @@ extern const ssh2_macalg ssh_hmac_sha256;
extern const ssh2_macalg ssh2_poly1305;
extern const ssh_compression_alg ssh_zlib;
/*
* On some systems, you have to detect hardware crypto acceleration by
* asking the local OS API rather than OS-agnostically asking the CPU
* itself. If so, then this function should be implemented in each
* platform subdirectory.
*/
bool platform_aes_hw_available(void);
/*
* PuTTY version number formatted as an SSH version string.
*/

View File

@@ -13,13 +13,14 @@ struct ssh1_bpp_state {
int crState;
long len, pad, biglen, length, maxlen;
unsigned char *data;
unsigned long realcrc, gotcrc;
uint32_t realcrc, gotcrc;
int chunk;
PktIn *pktin;
ssh1_cipher *cipher;
ssh_cipher *cipher_in, *cipher_out;
struct crcda_ctx *crcda_ctx;
uint8_t iv[8]; /* for crcda */
bool pending_compression_request;
ssh_compressor *compctx;
@@ -56,8 +57,10 @@ BinaryPacketProtocol *ssh1_bpp_new(LogContext *logctx)
static void ssh1_bpp_free(BinaryPacketProtocol *bpp)
{
struct ssh1_bpp_state *s = container_of(bpp, struct ssh1_bpp_state, bpp);
if (s->cipher)
ssh1_cipher_free(s->cipher);
if (s->cipher_in)
ssh_cipher_free(s->cipher_in);
if (s->cipher_out)
ssh_cipher_free(s->cipher_out);
if (s->compctx)
ssh_compressor_free(s->compctx);
if (s->decompctx)
@@ -69,23 +72,32 @@ static void ssh1_bpp_free(BinaryPacketProtocol *bpp)
}
void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
const ssh1_cipheralg *cipher,
const ssh_cipheralg *cipher,
const void *session_key)
{
struct ssh1_bpp_state *s;
assert(bpp->vt == &ssh1_bpp_vtable);
s = container_of(bpp, struct ssh1_bpp_state, bpp);
assert(!s->cipher);
assert(!s->cipher_in);
assert(!s->cipher_out);
if (cipher) {
s->cipher = ssh1_cipher_new(cipher);
ssh1_cipher_sesskey(s->cipher, session_key);
s->cipher_in = ssh_cipher_new(cipher);
s->cipher_out = ssh_cipher_new(cipher);
ssh_cipher_setkey(s->cipher_in, session_key);
ssh_cipher_setkey(s->cipher_out, session_key);
assert(!s->crcda_ctx);
s->crcda_ctx = crcda_make_context();
bpp_logevent("Initialised %s encryption", cipher->text_name);
memset(s->iv, 0, sizeof(s->iv));
assert(cipher->blksize <= sizeof(s->iv));
ssh_cipher_setiv(s->cipher_in, s->iv);
ssh_cipher_setiv(s->cipher_out, s->iv);
}
}
@@ -154,17 +166,21 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
BPP_READ(s->data, s->biglen);
if (s->cipher && detect_attack(s->crcda_ctx,
s->data, s->biglen, NULL)) {
if (s->cipher_in && detect_attack(s->crcda_ctx,
s->data, s->biglen, s->iv)) {
ssh_sw_abort(s->bpp.ssh,
"Network attack (CRC compensation) detected!");
crStopV;
}
/* Save the last cipher block, to be passed to the next call
* to detect_attack */
assert(s->biglen >= 8);
memcpy(s->iv, s->data + s->biglen - 8, sizeof(s->iv));
if (s->cipher)
ssh1_cipher_decrypt(s->cipher, s->data, s->biglen);
if (s->cipher_in)
ssh_cipher_decrypt(s->cipher_in, s->data, s->biglen);
s->realcrc = crc32_compute(s->data, s->biglen - 4);
s->realcrc = crc32_ssh1(make_ptrlen(s->data, s->biglen - 4));
s->gotcrc = GET_32BIT(s->data + s->biglen - 4);
if (s->gotcrc != s->realcrc) {
ssh_sw_abort(s->bpp.ssh, "Incorrect CRC received on packet");
@@ -280,7 +296,7 @@ static PktOut *ssh1_bpp_new_pktout(int pkt_type)
static void ssh1_bpp_format_packet(struct ssh1_bpp_state *s, PktOut *pkt)
{
int pad, biglen, i, pktoffs;
unsigned long crc;
uint32_t crc;
int len;
if (s->bpp.logctx) {
@@ -315,13 +331,13 @@ static void ssh1_bpp_format_packet(struct ssh1_bpp_state *s, PktOut *pkt)
for (i = pktoffs; i < 4+8; i++)
pkt->data[i] = random_byte();
crc = crc32_compute(pkt->data + pktoffs + 4,
biglen - 4); /* all ex len */
crc = crc32_ssh1(
make_ptrlen(pkt->data + pktoffs + 4, biglen - 4)); /* all ex len */
PUT_32BIT(pkt->data + pktoffs + 4 + biglen - 4, crc);
PUT_32BIT(pkt->data + pktoffs, len);
if (s->cipher)
ssh1_cipher_encrypt(s->cipher, pkt->data + pktoffs + 4, biglen);
if (s->cipher_out)
ssh_cipher_encrypt(s->cipher_out, pkt->data + pktoffs + 4, biglen);
bufchain_add(s->bpp.out_raw, pkt->data + pktoffs,
biglen + 4); /* len(length+padding+type+data+CRC) */

View File

@@ -50,6 +50,7 @@ struct ssh1_connection_state {
struct outstanding_succfail *succfail_head, *succfail_tail;
bool compressing; /* used in server mode only */
bool sent_exit_status; /* also for server mode */
ConnectionLayer cl;
PacketProtocolLayer ppl;

View File

@@ -362,9 +362,9 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
ssh_bpp_handle_output(s->ppl.bpp);
{
const ssh1_cipheralg *cipher =
(s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh1_blowfish :
s->cipher_type == SSH_CIPHER_DES ? &ssh1_des : &ssh1_3des);
const ssh_cipheralg *cipher =
(s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
s->cipher_type == SSH_CIPHER_DES ? &ssh_des : &ssh_3des_ssh1);
ssh1_bpp_new_cipher(s->ppl.bpp, cipher, s->session_key);
}

View File

@@ -11,7 +11,7 @@
struct ssh2_bpp_direction {
unsigned long sequence;
ssh2_cipher *cipher;
ssh_cipher *cipher;
ssh2_mac *mac;
bool etm_mode;
const ssh_compression_alg *pending_compression;
@@ -73,7 +73,7 @@ static void ssh2_bpp_free_outgoing_crypto(struct ssh2_bpp_state *s)
* We must free the MAC before the cipher, because sometimes the
* MAC is not actually separately allocated but just a different
* facet of the same object as the cipher, in which case
* ssh2_mac_free does nothing and ssh2_cipher_free does the actual
* ssh2_mac_free does nothing and ssh_cipher_free does the actual
* freeing. So if we freed the cipher first and then tried to
* dereference the MAC's vtable pointer to find out how to free
* that too, we'd be accessing freed memory.
@@ -81,7 +81,7 @@ static void ssh2_bpp_free_outgoing_crypto(struct ssh2_bpp_state *s)
if (s->out.mac)
ssh2_mac_free(s->out.mac);
if (s->out.cipher)
ssh2_cipher_free(s->out.cipher);
ssh_cipher_free(s->out.cipher);
if (s->out_comp)
ssh_compressor_free(s->out_comp);
}
@@ -92,7 +92,7 @@ static void ssh2_bpp_free_incoming_crypto(struct ssh2_bpp_state *s)
if (s->in.mac)
ssh2_mac_free(s->in.mac);
if (s->in.cipher)
ssh2_cipher_free(s->in.cipher);
ssh_cipher_free(s->in.cipher);
if (s->in_decomp)
ssh_decompressor_free(s->in_decomp);
}
@@ -109,7 +109,7 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp)
void ssh2_bpp_new_outgoing_crypto(
BinaryPacketProtocol *bpp,
const ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const ssh_cipheralg *cipher, const void *ckey, const void *iv,
const ssh2_macalg *mac, bool etm_mode, const void *mac_key,
const ssh_compression_alg *compression, bool delayed_compression)
{
@@ -120,16 +120,16 @@ void ssh2_bpp_new_outgoing_crypto(
ssh2_bpp_free_outgoing_crypto(s);
if (cipher) {
s->out.cipher = ssh2_cipher_new(cipher);
ssh2_cipher_setkey(s->out.cipher, ckey);
ssh2_cipher_setiv(s->out.cipher, iv);
s->out.cipher = ssh_cipher_new(cipher);
ssh_cipher_setkey(s->out.cipher, ckey);
ssh_cipher_setiv(s->out.cipher, iv);
s->cbc_ignore_workaround = (
(ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_IS_CBC) &&
(ssh_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_IS_CBC) &&
!(s->bpp.remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE));
bpp_logevent("Initialised %s outbound encryption",
ssh2_cipher_alg(s->out.cipher)->text_name);
ssh_cipher_alg(s->out.cipher)->text_name);
} else {
s->out.cipher = NULL;
s->cbc_ignore_workaround = false;
@@ -143,7 +143,7 @@ void ssh2_bpp_new_outgoing_crypto(
ssh2_mac_alg(s->out.mac)->text_name,
etm_mode ? " (in ETM mode)" : "",
(s->out.cipher &&
ssh2_cipher_alg(s->out.cipher)->required_mac ?
ssh_cipher_alg(s->out.cipher)->required_mac ?
" (required by cipher)" : ""));
} else {
s->out.mac = NULL;
@@ -171,7 +171,7 @@ void ssh2_bpp_new_outgoing_crypto(
void ssh2_bpp_new_incoming_crypto(
BinaryPacketProtocol *bpp,
const ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const ssh_cipheralg *cipher, const void *ckey, const void *iv,
const ssh2_macalg *mac, bool etm_mode, const void *mac_key,
const ssh_compression_alg *compression, bool delayed_compression)
{
@@ -182,12 +182,12 @@ void ssh2_bpp_new_incoming_crypto(
ssh2_bpp_free_incoming_crypto(s);
if (cipher) {
s->in.cipher = ssh2_cipher_new(cipher);
ssh2_cipher_setkey(s->in.cipher, ckey);
ssh2_cipher_setiv(s->in.cipher, iv);
s->in.cipher = ssh_cipher_new(cipher);
ssh_cipher_setkey(s->in.cipher, ckey);
ssh_cipher_setiv(s->in.cipher, iv);
bpp_logevent("Initialised %s inbound encryption",
ssh2_cipher_alg(s->in.cipher)->text_name);
ssh_cipher_alg(s->in.cipher)->text_name);
} else {
s->in.cipher = NULL;
}
@@ -200,7 +200,7 @@ void ssh2_bpp_new_incoming_crypto(
ssh2_mac_alg(s->in.mac)->text_name,
etm_mode ? " (in ETM mode)" : "",
(s->in.cipher &&
ssh2_cipher_alg(s->in.cipher)->required_mac ?
ssh_cipher_alg(s->in.cipher)->required_mac ?
" (required by cipher)" : ""));
} else {
s->in.mac = NULL;
@@ -283,7 +283,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
s->maxlen = 0;
s->length = 0;
if (s->in.cipher)
s->cipherblk = ssh2_cipher_alg(s->in.cipher)->blksize;
s->cipherblk = ssh_cipher_alg(s->in.cipher)->blksize;
else
s->cipherblk = 8;
if (s->cipherblk < 8)
@@ -291,7 +291,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
s->maclen = s->in.mac ? ssh2_mac_alg(s->in.mac)->len : 0;
if (s->in.cipher &&
(ssh2_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) &&
(ssh_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) &&
s->in.mac && !s->in.etm_mode) {
/*
* When dealing with a CBC-mode cipher, we want to avoid the
@@ -333,8 +333,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
BPP_READ(s->buf + (s->packetlen + s->maclen), s->cipherblk);
/* Decrypt one more block (a little further back in
* the stream). */
ssh2_cipher_decrypt(s->in.cipher,
s->buf + s->packetlen, s->cipherblk);
ssh_cipher_decrypt(s->in.cipher,
s->buf + s->packetlen, s->cipherblk);
/* Feed that block to the MAC. */
put_data(s->in.mac,
@@ -376,12 +376,12 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
BPP_READ(s->buf, 4);
/* Cipher supports length decryption, so do it */
if (s->in.cipher && (ssh2_cipher_alg(s->in.cipher)->flags &
if (s->in.cipher && (ssh_cipher_alg(s->in.cipher)->flags &
SSH_CIPHER_SEPARATE_LENGTH)) {
/* Keep the packet the same though, so the MAC passes */
unsigned char len[4];
memcpy(len, s->buf, 4);
ssh2_cipher_decrypt_length(
ssh_cipher_decrypt_length(
s->in.cipher, len, 4, s->in.sequence);
s->len = toint(GET_32BIT(len));
} else {
@@ -430,7 +430,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
/* Decrypt everything between the length field and the MAC. */
if (s->in.cipher)
ssh2_cipher_decrypt(
ssh_cipher_decrypt(
s->in.cipher, s->data + 4, s->packetlen - 4);
} else {
if (s->bufsize < s->cipherblk) {
@@ -445,8 +445,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
BPP_READ(s->buf, s->cipherblk);
if (s->in.cipher)
ssh2_cipher_decrypt(
s->in.cipher, s->buf, s->cipherblk);
ssh_cipher_decrypt(s->in.cipher, s->buf, s->cipherblk);
/*
* Now get the length figure.
@@ -488,7 +487,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
/* Decrypt everything _except_ the MAC. */
if (s->in.cipher)
ssh2_cipher_decrypt(
ssh_cipher_decrypt(
s->in.cipher,
s->data + s->cipherblk, s->packetlen - s->cipherblk);
@@ -684,7 +683,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
pkt->downstream_id, pkt->additional_log_text);
}
cipherblk = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 8;
cipherblk = s->out.cipher ? ssh_cipher_alg(s->out.cipher)->blksize : 8;
cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
if (s->out_comp) {
@@ -733,9 +732,9 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
/* Encrypt length if the scheme requires it */
if (s->out.cipher &&
(ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_SEPARATE_LENGTH)) {
ssh2_cipher_encrypt_length(s->out.cipher, pkt->data, 4,
s->out.sequence);
(ssh_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_SEPARATE_LENGTH)) {
ssh_cipher_encrypt_length(s->out.cipher, pkt->data, 4,
s->out.sequence);
}
put_padding(pkt, maclen, 0);
@@ -745,8 +744,8 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
* OpenSSH-defined encrypt-then-MAC protocol.
*/
if (s->out.cipher)
ssh2_cipher_encrypt(s->out.cipher,
pkt->data + 4, origlen + padding - 4);
ssh_cipher_encrypt(s->out.cipher,
pkt->data + 4, origlen + padding - 4);
ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
s->out.sequence);
} else {
@@ -757,7 +756,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
s->out.sequence);
if (s->out.cipher)
ssh2_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding);
ssh_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding);
}
s->out.sequence++; /* whether or not we MACed */
@@ -791,7 +790,7 @@ static void ssh2_bpp_format_packet(struct ssh2_bpp_state *s, PktOut *pkt)
int block, length;
PktOut *ignore_pkt;
block = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 0;
block = s->out.cipher ? ssh_cipher_alg(s->out.cipher)->blksize : 0;
if (block < 8)
block = 8;
length = pkt->length;
@@ -874,7 +873,7 @@ static void ssh2_bpp_handle_output(BinaryPacketProtocol *bpp)
* from out_raw).
*/
if (bufchain_size(s->bpp.out_raw) <
(ssh2_cipher_alg(s->out.cipher)->blksize +
(ssh_cipher_alg(s->out.cipher)->blksize +
ssh2_mac_alg(s->out.mac)->len)) {
/*
* There's less data in out_raw than the MAC size plus the

View File

@@ -657,7 +657,7 @@ static void ssh2_write_kexinit_lists(
if (!c) warn = true;
else for (j = 0; j < c->nciphers; j++) {
alg = ssh2_kexinit_addalg(kexlists[k],
c->list[j]->name);
c->list[j]->ssh2_id);
alg->u.cipher.cipher = c->list[j];
alg->u.cipher.warn = warn;
}
@@ -1208,7 +1208,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
if (s->warn_cscipher) {
s->dlgret = seat_confirm_weak_crypto_primitive(
s->ppl.seat, "client-to-server cipher", s->out.cipher->name,
s->ppl.seat, "client-to-server cipher", s->out.cipher->ssh2_id,
ssh2_transport_dialog_callback, s);
crMaybeWaitUntilV(s->dlgret >= 0);
if (s->dlgret == 0) {
@@ -1219,7 +1219,7 @@ static void ssh2_transport_process_queue(PacketProtocolLayer *ppl)
if (s->warn_sccipher) {
s->dlgret = seat_confirm_weak_crypto_primitive(
s->ppl.seat, "server-to-client cipher", s->in.cipher->name,
s->ppl.seat, "server-to-client cipher", s->in.cipher->ssh2_id,
ssh2_transport_dialog_callback, s);
crMaybeWaitUntilV(s->dlgret >= 0);
if (s->dlgret == 0) {

View File

@@ -36,7 +36,7 @@ struct kexinit_algorithm {
bool warn;
} hk;
struct {
const ssh2_cipheralg *cipher;
const ssh_cipheralg *cipher;
bool warn;
} cipher;
struct {
@@ -104,7 +104,7 @@ typedef enum RekeyClass {
} RekeyClass;
typedef struct transport_direction {
const ssh2_cipheralg *cipher;
const ssh_cipheralg *cipher;
const ssh2_macalg *mac;
bool etm_mode;
const ssh_compression_alg *comp;

501
source/putty/sshaes.c vendored
View File

@@ -13,6 +13,7 @@
*/
#define HW_AES_NONE 0
#define HW_AES_NI 1
#define HW_AES_NEON 2
#ifdef _FORCE_AES_NI
# define HW_AES HW_AES_NI
@@ -34,6 +35,37 @@
#define HW_AES HW_AES_NI // WINSCP
#ifdef _FORCE_AES_NEON
# define HW_AES HW_AES_NEON
#elif defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* Arm can potentially support both endiannesses, but this code
* hasn't been tested on anything but little. If anyone wants to
* run big-endian, they'll need to fix it first. */
#elif defined __ARM_FEATURE_CRYPTO
/* If the Arm crypto extension is available already, we can
* support NEON AES without having to enable anything by hand */
# define HW_AES HW_AES_NEON
#elif defined(__clang__)
# if __has_attribute(target) && __has_include(<arm_neon.h>) && \
(defined(__aarch64__))
/* clang can enable the crypto extension in AArch64 using
* __attribute__((target)) */
# define HW_AES HW_AES_NEON
# define USE_CLANG_ATTR_TARGET_AARCH64
# endif
#elif defined _MSC_VER
/* Visual Studio supports the crypto extension when targeting
* AArch64, but as of VS2017, the AArch32 header doesn't quite
* manage it (declaring the aese/aesd intrinsics without a round
* key operand). */
# if defined _M_ARM64
# define HW_AES HW_AES_NEON
# if defined _M_ARM64
# define USE_ARM64_NEON_H /* unusual header name in this case */
# endif
# endif
#endif
#if defined _FORCE_SOFTWARE_AES || !defined HW_AES
# undef HW_AES
# define HW_AES HW_AES_NONE
@@ -41,6 +73,8 @@
#if HW_AES == HW_AES_NI
#define HW_NAME_SUFFIX " (AES-NI accelerated)"
#elif HW_AES == HW_AES_NEON
#define HW_NAME_SUFFIX " (NEON accelerated)"
#else
#define HW_NAME_SUFFIX " (!NONEXISTENT ACCELERATED VERSION!)"
#endif
@@ -55,35 +89,35 @@
* instance of.
*/
static ssh2_cipher *aes_select(const ssh2_cipheralg *alg);
static ssh2_cipher *aes_sw_new(const ssh2_cipheralg *alg);
static void aes_sw_free(ssh2_cipher *);
static void aes_sw_setiv_cbc(ssh2_cipher *, const void *iv);
static void aes_sw_setiv_sdctr(ssh2_cipher *, const void *iv);
static void aes_sw_setkey(ssh2_cipher *, const void *key);
/*WINSCP static*/ ssh2_cipher *aes_hw_new(const ssh2_cipheralg *alg);
/*WINSCP static*/ void aes_hw_free(ssh2_cipher *);
/*WINSCP static*/ void aes_hw_setiv_cbc(ssh2_cipher *, const void *iv);
/*WINSCP static*/ void aes_hw_setiv_sdctr(ssh2_cipher *, const void *iv);
/*WINSCP static*/ void aes_hw_setkey(ssh2_cipher *, const void *key);
static ssh_cipher *aes_select(const ssh_cipheralg *alg);
static ssh_cipher *aes_sw_new(const ssh_cipheralg *alg);
static void aes_sw_free(ssh_cipher *);
static void aes_sw_setiv_cbc(ssh_cipher *, const void *iv);
static void aes_sw_setiv_sdctr(ssh_cipher *, const void *iv);
static void aes_sw_setkey(ssh_cipher *, const void *key);
/*WINSCP static*/ ssh_cipher *aes_hw_new(const ssh_cipheralg *alg);
/*WINSCP static*/ void aes_hw_free(ssh_cipher *);
/*WINSCP static*/ void aes_hw_setiv_cbc(ssh_cipher *, const void *iv);
/*WINSCP static*/ void aes_hw_setiv_sdctr(ssh_cipher *, const void *iv);
/*WINSCP static*/ void aes_hw_setkey(ssh_cipher *, const void *key);
#ifndef WINSCP_VS
struct aes_extra {
const ssh2_cipheralg *sw, *hw;
const ssh_cipheralg *sw, *hw;
};
#define VTABLES(cid, pid, bits, name, encsuffix, decsuffix, setiv) \
/*WINSCP static */void cid##_sw##encsuffix(ssh2_cipher *, void *blk, int len); \
/*WINSCP static */void cid##_sw##decsuffix(ssh2_cipher *, void *blk, int len); \
const ssh2_cipheralg ssh_##cid##_sw = { \
/*WINSCP static */void cid##_sw##encsuffix(ssh_cipher *, void *blk, int len); \
/*WINSCP static */void cid##_sw##decsuffix(ssh_cipher *, void *blk, int len); \
const ssh_cipheralg ssh_##cid##_sw = { \
aes_sw_new, aes_sw_free, aes_sw_##setiv, aes_sw_setkey, \
cid##_sw##encsuffix, cid##_sw##decsuffix, NULL, NULL, \
pid, 16, bits, bits/8, 0, name " (unaccelerated)", \
NULL, NULL }; \
\
/*WINSCP static*/ void cid##_hw##encsuffix(ssh2_cipher *, void *blk, int len); \
/*WINSCP static*/ void cid##_hw##decsuffix(ssh2_cipher *, void *blk, int len); \
const ssh2_cipheralg ssh_##cid##_hw = { \
/*WINSCP static*/ void cid##_hw##encsuffix(ssh_cipher *, void *blk, int len); \
/*WINSCP static*/ void cid##_hw##decsuffix(ssh_cipher *, void *blk, int len); \
const ssh_cipheralg ssh_##cid##_hw = { \
aes_hw_new, aes_hw_free, aes_hw_##setiv, aes_hw_setkey, \
cid##_hw##encsuffix, cid##_hw##decsuffix, NULL, NULL, \
pid, 16, bits, bits/8, 0, name HW_NAME_SUFFIX, \
@@ -92,7 +126,7 @@ struct aes_extra {
const struct aes_extra extra_##cid = { \
&ssh_##cid##_sw, &ssh_##cid##_hw }; \
\
const ssh2_cipheralg ssh_##cid = { \
const ssh_cipheralg ssh_##cid = { \
aes_select, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
pid, 16, bits, bits/8, 0, name " (dummy selector vtable)", \
NULL, &extra_##cid }; \
@@ -104,14 +138,14 @@ VTABLES(aes128_sdctr, "aes128-ctr", 128, "AES-128 SDCTR",,, setiv_sdctr)
VTABLES(aes192_sdctr, "aes192-ctr", 192, "AES-192 SDCTR",,, setiv_sdctr)
VTABLES(aes256_sdctr, "aes256-ctr", 256, "AES-256 SDCTR",,, setiv_sdctr)
static const ssh2_cipheralg ssh_rijndael_lysator = {
static const ssh_cipheralg ssh_rijndael_lysator = {
/* Same as aes256_cbc, but with a different protocol ID */
aes_select, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"rijndael-cbc@lysator.liu.se", 16, 256, 256/8, 0,
"AES-256 CBC (dummy selector vtable)", NULL, &extra_aes256_cbc
};
static const ssh2_cipheralg *const aes_list[] = {
static const ssh_cipheralg *const aes_list[] = {
&ssh_aes256_sdctr,
&ssh_aes256_cbc,
&ssh_rijndael_lysator,
@@ -138,19 +172,21 @@ static bool aes_hw_available_cached(void)
{
static bool initialised = false;
static bool hw_available;
if (!initialised)
if (!initialised) {
hw_available = aes_hw_available();
initialised = true;
}
return hw_available;
}
#ifndef WINSCP_VS
static ssh2_cipher *aes_select(const ssh2_cipheralg *alg)
static ssh_cipher *aes_select(const ssh_cipheralg *alg)
{
const struct aes_extra *extra = (const struct aes_extra *)alg->extra;
const ssh2_cipheralg *real_alg =
const ssh_cipheralg *real_alg =
aes_hw_available_cached() ? extra->hw : extra->sw;
return ssh2_cipher_new(real_alg);
return ssh_cipher_new(real_alg);
}
#endif
@@ -968,38 +1004,38 @@ struct aes_sw_context {
uint8_t *keystream_pos;
} sdctr;
} iv;
ssh2_cipher ciph;
ssh_cipher ciph;
};
#ifndef WINSCP_VS
static ssh2_cipher *aes_sw_new(const ssh2_cipheralg *alg)
static ssh_cipher *aes_sw_new(const ssh_cipheralg *alg)
{
aes_sw_context *ctx = snew(aes_sw_context);
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static void aes_sw_free(ssh2_cipher *ciph)
static void aes_sw_free(ssh_cipher *ciph)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void aes_sw_setkey(ssh2_cipher *ciph, const void *vkey)
static void aes_sw_setkey(ssh_cipher *ciph, const void *vkey)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
aes_sliced_key_setup(&ctx->sk, vkey, ctx->ciph.vt->real_keybits);
}
static void aes_sw_setiv_cbc(ssh2_cipher *ciph, const void *iv)
static void aes_sw_setiv_cbc(ssh_cipher *ciph, const void *iv)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
memcpy(ctx->iv.cbc.prevblk, iv, 16);
}
static void aes_sw_setiv_sdctr(ssh2_cipher *ciph, const void *viv)
static void aes_sw_setiv_sdctr(ssh_cipher *ciph, const void *viv)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
const uint8_t *iv = (const uint8_t *)viv;
@@ -1038,7 +1074,7 @@ static inline void memxor16(void *vout, const void *vlhs, const void *vrhs)
}
static inline void aes_cbc_sw_encrypt(
ssh2_cipher *ciph, void *vblk, int blklen)
ssh_cipher *ciph, void *vblk, int blklen)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
@@ -1069,7 +1105,7 @@ static inline void aes_cbc_sw_encrypt(
}
static inline void aes_cbc_sw_decrypt(
ssh2_cipher *ciph, void *vblk, int blklen)
ssh_cipher *ciph, void *vblk, int blklen)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
uint8_t *blk = (uint8_t *)vblk;
@@ -1120,7 +1156,7 @@ static inline void aes_cbc_sw_decrypt(
}
static inline void aes_sdctr_sw(
ssh2_cipher *ciph, void *vblk, int blklen)
ssh_cipher *ciph, void *vblk, int blklen)
{
aes_sw_context *ctx = container_of(ciph, aes_sw_context, ciph);
@@ -1170,13 +1206,13 @@ static inline void aes_sdctr_sw(
#define SW_ENC_DEC(len) \
/*WINSCP static*/ void aes##len##_cbc_sw_encrypt( \
ssh2_cipher *ciph, void *vblk, int blklen) \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_cbc_sw_encrypt(ciph, vblk, blklen); } \
/*WINSCP static*/ void aes##len##_cbc_sw_decrypt( \
ssh2_cipher *ciph, void *vblk, int blklen) \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_cbc_sw_decrypt(ciph, vblk, blklen); } \
/*WINSCP static*/ void aes##len##_sdctr_sw( \
ssh2_cipher *ciph, void *vblk, int blklen) \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_sdctr_sw(ciph, vblk, blklen); }
SW_ENC_DEC(128)
@@ -1372,10 +1408,10 @@ struct aes_ni_context {
__m128i keysched_e[MAXROUNDKEYS], keysched_d[MAXROUNDKEYS], iv;
void *pointer_to_free;
ssh2_cipher ciph;
ssh_cipher ciph;
};
/*static WINSCP*/ ssh2_cipher *aes_hw_new(const ssh2_cipheralg *alg)
/*static WINSCP*/ ssh_cipher *aes_hw_new(const ssh_cipheralg *alg)
{
if (!aes_hw_available_cached())
return NULL;
@@ -1398,7 +1434,7 @@ struct aes_ni_context {
return &ctx->ciph;
}
/*static WINSCP*/ void aes_hw_free(ssh2_cipher *ciph)
/*static WINSCP*/ void aes_hw_free(ssh_cipher *ciph)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
void *allocation = ctx->pointer_to_free;
@@ -1406,7 +1442,7 @@ struct aes_ni_context {
sfree(allocation);
}
/*static WINSCP*/ void aes_hw_setkey(ssh2_cipher *ciph, const void *vkey)
/*static WINSCP*/ void aes_hw_setkey(ssh_cipher *ciph, const void *vkey)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
const unsigned char *key = (const unsigned char *)vkey;
@@ -1415,13 +1451,13 @@ struct aes_ni_context {
ctx->keysched_e, ctx->keysched_d);
}
/*static WINSCP*/ FUNC_ISA void aes_hw_setiv_cbc(ssh2_cipher *ciph, const void *iv)
/*static WINSCP*/ FUNC_ISA void aes_hw_setiv_cbc(ssh_cipher *ciph, const void *iv)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
ctx->iv = _mm_loadu_si128(iv);
}
/*static WINSCP*/ FUNC_ISA void aes_hw_setiv_sdctr(ssh2_cipher *ciph, const void *iv)
/*static WINSCP*/ FUNC_ISA void aes_hw_setiv_sdctr(ssh_cipher *ciph, const void *iv)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
__m128i counter = _mm_loadu_si128(iv);
@@ -1431,7 +1467,7 @@ struct aes_ni_context {
typedef __m128i (*aes_ni_fn)(__m128i v, const __m128i *keysched);
static FUNC_ISA inline void aes_cbc_ni_encrypt(
ssh2_cipher *ciph, void *vblk, int blklen, aes_ni_fn encrypt)
ssh_cipher *ciph, void *vblk, int blklen, aes_ni_fn encrypt)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
@@ -1446,7 +1482,7 @@ static FUNC_ISA inline void aes_cbc_ni_encrypt(
}
static FUNC_ISA inline void aes_cbc_ni_decrypt(
ssh2_cipher *ciph, void *vblk, int blklen, aes_ni_fn decrypt)
ssh_cipher *ciph, void *vblk, int blklen, aes_ni_fn decrypt)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
@@ -1461,7 +1497,7 @@ static FUNC_ISA inline void aes_cbc_ni_decrypt(
}
static FUNC_ISA inline void aes_sdctr_ni(
ssh2_cipher *ciph, void *vblk, int blklen, aes_ni_fn encrypt)
ssh_cipher *ciph, void *vblk, int blklen, aes_ni_fn encrypt)
{
aes_ni_context *ctx = container_of(ciph, aes_ni_context, ciph);
@@ -1478,13 +1514,13 @@ static FUNC_ISA inline void aes_sdctr_ni(
#define NI_ENC_DEC(len) \
/*static WINSCP*/ FUNC_ISA void aes##len##_cbc_hw_encrypt( \
ssh2_cipher *ciph, void *vblk, int blklen) \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_cbc_ni_encrypt(ciph, vblk, blklen, aes_ni_##len##_e); } \
/*static WINSCP*/ FUNC_ISA void aes##len##_cbc_hw_decrypt( \
ssh2_cipher *ciph, void *vblk, int blklen) \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_cbc_ni_decrypt(ciph, vblk, blklen, aes_ni_##len##_d); } \
/*static WINSCP*/ FUNC_ISA void aes##len##_sdctr_hw( \
ssh2_cipher *ciph, void *vblk, int blklen) \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_sdctr_ni(ciph, vblk, blklen, aes_ni_##len##_e); } \
NI_ENC_DEC(128)
@@ -1493,6 +1529,317 @@ NI_ENC_DEC(256)
#endif // WINSCP_VS
/* ----------------------------------------------------------------------
* Hardware-accelerated implementation of AES using Arm NEON.
*/
#elif HW_AES == HW_AES_NEON
/*
* Manually set the target architecture, if we decided above that we
* need to.
*/
#ifdef USE_CLANG_ATTR_TARGET_AARCH64
/*
* A spot of cheating: redefine some ACLE feature macros before
* including arm_neon.h. Otherwise we won't get the AES intrinsics
* defined by that header, because it will be looking at the settings
* for the whole translation unit rather than the ones we're going to
* put on some particular functions using __attribute__((target)).
*/
#define __ARM_NEON 1
#define __ARM_FEATURE_CRYPTO 1
#define FUNC_ISA __attribute__ ((target("neon,crypto")))
#endif /* USE_CLANG_ATTR_TARGET_AARCH64 */
#ifndef FUNC_ISA
#define FUNC_ISA
#endif
#ifdef USE_ARM64_NEON_H
#include <arm64_neon.h>
#else
#include <arm_neon.h>
#endif
static bool aes_hw_available(void)
{
/*
* For Arm, we delegate to a per-platform AES detection function,
* because it has to be implemented by asking the operating system
* rather than directly querying the CPU.
*
* That's because Arm systems commonly have multiple cores that
* are not all alike, so any method of querying whether NEON
* crypto instructions work on the _current_ CPU - even one as
* crude as just trying one and catching the SIGILL - wouldn't
* give an answer that you could still rely on the first time the
* OS migrated your process to another CPU.
*/
return platform_aes_hw_available();
}
/*
* Core NEON encrypt/decrypt functions, one per length and direction.
*/
#define NEON_CIPHER(len, repmacro) \
static FUNC_ISA inline uint8x16_t aes_neon_##len##_e( \
uint8x16_t v, const uint8x16_t *keysched) \
{ \
repmacro(v = vaesmcq_u8(vaeseq_u8(v, *keysched++));); \
v = vaeseq_u8(v, *keysched++); \
return veorq_u8(v, *keysched); \
} \
static FUNC_ISA inline uint8x16_t aes_neon_##len##_d( \
uint8x16_t v, const uint8x16_t *keysched) \
{ \
repmacro(v = vaesimcq_u8(vaesdq_u8(v, *keysched++));); \
v = vaesdq_u8(v, *keysched++); \
return veorq_u8(v, *keysched); \
}
NEON_CIPHER(128, REP9)
NEON_CIPHER(192, REP11)
NEON_CIPHER(256, REP13)
/*
* The main key expansion.
*/
static FUNC_ISA void aes_neon_key_expand(
const unsigned char *key, size_t key_words,
uint8x16_t *keysched_e, uint8x16_t *keysched_d)
{
size_t rounds = key_words + 6;
size_t sched_words = (rounds + 1) * 4;
/*
* Store the key schedule as 32-bit integers during expansion, so
* that it's easy to refer back to individual previous words. We
* collect them into the final uint8x16_t form at the end.
*/
uint32_t sched[MAXROUNDKEYS * 4];
unsigned rconpos = 0;
for (size_t i = 0; i < sched_words; i++) {
if (i < key_words) {
sched[i] = GET_32BIT_LSB_FIRST(key + 4 * i);
} else {
uint32_t temp = sched[i - 1];
bool rotate_and_round_constant = (i % key_words == 0);
bool sub = rotate_and_round_constant ||
(key_words == 8 && i % 8 == 4);
if (rotate_and_round_constant)
temp = (temp << 24) | (temp >> 8);
if (sub) {
uint32x4_t v32 = vdupq_n_u32(temp);
uint8x16_t v8 = vreinterpretq_u8_u32(v32);
v8 = vaeseq_u8(v8, vdupq_n_u8(0));
v32 = vreinterpretq_u32_u8(v8);
temp = vget_lane_u32(vget_low_u32(v32), 0);
}
if (rotate_and_round_constant) {
assert(rconpos < lenof(key_setup_round_constants));
temp ^= key_setup_round_constants[rconpos++];
}
sched[i] = sched[i - key_words] ^ temp;
}
}
/*
* Combine the key schedule words into uint8x16_t vectors and
* store them in the output context.
*/
for (size_t round = 0; round <= rounds; round++)
keysched_e[round] = vreinterpretq_u8_u32(vld1q_u32(sched + 4*round));
smemclr(sched, sizeof(sched));
/*
* Now prepare the modified keys for the inverse cipher.
*/
for (size_t eround = 0; eround <= rounds; eround++) {
size_t dround = rounds - eround;
uint8x16_t rkey = keysched_e[eround];
if (eround && dround) /* neither first nor last */
rkey = vaesimcq_u8(rkey);
keysched_d[dround] = rkey;
}
}
/*
* Auxiliary routine to reverse the byte order of a vector, so that
* the SDCTR IV can be made big-endian for feeding to the cipher.
*
* In fact we don't need to reverse the vector _all_ the way; we leave
* the two lanes in MSW,LSW order, because that makes no difference to
* the efficiency of the increment. That way we only have to reverse
* bytes within each lane in this function.
*/
static FUNC_ISA inline uint8x16_t aes_neon_sdctr_reverse(uint8x16_t v)
{
return vrev64q_u8(v);
}
/*
* Auxiliary routine to increment the 128-bit counter used in SDCTR
* mode. There's no instruction to treat a 128-bit vector as a single
* long integer, so instead we have to increment the bottom half
* unconditionally, and the top half if the bottom half started off as
* all 1s (in which case there was about to be a carry).
*/
static FUNC_ISA inline uint8x16_t aes_neon_sdctr_increment(uint8x16_t in)
{
#ifdef __aarch64__
/* There will be a carry if the low 64 bits are all 1s. */
uint64x1_t all1 = vcreate_u64(0xFFFFFFFFFFFFFFFF);
uint64x1_t carry = vceq_u64(vget_high_u64(vreinterpretq_u64_u8(in)), all1);
/* Make a word whose bottom half is unconditionally all 1s, and
* the top half is 'carry', i.e. all 0s most of the time but all
* 1s if we need to increment the top half. Then that word is what
* we need to _subtract_ from the input counter. */
uint64x2_t subtrahend = vcombine_u64(carry, all1);
#else
/* AArch32 doesn't have comparisons that operate on a 64-bit lane,
* so we start by comparing each 32-bit half of the low 64 bits
* _separately_ to all-1s. */
uint32x2_t all1 = vdup_n_u32(0xFFFFFFFF);
uint32x2_t carry = vceq_u32(
vget_high_u32(vreinterpretq_u32_u8(in)), all1);
/* Swap the 32-bit words of the compare output, and AND with the
* unswapped version. Now carry is all 1s iff the bottom half of
* the input counter was all 1s, and all 0s otherwise. */
carry = vand_u32(carry, vrev64_u32(carry));
/* Now make the vector to subtract in the same way as above. */
uint64x2_t subtrahend = vreinterpretq_u64_u32(vcombine_u32(carry, all1));
#endif
return vreinterpretq_u8_u64(
vsubq_u64(vreinterpretq_u64_u8(in), subtrahend));
}
/*
* The SSH interface and the cipher modes.
*/
typedef struct aes_neon_context aes_neon_context;
struct aes_neon_context {
uint8x16_t keysched_e[MAXROUNDKEYS], keysched_d[MAXROUNDKEYS], iv;
ssh_cipher ciph;
};
static ssh_cipher *aes_hw_new(const ssh_cipheralg *alg)
{
if (!aes_hw_available_cached())
return NULL;
aes_neon_context *ctx = snew(aes_neon_context);
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static void aes_hw_free(ssh_cipher *ciph)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void aes_hw_setkey(ssh_cipher *ciph, const void *vkey)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
const unsigned char *key = (const unsigned char *)vkey;
aes_neon_key_expand(key, ctx->ciph.vt->real_keybits / 32,
ctx->keysched_e, ctx->keysched_d);
}
static FUNC_ISA void aes_hw_setiv_cbc(ssh_cipher *ciph, const void *iv)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
ctx->iv = vld1q_u8(iv);
}
static FUNC_ISA void aes_hw_setiv_sdctr(ssh_cipher *ciph, const void *iv)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
uint8x16_t counter = vld1q_u8(iv);
ctx->iv = aes_neon_sdctr_reverse(counter);
}
typedef uint8x16_t (*aes_neon_fn)(uint8x16_t v, const uint8x16_t *keysched);
static FUNC_ISA inline void aes_cbc_neon_encrypt(
ssh_cipher *ciph, void *vblk, int blklen, aes_neon_fn encrypt)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
for (uint8_t *blk = (uint8_t *)vblk, *finish = blk + blklen;
blk < finish; blk += 16) {
uint8x16_t plaintext = vld1q_u8(blk);
uint8x16_t cipher_input = veorq_u8(plaintext, ctx->iv);
uint8x16_t ciphertext = encrypt(cipher_input, ctx->keysched_e);
vst1q_u8(blk, ciphertext);
ctx->iv = ciphertext;
}
}
static FUNC_ISA inline void aes_cbc_neon_decrypt(
ssh_cipher *ciph, void *vblk, int blklen, aes_neon_fn decrypt)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
for (uint8_t *blk = (uint8_t *)vblk, *finish = blk + blklen;
blk < finish; blk += 16) {
uint8x16_t ciphertext = vld1q_u8(blk);
uint8x16_t decrypted = decrypt(ciphertext, ctx->keysched_d);
uint8x16_t plaintext = veorq_u8(decrypted, ctx->iv);
vst1q_u8(blk, plaintext);
ctx->iv = ciphertext;
}
}
static FUNC_ISA inline void aes_sdctr_neon(
ssh_cipher *ciph, void *vblk, int blklen, aes_neon_fn encrypt)
{
aes_neon_context *ctx = container_of(ciph, aes_neon_context, ciph);
for (uint8_t *blk = (uint8_t *)vblk, *finish = blk + blklen;
blk < finish; blk += 16) {
uint8x16_t counter = aes_neon_sdctr_reverse(ctx->iv);
uint8x16_t keystream = encrypt(counter, ctx->keysched_e);
uint8x16_t input = vld1q_u8(blk);
uint8x16_t output = veorq_u8(input, keystream);
vst1q_u8(blk, output);
ctx->iv = aes_neon_sdctr_increment(ctx->iv);
}
}
#define NEON_ENC_DEC(len) \
static FUNC_ISA void aes##len##_cbc_hw_encrypt( \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_cbc_neon_encrypt(ciph, vblk, blklen, aes_neon_##len##_e); } \
static FUNC_ISA void aes##len##_cbc_hw_decrypt( \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_cbc_neon_decrypt(ciph, vblk, blklen, aes_neon_##len##_d); } \
static FUNC_ISA void aes##len##_sdctr_hw( \
ssh_cipher *ciph, void *vblk, int blklen) \
{ aes_sdctr_neon(ciph, vblk, blklen, aes_neon_##len##_e); } \
NEON_ENC_DEC(128)
NEON_ENC_DEC(192)
NEON_ENC_DEC(256)
/* ----------------------------------------------------------------------
* Stub functions if we have no hardware-accelerated AES. In this
* case, aes_hw_new returns NULL (though it should also never be
@@ -1508,24 +1855,24 @@ bool aes_hw_available(void)
return false;
}
static ssh2_cipher *aes_hw_new(const ssh2_cipheralg *alg)
static ssh_cipher *aes_hw_new(const ssh_cipheralg *alg)
{
return NULL;
}
#define STUB_BODY { unreachable("Should never be called"); }
static void aes_hw_free(ssh2_cipher *ciph) STUB_BODY
static void aes_hw_setkey(ssh2_cipher *ciph, const void *key) STUB_BODY
static void aes_hw_setiv_cbc(ssh2_cipher *ciph, const void *iv) STUB_BODY
static void aes_hw_setiv_sdctr(ssh2_cipher *ciph, const void *iv) STUB_BODY
#define STUB_ENC_DEC(len) \
static void aes##len##_cbc_hw_encrypt( \
ssh2_cipher *ciph, void *vblk, int blklen) STUB_BODY \
static void aes##len##_cbc_hw_decrypt( \
ssh2_cipher *ciph, void *vblk, int blklen) STUB_BODY \
static void aes##len##_sdctr_hw( \
ssh2_cipher *ciph, void *vblk, int blklen) STUB_BODY
static void aes_hw_free(ssh_cipher *ciph) STUB_BODY
static void aes_hw_setkey(ssh_cipher *ciph, const void *key) STUB_BODY
static void aes_hw_setiv_cbc(ssh_cipher *ciph, const void *iv) STUB_BODY
static void aes_hw_setiv_sdctr(ssh_cipher *ciph, const void *iv) STUB_BODY
#define STUB_ENC_DEC(len) \
static void aes##len##_cbc_hw_encrypt( \
ssh_cipher *ciph, void *vblk, int blklen) STUB_BODY \
static void aes##len##_cbc_hw_decrypt( \
ssh_cipher *ciph, void *vblk, int blklen) STUB_BODY \
static void aes##len##_sdctr_hw( \
ssh_cipher *ciph, void *vblk, int blklen) STUB_BODY
STUB_ENC_DEC(128)
STUB_ENC_DEC(192)
@@ -1533,40 +1880,8 @@ STUB_ENC_DEC(256)
#endif /* HW_AES */
/* ----------------------------------------------------------------------
* Auxiliary routines for use of AES in other contexts than the main
* SSH packet protocol.
*/
#ifndef WINSCP_VS
void aes256_encrypt_pubkey(const void *key, void *blk, int len)
{
char iv[16];
memset(iv, 0, 16);
{ // WINSCP
ssh2_cipher *cipher = ssh2_cipher_new(&ssh_aes256_cbc);
ssh2_cipher_setkey(cipher, key);
ssh2_cipher_setiv(cipher, iv);
ssh2_cipher_encrypt(cipher, blk, len);
ssh2_cipher_free(cipher);
} // WINSCP
}
void aes256_decrypt_pubkey(const void *key, void *blk, int len)
{
char iv[16];
memset(iv, 0, 16);
{ // WINSCP
ssh2_cipher *cipher = ssh2_cipher_new(&ssh_aes256_cbc);
ssh2_cipher_setkey(cipher, key);
ssh2_cipher_setiv(cipher, iv);
ssh2_cipher_decrypt(cipher, blk, len);
ssh2_cipher_free(cipher);
} // WINSCP
}
#ifdef MPEXT
#include "puttyexp.h"

View File

@@ -9,7 +9,7 @@
typedef struct {
unsigned char i, j, s[256];
ssh2_cipher ciph;
ssh_cipher ciph;
} ArcfourContext;
static void arcfour_block(void *handle, void *vblk, int len)
@@ -62,14 +62,14 @@ static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
* to leak data about the key.
*/
static ssh2_cipher *arcfour_new(const ssh2_cipheralg *alg)
static ssh_cipher *arcfour_new(const ssh_cipheralg *alg)
{
ArcfourContext *ctx = snew(ArcfourContext);
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static void arcfour_free(ssh2_cipher *cipher)
static void arcfour_free(ssh_cipher *cipher)
{
ArcfourContext *ctx = container_of(cipher, ArcfourContext, ciph);
smemclr(ctx, sizeof(*ctx));
@@ -85,25 +85,25 @@ static void arcfour_stir(ArcfourContext *ctx)
sfree(junk);
}
static void arcfour_ssh2_setiv(ssh2_cipher *cipher, const void *key)
static void arcfour_ssh2_setiv(ssh_cipher *cipher, const void *key)
{
/* As a pure stream cipher, Arcfour has no IV separate from the key */
}
static void arcfour_ssh2_setkey(ssh2_cipher *cipher, const void *key)
static void arcfour_ssh2_setkey(ssh_cipher *cipher, const void *key)
{
ArcfourContext *ctx = container_of(cipher, ArcfourContext, ciph);
arcfour_setkey(ctx, key, ctx->ciph.vt->padded_keybytes);
arcfour_stir(ctx);
}
static void arcfour_ssh2_block(ssh2_cipher *cipher, void *blk, int len)
static void arcfour_ssh2_block(ssh_cipher *cipher, void *blk, int len)
{
ArcfourContext *ctx = container_of(cipher, ArcfourContext, ciph);
arcfour_block(ctx, blk, len);
}
const ssh2_cipheralg ssh_arcfour128_ssh2 = {
const ssh_cipheralg ssh_arcfour128_ssh2 = {
arcfour_new, arcfour_free, arcfour_ssh2_setiv, arcfour_ssh2_setkey,
arcfour_ssh2_block, arcfour_ssh2_block, NULL, NULL,
"arcfour128",
@@ -111,7 +111,7 @@ const ssh2_cipheralg ssh_arcfour128_ssh2 = {
NULL
};
const ssh2_cipheralg ssh_arcfour256_ssh2 = {
const ssh_cipheralg ssh_arcfour256_ssh2 = {
arcfour_new, arcfour_free, arcfour_ssh2_setiv, arcfour_ssh2_setkey,
arcfour_ssh2_block, arcfour_ssh2_block, NULL, NULL,
"arcfour256",
@@ -119,7 +119,7 @@ const ssh2_cipheralg ssh_arcfour256_ssh2 = {
NULL
};
static const ssh2_cipheralg *const arcfour_list[] = {
static const ssh_cipheralg *const arcfour_list[] = {
&ssh_arcfour256_ssh2,
&ssh_arcfour128_ssh2,
};

152
source/putty/sshauxcrypt.c vendored Normal file
View File

@@ -0,0 +1,152 @@
/*
* 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.
*
* 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.
*/
#include "ssh.h"
static ssh_cipher *aes256_pubkey_cipher(const void *key)
{
/*
* PuTTY's own .PPK format for SSH-2 private key files is
* encrypted with 256-bit AES in CBC mode.
*/
char iv[16];
memset(iv, 0, 16);
ssh_cipher *cipher = ssh_cipher_new(&ssh_aes256_cbc);
ssh_cipher_setkey(cipher, key);
ssh_cipher_setiv(cipher, iv);
return cipher;
}
void aes256_encrypt_pubkey(const void *key, void *blk, int len)
{
ssh_cipher *c = aes256_pubkey_cipher(key);
ssh_cipher_encrypt(c, blk, len);
ssh_cipher_free(c);
}
void aes256_decrypt_pubkey(const void *key, void *blk, int len)
{
ssh_cipher *c = aes256_pubkey_cipher(key);
ssh_cipher_decrypt(c, blk, len);
ssh_cipher_free(c);
}
static ssh_cipher *des3_pubkey_cipher(const void *vkey)
{
/*
* SSH-1 private key files are encrypted with triple-DES in SSH-1
* style (three separate CBC layers), but the same key is used for
* the first and third layers.
*/
ssh_cipher *c = ssh_cipher_new(&ssh_3des_ssh1);
uint8_t keys3[24], iv[8];
memcpy(keys3, vkey, 16);
memcpy(keys3 + 16, vkey, 8);
ssh_cipher_setkey(c, keys3);
smemclr(keys3, sizeof(keys3));
memset(iv, 0, 8);
ssh_cipher_setiv(c, iv);
return c;
}
void des3_decrypt_pubkey(const void *vkey, void *vblk, int len)
{
ssh_cipher *c = des3_pubkey_cipher(vkey);
ssh_cipher_decrypt(c, vblk, len);
ssh_cipher_free(c);
}
void des3_encrypt_pubkey(const void *vkey, void *vblk, int len)
{
ssh_cipher *c = des3_pubkey_cipher(vkey);
ssh_cipher_encrypt(c, vblk, len);
ssh_cipher_free(c);
}
static ssh_cipher *des3_pubkey_ossh_cipher(const void *vkey, const void *viv)
{
/*
* OpenSSH PEM private key files are encrypted with triple-DES in
* SSH-2 style (one CBC layer), with three distinct keys, and an
* IV also generated from the passphrase.
*/
ssh_cipher *c = ssh_cipher_new(&ssh_3des_ssh2);
ssh_cipher_setkey(c, vkey);
ssh_cipher_setiv(c, viv);
return c;
}
void des3_decrypt_pubkey_ossh(const void *vkey, const void *viv,
void *vblk, int len)
{
ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
ssh_cipher_decrypt(c, vblk, len);
ssh_cipher_free(c);
}
void des3_encrypt_pubkey_ossh(const void *vkey, const void *viv,
void *vblk, int len)
{
ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
ssh_cipher_encrypt(c, vblk, len);
ssh_cipher_free(c);
}
static ssh_cipher *des_xdmauth_cipher(const void *vkeydata)
{
/*
* XDM-AUTHORIZATION-1 uses single-DES, but packs the key into 7
* bytes, so here we have to repack it manually into the canonical
* form where it occupies 8 bytes each with the low bit unused.
*/
const unsigned char *keydata = (const unsigned char *)vkeydata;
unsigned char key[8];
int i, nbits, j;
unsigned int bits;
bits = 0;
nbits = 0;
j = 0;
for (i = 0; i < 8; i++) {
if (nbits < 7) {
bits = (bits << 8) | keydata[j];
nbits += 8;
j++;
}
key[i] = (bits >> (nbits - 7)) << 1;
bits &= ~(0x7F << (nbits - 7));
nbits -= 7;
}
ssh_cipher *c = ssh_cipher_new(&ssh_des);
ssh_cipher_setkey(c, key);
smemclr(key, sizeof(key));
ssh_cipher_setiv(c, key);
return c;
}
void des_encrypt_xdmauth(const void *keydata, void *blk, int len)
{
ssh_cipher *c = des_xdmauth_cipher(keydata);
ssh_cipher_encrypt(c, blk, len);
ssh_cipher_free(c);
}
void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
{
ssh_cipher *c = des_xdmauth_cipher(keydata);
ssh_cipher_decrypt(c, blk, len);
ssh_cipher_free(c);
}

View File

@@ -566,138 +566,115 @@ void blowfish_free_context(BlowfishContext *ctx)
sfree(ctx);
}
static void blowfish_iv(BlowfishContext *ctx, const void *viv)
static void blowfish_iv_be(BlowfishContext *ctx, const void *viv)
{
const unsigned char *iv = (const unsigned char *)viv;
ctx->iv0 = GET_32BIT_MSB_FIRST(iv);
ctx->iv1 = GET_32BIT_MSB_FIRST(iv + 4);
}
struct blowfish_ssh1_ctx {
/* In SSH-1, need one key for each direction */
BlowfishContext contexts[2];
ssh1_cipher ciph;
};
static ssh1_cipher *blowfish_ssh1_new(void)
static void blowfish_iv_le(BlowfishContext *ctx, const void *viv)
{
struct blowfish_ssh1_ctx *ctx = snew(struct blowfish_ssh1_ctx);
ctx->ciph.vt = &ssh1_blowfish;
return &ctx->ciph;
const unsigned char *iv = (const unsigned char *)viv;
ctx->iv0 = GET_32BIT_LSB_FIRST(iv);
ctx->iv1 = GET_32BIT_LSB_FIRST(iv + 4);
}
static void blowfish_ssh1_free(ssh1_cipher *cipher)
{
struct blowfish_ssh1_ctx *ctx =
container_of(cipher, struct blowfish_ssh1_ctx, ciph);
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void blowfish_ssh1_sesskey(ssh1_cipher *cipher, const void *key)
{
struct blowfish_ssh1_ctx *ctx =
container_of(cipher, struct blowfish_ssh1_ctx, ciph);
blowfish_setkey(&ctx->contexts[0], key, SSH1_SESSION_KEY_LENGTH);
ctx->contexts[0].iv0 = ctx->contexts[0].iv1 = 0;
ctx->contexts[1] = ctx->contexts[0]; /* structure copy */
}
static void blowfish_ssh1_encrypt_blk(ssh1_cipher *cipher, void *blk, int len)
{
struct blowfish_ssh1_ctx *ctx =
container_of(cipher, struct blowfish_ssh1_ctx, ciph);
blowfish_lsb_encrypt_cbc(blk, len, ctx->contexts);
}
static void blowfish_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len)
{
struct blowfish_ssh1_ctx *ctx =
container_of(cipher, struct blowfish_ssh1_ctx, ciph);
blowfish_lsb_decrypt_cbc(blk, len, ctx->contexts+1);
}
struct blowfish_ssh2_ctx {
struct blowfish_ctx {
BlowfishContext context;
ssh2_cipher ciph;
ssh_cipher ciph;
};
static ssh2_cipher *blowfish_ssh2_new(const ssh2_cipheralg *alg)
static ssh_cipher *blowfish_new(const ssh_cipheralg *alg)
{
struct blowfish_ssh2_ctx *ctx = snew(struct blowfish_ssh2_ctx);
struct blowfish_ctx *ctx = snew(struct blowfish_ctx);
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static void blowfish_ssh2_free(ssh2_cipher *cipher)
static void blowfish_free(ssh_cipher *cipher)
{
struct blowfish_ssh2_ctx *ctx =
container_of(cipher, struct blowfish_ssh2_ctx, ciph);
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void blowfish_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
static void blowfish_ssh_setkey(ssh_cipher *cipher, const void *key)
{
struct blowfish_ssh2_ctx *ctx =
container_of(cipher, struct blowfish_ssh2_ctx, ciph);
blowfish_iv(&ctx->context, iv);
}
static void blowfish_ssh2_setkey(ssh2_cipher *cipher, const void *key)
{
struct blowfish_ssh2_ctx *ctx =
container_of(cipher, struct blowfish_ssh2_ctx, ciph);
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_setkey(&ctx->context, key, ctx->ciph.vt->padded_keybytes);
}
static void blowfish_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len)
static void blowfish_ssh1_setiv(ssh_cipher *cipher, const void *iv)
{
struct blowfish_ssh2_ctx *ctx =
container_of(cipher, struct blowfish_ssh2_ctx, ciph);
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_iv_le(&ctx->context, iv);
}
static void blowfish_ssh2_setiv(ssh_cipher *cipher, const void *iv)
{
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_iv_be(&ctx->context, iv);
}
static void blowfish_ssh1_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_lsb_encrypt_cbc(blk, len, &ctx->context);
}
static void blowfish_ssh1_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_lsb_decrypt_cbc(blk, len, &ctx->context);
}
static void blowfish_ssh2_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_msb_encrypt_cbc(blk, len, &ctx->context);
}
static void blowfish_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len)
static void blowfish_ssh2_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct blowfish_ssh2_ctx *ctx =
container_of(cipher, struct blowfish_ssh2_ctx, ciph);
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_msb_decrypt_cbc(blk, len, &ctx->context);
}
static void blowfish_ssh2_sdctr(ssh2_cipher *cipher, void *blk, int len)
static void blowfish_ssh2_sdctr(ssh_cipher *cipher, void *blk, int len)
{
struct blowfish_ssh2_ctx *ctx =
container_of(cipher, struct blowfish_ssh2_ctx, ciph);
struct blowfish_ctx *ctx = container_of(cipher, struct blowfish_ctx, ciph);
blowfish_msb_sdctr(blk, len, &ctx->context);
}
const ssh1_cipheralg ssh1_blowfish = {
blowfish_ssh1_new, blowfish_ssh1_free,
blowfish_ssh1_sesskey,
const ssh_cipheralg ssh_blowfish_ssh1 = {
blowfish_new, blowfish_free,
blowfish_ssh1_setiv, blowfish_ssh_setkey,
blowfish_ssh1_encrypt_blk, blowfish_ssh1_decrypt_blk,
8, "Blowfish-128 CBC"
NULL, NULL, NULL,
8, 128, SSH1_SESSION_KEY_LENGTH, SSH_CIPHER_IS_CBC, "Blowfish-256 CBC",
NULL
};
const ssh2_cipheralg ssh_blowfish_ssh2 = {
blowfish_ssh2_new, blowfish_ssh2_free,
blowfish_ssh2_setiv, blowfish_ssh2_setkey,
const ssh_cipheralg ssh_blowfish_ssh2 = {
blowfish_new, blowfish_free,
blowfish_ssh2_setiv, blowfish_ssh_setkey,
blowfish_ssh2_encrypt_blk, blowfish_ssh2_decrypt_blk, NULL, NULL,
"blowfish-cbc",
8, 128, 16, SSH_CIPHER_IS_CBC, "Blowfish-128 CBC",
NULL
};
const ssh2_cipheralg ssh_blowfish_ssh2_ctr = {
blowfish_ssh2_new, blowfish_ssh2_free,
blowfish_ssh2_setiv, blowfish_ssh2_setkey,
const ssh_cipheralg ssh_blowfish_ssh2_ctr = {
blowfish_new, blowfish_free,
blowfish_ssh2_setiv, blowfish_ssh_setkey,
blowfish_ssh2_sdctr, blowfish_ssh2_sdctr, NULL, NULL,
"blowfish-ctr",
8, 256, 32, 0, "Blowfish-256 SDCTR",
NULL
};
static const ssh2_cipheralg *const blowfish_list[] = {
static const ssh_cipheralg *const blowfish_list[] = {
&ssh_blowfish_ssh2_ctr,
&ssh_blowfish_ssh2
};

View File

@@ -54,7 +54,7 @@ void ssh_bpp_free(BinaryPacketProtocol *bpp);
BinaryPacketProtocol *ssh1_bpp_new(LogContext *logctx);
void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
const ssh1_cipheralg *cipher,
const ssh_cipheralg *cipher,
const void *session_key);
/* This is only called from outside the BPP in server mode; in client
* mode the BPP detects compression start time automatically by
@@ -104,12 +104,12 @@ BinaryPacketProtocol *ssh2_bpp_new(
LogContext *logctx, struct DataTransferStats *stats, bool is_server);
void ssh2_bpp_new_outgoing_crypto(
BinaryPacketProtocol *bpp,
const ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const ssh_cipheralg *cipher, const void *ckey, const void *iv,
const ssh2_macalg *mac, bool etm_mode, const void *mac_key,
const ssh_compression_alg *compression, bool delayed_compression);
void ssh2_bpp_new_incoming_crypto(
BinaryPacketProtocol *bpp,
const ssh2_cipheralg *cipher, const void *ckey, const void *iv,
const ssh_cipheralg *cipher, const void *ckey, const void *iv,
const ssh2_macalg *mac, bool etm_mode, const void *mac_key,
const ssh_compression_alg *compression, bool delayed_compression);

26
source/putty/sshccp.c vendored
View File

@@ -20,7 +20,7 @@
* This has an intricate link between the cipher and the MAC. The
* keying of both is done in by the cipher and setting of the IV is
* done by the MAC. One cannot operate without the other. The
* configuration of the ssh2_cipheralg structure ensures that the MAC is
* configuration of the ssh_cipheralg structure ensures that the MAC is
* set (and others ignored) if this cipher is chosen.
*
* This cipher also encrypts the length using a different
@@ -867,12 +867,12 @@ struct ccp_context {
struct poly1305 mac;
BinarySink_IMPLEMENTATION;
ssh2_cipher ciph;
ssh_cipher ciph;
ssh2_mac mac_if;
};
static ssh2_mac *poly_ssh2_new(
const ssh2_macalg *alg, ssh2_cipher *cipher)
const ssh2_macalg *alg, ssh_cipher *cipher)
{
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
ctx->mac_if.vt = alg;
@@ -946,7 +946,7 @@ const ssh2_macalg ssh2_poly1305 = {
16, 0, "Poly1305"
};
static ssh2_cipher *ccp_new(const ssh2_cipheralg *alg)
static ssh_cipher *ccp_new(const ssh_cipheralg *alg)
{
struct ccp_context *ctx = snew(struct ccp_context);
BinarySink_INIT(ctx, poly_BinarySink_write);
@@ -955,7 +955,7 @@ static ssh2_cipher *ccp_new(const ssh2_cipheralg *alg)
return &ctx->ciph;
}
static void ccp_free(ssh2_cipher *cipher)
static void ccp_free(ssh_cipher *cipher)
{
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
smemclr(&ctx->a_cipher, sizeof(ctx->a_cipher));
@@ -964,14 +964,14 @@ static void ccp_free(ssh2_cipher *cipher)
sfree(ctx);
}
static void ccp_iv(ssh2_cipher *cipher, const void *iv)
static void ccp_iv(ssh_cipher *cipher, const void *iv)
{
/* struct ccp_context *ctx =
container_of(cipher, struct ccp_context, ciph); */
/* IV is set based on the sequence number */
}
static void ccp_key(ssh2_cipher *cipher, const void *vkey)
static void ccp_key(ssh_cipher *cipher, const void *vkey)
{
const unsigned char *key = (const unsigned char *)vkey;
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
@@ -981,13 +981,13 @@ static void ccp_key(ssh2_cipher *cipher, const void *vkey)
chacha20_key(&ctx->b_cipher, key);
}
static void ccp_encrypt(ssh2_cipher *cipher, void *blk, int len)
static void ccp_encrypt(ssh_cipher *cipher, void *blk, int len)
{
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
chacha20_encrypt(&ctx->b_cipher, blk, len);
}
static void ccp_decrypt(ssh2_cipher *cipher, void *blk, int len)
static void ccp_decrypt(ssh_cipher *cipher, void *blk, int len)
{
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
chacha20_decrypt(&ctx->b_cipher, blk, len);
@@ -1010,7 +1010,7 @@ static void ccp_length_op(struct ccp_context *ctx, void *blk, int len,
smemclr(iv, sizeof(iv));
}
static void ccp_encrypt_length(ssh2_cipher *cipher, void *blk, int len,
static void ccp_encrypt_length(ssh_cipher *cipher, void *blk, int len,
unsigned long seq)
{
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
@@ -1018,7 +1018,7 @@ static void ccp_encrypt_length(ssh2_cipher *cipher, void *blk, int len,
chacha20_encrypt(&ctx->a_cipher, blk, len);
}
static void ccp_decrypt_length(ssh2_cipher *cipher, void *blk, int len,
static void ccp_decrypt_length(ssh_cipher *cipher, void *blk, int len,
unsigned long seq)
{
struct ccp_context *ctx = container_of(cipher, struct ccp_context, ciph);
@@ -1026,7 +1026,7 @@ static void ccp_decrypt_length(ssh2_cipher *cipher, void *blk, int len,
chacha20_decrypt(&ctx->a_cipher, blk, len);
}
const ssh2_cipheralg ssh2_chacha20_poly1305 = {
const ssh_cipheralg ssh2_chacha20_poly1305 = {
ccp_new,
ccp_free,
@@ -1043,7 +1043,7 @@ const ssh2_cipheralg ssh2_chacha20_poly1305 = {
&ssh2_poly1305
};
static const ssh2_cipheralg *const ccp_list[] = {
static const ssh_cipheralg *const ccp_list[] = {
&ssh2_chacha20_poly1305
};

283
source/putty/sshcrc.c vendored
View File

@@ -1,229 +1,108 @@
/*
* CRC32 implementation.
* CRC32 implementation, as used in SSH-1.
*
* The basic concept of a CRC is that you treat your bit-string
* abcdefg... as a ludicrously long polynomial M=a+bx+cx^2+dx^3+...
* over Z[2]. You then take a modulus polynomial P, and compute the
* remainder of M on division by P. Thus, an erroneous message N
* will only have the same CRC if the difference E = M-N is an
* exact multiple of P. (Note that as we are working over Z[2], M-N
* = N-M = M+N; but that's not very important.)
* This particular form of the CRC uses the polynomial
* P(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+1
* and represents polynomials in bit-reversed form, so that the x^0
* coefficient (constant term) appears in the bit with place value
* 2^31, and the x^31 coefficient in the bit with place value 2^0. In
* this representation, (x^32 mod P) = 0xEDB88320, so multiplying the
* current state by x is done by shifting right by one bit, and XORing
* that constant into the result if the bit shifted out was 1.
*
* What makes the CRC good is choosing P to have good properties:
* There's a bewildering array of subtly different variants of CRC out
* there, using different polynomials, both bit orders, and varying
* the start and end conditions. There are catalogue websites such as
* http://reveng.sourceforge.net/crc-catalogue/ , which generally seem
* to have the convention of indexing CRCs by their 'check value',
* defined as whatever you get if you hash the 9-byte test string
* "123456789".
*
* - If its first and last terms are both nonzero then it cannot
* be a factor of any single term x^i. Therefore if M and N
* differ by exactly one bit their CRCs will guaranteeably
* be distinct.
* The crc32_rfc1662() function below, which starts off the CRC state
* at 0xFFFFFFFF and complements it after feeding all the data, gives
* the check value 0xCBF43926, and matches the hash function that the
* above catalogue refers to as "CRC-32/ISO-HDLC"; among other things,
* it's also the "FCS-32" checksum described in RFC 1662 section C.3
* (hence the name I've given it here).
*
* - If it has a prime (irreducible) factor with three terms then
* it cannot divide a polynomial of the form x^i(1+x^j).
* Therefore if M and N differ by exactly _two_ bits they will
* have different CRCs.
*
* - If it has a factor (x+1) then it cannot divide a polynomial
* with an odd number of terms. Therefore if M and N differ by
* _any odd_ number of bits they will have different CRCs.
*
* - If the error term E is of the form x^i*B(x) where B(x) has
* order less than P (i.e. a short _burst_ of errors) then P
* cannot divide E (since no polynomial can divide a shorter
* one), so any such error burst will be spotted.
*
* The CRC32 standard polynomial is
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
*
* In fact, we don't compute M mod P; we compute M*x^32 mod P.
*
* The concrete implementation of the CRC is this: we maintain at
* all times a 32-bit word which is the current remainder of the
* polynomial mod P. Whenever we receive an extra bit, we multiply
* the existing remainder by x, add (XOR) the x^32 term thus
* generated to the new x^32 term caused by the incoming bit, and
* remove the resulting combined x^32 term if present by replacing
* it with (P-x^32).
*
* Bit 0 of the word is the x^31 term and bit 31 is the x^0 term.
* Thus, multiplying by x means shifting right. So the actual
* algorithm goes like this:
*
* x32term = (crcword & 1) ^ newbit;
* crcword = (crcword >> 1) ^ (x32term * 0xEDB88320);
*
* In practice, we pre-compute what will happen to crcword on any
* given sequence of eight incoming bits, and store that in a table
* which we then use at run-time to do the job:
*
* outgoingplusnew = (crcword & 0xFF) ^ newbyte;
* crcword = (crcword >> 8) ^ table[outgoingplusnew];
*
* where table[outgoingplusnew] is computed by setting crcword=0
* and then iterating the first code fragment eight times (taking
* the incoming byte low bit first).
*
* Note that all shifts are rightward and thus no assumption is
* made about exact word length! (Although word length must be at
* _least_ 32 bits, but ANSI C guarantees this for `unsigned long'
* anyway.)
* The crc32_ssh1() function implements the variant form used by
* SSH-1, which uses the same update function, but starts the state at
* zero and doesn't complement it at the end of the computation. The
* check value for that version is 0x2DFD2D88, which that CRC
* catalogue doesn't list at all.
*/
#include <stdint.h>
#include <stdlib.h>
#include "ssh.h"
/* ----------------------------------------------------------------------
* Multi-function module. Can be compiled three ways.
/*
* Multiply a CRC value by x^4. This implementation strategy avoids
* using a lookup table (which would be a side-channel hazard, since
* SSH-1 applies this CRC to decrypted session data).
*
* - Compile with no special #defines. Will generate a table
* that's already initialised at compile time, and one function
* crc32_compute(buf,len) that uses it. Normal usage.
* The basic idea is that you'd like to "multiply" the shifted-out 4
* bits by the CRC polynomial value 0xEDB88320, or rather by that
* value shifted right 3 bits (since you want the _last_ bit shifted
* out, i.e. the one originally at the 2^3 position, to generate
* 0xEDB88320 itself). But the scare-quoted "multiply" would have to
* be a multiplication of polynomials over GF(2), which differs from
* integer multiplication in that you don't have any carries. In other
* words, you make a copy of one input shifted left by the index of
* each set bit in the other, so that adding them all together would
* give you the ordinary integer product, and then you XOR them
* together instead.
*
* - Compile with INITFUNC defined. Will generate an uninitialised
* array as the table, and as well as crc32_compute(buf,len) it
* will also generate void crc32_init(void) which sets up the
* table at run time. Useful if binary size is important.
*
* - Compile with GENPROGRAM defined. Will create a standalone
* program that does the initialisation and outputs the table as
* C code.
* With a 4-bit multiplier, the two kinds of multiplication coincide
* provided the multiplicand has no two set bits at positions
* differing by less than 4, because then no two copies of the
* multiplier can overlap to generate a carry. So I break up the
* intended multiplicand K = 0xEDB88320 >> 3 into three sub-constants
* a,b,c with that property, such that a^b^c = K. Then I can multiply
* m by each of them separately, and XOR together the results.
*/
#define POLY (0xEDB88320L)
#ifdef GENPROGRAM
#define INITFUNC /* the gen program needs the init func :-) */
#endif
#ifdef INITFUNC
static inline uint32_t crc32_shift_4(uint32_t v)
{
const uint32_t a = 0x11111044, b = 0x08840020, c = 0x04220000;
uint32_t m = v & 0xF;
return (v >> 4) ^ (a*m) ^ (b*m) ^ (c*m);
}
/*
* This variant of the code generates the table at run-time from an
* init function.
* The 8-bit shift you need every time you absorb an input byte,
* implemented simply by iterating the 4-bit shift twice.
*/
static unsigned long crc32_table[256];
void crc32_init(void)
static inline uint32_t crc32_shift_8(uint32_t v)
{
unsigned long crcword;
int i;
for (i = 0; i < 256; i++) {
unsigned long newbyte, x32term;
int j;
crcword = 0;
newbyte = i;
for (j = 0; j < 8; j++) {
x32term = (crcword ^ newbyte) & 1;
crcword = (crcword >> 1) ^ (x32term * POLY);
newbyte >>= 1;
}
crc32_table[i] = crcword;
}
return crc32_shift_4(crc32_shift_4(v));
}
#else
/*
* This variant of the code has the data already prepared.
* Update an existing hash value with extra bytes of data.
*/
static const unsigned long crc32_table[256] = {
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
};
#endif
#ifdef GENPROGRAM
int main(void)
uint32_t crc32_update(uint32_t crc, ptrlen data)
{
int i;
crc32_init();
for (i = 0; i < 256; i++) {
printf("%s0x%08lXL%s",
(i % 4 == 0 ? " " : " "),
crc32_table[i],
(i % 4 == 3 ? (i == 255 ? "\n" : ",\n") : ","));
}
return 0;
}
#endif
unsigned long crc32_update(unsigned long crcword, const void *buf, size_t len)
{
const unsigned char *p = (const unsigned char *) buf;
while (len--) {
unsigned long newbyte = *p++;
newbyte ^= crcword & 0xFFL;
crcword = (crcword >> 8) ^ crc32_table[newbyte];
}
return crcword;
const uint8_t *p = (const uint8_t *)data.ptr;
for (size_t len = data.len; len-- > 0 ;)
crc = crc32_shift_8(crc ^ *p++);
return crc;
}
unsigned long crc32_compute(const void *buf, size_t len)
/*
* The SSH-1 variant of CRC-32.
*/
uint32_t crc32_ssh1(ptrlen data)
{
return crc32_update(0L, buf, len);
return crc32_update(0, data);
}
/*
* The official version of CRC-32. Nothing in PuTTY proper uses this,
* but it's useful to expose it to testcrypt so that we can implement
* standard test vectors.
*/
uint32_t crc32_rfc1662(ptrlen data)
{
return crc32_update(0xFFFFFFFF, data) ^ 0xFFFFFFFF;
}

View File

@@ -75,16 +75,17 @@ void crcda_free_context(struct crcda_ctx *ctx)
}
}
static void crc_update(uint32_t *a, void *b)
static void crc_update(uint32_t *a, const void *b)
{
*a = crc32_update(*a, b, 4);
*a = crc32_update(*a, make_ptrlen(b, 4));
}
/* detect if a block is used in a particular pattern */
static bool check_crc(uint8_t *S, uint8_t *buf, uint32_t len, uint8_t *IV)
static bool check_crc(const uint8_t *S, const uint8_t *buf,
uint32_t len, const uint8_t *IV)
{
uint32_t crc;
uint8_t *c;
const uint8_t *c;
crc = 0;
if (IV && !CMP(S, IV)) {
@@ -104,13 +105,14 @@ static bool check_crc(uint8_t *S, uint8_t *buf, uint32_t len, uint8_t *IV)
}
/* Detect a crc32 compensation attack on a packet */
bool detect_attack(
struct crcda_ctx *ctx, uint8_t *buf, uint32_t len, uint8_t *IV)
bool detect_attack(struct crcda_ctx *ctx,
const unsigned char *buf, uint32_t len,
const unsigned char *IV)
{
register uint32_t i, j;
uint32_t l;
register uint8_t *c;
uint8_t *d;
register const uint8_t *c;
const uint8_t *d;
assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
len % SSH_BLOCKSIZE != 0));

267
source/putty/sshdes.c vendored
View File

@@ -774,32 +774,18 @@ static void des_key(DESContext *context, const void *vkey)
}
struct des3_ssh1_ctx {
/* 3 cipher context for each direction */
DESContext contexts[6];
ssh1_cipher ciph;
DESContext contexts[3];
ssh_cipher ciph;
};
struct des_ssh1_ctx {
/* 1 cipher context for each direction */
DESContext contexts[2];
ssh1_cipher ciph;
};
static ssh1_cipher *des3_ssh1_new(void)
static ssh_cipher *des3_ssh1_new(const ssh_cipheralg *alg)
{
struct des3_ssh1_ctx *ctx = snew(struct des3_ssh1_ctx);
ctx->ciph.vt = &ssh1_3des;
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static ssh1_cipher *des_ssh1_new(void)
{
struct des_ssh1_ctx *ctx = snew(struct des_ssh1_ctx);
ctx->ciph.vt = &ssh1_des;
return &ctx->ciph;
}
static void des3_ssh1_free(ssh1_cipher *cipher)
static void des3_ssh1_free(ssh_cipher *cipher)
{
struct des3_ssh1_ctx *ctx = container_of(
cipher, struct des3_ssh1_ctx, ciph);
@@ -807,83 +793,65 @@ static void des3_ssh1_free(ssh1_cipher *cipher)
sfree(ctx);
}
static void des_ssh1_free(ssh1_cipher *cipher)
{
struct des_ssh1_ctx *ctx = container_of(
cipher, struct des_ssh1_ctx, ciph);
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void des3_ssh1_sesskey(ssh1_cipher *cipher, const void *key)
static void des3_ssh1_setkey(ssh_cipher *cipher, const void *key)
{
struct des3_ssh1_ctx *ctx = container_of(
cipher, struct des3_ssh1_ctx, ciph);
des3_key(ctx->contexts, key);
des3_key(ctx->contexts+3, key);
}
static void des3_ssh1_encrypt_blk(ssh1_cipher *cipher, void *blk, int len)
static void des3_ssh1_setiv(ssh_cipher *cipher, const void *iv)
{
struct des3_ssh1_ctx *ctx = container_of(
cipher, struct des3_ssh1_ctx, ciph);
/* SSH-1's idea of triple-DES CBC is three actual instances of the
* whole of DES-CBC, i.e. three separate CBC layers each with
* their own IV. So in principle we ought to be able to accept 24
* bytes of IV here. However, SSH-1 initialises all IVs to zero
* anyway, so we fudge it by just setting them all the same. */
for (int i = 0; i < 3; i++)
des_iv(&ctx->contexts[i], iv);
}
static void des3_ssh1_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct des3_ssh1_ctx *ctx = container_of(
cipher, struct des3_ssh1_ctx, ciph);
des_3cbc_encrypt(blk, len, ctx->contexts);
}
static void des3_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len)
static void des3_ssh1_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct des3_ssh1_ctx *ctx = container_of(
cipher, struct des3_ssh1_ctx, ciph);
des_3cbc_decrypt(blk, len, ctx->contexts+3);
}
static void des_ssh1_sesskey(ssh1_cipher *cipher, const void *key)
{
struct des_ssh1_ctx *ctx = container_of(
cipher, struct des_ssh1_ctx, ciph);
des_key(ctx->contexts, key);
des_key(ctx->contexts+1, key);
}
static void des_ssh1_encrypt_blk(ssh1_cipher *cipher, void *blk, int len)
{
struct des_ssh1_ctx *ctx = container_of(
cipher, struct des_ssh1_ctx, ciph);
des_cbc_encrypt(blk, len, ctx->contexts);
}
static void des_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len)
{
struct des_ssh1_ctx *ctx = container_of(
cipher, struct des_ssh1_ctx, ciph);
des_cbc_decrypt(blk, len, ctx->contexts+1);
des_3cbc_decrypt(blk, len, ctx->contexts);
}
struct des3_ssh2_ctx {
DESContext contexts[3];
ssh2_cipher ciph;
ssh_cipher ciph;
};
struct des_ssh2_ctx {
struct des_ctx {
DESContext context;
ssh2_cipher ciph;
ssh_cipher ciph;
};
static ssh2_cipher *des3_ssh2_new(const ssh2_cipheralg *alg)
static ssh_cipher *des3_ssh2_new(const ssh_cipheralg *alg)
{
struct des3_ssh2_ctx *ctx = snew(struct des3_ssh2_ctx);
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static ssh2_cipher *des_ssh2_new(const ssh2_cipheralg *alg)
static ssh_cipher *des_new(const ssh_cipheralg *alg)
{
struct des_ssh2_ctx *ctx = snew(struct des_ssh2_ctx);
struct des_ctx *ctx = snew(struct des_ctx);
ctx->ciph.vt = alg;
return &ctx->ciph;
}
static void des3_ssh2_free(ssh2_cipher *cipher)
static void des3_ssh2_free(ssh_cipher *cipher)
{
struct des3_ssh2_ctx *ctx = container_of(
cipher, struct des3_ssh2_ctx, ciph);
@@ -891,15 +859,14 @@ static void des3_ssh2_free(ssh2_cipher *cipher)
sfree(ctx);
}
static void des_ssh2_free(ssh2_cipher *cipher)
static void des_free(ssh_cipher *cipher)
{
struct des_ssh2_ctx *ctx = container_of(
cipher, struct des_ssh2_ctx, ciph);
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void des3_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
static void des3_ssh2_setiv(ssh_cipher *cipher, const void *iv)
{
struct des3_ssh2_ctx *ctx = container_of(
cipher, struct des3_ssh2_ctx, ciph);
@@ -908,169 +875,59 @@ static void des3_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
* CBC, so there's only one IV required, not three */
}
static void des3_ssh2_setkey(ssh2_cipher *cipher, const void *key)
static void des3_ssh2_setkey(ssh_cipher *cipher, const void *key)
{
struct des3_ssh2_ctx *ctx = container_of(
cipher, struct des3_ssh2_ctx, ciph);
des3_key(ctx->contexts, key);
}
static void des_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
static void des_setiv(ssh_cipher *cipher, const void *iv)
{
struct des_ssh2_ctx *ctx = container_of(
cipher, struct des_ssh2_ctx, ciph);
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
des_iv(&ctx->context, iv);
}
static void des_ssh2_setkey(ssh2_cipher *cipher, const void *key)
static void des_setkey(ssh_cipher *cipher, const void *key)
{
struct des_ssh2_ctx *ctx = container_of(
cipher, struct des_ssh2_ctx, ciph);
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
des_key(&ctx->context, key);
}
static void des3_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len)
static void des3_ssh2_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct des3_ssh2_ctx *ctx = container_of(
cipher, struct des3_ssh2_ctx, ciph);
des_cbc3_encrypt(blk, len, ctx->contexts);
}
static void des3_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len)
static void des3_ssh2_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct des3_ssh2_ctx *ctx = container_of(
cipher, struct des3_ssh2_ctx, ciph);
des_cbc3_decrypt(blk, len, ctx->contexts);
}
static void des3_ssh2_sdctr(ssh2_cipher *cipher, void *blk, int len)
static void des3_ssh2_sdctr(ssh_cipher *cipher, void *blk, int len)
{
struct des3_ssh2_ctx *ctx = container_of(
cipher, struct des3_ssh2_ctx, ciph);
des_sdctr3(blk, len, ctx->contexts);
}
static void des_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len)
static void des_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct des_ssh2_ctx *ctx = container_of(
cipher, struct des_ssh2_ctx, ciph);
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
des_cbc_encrypt(blk, len, &ctx->context);
}
static void des_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len)
static void des_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
{
struct des_ssh2_ctx *ctx = container_of(
cipher, struct des_ssh2_ctx, ciph);
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
des_cbc_decrypt(blk, len, &ctx->context);
}
void des3_decrypt_pubkey(const void *vkey, void *vblk, int len)
{
const unsigned char *key = (const unsigned char *)vkey;
unsigned char *blk = (unsigned char *)vblk;
DESContext ourkeys[3];
des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]);
des_3cbc_decrypt(blk, len, ourkeys);
smemclr(ourkeys, sizeof(ourkeys));
}
void des3_encrypt_pubkey(const void *vkey, void *vblk, int len)
{
const unsigned char *key = (const unsigned char *)vkey;
unsigned char *blk = (unsigned char *)vblk;
DESContext ourkeys[3];
des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]);
des_3cbc_encrypt(blk, len, ourkeys);
smemclr(ourkeys, sizeof(ourkeys));
}
void des3_decrypt_pubkey_ossh(const void *vkey, const void *viv,
void *vblk, int len)
{
const unsigned char *key = (const unsigned char *)vkey;
const unsigned char *iv = (const unsigned char *)viv;
unsigned char *blk = (unsigned char *)vblk;
DESContext ourkeys[3];
des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key + 16),
GET_32BIT_MSB_FIRST(key + 20), &ourkeys[2]);
ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv);
ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4);
des_cbc3_decrypt(blk, len, ourkeys);
smemclr(ourkeys, sizeof(ourkeys));
}
void des3_encrypt_pubkey_ossh(const void *vkey, const void *viv,
void *vblk, int len)
{
const unsigned char *key = (const unsigned char *)vkey;
const unsigned char *iv = (const unsigned char *)viv;
unsigned char *blk = (unsigned char *)vblk;
DESContext ourkeys[3];
des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key + 16),
GET_32BIT_MSB_FIRST(key + 20), &ourkeys[2]);
ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv);
ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4);
des_cbc3_encrypt(blk, len, ourkeys);
smemclr(ourkeys, sizeof(ourkeys));
}
static void des_keysetup_xdmauth(const void *vkeydata, DESContext *dc)
{
const unsigned char *keydata = (const unsigned char *)vkeydata;
unsigned char key[8];
int i, nbits, j;
unsigned int bits;
bits = 0;
nbits = 0;
j = 0;
for (i = 0; i < 8; i++) {
if (nbits < 7) {
bits = (bits << 8) | keydata[j];
nbits += 8;
j++;
}
key[i] = (bits >> (nbits - 7)) << 1;
bits &= ~(0x7F << (nbits - 7));
nbits -= 7;
}
des_key_setup(GET_32BIT_MSB_FIRST(key), GET_32BIT_MSB_FIRST(key + 4), dc);
}
void des_encrypt_xdmauth(const void *keydata, void *blk, int len)
{
DESContext dc;
des_keysetup_xdmauth(keydata, &dc);
des_cbc_encrypt(blk, len, &dc);
}
void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
{
DESContext dc;
des_keysetup_xdmauth(keydata, &dc);
des_cbc_decrypt(blk, len, &dc);
}
const ssh2_cipheralg ssh_3des_ssh2 = {
const ssh_cipheralg ssh_3des_ssh2 = {
des3_ssh2_new, des3_ssh2_free, des3_ssh2_setiv, des3_ssh2_setkey,
des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk, NULL, NULL,
"3des-cbc",
@@ -1078,7 +935,7 @@ const ssh2_cipheralg ssh_3des_ssh2 = {
NULL
};
const ssh2_cipheralg ssh_3des_ssh2_ctr = {
const ssh_cipheralg ssh_3des_ssh2_ctr = {
des3_ssh2_new, des3_ssh2_free, des3_ssh2_setiv, des3_ssh2_setkey,
des3_ssh2_sdctr, des3_ssh2_sdctr, NULL, NULL,
"3des-ctr",
@@ -1094,44 +951,38 @@ const ssh2_cipheralg ssh_3des_ssh2_ctr = {
* apparently aren't the only people to do so, so we sigh
* and implement it anyway.
*/
const ssh2_cipheralg ssh_des_ssh2 = {
des_ssh2_new, des_ssh2_free, des_ssh2_setiv, des_ssh2_setkey,
des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, NULL, NULL,
const ssh_cipheralg ssh_des = {
des_new, des_free, des_setiv, des_setkey,
des_encrypt_blk, des_decrypt_blk, NULL, NULL,
"des-cbc",
8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC",
NULL
};
const ssh2_cipheralg ssh_des_sshcom_ssh2 = {
des_ssh2_new, des_ssh2_free, des_ssh2_setiv, des_ssh2_setkey,
des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, NULL, NULL,
const ssh_cipheralg ssh_des_sshcom_ssh2 = {
des_new, des_free, des_setiv, des_setkey,
des_encrypt_blk, des_decrypt_blk, NULL, NULL,
"des-cbc@ssh.com",
8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC",
NULL
};
static const ssh2_cipheralg *const des3_list[] = {
static const ssh_cipheralg *const des3_list[] = {
&ssh_3des_ssh2_ctr,
&ssh_3des_ssh2
};
const ssh2_ciphers ssh2_3des = { lenof(des3_list), des3_list };
static const ssh2_cipheralg *const des_list[] = {
&ssh_des_ssh2,
static const ssh_cipheralg *const des_list[] = {
&ssh_des,
&ssh_des_sshcom_ssh2
};
const ssh2_ciphers ssh2_des = { lenof(des_list), des_list };
const ssh1_cipheralg ssh1_3des = {
des3_ssh1_new, des3_ssh1_free, des3_ssh1_sesskey,
des3_ssh1_encrypt_blk, des3_ssh1_decrypt_blk,
8, "triple-DES inner-CBC"
};
const ssh1_cipheralg ssh1_des = {
des_ssh1_new, des_ssh1_free, des_ssh1_sesskey,
des_ssh1_encrypt_blk, des_ssh1_decrypt_blk,
8, "single-DES CBC"
const ssh_cipheralg ssh_3des_ssh1 = {
des3_ssh1_new, des3_ssh1_free, des3_ssh1_setiv, des3_ssh1_setkey,
des3_ssh1_encrypt_blk, des3_ssh1_decrypt_blk, NULL, NULL, NULL,
8, 168, 24, SSH_CIPHER_IS_CBC, "triple-DES inner-CBC", NULL
};

View File

@@ -285,8 +285,7 @@ struct hmacmd5_context *hmacmd5_make_context(void)
return ctx;
}
static ssh2_mac *hmacmd5_ssh2_new(const ssh2_macalg *alg,
ssh2_cipher *cipher)
static ssh2_mac *hmacmd5_ssh2_new(const ssh2_macalg *alg, ssh_cipher *cipher)
{
struct hmacmd5_context *ctx = hmacmd5_make_context();
ctx->mac.vt = alg;

View File

@@ -264,8 +264,7 @@ struct hmacsha256 {
ssh2_mac mac;
};
static ssh2_mac *hmacsha256_new(
const ssh2_macalg *alg, ssh2_cipher *cipher)
static ssh2_mac *hmacsha256_new(const ssh2_macalg *alg, ssh_cipher *cipher)
{
struct hmacsha256 *ctx = snew(struct hmacsha256);
ctx->mac.vt = alg;

View File

@@ -288,8 +288,7 @@ struct hmacsha1 {
ssh2_mac mac;
};
static ssh2_mac *hmacsha1_new(
const ssh2_macalg *alg, ssh2_cipher *cipher)
static ssh2_mac *hmacsha1_new(const ssh2_macalg *alg, ssh_cipher *cipher)
{
struct hmacsha1 *ctx = snew(struct hmacsha1);
ctx->mac.vt = alg;

View File

@@ -275,3 +275,12 @@ uintmax_t strtoumax(const char *nptr, char **endptr, int base)
}
#endif
#if defined _M_ARM || defined _M_ARM64
bool platform_aes_hw_available(void)
{
return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
}
#endif