Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/keyfiles-putty.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9258 - (show annotations) (download) (as text)
Wed May 19 15:39:46 2021 UTC (2 years, 10 months ago) by nmaya
File MIME type: text/x-csrc
File size: 9913 byte(s)
PuTTY private key format version 3 (PPK3) に対応

MF4-stable: r9256, r9257
1 /* Imported from PuTTY 0.74, 0.75, TeraTerm Project */
2
3 /*
4 * (C) 2021- TeraTerm Project
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "ttxssh.h"
32 #include "keyfiles-putty.h"
33
34 // from sshpubk.c (ver 0.75)
35 BOOL str_to_uint32_t(const char *s, uint32_t *out)
36 {
37 char *endptr;
38 unsigned long converted = strtoul(s, &endptr, 10);
39 if (*s && !*endptr && converted <= ~(uint32_t)0) {
40 *out = converted;
41 return TRUE;
42 } else {
43 return FALSE;
44 }
45 }
46
47 // from sshpubk.c (ver 0.74)
48 BOOL ppk_read_header(FILE * fp, char *header)
49 {
50 int len = 39;
51 int c;
52
53 while (1) {
54 c = fgetc(fp);
55 if (c == '\n' || c == '\r' || c == EOF)
56 return FALSE;
57 if (c == ':') {
58 c = fgetc(fp);
59 if (c != ' ')
60 return FALSE;
61 *header = '\0';
62 return TRUE;
63 }
64 if (len == 0)
65 return FALSE;
66 *header++ = c;
67 len--;
68 }
69 return FALSE;
70 }
71
72 // from sshpubk.c (ver 0.74)
73 char *ppk_read_body(FILE * fp)
74 {
75 buffer_t *buf = buffer_init();
76
77 while (1) {
78 int c = fgetc(fp);
79 if (c == '\r' || c == '\n' || c == EOF) {
80 if (c != EOF) {
81 c = fgetc(fp);
82 if (c != '\r' && c != '\n')
83 ungetc(c, fp);
84 }
85 return buffer_ptr(buf);
86 }
87 buffer_put_char(buf, c);
88 }
89 }
90
91 // from sshpubk.c (ver 0.74), and modified
92 // - use buffer_t insted of strbuf
93 // - use OpenSSL function
94 BOOL ppk_read_blob(FILE* fp, int nlines, buffer_t *blob)
95 {
96 BIO *bmem, *b64, *chain;
97 int i, len;
98 char line[200], buf[100];
99
100 b64 = BIO_new(BIO_f_base64());
101 bmem = BIO_new(BIO_s_mem());
102 for (i=0; i<nlines && fgets(line, sizeof(line), fp)!=NULL; i++) {
103 BIO_write(bmem, line, strlen(line));
104 }
105 BIO_flush(bmem);
106 chain = BIO_push(b64, bmem);
107 BIO_set_mem_eof_return(chain, 0);
108 while ((len = BIO_read(chain, buf, sizeof(buf))) > 0) {
109 buffer_append(blob, buf, len);
110 }
111 BIO_free_all(chain);
112
113 return TRUE;
114 }
115
116 // from sshsha.c (ver 0.70), and modifled
117 // - use OpenSSL function
118 void hmac_sha1_simple(unsigned char *key, int keylen, void *data, int datalen,
119 unsigned char *output)
120 {
121 EVP_MD_CTX *ctx[2] = {0, 0};
122 unsigned char intermediate[20];
123 unsigned char foo[64];
124 const EVP_MD *md = EVP_sha1();
125 int i;
126 unsigned int len;
127
128 ctx[0] = EVP_MD_CTX_new();
129 if (ctx[0] == NULL) {
130 return;
131 }
132 ctx[1] = EVP_MD_CTX_new();
133 if (ctx[1] == NULL) {
134 EVP_MD_CTX_free(ctx[0]);
135 return;
136 }
137
138 memset(foo, 0x36, sizeof(foo));
139 for (i = 0; i < keylen && i < sizeof(foo); i++) {
140 foo[i] ^= key[i];
141 }
142 EVP_DigestInit(ctx[0], md);
143 EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
144
145 memset(foo, 0x5C, sizeof(foo));
146 for (i = 0; i < keylen && i < sizeof(foo); i++) {
147 foo[i] ^= key[i];
148 }
149 EVP_DigestInit(ctx[1], md);
150 EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
151
152 memset(foo, 0, sizeof(foo));
153
154 EVP_DigestUpdate(ctx[0], data, datalen);
155 EVP_DigestFinal(ctx[0], intermediate, &len);
156
157 EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
158 EVP_DigestFinal(ctx[1], output, &len);
159
160 EVP_MD_CTX_free(ctx[0]);
161 EVP_MD_CTX_free(ctx[1]);
162 }
163
164 void hmac_sha256_simple(unsigned char *key, int keylen, void *data, int datalen,
165 unsigned char *output)
166 {
167 EVP_MD_CTX *ctx[2] = {0, 0};
168 unsigned char intermediate[32];
169 unsigned char foo[64];
170 const EVP_MD *md = EVP_sha256();
171 int i;
172 unsigned int len;
173
174 ctx[0] = EVP_MD_CTX_new();
175 if (ctx[0] == NULL) {
176 return;
177 }
178 ctx[1] = EVP_MD_CTX_new();
179 if (ctx[1] == NULL) {
180 EVP_MD_CTX_free(ctx[0]);
181 return;
182 }
183
184 memset(foo, 0x36, sizeof(foo));
185 for (i = 0; i < keylen && i < sizeof(foo); i++) {
186 foo[i] ^= key[i];
187 }
188 EVP_DigestInit(ctx[0], md);
189 EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
190
191 memset(foo, 0x5C, sizeof(foo));
192 for (i = 0; i < keylen && i < sizeof(foo); i++) {
193 foo[i] ^= key[i];
194 }
195 EVP_DigestInit(ctx[1], md);
196 EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
197
198 memset(foo, 0, sizeof(foo));
199
200 EVP_DigestUpdate(ctx[0], data, datalen);
201 EVP_DigestFinal(ctx[0], intermediate, &len);
202
203 EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
204 EVP_DigestFinal(ctx[1], output, &len);
205
206 EVP_MD_CTX_free(ctx[0]);
207 EVP_MD_CTX_free(ctx[1]);
208 }
209
210 // from sshsha.c (ver 0.70) hmac_sha1_simple
211 // sshauxcrypt.c (ver 0.75) mac_simple, and modifled
212 // - use OpenSSL function
213 // - use EVP_MD instead of ssh2_macalg
214 void mac_simple(const EVP_MD *md,
215 unsigned char *key, int keylen, void *data, int datalen,
216 unsigned char *output)
217 {
218 EVP_MD_CTX *ctx[2] = {0, 0};
219 unsigned char intermediate[32]; // sha1: 160bit / sha256: 256bit
220 unsigned char foo[64]; // block size ... sha1: 512bit / sha256: 512bit
221 int i;
222 unsigned int len;
223
224 ctx[0] = EVP_MD_CTX_new();
225 if (ctx[0] == NULL) {
226 return;
227 }
228 ctx[1] = EVP_MD_CTX_new();
229 if (ctx[1] == NULL) {
230 EVP_MD_CTX_free(ctx[0]);
231 return;
232 }
233
234 memset(foo, 0x36, sizeof(foo));
235 for (i = 0; i < keylen && i < sizeof(foo); i++) {
236 foo[i] ^= key[i];
237 }
238 EVP_DigestInit(ctx[0], md);
239 EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
240
241 memset(foo, 0x5C, sizeof(foo));
242 for (i = 0; i < keylen && i < sizeof(foo); i++) {
243 foo[i] ^= key[i];
244 }
245 EVP_DigestInit(ctx[1], md);
246 EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
247
248 memset(foo, 0, sizeof(foo));
249
250 EVP_DigestUpdate(ctx[0], data, datalen);
251 EVP_DigestFinal(ctx[0], intermediate, &len);
252
253 EVP_DigestUpdate(ctx[1], intermediate, EVP_MD_size(md));
254 EVP_DigestFinal(ctx[1], output, &len);
255
256 EVP_MD_CTX_free(ctx[0]);
257 EVP_MD_CTX_free(ctx[1]);
258 }
259
260 // from sshpubk.c (ver 0.75), and modifled
261 // - delete unnecessary paramters
262 // - use char ** and int * instead of ptrlen
263 // - use buffer_t instead of strbuf
264 // - use OpenSSL function
265 // - use argon2 function
266 void ssh2_ppk_derive_keys(
267 unsigned fmt_version, const struct ssh2cipher* ciphertype,
268 unsigned char *passphrase, buffer_t *storage,
269 unsigned char **cipherkey, unsigned int *cipherkey_len,
270 unsigned char **cipheriv, unsigned int *cipheriv_len,
271 unsigned char **mackey, unsigned int *mackey_len,
272 ppk_argon2_parameters *params)
273 {
274 size_t mac_keylen = 0;
275 u_int ivlen;
276 unsigned int cipherkey_offset = 0;
277
278 ivlen = (ciphertype->iv_len == 0) ? ciphertype->block_size : ciphertype->iv_len;
279
280 switch (fmt_version) {
281 case 3: {
282 uint32_t taglen;
283 unsigned char *tag;
284
285 if (ciphertype->key_len == 0) {
286 mac_keylen = 0;
287 break;
288 }
289 mac_keylen = 32;
290 taglen = ciphertype->key_len + ivlen + mac_keylen;
291 tag = (char *)malloc(taglen);
292
293 argon2_hash(params->argon2_passes, params->argon2_mem,
294 params->argon2_parallelism,
295 passphrase, strlen(passphrase),
296 params->salt, params->saltlen,
297 tag, taglen,
298 NULL, 0,
299 params->type, 0x13);
300 buffer_append(storage, tag, taglen);
301
302 free(tag);
303
304 break;
305 }
306 case 2: {
307 unsigned ctr;
308 const EVP_MD *md = EVP_sha1();
309 EVP_MD_CTX *ctx = NULL;
310 unsigned char u[4], buf[20]; // SHA1: 20byte
311 unsigned int i, len, cipherkey_write_byte = 0;
312
313 ctx = EVP_MD_CTX_new();
314
315 /* Counter-mode iteration to generate cipher key data. */
316 for (ctr = 0; ctr * 20 < ciphertype->key_len; ctr++) {
317 EVP_DigestInit(ctx, md);
318 set_uint32_MSBfirst(u, ctr);
319 EVP_DigestUpdate(ctx, u, 4);
320 EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
321 EVP_DigestFinal(ctx, buf, &len);
322 buffer_append(storage, buf, 20);
323 cipherkey_write_byte += 20;
324 }
325 // TTSSH �� buffer_t ���� shrink �������������������A
326 // shrink ������ 40byte ������ 32byte �������g��
327 cipherkey_offset = cipherkey_write_byte - ciphertype->key_len;
328
329 /* In this version of the format, the CBC IV was always all 0. */
330 for (i = 0; i < ivlen; i++) {
331 buffer_put_char(storage, 0);
332 }
333
334 /* Completely separate hash for the MAC key. */
335 EVP_DigestInit(ctx, md);
336 mac_keylen = EVP_MD_size(md); // SHA1: 20byte
337 EVP_DigestUpdate(ctx, "putty-private-key-file-mac-key", 30);
338 EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
339 EVP_DigestFinal(ctx, buf, &len);
340 buffer_append(storage, buf, mac_keylen);
341
342 EVP_MD_CTX_free(ctx);
343
344 break;
345 }
346 }
347
348 *cipherkey = storage->buf;
349 *cipherkey_len = ciphertype->key_len;
350 *cipheriv = storage->buf + ciphertype->key_len + cipherkey_offset;
351 *cipheriv_len = ivlen;
352 *mackey = storage->buf + ciphertype->key_len + cipherkey_offset + ivlen;
353 *mackey_len = mac_keylen;
354 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26