-
Notifications
You must be signed in to change notification settings - Fork 447
/
openssh-privkey.c
135 lines (118 loc) · 3.22 KB
/
openssh-privkey.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
/**
@file openssh-privkey.c
OpenSSH Private Key decryption demo, Steffen Jaeckel
*/
#include <tomcrypt.h>
#include <stdarg.h>
#include <termios.h>
#if defined(LTC_PEM) && defined(LTC_SSH)
static void print_err(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
static void die_(int err, int line)
{
print_err("%3d: LTC sez %s\n", line, error_to_string(err));
exit(EXIT_FAILURE);
}
#define die(i) do { die_(i, __LINE__); } while(0)
#define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
static char* getpassword(const char *prompt, size_t maxlen)
{
char *wr, *end, *pass = XCALLOC(1, maxlen + 1);
struct termios tio;
tcflag_t c_lflag;
if (pass == NULL)
return NULL;
wr = pass;
end = pass + maxlen;
tcgetattr(0, &tio);
c_lflag = tio.c_lflag;
tio.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &tio);
printf("%s", prompt);
fflush(stdout);
while (pass < end) {
int c = getchar();
if (c == '\r' || c == '\n' || c == -1)
break;
*wr++ = c;
}
tio.c_lflag = c_lflag;
tcsetattr(0, TCSAFLUSH, &tio);
printf("\n");
return pass;
}
static int password_get(void **p, unsigned long *l, void *u)
{
(void)u;
*p = getpassword("Enter passphrase: ", 256);
*l = strlen(*p);
return 0;
}
static void print(ltc_pka_key *k)
{
int err = CRYPT_OK;
unsigned char buf[256];
unsigned long lbuf = sizeof(buf);
char pubkey[256*4/3];
unsigned long lpubkey = sizeof(pubkey);
void *mpint = NULL;
switch (k->id) {
case LTC_PKA_ED25519:
ltc_mp.init(&mpint);
ltc_mp.unsigned_read(mpint, k->u.ed25519.pub, sizeof(k->u.ed25519.pub));
if ((err = ssh_encode_sequence_multi(buf, &lbuf,
LTC_SSHDATA_STRING, "ssh-ed25519", strlen("ssh-ed25519"),
LTC_SSHDATA_MPINT, mpint,
0, NULL)) != CRYPT_OK)
goto errout;
if ((err = base64_encode(buf, lbuf, pubkey, &lpubkey)) != CRYPT_OK)
goto errout;
printf("\rssh-ed25519 %s\n", pubkey);
break;
default:
print_err("Unsupported key type: %d\n", k->id);
break;
}
errout:
if (mpint != NULL)
ltc_mp.deinit(mpint);
if (err != CRYPT_OK)
die(err);
}
int main(int argc, char **argv)
{
int err;
FILE *f = NULL;
ltc_pka_key k;
password_ctx pw_ctx = { .callback = password_get };
if ((err = register_all_ciphers()) != CRYPT_OK) {
die(err);
}
if ((err = register_all_hashes()) != CRYPT_OK) {
die(err);
}
if ((err = crypt_mp_init("ltm")) != CRYPT_OK) {
die(err);
}
if (argc > 1) f = fopen(argv[1], "r");
else f = stdin;
if (f == NULL) DIE("fopen sez no");
if ((err = pem_decode_openssh_filehandle(f, &k, &pw_ctx))) {
die(err);
}
print(&k);
return EXIT_SUCCESS;
}
#else
int main(void) { return EXIT_FAILURE; }
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */