1 /*
2 * sshauxcrypt.c: wrapper functions on crypto primitives for use in
3 * other contexts than the main SSH packet protocol, such as
4 * encrypting private key files and performing XDM-AUTHORIZATION-1.
5 *
6 * These all work through the standard cipher/hash/MAC APIs, so they
7 * don't need to live in the same actual source files as the ciphers
8 * they wrap, and I think it keeps things tidier to have them out of
9 * the way here instead.
10 */
11
12 #include "ssh.h"
13
aes256_pubkey_cipher(const void * key,const void * iv)14 static ssh_cipher *aes256_pubkey_cipher(const void *key, const void *iv)
15 {
16 /*
17 * PuTTY's own .PPK format for SSH-2 private key files is
18 * encrypted with 256-bit AES in CBC mode.
19 */
20 ssh_cipher *cipher = ssh_cipher_new(&ssh_aes256_cbc);
21 ssh_cipher_setkey(cipher, key);
22 ssh_cipher_setiv(cipher, iv);
23 return cipher;
24 }
25
aes256_encrypt_pubkey(const void * key,const void * iv,void * blk,int len)26 void aes256_encrypt_pubkey(const void *key, const void *iv, void *blk, int len)
27 {
28 ssh_cipher *c = aes256_pubkey_cipher(key, iv);
29 ssh_cipher_encrypt(c, blk, len);
30 ssh_cipher_free(c);
31 }
32
aes256_decrypt_pubkey(const void * key,const void * iv,void * blk,int len)33 void aes256_decrypt_pubkey(const void *key, const void *iv, void *blk, int len)
34 {
35 ssh_cipher *c = aes256_pubkey_cipher(key, iv);
36 ssh_cipher_decrypt(c, blk, len);
37 ssh_cipher_free(c);
38 }
39
des3_pubkey_cipher(const void * vkey)40 static ssh_cipher *des3_pubkey_cipher(const void *vkey)
41 {
42 /*
43 * SSH-1 private key files are encrypted with triple-DES in SSH-1
44 * style (three separate CBC layers), but the same key is used for
45 * the first and third layers.
46 */
47 ssh_cipher *c = ssh_cipher_new(&ssh_3des_ssh1);
48 uint8_t keys3[24], iv[8];
49
50 memcpy(keys3, vkey, 16);
51 memcpy(keys3 + 16, vkey, 8);
52 ssh_cipher_setkey(c, keys3);
53 smemclr(keys3, sizeof(keys3));
54
55 memset(iv, 0, 8);
56 ssh_cipher_setiv(c, iv);
57
58 return c;
59 }
60
des3_decrypt_pubkey(const void * vkey,void * vblk,int len)61 void des3_decrypt_pubkey(const void *vkey, void *vblk, int len)
62 {
63 ssh_cipher *c = des3_pubkey_cipher(vkey);
64 ssh_cipher_decrypt(c, vblk, len);
65 ssh_cipher_free(c);
66 }
67
des3_encrypt_pubkey(const void * vkey,void * vblk,int len)68 void des3_encrypt_pubkey(const void *vkey, void *vblk, int len)
69 {
70 ssh_cipher *c = des3_pubkey_cipher(vkey);
71 ssh_cipher_encrypt(c, vblk, len);
72 ssh_cipher_free(c);
73 }
74
des3_pubkey_ossh_cipher(const void * vkey,const void * viv)75 static ssh_cipher *des3_pubkey_ossh_cipher(const void *vkey, const void *viv)
76 {
77 /*
78 * OpenSSH PEM private key files are encrypted with triple-DES in
79 * SSH-2 style (one CBC layer), with three distinct keys, and an
80 * IV also generated from the passphrase.
81 */
82 ssh_cipher *c = ssh_cipher_new(&ssh_3des_ssh2);
83 ssh_cipher_setkey(c, vkey);
84 ssh_cipher_setiv(c, viv);
85 return c;
86 }
87
des3_decrypt_pubkey_ossh(const void * vkey,const void * viv,void * vblk,int len)88 void des3_decrypt_pubkey_ossh(const void *vkey, const void *viv,
89 void *vblk, int len)
90 {
91 ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
92 ssh_cipher_decrypt(c, vblk, len);
93 ssh_cipher_free(c);
94 }
95
des3_encrypt_pubkey_ossh(const void * vkey,const void * viv,void * vblk,int len)96 void des3_encrypt_pubkey_ossh(const void *vkey, const void *viv,
97 void *vblk, int len)
98 {
99 ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
100 ssh_cipher_encrypt(c, vblk, len);
101 ssh_cipher_free(c);
102 }
103
des_xdmauth_cipher(const void * vkeydata)104 static ssh_cipher *des_xdmauth_cipher(const void *vkeydata)
105 {
106 /*
107 * XDM-AUTHORIZATION-1 uses single-DES, but packs the key into 7
108 * bytes, so here we have to repack it manually into the canonical
109 * form where it occupies 8 bytes each with the low bit unused.
110 */
111 const unsigned char *keydata = (const unsigned char *)vkeydata;
112 unsigned char key[8];
113 int i, nbits, j;
114 unsigned int bits;
115
116 bits = 0;
117 nbits = 0;
118 j = 0;
119 for (i = 0; i < 8; i++) {
120 if (nbits < 7) {
121 bits = (bits << 8) | keydata[j];
122 nbits += 8;
123 j++;
124 }
125 key[i] = (bits >> (nbits - 7)) << 1;
126 bits &= ~(0x7F << (nbits - 7));
127 nbits -= 7;
128 }
129
130 ssh_cipher *c = ssh_cipher_new(&ssh_des);
131 ssh_cipher_setkey(c, key);
132 smemclr(key, sizeof(key));
133 ssh_cipher_setiv(c, key);
134 return c;
135 }
136
des_encrypt_xdmauth(const void * keydata,void * blk,int len)137 void des_encrypt_xdmauth(const void *keydata, void *blk, int len)
138 {
139 ssh_cipher *c = des_xdmauth_cipher(keydata);
140 ssh_cipher_encrypt(c, blk, len);
141 ssh_cipher_free(c);
142 }
143
des_decrypt_xdmauth(const void * keydata,void * blk,int len)144 void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
145 {
146 ssh_cipher *c = des_xdmauth_cipher(keydata);
147 ssh_cipher_decrypt(c, blk, len);
148 ssh_cipher_free(c);
149 }
150
hash_simple(const ssh_hashalg * alg,ptrlen data,void * output)151 void hash_simple(const ssh_hashalg *alg, ptrlen data, void *output)
152 {
153 ssh_hash *hash = ssh_hash_new(alg);
154 put_datapl(hash, data);
155 ssh_hash_final(hash, output);
156 }
157
mac_simple(const ssh2_macalg * alg,ptrlen key,ptrlen data,void * output)158 void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output)
159 {
160 ssh2_mac *mac = ssh2_mac_new(alg, NULL);
161 ssh2_mac_setkey(mac, key);
162 ssh2_mac_start(mac);
163 put_datapl(mac, data);
164 ssh2_mac_genresult(mac, output);
165 ssh2_mac_free(mac);
166 }
167