5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /****h* silcske/SILC SKE Interface
24 * The SILC Key Exchange (SKE) protocol interface. The SKE protocol
25 * is used to negotiate secret key material between two parties, to be used
26 * as session key or some other key. For example, when client connects to
27 * server SKE is performed to exchange public keys, and to generate the key
28 * that is then used as session key. Two clients can execute SKE as well
29 * two create secret key material for securing for example file transfer
30 * stream. This SKE implementation provides easy interface for application
31 * that wants to use SKE.
38 /* Forward declarations */
39 typedef struct SilcSKECallbacksStruct *SilcSKECallbacks;
40 typedef struct SilcSKEStruct *SilcSKE;
42 /****d* silcske/SilcSKEAPI/SilcSKEStatus
46 * typedef enum { ... } SilcSKEStatus;
50 * Status types returned in SKE callbacks. This tell the status of
51 * the SKE session, and if an error occurred. Application can map the
52 * status to human readable string with silc_ske_map_status function.
57 /* These are defined by the protocol */
58 SILC_SKE_STATUS_OK = 0, /* No error */
59 SILC_SKE_STATUS_ERROR = 1, /* Unknown error */
60 SILC_SKE_STATUS_BAD_PAYLOAD = 2, /* Malformed payload */
61 SILC_SKE_STATUS_UNKNOWN_GROUP = 3, /* Unsupported DH group */
62 SILC_SKE_STATUS_UNKNOWN_CIPHER = 4, /* Unsupported cipher */
63 SILC_SKE_STATUS_UNKNOWN_PKCS = 5, /* Unsupported PKCS algorithm */
64 SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION = 6, /* Unsupported hash function */
65 SILC_SKE_STATUS_UNKNOWN_HMAC = 7, /* Unsupported HMAC */
66 SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY = 8, /* Unsupported/not trusted PK */
67 SILC_SKE_STATUS_INCORRECT_SIGNATURE = 9, /* Incorrect signature */
68 SILC_SKE_STATUS_BAD_VERSION = 10, /* Unsupported version */
69 SILC_SKE_STATUS_INVALID_COOKIE = 11, /* Cookie was modified */
71 /* Implementation specific status types */
72 SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED, /* Remote did not send PK */
73 SILC_SKE_STATUS_BAD_RESERVED_FIELD, /* Reserved field was not 0 */
74 SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH, /* Payload includes garbage */
75 SILC_SKE_STATUS_SIGNATURE_ERROR, /* Error computing signature */
76 SILC_SKE_STATUS_OUT_OF_MEMORY, /* System out of memory */
77 SILC_SKE_STATUS_TIMEOUT, /* Timeout */
81 #include "silcske_groups.h"
82 #include "silcske_payload.h"
84 /****d* silcske/SilcSKEAPI/SilcSKESecurityPropertyFlag
88 * typedef enum { ... } SilcSKESecurityPropertyFlag
92 * SKE security property flags as defined by the SK protocol.
97 SILC_SKE_SP_FLAG_NONE = 0x00, /* No flags */
98 SILC_SKE_SP_FLAG_IV_INCLUDED = 0x01, /* IV included in packet */
99 SILC_SKE_SP_FLAG_PFS = 0x02, /* Perfect Forward Secrecy */
100 SILC_SKE_SP_FLAG_MUTUAL = 0x04, /* Mutual authentication */
101 } SilcSKESecurityPropertyFlag;
104 /****s* silcske/SilcSKEAPI/SilcSKESecurityProperties
108 * typedef struct { ... } *SilcSKESecurityProperties;
112 * Security Properties negotiated between key exchange parties. This
113 * structure is filled from the Key Exchange Start Payload which is used
114 * to negotiate what security properties must be used in the
119 typedef struct SilcSKESecurityPropertiesStruct {
120 SilcSKESecurityPropertyFlag flags; /* Flags */
121 SilcSKEDiffieHellmanGroup group; /* Selected Diffie Hellman group */
122 SilcCipher cipher; /* Selected cipher */
123 SilcHmac hmac; /* Selected HMAC */
124 SilcHash hash; /* Selected hash algorithm */
125 SilcPublicKey public_key; /* Remote public key */
126 SilcUInt16 remote_port; /* Remote port, set when IV Included
127 set and using UDP/IP */
128 } *SilcSKESecurityProperties;
131 /****s* silcske/SilcSKEAPI/SilcSKEKeyMaterial
135 * typedef struct { ... } *SilcSKEKeyMaterial;
139 * This is the key material structure, and is passed as argument by the
140 * application to silc_ske_process_key_material_data function. It includes
141 * the processed key material which can be used as SILC session keys.
145 typedef struct SilcSKEKeyMaterialStruct {
146 unsigned char *send_iv;
147 unsigned char *receive_iv;
149 unsigned char *send_enc_key;
150 unsigned char *receive_enc_key;
151 SilcUInt32 enc_key_len; /* Key length in bits */
152 unsigned char *send_hmac_key;
153 unsigned char *receive_hmac_key;
154 SilcUInt32 hmac_key_len; /* Key length in bytes */
155 } *SilcSKEKeyMaterial;
158 /****s* silcske/SilcSKEAPI/SilcSKERekeyMaterial
162 * typedef struct { ... } *SilcSKERekeyMaterial;
166 * This context is returned after key exchange protocol to application
167 * in the completion callback. Application may save it and use it later
168 * to perform the rekey with silc_ske_rekey_initiator and/or
169 * silc_ske_rekey_responder functions. If application does not
170 * need the context, it may free it with silc_ske_free_rekey_material
174 typedef struct SilcSKERekeyMaterialStruct {
175 unsigned char *send_enc_key;
177 unsigned int enc_key_len : 23;
178 unsigned int ske_group : 8;
179 unsigned int pfs : 1;
180 } *SilcSKERekeyMaterial;
182 /****s* silcske/SilcSKEAPI/SilcSKEParams
186 * typedef struct { ... } *SilcSKEParams, SilcSKEParamsStruct;
190 * SKE parameters structure. This structure is given as argument to
191 * silc_ske_initiator and silc_ske_responder functions.
195 typedef struct SilcSKEParamsObject {
196 /* The SKE version string that is sent to the remote end. This field
197 must be set. Caller must free the pointer. */
200 /* Security property flags. When initiator sets these it requests them
201 from the responder. Responder may set here the flags it supports
202 and wants to enforce for the initiator. */
203 SilcSKESecurityPropertyFlag flags;
205 /* SILC Session port when using UDP/IP and SILC_SKE_SP_FLAG_IV_INCLUDED
206 flag. It is the port the remote will use as SILC session port after
207 the key exchange protocol. Ignored without SILC_SKE_SP_FLAG_IV_INCLUDED
209 SilcUInt16 session_port;
211 /* Key exchange timeout in seconds. If key exchange is not completed in
212 this time it will timeout. If not specified (zero), default value
213 (30 seconds) will be used. */
214 SilcUInt16 timeout_secs;
215 } *SilcSKEParams, SilcSKEParamsStruct;
218 /****d* silcske/SilcSKEAPI/SilcSKEPKType
222 * typedef enum { ... } SilcSKEPKType;
226 * Public key and certificate types defined by the SKE protocol.
231 SILC_SKE_PK_TYPE_SILC = 1, /* SILC Public Key, mandatory */
232 SILC_SKE_PK_TYPE_SSH2 = 2, /* SSH2 Public key, not supported */
233 SILC_SKE_PK_TYPE_X509V3 = 3, /* X.509v3 certificate, not supported */
234 SILC_SKE_PK_TYPE_OPENPGP = 4, /* OpenPGP certificate, not supported */
235 SILC_SKE_PK_TYPE_SPKI = 5 /* SPKI certificate, not supported */
239 /****f* silcske/SilcSKEAPI/SilcSKEVerifyCbCompletion
243 * typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske,
244 * SilcSKEStatus status,
249 * Completion callback that will be called when the public key
250 * has been verified. The `status' will indicate whether the public
251 * key were trusted or not.
254 typedef void (*SilcSKEVerifyCbCompletion)(SilcSKE ske,
255 SilcSKEStatus status,
258 /****f* silcske/SilcSKEAPI/SilcSKEVerifyCb
262 * typedef void (*SilcSKEVerifyCb)(SilcSKE ske,
263 * SilcPublicKey public_key,
265 * SilcSKEVerifyCbCompletion completion,
266 * void *completion_context);
270 * Callback function used to verify the received public key or certificate.
271 * The verification process is most likely asynchronous. That's why the
272 * application must call the `completion' callback when the verification
273 * process has been completed. The `context' is the context given as
274 * arugment to silc_ske_set_callbacks. See silc_ske_set_callbacks for
277 * If the key repository was provided in silc_ske_alloc this callback
278 * is called only if the public key was not found from the repository.
281 typedef void (*SilcSKEVerifyCb)(SilcSKE ske,
282 SilcPublicKey public_key,
284 SilcSKEVerifyCbCompletion completion,
285 void *completion_context);
287 /****f* silcske/SilcSKEAPI/SilcSKECompletionCb
291 * typedef void (*SilcSKECompletionCb)(SilcSKE ske,
292 * SilcSKEStatus status,
293 * const SilcSKESecurityProperties prop,
294 * const SilcSKEKeyMaterial keymat,
295 * SilcSKERekeyMaterial rekey,
300 * Completion callback. This is called after the key exchange protocol
301 * has been completed. It delivers the status of the protocol, and if
302 * successful the security properties `prop' that was negotiated in the
303 * protocol and the key material `keymat' that can be set into use by
304 * calling silc_ske_set_keys, and the rekey key material `rekey' which
305 * can be used later to start rekey protocol. The `prop' and `keymat'
306 * will remain valid as long as `ske' is valid. The `rekey' will remain
307 * valid until silc_ske_free_rekey_material is called. The application
308 * must call it to free the `rekey'.
310 * When doing rekey, this completion callback delivers the `keymat' and
311 * new `rekey'. The `prop' is ignored. The `keymat' has already been set
312 * to the packet stream associated with the `ske'. Thus, after this
313 * is called the new keys are in use.
316 typedef void (*SilcSKECompletionCb)(SilcSKE ske,
317 SilcSKEStatus status,
318 const SilcSKESecurityProperties prop,
319 const SilcSKEKeyMaterial keymat,
320 SilcSKERekeyMaterial rekey,
325 /****f* silcske/SilcSKEAPI/silc_ske_alloc
329 * SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
330 * SilcSKR repository, SilcPublicKey public_key,
331 * SilcPrivateKey private_key, void *context);
335 * Allocates the SKE session context and returns it. The `rng' is
336 * the random number generator the SKE is going to use when it needs
337 * random number generation during the SKE session. The `context' is
338 * user context that the libary will not touch. Application can get the
339 * context by calling the fuction silc_ske_get_context function. The
340 * application is responsible of freeing the `context'. After the
341 * SKE session context is allocated application must call the
342 * silc_ske_set_callbacks.
344 * If the `repository' is non-NULL then the remote's public key will be
345 * verified from the repository. If it is not provided then the
346 * SilcSKEVerifyCb callback must be set, and it will be called to
347 * verify the key. If both `repository' and the callback is provided the
348 * callback is called only if the key is not found from the repository.
350 * The `public_key' and `private_key' is the caller's identity used
351 * during the key exchange. Giving `private_key' is optional if the
352 * SILC_SKE_SP_FLAG_MUTUAL is not set and you are initiator. For
353 * responder both `public_key' and `private_key' must be set.
355 * When allocating SKE session for rekey, the `repository' and `private_key'
356 * pointers must be NULL and the SilcSKEVerifyCb callback must not be
357 * set with silc_ske_set_callbacks.
361 * // Initiator example
362 * params.version = version;
363 * params.flags = SILC_SKE_SP_FLAG_PFS | SILC_SKE_SP_FLAG_MUTUAL;
364 * ske = silc_ske_alloc(rng, scheduler, NULL, pk, prv, app);
365 * silc_ske_set_callbacks(ske, verify_public_key, completion, app);
366 * silc_ske_initiator(ske, stream, ¶ms, NULL);
369 SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
370 SilcSKR repository, SilcPublicKey public_key,
371 SilcPrivateKey private_key, void *context);
373 /****f* silcske/SilcSKEAPI/silc_ske_free
377 * void silc_ske_free(SilcSKE ske);
381 * Frees the SKE session context and all allocated resources.
384 void silc_ske_free(SilcSKE ske);
386 /****f* silcske/SilcSKEAPI/silc_ske_get_context
390 * void *silc_ske_get_context(SilcSKE ske);
394 * Returns the context that was given as argument to silc_ske_alloc.
397 void *silc_ske_get_context(SilcSKE ske);
399 /****f* silcske/SilcSKEAPI/silc_ske_set_callbacks
403 * void silc_ske_set_callbacks(SilcSKE ske,
404 * SilcSKEVerifyCb verify_key,
405 * SilcSKECompletion completed,
410 * Sets the callback functions for the SKE session.
412 * The `verify_key' callback is called to verify the received public key
413 * or certificate. The verification process is most likely asynchronous.
414 * That is why the application must call the completion callback when the
415 * verification process has been completed. If this SKE session context
416 * is used to perform rekey, this callback usually is not provided as
417 * argument since sending public key in rekey is not mandatory. Setting
418 * this callback implies that remote end MUST send its public key.
420 * The `completed' callback will be called once the protocol has completed,
421 * either successfully or with an error. The status of the protocol is
422 * delivered to application with the callback.
424 * The `context' is passed as argument to all of the above callback
428 void silc_ske_set_callbacks(SilcSKE ske,
429 SilcSKEVerifyCb verify_key,
430 SilcSKECompletionCb completed,
433 /****f* silcske/SilcSKEAPI/silc_ske_initiator
438 * silc_ske_initiator(SilcSKE ske,
439 * SilcPacketStream stream,
440 * SilcSKEParams params,
441 * SilcSKEStartPayload start_payload);
445 * Starts the SILC Key Exchange protocol as initiator. The completion
446 * callback that was set in silc_ske_set_callbacks will be called once
447 * the protocol has completed. The `stream' is the network connection
448 * to the remote host. The SKE library will handle all key exchange
449 * packets sent and received in the `stream' connection. The library will
450 * also set the remote host's ID automatically to the `stream' if it is
451 * present in the exchanged packets. The `params' include SKE parameters,
452 * and it must be provided.
454 * If the `start_payload' is NULL the library will generate it
455 * automatically. Caller may provide it if it wants to send its own
456 * security properties instead of using the default ones library
457 * generates. If caller provides it, it must not free it once it has
458 * been given as argument to this function.
460 * This function returns SilcAsyncOperation operation context which can
461 * be used to control the protocol from the application. Application may
462 * for example safely abort the protocol at any point, if needed. Returns
466 SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
467 SilcPacketStream stream,
468 SilcSKEParams params,
469 SilcSKEStartPayload start_payload);
471 /****f* silcske/SilcSKEAPI/silc_ske_responder
476 * silc_ske_responder(SilcSKE ske,
477 * SilcPacketStream stream,
478 * SilcSKEParams params);
482 * Starts SILC Key Exchange protocol as responder. The completion
483 * callback that was set in silc_ske_set_callbacks will be called once
484 * the protocol has completed. The `stream' is the network connection
485 * to the remote host. The SKE library will handle all key exchange
486 * packets sent and received in the `stream' connection. The library will
487 * also set the remote hosts's ID automatically to the `stream' if it is
488 * present in the exchanged packets. The `params' include SKE parameters,
489 * and must be provided.
491 * This function returns SilcAsyncOperation operation context which can
492 * be used to control the protocol from the application. Application may
493 * for example safely abort the protocol at any point, if needed. Returns
497 SilcAsyncOperation silc_ske_responder(SilcSKE ske,
498 SilcPacketStream stream,
499 SilcSKEParams params);
501 /****f* silcske/SilcSKEAPI/silc_ske_rekey_initiator
506 * silc_ske_rekey_initiator(SilcSKE ske,
507 * SilcPacketStream stream,
508 * SilcSKERekeyMaterial rekey);
512 * Starts SILC Key Exchange key regeneration (rekey) protocol. The `rekey'
513 * is the rekey material received earlier in SilcSKECompletionCb. That
514 * same callback is called after the rekey protocol is over to deliver new
515 * key material and new rekey material. When the rekey is completed the
516 * SKE library will automatically update the new keys into `stream'. The
517 * completion callback is called after the new keys has been taken into
520 * This function returns SilcAsyncOperation operation context which can
521 * be used to control the protocol from the application. Application may
522 * for example safely abort the protocol at any point, if needed. Returns
526 SilcAsyncOperation silc_ske_rekey_initiator(SilcSKE ske,
527 SilcPacketStream stream,
528 SilcSKERekeyMaterial rekey);
530 /****f* silcske/SilcSKEAPI/silc_ske_rekey_responder
535 * silc_ske_rekey_responder(SilcSKE ske,
536 * SilcPacketStream stream,
537 * SilcSKERekeyMaterial rekey,
538 * SilcPacket packet);
542 * Starts SILC Key Exchange key regeneration (rekey) protocol as responder.
543 * The `rekey' is the rekey material received earlier in
544 * SilcSKECompletionCb. That same callback is called after the rekey
545 * protocol is over to deliver new key material and new rekey material.
546 * When the rekey is completed the SKE library will automatically update
547 * the new keys into `stream'. The completion callback is called after
548 * the new keys has been taken into use.
550 * The `packet' is the SILC_PACKET_REKEY received to start the rekey
551 * protocol. If `packet' is NULL it is assumed that the packet will be
552 * received from the `stream'.
554 * This function returns SilcAsyncOperation operation context which can
555 * be used to control the protocol from the application. Application may
556 * for example safely abort the protocol at any point, if needed. Returns
560 SilcAsyncOperation silc_ske_rekey_responder(SilcSKE ske,
561 SilcPacketStream stream,
562 SilcSKERekeyMaterial rekey,
565 /****f* silcske/SilcSKEAPI/silc_ske_set_keys
569 * SilcBool silc_ske_set_keys(SilcSKE ske,
570 * SilcSKEKeyMaterial keymat,
571 * SilcSKESecurityProperties prop,
572 * SilcCipher *ret_send_key,
573 * SilcCipher *ret_receive_key,
574 * SilcHmac *ret_hmac_send,
575 * SilcHmac *ret_hmac_receive,
576 * SilcHash *ret_hash);
580 * This function can be used after successful key exchange to take the
581 * key material `keymat' with security properties `prop' into use.
582 * This will allocate send and receive ciphers, HMACs and hash for the
583 * application. Caller must free the returned contexts. This is an
587 SilcBool silc_ske_set_keys(SilcSKE ske,
588 SilcSKEKeyMaterial keymat,
589 SilcSKESecurityProperties prop,
590 SilcCipher *ret_send_key,
591 SilcCipher *ret_receive_key,
592 SilcHmac *ret_hmac_send,
593 SilcHmac *ret_hmac_receive,
596 /****f* silcske/SilcSKEAPI/silc_ske_parse_version
600 * SilcBool silc_ske_parse_version(SilcSKE ske,
601 * SilcUInt32 *protocol_version,
602 * char **protocol_version_string,
603 * SilcUInt32 *software_version,
604 * char **software_version_string,
605 * char **vendor_version);
609 * Utility function to parse the remote host's version string. This can
610 * be called after the key exchange has been completed.
613 SilcBool silc_ske_parse_version(SilcSKE ske,
614 SilcUInt32 *protocol_version,
615 char **protocol_version_string,
616 SilcUInt32 *software_version,
617 char **software_version_string,
618 char **vendor_version);
620 /****f* silcske/SilcSKEAPI/silc_ske_get_security_properties
624 * SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske);
628 * Returns negotiated security properties from the `ske' or NULL if they
629 * have not yet been negotiated. This may be called to retrieve the
630 * security properties after the SilcSKECompletionCb has been called.
633 SilcSKESecurityProperties silc_ske_get_security_properties(SilcSKE ske);
635 /****f* silcske/SilcSKEAPI/silc_ske_get_key_material
639 * SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske);
643 * Returns the negotiated key material from the `ske' or NULL if the
644 * key material does not exist. The caller must not free the returned
648 SilcSKEKeyMaterial silc_ske_get_key_material(SilcSKE ske);
650 /****f* silcske/SilcSKEAPI/silc_ske_process_key_material_data
654 * const char *silc_ske_map_status(SilcSKEStatus status);
658 * Utility function to process key data `data' in the way specified
659 * by the SILC Key Exchange protocol. This returns the processed key
660 * material or NULL on error. Caller must free the returned key
661 * material context by calling silc_ske_free_key_material.
665 silc_ske_process_key_material_data(unsigned char *data,
667 SilcUInt32 req_iv_len,
668 SilcUInt32 req_enc_key_len,
669 SilcUInt32 req_hmac_key_len,
672 /****f* silcske/SilcSKEAPI/silc_ske_free_key_material
676 * void silc_ske_free_key_material(SilcSKEKeyMaterial key)
680 * Utility function to free the key material created by calling
681 * silc_ske_process_key_material_data.
684 void silc_ske_free_key_material(SilcSKEKeyMaterial key);
686 /****f* silcske/SilcSKEAPI/silc_ske_free_rekey_material
690 * void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey);
694 * Utility function to free the rekey material returned in the
695 * SilcSKECompletionCb callback.
698 void silc_ske_free_rekey_material(SilcSKERekeyMaterial rekey);
700 /****f* silcske/SilcSKEAPI/silc_ske_map_status
704 * const char *silc_ske_map_status(SilcSKEStatus status);
708 * Utility function to map the `status' into human readable message.
711 const char *silc_ske_map_status(SilcSKEStatus status);
713 #include "silcske_i.h"
715 #endif /* !SILCSKE_H */