Skip to content

Commit 4d9823f

Browse files
committed
Update docs
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent 1725ed8 commit 4d9823f

File tree

8 files changed

+208
-25
lines changed

8 files changed

+208
-25
lines changed

.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

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ openssl-enc
3636
openssl-enc.exe
3737
openssh-privkey
3838
openssh-privkey.exe
39+
pem-info
40+
pem-info.exe
3941
sizes
4042
sizes.exe
4143
small

demos/pem-info.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
{ "camellia", "Camellia" },
20+
{ "cast5", "CAST5" },
21+
{ "3des", "3DES (EDE)" },
22+
{ "des", "DES" },
23+
{ "idea", "IDEA" },
24+
{ "rc5", "RC5" },
25+
{ "rc2", "RC2" },
26+
{ "seed", "SEED" },
27+
{ "serpent", "Serpent" },
28+
{ "twofish", "Twofish" },
29+
};
30+
31+
static const char *s_map_cipher(const char *name)
32+
{
33+
unsigned long n;
34+
for (n = 0; n < sizeof(cipher_name_map)/sizeof(cipher_name_map[0]); ++n) {
35+
if (strcmp(name, cipher_name_map[n].is) == 0)
36+
return cipher_name_map[n].should;
37+
}
38+
fprintf(stderr, "Error: Can't map %s\n", name);
39+
exit(1);
40+
}
41+
42+
static const char *cipher_mode_map[] = {
43+
"none", "CBC", "CFB", "CTR", "OFB", "STREAM", "GCM"
44+
};
45+
46+
static const char *s_map_mode(enum cipher_mode mode)
47+
{
48+
if (mode >= 0 && mode <= sizeof(cipher_mode_map)/sizeof(cipher_mode_map[0]))
49+
return cipher_mode_map[mode];
50+
fprintf(stderr, "Error: Can't map cipher_mode %d\n", mode);
51+
exit(1);
52+
}
53+
54+
int main(void)
55+
{
56+
unsigned long n;
57+
printf("PEM ciphers:\n\n");
58+
for (n = 0; n < pem_dek_infos_num; ++n) {
59+
char nbuf[20] = {0};
60+
size_t nlen = strlen(pem_dek_infos[n].name);
61+
memcpy(nbuf, pem_dek_infos[n].name, nlen);
62+
nbuf[nlen-1] = '}';
63+
printf("\\hline \\texttt{%-18s & %-15s & %-25ld & %s \\\\\n",
64+
nbuf, s_map_cipher(pem_dek_infos[n].algo),
65+
pem_dek_infos[n].keylen * 8,
66+
s_map_mode(pem_dek_infos[n].mode));
67+
}
68+
69+
printf("\nSSH ciphers:\n\n");
70+
for (n = 0; n < ssh_ciphers_num; ++n) {
71+
char nbuf[20] = {0};
72+
size_t nlen = strlen(ssh_ciphers[n].name);
73+
memcpy(nbuf, ssh_ciphers[n].name, nlen);
74+
nbuf[nlen] = '}';
75+
printf("\\hline \\texttt{%-18s & %-15s & %-25ld & %-4s \\\\\n",
76+
nbuf, s_map_cipher(ssh_ciphers[n].algo),
77+
ssh_ciphers[n].keylen * 8,
78+
s_map_mode(ssh_ciphers[n].mode));
79+
}
80+
81+
return 0;
82+
}
83+
#else
84+
int main(void) { return EXIT_FAILURE; }
85+
#endif

doc/crypt.tex

Lines changed: 107 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5117,7 +5117,7 @@ \chapter{Elliptic Curve Cryptography - $GF(p)$}
51175117
analogy for digital signatures (also known as \textit{ECDSA}).
51185118

51195119
\mysection{Supported Curves}
5120-
\label{supported-curvers}
5120+
\label{supported-curves}
51215121

51225122
The following table \ref{fig:builtincurves} shows all built--in curves supported by the library. On top of that one can also use a custom curve
51235123
defined by own parameters (the only limitation is that the curve must be based on equation \ref{ecc-gf-p-equation}).
@@ -7442,7 +7442,7 @@ \subsection{De- and Encoding with Multiple Argument Lists}
74427442
\mysection{PEM Files}
74437443
\label{pem-files}
74447444
\subsection{Introduction}
7445-
LibTomCrypt supports reading of asymmetric cryptography private keys out of
7445+
LibTomCrypt supports reading of asymmetric cryptography keys out of
74467446
PEM files in multiple formats.
74477447

74487448
The library provides support for:
@@ -7499,6 +7499,17 @@ \subsection{The PKA Union}
74997499
void pka_key_free(ltc_pka_key *key);
75007500
\end{verbatim}
75017501

7502+
\subsection{Generic PEM API}
7503+
7504+
The generic API functions provided to decode a PEM file into the \texttt{ltc\_pka\_key} union are:
7505+
7506+
\begin{verbatim}
7507+
int pem_decode_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx);
7508+
int pem_decode(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx);
7509+
\end{verbatim}
7510+
7511+
Additional to that, there exist specific API functions for the two supported classes of PEM files.
7512+
75027513
\subsection{PKCS PEM files}
75037514

75047515
The library supports the following types of PKCS PEM files:
@@ -7514,42 +7525,83 @@ \subsection{PKCS PEM files}
75147525
The identifiers in the PEM headers recognized are as follows:
75157526

75167527
\begin{table}[H]
7517-
\begin{center}
75187528
\begin{small}
7519-
\begin{tabular}{|l|l|l|l|}
7520-
\hline \textbf{Identifier} & \textbf{Encrypted} & \textbf{Standard} & \textbf{Type} \\
7521-
\hline \texttt{BEGIN ENCRYPTED PRIVATE KEY} & Yes & \texttt{PKCS \#8} & DSA, ECC, Ed25519, RSA, X25519 \\
7522-
\hline \texttt{BEGIN PRIVATE KEY} & No & \texttt{PKCS \#8} & DSA, ECC, Ed25519, RSA, X25519 \\
7523-
\hline \texttt{BEGIN DSA PRIVATE KEY} & Maybe & \texttt{PKCS \#1} & DSA \\
7524-
\hline \texttt{BEGIN EC PRIVATE KEY} & Maybe & \texttt{RFC 5915} & ECC \\
7525-
\hline \texttt{BEGIN RSA PRIVATE KEY} & Maybe & \texttt{PKCS \#1} & RSA \\
7529+
\begin{tabular}{|l|l|l|l|l|}
7530+
\hline \textbf{Identifier} & \textbf{Key type} & \textbf{File content} & \textbf{Standard} & \textbf{Algorithm} \\
7531+
\hline \texttt{BEGIN CERTIFICATE} & Public & Plain & \texttt{X.509} & DH, DSA, ECC, Ed25519, RSA, X25519 \\
7532+
\hline \texttt{BEGIN DSA PRIVATE KEY} & Private & Maybe encrypted & \texttt{PKCS \#1} & DSA \\
7533+
\hline \texttt{BEGIN EC PRIVATE KEY} & Private & Maybe encrypted & \texttt{RFC 5915} & ECC \\
7534+
\hline \texttt{BEGIN ENCRYPTED PRIVATE KEY} & Private & Encrypted & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, RSA, X25519 \\
7535+
\hline \texttt{BEGIN PRIVATE KEY} & Private & Plain & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, RSA, X25519 \\
7536+
\hline \texttt{BEGIN PUBLIC KEY} & Public & Plain & \texttt{PKCS \#8} & DH, DSA, ECC, Ed25519, RSA, X25519 \\
7537+
\hline \texttt{BEGIN RSA PRIVATE KEY} & Private & Maybe encrypted & \texttt{PKCS \#1} & RSA \\
7538+
\hline \texttt{BEGIN RSA PUBLIC KEY} & Public & Plain & \texttt{PKCS \#1} & RSA \\
75267539
\hline
75277540
\end{tabular}
75287541
\end{small}
7529-
\end{center}
7530-
\caption{List of supported PKCS private key types}
7531-
\label{supported-pkcs-private-key-types}
7542+
\caption{List of supported PEM headers}
7543+
\label{supported-PEM-headers}
75327544
\end{table}
75337545

75347546
When dealing with PEM formatted private keys the following encryption algorithms are supported:
75357547

75367548
\begin{table}[H]
7537-
\begin{center}
75387549
\begin{small}
75397550
\begin{tabular}{|l|l|l|l|}
75407551
\hline \textbf{Identifier} & \textbf{Cipher} & \textbf{Key size in bits} & \textbf{Mode} \\
75417552
\hline \texttt{AES-128-CBC} & AES & 128 & CBC \\
75427553
\hline \texttt{AES-192-CBC} & AES & 192 & CBC \\
75437554
\hline \texttt{AES-256-CBC} & AES & 256 & CBC \\
7555+
\hline \texttt{AES-128-CFB} & AES & 128 & CFB \\
7556+
\hline \texttt{AES-192-CFB} & AES & 192 & CFB \\
7557+
\hline \texttt{AES-256-CFB} & AES & 256 & CFB \\
7558+
\hline \texttt{AES-128-CTR} & AES & 128 & CTR \\
7559+
\hline \texttt{AES-192-CTR} & AES & 192 & CTR \\
7560+
\hline \texttt{AES-256-CTR} & AES & 256 & CTR \\
7561+
\hline \texttt{AES-128-OFB} & AES & 128 & OFB \\
7562+
\hline \texttt{AES-192-OFB} & AES & 192 & OFB \\
7563+
\hline \texttt{AES-256-OFB} & AES & 256 & OFB \\
7564+
\hline \texttt{BF-CBC} & Blowfish & 128 & CBC \\
7565+
\hline \texttt{BF-CFB} & Blowfish & 128 & CFB \\
7566+
\hline \texttt{BF-OFB} & Blowfish & 128 & OFB \\
75447567
\hline \texttt{CAMELLIA-128-CBC} & Camellia & 128 & CBC \\
75457568
\hline \texttt{CAMELLIA-192-CBC} & Camellia & 192 & CBC \\
75467569
\hline \texttt{CAMELLIA-256-CBC} & Camellia & 256 & CBC \\
7570+
\hline \texttt{CAMELLIA-128-CFB} & Camellia & 128 & CFB \\
7571+
\hline \texttt{CAMELLIA-192-CFB} & Camellia & 192 & CFB \\
7572+
\hline \texttt{CAMELLIA-256-CFB} & Camellia & 256 & CFB \\
7573+
\hline \texttt{CAMELLIA-128-CTR} & Camellia & 128 & CTR \\
7574+
\hline \texttt{CAMELLIA-192-CTR} & Camellia & 192 & CTR \\
7575+
\hline \texttt{CAMELLIA-256-CTR} & Camellia & 256 & CTR \\
7576+
\hline \texttt{CAMELLIA-128-OFB} & Camellia & 128 & OFB \\
7577+
\hline \texttt{CAMELLIA-192-OFB} & Camellia & 192 & OFB \\
7578+
\hline \texttt{CAMELLIA-256-OFB} & Camellia & 256 & OFB \\
7579+
\hline \texttt{CAST5-CBC} & CAST5 & 128 & CBC \\
7580+
\hline \texttt{CAST5-CFB} & CAST5 & 128 & CFB \\
7581+
\hline \texttt{CAST5-OFB} & CAST5 & 128 & OFB \\
75477582
\hline \texttt{DES-EDE3-CBC} & 3DES (EDE) & 192 & CBC \\
7548-
\hline \texttt{DES-CBC} & DES & 64 & CBC \\
7583+
\hline \texttt{DES-EDE3-CFB} & 3DES (EDE) & 192 & CFB \\
7584+
\hline \texttt{DES-EDE3-OFB} & 3DES (EDE) & 192 & OFB \\
7585+
\hline \texttt{DES-CBC} & DES & 64 & CBC \\
7586+
\hline \texttt{DES-CFB} & DES & 64 & CFB \\
7587+
\hline \texttt{DES-OFB} & DES & 64 & OFB \\
7588+
\hline \texttt{IDEA-CBC} & IDEA & 128 & CBC \\
7589+
\hline \texttt{IDEA-CFB} & IDEA & 128 & CFB \\
7590+
\hline \texttt{IDEA-OFB} & IDEA & 128 & OFB \\
7591+
\hline \texttt{RC5-CBC} & RC5 & 128 & CBC \\
7592+
\hline \texttt{RC5-CFB} & RC5 & 128 & CFB \\
7593+
\hline \texttt{RC5-OFB} & RC5 & 128 & OFB \\
7594+
\hline \texttt{RC2-40-CBC} & RC2 & 40 & CBC \\
7595+
\hline \texttt{RC2-64-CBC} & RC2 & 64 & CBC \\
7596+
\hline \texttt{RC2-CBC} & RC2 & 128 & CBC \\
7597+
\hline \texttt{RC2-CFB} & RC2 & 128 & CFB \\
7598+
\hline \texttt{RC2-OFB} & RC2 & 128 & OFB \\
7599+
\hline \texttt{SEED-CBC} & SEED & 128 & CBC \\
7600+
\hline \texttt{SEED-CFB} & SEED & 128 & CFB \\
7601+
\hline \texttt{SEED-OFB} & SEED & 128 & OFB \\
75497602
\hline
75507603
\end{tabular}
75517604
\end{small}
7552-
\end{center}
75537605
\caption{List of supported PEM DEK algorithms}
75547606
\label{supported-pem-dek-algorithms}
75557607
\end{table}
@@ -7566,27 +7618,61 @@ \subsection{OpenSSH PEM files}
75667618
OpenSSH PEM files can contain private keys of the following types:
75677619

75687620
\begin{table}[H]
7569-
\begin{center}
75707621
\begin{small}
75717622
\begin{tabular}{|l|l|}
75727623
\hline \textbf{Identifier} & \textbf{Type} \\
75737624
\hline \texttt{ecdsa-sha2-*} & ECC keys \\
7625+
\hline \texttt{ssh-dss} & DSA \\
75747626
\hline \texttt{ssh-ed25519} & Curve25519 \\
75757627
\hline \texttt{ssh-rsa} & RSA \\
75767628
\hline
75777629
\end{tabular}
75787630
\end{small}
7579-
\end{center}
75807631
\caption{List of supported OpenSSH private key types}
75817632
\label{supported-openssh-private-key-types}
75827633
\end{table}
75837634

75847635
C.f. \href{https://datatracker.ietf.org/doc/html/rfc5656}{\texttt{RFC 5656}} for details on ECC keys
75857636
in OpenSSH. LibTomCrypt should be able to handle all the ECC curves supported by the library,
7586-
c.f. Ch. \ref{supported-curvers} for details.
7637+
c.f. Ch. \ref{supported-curves} for details.
7638+
7639+
When dealing with SSH formatted private keys the following encryption algorithms are supported:
75877640

7588-
OpenSSH PEM files can either not be encrypted, or the encryption is done via \texttt{aes256-cbc}
7589-
and key derivation via \texttt{bcrypt}, c.f. Ch. \ref{bcrypt}.
7641+
\begin{table}[H]
7642+
\begin{small}
7643+
\begin{tabular}{|l|l|l|l|}
7644+
\hline \textbf{Identifier} & \textbf{Cipher} & \textbf{Key size in bits} & \textbf{Mode} \\
7645+
\hline \texttt{none} & none & 0 & none \\
7646+
\hline \texttt{aes128-cbc} & AES & 128 & CBC \\
7647+
\hline \texttt{aes128-ctr} & AES & 128 & CTR \\
7648+
\hline \texttt{aes192-cbc} & AES & 192 & CBC \\
7649+
\hline \texttt{aes192-ctr} & AES & 192 & CTR \\
7650+
\hline \texttt{aes256-cbc} & AES & 256 & CBC \\
7651+
\hline \texttt{aes256-ctr} & AES & 256 & CTR \\
7652+
\hline \texttt{blowfish128-cbc} & Blowfish & 128 & CBC \\
7653+
\hline \texttt{blowfish128-ctr} & Blowfish & 128 & CTR \\
7654+
\hline \texttt{des-cbc} & DES & 64 & CBC \\
7655+
\hline \texttt{3des-cbc} & 3DES (EDE) & 192 & CBC \\
7656+
\hline \texttt{3des-ctr} & 3DES (EDE) & 192 & CTR \\
7657+
\hline \texttt{serpent128-cbc} & Serpent & 128 & CBC \\
7658+
\hline \texttt{serpent128-ctr} & Serpent & 128 & CTR \\
7659+
\hline \texttt{serpent192-cbc} & Serpent & 192 & CBC \\
7660+
\hline \texttt{serpent192-ctr} & Serpent & 192 & CTR \\
7661+
\hline \texttt{serpent256-cbc} & Serpent & 256 & CBC \\
7662+
\hline \texttt{serpent256-ctr} & Serpent & 256 & CTR \\
7663+
\hline \texttt{twofish128-cbc} & Twofish & 128 & CBC \\
7664+
\hline \texttt{twofish128-ctr} & Twofish & 128 & CTR \\
7665+
\hline \texttt{twofish192-cbc} & Twofish & 192 & CBC \\
7666+
\hline \texttt{twofish192-ctr} & Twofish & 192 & CTR \\
7667+
\hline \texttt{twofish-cbc} & Twofish & 256 & CBC \\
7668+
\hline \texttt{twofish256-cbc} & Twofish & 256 & CBC \\
7669+
\hline \texttt{twofish256-ctr} & Twofish & 256 & CTR \\
7670+
\hline
7671+
\end{tabular}
7672+
\end{small}
7673+
\caption{List of supported SSH Encryption algorithms}
7674+
\label{supported-ssh-encryption-algorithms}
7675+
\end{table}
75907676

75917677
The API functions provided to decode an OpenSSH PEM file into the \texttt{ltc\_pka\_key} union are:
75927678

makefile_include.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ TEST=test
168168
USEFUL_DEMOS = hashsum
169169

170170
# Demos that are usable but only rarely make sense to be installed
171-
USEABLE_DEMOS = ltcrypt sizes constants
171+
USEABLE_DEMOS = ltcrypt sizes constants pem-info
172172

173173
# Demos that are used for testing or measuring
174174
TEST_DEMOS = small tv_gen

src/headers/tomcrypt_pk.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ int dsa_shared_secret(void *private_key, void *base,
527527
#endif /* LTC_MDSA */
528528

529529
/*
530-
* LibTomCrypt Public Key Algorithm descriptor
530+
* LibTomCrypt tagged-union for holding a Public Key
531531
*/
532532

533533
typedef struct {
@@ -548,6 +548,7 @@ typedef struct {
548548
#ifdef LTC_MRSA
549549
rsa_key rsa;
550550
#endif
551+
char dummy;
551552
} u;
552553
enum ltc_pka_id id;
553554
} ltc_pka_key;

src/misc/pem/pem_pkcs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ static int s_import_pkcs8(unsigned char *pem, unsigned long l, ltc_pka_key *k, c
168168
return err;
169169
}
170170

171-
int s_extract_pka(unsigned char *pem, unsigned long w, enum ltc_pka_id *pka)
171+
static int s_extract_pka(unsigned char *pem, unsigned long w, enum ltc_pka_id *pka)
172172
{
173173
ltc_asn1_list *pub;
174174
int err = CRYPT_ERROR;

src/misc/pem/pem_ssh.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const struct blockcipher_info ssh_ciphers[] =
4343
{ .name = "twofish256-cbc", .algo = "twofish", .keylen = 256 / 8, .mode = cm_cbc },
4444
{ .name = "twofish256-ctr", .algo = "twofish", .keylen = 256 / 8, .mode = cm_ctr },
4545
};
46+
const unsigned long ssh_ciphers_num = sizeof(ssh_ciphers)/sizeof(ssh_ciphers[0]);
4647

4748
struct kdf_options {
4849
const char *name;
@@ -470,7 +471,7 @@ static int s_decode_header(unsigned char *in, unsigned long *inlen, struct kdf_o
470471

471472
*inlen = len + slen + 1;
472473

473-
for (i = 0; i < sizeof(ssh_ciphers)/sizeof(ssh_ciphers[0]); ++i) {
474+
for (i = 0; i < ssh_ciphers_num; ++i) {
474475
if (XSTRCMP((char*)ciphername, ssh_ciphers[i].name) == 0) {
475476
opts->cipher = &ssh_ciphers[i];
476477
break;

0 commit comments

Comments
 (0)