Added OpenPGP library to lib/silcpgp
[crypto.git] / lib / silcpgp / silcpgp.h
diff --git a/lib/silcpgp/silcpgp.h b/lib/silcpgp/silcpgp.h
new file mode 100644 (file)
index 0000000..643a70a
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+
+  silcpgp.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2007 - 2008 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+
+/****h* silcpgp/OpenPGP Interface
+ *
+ * DESCRIPTION
+ *
+ * This implementation supports OpenPGP public key versions 2, 3 and 4.
+ * OpenPGP private key support exist only for version 4.  This means that
+ * this API can be used verify signatures with all versions of OpenPGP public
+ * keys, but signatures can only be computed with version 4 private keys.
+ * This implementation also only generates version 4 private keys.
+ *
+ * The interface implements the RFC 2440 and rfc2440bis-22 Internet Draft
+ * specifications.
+ *
+ ***/
+
+#ifndef SILCPGP_H
+#define SILCPGP_H
+
+/****s* silcpgp/SilcPGPPublicKey
+ *
+ * NAME
+ *
+ *    typedef struct { ... } *SilcPGPPublicKey;
+ *
+ * DESCRIPTION
+ *
+ *    This structure defines the OpenPGP public key (certificate).  This
+ *    context can be retrieved from SilcPublicKey by calling
+ *    silc_pkcs_public_key_get_pkcs for the PKCS type SILC_PKCS_OPENPGP.
+ *
+ * SOURCE
+ */
+typedef struct SilcPGPPublicKeyStruct {
+  SilcList packets;               /* Packets making this public key, contains
+                                     main key, subkeys, signatures etc. */
+  SilcDList subkeys;              /* Subkeys, each is SilcPGPPublicKey */
+
+  const SilcPKCSAlgorithm *pkcs;   /* PKCS Algorithm */
+  void *public_key;               /* PKCS Algorithm specific public key */
+
+  unsigned char key_id[8];        /* Public key ID */
+  unsigned char fingerprint[20];   /* Fingerprint of the public key */
+
+  SilcUInt32 created;             /* Time when public key was created */
+  SilcUInt16 valid;               /* Validity period (V3 keys) */
+  SilcUInt8 version;              /* Version, 2, 3 or 4 */
+  SilcUInt8 algorithm;            /* Algorithm, SilcPGPPKCSAlgorithm */
+} *SilcPGPPublicKey;
+/***/
+
+/****s* silcpgp/SilcPGPPrivateKey
+ *
+ * NAME
+ *
+ *    typedef struct { ... } *SilcPGPPrivateKey;
+ *
+ * DESCRIPTION
+ *
+ *    This structure defines the OpenPGP private key.  This context can be
+ *    retrieved from SilcPublicKey by calling silc_pkcs_private_key_get_pkcs
+ *    for the PKCS type SILC_PKCS_OPENPGP.
+ *
+ * SOURCE
+ */
+typedef struct SilcPGPPrivateKeyStruct {
+  SilcList packets;               /* Packets making this private key, contains
+                                     main key, subkeys, signatures etc. */
+  SilcDList subkeys;              /* Subkeys, each is SilcPGPPrivateKey */
+
+  SilcPGPPublicKey public_key;    /* Public key */
+  void *private_key;              /* Algorithm specific private key */
+
+  SilcUInt32 s2k_count;                   /* S2K iterate octet count */
+  SilcUInt8 cipher;               /* Cipher, SilcPGPCipher */
+  SilcUInt8 s2k_type;             /* S2K type, SilcPGPS2KType */
+  SilcUInt8 s2k_hash;             /* Hash, SilcPGPHash */
+} *SilcPGPPrivateKey;
+/***/
+
+/****s* silcpgp/SilcPGPPacket
+ *
+ * NAME
+ *
+ *    typedef struct SilcPGPPacketStruct *SilcPGPPacket;
+ *
+ * DESCRIPTION
+ *
+ *    OpenPGP packet context.  This context is allocated by calling
+ *    silc_pgp_packet_decode.
+ *
+ ***/
+typedef struct SilcPGPPacketStruct *SilcPGPPacket;
+
+/****d* silcpgp/SilcPGPPacketTag
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPGPPacketTag;
+ *
+ * DESCRIPTION
+ *
+ *    OpenPGP packet types.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PGP_PACKET_PKENC_SK        = 1,   /* Public key enc session key */
+  SILC_PGP_PACKET_SIGNATURE       = 2,  /* Signature packet */
+  SILC_PGP_PACKET_SENC_SK         = 3,  /* Symmetric-key enc session key */
+  SILC_PGP_PACKET_OP_SIGNATURE    = 4,  /* One pass signature packet */
+  SILC_PGP_PACKET_SECKEY          = 5,  /* Secret key packet */
+  SILC_PGP_PACKET_PUBKEY          = 6,  /* Public key packet */
+  SILC_PGP_PACKET_SECKEY_SUB      = 7,  /* Secret subkey packet */
+  SILC_PGP_PACKET_COMP_DATA       = 8,  /* Compressed data packet */
+  SILC_PGP_PACKET_SENC_DATA       = 9,  /* Symmetrically enc data packet */
+  SILC_PGP_PACKET_MARKER          = 10,         /* Marker packet */
+  SILC_PGP_PACKET_LITERAL_DATA    = 11,         /* Literal data packet */
+  SILC_PGP_PACKET_TRUST           = 12,         /* Trust packet */
+  SILC_PGP_PACKET_USER_ID         = 13,         /* User ID packet */
+  SILC_PGP_PACKET_PUBKEY_SUB      = 14,         /* Public subkey packet */
+  SILC_PGP_PACKET_USER_ATTR       = 17,         /* User attribute packet */
+  SILC_PGP_PACKET_SENC_I_DATA     = 18,         /* Symmetric key enc/integ data */
+  SILC_PGP_PACKET_MDC             = 19,         /* Modification detection code */
+} SilcPGPPacketTag;
+/***/
+
+/****d* silcpgp/SilcPGPPKCSAlgorithm
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPGPPKCSAlgorithm;
+ *
+ * DESCRIPTION
+ *
+ *    OpenPGP public key cryptosystem algorithms.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PGP_PKCS_RSA               = 1,   /* RSA */
+  SILC_PGP_PKCS_RSA_ENC_ONLY      = 2,   /* RSA encryption allowed only */
+  SILC_PGP_PKCS_RSA_SIG_ONLY      = 3,   /* RSA signatures allowed only */
+  SILC_PGP_PKCS_ELGAMAL_ENC_ONLY  = 16,         /* Elgamal encryption only */
+  SILC_PGP_PKCS_DSA               = 17,         /* DSA */
+  SILC_PGP_PKCS_ECDSA             = 19,         /* ECDSA */
+  SILC_PGP_PKCS_ELGAMAL           = 20,         /* Elgamal encryption/signatures */
+  SILC_PGP_PKCS_DH                = 21,         /* Diffie-Hellman */
+} SilcPGPPKCSAlgorithm;
+/***/
+
+/****d* silcpgp/SilcPGPCipher
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPGPCipher;
+ *
+ * DESCRIPTION
+ *
+ *    OpenPGP ciphers.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PGP_CIPHER_NONE            = 0,   /* No cipher, plaintext */
+  SILC_PGP_CIPHER_IDEA            = 1,  /* IDEA */
+  SILC_PGP_CIPHER_3DES            = 2,  /* Triple-DES */
+  SILC_PGP_CIPHER_CAST5           = 3,  /* CAST5 (CAST-128) */
+  SILC_PGP_CIPHER_BLOWFISH        = 4,  /* Blowfish */
+  SILC_PGP_CIPHER_AES128          = 7,  /* AES 128-bit key */
+  SILC_PGP_CIPHER_AES192          = 8,  /* AES 192-bit key */
+  SILC_PGP_CIPHER_AES256          = 9,  /* AES 256-bit key */
+  SILC_PGP_CIPHER_TWOFISH         = 10,         /* Twofish 256-bit key */
+} SilcPGPCipher;
+/***/
+
+/****d* silcpgp/SilcPGPHash
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPGPHash;
+ *
+ * DESCRIPTION
+ *
+ *    OpenPGP hash functions.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PGP_HASH_MD5               = 1,  /* MD5 */
+  SILC_PGP_HASH_SHA1              = 2,  /* SHA-1 */
+  SILC_PGP_HASH_RIPEMD160         = 3,  /* RIPE-MD160 */
+  SILC_PGP_HASH_SHA256            = 8,  /* SHA-256 */
+  SILC_PGP_HASH_SHA384            = 9,  /* SHA-394 */
+  SILC_PGP_HASH_SHA512            = 10,         /* SHA-512 */
+  SILC_PGP_HASH_SHA224            = 11,         /* SHA-224 */
+} SilcPGPHash;
+/***/
+
+/****d* silcpgp/SilcPGPS2KType
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPGPS2KType;
+ *
+ * DESCRIPTION
+ *
+ *    String-to-key (S2K) specifier types.  These define how the passphrase
+ *    is converted into encryption and decryption key.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PGP_S2K_SIMPLE            = 0,   /* Simple S2K */
+  SILC_PGP_S2K_SALTED             = 1,  /* Salted S2K */
+  SILC_PGP_S2K_ITERATED_SALTED    = 3,  /* Iterated and salted S2K */
+} SilcPGPS2KType;
+/***/
+
+/****d* silcpgp/SilcPGPKeyType
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPGPKeyType;
+ *
+ * DESCRIPTION
+ *
+ *    PGP key generation types.  These types define what kind of PGP key
+ *    is created with silc_pgp_generate_key.
+ *
+ *    SILC_PGP_RSA
+ *
+ *      Generates RSA key that can be used for both signatures and encryption.
+ *      This is default.  If key type is not specified, this is used as
+ *      default key type.
+ *
+ *    SILC_PGP_DSA_SIG
+ *
+ *      Generates signature only DSA key.  The key cannot be used for
+ *      encryption.
+ *
+ *    SILC_PGP_ECDSA_SIG
+ *
+ *      Generates signature only ECDSA key.  The key cannot be used for
+ *      encryption.
+ *
+ *    SILC_PGP_DSA_SIG_ELGAMAL_ENC
+ *
+ *      Generates key with DSA for signatures and Elgamal for encryption.
+ *
+ *    SILC_PGP_DSA_SIG_RSA_ENC
+ *
+ *      Generates key with DSA for signatures and RSA for encryption.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PGP_RSA                     = 0,         /* Generate RSA key */
+  SILC_PGP_DSA_SIG                 = 1,         /* Generate signature only DSA key */
+  SILC_PGP_ECDSA_SIG               = 2,         /* Generate signature only ECDSA key */
+  SILC_PGP_DSA_SIG_ELGAMAL_ENC     = 3,         /* Generate DSA and Elgamal key */
+  SILC_PGP_DSA_SIG_RSA_ENC         = 4,         /* Generate DSA and RSA key */
+} SilcPGPKeyType;
+/***/
+
+typedef struct SilcPgpKeygenParamsStruct {
+  SilcPGPKeyType type;
+  int key_len_bits;
+
+  int expire_days;
+  int expire_weeks;
+  int expire_months;
+  int expire_years;
+} SilcPgpKeygenParams;
+
+/* XXX TODO */
+SilcBool silc_pgp_generate_key(SilcPgpKeygenParams *params,
+                              const char *user_id,
+                              SilcRng rng,
+                              SilcPublicKey *ret_public_key,
+                              SilcPrivateKey *ret_private_key);
+
+/****f* silcpgp/silc_pgp_packet_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcBool silc_pgp_packet_decode(const unsigned char *data,
+ *                                    SilcUInt32 data_len,
+ *                                    SilcBool *success,
+ *                                    SilcList *ret_list);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes PGP packets from the data buffer indicated by `data' of length
+ *    of `data_len' bytes.  The data buffer may include one or more packets
+ *    that are decoded and returned to the `ret_list'.  The caller must free
+ *    the returned packets with silc_pgp_packet_free_list.  Each entry in
+ *    the `ret_list' is SilcPGPPacket.
+ *
+ *    Returns the number of packets decoded or 0 on error.  If the `success'
+ *    is FALSE but this returns > 0 then not all packets were decoded
+ *    successfully and the `ret_list' includes the packets that were decoded.
+ *    When the `success' is TRUE all packets were decoded successfully.
+ *
+ * EXAMPLE
+ *
+ *    SilcList list;
+ *    SilcBool success;
+ *    unsigned char *data;
+ *    SilcUInt32 data_len;
+ *    SilcPGPPublicKey public_key;
+ *
+ *    // Open public key file (binary format) and parse all PGP packets
+ *    data = silc_file_readfile("pubkey.bin", &data_len, NULL);
+ *    silc_pgp_packet_decode(data, data_len, &success, &list);
+ *
+ *    // Parse public key
+ *    silc_pgp_public_key_decode(&list, &public_key);
+ *
+ ***/
+int silc_pgp_packet_decode(const unsigned char *data,
+                          SilcUInt32 data_len,
+                          SilcBool *success,
+                          SilcList *ret_list);
+
+/****f* silcpgp/silc_pgp_packet_get_tag
+ *
+ * SYNOPSIS
+ *
+ *    SilcPGPPacketTag silc_pgp_packet_get_tag(SilcPGPPacket packet);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the OpenPGP packet tag (packet type) from `packet'.
+ *
+ ***/
+SilcPGPPacketTag silc_pgp_packet_get_tag(SilcPGPPacket packet);
+
+/****f* silcpgp/silc_pgp_packet_get_data
+ *
+ * SYNOPSIS
+ *
+ *    unsigned char *silc_pgp_packet_get_data(SilcPGPPacket packet,
+ *                                            SilcUInt32 *data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the packet data from the `packet'.  The returned pointer
+ *    must not be freed by the caller.  The length of the data is returned
+ *    into `data_len' pointer.
+ *
+ ***/
+unsigned char *silc_pgp_packet_get_data(SilcPGPPacket packet,
+                                       SilcUInt32 *data_len);
+
+/****f* silcpgp/silc_pgp_packet_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_pgp_packet_free(SilcPGPPacket packet);
+ *
+ * DESCRIPTION
+ *
+ *    Free PGP packet.
+ *
+ ***/
+void silc_pgp_packet_free(SilcPGPPacket packet);
+
+/****f* silcpgp/silc_pgp_packet_free_list
+ *
+ * SYNOPSIS
+ *
+ *    void silc_pgp_packet_free_list(SilcList *list);
+ *
+ * DESCRIPTION
+ *
+ *    Free all PGP packets from the `list'.  All packets in the list will
+ *    become invalid after this call.
+ *
+ ***/
+void silc_pgp_packet_free_list(SilcList *list);
+
+/****f* silcpgp/silc_pgp_public_key_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcBool silc_pgp_public_key_decode(SilcList *list,
+ *                                        SilcPGPPublicKey *ret_public_key);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes OpenPGP public key (certificate) from decoded PGP packets list
+ *    indicated by `list'.  The decoded public key is returned into the
+ *    `ret_public_key' which the caller must free by calling the
+ *    silc_pgp_public_key_free function.  Returns FALSE on error.
+ *
+ *    The `list' can be allocated by calling silc_pgp_packet_decode.
+ *    If the `list' contains more that one public keys this only decodes
+ *    the first one.  The public key `list' is advanced while decoding the
+ *    public key.  If another public key follows the first public key, this
+ *    function may be called again to decode that public key as well.
+ *
+ ***/
+SilcBool silc_pgp_public_key_decode(SilcList *pubkey,
+                                   SilcPGPPublicKey *ret_public_key);
+
+/****f* silcpgp/silc_pgp_public_key_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_pgp_public_key_free(SilcPGPPublicKey public_key);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the public key.
+ *
+ ***/
+void silc_pgp_public_key_free(SilcPGPPublicKey public_key);
+
+/****f* silcpgp/silc_pgp_private_key_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcBool silc_pgp_private_key_decode(SilcList *list,
+ *                                         const char *passphrase,
+ *                                         SilcUInt32 passphrase_len,
+ *                                         SilcPGPPrivateKey *ret_private_key);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes OpenPGP secret key (private key) from decoded PGP packets list
+ *    indicated by `list'.  The decoded private key is returned into the
+ *    `ret_private_key' which the caller must free by calling the
+ *    silc_pgp_private_key_free function.  Returns FALSE on error.
+ *
+ *    The `passphrase' can be provided in case the private key is
+ *    encrypted.  Usually all OpenPGP private keys are encrypted so the
+ *    passphrase should be always provided.
+ *
+ *    The `list' can be allocated by calling silc_pgp_packet_decode.
+ *    If the `list' contains more that one private keys this only decodes
+ *    the first one.  The private key `list' is advanced while decoding the
+ *    public key.  If another private key follows the first public key, this
+ *    function may be called again to decode that private key as well.
+ *
+ ***/
+SilcBool silc_pgp_private_key_decode(SilcList *list,
+                                    const char *passphrase,
+                                    SilcUInt32 passphrase_len,
+                                    SilcPGPPrivateKey *ret_private_key);
+
+/****f* silcpgp/silc_pgp_private_key_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_pgp_private_key_free(SilcPGPPrivateKey private_key);
+ *
+ * DESCRIPTION
+ *
+ *    Frees the private key.
+ *
+ ***/
+void silc_pgp_private_key_free(SilcPGPPrivateKey private_key);
+
+/****f* silcpgp/silc_pgp_s2k
+ *
+ * SYNOPSIS
+ *
+ *    unsigned char *silc_pgp_s2k(SilcPGPS2KType type,
+ *                                SilcPGPHash hash,
+ *                                const char *passphrase,
+ *                                SilcUInt32 passphrase_len,
+ *                                SilcUInt32 key_len,
+ *                                unsigned char *salt,
+ *                                SilcUInt32 iter_octet_count,
+ *                                SilcRng rng);
+ *
+ * DESCRIPTION
+ *
+ *   Computes the OpenPGP string-to-key (S2K).  Converts passphrases to
+ *   encryption and decryption keys.  The `passphrase' must be non-NULL.
+ *
+ *   The `type' specifies the S2K specifier type.  The `hash' is the
+ *   hash algorithm used if the `type' is SILC_PGP_S2K_SALTED or
+ *   SILC_PGP_S2K_ITERATED_SALTED.  If the `type' is
+ *   SILC_PGP_S2K_ITERATED_SALTED the `iter_octet_count' is the number of
+ *   bytes to iteratively hash (max value is 65536).
+ *
+ *   The `key_len' is the length of the key to produce in bytes.  If `salt'
+ *   is NULL this will generate an encryption key.  If it is non-NULL this
+ *   will use the salt to compute the decryption key.
+ *
+ ***/
+unsigned char *silc_pgp_s2k(SilcPGPS2KType type,
+                           SilcPGPHash hash,
+                           const char *passphrase,
+                           SilcUInt32 passphrase_len,
+                           SilcUInt32 key_len,
+                           unsigned char *salt,
+                           SilcUInt32 iter_count,
+                           SilcRng rng);
+
+unsigned char *silc_pgp_dearmor(unsigned char *data,
+                               SilcUInt32 data_len,
+                               SilcUInt32 *ret_len);
+
+#include "silcpgp_i.h"
+
+#endif /* SILCPGP_H */