svnno****@sourc*****
svnno****@sourc*****
2014年 3月 11日 (火) 21:49:21 JST
Revision: 5530 http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5530 Author: yutakapon Date: 2014-03-11 21:49:21 +0900 (Tue, 11 Mar 2014) Log Message: ----------- ED25519 秘密鍵のファイル読み込み処理の追加。 まだ、途中です。 Modified Paths: -------------- branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.h -------------- next part -------------- Modified: branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c =================================================================== --- branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c 2014-03-11 12:48:54 UTC (rev 5529) +++ branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c 2014-03-11 12:49:21 UTC (rev 5530) @@ -342,6 +342,218 @@ // SSH2 // +// ED25519 \x8C`\x8E\xAE\x82œǂ\xDE +// based on key_parse_private2() @ OpenSSH 6.5 +static Key *read_SSH2_private2_key(PTInstVar pvar, + FILE * fp, + char * passphrase, + BOOL * invalid_passphrase, + BOOL is_auto_login, + char *errmsg, + int errmsg_len) +{ + buffer_t *blob = NULL; + buffer_t *b = NULL; + buffer_t *kdf = NULL; + buffer_t *encoded = NULL; + buffer_t *copy = NULL; + Key *key = NULL; + unsigned char buf[1024]; + unsigned char *cp, last; + char *ciphername = NULL, *kdfname = NULL, *kdfp = NULL; + unsigned int len, klen, nkeys, blocksize; + unsigned int check1, check2, m1len, m2len; + int dlen; + SSHCipher ciphernameval; + size_t authlen; + + blob = buffer_init(); + b = buffer_init(); + kdf = buffer_init(); + encoded = buffer_init(); + copy = buffer_init(); + if (blob == NULL || b == NULL || kdf == NULL || encoded == NULL || copy == NULL) + goto error; + + // \x83t\x83@\x83C\x83\x8B\x82\xF0\x82\xB7\x82ׂēǂݍ\x9E\x82\xDE + for (;;) { + len = fread(buf, 1, sizeof(buf), fp); + buffer_append(blob, buf, len); + if (buffer_len(blob) > MAX_KEY_FILE_SIZE) { + goto error; + } + if (len < sizeof(buf)) + break; + } + + /* uudecode */ + m1len = sizeof(MARK_BEGIN) - 1; + m2len = sizeof(MARK_END) - 1; + cp = buffer_ptr(blob); + len = buffer_len(blob); + if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) { + //debug("%s: missing begin marker", __func__); + goto error; + } + cp += m1len; + len -= m1len; + while (len) { + if (*cp != '\n' && *cp != '\r') + buffer_put_char(encoded, *cp); + last = *cp; + len--; + cp++; + if (last == '\n') { + if (len >= m2len && !memcmp(cp, MARK_END, m2len)) { + buffer_put_char(encoded, '\0'); + break; + } + } + } + if (!len) { + //debug("%s: no end marker", __func__); + goto error; + } + + // \x83t\x83@\x83C\x83\x8B\x82̃X\x83L\x83\x83\x83\x93\x82\xAA\x8FI\x82\xED\x82\xC1\x82\xBD\x82̂ŁAuudecode\x82\xB7\x82\xE9\x81B + len = buffer_len(encoded); + if ((cp = buffer_append_space(copy, len)) == NULL) { + //error("%s: buffer_append_space", __func__); + goto error; + } + if ((dlen = uudecode(buffer_ptr(encoded), buffer_len(encoded), cp, len)) < 0) { + //error("%s: uudecode failed", __func__); + goto error; + } + if ((unsigned int)dlen > len) { + //error("%s: crazy uudecode length %d > %u", __func__, dlen, len); + goto error; + } + + buffer_consume_end(copy, len - dlen); + if (buffer_len(copy) < sizeof(AUTH_MAGIC) || + memcmp(buffer_ptr(copy), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { + //error("%s: bad magic", __func__); + goto error; + } + buffer_consume(copy, sizeof(AUTH_MAGIC)); + + /* + * \x83f\x83R\x81[\x83h\x82\xB5\x82\xBD\x83f\x81[\x83^\x82\xF0\x89\xF0\x90͂\xB7\x82\xE9\x81B + */ + // \x88Í\x86\x89\xBB\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̖\xBC\x91O + ciphername = buffer_get_string_msg(copy, NULL); + ciphernameval = get_cipher_by_name(ciphername); + if (ciphernameval == SSH_CIPHER_NONE) { + //error("%s: unknown cipher name", __func__); + goto error; + } + // \x83p\x83X\x83t\x83\x8C\x81[\x83Y\x82̃`\x83F\x83b\x83N\x81B\x8B\xF3\x82̃p\x83X\x83\x8F\x81[\x83h\x82͔F\x82߂Ȃ\xA2\x81B + if (passphrase == NULL || strlen(passphrase) == 0) { + /* passphrase required */ + goto error; + } + + kdfname = buffer_get_string_msg(copy, NULL); + if (kdfname == NULL || strcmp(kdfname, KDFNAME) != 0) { + //error("%s: unknown kdf name", __func__); + goto error; + } + + /* kdf options */ + kdfp = buffer_get_string_msg(copy, &klen); + if (kdfp == NULL) { + //error("%s: kdf options not set", __func__); + goto error; + } + if (klen > 0) { + if ((cp = buffer_append_space(kdf, klen)) == NULL) { + //error("%s: kdf alloc failed", __func__); + goto error; + } + memcpy(cp, kdfp, klen); + } + + /* number of keys */ + if (buffer_get_int_ret(&nkeys, copy) < 0) { + //error("%s: key counter missing", __func__); + goto error; + } + if (nkeys != 1) { + //error("%s: only one key supported", __func__); + goto error; + } + + /* pubkey */ + cp = buffer_get_string_msg(copy, &len); + if (cp == NULL) { + //error("%s: pubkey not found", __func__); + goto error; + } + free(cp); /* XXX check pubkey against decrypted private key */ + + /* size of encrypted key blob */ + len = buffer_get_int(copy); + blocksize = get_cipher_block_size(ciphernameval); + authlen = 0; // TODO: \x82Ƃ肠\x82\xA6\x82\xB8\x8CŒ艻 + if (len < blocksize) { + //error("%s: encrypted data too small", __func__); + goto error; + } + if (len % blocksize) { + //error("%s: length not multiple of blocksize", __func__); + goto error; + } + +#if 0 + /* setup key */ + keylen = cipher_keylen(c); + ivlen = cipher_ivlen(c); + key = xcalloc(1, keylen + ivlen); + if (!strcmp(kdfname, "bcrypt")) { + if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) { + error("%s: salt not set", __func__); + goto out; + } + if (buffer_get_int_ret(&rounds, &kdf) < 0) { + error("%s: rounds not set", __func__); + goto out; + } + if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, + key, keylen + ivlen, rounds) < 0) { + error("%s: bcrypt_pbkdf failed", __func__); + goto out; + } + } +#endif + + + /* success */ + +error: + buffer_free(blob); + buffer_free(b); + buffer_free(kdf); + buffer_free(encoded); + buffer_free(copy); + + free(ciphername); + free(kdfname); + free(kdfp); + + // ED25519 \x82ł͂Ȃ\xA9\x82\xC1\x82\xBD + if (key == NULL) { + fseek(fp, 0, SEEK_SET); + + } else { + fclose(fp); + + } + + return (key); +} + + // OpenSSL format Key *read_SSH2_private_key(PTInstVar pvar, FILE * fp, @@ -359,6 +571,10 @@ ERR_load_crypto_strings(); //seed_prng(); + result = read_SSH2_private2_key(pvar, fp, passphrase, invalid_passphrase, is_auto_login, errmsg, errmsg_len); + if (result) + return (result); + result = (Key *)malloc(sizeof(Key)); ZeroMemory(result, sizeof(Key)); Modified: branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.h =================================================================== --- branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.h 2014-03-11 12:48:54 UTC (rev 5529) +++ branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.h 2014-03-11 12:49:21 UTC (rev 5530) @@ -86,9 +86,22 @@ {SSH2_KEYFILE_TYPE_OPENSSH, "-----BEGIN DSA PRIVATE KEY-----"}, {SSH2_KEYFILE_TYPE_OPENSSH, "-----BEGIN EC PRIVATE KEY-----"}, {SSH2_KEYFILE_TYPE_OPENSSH, "-----BEGIN ENCRYPTED PRIVATE KEY-----"}, + {SSH2_KEYFILE_TYPE_OPENSSH, "-----BEGIN OPENSSH PRIVATE KEY-----"}, {SSH2_KEYFILE_TYPE_PUTTY, "PuTTY-User-Key-File-2"}, {SSH2_KEYFILE_TYPE_SECSH, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"}, {SSH2_KEYFILE_TYPE_NONE, NULL}, }; + +/* openssh private key file format */ +#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" +#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" +#define KDFNAME "bcrypt" +#define AUTH_MAGIC "openssh-key-v1" +#define SALT_LEN 16 +#define DEFAULT_CIPHERNAME "aes256-cbc" +#define DEFAULT_ROUNDS 16 + +#define MAX_KEY_FILE_SIZE (1024 * 1024) + #endif