svnno****@sourc*****
svnno****@sourc*****
2014年 3月 13日 (木) 00:09:04 JST
Revision: 5532 http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5532 Author: yutakapon Date: 2014-03-13 00:09:04 +0900 (Thu, 13 Mar 2014) Log Message: ----------- ED25519 秘密鍵のファイル読み込み処理を更新した。 まだ正常につながりません。 Modified Paths: -------------- branches/ssh_ed25519/ttssh2/ttxssh/key.c branches/ssh_ed25519/ttssh2/ttxssh/key.h branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c -------------- next part -------------- Modified: branches/ssh_ed25519/ttssh2/ttxssh/key.c =================================================================== --- branches/ssh_ed25519/ttssh2/ttxssh/key.c 2014-03-11 15:07:30 UTC (rev 5531) +++ branches/ssh_ed25519/ttssh2/ttxssh/key.c 2014-03-12 15:09:04 UTC (rev 5532) @@ -704,6 +704,19 @@ EC_KEY_free(key->ecdsa); key->ecdsa = NULL; break; + + case KEY_ED25519: + if (key->ed25519_pk) { + memset(key->ed25519_pk, 0, ED25519_PK_SZ); + free(key->ed25519_pk); + key->ed25519_pk = NULL; + } + if (key->ed25519_sk) { + memset(key->ed25519_sk, 0, ED25519_SK_SZ); + free(key->ed25519_sk); + key->ed25519_sk = NULL; + } + break; } free(key); } @@ -737,6 +750,8 @@ return KEY_ECDSA384; } else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) { return KEY_ECDSA521; + } else if (strcmp(name, "ssh-ed25519") == 0) { + return KEY_ED25519; } return KEY_UNSPEC; } @@ -1263,3 +1278,44 @@ break; } } + +Key *key_private_deserialize(buffer_t *blob) +{ + char *type_name = NULL; + Key *k = NULL; + unsigned int pklen, sklen; + int type; + int success = 0; + + type_name = buffer_get_string_msg(blob, NULL); + type = get_keytype_from_name(type_name); + + switch (type) { + case KEY_ED25519: + k = malloc(sizeof(Key)); + memset(k, 0, sizeof(Key)); + + k->ed25519_pk = buffer_get_string_msg(blob, &pklen); + k->ed25519_sk = buffer_get_string_msg(blob, &sklen); + if (pklen != ED25519_PK_SZ) + goto error; + if (sklen != ED25519_SK_SZ) + goto error; + break; + + default: + // TODO: ED25519 \x88ȊO\x82͖\xA2\x83T\x83|\x81[\x83g\x81B + break; + } + success = 1; + +error: + free(type_name); + + if (success == 0) { + key_free(k); + k = NULL; + } + + return (k); +} Modified: branches/ssh_ed25519/ttssh2/ttxssh/key.h =================================================================== --- branches/ssh_ed25519/ttssh2/ttxssh/key.h 2014-03-11 15:07:30 UTC (rev 5531) +++ branches/ssh_ed25519/ttssh2/ttxssh/key.h 2014-03-12 15:09:04 UTC (rev 5532) @@ -61,5 +61,6 @@ ssh_keytype nid_to_keytype(int nid); void key_private_serialize(Key *key, buffer_t *b); +Key *key_private_deserialize(buffer_t *blob); #endif Modified: branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c =================================================================== --- branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c 2014-03-11 15:07:30 UTC (rev 5531) +++ branches/ssh_ed25519/ttssh2/ttxssh/keyfiles.c 2014-03-12 15:09:04 UTC (rev 5532) @@ -365,13 +365,13 @@ buffer_t *copy_consumed = NULL; // (A) Key *keyfmt = NULL; unsigned char buf[1024]; - unsigned char *cp, last; - char *ciphername = NULL, *kdfname = NULL, *kdfp = NULL, *key = NULL, *salt = NULL; + unsigned char *cp, last, pad; + char *ciphername = NULL, *kdfname = NULL, *kdfp = NULL, *key = NULL, *salt = NULL, *comment = NULL; unsigned int len, klen, nkeys, blocksize, keylen, ivlen, slen, rounds; unsigned int check1, check2, m1len, m2len; - int dlen; + int dlen, i; SSHCipher ciphernameval; - size_t authlen; + size_t authlen; EVP_CIPHER_CTX cipher_ctx; blob = buffer_init(); @@ -393,146 +393,146 @@ 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_consumed, 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_consumed, len - dlen); - if (buffer_remain_len(copy_consumed) < sizeof(AUTH_MAGIC) || - memcmp(buffer_tail_ptr(copy_consumed), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { - //error("%s: bad magic", __func__); - goto error; - } - buffer_consume(copy_consumed, 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_consumed, 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_consumed, NULL); - if (kdfname == NULL || strcmp(kdfname, KDFNAME) != 0) { - //error("%s: unknown kdf name", __func__); - goto error; - } - - /* kdf options */ - kdfp = buffer_get_string_msg(copy_consumed, &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_consumed) < 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_consumed, &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_consumed); - 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; - } - - /* setup key */ - keylen = get_cipher_key_len(ciphernameval); - ivlen = blocksize; - key = calloc(1, keylen + ivlen); - if (!strcmp(kdfname, KDFNAME)) { - salt = buffer_get_string_msg(kdf, &slen); - if (salt == NULL) { - //error("%s: salt not set", __func__); - goto error; - } - rounds = buffer_get_int(kdf); - // TODO: error check - if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, - key, keylen + ivlen, rounds) < 0) { - //error("%s: bcrypt_pbkdf failed", __func__); - goto error; - } - } - - // \x95\x9C\x8D\x86\x89\xBB - cp = buffer_append_space(b, len); + /* 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_consumed, 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_consumed, len - dlen); + if (buffer_remain_len(copy_consumed) < sizeof(AUTH_MAGIC) || + memcmp(buffer_tail_ptr(copy_consumed), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { + //error("%s: bad magic", __func__); + goto error; + } + buffer_consume(copy_consumed, 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_consumed, 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_consumed, NULL); + if (kdfname == NULL || strcmp(kdfname, KDFNAME) != 0) { + //error("%s: unknown kdf name", __func__); + goto error; + } + + /* kdf options */ + kdfp = buffer_get_string_msg(copy_consumed, &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_consumed) < 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_consumed, &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_consumed); + 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; + } + + /* setup key */ + keylen = get_cipher_key_len(ciphernameval); + ivlen = blocksize; + key = calloc(1, keylen + ivlen); + if (!strcmp(kdfname, KDFNAME)) { + salt = buffer_get_string_msg(kdf, &slen); + if (salt == NULL) { + //error("%s: salt not set", __func__); + goto error; + } + rounds = buffer_get_int(kdf); + // TODO: error check + if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, + key, keylen + ivlen, rounds) < 0) { + //error("%s: bcrypt_pbkdf failed", __func__); + goto error; + } + } + + // \x95\x9C\x8D\x86\x89\xBB + cp = buffer_append_space(b, len); cipher_init_SSH2(&cipher_ctx, key, keylen, key + keylen, ivlen, CIPHER_DECRYPT, get_cipher_EVP_CIPHER(ciphernameval), 0, pvar); if (EVP_Cipher(&cipher_ctx, cp, buffer_tail_ptr(copy_consumed), len) == 0) { @@ -540,49 +540,44 @@ goto error; } cipher_cleanup_SSH2(&cipher_ctx); - buffer_consume(copy_consumed, len); - - if (buffer_remain_len(copy_consumed) != 0) { - //error("%s: key blob has trailing data (len = %u)", __func__, - // buffer_len(©)); - goto error; - } - - /* check bytes */ - if (buffer_get_int_ret(&check1, b) < 0 || - buffer_get_int_ret(&check2, b) < 0) { - //error("check bytes missing"); - goto error; - } - if (check1 != check2) { - //debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__, - // check1, check2); - goto error; - } - -#if 0 - keyfmt = key_private_deserialize(&b); - - /* comment */ - comment = buffer_get_cstring_ret(&b, NULL); - - i = 0; - while (buffer_len(&b)) { - if (buffer_get_char_ret(&pad, &b) == -1 || - pad != (++i & 0xff)) { - error("%s: bad padding", __func__); - key_free(k); - k = NULL; - goto out; - } - } - - if (k && commentp) { - *commentp = comment; - comment = NULL; - } -#endif + buffer_consume(copy_consumed, len); + if (buffer_remain_len(copy_consumed) != 0) { + //error("%s: key blob has trailing data (len = %u)", __func__, + // buffer_len(©)); + goto error; + } + + /* check bytes */ + if (buffer_get_int_ret(&check1, b) < 0 || + buffer_get_int_ret(&check2, b) < 0) { + //error("check bytes missing"); + goto error; + } + if (check1 != check2) { + //debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__, + // check1, check2); + goto error; + } + + keyfmt = key_private_deserialize(b); + if (keyfmt == NULL) + goto error; + + /* comment */ + comment = buffer_get_string_msg(b, NULL); + + i = 0; + while (buffer_remain_len(b)) { + if (buffer_get_char_ret(&pad, b) == -1 || + pad != (++i & 0xff)) { + //error("%s: bad padding", __func__); + key_free(keyfmt); + keyfmt = NULL; + goto error; + } + } + /* success */ error: @@ -597,6 +592,7 @@ free(kdfp); free(key); free(salt); + free(comment); // ED25519 \x82ł͂Ȃ\xA9\x82\xC1\x82\xBD if (keyfmt == NULL) {