Skip to content

Commit 668bd74

Browse files
authored
Merge pull request #587 from libtom/add-pem-support
Add PEM support
2 parents f27a312 + 2594f3a commit 668bd74

File tree

371 files changed

+9723
-973
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

371 files changed

+9723
-973
lines changed

.ci/Valgrind-Ubuntu_focal.supp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
<s_decode_header>
3+
Memcheck:Cond
4+
...
5+
fun:s_decode_header
6+
}

.ci/meta_builds.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ fi
2222
function run_gcc() {
2323
bash .ci/check_source.sh "CHECK_SOURCES" "$2" "$3" "$4" "$5"
2424

25+
make -j$(nproc) pem-info V=0
26+
27+
echo "verify docs..."
28+
while read -r line; do
29+
grep -q -e "$line" doc/crypt.tex || { echo "Failed to find \"$line\" in doc/crypt.tex"; exit 1; }
30+
done < <(./pem-info | grep '^\\' | sed 's@\\@\\\\@g')
31+
echo "docs OK"
32+
2533
make clean &>/dev/null
2634

2735
echo

.ci/valgrind.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ echo "Run tests with valgrind..."
3131
for i in `seq 1 10` ; do sleep 300 && echo "Valgrind tests in Progress..."; done &
3232
alive_pid=$!
3333

34-
valgrind --error-exitcode=666 --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all ./test >test_std.txt 2> >(tee -a test_err.txt >&2) || { kill $alive_pid; echo "Valgrind failed"; exit 1; }
34+
readonly VALGRIND_OPTS="--error-exitcode=666 --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all"
35+
36+
readonly distro="$(lsb_release -si)_$(lsb_release -sc)"
37+
readonly suppfile=".ci/Valgrind-${distro}.supp"
38+
function get_suppfile() { [ -f "$suppfile" ] && echo "--suppressions=$suppfile" || echo ""; }
39+
readonly VALGRIND_EXTRA_OPTS=$(get_suppfile)
40+
41+
valgrind $VALGRIND_OPTS $VALGRIND_EXTRA_OPTS ./test >test_std.txt 2> >(tee -a test_err.txt >&2) || { kill $alive_pid; echo "Valgrind failed"; exit 1; }
3542

3643
kill $alive_pid
3744

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ multi
3434
multi.exe
3535
openssl-enc
3636
openssl-enc.exe
37+
openssh-privkey
38+
openssh-privkey.exe
39+
pem-info
40+
pem-info.exe
3741
sizes
3842
sizes.exe
3943
small

demos/openssh-privkey.c

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

demos/pem-info.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2+
/* SPDX-License-Identifier: Unlicense */
3+
/* print all PEM related infos */
4+
#include "tomcrypt_private.h"
5+
6+
#if defined(LTC_PEM_SSH)
7+
extern const struct blockcipher_info pem_dek_infos[];
8+
extern const unsigned long pem_dek_infos_num;
9+
10+
extern const struct blockcipher_info ssh_ciphers[];
11+
extern const unsigned long ssh_ciphers_num;
12+
13+
static const struct {
14+
const char *is, *should;
15+
} cipher_name_map[] = {
16+
{ "", "none" },
17+
{ "aes", "AES" },
18+
{ "blowfish", "Blowfish" },
19+
{ "c20p1305", "ChaCha20Poly1305" },
20+
{ "camellia", "Camellia" },
21+
{ "cast5", "CAST5" },
22+
{ "chacha20", "ChaCha20" },
23+
{ "3des", "3DES (EDE)" },
24+
{ "des", "DES" },
25+
{ "desx", "DES-X" },
26+
{ "idea", "IDEA" },
27+
{ "rc5", "RC5" },
28+
{ "rc2", "RC2" },
29+
{ "seed", "SEED" },
30+
{ "serpent", "Serpent" },
31+
{ "twofish", "Twofish" },
32+
};
33+
34+
static const char *s_map_cipher(const char *name)
35+
{
36+
unsigned long n;
37+
for (n = 0; n < sizeof(cipher_name_map)/sizeof(cipher_name_map[0]); ++n) {
38+
if (strcmp(name, cipher_name_map[n].is) == 0)
39+
return cipher_name_map[n].should;
40+
}
41+
fprintf(stderr, "Error: Can't map %s\n", name);
42+
exit(1);
43+
}
44+
45+
static const struct {
46+
enum cipher_mode mode;
47+
const char *name;
48+
} cipher_mode_map[] = {
49+
{ cm_none, "none", },
50+
{ cm_cbc, "CBC", },
51+
{ cm_cfb, "CFB", },
52+
{ cm_ctr, "CTR", },
53+
{ cm_ofb, "OFB", },
54+
{ cm_stream, "STREAM", },
55+
{ cm_gcm, "GCM", },
56+
};
57+
58+
static const char *s_map_mode(enum cipher_mode mode)
59+
{
60+
size_t n;
61+
mode &= cm_modes;
62+
for (n = 0; n < sizeof(cipher_mode_map)/sizeof(cipher_mode_map[0]); ++n) {
63+
if (cipher_mode_map[n].mode == mode)
64+
return cipher_mode_map[n].name;
65+
}
66+
fprintf(stderr, "Error: Can't map cipher_mode %d\n", mode);
67+
exit(1);
68+
}
69+
70+
int main(void)
71+
{
72+
unsigned long n;
73+
printf("PEM ciphers:\n\n");
74+
for (n = 0; n < pem_dek_infos_num; ++n) {
75+
char nbuf[32] = {0};
76+
size_t nlen = strlen(pem_dek_infos[n].name);
77+
memcpy(nbuf, pem_dek_infos[n].name, nlen);
78+
nbuf[nlen-1] = '}';
79+
printf("\\hline \\texttt{%-18s & %-15s & %-25ld & %-6s \\\\\n",
80+
nbuf, s_map_cipher(pem_dek_infos[n].algo),
81+
pem_dek_infos[n].keylen * 8,
82+
s_map_mode(pem_dek_infos[n].mode));
83+
}
84+
85+
printf("\nSSH ciphers:\n\n");
86+
for (n = 0; n < ssh_ciphers_num; ++n) {
87+
char nbuf[32] = {0};
88+
size_t nlen = strlen(ssh_ciphers[n].name);
89+
memcpy(nbuf, ssh_ciphers[n].name, nlen);
90+
nbuf[nlen] = '}';
91+
printf("\\hline \\texttt{%-30s & %-16s & %-24ld & %-6s \\\\\n",
92+
nbuf, s_map_cipher(ssh_ciphers[n].algo),
93+
ssh_ciphers[n].keylen * 8,
94+
s_map_mode(ssh_ciphers[n].mode));
95+
}
96+
97+
return 0;
98+
}
99+
#else
100+
int main(void) { return EXIT_FAILURE; }
101+
#endif

0 commit comments

Comments
 (0)