5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 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));
53 ske->status = SILC_SKE_STATUS_OK;
55 ske->user_data = context;
61 /* Free's SKE object. */
63 void silc_ske_free(SilcSKE ske)
67 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
68 ske->status = SILC_SKE_STATUS_FREED;
72 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
75 /* Free start payload */
76 if (ske->start_payload)
77 silc_ske_payload_start_free(ske->start_payload);
81 silc_ske_payload_ke_free(ske->ke1_payload);
83 silc_ske_payload_ke_free(ske->ke2_payload);
88 silc_ske_group_free(ske->prop->group);
90 silc_pkcs_free(ske->prop->pkcs);
91 if (ske->prop->cipher)
92 silc_cipher_free(ske->prop->cipher);
94 silc_hash_free(ske->prop->hash);
96 silc_hmac_free(ske->prop->hmac);
99 if (ske->start_payload_copy)
100 silc_buffer_free(ske->start_payload_copy);
102 silc_mp_uninit(ske->x);
106 silc_mp_uninit(ske->KEY);
109 silc_free(ske->hash);
110 silc_free(ske->callbacks);
115 /* Sets the callback functions for the SKE session.
117 The `send_packet' callback is a function that sends the packet to
118 network. The SKE library will call it at any time packet needs to
119 be sent to the remote host.
121 The `payload_receive' callback is called when the remote host's Key
122 Exchange Start Payload has been processed. The payload is saved
123 to ske->start_payload if the application would need it. The application
124 must also provide the payload to the next state of the SKE.
126 The `verify_key' callback is called to verify the received public key
127 or certificate. The verification process is most likely asynchronous.
128 That is why the application must call the completion callback when the
129 verification process has been completed. The library then calls the user
130 callback (`proto_continue'), if it is provided to indicate that the SKE
131 protocol may continue.
133 The `proto_continue' callback is called to indicate that it is
134 safe to continue the execution of the SKE protocol after executing
135 an asynchronous operation, such as calling the `verify_key' callback
136 function, which is asynchronous. The application should check the
137 ske->status in this function to check whether it is Ok to continue
138 the execution of the protocol.
140 The `check_version' callback is called to verify the remote host's
141 version. The application may check its own version against the remote
142 host's version and determine whether supporting the remote host
145 The `context' is passed as argument to all of the above callback
148 void silc_ske_set_callbacks(SilcSKE ske,
149 SilcSKESendPacketCb send_packet,
150 SilcSKECb payload_receive,
151 SilcSKEVerifyCb verify_key,
152 SilcSKECb proto_continue,
153 SilcSKECheckVersion check_version,
157 silc_free(ske->callbacks);
158 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
159 ske->callbacks->send_packet = send_packet;
160 ske->callbacks->payload_receive = payload_receive;
161 ske->callbacks->verify_key = verify_key;
162 ske->callbacks->proto_continue = proto_continue;
163 ske->callbacks->check_version = check_version;
164 ske->callbacks->context = context;
167 /* Starts the SILC Key Exchange protocol for initiator. The connection
168 to the remote end must be established before calling this function
169 and the connecting socket must be sent as argument. This function
170 creates the Key Exchange Start Payload which includes all our
171 configured security properties. This payload is then sent to the
172 remote end for further processing. This payload must be sent as
173 argument to the function, however, it must not be encoded
174 already, it is done by this function. The caller must not free
175 the `start_payload' since the SKE library will save it.
177 The packet sending is done by calling a callback function. Caller
178 must provide a routine to send the packet. */
180 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
181 SilcSocketConnection sock,
182 SilcSKEStartPayload *start_payload)
184 SilcSKEStatus status = SILC_SKE_STATUS_OK;
185 SilcBuffer payload_buf;
187 SILC_LOG_DEBUG(("Start"));
192 /* Encode the payload */
193 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
194 if (status != SILC_SKE_STATUS_OK)
197 /* Take a copy of the payload buffer for future use. It is used to
198 compute the HASH value. */
199 ske->start_payload_copy = silc_buffer_copy(payload_buf);
200 ske->start_payload = start_payload;
202 /* Send the packet. */
203 if (ske->callbacks->send_packet)
204 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
205 ske->callbacks->context);
207 silc_buffer_free(payload_buf);
212 /* Function called after ske_initiator_start fuction. This receives
213 the remote ends Key Exchange Start payload which includes the
214 security properties selected by the responder from our payload
215 sent in the silc_ske_initiator_start function. */
217 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
218 SilcBuffer start_payload)
220 SilcSKEStatus status = SILC_SKE_STATUS_OK;
221 SilcSKEStartPayload *payload;
222 SilcSKESecurityProperties prop;
223 SilcSKEDiffieHellmanGroup group;
225 SILC_LOG_DEBUG(("Start"));
227 /* Decode the payload */
228 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
229 if (status != SILC_SKE_STATUS_OK) {
230 ske->status = status;
231 silc_ske_payload_start_free(ske->start_payload);
235 /* Check that the cookie is returned unmodified */
236 if (memcmp(ske->start_payload->cookie, payload->cookie,
237 ske->start_payload->cookie_len)) {
238 SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
239 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
240 silc_ske_payload_start_free(ske->start_payload);
244 /* Check version string */
245 if (ske->callbacks->check_version) {
246 status = ske->callbacks->check_version(ske, payload->version,
247 payload->version_len,
248 ske->callbacks->context);
249 if (status != SILC_SKE_STATUS_OK) {
250 ske->status = status;
251 silc_ske_payload_start_free(ske->start_payload);
256 /* Free our KE Start Payload context, we don't need it anymore. */
257 silc_ske_payload_start_free(ske->start_payload);
259 /* Take the selected security properties into use while doing
260 the key exchange. This is used only while doing the key
261 exchange. The same data is returned to upper levels by calling
262 the callback function. */
263 ske->prop = prop = silc_calloc(1, sizeof(*prop));
264 prop->flags = payload->flags;
265 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
266 if (status != SILC_SKE_STATUS_OK)
271 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
272 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
276 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
277 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
281 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
282 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
286 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
287 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
291 /* Save remote's KE Start Payload */
292 ske->start_payload = payload;
294 /* Return the received payload by calling the callback function. */
295 if (ske->callbacks->payload_receive)
296 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
302 silc_ske_payload_start_free(payload);
304 silc_ske_group_free(group);
307 silc_pkcs_free(prop->pkcs);
309 silc_cipher_free(prop->cipher);
311 silc_hash_free(prop->hash);
313 silc_hmac_free(prop->hmac);
317 if (status == SILC_SKE_STATUS_OK)
318 return SILC_SKE_STATUS_ERROR;
320 ske->status = status;
324 /* This function creates random number x, such that 1 < x < q and
325 computes e = g ^ x mod p and sends the result to the remote end in
326 Key Exchange Payload. */
328 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
329 SilcPublicKey public_key,
330 SilcPrivateKey private_key,
331 SilcSKEPKType pk_type)
333 SilcSKEStatus status = SILC_SKE_STATUS_OK;
334 SilcBuffer payload_buf;
336 SilcSKEKEPayload *payload;
339 SILC_LOG_DEBUG(("Start"));
341 /* Create the random number x, 1 < x < q. */
342 x = silc_calloc(1, sizeof(*x));
345 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
346 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
348 if (status != SILC_SKE_STATUS_OK) {
351 ske->status = status;
355 /* Encode the result to Key Exchange Payload. */
357 payload = silc_calloc(1, sizeof(*payload));
358 ske->ke1_payload = payload;
360 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
362 /* Do the Diffie Hellman computation, e = g ^ x mod p */
363 silc_mp_init(&payload->x);
364 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
365 &ske->prop->group->group);
369 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
370 if (!payload->pk_data) {
373 silc_mp_uninit(&payload->x);
375 ske->status = SILC_SKE_STATUS_OK;
378 payload->pk_len = pk_len;
380 payload->pk_type = pk_type;
382 /* Compute signature data if we are doing mutual authentication */
383 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
384 unsigned char hash[32], sign[1024];
385 SilcUInt32 hash_len, sign_len;
387 SILC_LOG_DEBUG(("We are doing mutual authentication"));
388 SILC_LOG_DEBUG(("Computing HASH_i value"));
390 /* Compute the hash value */
391 memset(hash, 0, sizeof(hash));
392 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
394 SILC_LOG_DEBUG(("Signing HASH_i value"));
396 /* Sign the hash value */
397 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
398 private_key->prv_len);
399 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
400 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
401 memcpy(payload->sign_data, sign, sign_len);
402 memset(sign, 0, sizeof(sign));
403 payload->sign_len = sign_len;
406 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
407 if (status != SILC_SKE_STATUS_OK) {
410 silc_mp_uninit(&payload->x);
411 silc_free(payload->pk_data);
413 ske->status = status;
419 /* Send the packet. */
420 if (ske->callbacks->send_packet)
421 (*ske->callbacks->send_packet)(ske, payload_buf,
422 SILC_PACKET_KEY_EXCHANGE_1,
423 ske->callbacks->context);
425 silc_buffer_free(payload_buf);
430 /* An initiator finish final callback that is called to indicate that
431 the SKE protocol may continue. */
433 static void silc_ske_initiator_finish_final(SilcSKE ske,
434 SilcSKEStatus status,
437 SilcSKEKEPayload *payload;
438 unsigned char hash[32];
440 SilcPublicKey public_key = NULL;
442 /* If the SKE was freed during the async call then free it really now,
443 otherwise just decrement the reference counter. */
444 if (ske->status == SILC_SKE_STATUS_FREED) {
449 /* If the caller returns PENDING status SKE library will assume that
450 the caller will re-call this callback when it is not anymore in
452 if (status == SILC_SKE_STATUS_PENDING)
456 payload = ske->ke2_payload;
458 /* If the status is an error then the public key that was verified
459 by the caller is not authentic. */
460 if (status != SILC_SKE_STATUS_OK) {
461 ske->status = status;
462 if (ske->callbacks->proto_continue)
463 ske->callbacks->proto_continue(ske, ske->callbacks->context);
467 if (payload->pk_data) {
468 /* Decode the public key */
469 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
471 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
472 if (ske->callbacks->proto_continue)
473 ske->callbacks->proto_continue(ske, ske->callbacks->context);
477 SILC_LOG_DEBUG(("Public key is authentic"));
479 /* Compute the hash value */
480 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
481 if (status != SILC_SKE_STATUS_OK)
484 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
485 memcpy(ske->hash, hash, hash_len);
486 ske->hash_len = hash_len;
488 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
490 /* Verify signature */
491 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
492 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
493 payload->sign_len, hash, hash_len) == FALSE) {
495 SILC_LOG_DEBUG(("Signature don't match"));
497 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
501 SILC_LOG_DEBUG(("Signature is Ok"));
503 silc_pkcs_public_key_free(public_key);
504 memset(hash, 'F', hash_len);
507 ske->status = SILC_SKE_STATUS_OK;
509 /* Call the callback. The caller may now continue the SKE protocol. */
510 if (ske->callbacks->proto_continue)
511 ske->callbacks->proto_continue(ske, ske->callbacks->context);
516 memset(hash, 'F', sizeof(hash));
517 silc_ske_payload_ke_free(payload);
518 ske->ke2_payload = NULL;
520 silc_mp_uninit(ske->KEY);
525 silc_pkcs_public_key_free(public_key);
528 memset(ske->hash, 'F', hash_len);
529 silc_free(ske->hash);
533 if (status == SILC_SKE_STATUS_OK)
534 ske->status = SILC_SKE_STATUS_ERROR;
536 ske->status = status;
538 /* Call the callback. */
539 if (ske->callbacks->proto_continue)
540 ske->callbacks->proto_continue(ske, ske->callbacks->context);
543 /* Receives Key Exchange Payload from responder consisting responders
544 public key, f, and signature. This function verifies the public key,
545 computes the secret shared key and verifies the signature.
547 The `proto_continue' will be called to indicate that the caller may
548 continue with the SKE protocol. The caller must not continue
549 before the SKE libary has called that callback. If this function
550 returns an error the callback will not be called. It is called
551 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
552 However, note that when the library calls the callback the ske->status
555 This calls the `verify_key' callback to verify the received public
556 key or certificate. If the `verify_key' is provided then the remote
557 must send public key and it is considered to be an error if remote
558 does not send its public key. If caller is performing a re-key with
559 SKE then the `verify_key' is usually not provided when it is not also
560 required for the remote to send its public key. */
562 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
563 SilcBuffer ke_payload)
565 SilcSKEStatus status = SILC_SKE_STATUS_OK;
566 SilcSKEKEPayload *payload;
569 SILC_LOG_DEBUG(("Start"));
571 /* Decode the payload */
572 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
573 if (status != SILC_SKE_STATUS_OK) {
574 ske->status = status;
577 ske->ke2_payload = payload;
579 if (!payload->pk_data && ske->callbacks->verify_key) {
580 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
581 "even though we require it"));
582 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
586 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
588 /* Compute the shared secret key */
589 KEY = silc_calloc(1, sizeof(*KEY));
591 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
594 if (payload->pk_data && ske->callbacks->verify_key) {
595 SILC_LOG_DEBUG(("Verifying public key"));
598 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
599 payload->pk_type, ske->callbacks->context,
600 silc_ske_initiator_finish_final, NULL);
602 /* We will continue to the final state after the public key has
603 been verified by the caller. */
604 return SILC_SKE_STATUS_PENDING;
607 /* Continue to final state */
609 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
611 return SILC_SKE_STATUS_OK;
614 silc_ske_payload_ke_free(payload);
615 ske->ke2_payload = NULL;
617 silc_mp_uninit(ske->KEY);
621 if (status == SILC_SKE_STATUS_OK)
622 return SILC_SKE_STATUS_ERROR;
624 ske->status = status;
628 /* Starts Key Exchange protocol for responder. Responder receives
629 Key Exchange Start Payload from initiator consisting of all the
630 security properties the initiator supports. This function decodes
631 the payload and parses the payload further and selects the right
632 security properties. */
634 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
635 SilcSocketConnection sock,
637 SilcBuffer start_payload,
638 SilcSKESecurityPropertyFlag flags)
640 SilcSKEStatus status = SILC_SKE_STATUS_OK;
641 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
643 SILC_LOG_DEBUG(("Start"));
648 /* Decode the payload */
649 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
650 if (status != SILC_SKE_STATUS_OK) {
651 ske->status = status;
655 /* Take a copy of the payload buffer for future use. It is used to
656 compute the HASH value. */
657 ske->start_payload_copy = silc_buffer_copy(start_payload);
659 /* Force the mutual authentication flag if we want to do it. */
660 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
661 SILC_LOG_DEBUG(("Force mutual authentication"));
662 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
665 /* Force PFS flag if we require it */
666 if (flags & SILC_SKE_SP_FLAG_PFS) {
667 SILC_LOG_DEBUG(("Force PFS"));
668 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
671 /* Parse and select the security properties from the payload */
672 payload = silc_calloc(1, sizeof(*payload));
673 status = silc_ske_select_security_properties(ske, version,
674 payload, remote_payload);
675 if (status != SILC_SKE_STATUS_OK)
678 ske->start_payload = payload;
680 /* Call the callback function. */
681 if (ske->callbacks->payload_receive)
682 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
684 silc_ske_payload_start_free(remote_payload);
690 silc_ske_payload_start_free(remote_payload);
694 if (status == SILC_SKE_STATUS_OK)
695 return SILC_SKE_STATUS_ERROR;
697 ske->status = status;
701 /* The selected security properties from the initiator payload is now
702 encoded into Key Exchange Start Payload and sent to the initiator. */
704 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
706 SilcSKEStatus status = SILC_SKE_STATUS_OK;
707 SilcBuffer payload_buf;
708 SilcSKESecurityProperties prop;
709 SilcSKEDiffieHellmanGroup group = NULL;
711 SILC_LOG_DEBUG(("Start"));
713 /* Allocate security properties from the payload. These are allocated
714 only for this negotiation and will be free'd after KE is over. */
715 ske->prop = prop = silc_calloc(1, sizeof(*prop));
716 prop->flags = ske->start_payload->flags;
717 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
718 if (status != SILC_SKE_STATUS_OK)
723 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
724 &prop->pkcs) == FALSE) {
725 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
729 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
730 &prop->cipher) == FALSE) {
731 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
735 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
736 &prop->hash) == FALSE) {
737 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
741 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
742 &prop->hmac) == FALSE) {
743 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
747 /* Encode the payload */
748 status = silc_ske_payload_start_encode(ske, ske->start_payload,
750 if (status != SILC_SKE_STATUS_OK)
753 /* Send the packet. */
754 if (ske->callbacks->send_packet)
755 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
756 ske->callbacks->context);
758 silc_buffer_free(payload_buf);
764 silc_ske_group_free(group);
767 silc_pkcs_free(prop->pkcs);
769 silc_cipher_free(prop->cipher);
771 silc_hash_free(prop->hash);
773 silc_hmac_free(prop->hmac);
777 if (status == SILC_SKE_STATUS_OK)
778 return SILC_SKE_STATUS_ERROR;
780 ske->status = status;
784 /* An responder phase 2 final callback that is called to indicate that
785 the SKE protocol may continue. */
787 static void silc_ske_responder_phase2_final(SilcSKE ske,
788 SilcSKEStatus status,
791 SilcSKEKEPayload *recv_payload, *send_payload;
794 /* If the SKE was freed during the async call then free it really now,
795 otherwise just decrement the reference counter. */
796 if (ske->status == SILC_SKE_STATUS_FREED) {
801 /* If the caller returns PENDING status SKE library will assume that
802 the caller will re-call this callback when it is not anymore in
804 if (status == SILC_SKE_STATUS_PENDING)
808 recv_payload = ske->ke1_payload;
810 /* If the status is an error then the public key that was verified
811 by the caller is not authentic. */
812 if (status != SILC_SKE_STATUS_OK) {
813 ske->status = status;
814 if (ske->callbacks->proto_continue)
815 ske->callbacks->proto_continue(ske, ske->callbacks->context);
819 /* The public key verification was performed only if the Mutual
820 Authentication flag is set. */
821 if (ske->start_payload &&
822 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
823 SilcPublicKey public_key = NULL;
824 unsigned char hash[32];
827 /* Decode the public key */
828 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
829 recv_payload->pk_len,
831 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
832 if (ske->callbacks->proto_continue)
833 ske->callbacks->proto_continue(ske, ske->callbacks->context);
837 SILC_LOG_DEBUG(("Public key is authentic"));
839 /* Compute the hash value */
840 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
841 if (status != SILC_SKE_STATUS_OK) {
842 ske->status = status;
843 if (ske->callbacks->proto_continue)
844 ske->callbacks->proto_continue(ske, ske->callbacks->context);
848 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
850 /* Verify signature */
851 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
852 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
853 recv_payload->sign_len, hash, hash_len) == FALSE) {
855 SILC_LOG_DEBUG(("Signature don't match"));
857 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
858 if (ske->callbacks->proto_continue)
859 ske->callbacks->proto_continue(ske, ske->callbacks->context);
863 SILC_LOG_DEBUG(("Signature is Ok"));
865 silc_pkcs_public_key_free(public_key);
866 memset(hash, 'F', hash_len);
869 /* Create the random number x, 1 < x < q. */
870 x = silc_calloc(1, sizeof(*x));
873 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
874 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
876 if (status != SILC_SKE_STATUS_OK) {
879 ske->status = status;
880 if (ske->callbacks->proto_continue)
881 ske->callbacks->proto_continue(ske, ske->callbacks->context);
885 /* Save the results for later processing */
886 send_payload = silc_calloc(1, sizeof(*send_payload));
888 ske->ke2_payload = send_payload;
890 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
892 /* Do the Diffie Hellman computation, f = g ^ x mod p */
893 silc_mp_init(&send_payload->x);
894 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
895 &ske->prop->group->group);
897 /* Call the callback. The caller may now continue with the SKE protocol. */
898 ske->status = SILC_SKE_STATUS_OK;
899 if (ske->callbacks->proto_continue)
900 ske->callbacks->proto_continue(ske, ske->callbacks->context);
903 /* This function receives the Key Exchange Payload from the initiator.
904 This also performs the mutual authentication if required. Then, this
905 function first generated a random number x, such that 1 < x < q
906 and computes f = g ^ x mod p. This then puts the result f to a Key
909 The `proto_continue' will be called to indicate that the caller may
910 continue with the SKE protocol. The caller must not continue
911 before the SKE libary has called that callback. If this function
912 returns an error the callback will not be called. It is called
913 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
914 However, note that when the library calls the callback the ske->status
917 This calls the `verify_key' callback to verify the received public
918 key or certificate if the Mutual Authentication flag is set. If the
919 `verify_key' is provided then the remote must send public key and it
920 is considered to be an error if remote does not send its public key. */
922 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
923 SilcBuffer ke_payload)
925 SilcSKEStatus status = SILC_SKE_STATUS_OK;
926 SilcSKEKEPayload *recv_payload;
928 SILC_LOG_DEBUG(("Start"));
930 /* Decode Key Exchange Payload */
931 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
932 if (status != SILC_SKE_STATUS_OK) {
933 ske->status = status;
937 ske->ke1_payload = recv_payload;
939 /* Verify the received public key and verify the signature if we are
940 doing mutual authentication. */
941 if (ske->start_payload &&
942 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
944 SILC_LOG_DEBUG(("We are doing mutual authentication"));
946 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
947 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
948 "certificate), even though we require it"));
949 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
953 if (recv_payload->pk_data && ske->callbacks->verify_key) {
954 SILC_LOG_DEBUG(("Verifying public key"));
957 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
958 recv_payload->pk_len,
959 recv_payload->pk_type,
960 ske->callbacks->context,
961 silc_ske_responder_phase2_final, NULL);
963 /* We will continue to the final state after the public key has
964 been verified by the caller. */
965 return SILC_SKE_STATUS_PENDING;
969 /* Continue to final state */
971 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
973 return SILC_SKE_STATUS_OK;
976 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
977 value to be signed and sent to the other end. This then encodes Key
978 Exchange Payload and sends it to the other end. */
980 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
981 SilcPublicKey public_key,
982 SilcPrivateKey private_key,
983 SilcSKEPKType pk_type)
985 SilcSKEStatus status = SILC_SKE_STATUS_OK;
986 SilcBuffer payload_buf;
988 unsigned char hash[32], sign[1024], *pk;
989 SilcUInt32 hash_len, sign_len, pk_len;
991 SILC_LOG_DEBUG(("Start"));
993 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
995 /* Compute the shared secret key */
996 KEY = silc_calloc(1, sizeof(*KEY));
998 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
999 &ske->prop->group->group);
1002 if (public_key && private_key) {
1003 SILC_LOG_DEBUG(("Getting public key"));
1005 /* Get the public key */
1006 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1008 status = SILC_SKE_STATUS_ERROR;
1011 ske->ke2_payload->pk_data = pk;
1012 ske->ke2_payload->pk_len = pk_len;
1014 SILC_LOG_DEBUG(("Computing HASH value"));
1016 /* Compute the hash value */
1017 memset(hash, 0, sizeof(hash));
1018 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1019 if (status != SILC_SKE_STATUS_OK)
1022 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1023 memcpy(ske->hash, hash, hash_len);
1024 ske->hash_len = hash_len;
1026 SILC_LOG_DEBUG(("Signing HASH value"));
1028 /* Sign the hash value */
1029 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1030 private_key->prv_len);
1031 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1032 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1033 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1034 memset(sign, 0, sizeof(sign));
1035 ske->ke2_payload->sign_len = sign_len;
1037 ske->ke2_payload->pk_type = pk_type;
1039 /* Encode the Key Exchange Payload */
1040 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1042 if (status != SILC_SKE_STATUS_OK)
1045 /* Send the packet. */
1046 if (ske->callbacks->send_packet)
1047 (*ske->callbacks->send_packet)(ske, payload_buf,
1048 SILC_PACKET_KEY_EXCHANGE_2,
1049 ske->callbacks->context);
1051 silc_buffer_free(payload_buf);
1056 silc_mp_uninit(ske->KEY);
1057 silc_free(ske->KEY);
1059 silc_ske_payload_ke_free(ske->ke2_payload);
1061 if (status == SILC_SKE_STATUS_OK)
1062 return SILC_SKE_STATUS_ERROR;
1064 ske->status = status;
1068 /* The Key Exchange protocol is ended by calling this function. This
1069 must not be called until the keys are processed like the protocol
1070 defines. This function is for both initiator and responder. */
1072 SilcSKEStatus silc_ske_end(SilcSKE ske)
1076 SILC_LOG_DEBUG(("Start"));
1078 packet = silc_buffer_alloc(4);
1079 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1080 silc_buffer_format(packet,
1081 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1084 if (ske->callbacks->send_packet)
1085 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1086 ske->callbacks->context);
1088 silc_buffer_free(packet);
1090 return SILC_SKE_STATUS_OK;
1093 /* Aborts the Key Exchange protocol. This is called if error occurs
1094 while performing the protocol. The status argument is the error
1095 status and it is sent to the remote end. */
1097 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1101 SILC_LOG_DEBUG(("Start"));
1103 packet = silc_buffer_alloc(4);
1104 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1105 silc_buffer_format(packet,
1106 SILC_STR_UI_INT((SilcUInt32)status),
1109 if (ske->callbacks->send_packet)
1110 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1111 ske->callbacks->context);
1113 silc_buffer_free(packet);
1115 return SILC_SKE_STATUS_OK;
1118 /* Assembles security properties to Key Exchange Start Payload to be
1119 sent to the remote end. This checks system wide (SILC system, that is)
1120 settings and chooses from those. However, if other properties
1121 should be used this function is easy to replace by another function,
1122 as, this function is called by the caller of the protocol and not
1123 by the protocol itself. */
1126 silc_ske_assemble_security_properties(SilcSKE ske,
1127 SilcSKESecurityPropertyFlag flags,
1128 const char *version,
1129 SilcSKEStartPayload **return_payload)
1131 SilcSKEStartPayload *rp;
1134 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1136 rp = silc_calloc(1, sizeof(*rp));
1139 rp->flags = (unsigned char)flags;
1141 /* Set random cookie */
1142 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1143 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1144 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1145 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1148 rp->version = strdup(version);
1149 rp->version_len = strlen(version);
1151 /* Get supported Key Exhange groups */
1152 rp->ke_grp_list = silc_ske_get_supported_groups();
1153 rp->ke_grp_len = strlen(rp->ke_grp_list);
1155 /* Get supported PKCS algorithms */
1156 rp->pkcs_alg_list = silc_pkcs_get_supported();
1157 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1159 /* Get supported encryption algorithms */
1160 rp->enc_alg_list = silc_cipher_get_supported();
1161 rp->enc_alg_len = strlen(rp->enc_alg_list);
1163 /* Get supported hash algorithms */
1164 rp->hash_alg_list = silc_hash_get_supported();
1165 rp->hash_alg_len = strlen(rp->hash_alg_list);
1167 /* Get supported HMACs */
1168 rp->hmac_alg_list = silc_hmac_get_supported();
1169 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1172 /* Get supported compression algorithms */
1173 rp->comp_alg_list = strdup("");
1174 rp->comp_alg_len = 0;
1176 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1177 2 + rp->version_len +
1178 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1179 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1180 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1182 *return_payload = rp;
1184 return SILC_SKE_STATUS_OK;
1187 /* Selects the supported security properties from the remote end's Key
1188 Exchange Start Payload. */
1191 silc_ske_select_security_properties(SilcSKE ske,
1192 const char *version,
1193 SilcSKEStartPayload *payload,
1194 SilcSKEStartPayload *remote_payload)
1196 SilcSKEStatus status;
1197 SilcSKEStartPayload *rp;
1201 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1203 rp = remote_payload;
1205 /* Check version string */
1206 if (ske->callbacks->check_version) {
1207 status = ske->callbacks->check_version(ske, rp->version,
1209 ske->callbacks->context);
1210 if (status != SILC_SKE_STATUS_OK) {
1211 ske->status = status;
1216 /* Flags are returned unchanged. */
1217 payload->flags = rp->flags;
1219 /* Take cookie, we must return it to sender unmodified. */
1220 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1221 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1222 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1224 /* Put our version to our reply */
1225 payload->version = strdup(version);
1226 payload->version_len = strlen(version);
1228 /* Get supported Key Exchange groups */
1229 cp = rp->ke_grp_list;
1230 if (cp && strchr(cp, ',')) {
1234 len = strcspn(cp, ",");
1235 item = silc_calloc(len + 1, sizeof(char));
1236 memcpy(item, cp, len);
1238 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1240 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1241 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1243 payload->ke_grp_len = len;
1244 payload->ke_grp_list = item;
1249 if (strlen(cp) == 0)
1258 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1259 SILC_LOG_DEBUG(("Could not find supported KE group"));
1261 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1265 if (!rp->ke_grp_len) {
1266 SILC_LOG_DEBUG(("KE group not defined in payload"));
1268 return SILC_SKE_STATUS_BAD_PAYLOAD;
1271 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1272 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1274 payload->ke_grp_len = rp->ke_grp_len;
1275 payload->ke_grp_list = strdup(rp->ke_grp_list);
1278 /* Get supported PKCS algorithms */
1279 cp = rp->pkcs_alg_list;
1280 if (cp && strchr(cp, ',')) {
1284 len = strcspn(cp, ",");
1285 item = silc_calloc(len + 1, sizeof(char));
1286 memcpy(item, cp, len);
1288 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1290 if (silc_pkcs_is_supported(item) == TRUE) {
1291 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1293 payload->pkcs_alg_len = len;
1294 payload->pkcs_alg_list = item;
1299 if (strlen(cp) == 0)
1308 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1309 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1310 silc_free(payload->ke_grp_list);
1312 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1316 if (!rp->pkcs_alg_len) {
1317 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1318 silc_free(payload->ke_grp_list);
1320 return SILC_SKE_STATUS_BAD_PAYLOAD;
1323 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1324 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1326 payload->pkcs_alg_len = rp->pkcs_alg_len;
1327 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1330 /* Get supported encryption algorithms */
1331 cp = rp->enc_alg_list;
1332 if (cp && strchr(cp, ',')) {
1336 len = strcspn(cp, ",");
1337 item = silc_calloc(len + 1, sizeof(char));
1338 memcpy(item, cp, len);
1340 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1342 if (silc_cipher_is_supported(item) == TRUE) {
1343 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1345 payload->enc_alg_len = len;
1346 payload->enc_alg_list = item;
1351 if (strlen(cp) == 0)
1360 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1361 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1362 silc_free(payload->ke_grp_list);
1363 silc_free(payload->pkcs_alg_list);
1365 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1369 if (!rp->enc_alg_len) {
1370 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1371 silc_free(payload->ke_grp_list);
1372 silc_free(payload->pkcs_alg_list);
1374 return SILC_SKE_STATUS_BAD_PAYLOAD;
1377 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1380 payload->enc_alg_len = rp->enc_alg_len;
1381 payload->enc_alg_list = strdup(rp->enc_alg_list);
1384 /* Get supported hash algorithms */
1385 cp = rp->hash_alg_list;
1386 if (cp && strchr(cp, ',')) {
1390 len = strcspn(cp, ",");
1391 item = silc_calloc(len + 1, sizeof(char));
1392 memcpy(item, cp, len);
1394 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1396 if (silc_hash_is_supported(item) == TRUE) {
1397 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1399 payload->hash_alg_len = len;
1400 payload->hash_alg_list = item;
1405 if (strlen(cp) == 0)
1414 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1415 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1416 silc_free(payload->ke_grp_list);
1417 silc_free(payload->pkcs_alg_list);
1418 silc_free(payload->enc_alg_list);
1420 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1424 if (!rp->hash_alg_len) {
1425 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1426 silc_free(payload->ke_grp_list);
1427 silc_free(payload->pkcs_alg_list);
1428 silc_free(payload->enc_alg_list);
1430 return SILC_SKE_STATUS_BAD_PAYLOAD;
1433 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1434 rp->hash_alg_list));
1436 payload->hash_alg_len = rp->hash_alg_len;
1437 payload->hash_alg_list = strdup(rp->hash_alg_list);
1440 /* Get supported HMACs */
1441 cp = rp->hmac_alg_list;
1442 if (cp && strchr(cp, ',')) {
1446 len = strcspn(cp, ",");
1447 item = silc_calloc(len + 1, sizeof(char));
1448 memcpy(item, cp, len);
1450 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1452 if (silc_hmac_is_supported(item) == TRUE) {
1453 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1455 payload->hmac_alg_len = len;
1456 payload->hmac_alg_list = item;
1461 if (strlen(cp) == 0)
1470 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1471 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1472 silc_free(payload->ke_grp_list);
1473 silc_free(payload->pkcs_alg_list);
1474 silc_free(payload->enc_alg_list);
1475 silc_free(payload->hash_alg_list);
1477 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1481 if (!rp->hmac_alg_len) {
1482 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1483 silc_free(payload->ke_grp_list);
1484 silc_free(payload->pkcs_alg_list);
1485 silc_free(payload->enc_alg_list);
1486 silc_free(payload->hash_alg_list);
1488 return SILC_SKE_STATUS_BAD_PAYLOAD;
1491 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1492 rp->hmac_alg_list));
1494 payload->hmac_alg_len = rp->hmac_alg_len;
1495 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1499 /* Get supported compression algorithms */
1500 cp = rp->hash_alg_list;
1501 if (cp && strchr(cp, ',')) {
1505 len = strcspn(cp, ",");
1506 item = silc_calloc(len + 1, sizeof(char));
1507 memcpy(item, cp, len);
1509 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1511 if (silc_hash_is_supported(item) == TRUE) {
1512 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1514 payload->hash_alg_len = len;
1515 payload->hash_alg_list = item;
1520 if (strlen(cp) == 0)
1529 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1530 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1531 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1532 silc_free(payload->ke_grp_list);
1533 silc_free(payload->pkcs_alg_list);
1534 silc_free(payload->enc_alg_list);
1543 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1544 2 + payload->version_len +
1545 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1546 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1547 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1549 return SILC_SKE_STATUS_OK;
1552 /* Creates random number such that 1 < rnd < n and at most length
1553 of len bits. The rnd sent as argument must be initialized. */
1555 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1559 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1560 unsigned char *string;
1562 SILC_LOG_DEBUG(("Creating random number"));
1564 /* Get the random number as string */
1565 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1567 return SILC_SKE_STATUS_ERROR;
1569 /* Decode the string into a MP integer */
1570 silc_mp_bin2mp(string, (len / 8), rnd);
1571 silc_mp_mod_2exp(rnd, rnd, len);
1574 if (silc_mp_cmp_ui(rnd, 1) < 0)
1575 status = SILC_SKE_STATUS_ERROR;
1577 if (silc_mp_cmp(rnd, n) >= 0)
1578 status = SILC_SKE_STATUS_ERROR;
1580 memset(string, 'F', (len / 8));
1586 /* Creates a hash value HASH as defined in the SKE protocol. If the
1587 `initiator' is TRUE then this function is used to create the HASH_i
1588 hash value defined in the protocol. If it is FALSE then this is used
1589 to create the HASH value defined by the protocol. */
1591 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1592 unsigned char *return_hash,
1593 SilcUInt32 *return_hash_len,
1596 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1598 unsigned char *e, *f, *KEY;
1599 SilcUInt32 e_len, f_len, KEY_len;
1602 SILC_LOG_DEBUG(("Start"));
1604 if (initiator == FALSE) {
1605 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1606 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1607 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1609 /* Format the buffer used to compute the hash value */
1610 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1611 ske->ke2_payload->pk_len +
1612 ske->ke1_payload->pk_len +
1613 e_len + f_len + KEY_len);
1614 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1616 /* Initiator is not required to send its public key */
1617 if (!ske->ke1_payload->pk_data) {
1619 silc_buffer_format(buf,
1620 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1622 ske->start_payload_copy->
1624 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1625 ske->ke2_payload->pk_len),
1626 SILC_STR_UI_XNSTRING(e, e_len),
1627 SILC_STR_UI_XNSTRING(f, f_len),
1628 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1632 silc_buffer_format(buf,
1633 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1635 ske->start_payload_copy->
1637 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1638 ske->ke2_payload->pk_len),
1639 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1640 ske->ke1_payload->pk_len),
1641 SILC_STR_UI_XNSTRING(e, e_len),
1642 SILC_STR_UI_XNSTRING(f, f_len),
1643 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1647 silc_buffer_free(buf);
1648 memset(e, 0, e_len);
1649 memset(f, 0, f_len);
1650 memset(KEY, 0, KEY_len);
1654 return SILC_SKE_STATUS_ERROR;
1657 memset(e, 0, e_len);
1658 memset(f, 0, f_len);
1659 memset(KEY, 0, KEY_len);
1664 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1666 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1667 ske->ke1_payload->pk_len + e_len);
1668 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1670 /* Format the buffer used to compute the hash value */
1672 silc_buffer_format(buf,
1673 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1674 ske->start_payload_copy->len),
1675 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1676 ske->ke1_payload->pk_len),
1677 SILC_STR_UI_XNSTRING(e, e_len),
1680 silc_buffer_free(buf);
1681 memset(e, 0, e_len);
1683 return SILC_SKE_STATUS_ERROR;
1686 memset(e, 0, e_len);
1691 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1692 *return_hash_len = ske->prop->hash->hash->hash_len;
1694 if (initiator == FALSE) {
1695 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1697 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1700 silc_buffer_free(buf);
1705 /* Processes the provided key material `data' as the SILC protocol
1706 specification defines. */
1709 silc_ske_process_key_material_data(unsigned char *data,
1710 SilcUInt32 data_len,
1711 SilcUInt32 req_iv_len,
1712 SilcUInt32 req_enc_key_len,
1713 SilcUInt32 req_hmac_key_len,
1715 SilcSKEKeyMaterial *key)
1718 unsigned char hashd[32];
1719 SilcUInt32 hash_len = req_hmac_key_len;
1720 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1722 SILC_LOG_DEBUG(("Start"));
1724 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1725 return SILC_SKE_STATUS_ERROR;
1727 buf = silc_buffer_alloc(1 + data_len);
1728 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1729 silc_buffer_format(buf,
1730 SILC_STR_UI_CHAR(0),
1731 SILC_STR_UI_XNSTRING(data, data_len),
1735 memset(hashd, 0, sizeof(hashd));
1737 silc_hash_make(hash, buf->data, buf->len, hashd);
1738 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1739 memcpy(key->send_iv, hashd, req_iv_len);
1740 memset(hashd, 0, sizeof(hashd));
1742 silc_hash_make(hash, buf->data, buf->len, hashd);
1743 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1744 memcpy(key->receive_iv, hashd, req_iv_len);
1745 key->iv_len = req_iv_len;
1747 /* Take the encryption keys. If requested key size is more than
1748 the size of hash length we will distribute more key material
1749 as protocol defines. */
1751 if (enc_key_len > hash_len) {
1753 unsigned char k1[32], k2[32], k3[32];
1754 unsigned char *dtmp;
1757 if (enc_key_len > (3 * hash_len))
1758 return SILC_SKE_STATUS_ERROR;
1760 /* Take first round */
1761 memset(k1, 0, sizeof(k1));
1762 silc_hash_make(hash, buf->data, buf->len, k1);
1764 /* Take second round */
1765 dist = silc_buffer_alloc(data_len + hash_len);
1766 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1767 silc_buffer_format(dist,
1768 SILC_STR_UI_XNSTRING(data, data_len),
1769 SILC_STR_UI_XNSTRING(k1, hash_len),
1771 memset(k2, 0, sizeof(k2));
1772 silc_hash_make(hash, dist->data, dist->len, k2);
1774 /* Take third round */
1775 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1776 silc_buffer_pull_tail(dist, hash_len);
1777 silc_buffer_pull(dist, data_len + hash_len);
1778 silc_buffer_format(dist,
1779 SILC_STR_UI_XNSTRING(k2, hash_len),
1781 silc_buffer_push(dist, data_len + hash_len);
1782 memset(k3, 0, sizeof(k3));
1783 silc_hash_make(hash, dist->data, dist->len, k3);
1785 /* Then, save the keys */
1786 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1787 memcpy(dtmp, k1, hash_len);
1788 memcpy(dtmp + hash_len, k2, hash_len);
1789 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1791 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1792 memcpy(key->send_enc_key, dtmp, enc_key_len);
1793 key->enc_key_len = req_enc_key_len;
1795 memset(dtmp, 0, (3 * hash_len));
1796 memset(k1, 0, sizeof(k1));
1797 memset(k2, 0, sizeof(k2));
1798 memset(k3, 0, sizeof(k3));
1800 silc_buffer_free(dist);
1802 /* Take normal hash as key */
1803 memset(hashd, 0, sizeof(hashd));
1804 silc_hash_make(hash, buf->data, buf->len, hashd);
1805 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1806 memcpy(key->send_enc_key, hashd, enc_key_len);
1807 key->enc_key_len = req_enc_key_len;
1811 if (enc_key_len > hash_len) {
1813 unsigned char k1[32], k2[32], k3[32];
1814 unsigned char *dtmp;
1817 if (enc_key_len > (3 * hash_len))
1818 return SILC_SKE_STATUS_ERROR;
1820 /* Take first round */
1821 memset(k1, 0, sizeof(k1));
1822 silc_hash_make(hash, buf->data, buf->len, k1);
1824 /* Take second round */
1825 dist = silc_buffer_alloc(data_len + hash_len);
1826 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1827 silc_buffer_format(dist,
1828 SILC_STR_UI_XNSTRING(data, data_len),
1829 SILC_STR_UI_XNSTRING(k1, hash_len),
1831 memset(k2, 0, sizeof(k2));
1832 silc_hash_make(hash, dist->data, dist->len, k2);
1834 /* Take third round */
1835 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1836 silc_buffer_pull_tail(dist, hash_len);
1837 silc_buffer_pull(dist, data_len + hash_len);
1838 silc_buffer_format(dist,
1839 SILC_STR_UI_XNSTRING(k2, hash_len),
1841 silc_buffer_push(dist, data_len + hash_len);
1842 memset(k3, 0, sizeof(k3));
1843 silc_hash_make(hash, dist->data, dist->len, k3);
1845 /* Then, save the keys */
1846 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1847 memcpy(dtmp, k1, hash_len);
1848 memcpy(dtmp + hash_len, k2, hash_len);
1849 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1851 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1852 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1853 key->enc_key_len = req_enc_key_len;
1855 memset(dtmp, 0, (3 * hash_len));
1856 memset(k1, 0, sizeof(k1));
1857 memset(k2, 0, sizeof(k2));
1858 memset(k3, 0, sizeof(k3));
1860 silc_buffer_free(dist);
1862 /* Take normal hash as key */
1863 memset(hashd, 0, sizeof(hashd));
1864 silc_hash_make(hash, buf->data, buf->len, hashd);
1865 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1866 memcpy(key->receive_enc_key, hashd, enc_key_len);
1867 key->enc_key_len = req_enc_key_len;
1870 /* Take HMAC keys */
1871 memset(hashd, 0, sizeof(hashd));
1873 silc_hash_make(hash, buf->data, buf->len, hashd);
1874 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1875 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1876 memset(hashd, 0, sizeof(hashd));
1878 silc_hash_make(hash, buf->data, buf->len, hashd);
1879 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1880 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1881 key->hmac_key_len = req_hmac_key_len;
1882 memset(hashd, 0, sizeof(hashd));
1884 silc_buffer_free(buf);
1886 return SILC_SKE_STATUS_OK;
1889 /* Processes negotiated key material as protocol specifies. This returns
1890 the actual keys to be used in the SILC. */
1892 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1893 SilcUInt32 req_iv_len,
1894 SilcUInt32 req_enc_key_len,
1895 SilcUInt32 req_hmac_key_len,
1896 SilcSKEKeyMaterial *key)
1898 SilcSKEStatus status;
1900 unsigned char *tmpbuf;
1903 /* Encode KEY to binary data */
1904 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1906 buf = silc_buffer_alloc(klen + ske->hash_len);
1907 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1908 silc_buffer_format(buf,
1909 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1910 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1913 /* Process the key material */
1914 status = silc_ske_process_key_material_data(buf->data, buf->len,
1915 req_iv_len, req_enc_key_len,
1917 ske->prop->hash, key);
1919 memset(tmpbuf, 0, klen);
1921 silc_buffer_free(buf);
1926 /* Free key material structure */
1928 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1934 silc_free(key->send_iv);
1935 if (key->receive_iv)
1936 silc_free(key->receive_iv);
1937 if (key->send_enc_key) {
1938 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1939 silc_free(key->send_enc_key);
1941 if (key->receive_enc_key) {
1942 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1943 silc_free(key->receive_enc_key);
1945 if (key->send_hmac_key) {
1946 memset(key->send_hmac_key, 0, key->hmac_key_len);
1947 silc_free(key->send_hmac_key);
1949 if (key->receive_hmac_key) {
1950 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1951 silc_free(key->receive_hmac_key);
1956 const char *silc_ske_status_string[] =
1960 "Unkown error occurred",
1961 "Bad payload in packet",
1962 "Unsupported group",
1963 "Unsupported cipher",
1965 "Unsupported hash function",
1967 "Unsupported public key (or certificate)",
1968 "Incorrect signature",
1969 "Bad or unsupported version",
1974 "Remote did not provide public key",
1975 "Key exchange protocol is not active",
1976 "Bad reserved field in packet",
1977 "Bad payload length in packet",
1983 /* Maps status to readable string and returns the string. If string is not
1984 found and empty character string ("") is returned. */
1986 const char *silc_ske_map_status(SilcSKEStatus status)
1990 for (i = 0; silc_ske_status_string[i]; i++)
1992 return silc_ske_status_string[i];
1997 /* Parses remote host's version string. */
1999 bool silc_ske_parse_version(SilcSKE ske,
2000 SilcUInt32 *protocol_version,
2001 char **protocol_version_string,
2002 SilcUInt32 *software_version,
2003 char **software_version_string,
2004 char **vendor_version)
2006 return silc_parse_version_string(ske->start_payload->version,
2008 protocol_version_string,
2010 software_version_string,