5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2002 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.
21 #include "silcincludes.h"
23 #include "groups_internal.h"
25 /* Static functions */
26 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
29 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
30 unsigned char *return_hash,
31 SilcUInt32 *return_hash_len,
34 /* Structure to hold all SKE callbacks. */
35 struct SilcSKECallbacksStruct {
36 SilcSKESendPacketCb send_packet;
37 SilcSKECb payload_receive;
38 SilcSKEVerifyCb verify_key;
39 SilcSKECb proto_continue;
40 SilcSKECheckVersion check_version;
44 /* Allocates new SKE object. */
46 SilcSKE silc_ske_alloc(SilcRng rng, void *context)
50 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
52 ske = silc_calloc(1, sizeof(*ske));
55 ske->status = SILC_SKE_STATUS_OK;
57 ske->user_data = context;
63 /* Free's SKE object. */
65 void silc_ske_free(SilcSKE ske)
69 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
70 ske->status = SILC_SKE_STATUS_FREED;
74 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
77 /* Free start payload */
78 if (ske->start_payload)
79 silc_ske_payload_start_free(ske->start_payload);
83 silc_ske_payload_ke_free(ske->ke1_payload);
85 silc_ske_payload_ke_free(ske->ke2_payload);
86 silc_free(ske->remote_version);
91 silc_ske_group_free(ske->prop->group);
93 silc_pkcs_free(ske->prop->pkcs);
94 if (ske->prop->cipher)
95 silc_cipher_free(ske->prop->cipher);
97 silc_hash_free(ske->prop->hash);
99 silc_hmac_free(ske->prop->hmac);
100 silc_free(ske->prop);
102 if (ske->start_payload_copy)
103 silc_buffer_free(ske->start_payload_copy);
105 silc_mp_uninit(ske->x);
109 silc_mp_uninit(ske->KEY);
112 silc_free(ske->hash);
113 silc_free(ske->callbacks);
115 memset(ske, 'F', sizeof(*ske));
120 /* Sets the callback functions for the SKE session.
122 The `send_packet' callback is a function that sends the packet to
123 network. The SKE library will call it at any time packet needs to
124 be sent to the remote host.
126 The `payload_receive' callback is called when the remote host's Key
127 Exchange Start Payload has been processed. The payload is saved
128 to ske->start_payload if the application would need it. The application
129 must also provide the payload to the next state of the SKE.
131 The `verify_key' callback is called to verify the received public key
132 or certificate. The verification process is most likely asynchronous.
133 That is why the application must call the completion callback when the
134 verification process has been completed. The library then calls the user
135 callback (`proto_continue'), if it is provided to indicate that the SKE
136 protocol may continue.
138 The `proto_continue' callback is called to indicate that it is
139 safe to continue the execution of the SKE protocol after executing
140 an asynchronous operation, such as calling the `verify_key' callback
141 function, which is asynchronous. The application should check the
142 ske->status in this function to check whether it is Ok to continue
143 the execution of the protocol.
145 The `check_version' callback is called to verify the remote host's
146 version. The application may check its own version against the remote
147 host's version and determine whether supporting the remote host
150 The `context' is passed as argument to all of the above callback
153 void silc_ske_set_callbacks(SilcSKE ske,
154 SilcSKESendPacketCb send_packet,
155 SilcSKECb payload_receive,
156 SilcSKEVerifyCb verify_key,
157 SilcSKECb proto_continue,
158 SilcSKECheckVersion check_version,
162 silc_free(ske->callbacks);
163 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
166 ske->callbacks->send_packet = send_packet;
167 ske->callbacks->payload_receive = payload_receive;
168 ske->callbacks->verify_key = verify_key;
169 ske->callbacks->proto_continue = proto_continue;
170 ske->callbacks->check_version = check_version;
171 ske->callbacks->context = context;
174 /* Starts the SILC Key Exchange protocol for initiator. The connection
175 to the remote end must be established before calling this function
176 and the connecting socket must be sent as argument. This function
177 creates the Key Exchange Start Payload which includes all our
178 configured security properties. This payload is then sent to the
179 remote end for further processing. This payload must be sent as
180 argument to the function, however, it must not be encoded
181 already, it is done by this function. The caller must not free
182 the `start_payload' since the SKE library will save it.
184 The packet sending is done by calling a callback function. Caller
185 must provide a routine to send the packet. */
187 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
188 SilcSocketConnection sock,
189 SilcSKEStartPayload *start_payload)
191 SilcSKEStatus status = SILC_SKE_STATUS_OK;
192 SilcBuffer payload_buf;
194 SILC_LOG_DEBUG(("Start"));
199 /* Encode the payload */
200 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
201 if (status != SILC_SKE_STATUS_OK)
204 /* Take a copy of the payload buffer for future use. It is used to
205 compute the HASH value. */
206 ske->start_payload_copy = silc_buffer_copy(payload_buf);
207 ske->start_payload = start_payload;
209 /* Send the packet. */
210 if (ske->callbacks->send_packet)
211 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
212 ske->callbacks->context);
214 silc_buffer_free(payload_buf);
219 /* Function called after ske_initiator_start fuction. This receives
220 the remote ends Key Exchange Start payload which includes the
221 security properties selected by the responder from our payload
222 sent in the silc_ske_initiator_start function. */
224 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
225 SilcBuffer start_payload)
227 SilcSKEStatus status = SILC_SKE_STATUS_OK;
228 SilcSKEStartPayload *payload;
229 SilcSKESecurityProperties prop;
230 SilcSKEDiffieHellmanGroup group;
232 SILC_LOG_DEBUG(("Start"));
234 /* Decode the payload */
235 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
236 if (status != SILC_SKE_STATUS_OK) {
237 ske->status = status;
238 silc_ske_payload_start_free(ske->start_payload);
242 /* Check that the cookie is returned unmodified */
243 if (memcmp(ske->start_payload->cookie, payload->cookie,
244 ske->start_payload->cookie_len)) {
245 SILC_LOG_ERROR(("Responder modified our cookie and it must not do it"));
246 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
247 silc_ske_payload_start_free(ske->start_payload);
251 /* Check version string */
252 if (ske->callbacks->check_version) {
253 status = ske->callbacks->check_version(ske, payload->version,
254 payload->version_len,
255 ske->callbacks->context);
256 if (status != SILC_SKE_STATUS_OK) {
257 ske->status = status;
258 silc_ske_payload_start_free(ske->start_payload);
263 /* Free our KE Start Payload context, we don't need it anymore. */
264 silc_ske_payload_start_free(ske->start_payload);
266 /* Take the selected security properties into use while doing
267 the key exchange. This is used only while doing the key
268 exchange. The same data is returned to upper levels by calling
269 the callback function. */
270 ske->prop = prop = silc_calloc(1, sizeof(*prop));
273 prop->flags = payload->flags;
274 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
275 if (status != SILC_SKE_STATUS_OK)
280 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
281 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
285 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
286 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
290 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
291 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
295 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
296 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
300 /* Save remote's KE Start Payload */
301 ske->start_payload = payload;
303 /* Return the received payload by calling the callback function. */
304 if (ske->callbacks->payload_receive)
305 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
311 silc_ske_payload_start_free(payload);
313 silc_ske_group_free(group);
316 silc_pkcs_free(prop->pkcs);
318 silc_cipher_free(prop->cipher);
320 silc_hash_free(prop->hash);
322 silc_hmac_free(prop->hmac);
326 if (status == SILC_SKE_STATUS_OK)
327 return SILC_SKE_STATUS_ERROR;
329 ske->status = status;
333 /* This function creates random number x, such that 1 < x < q and
334 computes e = g ^ x mod p and sends the result to the remote end in
335 Key Exchange Payload. */
337 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
338 SilcPublicKey public_key,
339 SilcPrivateKey private_key,
340 SilcSKEPKType pk_type)
342 SilcSKEStatus status = SILC_SKE_STATUS_OK;
343 SilcBuffer payload_buf;
345 SilcSKEKEPayload *payload;
348 SILC_LOG_DEBUG(("Start"));
350 /* Create the random number x, 1 < x < q. */
351 x = silc_calloc(1, sizeof(*x));
353 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
358 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
359 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
361 if (status != SILC_SKE_STATUS_OK) {
364 ske->status = status;
368 /* Encode the result to Key Exchange Payload. */
370 payload = silc_calloc(1, sizeof(*payload));
374 ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
377 ske->ke1_payload = payload;
379 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
381 /* Do the Diffie Hellman computation, e = g ^ x mod p */
382 silc_mp_init(&payload->x);
383 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
384 &ske->prop->group->group);
388 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
389 if (!payload->pk_data) {
392 silc_mp_uninit(&payload->x);
394 ske->ke1_payload = NULL;
395 ske->status = SILC_SKE_STATUS_OK;
398 payload->pk_len = pk_len;
400 payload->pk_type = pk_type;
402 /* Compute signature data if we are doing mutual authentication */
403 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
404 unsigned char hash[32], sign[2048 + 1];
405 SilcUInt32 hash_len, sign_len;
407 SILC_LOG_DEBUG(("We are doing mutual authentication"));
408 SILC_LOG_DEBUG(("Computing HASH_i value"));
410 /* Compute the hash value */
411 memset(hash, 0, sizeof(hash));
412 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
414 SILC_LOG_DEBUG(("Signing HASH_i value"));
416 /* Sign the hash value */
417 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
418 private_key->prv_len);
419 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
420 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
423 silc_mp_uninit(&payload->x);
424 silc_free(payload->pk_data);
426 ske->ke1_payload = NULL;
427 ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
430 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
431 memcpy(payload->sign_data, sign, sign_len);
432 memset(sign, 0, sizeof(sign));
433 payload->sign_len = sign_len;
436 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
437 if (status != SILC_SKE_STATUS_OK) {
440 silc_mp_uninit(&payload->x);
441 silc_free(payload->pk_data);
442 silc_free(payload->sign_data);
444 ske->ke1_payload = NULL;
445 ske->status = status;
451 /* Send the packet. */
452 if (ske->callbacks->send_packet)
453 (*ske->callbacks->send_packet)(ske, payload_buf,
454 SILC_PACKET_KEY_EXCHANGE_1,
455 ske->callbacks->context);
457 silc_buffer_free(payload_buf);
462 /* An initiator finish final callback that is called to indicate that
463 the SKE protocol may continue. */
465 static void silc_ske_initiator_finish_final(SilcSKE ske,
466 SilcSKEStatus status,
469 SilcSKEKEPayload *payload;
470 unsigned char hash[32];
472 SilcPublicKey public_key = NULL;
474 /* If the SKE was freed during the async call then free it really now,
475 otherwise just decrement the reference counter. */
476 if (ske->status == SILC_SKE_STATUS_FREED) {
481 /* If the caller returns PENDING status SKE library will assume that
482 the caller will re-call this callback when it is not anymore in
484 if (status == SILC_SKE_STATUS_PENDING)
488 payload = ske->ke2_payload;
490 /* If the status is an error then the public key that was verified
491 by the caller is not authentic. */
492 if (status != SILC_SKE_STATUS_OK) {
493 ske->status = status;
494 if (ske->callbacks->proto_continue)
495 ske->callbacks->proto_continue(ske, ske->callbacks->context);
499 if (payload->pk_data) {
500 /* Decode the public key */
501 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
503 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
504 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
505 if (ske->callbacks->proto_continue)
506 ske->callbacks->proto_continue(ske, ske->callbacks->context);
510 SILC_LOG_DEBUG(("Public key is authentic"));
512 /* Compute the hash value */
513 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
514 if (status != SILC_SKE_STATUS_OK)
517 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
518 memcpy(ske->hash, hash, hash_len);
519 ske->hash_len = hash_len;
521 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
523 /* Verify signature */
524 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
525 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
526 payload->sign_len, hash, hash_len) == FALSE) {
527 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
528 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
532 SILC_LOG_DEBUG(("Signature is Ok"));
534 silc_pkcs_public_key_free(public_key);
535 memset(hash, 'F', hash_len);
538 ske->status = SILC_SKE_STATUS_OK;
540 /* Call the callback. The caller may now continue the SKE protocol. */
541 if (ske->callbacks->proto_continue)
542 ske->callbacks->proto_continue(ske, ske->callbacks->context);
547 memset(hash, 'F', sizeof(hash));
548 silc_ske_payload_ke_free(payload);
549 ske->ke2_payload = NULL;
551 silc_mp_uninit(ske->KEY);
556 silc_pkcs_public_key_free(public_key);
559 memset(ske->hash, 'F', hash_len);
560 silc_free(ske->hash);
564 if (status == SILC_SKE_STATUS_OK)
565 ske->status = SILC_SKE_STATUS_ERROR;
567 ske->status = status;
569 /* Call the callback. */
570 if (ske->callbacks->proto_continue)
571 ske->callbacks->proto_continue(ske, ske->callbacks->context);
574 /* Receives Key Exchange Payload from responder consisting responders
575 public key, f, and signature. This function verifies the public key,
576 computes the secret shared key and verifies the signature.
578 The `proto_continue' will be called to indicate that the caller may
579 continue with the SKE protocol. The caller must not continue
580 before the SKE libary has called that callback. If this function
581 returns an error the callback will not be called. It is called
582 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
583 However, note that when the library calls the callback the ske->status
586 This calls the `verify_key' callback to verify the received public
587 key or certificate. If the `verify_key' is provided then the remote
588 must send public key and it is considered to be an error if remote
589 does not send its public key. If caller is performing a re-key with
590 SKE then the `verify_key' is usually not provided when it is not also
591 required for the remote to send its public key. */
593 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
594 SilcBuffer ke_payload)
596 SilcSKEStatus status = SILC_SKE_STATUS_OK;
597 SilcSKEKEPayload *payload;
600 SILC_LOG_DEBUG(("Start"));
602 /* Decode the payload */
603 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
604 if (status != SILC_SKE_STATUS_OK) {
605 ske->status = status;
608 ske->ke2_payload = payload;
610 if (!payload->pk_data && ske->callbacks->verify_key) {
611 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
612 "even though we require it"));
613 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
617 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
619 /* Compute the shared secret key */
620 KEY = silc_calloc(1, sizeof(*KEY));
622 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
625 if (payload->pk_data && ske->callbacks->verify_key) {
626 SILC_LOG_DEBUG(("Verifying public key"));
629 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
630 payload->pk_type, ske->callbacks->context,
631 silc_ske_initiator_finish_final, NULL);
633 /* We will continue to the final state after the public key has
634 been verified by the caller. */
635 return SILC_SKE_STATUS_PENDING;
638 /* Continue to final state */
640 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
642 return SILC_SKE_STATUS_OK;
645 silc_ske_payload_ke_free(payload);
646 ske->ke2_payload = NULL;
648 silc_mp_uninit(ske->KEY);
652 if (status == SILC_SKE_STATUS_OK)
653 return SILC_SKE_STATUS_ERROR;
655 ske->status = status;
659 /* Starts Key Exchange protocol for responder. Responder receives
660 Key Exchange Start Payload from initiator consisting of all the
661 security properties the initiator supports. This function decodes
662 the payload and parses the payload further and selects the right
663 security properties. */
665 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
666 SilcSocketConnection sock,
668 SilcBuffer start_payload,
669 SilcSKESecurityPropertyFlag flags)
671 SilcSKEStatus status = SILC_SKE_STATUS_OK;
672 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
674 SILC_LOG_DEBUG(("Start"));
679 /* Decode the payload */
680 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
681 if (status != SILC_SKE_STATUS_OK) {
682 ske->status = status;
686 /* Take a copy of the payload buffer for future use. It is used to
687 compute the HASH value. */
688 ske->start_payload_copy = silc_buffer_copy(start_payload);
690 /* Force the mutual authentication flag if we want to do it. */
691 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
692 SILC_LOG_DEBUG(("Force mutual authentication"));
693 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
696 /* Force PFS flag if we require it */
697 if (flags & SILC_SKE_SP_FLAG_PFS) {
698 SILC_LOG_DEBUG(("Force PFS"));
699 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
702 /* Disable IV Included flag if requested */
703 if (remote_payload->flags & SILC_SKE_SP_FLAG_IV_INCLUDED &&
704 !(flags & SILC_SKE_SP_FLAG_IV_INCLUDED)) {
705 SILC_LOG_DEBUG(("We do not support IV Included flag"));
706 remote_payload->flags &= ~SILC_SKE_SP_FLAG_IV_INCLUDED;
709 /* Parse and select the security properties from the payload */
710 payload = silc_calloc(1, sizeof(*payload));
711 status = silc_ske_select_security_properties(ske, version,
712 payload, remote_payload);
713 if (status != SILC_SKE_STATUS_OK)
716 ske->start_payload = payload;
718 /* Call the callback function. */
719 if (ske->callbacks->payload_receive)
720 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
722 silc_ske_payload_start_free(remote_payload);
728 silc_ske_payload_start_free(remote_payload);
732 if (status == SILC_SKE_STATUS_OK)
733 return SILC_SKE_STATUS_ERROR;
735 ske->status = status;
739 /* The selected security properties from the initiator payload is now
740 encoded into Key Exchange Start Payload and sent to the initiator. */
742 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
744 SilcSKEStatus status = SILC_SKE_STATUS_OK;
745 SilcBuffer payload_buf;
746 SilcSKESecurityProperties prop;
747 SilcSKEDiffieHellmanGroup group = NULL;
749 SILC_LOG_DEBUG(("Start"));
751 /* Allocate security properties from the payload. These are allocated
752 only for this negotiation and will be free'd after KE is over. */
753 ske->prop = prop = silc_calloc(1, sizeof(*prop));
754 prop->flags = ske->start_payload->flags;
755 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
756 if (status != SILC_SKE_STATUS_OK)
761 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
762 &prop->pkcs) == FALSE) {
763 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
767 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
768 &prop->cipher) == FALSE) {
769 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
773 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
774 &prop->hash) == FALSE) {
775 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
779 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
780 &prop->hmac) == FALSE) {
781 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
785 /* Encode the payload */
786 status = silc_ske_payload_start_encode(ske, ske->start_payload,
788 if (status != SILC_SKE_STATUS_OK)
791 /* Send the packet. */
792 if (ske->callbacks->send_packet)
793 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
794 ske->callbacks->context);
796 silc_buffer_free(payload_buf);
802 silc_ske_group_free(group);
805 silc_pkcs_free(prop->pkcs);
807 silc_cipher_free(prop->cipher);
809 silc_hash_free(prop->hash);
811 silc_hmac_free(prop->hmac);
815 if (status == SILC_SKE_STATUS_OK)
816 return SILC_SKE_STATUS_ERROR;
818 ske->status = status;
822 /* An responder phase 2 final callback that is called to indicate that
823 the SKE protocol may continue. */
825 static void silc_ske_responder_phase2_final(SilcSKE ske,
826 SilcSKEStatus status,
829 SilcSKEKEPayload *recv_payload, *send_payload;
832 /* If the SKE was freed during the async call then free it really now,
833 otherwise just decrement the reference counter. */
834 if (ske->status == SILC_SKE_STATUS_FREED) {
839 /* If the caller returns PENDING status SKE library will assume that
840 the caller will re-call this callback when it is not anymore in
842 if (status == SILC_SKE_STATUS_PENDING)
846 recv_payload = ske->ke1_payload;
848 /* If the status is an error then the public key that was verified
849 by the caller is not authentic. */
850 if (status != SILC_SKE_STATUS_OK) {
851 ske->status = status;
852 if (ske->callbacks->proto_continue)
853 ske->callbacks->proto_continue(ske, ske->callbacks->context);
857 /* The public key verification was performed only if the Mutual
858 Authentication flag is set. */
859 if (ske->start_payload &&
860 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
861 SilcPublicKey public_key = NULL;
862 unsigned char hash[32];
865 /* Decode the public key */
866 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
867 recv_payload->pk_len,
869 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
870 SILC_LOG_ERROR(("Unsupported/malformed public key received"));
871 if (ske->callbacks->proto_continue)
872 ske->callbacks->proto_continue(ske, ske->callbacks->context);
876 SILC_LOG_DEBUG(("Public key is authentic"));
878 /* Compute the hash value */
879 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
880 if (status != SILC_SKE_STATUS_OK) {
881 ske->status = status;
882 if (ske->callbacks->proto_continue)
883 ske->callbacks->proto_continue(ske, ske->callbacks->context);
887 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
889 /* Verify signature */
890 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
891 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
892 recv_payload->sign_len, hash, hash_len) == FALSE) {
893 SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
894 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
895 if (ske->callbacks->proto_continue)
896 ske->callbacks->proto_continue(ske, ske->callbacks->context);
900 SILC_LOG_DEBUG(("Signature is Ok"));
902 silc_pkcs_public_key_free(public_key);
903 memset(hash, 'F', hash_len);
906 /* Create the random number x, 1 < x < q. */
907 x = silc_calloc(1, sizeof(*x));
910 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
911 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
913 if (status != SILC_SKE_STATUS_OK) {
916 ske->status = status;
917 if (ske->callbacks->proto_continue)
918 ske->callbacks->proto_continue(ske, ske->callbacks->context);
922 /* Save the results for later processing */
923 send_payload = silc_calloc(1, sizeof(*send_payload));
925 ske->ke2_payload = send_payload;
927 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
929 /* Do the Diffie Hellman computation, f = g ^ x mod p */
930 silc_mp_init(&send_payload->x);
931 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
932 &ske->prop->group->group);
934 /* Call the callback. The caller may now continue with the SKE protocol. */
935 ske->status = SILC_SKE_STATUS_OK;
936 if (ske->callbacks->proto_continue)
937 ske->callbacks->proto_continue(ske, ske->callbacks->context);
940 /* This function receives the Key Exchange Payload from the initiator.
941 This also performs the mutual authentication if required. Then, this
942 function first generated a random number x, such that 1 < x < q
943 and computes f = g ^ x mod p. This then puts the result f to a Key
946 The `proto_continue' will be called to indicate that the caller may
947 continue with the SKE protocol. The caller must not continue
948 before the SKE libary has called that callback. If this function
949 returns an error the callback will not be called. It is called
950 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
951 However, note that when the library calls the callback the ske->status
954 This calls the `verify_key' callback to verify the received public
955 key or certificate if the Mutual Authentication flag is set. If the
956 `verify_key' is provided then the remote must send public key and it
957 is considered to be an error if remote does not send its public key. */
959 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
960 SilcBuffer ke_payload)
962 SilcSKEStatus status = SILC_SKE_STATUS_OK;
963 SilcSKEKEPayload *recv_payload;
965 SILC_LOG_DEBUG(("Start"));
967 /* Decode Key Exchange Payload */
968 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
969 if (status != SILC_SKE_STATUS_OK) {
970 ske->status = status;
974 ske->ke1_payload = recv_payload;
976 /* Verify the received public key and verify the signature if we are
977 doing mutual authentication. */
978 if (ske->start_payload &&
979 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
981 SILC_LOG_DEBUG(("We are doing mutual authentication"));
983 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
984 SILC_LOG_ERROR(("Remote end did not send its public key (or "
985 "certificate), even though we require it"));
986 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
990 if (recv_payload->pk_data && ske->callbacks->verify_key) {
991 SILC_LOG_DEBUG(("Verifying public key"));
994 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
995 recv_payload->pk_len,
996 recv_payload->pk_type,
997 ske->callbacks->context,
998 silc_ske_responder_phase2_final, NULL);
1000 /* We will continue to the final state after the public key has
1001 been verified by the caller. */
1002 return SILC_SKE_STATUS_PENDING;
1006 /* Continue to final state */
1008 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
1010 return SILC_SKE_STATUS_OK;
1013 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
1014 value to be signed and sent to the other end. This then encodes Key
1015 Exchange Payload and sends it to the other end. */
1017 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
1018 SilcPublicKey public_key,
1019 SilcPrivateKey private_key,
1020 SilcSKEPKType pk_type)
1022 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1023 SilcBuffer payload_buf;
1025 unsigned char hash[32], sign[2048 + 1], *pk;
1026 SilcUInt32 hash_len, sign_len, pk_len;
1028 SILC_LOG_DEBUG(("Start"));
1030 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
1032 /* Compute the shared secret key */
1033 KEY = silc_calloc(1, sizeof(*KEY));
1035 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1036 &ske->prop->group->group);
1039 if (public_key && private_key) {
1040 SILC_LOG_DEBUG(("Getting public key"));
1042 /* Get the public key */
1043 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1045 status = SILC_SKE_STATUS_OUT_OF_MEMORY;
1048 ske->ke2_payload->pk_data = pk;
1049 ske->ke2_payload->pk_len = pk_len;
1051 SILC_LOG_DEBUG(("Computing HASH value"));
1053 /* Compute the hash value */
1054 memset(hash, 0, sizeof(hash));
1055 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1056 if (status != SILC_SKE_STATUS_OK)
1059 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1060 memcpy(ske->hash, hash, hash_len);
1061 ske->hash_len = hash_len;
1063 SILC_LOG_DEBUG(("Signing HASH value"));
1065 /* Sign the hash value */
1066 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1067 private_key->prv_len);
1068 if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
1069 !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
1070 status = SILC_SKE_STATUS_SIGNATURE_ERROR;
1073 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1074 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1075 memset(sign, 0, sizeof(sign));
1076 ske->ke2_payload->sign_len = sign_len;
1078 ske->ke2_payload->pk_type = pk_type;
1080 /* Encode the Key Exchange Payload */
1081 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1083 if (status != SILC_SKE_STATUS_OK)
1086 /* Send the packet. */
1087 if (ske->callbacks->send_packet)
1088 (*ske->callbacks->send_packet)(ske, payload_buf,
1089 SILC_PACKET_KEY_EXCHANGE_2,
1090 ske->callbacks->context);
1092 silc_buffer_free(payload_buf);
1097 silc_mp_uninit(ske->KEY);
1098 silc_free(ske->KEY);
1100 silc_ske_payload_ke_free(ske->ke2_payload);
1102 if (status == SILC_SKE_STATUS_OK)
1103 return SILC_SKE_STATUS_ERROR;
1105 ske->status = status;
1109 /* The Key Exchange protocol is ended by calling this function. This
1110 must not be called until the keys are processed like the protocol
1111 defines. This function is for both initiator and responder. */
1113 SilcSKEStatus silc_ske_end(SilcSKE ske)
1117 SILC_LOG_DEBUG(("Start"));
1119 packet = silc_buffer_alloc_size(4);
1121 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1122 silc_buffer_format(packet,
1123 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1126 if (ske->callbacks->send_packet)
1127 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1128 ske->callbacks->context);
1130 silc_buffer_free(packet);
1132 return SILC_SKE_STATUS_OK;
1135 /* Aborts the Key Exchange protocol. This is called if error occurs
1136 while performing the protocol. The status argument is the error
1137 status and it is sent to the remote end. */
1139 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1143 SILC_LOG_DEBUG(("Start"));
1145 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1146 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1148 packet = silc_buffer_alloc_size(4);
1150 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1151 silc_buffer_format(packet,
1152 SILC_STR_UI_INT((SilcUInt32)status),
1155 if (ske->callbacks->send_packet)
1156 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1157 ske->callbacks->context);
1159 silc_buffer_free(packet);
1161 return SILC_SKE_STATUS_OK;
1164 /* Assembles security properties to Key Exchange Start Payload to be
1165 sent to the remote end. This checks system wide (SILC system, that is)
1166 settings and chooses from those. However, if other properties
1167 should be used this function is easy to replace by another function,
1168 as, this function is called by the caller of the protocol and not
1169 by the protocol itself. */
1172 silc_ske_assemble_security_properties(SilcSKE ske,
1173 SilcSKESecurityPropertyFlag flags,
1174 const char *version,
1175 SilcSKEStartPayload **return_payload)
1177 SilcSKEStartPayload *rp;
1180 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1182 rp = silc_calloc(1, sizeof(*rp));
1185 rp->flags = (unsigned char)flags;
1187 /* Set random cookie */
1188 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1189 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1190 rp->cookie[i] = silc_rng_get_byte_fast(ske->rng);
1191 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1194 rp->version = strdup(version);
1195 rp->version_len = strlen(version);
1197 /* Get supported Key Exhange groups */
1198 rp->ke_grp_list = silc_ske_get_supported_groups();
1199 rp->ke_grp_len = strlen(rp->ke_grp_list);
1201 /* Get supported PKCS algorithms */
1202 rp->pkcs_alg_list = silc_pkcs_get_supported();
1203 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1205 /* Get supported encryption algorithms */
1206 rp->enc_alg_list = silc_cipher_get_supported();
1207 rp->enc_alg_len = strlen(rp->enc_alg_list);
1209 /* Get supported hash algorithms */
1210 rp->hash_alg_list = silc_hash_get_supported();
1211 rp->hash_alg_len = strlen(rp->hash_alg_list);
1213 /* Get supported HMACs */
1214 rp->hmac_alg_list = silc_hmac_get_supported();
1215 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1218 /* Get supported compression algorithms */
1219 rp->comp_alg_list = strdup("none");
1220 rp->comp_alg_len = strlen("none");
1222 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1223 2 + rp->version_len +
1224 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1225 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1226 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1228 *return_payload = rp;
1230 return SILC_SKE_STATUS_OK;
1233 /* Selects the supported security properties from the remote end's Key
1234 Exchange Start Payload. */
1237 silc_ske_select_security_properties(SilcSKE ske,
1238 const char *version,
1239 SilcSKEStartPayload *payload,
1240 SilcSKEStartPayload *remote_payload)
1242 SilcSKEStatus status;
1243 SilcSKEStartPayload *rp;
1247 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1249 rp = remote_payload;
1251 /* Check version string */
1252 if (ske->callbacks->check_version) {
1253 status = ske->callbacks->check_version(ske, rp->version,
1255 ske->callbacks->context);
1256 if (status != SILC_SKE_STATUS_OK) {
1257 ske->status = status;
1262 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1264 /* Flags are returned unchanged. */
1265 payload->flags = rp->flags;
1267 /* Take cookie, we must return it to sender unmodified. */
1268 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1269 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1270 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1272 /* Put our version to our reply */
1273 payload->version = strdup(version);
1274 payload->version_len = strlen(version);
1276 /* Get supported Key Exchange groups */
1277 cp = rp->ke_grp_list;
1278 if (cp && strchr(cp, ',')) {
1282 len = strcspn(cp, ",");
1283 item = silc_calloc(len + 1, sizeof(char));
1284 memcpy(item, cp, len);
1286 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1288 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1289 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1291 payload->ke_grp_len = len;
1292 payload->ke_grp_list = item;
1297 if (strlen(cp) == 0)
1306 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1307 SILC_LOG_DEBUG(("Could not find supported KE group"));
1309 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1313 if (!rp->ke_grp_len) {
1314 SILC_LOG_DEBUG(("KE group not defined in payload"));
1316 return SILC_SKE_STATUS_BAD_PAYLOAD;
1319 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1320 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1322 payload->ke_grp_len = rp->ke_grp_len;
1323 payload->ke_grp_list = strdup(rp->ke_grp_list);
1326 /* Get supported PKCS algorithms */
1327 cp = rp->pkcs_alg_list;
1328 if (cp && strchr(cp, ',')) {
1332 len = strcspn(cp, ",");
1333 item = silc_calloc(len + 1, sizeof(char));
1334 memcpy(item, cp, len);
1336 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1338 if (silc_pkcs_is_supported(item) == TRUE) {
1339 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1341 payload->pkcs_alg_len = len;
1342 payload->pkcs_alg_list = item;
1347 if (strlen(cp) == 0)
1356 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1357 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1358 silc_free(payload->ke_grp_list);
1360 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1364 if (!rp->pkcs_alg_len) {
1365 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1366 silc_free(payload->ke_grp_list);
1368 return SILC_SKE_STATUS_BAD_PAYLOAD;
1371 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1372 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1374 payload->pkcs_alg_len = rp->pkcs_alg_len;
1375 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1378 /* Get supported encryption algorithms */
1379 cp = rp->enc_alg_list;
1380 if (cp && strchr(cp, ',')) {
1384 len = strcspn(cp, ",");
1385 item = silc_calloc(len + 1, sizeof(char));
1386 memcpy(item, cp, len);
1388 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1390 if (silc_cipher_is_supported(item) == TRUE) {
1391 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1393 payload->enc_alg_len = len;
1394 payload->enc_alg_list = item;
1399 if (strlen(cp) == 0)
1408 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1409 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1410 silc_free(payload->ke_grp_list);
1411 silc_free(payload->pkcs_alg_list);
1413 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1417 if (!rp->enc_alg_len) {
1418 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1419 silc_free(payload->ke_grp_list);
1420 silc_free(payload->pkcs_alg_list);
1422 return SILC_SKE_STATUS_BAD_PAYLOAD;
1425 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1428 payload->enc_alg_len = rp->enc_alg_len;
1429 payload->enc_alg_list = strdup(rp->enc_alg_list);
1432 /* Get supported hash algorithms */
1433 cp = rp->hash_alg_list;
1434 if (cp && strchr(cp, ',')) {
1438 len = strcspn(cp, ",");
1439 item = silc_calloc(len + 1, sizeof(char));
1440 memcpy(item, cp, len);
1442 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1444 if (silc_hash_is_supported(item) == TRUE) {
1445 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1447 payload->hash_alg_len = len;
1448 payload->hash_alg_list = item;
1453 if (strlen(cp) == 0)
1462 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1463 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1464 silc_free(payload->ke_grp_list);
1465 silc_free(payload->pkcs_alg_list);
1466 silc_free(payload->enc_alg_list);
1468 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1472 if (!rp->hash_alg_len) {
1473 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1474 silc_free(payload->ke_grp_list);
1475 silc_free(payload->pkcs_alg_list);
1476 silc_free(payload->enc_alg_list);
1478 return SILC_SKE_STATUS_BAD_PAYLOAD;
1481 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1482 rp->hash_alg_list));
1484 payload->hash_alg_len = rp->hash_alg_len;
1485 payload->hash_alg_list = strdup(rp->hash_alg_list);
1488 /* Get supported HMACs */
1489 cp = rp->hmac_alg_list;
1490 if (cp && strchr(cp, ',')) {
1494 len = strcspn(cp, ",");
1495 item = silc_calloc(len + 1, sizeof(char));
1496 memcpy(item, cp, len);
1498 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1500 if (silc_hmac_is_supported(item) == TRUE) {
1501 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1503 payload->hmac_alg_len = len;
1504 payload->hmac_alg_list = item;
1509 if (strlen(cp) == 0)
1518 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1519 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1520 silc_free(payload->ke_grp_list);
1521 silc_free(payload->pkcs_alg_list);
1522 silc_free(payload->enc_alg_list);
1523 silc_free(payload->hash_alg_list);
1525 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1529 if (!rp->hmac_alg_len) {
1530 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1531 silc_free(payload->ke_grp_list);
1532 silc_free(payload->pkcs_alg_list);
1533 silc_free(payload->enc_alg_list);
1534 silc_free(payload->hash_alg_list);
1536 return SILC_SKE_STATUS_BAD_PAYLOAD;
1539 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1540 rp->hmac_alg_list));
1542 payload->hmac_alg_len = rp->hmac_alg_len;
1543 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1546 /* Get supported compression algorithms */
1547 cp = rp->comp_alg_list;
1548 if (cp && strchr(cp, ',')) {
1552 len = strcspn(cp, ",");
1553 item = silc_calloc(len + 1, sizeof(char));
1554 memcpy(item, cp, len);
1556 SILC_LOG_DEBUG(("Proposed Compression `%s'", item));
1559 if (!strcmp(item, "none")) {
1560 SILC_LOG_DEBUG(("Found Compression `%s'", item));
1561 payload->comp_alg_len = len;
1562 payload->comp_alg_list = item;
1566 if (silc_hmac_is_supported(item) == TRUE) {
1567 SILC_LOG_DEBUG(("Found Compression `%s'", item));
1568 payload->comp_alg_len = len;
1569 payload->comp_alg_list = item;
1575 if (strlen(cp) == 0)
1585 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1586 2 + payload->version_len +
1587 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1588 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1589 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1591 return SILC_SKE_STATUS_OK;
1594 /* Creates random number such that 1 < rnd < n and at most length
1595 of len bits. The rnd sent as argument must be initialized. */
1597 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1601 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1602 unsigned char *string;
1606 return SILC_SKE_STATUS_ERROR;
1608 SILC_LOG_DEBUG(("Creating random number"));
1610 l = ((len - 1) / 8);
1612 /* Get the random number as string */
1613 string = silc_rng_get_rn_data(ske->rng, l);
1615 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1617 /* Decode the string into a MP integer */
1618 silc_mp_bin2mp(string, l, rnd);
1619 silc_mp_mod_2exp(rnd, rnd, len);
1622 if (silc_mp_cmp_ui(rnd, 1) < 0)
1623 status = SILC_SKE_STATUS_ERROR;
1624 if (silc_mp_cmp(rnd, n) >= 0)
1625 status = SILC_SKE_STATUS_ERROR;
1627 memset(string, 'F', l);
1633 /* Creates a hash value HASH as defined in the SKE protocol. If the
1634 `initiator' is TRUE then this function is used to create the HASH_i
1635 hash value defined in the protocol. If it is FALSE then this is used
1636 to create the HASH value defined by the protocol. */
1638 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1639 unsigned char *return_hash,
1640 SilcUInt32 *return_hash_len,
1643 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1645 unsigned char *e, *f, *KEY;
1646 SilcUInt32 e_len, f_len, KEY_len;
1649 SILC_LOG_DEBUG(("Start"));
1651 if (initiator == FALSE) {
1652 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1653 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1654 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1656 /* Format the buffer used to compute the hash value */
1657 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1658 ske->ke2_payload->pk_len +
1659 ske->ke1_payload->pk_len +
1660 e_len + f_len + KEY_len);
1662 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1664 /* Initiator is not required to send its public key */
1665 if (!ske->ke1_payload->pk_data) {
1667 silc_buffer_format(buf,
1668 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1670 ske->start_payload_copy->
1672 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1673 ske->ke2_payload->pk_len),
1674 SILC_STR_UI_XNSTRING(e, e_len),
1675 SILC_STR_UI_XNSTRING(f, f_len),
1676 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1680 silc_buffer_format(buf,
1681 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1683 ske->start_payload_copy->
1685 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1686 ske->ke2_payload->pk_len),
1687 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1688 ske->ke1_payload->pk_len),
1689 SILC_STR_UI_XNSTRING(e, e_len),
1690 SILC_STR_UI_XNSTRING(f, f_len),
1691 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1695 silc_buffer_free(buf);
1696 memset(e, 0, e_len);
1697 memset(f, 0, f_len);
1698 memset(KEY, 0, KEY_len);
1702 return SILC_SKE_STATUS_ERROR;
1705 memset(e, 0, e_len);
1706 memset(f, 0, f_len);
1707 memset(KEY, 0, KEY_len);
1712 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1714 buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
1715 ske->ke1_payload->pk_len + e_len);
1717 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1719 /* Format the buffer used to compute the hash value */
1721 silc_buffer_format(buf,
1722 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1723 ske->start_payload_copy->len),
1724 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1725 ske->ke1_payload->pk_len),
1726 SILC_STR_UI_XNSTRING(e, e_len),
1729 silc_buffer_free(buf);
1730 memset(e, 0, e_len);
1732 return SILC_SKE_STATUS_ERROR;
1735 memset(e, 0, e_len);
1740 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1741 *return_hash_len = silc_hash_len(ske->prop->hash);
1743 if (initiator == FALSE) {
1744 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1746 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1749 silc_buffer_free(buf);
1754 /* Processes the provided key material `data' as the SILC protocol
1755 specification defines. */
1758 silc_ske_process_key_material_data(unsigned char *data,
1759 SilcUInt32 data_len,
1760 SilcUInt32 req_iv_len,
1761 SilcUInt32 req_enc_key_len,
1762 SilcUInt32 req_hmac_key_len,
1764 SilcSKEKeyMaterial *key)
1767 unsigned char hashd[32];
1768 SilcUInt32 hash_len = req_hmac_key_len;
1769 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1771 SILC_LOG_DEBUG(("Start"));
1773 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1774 return SILC_SKE_STATUS_ERROR;
1776 buf = silc_buffer_alloc_size(1 + data_len);
1778 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1779 silc_buffer_format(buf,
1780 SILC_STR_UI_CHAR(0),
1781 SILC_STR_UI_XNSTRING(data, data_len),
1785 memset(hashd, 0, sizeof(hashd));
1787 silc_hash_make(hash, buf->data, buf->len, hashd);
1788 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1789 memcpy(key->send_iv, hashd, req_iv_len);
1790 memset(hashd, 0, sizeof(hashd));
1792 silc_hash_make(hash, buf->data, buf->len, hashd);
1793 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1794 memcpy(key->receive_iv, hashd, req_iv_len);
1795 key->iv_len = req_iv_len;
1797 /* Take the encryption keys. If requested key size is more than
1798 the size of hash length we will distribute more key material
1799 as protocol defines. */
1801 if (enc_key_len > hash_len) {
1803 unsigned char k1[32], k2[32], k3[32];
1804 unsigned char *dtmp;
1807 if (enc_key_len > (3 * hash_len))
1808 return SILC_SKE_STATUS_ERROR;
1810 /* Take first round */
1811 memset(k1, 0, sizeof(k1));
1812 silc_hash_make(hash, buf->data, buf->len, k1);
1814 /* Take second round */
1815 dist = silc_buffer_alloc_size(data_len + hash_len);
1817 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1818 silc_buffer_format(dist,
1819 SILC_STR_UI_XNSTRING(data, data_len),
1820 SILC_STR_UI_XNSTRING(k1, hash_len),
1822 memset(k2, 0, sizeof(k2));
1823 silc_hash_make(hash, dist->data, dist->len, k2);
1825 /* Take third round */
1826 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1827 silc_buffer_pull_tail(dist, hash_len);
1828 silc_buffer_pull(dist, data_len + hash_len);
1829 silc_buffer_format(dist,
1830 SILC_STR_UI_XNSTRING(k2, hash_len),
1832 silc_buffer_push(dist, data_len + hash_len);
1833 memset(k3, 0, sizeof(k3));
1834 silc_hash_make(hash, dist->data, dist->len, k3);
1836 /* Then, save the keys */
1837 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1838 memcpy(dtmp, k1, hash_len);
1839 memcpy(dtmp + hash_len, k2, hash_len);
1840 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1842 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1843 memcpy(key->send_enc_key, dtmp, enc_key_len);
1844 key->enc_key_len = req_enc_key_len;
1846 memset(dtmp, 0, (3 * hash_len));
1847 memset(k1, 0, sizeof(k1));
1848 memset(k2, 0, sizeof(k2));
1849 memset(k3, 0, sizeof(k3));
1851 silc_buffer_clear(dist);
1852 silc_buffer_free(dist);
1854 /* Take normal hash as key */
1855 memset(hashd, 0, sizeof(hashd));
1856 silc_hash_make(hash, buf->data, buf->len, hashd);
1857 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1858 memcpy(key->send_enc_key, hashd, enc_key_len);
1859 key->enc_key_len = req_enc_key_len;
1863 if (enc_key_len > hash_len) {
1865 unsigned char k1[32], k2[32], k3[32];
1866 unsigned char *dtmp;
1869 if (enc_key_len > (3 * hash_len))
1870 return SILC_SKE_STATUS_ERROR;
1872 /* Take first round */
1873 memset(k1, 0, sizeof(k1));
1874 silc_hash_make(hash, buf->data, buf->len, k1);
1876 /* Take second round */
1877 dist = silc_buffer_alloc_size(data_len + hash_len);
1879 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1880 silc_buffer_format(dist,
1881 SILC_STR_UI_XNSTRING(data, data_len),
1882 SILC_STR_UI_XNSTRING(k1, hash_len),
1884 memset(k2, 0, sizeof(k2));
1885 silc_hash_make(hash, dist->data, dist->len, k2);
1887 /* Take third round */
1888 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1889 silc_buffer_pull_tail(dist, hash_len);
1890 silc_buffer_pull(dist, data_len + hash_len);
1891 silc_buffer_format(dist,
1892 SILC_STR_UI_XNSTRING(k2, hash_len),
1894 silc_buffer_push(dist, data_len + hash_len);
1895 memset(k3, 0, sizeof(k3));
1896 silc_hash_make(hash, dist->data, dist->len, k3);
1898 /* Then, save the keys */
1899 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1900 memcpy(dtmp, k1, hash_len);
1901 memcpy(dtmp + hash_len, k2, hash_len);
1902 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1904 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1905 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1906 key->enc_key_len = req_enc_key_len;
1908 memset(dtmp, 0, (3 * hash_len));
1909 memset(k1, 0, sizeof(k1));
1910 memset(k2, 0, sizeof(k2));
1911 memset(k3, 0, sizeof(k3));
1913 silc_buffer_clear(dist);
1914 silc_buffer_free(dist);
1916 /* Take normal hash as key */
1917 memset(hashd, 0, sizeof(hashd));
1918 silc_hash_make(hash, buf->data, buf->len, hashd);
1919 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1920 memcpy(key->receive_enc_key, hashd, enc_key_len);
1921 key->enc_key_len = req_enc_key_len;
1924 /* Take HMAC keys */
1925 memset(hashd, 0, sizeof(hashd));
1927 silc_hash_make(hash, buf->data, buf->len, hashd);
1928 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1929 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1930 memset(hashd, 0, sizeof(hashd));
1932 silc_hash_make(hash, buf->data, buf->len, hashd);
1933 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1934 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1935 key->hmac_key_len = req_hmac_key_len;
1936 memset(hashd, 0, sizeof(hashd));
1938 silc_buffer_clear(buf);
1939 silc_buffer_free(buf);
1941 return SILC_SKE_STATUS_OK;
1944 /* Processes negotiated key material as protocol specifies. This returns
1945 the actual keys to be used in the SILC. */
1947 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1948 SilcUInt32 req_iv_len,
1949 SilcUInt32 req_enc_key_len,
1950 SilcUInt32 req_hmac_key_len,
1951 SilcSKEKeyMaterial *key)
1953 SilcSKEStatus status;
1955 unsigned char *tmpbuf;
1958 /* Encode KEY to binary data */
1959 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1961 buf = silc_buffer_alloc_size(klen + ske->hash_len);
1963 return SILC_SKE_STATUS_OUT_OF_MEMORY;
1964 silc_buffer_format(buf,
1965 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1966 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1969 /* Process the key material */
1970 status = silc_ske_process_key_material_data(buf->data, buf->len,
1971 req_iv_len, req_enc_key_len,
1973 ske->prop->hash, key);
1975 memset(tmpbuf, 0, klen);
1977 silc_buffer_clear(buf);
1978 silc_buffer_free(buf);
1983 /* Free key material structure */
1985 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1991 silc_free(key->send_iv);
1992 if (key->receive_iv)
1993 silc_free(key->receive_iv);
1994 if (key->send_enc_key) {
1995 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1996 silc_free(key->send_enc_key);
1998 if (key->receive_enc_key) {
1999 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
2000 silc_free(key->receive_enc_key);
2002 if (key->send_hmac_key) {
2003 memset(key->send_hmac_key, 0, key->hmac_key_len);
2004 silc_free(key->send_hmac_key);
2006 if (key->receive_hmac_key) {
2007 memset(key->receive_hmac_key, 0, key->hmac_key_len);
2008 silc_free(key->receive_hmac_key);
2013 const char *silc_ske_status_string[] =
2017 "Unkown error occurred",
2018 "Bad payload in packet",
2019 "Unsupported group",
2020 "Unsupported cipher",
2022 "Unsupported hash function",
2024 "Unsupported public key (or certificate)",
2025 "Incorrect signature",
2026 "Bad or unsupported version",
2031 "Remote did not provide public key",
2032 "Key exchange protocol is not active",
2033 "Bad reserved field in packet",
2034 "Bad payload length in packet",
2035 "Error computing signature",
2036 "System out of memory",
2041 /* Maps status to readable string and returns the string. If string is not
2042 found and empty character string ("") is returned. */
2044 const char *silc_ske_map_status(SilcSKEStatus status)
2048 for (i = 0; silc_ske_status_string[i]; i++)
2050 return silc_ske_status_string[i];
2055 /* Parses remote host's version string. */
2057 bool silc_ske_parse_version(SilcSKE ske,
2058 SilcUInt32 *protocol_version,
2059 char **protocol_version_string,
2060 SilcUInt32 *software_version,
2061 char **software_version_string,
2062 char **vendor_version)
2064 return silc_parse_version_string(ske->remote_version,
2066 protocol_version_string,
2068 software_version_string,