Browse Source

Update docs

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 3 years ago
parent
commit
39d4b089ac
2 changed files with 330 additions and 35 deletions
  1. 312 34
      doc/crypt.tex
  2. 18 1
      src/headers/tomcrypt_pk.h

+ 312 - 34
doc/crypt.tex

@@ -4423,7 +4423,7 @@ least 128 bytes, and no more than 512 bytes in size (\textit{that is from 1024 t
 
 
 \index{rsa\_free()}
 \index{rsa\_free()}
 Note: the \textit{rsa\_make\_key()} and \textit{rsa\_make\_key\_ubin\_e()} functions allocates memory at run--time when you make the key.
 Note: the \textit{rsa\_make\_key()} and \textit{rsa\_make\_key\_ubin\_e()} functions allocates memory at run--time when you make the key.
-Make sure to call \textit{rsa\_free()} (see below) when you are finished with the key.  If \textit{rsa\_make\_key()} or \textit{rsa\_make\_key\_ubin\_e()} 
+Make sure to call \textit{rsa\_free()} (see below) when you are finished with the key.  If \textit{rsa\_make\_key()} or \textit{rsa\_make\_key\_ubin\_e()}
 fails it will automatically free the memory allocated.
 fails it will automatically free the memory allocated.
 
 
 \index{PK\_PRIVATE} \index{PK\_PUBLIC}
 \index{PK\_PRIVATE} \index{PK\_PUBLIC}
@@ -4806,16 +4806,15 @@ import the key, strip off the additional data and fill in the \textit{rsa\_key}
 \index{rsa\_import\_pkcs8()}
 \index{rsa\_import\_pkcs8()}
 \begin{verbatim}
 \begin{verbatim}
 int rsa_import_pkcs8(const unsigned char *in,
 int rsa_import_pkcs8(const unsigned char *in,
-                           unsigned long inlen,
-                              const void *passwd,
-                           unsigned long passwdlen,
-                                rsa_key *key);
+                           unsigned long  inlen,
+                     const  password_ctx *pw_ctx,
+                                 rsa_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 This function can import RSA private keys serialized in PKCS\#8 format.
 This function can import RSA private keys serialized in PKCS\#8 format.
 
 
 Where \textit{key} is the RSA key structure (uninitialized), \textit{inlen} bytes of \textit{in} buffer is the DER encoded key,
 Where \textit{key} is the RSA key structure (uninitialized), \textit{inlen} bytes of \textit{in} buffer is the DER encoded key,
-and \textit{pwdlen} bytes of \textit{pwd} is optional password/secret (use \textit{pwd = NULL} for keys without password protection).
+and \textit{pw\_ctx} optionally points to a password-retrieval context, c.f. Ch. \ref{password-retrieval} for details.
 
 
 For password-protected files all supported encryption algorithms are listed in \ref{fig:pkcs8}.
 For password-protected files all supported encryption algorithms are listed in \ref{fig:pkcs8}.
 
 
@@ -5118,6 +5117,7 @@ analogy for deriving a shared secret between a pair of keys (also known as \text
 analogy for digital signatures (also known as \textit{ECDSA}).
 analogy for digital signatures (also known as \textit{ECDSA}).
 
 
 \mysection{Supported Curves}
 \mysection{Supported Curves}
+\label{supported-curvers}
 
 
 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
 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
 defined by own parameters (the only limitation is that the curve must be based on equation \ref{ecc-gf-p-equation}).
 defined by own parameters (the only limitation is that the curve must be based on equation \ref{ecc-gf-p-equation}).
@@ -5487,14 +5487,13 @@ To import the private key (optionally password protected/encrypted) in PKCS\#8 (
 \index{ecc\_import\_pkcs8()}
 \index{ecc\_import\_pkcs8()}
 \begin{verbatim}
 \begin{verbatim}
 int ecc_import_pkcs8(const unsigned char *in,
 int ecc_import_pkcs8(const unsigned char *in,
-                                unsigned  long inlen,
-                              const void *pwd,
-                           unsigned long  pwdlen,
+                           unsigned long  inlen,
+                     const  password_ctx *pw_ctx,
                                  ecc_key *key);
                                  ecc_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 Where \textit{key} is the ECC key structure (uninitialized), \textit{inlen} bytes of \textit{in} buffer is the DER encoded key,
 Where \textit{key} is the ECC key structure (uninitialized), \textit{inlen} bytes of \textit{in} buffer is the DER encoded key,
-and \textit{pwdlen} bytes of \textit{pwd} is optional password/secret (use \textit{pwd = NULL} for keys without password protection).
+and \textit{pw\_ctx} optionally points to a password-retrieval context, c.f. Ch. \ref{password-retrieval} for details.
 
 
 For password-protected files all supported encryption algorithms are listed in \ref{fig:pkcs8}.
 For password-protected files all supported encryption algorithms are listed in \ref{fig:pkcs8}.
 
 
@@ -5840,36 +5839,46 @@ The \textit{X25519} algorithm API provides the following set of functions to cre
 
 
 \index{x25519\_make\_key}
 \index{x25519\_make\_key}
 \begin{verbatim}
 \begin{verbatim}
-int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key);
+int x25519_make_key(    prng_state *prng,
+                               int  wprng,
+                    curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To generate a fresh X25529 key, one can use \textit{x25519\_make\_key} which will create a private\&public key-pair.
 To generate a fresh X25529 key, one can use \textit{x25519\_make\_key} which will create a private\&public key-pair.
 \index{x25519\_import}
 \index{x25519\_import}
 \begin{verbatim}
 \begin{verbatim}
-int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int x25519_import(const  unsigned char *in,
+                         unsigned long  inlen,
+                        curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 The \textit{x25519\_import} function can be used to import a public key in DER-encoded \textit{SubjectPublicKeyInfo} format.
 The \textit{x25519\_import} function can be used to import a public key in DER-encoded \textit{SubjectPublicKeyInfo} format.
 
 
 \index{x25519\_import\_raw}
 \index{x25519\_import\_raw}
 \begin{verbatim}
 \begin{verbatim}
-int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key);
+int x25519_import_raw(const  unsigned char *in,
+                             unsigned long  inlen,
+                                       int  which,
+                            curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To import a public or private key in raw format, one can use the function \textit{x25519\_import\_raw}.
 To import a public or private key in raw format, one can use the function \textit{x25519\_import\_raw}.
 
 
 \index{x25519\_import\_x509}
 \index{x25519\_import\_x509}
 \begin{verbatim}
 \begin{verbatim}
-int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int x25519_import_x509(const  unsigned char *in,
+                              unsigned long  inlen,
+                             curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function \textit{x25519\_import\_x509}.
 To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function \textit{x25519\_import\_x509}.
 
 
 \index{x25519\_import\_pkcs8}
 \index{x25519\_import\_pkcs8}
 \begin{verbatim}
 \begin{verbatim}
-int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
-                                 const void *pwd, unsigned long pwdlen,
-                             curve25519_key *key);
+int x25519_import_pkcs8(const  unsigned char *in,
+                               unsigned long  inlen,
+                        const   password_ctx *pw_ctx,
+                              curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To import a private key in the \textit{OneAsymmetricKey} a.k.a \textit{PKCS \#8} format, either plain or PBES encrypted,
 To import a private key in the \textit{OneAsymmetricKey} a.k.a \textit{PKCS \#8} format, either plain or PBES encrypted,
@@ -5877,7 +5886,8 @@ one can use the function \textit{x25519\_import\_pkcs8}.
 
 
 \index{x25519\_export}
 \index{x25519\_export}
 \begin{verbatim}
 \begin{verbatim}
-int x25519_export(       unsigned char *out, unsigned long *outlen,
+int x25519_export(       unsigned char *out,
+                         unsigned long *outlen,
                                    int  which,
                                    int  which,
                   const curve25519_key *key);
                   const curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
@@ -5908,7 +5918,8 @@ To construct a Diffie-Hellman shared secret with a private and a public X25519 k
 \begin{verbatim}
 \begin{verbatim}
 int x25519_shared_secret(const curve25519_key *private_key,
 int x25519_shared_secret(const curve25519_key *private_key,
                          const curve25519_key *public_key,
                          const curve25519_key *public_key,
-                                unsigned char *out, unsigned long *outlen);
+                                unsigned char *out,
+                                unsigned long *outlen);
 \end{verbatim}
 \end{verbatim}
 
 
 This will construct the shared secret between the private- and the public-key and store the result in \textit{out} of length \textit{outlen}.
 This will construct the shared secret between the private- and the public-key and store the result in \textit{out} of length \textit{outlen}.
@@ -5923,37 +5934,47 @@ The \textit{Ed25519} algorithm API provides the following set of functions to cr
 
 
 \index{ed25519\_make\_key}
 \index{ed25519\_make\_key}
 \begin{verbatim}
 \begin{verbatim}
-int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key);
+int ed25519_make_key(    prng_state *prng,
+                                int  wprng,
+                     curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To generate a fresh Ed25529 key, one can use \textit{ed25519\_make\_key} which will create a private\&public key-pair.
 To generate a fresh Ed25529 key, one can use \textit{ed25519\_make\_key} which will create a private\&public key-pair.
 
 
 \index{ed25519\_import}
 \index{ed25519\_import}
 \begin{verbatim}
 \begin{verbatim}
-int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int ed25519_import(const  unsigned char *in,
+                          unsigned long  inlen,
+                         curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 The \textit{ed25519\_import} function can be used to import a public key in DER-encoded \textit{SubjectPublicKeyInfo} format.
 The \textit{ed25519\_import} function can be used to import a public key in DER-encoded \textit{SubjectPublicKeyInfo} format.
 
 
 \index{ed25519\_import\_raw}
 \index{ed25519\_import\_raw}
 \begin{verbatim}
 \begin{verbatim}
-int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key);
+int ed25519_import_raw(const  unsigned char *in,
+                              unsigned long  inlen,
+                                        int  which,
+                             curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To import a public or private key in raw format, one can use the function \textit{ed25519\_import\_raw}.
 To import a public or private key in raw format, one can use the function \textit{ed25519\_import\_raw}.
 
 
 \index{ed25519\_import\_x509}
 \index{ed25519\_import\_x509}
 \begin{verbatim}
 \begin{verbatim}
-int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key);
+int ed25519_import_x509(const  unsigned char *in,
+                               unsigned long inlen,
+                              curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function \textit{ed25519\_import\_x509}.
 To import a public key from a DER-encoded \textit{X.509} certificate, one can use the function \textit{ed25519\_import\_x509}.
 
 
 \index{ed25519\_import\_pkcs8}
 \index{ed25519\_import\_pkcs8}
 \begin{verbatim}
 \begin{verbatim}
-int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
-                                  const void *pwd, unsigned long pwdlen,
-                              curve25519_key *key);
+int ed25519_import_pkcs8(const  unsigned char *in,
+                                unsigned long  inlen,
+                         const   password_ctx *pw_ctx,
+                               curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
 
 
 To import a private key in the \textit{OneAsymmetricKey} a.k.a \textit{PKCS \#8} format, either plain or PBES encrypted,
 To import a private key in the \textit{OneAsymmetricKey} a.k.a \textit{PKCS \#8} format, either plain or PBES encrypted,
@@ -5961,7 +5982,8 @@ one can use the function \textit{ed25519\_import\_pkcs8}.
 
 
 \index{ed25519\_export}
 \index{ed25519\_export}
 \begin{verbatim}
 \begin{verbatim}
-int ed25519_export(       unsigned char *out, unsigned long *outlen,
+int ed25519_export(       unsigned char *out,
+                          unsigned long *outlen,
                                     int  which,
                                     int  which,
                    const curve25519_key *key);
                    const curve25519_key *key);
 \end{verbatim}
 \end{verbatim}
@@ -7206,6 +7228,7 @@ int main(void)
 
 
 \subsection{bcrypt}
 \subsection{bcrypt}
 \index{bcrypt}
 \index{bcrypt}
+\label{bcrypt}
 
 
 bcrypt is a password hashing function, similar to PKCS \#5, but it is based on the blowfish symmetric cipher.
 bcrypt is a password hashing function, similar to PKCS \#5, but it is based on the blowfish symmetric cipher.
 It is widely used in e.g. OpenBSD as default password hash algorithm, or in encrypted OpenSSH key files.
 It is widely used in e.g. OpenBSD as default password hash algorithm, or in encrypted OpenSSH key files.
@@ -7227,15 +7250,16 @@ int bcrypt_pbkdf_openbsd(const          void *secret, unsigned long secret_len,
 The \textit{secret} parameter is the secret of length \textit{secret\_len} (most of the time a utf-8 encoded user password).
 The \textit{secret} parameter is the secret of length \textit{secret\_len} (most of the time a utf-8 encoded user password).
 The \textit{salt} parameter is a pointer to the array of octets of length \textit{salt\_len} containing the salt.
 The \textit{salt} parameter is a pointer to the array of octets of length \textit{salt\_len} containing the salt.
 The \textit{rounds} parameter defines the number of iterations of the expensive key setup that shall be executed.
 The \textit{rounds} parameter defines the number of iterations of the expensive key setup that shall be executed.
-The \textit{hash\_idx} parameter defines the hash algorithm that shall be used. 
+The \textit{hash\_idx} parameter defines the hash algorithm that shall be used.
 The \textit{out} parameter shall be a pointer to a buffer of at least 32 octets,
 The \textit{out} parameter shall be a pointer to a buffer of at least 32 octets,
 where \textit{outlen} contains the available buffer size on input and the written size after the invocation.
 where \textit{outlen} contains the available buffer size on input and the written size after the invocation.
 
 
 
 
 \mysection{PKCS \#8}
 \mysection{PKCS \#8}
 \index{PKCS \#8}
 \index{PKCS \#8}
+\label{pkcs8}
 
 
-The library has built-in support for PKCS \#8 decoding as specified in RFC 5208.
+The library has built-in support for PKCS \#8 decoding as specified in \href{https://datatracker.ietf.org/doc/html/rfc5208}{\texttt{RFC 5208}}.
 
 
 Encoding of private keys into PKCS \#8 is not supported.
 Encoding of private keys into PKCS \#8 is not supported.
 
 
@@ -7265,8 +7289,8 @@ The library supports the following encryption algorithms:
 \label{fig:pkcs8}
 \label{fig:pkcs8}
 \end{table}
 \end{table}
 
 
-The PKCS \#8 import has no direct API endpoints, but it is available through Public Key Algorithm-specific
-\textit{pkaX\_import\_pkcs8()} functions.
+The PKCS \#8 import has no direct API endpoints, but it is available either through Public Key Algorithm-specific
+\textit{pkaX\_import\_pkcs8()} functions or the PEM decoding API (c.f. Ch. \ref{pem-files}).
 
 
 
 
 \mysection{Key Derviation Functions}
 \mysection{Key Derviation Functions}
@@ -7391,8 +7415,8 @@ They either encode or decode a sequence of the supported SSH types where the ite
 int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
 int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
 \end{verbatim}
 \end{verbatim}
 
 
-Where \texttt{out} points to the destination buffer and  \texttt{outlen} points 
-on function invocation to the length of the destination buffer 
+Where \texttt{out} points to the destination buffer and  \texttt{outlen} points
+on function invocation to the length of the destination buffer
 and after returning it will be filled with the number of octets written to the buffer.
 and after returning it will be filled with the number of octets written to the buffer.
 
 
 The encoding function \texttt{ssh\_encode\_sequence\_multi()} expects its items to be a pair of \texttt{(type, data)},
 The encoding function \texttt{ssh\_encode\_sequence\_multi()} expects its items to be a pair of \texttt{(type, data)},
@@ -7404,7 +7428,7 @@ with \texttt{size} being of type \texttt{unsigned long}.
 int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...);
 int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...);
 \end{verbatim}
 \end{verbatim}
 
 
-Where \texttt{in} points to the buffer with the sequence to decode and \texttt{inlen} points 
+Where \texttt{in} points to the buffer with the sequence to decode and \texttt{inlen} points
 on function invocation to the length of the sequence
 on function invocation to the length of the sequence
 and after returning it will be filled with the decoded number of octets.
 and after returning it will be filled with the decoded number of octets.
 
 
@@ -7412,6 +7436,166 @@ The decoding function \texttt{ssh\_decode\_sequence\_multi()} expects its items
 except for the \texttt{string} resp. \texttt{name-list} type, which expects the triple \texttt{(type, data, size*)}
 except for the \texttt{string} resp. \texttt{name-list} type, which expects the triple \texttt{(type, data, size*)}
 with \texttt{size*} being of type \texttt{unsigned long*}.
 with \texttt{size*} being of type \texttt{unsigned long*}.
 
 
+
+
+
+\mysection{PEM Files}
+\label{pem-files}
+\subsection{Introduction}
+LibTomCrypt supports reading of asymmetric cryptography private keys out of
+PEM files in multiple formats.
+
+The library provides support for:
+\begin{itemize}
+   \item OpenSSH - encrypted and plain files (if SSH support is enabled).
+   \item PEM - encrypted and plain files.
+   \item PKCS \#8 - encrypted and plain files.
+\end{itemize}
+
+There is no support for PKCS \#12 containers/PFX files implemented.
+
+\subsection{The PKA Union}
+
+To be able to return all the potential public key algorithms via a central API,
+a tagged union \texttt{ltc\_pka\_key} is used.
+
+\begin{verbatim}
+enum ltc_pka_id {
+   LTC_PKA_UNDEF = 0,
+   LTC_PKA_RSA,
+   LTC_PKA_DSA,
+   LTC_PKA_EC,
+   LTC_PKA_CURVE25519,
+   LTC_PKA_DH,
+};
+
+typedef struct {
+   union {
+#ifdef LTC_CURVE25519
+      curve25519_key curve25519;
+#endif
+#ifdef LTC_MDH
+      dh_key dh;
+#endif
+#ifdef LTC_MDSA
+      dsa_key dsa;
+#endif
+#ifdef LTC_MECC
+      ecc_key ecc;
+#endif
+#ifdef LTC_MRSA
+      rsa_key rsa;
+#endif
+   } u;
+   enum ltc_pka_id id;
+} ltc_pka_key;
+\end{verbatim}
+
+To free such a union the following API function is provided:
+
+\begin{verbatim}
+void pka_key_free(ltc_pka_key *key);
+\end{verbatim}
+
+\subsection{PKCS PEM files}
+
+The library supports the following types of PKCS PEM files:
+
+\begin{itemize}
+\item PKCS \#8 private keys, c.f. Ch. \ref{pkcs8} for details.
+\item PEM formatted private keys according to
+\href{https://datatracker.ietf.org/doc/html/rfc1421}{\texttt{RFC 1421}}/
+\href{https://datatracker.ietf.org/doc/html/rfc1422}{\texttt{RFC 1422}}/
+\href{https://datatracker.ietf.org/doc/html/rfc1423}{\texttt{RFC 1423}}.
+\end{itemize}
+
+The identifiers in the PEM headers recognized are as follows:
+
+\begin{table}[H]
+\begin{center}
+\begin{small}
+\begin{tabular}{|l|l|l|l|}
+\hline \textbf{Identifier}                   & \textbf{Encrypted} & \textbf{Standard} & \textbf{Type}                  \\
+\hline \texttt{BEGIN ENCRYPTED PRIVATE KEY}  & Yes                & \texttt{PKCS \#8} & DSA, ECC, Ed25519, RSA, X25519 \\
+\hline \texttt{BEGIN PRIVATE KEY}            & No                 & \texttt{PKCS \#8} & DSA, ECC, Ed25519, RSA, X25519 \\
+\hline \texttt{BEGIN DSA PRIVATE KEY}        & Maybe              & \texttt{PKCS \#1} & DSA \\
+\hline \texttt{BEGIN EC PRIVATE KEY}         & Maybe              & \texttt{RFC 5915} & ECC \\
+\hline \texttt{BEGIN RSA PRIVATE KEY}        & Maybe              & \texttt{PKCS \#1} & RSA \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{List of supported PKCS private key types}
+\label{supported-pkcs-private-key-types}
+\end{table}
+
+When dealing with PEM formatted private keys the following encryption algorithms are supported:
+
+\begin{table}[H]
+\begin{center}
+\begin{small}
+\begin{tabular}{|l|l|l|l|}
+\hline \textbf{Identifier}        & \textbf{Cipher} & \textbf{Key size in bits} & \textbf{Mode} \\
+\hline \texttt{AES-128-CBC}       & AES             & 128                       & CBC \\
+\hline \texttt{AES-192-CBC}       & AES             & 192                       & CBC \\
+\hline \texttt{AES-256-CBC}       & AES             & 256                       & CBC \\
+\hline \texttt{CAMELLIA-128-CBC}  & Camellia        & 128                       & CBC \\
+\hline \texttt{CAMELLIA-192-CBC}  & Camellia        & 192                       & CBC \\
+\hline \texttt{CAMELLIA-256-CBC}  & Camellia        & 256                       & CBC \\
+\hline \texttt{DES-EDE3-CBC}      & 3DES (EDE)      & 192                       & CBC \\
+\hline \texttt{DES-CBC}           & DES             & 64                       & CBC \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{List of supported PEM DEK algorithms}
+\label{supported-pem-dek-algorithms}
+\end{table}
+
+The API functions provided to decode a PEM file into the \texttt{ltc\_pka\_key} union are:
+
+\begin{verbatim}
+int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx);
+int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx);
+\end{verbatim}
+
+\subsection{OpenSSH PEM files}
+
+OpenSSH PEM files can contain private keys of the following types:
+
+\begin{table}[H]
+\begin{center}
+\begin{small}
+\begin{tabular}{|l|l|}
+\hline \textbf{Identifier}    & \textbf{Type} \\
+\hline \texttt{ecdsa-sha2-*}  & ECC keys \\
+\hline \texttt{ssh-ed25519}   & Curve25519 \\
+\hline \texttt{ssh-rsa}       & RSA \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{List of supported OpenSSH private key types}
+\label{supported-openssh-private-key-types}
+\end{table}
+
+C.f. \href{https://datatracker.ietf.org/doc/html/rfc5656}{\texttt{RFC 5656}} for details on ECC keys
+in OpenSSH.  LibTomCrypt should be able to handle all the ECC curves supported by the library,
+c.f. Ch. \ref{supported-curvers} for details.
+
+OpenSSH PEM files can either not be encrypted, or the encryption is done via \texttt{aes256-cbc}
+and key derivation via \texttt{bcrypt}, c.f. Ch. \ref{bcrypt}.
+
+The API functions provided to decode an OpenSSH PEM file into the \texttt{ltc\_pka\_key} union are:
+
+\begin{verbatim}
+int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx);
+int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const password_ctx *pw_ctx);
+\end{verbatim}
+
+
+
+
 \chapter{Miscellaneous}
 \chapter{Miscellaneous}
 \mysection{Base64 Encoding and Decoding}
 \mysection{Base64 Encoding and Decoding}
 The library provides functions to encode and decode a RFC 4648 Base64 coding scheme.
 The library provides functions to encode and decode a RFC 4648 Base64 coding scheme.
@@ -7635,6 +7819,100 @@ Where \textit{data} is a pointer to the data to depad,
 \textit{length} is a pointer that should contain the length of the padded data and will be updated to contain the length of the data after depadding.
 \textit{length} is a pointer that should contain the length of the padded data and will be updated to contain the length of the data after depadding.
 
 
 
 
+\mysection{Password retrieval}
+\label{password-retrieval}
+
+The following struct is used in various parts of the library that deals with user-passwords.
+
+\begin{verbatim}
+typedef struct {
+   /**
+      Callback function that is called when a password is required.
+
+      @param str        Pointer to pointer where the password will be stored.
+      @param len        Pointer to the length of the password.
+      @param userdata   `userdata` that was passed in the `password_ctx` struct.
+      @return CRYPT_OK on success
+   */
+   int (*callback)(void **str, unsigned long *len, void *userdata);
+   /** Opaque `userdata` pointer passed when the callback is called */
+   void *userdata;
+} password_ctx;
+\end{verbatim}
+
+Always when this struct is used as input argument to an API function it can be treated as optional.
+The library will return the error \texttt{CRYPT\_PW\_CTX\_MISSING} in case a user-password is expected
+to be provided but this context is not given (passed a \textit{NULL} pointer instead) or
+the \textit{callback} pointer inside is \textit{NULL}.
+
+The \textit{str} pointer is declared as a \textit{void} pointer, since passwords are not necessarily
+always representable as a NUL-terminated C string. Therefor the user also has to provide the length of the
+password via \textit{len}.
+
+In order to prevent arbitrary limitations of the length of a password, the user is responsible for the
+dynamic allocation of the buffer that holds the password. The library takes ownership of said buffer
+and will zeroize it and call \texttt{XFREE} on it as soon as it doesn't require it anymore.
+
+An example usage is as follows:
+
+\begin{small}
+\begin{verbatim}
+#include <tomcrypt.h>
+#include <unistd.h>
+
+static const char *pka_algos[] = {
+   "Undefined",
+   "RSA",
+   "DSA",
+   "ECC",
+   "Curve25519",
+   "DH",
+};
+
+static int password_get(void **p, unsigned long *l, void *u)
+{
+   char *pass;
+   (void)u;
+   /* In reality you should never use `getpass`.
+    * 1. it's insecure, 2. it's obsolete
+    */
+   pass = getpass("Please enter password: ");
+   if (!pass)
+      return -1;
+   *p = strdup(pass);
+   *l = strlen(*p);
+   zeromem(pass, *l);
+   return 0;
+}
+
+int main(int argc, char **argv)
+{
+   FILE *pem;
+   ltc_pka_key key;
+   password_ctx pw_ctx = { .callback = password_get };
+   if (argc < 2)
+      return EXIT_FAILURE;
+   pem = fopen(argv[1], "rb");
+   if (!pem)
+      return EXIT_FAILURE;
+
+   if (register_all_ciphers() != CRYPT_OK)
+      return EXIT_FAILURE;
+   if (register_all_hashes() != CRYPT_OK)
+      return EXIT_FAILURE;
+   if (crypt_mp_init("ltm") != CRYPT_OK)
+      return EXIT_FAILURE;
+   if (pem_decode_pkcs_filehandle(pem, &key, &pw_ctx) != CRYPT_OK)
+      return EXIT_FAILURE;
+   if (key.id < sizeof(pka_algos)/sizeof(pka_algos[0]))
+      printf("key type: %s\n", pka_algos[key.id]);
+   pka_key_free(&key);
+   return EXIT_SUCCESS;
+}
+
+\end{verbatim}
+\end{small}
+
 \mysection{Primality Testing}
 \mysection{Primality Testing}
 \index{Primality Testing}
 \index{Primality Testing}
 The library includes primality testing and random prime functions as well.  The primality tester will perform the test in
 The library includes primality testing and random prime functions as well.  The primality tester will perform the test in

+ 18 - 1
src/headers/tomcrypt_pk.h

@@ -2,7 +2,21 @@
 /* SPDX-License-Identifier: Unlicense */
 /* SPDX-License-Identifier: Unlicense */
 
 
 typedef struct {
 typedef struct {
-   int (*callback)(void **, unsigned long *, void *);
+   /**
+      Callback function that is called when a password is required.
+
+      Please be aware that the library takes ownership of the pointer that is
+      returned to the library via `str`.
+      `str` shall be allocated via the same function as `XMALLOC` points to.
+      The data will be zeroed and `XFREE`'d as soon as it isn't required anymore.
+
+      @param str        Pointer to pointer where the password will be stored.
+      @param len        Pointer to the length of the password.
+      @param userdata   `userdata` that was passed in the `password_ctx` struct.
+      @return CRYPT_OK on success
+   */
+   int (*callback)(void **str, unsigned long *len, void *userdata);
+   /** Opaque `userdata` pointer passed when the callback is called */
    void *userdata;
    void *userdata;
 } password_ctx;
 } password_ctx;
 
 
@@ -495,6 +509,9 @@ int dsa_shared_secret(void          *private_key, void *base,
                       unsigned char *out,         unsigned long *outlen);
                       unsigned char *out,         unsigned long *outlen);
 #endif /* LTC_MDSA */
 #endif /* LTC_MDSA */
 
 
+/*
+ * LibTomCrypt Public Key Algorithm descriptor
+ */
 
 
 enum ltc_pka_id {
 enum ltc_pka_id {
    LTC_PKA_UNDEF = 0,
    LTC_PKA_UNDEF = 0,