/* silcske.h Author: Pekka Riikonen Copyright (C) 2000 - 2007 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* silcske/SILC SKE Interface * * DESCRIPTION * * The SILC Key Exchange (SKE) protocol interface. The SKE protocol * is used to negotiate secret key material between two parties, to be used * as session key or some other key. For example, when client connects to * server SKE is performed to exchange public keys, and to generate the key * that is then used as session key. Two clients can execute SKE as well * two create secret key material for securing for example file transfer * stream. This SKE implementation provides easy interface for application * that wants to use SKE. * ***/ #ifndef SILCSKE_H #define SILCSKE_H /* Forward declarations */ typedef struct SilcSKECallbacksStruct *SilcSKECallbacks; typedef struct SilcSKEStruct *SilcSKE; /****d* silcske/SilcSKEAPI/SilcSKEStatus * * NAME * * typedef enum { ... } SilcSKEStatus; * * DESCRIPTION * * Status types returned in SKE callbacks. This tell the status of * the SKE session, and if an error occurred. Application can map the * status to human readable string with silc_ske_map_status function. * * SOURCE */ typedef enum { /* These are defined by the protocol */ SILC_SKE_STATUS_OK = 0, /* No error */ SILC_SKE_STATUS_ERROR = 1, /* Unknown error */ SILC_SKE_STATUS_BAD_PAYLOAD = 2, /* Malformed payload */ SILC_SKE_STATUS_UNKNOWN_GROUP = 3, /* Unsupported DH group */ SILC_SKE_STATUS_UNKNOWN_CIPHER = 4, /* Unsupported cipher */ SILC_SKE_STATUS_UNKNOWN_PKCS = 5, /* Unsupported PKCS algorithm */ SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION = 6, /* Unsupported hash function */ SILC_SKE_STATUS_UNKNOWN_HMAC = 7, /* Unsupported HMAC */ SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY = 8, /* Unsupported/not trusted PK */ SILC_SKE_STATUS_INCORRECT_SIGNATURE = 9, /* Incorrect signature */ SILC_SKE_STATUS_BAD_VERSION = 10, /* Unsupported version */ SILC_SKE_STATUS_INVALID_COOKIE = 11, /* Cookie was modified */ /* Implementation specific status types */ SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED, /* Remote did not send PK */ SILC_SKE_STATUS_BAD_RESERVED_FIELD, /* Reserved field was not 0 */ SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH, /* Payload includes garbage */ SILC_SKE_STATUS_SIGNATURE_ERROR, /* Error computing signature */ SILC_SKE_STATUS_OUT_OF_MEMORY, /* System out of memory */ SILC_SKE_STATUS_TIMEOUT, /* Timeout */ } SilcSKEStatus; /***/ #include "silcske_groups.h" #include "silcske_payload.h" /****d* silcske/SilcSKEAPI/SilcSKESecurityPropertyFlag * * NAME * * typedef enum { ... } SilcSKESecurityPropertyFlag * * DESCRIPTION * * SKE security property flags as defined by the SK protocol. * * SOURCE */ typedef enum { SILC_SKE_SP_FLAG_NONE = 0x00, /* No flags */ SILC_SKE_SP_FLAG_IV_INCLUDED = 0x01, /* IV included in packet */ SILC_SKE_SP_FLAG_PFS = 0x02, /* Perfect Forward Secrecy */ SILC_SKE_SP_FLAG_MUTUAL = 0x04, /* Mutual authentication */ } SilcSKESecurityPropertyFlag; /***/ /****s* silcske/SilcSKEAPI/SilcSKESecurityProperties * * NAME * * typedef struct { ... } *SilcSKESecurityProperties; * * DESCRIPTION * * Security Properties negotiated between key exchange parties. This * structure is filled from the Key Exchange Start Payload which is used * to negotiate what security properties must be used in the * communication. * * SOURCE */ typedef struct SilcSKESecurityPropertiesStruct { SilcSKESecurityPropertyFlag flags; /* Flags */ SilcSKEDiffieHellmanGroup group; /* Selected Diffie Hellman group */ SilcCipher cipher; /* Selected cipher */ SilcHmac hmac; /* Selected HMAC */ SilcHash hash; /* Selected hash algorithm */ SilcPublicKey public_key; /* Remote public key */ SilcUInt16 remote_port; /* Remote port, set when IV Included set and using UDP/IP */ } *SilcSKESecurityProperties; /***/ /****s* silcske/SilcSKEAPI/SilcSKEKeyMaterial * * NAME * * typedef struct { ... } *SilcSKEKeyMaterial; * * DESCRIPTION * * This is the key material structure, and is passed as argument by the * application to silc_ske_process_key_material_data function. It includes * the processed key material which can be used as SILC session keys. * * SOURCE */ typedef struct SilcSKEKeyMaterialStruct { unsigned char *send_iv; unsigned char *receive_iv; SilcUInt32 iv_len; unsigned char *send_enc_key; unsigned char *receive_enc_key; SilcUInt32 enc_key_len; /* Key length in bits */ unsigned char *send_hmac_key; unsigned char *receive_hmac_key; SilcUInt32 hmac_key_len; /* Key length in bytes */ } *SilcSKEKeyMaterial; /***/ /****s* silcske/SilcSKEAPI/SilcSKERekeyMaterial * * NAME * * typedef struct { ... } *SilcSKERekeyMaterial; * * DESCRIPTION * * This context is returned after key exchange protocol to application * in the completion callback. Application may save it and use it later * to perform the rekey with silc_ske_rekey_initiator and/or * silc_ske_rekey_responder functions. If application does not * need the context, it may free it with silc_ske_free_rekey_material * function. * ***/ typedef struct SilcSKERekeyMaterialStruct { unsigned char *send_enc_key; char *hash; unsigned int enc_key_len : 23; unsigned int ske_group : 8; unsigned int pfs : 1; } *SilcSKERekeyMaterial; /****s* silcske/SilcSKEAPI/SilcSKEParams * * NAME * * typedef struct { ... } *SilcSKEParams, SilcSKEParamsStruct; * * DESCRIPTION * * SKE parameters structure. This structure is given as argument to * silc_ske_initiator and silc_ske_responder functions. * * SOURCE */ typedef struct SilcSKEParamsObject { /* The SKE version string that is sent to the remote end. This field must be set. Caller must free the pointer. */ char *version; /* Security property flags. When initiator sets these it requests them from the responder. Responder may set here the flags it supports and wants to enforce for the initiator. */ SilcSKESecurityPropertyFlag flags; /* SILC Session port when using UDP/IP and SILC_SKE_SP_FLAG_IV_INCLUDED flag. It is the port the remote will use as SILC session port after the key exchange protocol. Ignored without SILC_SKE_SP_FLAG_IV_INCLUDED flag. */ SilcUInt16 session_port; /* Key exchange timeout in seconds. If key exchange is not completed in this time it will timeout. If not specified (zero), default value (30 seconds) will be used. */ SilcUInt16 timeout_secs; } *SilcSKEParams, SilcSKEParamsStruct; /***/ /****d* silcske/SilcSKEAPI/SilcSKEPKType * * NAME * * typedef enum { ... } SilcSKEPKType; * * DESCRIPTION * * Public key and certificate types defined by the SKE protocol. * * SOURCE */ typedef enum { SILC_SKE_PK_TYPE_SILC = 1, /* SILC Public Key, mandatory */ SILC_SKE_PK_TYPE_SSH2 = 2, /* SSH2 Public key, not supported */ SILC_SKE_PK_TYPE_X509V3 = 3, /* X.509v3 certificate, not supported */ SILC_SKE_PK_TYPE_OPENPGP = 4, /* OpenPGP certificate, not supported */ SILC_SKE_PK_TYPE_SPKI = 5 /* SPKI certificate, not supported */ } SilcSKEPKType; /***/ /****f* silcske/SilcSKEAPI/SilcSKEVerifyCbCompletion * * SYNOPSIS * * typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske, * SilcSKEStatus status, * void *context); * * DESCRIPTION * * Completion callback that will be called when the public key * has been verified. The `status' will indicate whether the public * key were trusted or not. * ***/ typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske, SilcSKEStatus status, void *context); /****f* silcske/SilcSKEAPI/SilcSKEVerifyCb * * SYNOPSIS * * typedef void (*SilcSKEVerifyCb)(SilcSKE ske, * SilcPublicKey public_key, * void *context, * SilcSKEVerifyCbCompletion completion, * void *completion_context); * * DESCRIPTION * * Callback function used to verify the received public key or certificate. * The verification process is most likely asynchronous. That's why the * application must call the `completion' callback when the verification * process has been completed. The `context' is the context given as * arugment to silc_ske_set_callbacks. See silc_ske_set_callbacks for * more information. * * If the key repository was provided in silc_ske_alloc this callback * is called only if the public key was not found from the repository. * ***/ typedef void (*SilcSKEVerifyCb)(SilcSKE ske, SilcPublicKey public_key, void *context, SilcSKEVerifyCbCompletion completion, void *completion_context); /****f* silcske/SilcSKEAPI/SilcSKECompletionCb * * SYNOPSIS * * typedef void (*SilcSKECompletionCb)(SilcSKE ske, * SilcSKEStatus status, * const SilcSKESecurityProperties prop, * const SilcSKEKeyMaterial keymat, * SilcSKERekeyMaterial rekey, * void *context); * * DESCRIPTION * * Completion callback. This is called after the key exchange protocol * has been completed. It delivers the status of the protocol, and if * successful the security properties `prop' that was negotiated in the * protocol and the key material `keymat' that can be set into use by * calling silc_ske_set_keys, and the rekey key material `rekey' which * can be used later to start rekey protocol. The `prop' and `keymat' * will remain valid as long as `ske' is valid. The `rekey' will remain * valid until silc_ske_free_rekey_material is called. The application * must call it to free the `rekey'. * * When doing rekey, this completion callback delivers the `keymat' and * new `rekey'. The `prop' is ignored. The `keymat' has already been set * to the packet stream associated with the `ske'. Thus, after this * is called the new keys are in use. * ***/ typedef void (*SilcSKECompletionCb)(SilcSKE ske, SilcSKEStatus status, const SilcSKESecurityProperties prop, const SilcSKEKeyMaterial keymat, SilcSKERekeyMaterial rekey, void *context); /* Prototypes */ /****f* silcske/SilcSKEAPI/silc_ske_alloc * * SYNOPSIS * * SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, * SilcSKR repository, SilcPublicKey public_key, * SilcPrivateKey private_key, void *context); * * DESCRIPTION * * Allocates the SKE session context and returns it. The `rng' is * the random number generator the SKE is going to use when it needs * random number generation during the SKE session. The `context' is * user context that the libary will not touch. Application can get the * context by calling the fuction silc_ske_get_context function. The * application is responsible of freeing the `context'. After the * SKE session context is allocated application must call the * silc_ske_set_callbacks. * * If the `repository' is non-NULL then the remote's public key will be * verified from the repository. If it is not provided then the * SilcSKEVerifyCb callback must be set, and it will be called to * verify the key. If both `repository' and the callback is provided the * callback is called only if the key is not found from the repository. * * The `public_key' and `private_key' is the caller's identity used * during the key exchange. Giving `private_key' is optional if the * SILC_SKE_SP_FLAG_MUTUAL is not set and you are initiator. For * responder both `public_key' and `private_key' must be set. * * When allocating SKE session for rekey, the `repository' and `private_key' * pointers must be NULL and the SilcSKEVerifyCb callback must not be * set with silc_ske_set_callbacks. * * EXMPALE * * // Initiator example * params.version = version; * params.flags = SILC_SKE_SP_FLAG_PFS | SILC_SKE_SP_FLAG_MUTUAL; * ske = silc_ske_alloc(rng, scheduler, NULL, pk, prv, app); * silc_ske_set_callbacks(ske, verify_public_key, completion, app); * silc_ske_initiator(ske, stream, ¶ms, NULL); * ***/ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule, SilcSKR repository, SilcPublicKey public_key, SilcPrivateKey private_key, void *context); /****f* silcske/SilcSKEAPI/silc_ske_free * * SYNOPSIS * * void silc_ske_free(SilcSKE ske); * * DESCRIPTION * * Frees the SKE session context and all allocated resources. * ***/ void silc_ske_free(SilcSKE ske); /****f* silcske/SilcSKEAPI/silc_ske_get_context * * SYNOPSIS * * void *silc_ske_get_context(SilcSKE ske); * * DESCRIPTION * * Returns the context that was given as argument to silc_ske_alloc. * ***/ void *silc_ske_get_context(SilcSKE ske); /****f* silcske/SilcSKEAPI/silc_ske_set_callbacks * * SYNOPSIS * * void silc_ske_set_callbacks(SilcSKE ske, * SilcSKEVerifyCb verify_key, * SilcSKECompletion completed, * void *context); * * DESCRIPTION * * Sets the callback functions for the SKE session. * * The `verify_key' callback is called to verify the received public key * or certificate. The verification process is most likely asynchronous. * That is why the application must call the completion callback when the * verification process has been completed. If this SKE session context * is used to perform rekey, this callback usually is not provided as * argument since sending public key in rekey is not mandatory. Setting * this callback implies that remote end MUST send its public key. * * The `completed' callback will be called once the protocol has completed, * either successfully or with an error. The status of the protocol is * delivered to application with the callback. * * The `context' is passed as argument to all of the above callback * functions. * ***/ void silc_ske_set_callbacks(SilcSKE ske, SilcSKEVerifyCb verify_key, SilcSKECompletionCb completed, void *context); /****f* silcske/SilcSKEAPI/silc_ske_initiator * * SYNOPSIS * * SilcAsyncOperation * silc_ske_initiator(SilcSKE ske, * SilcPacketStream stream, * SilcSKEParams params, * SilcSKEStartPayload start_payload); * * DESCRIPTION * * Starts the SILC Key Exchange protocol as initiator. The completion * callback that was set in silc_ske_set_callbacks will be called once * the protocol has completed. The `stream' is the network connection * to the remote host. The SKE library will handle all key exchange * packets sent and received in the `stream' connection. The library will * also set the remote host's ID automatically to the `stream' if it is * present in the exchanged packets. The `params' include SKE parameters, * and it must be provided. * * If the `start_payload' is NULL the library will generate it * automatically. Caller may provide it if it wants to send its own * security properties instead of using the default ones library * generates. If caller provides it, it must not free it once it has * been given as argument to this function. * * This function returns SilcAsyncOperation operation context which can * be used to control the protocol from the application. Application may * for example safely abort the protocol at any point, if needed. Returns * NULL on error. * ***/ SilcAsyncOperation silc_ske_initiator(SilcSKE ske, SilcPacketStream stream, SilcSKEParams params, SilcSKEStartPayload start_payload); /****f* silcske/SilcSKEAPI/silc_ske_responder * * SYNOPSIS * * SilcAsyncOperation * silc_ske_responder(SilcSKE ske, * SilcPacketStream stream, * SilcSKEParams params); * * DESCRIPTION * * Starts SILC Key Exchange protocol as responder. The completion * callback that was set in silc_ske_set_callbacks will be called once * the protocol has completed. The `stream' is the network connection * to the remote host. The SKE library will handle all key exchange * packets sent and received in the `stream' connection. The library will * also set the remote hosts's ID automatically to the `stream' if it is * present in the exchanged packets. The `params' include SKE parameters, * and must be provided. * * This function returns SilcAsyncOperation operation context which can * be used to control the protocol from the application. Application may * for example safely abort the protocol at any point, if needed. Returns * NULL on error. * ***/ SilcAsyncOperation silc_ske_responder(SilcSKE ske, SilcPacketStream stream, SilcSKEParams params); /****f* silcske/SilcSKEAPI/silc_ske_rekey_initiator * * SYNOPSIS * * SilcAsyncOperation * silc_ske_rekey_initiator(SilcSKE ske, * SilcPacketStream stream, * SilcSKERekeyMaterial rekey); * * DESCRIPTION * * Starts SILC Key Exchange key regeneration (rekey) protocol. The `rekey' * is the rekey material received earlier in SilcSKECompletionCb. That * same callback is called after the rekey protocol is over to deliver new * key material and new rekey material. When the rekey is completed the * SKE library will automatically update the new keys into `stream'. The * completion callback is called after the new keys has been taken into * use. * * This function returns SilcAsyncOperation operation context which can * be used to control the protocol from the application. Application may * for example safely abort the protocol at any point, if needed. Returns * NULL on error. * ***/ SilcAsyncOperation silc_ske_rekey_initiator(SilcSKE ske, SilcPacketStream stream, SilcSKERekeyMaterial rekey); /****f* silcske/SilcSKEAPI/silc_ske_rekey_responder * * SYNOPSIS * * SilcAsyncOperation * silc_ske_rekey_responder(SilcSKE ske, * SilcPacketStream stream, * SilcSKERekeyMaterial rekey, * SilcPacket packet); * * DESCRIPTION * * Starts SILC Key Exchange key regeneration (rekey) protocol as responder. * The `rekey' is the rekey material received earlier in * SilcSKECompletionCb. That same callback is called after the rekey * protocol is over to deliver new key material and new rekey material. * When the rekey is completed the SKE library will automatically update * the new keys into `stream'. The completion callback is called after * the new keys has been taken into use. * * The `packet' is the SILC_PACKET_REKEY received to start the rekey * protocol. If `packet' is NULL it is assumed that the packet will be * received from the `stream'. * * This function returns SilcAsyncOperation operation context which can * be used to control the protocol from the application. Application may * for example safely abort the protocol at any point, if needed. Returns * NULL on error. * ***/ SilcAsyncOperation silc_ske_rekey_responder(SilcSKE ske, SilcPacketStream stream, SilcSKERekeyMaterial rekey, SilcPacket packet); /****f* silcske/SilcSKEAPI/silc_ske_set_keys * * SYNOPSIS * * SilcBool silc_ske_set_keys(SilcSKE ske, * SilcSKEKeyMaterial keymat, * SilcSKESecurityProperties prop, * SilcCipher *ret_send_key, * SilcCipher *ret_receive_key, * SilcHmac *ret_hmac_send, * SilcHmac *ret_hmac_receive, * SilcHash *ret_hash); * * DESCRIPTION * * This function can be used after successful key exchange to take the * key material `keymat' with security properties `prop' into use. * This will allocate send and receive ciphers, HMACs and hash for the * application. Caller must free the returned contexts. This is an * utility function. * ***/ SilcBool silc_ske_set_keys(SilcSKE ske, SilcSKEKeyMaterial keymat, SilcSKESecurityProperties prop, SilcCipher *ret_send_key, SilcCipher *ret_receive_key, SilcHmac *ret_hmac_send, SilcHmac *ret_hmac_receive, SilcHash *ret_hash); /****f* silcske/SilcSKEAPI/silc_ske_parse_version * * SYNOPSIS * * SilcBool silc_ske_parse_version(SilcSKE ske, * SilcUInt32 *protocol_version, * char **protocol_version_string, * SilcUInt32 *software_version, * char **software_version_string, * char **vendor_version); * * DESCRIPTION * * Utility function to parse the remote host's version string. This can * be called after the key exchange has been completed. * ***/ SilcBool silc_ske_parse_version(SilcSKE ske, SilcUInt32 *protocol_version, char **protocol_version_string, SilcUInt32 *software_version, char **software_version_string, char **vendor_version); /****f* silcske/SilcSKEAPI/silc_ske_get_security_properties * * SYNOPSIS * * SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske); * * DESCRIPTION * * Returns negotiated security properties from the `ske' or NULL if they * have not yet been negotiated. This may be called to retrieve the * security properties after the SilcSKECompletionCb has been called. * ***/ SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske); /****f* silcske/SilcSKEAPI/silc_ske_get_key_material * * SYNOPSIS * * SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske); * * DESCRIPTION * * Returns the negotiated key material from the `ske' or NULL if the * key material does not exist. The caller must not free the returned * pointer. * ***/ SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske); /****f* silcske/SilcSKEAPI/silc_ske_process_key_material_data * * SYNOPSIS * * const char *silc_ske_map_status(SilcSKEStatus status); * * DESCRIPTION * * Utility function to process key data `data' in the way specified * by the SILC Key Exchange protocol. This returns the processed key * material or NULL on error. Caller must free the returned key * material context by calling silc_ske_free_key_material. * ***/ SilcSKEKeyMaterial silc_ske_process_key_material_data(unsigned char *data, SilcUInt32 data_len, SilcUInt32 req_iv_len, SilcUInt32 req_enc_key_len, SilcUInt32 req_hmac_key_len, SilcHash hash); /****f* silcske/SilcSKEAPI/silc_ske_free_key_material * * SYNOPSIS * * void silc_ske_free_key_material(SilcSKEKeyMaterial key) * * DESCRIPTION * * Utility function to free the key material created by calling * silc_ske_process_key_material_data. * ***/ void silc_ske_free_key_material(SilcSKEKeyMaterial key); /****f* silcske/SilcSKEAPI/silc_ske_free_rekey_material * * SYNOPSIS * * void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey); * * DESCRIPTION * * Utility function to free the rekey material returned in the * SilcSKECompletionCb callback. * ***/ void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey); /****f* silcske/SilcSKEAPI/silc_ske_map_status * * SYNOPSIS * * const char *silc_ske_map_status(SilcSKEStatus status); * * DESCRIPTION * * Utility function to map the `status' into human readable message. * ***/ const char *silc_ske_map_status(SilcSKEStatus status); #include "silcske_i.h" #endif /* !SILCSKE_H */