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 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1104 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1106 packet = silc_buffer_alloc(4);
1107 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1108 silc_buffer_format(packet,
1109 SILC_STR_UI_INT((SilcUInt32)status),
1112 if (ske->callbacks->send_packet)
1113 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1114 ske->callbacks->context);
1116 silc_buffer_free(packet);
1118 return SILC_SKE_STATUS_OK;
1121 /* Assembles security properties to Key Exchange Start Payload to be
1122 sent to the remote end. This checks system wide (SILC system, that is)
1123 settings and chooses from those. However, if other properties
1124 should be used this function is easy to replace by another function,
1125 as, this function is called by the caller of the protocol and not
1126 by the protocol itself. */
1129 silc_ske_assemble_security_properties(SilcSKE ske,
1130 SilcSKESecurityPropertyFlag flags,
1131 const char *version,
1132 SilcSKEStartPayload **return_payload)
1134 SilcSKEStartPayload *rp;
1137 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1139 rp = silc_calloc(1, sizeof(*rp));
1142 rp->flags = (unsigned char)flags;
1144 /* Set random cookie */
1145 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1146 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1147 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1148 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1151 rp->version = strdup(version);
1152 rp->version_len = strlen(version);
1154 /* Get supported Key Exhange groups */
1155 rp->ke_grp_list = silc_ske_get_supported_groups();
1156 rp->ke_grp_len = strlen(rp->ke_grp_list);
1158 /* Get supported PKCS algorithms */
1159 rp->pkcs_alg_list = silc_pkcs_get_supported();
1160 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1162 /* Get supported encryption algorithms */
1163 rp->enc_alg_list = silc_cipher_get_supported();
1164 rp->enc_alg_len = strlen(rp->enc_alg_list);
1166 /* Get supported hash algorithms */
1167 rp->hash_alg_list = silc_hash_get_supported();
1168 rp->hash_alg_len = strlen(rp->hash_alg_list);
1170 /* Get supported HMACs */
1171 rp->hmac_alg_list = silc_hmac_get_supported();
1172 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1175 /* Get supported compression algorithms */
1176 rp->comp_alg_list = strdup("");
1177 rp->comp_alg_len = 0;
1179 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1180 2 + rp->version_len +
1181 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1182 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1183 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1185 *return_payload = rp;
1187 return SILC_SKE_STATUS_OK;
1190 /* Selects the supported security properties from the remote end's Key
1191 Exchange Start Payload. */
1194 silc_ske_select_security_properties(SilcSKE ske,
1195 const char *version,
1196 SilcSKEStartPayload *payload,
1197 SilcSKEStartPayload *remote_payload)
1199 SilcSKEStatus status;
1200 SilcSKEStartPayload *rp;
1204 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1206 rp = remote_payload;
1208 /* Check version string */
1209 if (ske->callbacks->check_version) {
1210 status = ske->callbacks->check_version(ske, rp->version,
1212 ske->callbacks->context);
1213 if (status != SILC_SKE_STATUS_OK) {
1214 ske->status = status;
1219 /* Flags are returned unchanged. */
1220 payload->flags = rp->flags;
1222 /* Take cookie, we must return it to sender unmodified. */
1223 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1224 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1225 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1227 /* Put our version to our reply */
1228 payload->version = strdup(version);
1229 payload->version_len = strlen(version);
1231 /* Get supported Key Exchange groups */
1232 cp = rp->ke_grp_list;
1233 if (cp && strchr(cp, ',')) {
1237 len = strcspn(cp, ",");
1238 item = silc_calloc(len + 1, sizeof(char));
1239 memcpy(item, cp, len);
1241 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1243 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1244 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1246 payload->ke_grp_len = len;
1247 payload->ke_grp_list = item;
1252 if (strlen(cp) == 0)
1261 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1262 SILC_LOG_DEBUG(("Could not find supported KE group"));
1264 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1268 if (!rp->ke_grp_len) {
1269 SILC_LOG_DEBUG(("KE group not defined in payload"));
1271 return SILC_SKE_STATUS_BAD_PAYLOAD;
1274 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1275 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1277 payload->ke_grp_len = rp->ke_grp_len;
1278 payload->ke_grp_list = strdup(rp->ke_grp_list);
1281 /* Get supported PKCS algorithms */
1282 cp = rp->pkcs_alg_list;
1283 if (cp && strchr(cp, ',')) {
1287 len = strcspn(cp, ",");
1288 item = silc_calloc(len + 1, sizeof(char));
1289 memcpy(item, cp, len);
1291 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1293 if (silc_pkcs_is_supported(item) == TRUE) {
1294 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1296 payload->pkcs_alg_len = len;
1297 payload->pkcs_alg_list = item;
1302 if (strlen(cp) == 0)
1311 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1312 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1313 silc_free(payload->ke_grp_list);
1315 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1319 if (!rp->pkcs_alg_len) {
1320 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1321 silc_free(payload->ke_grp_list);
1323 return SILC_SKE_STATUS_BAD_PAYLOAD;
1326 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1327 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1329 payload->pkcs_alg_len = rp->pkcs_alg_len;
1330 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1333 /* Get supported encryption algorithms */
1334 cp = rp->enc_alg_list;
1335 if (cp && strchr(cp, ',')) {
1339 len = strcspn(cp, ",");
1340 item = silc_calloc(len + 1, sizeof(char));
1341 memcpy(item, cp, len);
1343 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1345 if (silc_cipher_is_supported(item) == TRUE) {
1346 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1348 payload->enc_alg_len = len;
1349 payload->enc_alg_list = item;
1354 if (strlen(cp) == 0)
1363 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1364 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1365 silc_free(payload->ke_grp_list);
1366 silc_free(payload->pkcs_alg_list);
1368 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1372 if (!rp->enc_alg_len) {
1373 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1374 silc_free(payload->ke_grp_list);
1375 silc_free(payload->pkcs_alg_list);
1377 return SILC_SKE_STATUS_BAD_PAYLOAD;
1380 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1383 payload->enc_alg_len = rp->enc_alg_len;
1384 payload->enc_alg_list = strdup(rp->enc_alg_list);
1387 /* Get supported hash algorithms */
1388 cp = rp->hash_alg_list;
1389 if (cp && strchr(cp, ',')) {
1393 len = strcspn(cp, ",");
1394 item = silc_calloc(len + 1, sizeof(char));
1395 memcpy(item, cp, len);
1397 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1399 if (silc_hash_is_supported(item) == TRUE) {
1400 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1402 payload->hash_alg_len = len;
1403 payload->hash_alg_list = item;
1408 if (strlen(cp) == 0)
1417 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1418 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1419 silc_free(payload->ke_grp_list);
1420 silc_free(payload->pkcs_alg_list);
1421 silc_free(payload->enc_alg_list);
1423 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1427 if (!rp->hash_alg_len) {
1428 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1429 silc_free(payload->ke_grp_list);
1430 silc_free(payload->pkcs_alg_list);
1431 silc_free(payload->enc_alg_list);
1433 return SILC_SKE_STATUS_BAD_PAYLOAD;
1436 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1437 rp->hash_alg_list));
1439 payload->hash_alg_len = rp->hash_alg_len;
1440 payload->hash_alg_list = strdup(rp->hash_alg_list);
1443 /* Get supported HMACs */
1444 cp = rp->hmac_alg_list;
1445 if (cp && strchr(cp, ',')) {
1449 len = strcspn(cp, ",");
1450 item = silc_calloc(len + 1, sizeof(char));
1451 memcpy(item, cp, len);
1453 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1455 if (silc_hmac_is_supported(item) == TRUE) {
1456 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1458 payload->hmac_alg_len = len;
1459 payload->hmac_alg_list = item;
1464 if (strlen(cp) == 0)
1473 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1474 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1475 silc_free(payload->ke_grp_list);
1476 silc_free(payload->pkcs_alg_list);
1477 silc_free(payload->enc_alg_list);
1478 silc_free(payload->hash_alg_list);
1480 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1484 if (!rp->hmac_alg_len) {
1485 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1486 silc_free(payload->ke_grp_list);
1487 silc_free(payload->pkcs_alg_list);
1488 silc_free(payload->enc_alg_list);
1489 silc_free(payload->hash_alg_list);
1491 return SILC_SKE_STATUS_BAD_PAYLOAD;
1494 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1495 rp->hmac_alg_list));
1497 payload->hmac_alg_len = rp->hmac_alg_len;
1498 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1502 /* Get supported compression algorithms */
1503 cp = rp->hash_alg_list;
1504 if (cp && strchr(cp, ',')) {
1508 len = strcspn(cp, ",");
1509 item = silc_calloc(len + 1, sizeof(char));
1510 memcpy(item, cp, len);
1512 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1514 if (silc_hash_is_supported(item) == TRUE) {
1515 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1517 payload->hash_alg_len = len;
1518 payload->hash_alg_list = item;
1523 if (strlen(cp) == 0)
1532 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1533 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1534 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1535 silc_free(payload->ke_grp_list);
1536 silc_free(payload->pkcs_alg_list);
1537 silc_free(payload->enc_alg_list);
1546 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1547 2 + payload->version_len +
1548 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1549 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1550 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1552 return SILC_SKE_STATUS_OK;
1555 /* Creates random number such that 1 < rnd < n and at most length
1556 of len bits. The rnd sent as argument must be initialized. */
1558 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1562 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1563 unsigned char *string;
1565 SILC_LOG_DEBUG(("Creating random number"));
1567 /* Get the random number as string */
1568 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1570 return SILC_SKE_STATUS_ERROR;
1572 /* Decode the string into a MP integer */
1573 silc_mp_bin2mp(string, (len / 8), rnd);
1574 silc_mp_mod_2exp(rnd, rnd, len);
1577 if (silc_mp_cmp_ui(rnd, 1) < 0)
1578 status = SILC_SKE_STATUS_ERROR;
1580 if (silc_mp_cmp(rnd, n) >= 0)
1581 status = SILC_SKE_STATUS_ERROR;
1583 memset(string, 'F', (len / 8));
1589 /* Creates a hash value HASH as defined in the SKE protocol. If the
1590 `initiator' is TRUE then this function is used to create the HASH_i
1591 hash value defined in the protocol. If it is FALSE then this is used
1592 to create the HASH value defined by the protocol. */
1594 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1595 unsigned char *return_hash,
1596 SilcUInt32 *return_hash_len,
1599 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1601 unsigned char *e, *f, *KEY;
1602 SilcUInt32 e_len, f_len, KEY_len;
1605 SILC_LOG_DEBUG(("Start"));
1607 if (initiator == FALSE) {
1608 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1609 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1610 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1612 /* Format the buffer used to compute the hash value */
1613 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1614 ske->ke2_payload->pk_len +
1615 ske->ke1_payload->pk_len +
1616 e_len + f_len + KEY_len);
1617 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1619 /* Initiator is not required to send its public key */
1620 if (!ske->ke1_payload->pk_data) {
1622 silc_buffer_format(buf,
1623 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1625 ske->start_payload_copy->
1627 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1628 ske->ke2_payload->pk_len),
1629 SILC_STR_UI_XNSTRING(e, e_len),
1630 SILC_STR_UI_XNSTRING(f, f_len),
1631 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1635 silc_buffer_format(buf,
1636 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1638 ske->start_payload_copy->
1640 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1641 ske->ke2_payload->pk_len),
1642 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1643 ske->ke1_payload->pk_len),
1644 SILC_STR_UI_XNSTRING(e, e_len),
1645 SILC_STR_UI_XNSTRING(f, f_len),
1646 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1650 silc_buffer_free(buf);
1651 memset(e, 0, e_len);
1652 memset(f, 0, f_len);
1653 memset(KEY, 0, KEY_len);
1657 return SILC_SKE_STATUS_ERROR;
1660 memset(e, 0, e_len);
1661 memset(f, 0, f_len);
1662 memset(KEY, 0, KEY_len);
1667 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1669 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1670 ske->ke1_payload->pk_len + e_len);
1671 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1673 /* Format the buffer used to compute the hash value */
1675 silc_buffer_format(buf,
1676 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1677 ske->start_payload_copy->len),
1678 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1679 ske->ke1_payload->pk_len),
1680 SILC_STR_UI_XNSTRING(e, e_len),
1683 silc_buffer_free(buf);
1684 memset(e, 0, e_len);
1686 return SILC_SKE_STATUS_ERROR;
1689 memset(e, 0, e_len);
1694 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1695 *return_hash_len = ske->prop->hash->hash->hash_len;
1697 if (initiator == FALSE) {
1698 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1700 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1703 silc_buffer_free(buf);
1708 /* Processes the provided key material `data' as the SILC protocol
1709 specification defines. */
1712 silc_ske_process_key_material_data(unsigned char *data,
1713 SilcUInt32 data_len,
1714 SilcUInt32 req_iv_len,
1715 SilcUInt32 req_enc_key_len,
1716 SilcUInt32 req_hmac_key_len,
1718 SilcSKEKeyMaterial *key)
1721 unsigned char hashd[32];
1722 SilcUInt32 hash_len = req_hmac_key_len;
1723 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1725 SILC_LOG_DEBUG(("Start"));
1727 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1728 return SILC_SKE_STATUS_ERROR;
1730 buf = silc_buffer_alloc(1 + data_len);
1731 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1732 silc_buffer_format(buf,
1733 SILC_STR_UI_CHAR(0),
1734 SILC_STR_UI_XNSTRING(data, data_len),
1738 memset(hashd, 0, sizeof(hashd));
1740 silc_hash_make(hash, buf->data, buf->len, hashd);
1741 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1742 memcpy(key->send_iv, hashd, req_iv_len);
1743 memset(hashd, 0, sizeof(hashd));
1745 silc_hash_make(hash, buf->data, buf->len, hashd);
1746 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1747 memcpy(key->receive_iv, hashd, req_iv_len);
1748 key->iv_len = req_iv_len;
1750 /* Take the encryption keys. If requested key size is more than
1751 the size of hash length we will distribute more key material
1752 as protocol defines. */
1754 if (enc_key_len > hash_len) {
1756 unsigned char k1[32], k2[32], k3[32];
1757 unsigned char *dtmp;
1760 if (enc_key_len > (3 * hash_len))
1761 return SILC_SKE_STATUS_ERROR;
1763 /* Take first round */
1764 memset(k1, 0, sizeof(k1));
1765 silc_hash_make(hash, buf->data, buf->len, k1);
1767 /* Take second round */
1768 dist = silc_buffer_alloc(data_len + hash_len);
1769 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1770 silc_buffer_format(dist,
1771 SILC_STR_UI_XNSTRING(data, data_len),
1772 SILC_STR_UI_XNSTRING(k1, hash_len),
1774 memset(k2, 0, sizeof(k2));
1775 silc_hash_make(hash, dist->data, dist->len, k2);
1777 /* Take third round */
1778 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1779 silc_buffer_pull_tail(dist, hash_len);
1780 silc_buffer_pull(dist, data_len + hash_len);
1781 silc_buffer_format(dist,
1782 SILC_STR_UI_XNSTRING(k2, hash_len),
1784 silc_buffer_push(dist, data_len + hash_len);
1785 memset(k3, 0, sizeof(k3));
1786 silc_hash_make(hash, dist->data, dist->len, k3);
1788 /* Then, save the keys */
1789 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1790 memcpy(dtmp, k1, hash_len);
1791 memcpy(dtmp + hash_len, k2, hash_len);
1792 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1794 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1795 memcpy(key->send_enc_key, dtmp, enc_key_len);
1796 key->enc_key_len = req_enc_key_len;
1798 memset(dtmp, 0, (3 * hash_len));
1799 memset(k1, 0, sizeof(k1));
1800 memset(k2, 0, sizeof(k2));
1801 memset(k3, 0, sizeof(k3));
1803 silc_buffer_free(dist);
1805 /* Take normal hash as key */
1806 memset(hashd, 0, sizeof(hashd));
1807 silc_hash_make(hash, buf->data, buf->len, hashd);
1808 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1809 memcpy(key->send_enc_key, hashd, enc_key_len);
1810 key->enc_key_len = req_enc_key_len;
1814 if (enc_key_len > hash_len) {
1816 unsigned char k1[32], k2[32], k3[32];
1817 unsigned char *dtmp;
1820 if (enc_key_len > (3 * hash_len))
1821 return SILC_SKE_STATUS_ERROR;
1823 /* Take first round */
1824 memset(k1, 0, sizeof(k1));
1825 silc_hash_make(hash, buf->data, buf->len, k1);
1827 /* Take second round */
1828 dist = silc_buffer_alloc(data_len + hash_len);
1829 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1830 silc_buffer_format(dist,
1831 SILC_STR_UI_XNSTRING(data, data_len),
1832 SILC_STR_UI_XNSTRING(k1, hash_len),
1834 memset(k2, 0, sizeof(k2));
1835 silc_hash_make(hash, dist->data, dist->len, k2);
1837 /* Take third round */
1838 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1839 silc_buffer_pull_tail(dist, hash_len);
1840 silc_buffer_pull(dist, data_len + hash_len);
1841 silc_buffer_format(dist,
1842 SILC_STR_UI_XNSTRING(k2, hash_len),
1844 silc_buffer_push(dist, data_len + hash_len);
1845 memset(k3, 0, sizeof(k3));
1846 silc_hash_make(hash, dist->data, dist->len, k3);
1848 /* Then, save the keys */
1849 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1850 memcpy(dtmp, k1, hash_len);
1851 memcpy(dtmp + hash_len, k2, hash_len);
1852 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1854 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1855 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1856 key->enc_key_len = req_enc_key_len;
1858 memset(dtmp, 0, (3 * hash_len));
1859 memset(k1, 0, sizeof(k1));
1860 memset(k2, 0, sizeof(k2));
1861 memset(k3, 0, sizeof(k3));
1863 silc_buffer_free(dist);
1865 /* Take normal hash as key */
1866 memset(hashd, 0, sizeof(hashd));
1867 silc_hash_make(hash, buf->data, buf->len, hashd);
1868 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1869 memcpy(key->receive_enc_key, hashd, enc_key_len);
1870 key->enc_key_len = req_enc_key_len;
1873 /* Take HMAC keys */
1874 memset(hashd, 0, sizeof(hashd));
1876 silc_hash_make(hash, buf->data, buf->len, hashd);
1877 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1878 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1879 memset(hashd, 0, sizeof(hashd));
1881 silc_hash_make(hash, buf->data, buf->len, hashd);
1882 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1883 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1884 key->hmac_key_len = req_hmac_key_len;
1885 memset(hashd, 0, sizeof(hashd));
1887 silc_buffer_free(buf);
1889 return SILC_SKE_STATUS_OK;
1892 /* Processes negotiated key material as protocol specifies. This returns
1893 the actual keys to be used in the SILC. */
1895 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1896 SilcUInt32 req_iv_len,
1897 SilcUInt32 req_enc_key_len,
1898 SilcUInt32 req_hmac_key_len,
1899 SilcSKEKeyMaterial *key)
1901 SilcSKEStatus status;
1903 unsigned char *tmpbuf;
1906 /* Encode KEY to binary data */
1907 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1909 buf = silc_buffer_alloc(klen + ske->hash_len);
1910 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1911 silc_buffer_format(buf,
1912 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1913 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1916 /* Process the key material */
1917 status = silc_ske_process_key_material_data(buf->data, buf->len,
1918 req_iv_len, req_enc_key_len,
1920 ske->prop->hash, key);
1922 memset(tmpbuf, 0, klen);
1924 silc_buffer_free(buf);
1929 /* Free key material structure */
1931 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1937 silc_free(key->send_iv);
1938 if (key->receive_iv)
1939 silc_free(key->receive_iv);
1940 if (key->send_enc_key) {
1941 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1942 silc_free(key->send_enc_key);
1944 if (key->receive_enc_key) {
1945 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1946 silc_free(key->receive_enc_key);
1948 if (key->send_hmac_key) {
1949 memset(key->send_hmac_key, 0, key->hmac_key_len);
1950 silc_free(key->send_hmac_key);
1952 if (key->receive_hmac_key) {
1953 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1954 silc_free(key->receive_hmac_key);
1959 const char *silc_ske_status_string[] =
1963 "Unkown error occurred",
1964 "Bad payload in packet",
1965 "Unsupported group",
1966 "Unsupported cipher",
1968 "Unsupported hash function",
1970 "Unsupported public key (or certificate)",
1971 "Incorrect signature",
1972 "Bad or unsupported version",
1977 "Remote did not provide public key",
1978 "Key exchange protocol is not active",
1979 "Bad reserved field in packet",
1980 "Bad payload length in packet",
1986 /* Maps status to readable string and returns the string. If string is not
1987 found and empty character string ("") is returned. */
1989 const char *silc_ske_map_status(SilcSKEStatus status)
1993 for (i = 0; silc_ske_status_string[i]; i++)
1995 return silc_ske_status_string[i];
2000 /* Parses remote host's version string. */
2002 bool silc_ske_parse_version(SilcSKE ske,
2003 SilcUInt32 *protocol_version,
2004 char **protocol_version_string,
2005 SilcUInt32 *software_version,
2006 char **software_version_string,
2007 char **vendor_version)
2009 return silc_parse_version_string(ske->start_payload->version,
2011 protocol_version_string,
2013 software_version_string,