5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2000 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
23 #include "payload_internal.h"
24 #include "groups_internal.h"
26 /* Allocates new SKE object. */
28 SilcSKE silc_ske_alloc()
32 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
34 ske = silc_calloc(1, sizeof(*ske));
35 ske->status = SILC_SKE_STATUS_OK;
41 /* Free's SKE object. */
43 void silc_ske_free(SilcSKE ske)
47 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
48 ske->status = SILC_SKE_STATUS_FREED;
52 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
55 /* Free start payload */
56 if (ske->start_payload)
57 silc_ske_payload_start_free(ske->start_payload);
61 silc_ske_payload_ke_free(ske->ke1_payload);
66 silc_free(ske->prop->group);
68 silc_pkcs_free(ske->prop->pkcs);
69 if (ske->prop->cipher)
70 silc_cipher_free(ske->prop->cipher);
72 silc_hash_free(ske->prop->hash);
74 silc_hmac_free(ske->prop->hmac);
77 if (ske->start_payload_copy)
78 silc_buffer_free(ske->start_payload_copy);
82 silc_mp_uninit(ske->x);
86 silc_mp_uninit(ske->KEY);
95 /* Starts the SILC Key Exchange protocol for initiator. The connection
96 to the remote end must be established before calling this function
97 and the connecting socket must be sent as argument. This function
98 creates the Key Exchange Start Paload which includes all our
99 configured security properties. This payload is then sent to the
100 remote end for further processing. This payload must be sent as
101 argument to the function, however, it must not be encoded
102 already, it is done by this function.
104 The packet sending is done by calling a callback function. Caller
105 must provide a routine to send the packet. */
107 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
108 SilcSocketConnection sock,
109 SilcSKEStartPayload *start_payload,
110 SilcSKESendPacketCb send_packet,
113 SilcSKEStatus status = SILC_SKE_STATUS_OK;
114 SilcBuffer payload_buf;
116 SILC_LOG_DEBUG(("Start"));
121 /* Encode the payload */
122 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
123 if (status != SILC_SKE_STATUS_OK)
126 /* Take a copy of the payload buffer for future use. It is used to
127 compute the HASH value. */
128 ske->start_payload_copy = silc_buffer_copy(payload_buf);
130 /* Send the packet. */
132 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, context);
134 silc_buffer_free(payload_buf);
139 /* Function called after ske_initiator_start fuction. This receives
140 the remote ends Key Exchange Start payload which includes the
141 security properties selected by the responder from our payload
142 sent in the silc_ske_initiator_start function. */
144 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
145 SilcBuffer start_payload,
149 SilcSKEStatus status = SILC_SKE_STATUS_OK;
150 SilcSKEStartPayload *payload;
151 SilcSKESecurityProperties prop;
152 SilcSKEDiffieHellmanGroup group;
154 SILC_LOG_DEBUG(("Start"));
156 /* Decode the payload */
157 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
158 if (status != SILC_SKE_STATUS_OK) {
159 ske->status = status;
163 /* Take the selected security properties into use while doing
164 the key exchange. This is used only while doing the key
165 exchange. The same data is returned to upper levels by calling
166 the callback function. */
167 ske->prop = prop = silc_calloc(1, sizeof(*prop));
168 prop->flags = payload->flags;
169 status = silc_ske_get_group_by_name(payload->ke_grp_list, &group);
170 if (status != SILC_SKE_STATUS_OK)
175 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
176 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
180 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
181 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
185 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
186 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
190 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
191 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
195 ske->start_payload = payload;
197 /* Return the received payload by calling the callback function. */
199 (*callback)(ske, context);
205 silc_ske_payload_start_free(payload);
210 silc_pkcs_free(prop->pkcs);
212 silc_cipher_free(prop->cipher);
214 silc_hash_free(prop->hash);
216 silc_hmac_free(prop->hmac);
220 if (status == SILC_SKE_STATUS_OK)
221 return SILC_SKE_STATUS_ERROR;
223 ske->status = status;
227 /* This function creates random number x, such that 1 < x < q and
228 computes e = g ^ x mod p and sends the result to the remote end in
229 Key Exchange Payload. */
231 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
232 SilcPublicKey public_key,
233 SilcPrivateKey private_key,
234 SilcSKESendPacketCb send_packet,
237 SilcSKEStatus status = SILC_SKE_STATUS_OK;
238 SilcBuffer payload_buf;
240 SilcSKEKEPayload *payload;
243 SILC_LOG_DEBUG(("Start"));
245 /* Create the random number x, 1 < x < q. */
246 x = silc_calloc(1, sizeof(*x));
249 silc_ske_create_rnd(ske, ske->prop->group->group_order,
250 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
252 if (status != SILC_SKE_STATUS_OK) {
255 ske->status = status;
259 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
261 /* Do the Diffie Hellman computation, e = g ^ x mod p */
263 silc_mp_pow_mod(&e, &ske->prop->group->generator, x,
264 &ske->prop->group->group);
266 /* Encode the result to Key Exchange Payload. */
268 payload = silc_calloc(1, sizeof(*payload));
269 ske->ke1_payload = payload;
275 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
276 if (!payload->pk_data) {
281 ske->status = SILC_SKE_STATUS_OK;
284 payload->pk_len = pk_len;
286 payload->pk_type = SILC_SKE_PK_TYPE_SILC;
288 /* Compute signature data if we are doing mutual authentication */
289 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
290 unsigned char hash[32], sign[1024];
291 uint32 hash_len, sign_len;
293 SILC_LOG_DEBUG(("We are doing mutual authentication"));
294 SILC_LOG_DEBUG(("Computing HASH_i value"));
296 /* Compute the hash value */
297 memset(hash, 0, sizeof(hash));
298 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
300 SILC_LOG_DEBUG(("Signing HASH_i value"));
302 /* Sign the hash value */
303 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
304 private_key->prv_len);
305 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
306 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
307 memcpy(payload->sign_data, sign, sign_len);
308 memset(sign, 0, sizeof(sign));
309 payload->sign_len = sign_len;
312 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
313 if (status != SILC_SKE_STATUS_OK) {
317 silc_free(payload->pk_data);
319 ske->status = status;
325 /* Send the packet. */
327 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE_1, context);
329 silc_buffer_free(payload_buf);
334 /* An initiator finish final callback that is called to indicate that
335 the SKE protocol may continue. */
340 } *SKEInitiatorFinish;
342 static void silc_ske_initiator_finish_final(SilcSKE ske,
343 SilcSKEStatus status,
346 SKEInitiatorFinish finish = (SKEInitiatorFinish)context;
347 SilcSKEKEPayload *payload;
348 unsigned char hash[32];
350 SilcPublicKey public_key = NULL;
352 /* If the SKE was freed during the async call then free it really now,
353 otherwise just decrement the reference counter. */
354 if (ske->status == SILC_SKE_STATUS_FREED) {
361 payload = ske->ke2_payload;
363 /* If the caller returns PENDING status SKE library will assume that
364 the caller will re-call this callback when it is not anymore in
366 if (status == SILC_SKE_STATUS_PENDING)
369 /* If the status is an error then the public key that was verified
370 by the caller is not authentic. */
371 if (status != SILC_SKE_STATUS_OK) {
372 ske->status = status;
373 if (finish->callback)
374 finish->callback(ske, finish->context);
379 if (payload->pk_data) {
380 /* Decode the public key */
381 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
383 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
384 if (finish->callback)
385 finish->callback(ske, finish->context);
390 SILC_LOG_DEBUG(("Public key is authentic"));
392 /* Compute the hash value */
393 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
394 if (status != SILC_SKE_STATUS_OK)
397 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
398 memcpy(ske->hash, hash, hash_len);
399 ske->hash_len = hash_len;
401 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
403 /* Verify signature */
404 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
405 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
406 payload->sign_len, hash, hash_len) == FALSE) {
408 SILC_LOG_DEBUG(("Signature don't match"));
410 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
414 SILC_LOG_DEBUG(("Signature is Ok"));
416 silc_pkcs_public_key_free(public_key);
417 memset(hash, 'F', hash_len);
420 ske->status = SILC_SKE_STATUS_OK;
422 /* Call the callback. The caller may now continue the SKE protocol. */
423 if (finish->callback)
424 finish->callback(ske, finish->context);
430 memset(hash, 'F', sizeof(hash));
431 silc_ske_payload_ke_free(payload);
432 ske->ke2_payload = NULL;
434 silc_mp_uninit(ske->KEY);
439 silc_pkcs_public_key_free(public_key);
442 memset(ske->hash, 'F', hash_len);
443 silc_free(ske->hash);
447 if (status == SILC_SKE_STATUS_OK)
448 ske->status = SILC_SKE_STATUS_ERROR;
450 ske->status = status;
452 /* Call the callback. */
453 if (finish->callback)
454 finish->callback(ske, finish->context);
458 /* Receives Key Exchange Payload from responder consisting responders
459 public key, f, and signature. This function verifies the public key,
460 computes the secret shared key and verifies the signature.
462 The `callback' will be called to indicate that the caller may
463 continue with the SKE protocol. The caller must not continue
464 before the SKE libary has called that callback. If this function
465 returns an error the callback will not be called. It is called
466 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
467 However, note that when the library calls the callback the ske->status
470 This calls the `verify_key' callback to verify the received public
471 key or certificate. If the `verify_key' is provided then the remote
472 must send public key and it is considered to be an error if remote
473 does not send its public key. If caller is performing a re-key with
474 SKE then the `verify_key' is usually not provided when it is not also
475 required for the remote to send its public key. */
477 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
478 SilcBuffer ke_payload,
479 SilcSKEVerifyCb verify_key,
480 void *verify_context,
484 SilcSKEStatus status = SILC_SKE_STATUS_OK;
485 SilcSKEKEPayload *payload;
487 SKEInitiatorFinish finish;
489 SILC_LOG_DEBUG(("Start"));
491 /* Decode the payload */
492 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
493 if (status != SILC_SKE_STATUS_OK) {
494 ske->status = status;
497 ske->ke2_payload = payload;
499 if (!payload->pk_data && verify_key) {
500 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
501 "even though we require it"));
502 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
506 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
508 /* Compute the shared secret key */
509 KEY = silc_calloc(1, sizeof(*KEY));
511 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
514 finish = silc_calloc(1, sizeof(*finish));
515 finish->callback = callback;
516 finish->context = context;
518 if (payload->pk_data && verify_key) {
519 SILC_LOG_DEBUG(("Verifying public key"));
522 (*verify_key)(ske, payload->pk_data, payload->pk_len,
523 payload->pk_type, verify_context,
524 silc_ske_initiator_finish_final, finish);
526 /* We will continue to the final state after the public key has
527 been verified by the caller. */
528 return SILC_SKE_STATUS_PENDING;
531 /* Continue to final state */
532 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, finish);
534 return SILC_SKE_STATUS_OK;
537 silc_ske_payload_ke_free(payload);
538 ske->ke2_payload = NULL;
540 silc_mp_uninit(ske->KEY);
544 if (status == SILC_SKE_STATUS_OK)
545 return SILC_SKE_STATUS_ERROR;
547 ske->status = status;
551 /* Starts Key Exchange protocol for responder. Responder receives
552 Key Exchange Start Payload from initiator consisting of all the
553 security properties the initiator supports. This function decodes
554 the payload and parses the payload further and selects the right
555 security properties. */
557 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
558 SilcSocketConnection sock,
560 SilcBuffer start_payload,
565 SilcSKEStatus status = SILC_SKE_STATUS_OK;
566 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
568 SILC_LOG_DEBUG(("Start"));
573 /* Decode the payload */
574 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
575 if (status != SILC_SKE_STATUS_OK) {
576 ske->status = status;
580 /* Take a copy of the payload buffer for future use. It is used to
581 compute the HASH value. */
582 ske->start_payload_copy = silc_buffer_copy(start_payload);
584 /* Force the mutual authentication flag if we want to do it. */
586 SILC_LOG_DEBUG(("Force mutual authentication"));
587 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
590 /* Parse and select the security properties from the payload */
591 payload = silc_calloc(1, sizeof(*payload));
592 status = silc_ske_select_security_properties(ske, version,
593 payload, remote_payload);
594 if (status != SILC_SKE_STATUS_OK)
597 ske->start_payload = payload;
599 /* Call the callback function. */
601 (*callback)(ske, context);
607 silc_ske_payload_start_free(remote_payload);
611 if (status == SILC_SKE_STATUS_OK)
612 return SILC_SKE_STATUS_ERROR;
614 ske->status = status;
618 /* The selected security properties from the initiator payload is now
619 encoded into Key Exchange Start Payload and sent to the initiator. */
621 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
622 SilcSKEStartPayload *start_payload,
623 SilcSKESendPacketCb send_packet,
626 SilcSKEStatus status = SILC_SKE_STATUS_OK;
627 SilcBuffer payload_buf;
628 SilcSKESecurityProperties prop;
629 SilcSKEDiffieHellmanGroup group = NULL;
631 SILC_LOG_DEBUG(("Start"));
633 /* Allocate security properties from the payload. These are allocated
634 only for this negotiation and will be free'd after KE is over. */
635 ske->prop = prop = silc_calloc(1, sizeof(*prop));
636 prop->flags = start_payload->flags;
637 status = silc_ske_get_group_by_name(start_payload->ke_grp_list, &group);
638 if (status != SILC_SKE_STATUS_OK)
643 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
644 &prop->pkcs) == FALSE) {
645 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
649 if (silc_cipher_alloc(start_payload->enc_alg_list,
650 &prop->cipher) == FALSE) {
651 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
655 if (silc_hash_alloc(start_payload->hash_alg_list,
656 &prop->hash) == FALSE) {
657 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
661 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
662 &prop->hmac) == FALSE) {
663 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
667 /* Encode the payload */
668 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
669 if (status != SILC_SKE_STATUS_OK)
672 /* Send the packet. */
674 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, context);
676 silc_buffer_free(payload_buf);
685 silc_pkcs_free(prop->pkcs);
687 silc_cipher_free(prop->cipher);
689 silc_hash_free(prop->hash);
691 silc_hmac_free(prop->hmac);
695 if (status == SILC_SKE_STATUS_OK)
696 return SILC_SKE_STATUS_ERROR;
698 ske->status = status;
702 /* An responder phase 2 final callback that is called to indicate that
703 the SKE protocol may continue. */
708 } *SKEResponderPhaseII;
710 static void silc_ske_responder_phase2_final(SilcSKE ske,
711 SilcSKEStatus status,
714 SKEResponderPhaseII finish = (SKEResponderPhaseII)context;
715 SilcSKEKEPayload *recv_payload, *send_payload;
718 /* If the SKE was freed during the async call then free it really now,
719 otherwise just decrement the reference counter. */
720 if (ske->status == SILC_SKE_STATUS_FREED) {
727 recv_payload = ske->ke1_payload;
729 /* If the caller returns PENDING status SKE library will assume that
730 the caller will re-call this callback when it is not anymore in
732 if (status == SILC_SKE_STATUS_PENDING)
735 /* If the status is an error then the public key that was verified
736 by the caller is not authentic. */
737 if (status != SILC_SKE_STATUS_OK) {
738 ske->status = status;
739 if (finish->callback)
740 finish->callback(ske, finish->context);
745 /* The public key verification was performed only if the Mutual
746 Authentication flag is set. */
747 if (ske->start_payload &&
748 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
749 SilcPublicKey public_key = NULL;
750 unsigned char hash[32];
753 /* Decode the public key */
754 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
755 recv_payload->pk_len,
757 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
758 if (finish->callback)
759 finish->callback(ske, finish->context);
764 SILC_LOG_DEBUG(("Public key is authentic"));
766 /* Compute the hash value */
767 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
768 if (status != SILC_SKE_STATUS_OK) {
769 ske->status = status;
770 if (finish->callback)
771 finish->callback(ske, finish->context);
776 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
778 /* Verify signature */
779 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
780 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
781 recv_payload->sign_len, hash, hash_len) == FALSE) {
783 SILC_LOG_DEBUG(("Signature don't match"));
785 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
786 if (finish->callback)
787 finish->callback(ske, finish->context);
792 SILC_LOG_DEBUG(("Signature is Ok"));
794 silc_pkcs_public_key_free(public_key);
795 memset(hash, 'F', hash_len);
798 /* Create the random number x, 1 < x < q. */
799 x = silc_calloc(1, sizeof(*x));
802 silc_ske_create_rnd(ske, ske->prop->group->group_order,
803 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
805 if (status != SILC_SKE_STATUS_OK) {
808 ske->status = status;
809 if (finish->callback)
810 finish->callback(ske, finish->context);
815 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
817 /* Do the Diffie Hellman computation, f = g ^ x mod p */
819 silc_mp_pow_mod(&f, &ske->prop->group->generator, x,
820 &ske->prop->group->group);
822 /* Save the results for later processing */
823 send_payload = silc_calloc(1, sizeof(*send_payload));
826 ske->ke2_payload = send_payload;
828 /* Call the callback. The caller may now continue with the SKE protocol. */
829 ske->status = SILC_SKE_STATUS_OK;
830 if (finish->callback)
831 finish->callback(ske, finish->context);
835 /* This function receives the Key Exchange Payload from the initiator.
836 This also performs the mutual authentication if required. Then, this
837 function first generated a random number x, such that 1 < x < q
838 and computes f = g ^ x mod p. This then puts the result f to a Key
841 The `callback' will be called to indicate that the caller may
842 continue with the SKE protocol. The caller must not continue
843 before the SKE libary has called that callback. If this function
844 returns an error the callback will not be called. It is called
845 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
846 However, note that when the library calls the callback the ske->status
849 This calls the `verify_key' callback to verify the received public
850 key or certificate if the Mutual Authentication flag is set. If the
851 `verify_key' is provided then the remote must send public key and it
852 is considered to be an error if remote does not send its public key. */
854 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
855 SilcBuffer ke_payload,
856 SilcSKEVerifyCb verify_key,
857 void *verify_context,
861 SilcSKEStatus status = SILC_SKE_STATUS_OK;
862 SilcSKEKEPayload *recv_payload;
863 SKEResponderPhaseII finish;
865 SILC_LOG_DEBUG(("Start"));
867 /* Decode Key Exchange Payload */
868 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
869 if (status != SILC_SKE_STATUS_OK) {
870 ske->status = status;
874 ske->ke1_payload = recv_payload;
876 finish = silc_calloc(1, sizeof(*finish));
877 finish->callback = callback;
878 finish->context = context;
880 /* Verify the received public key and verify the signature if we are
881 doing mutual authentication. */
882 if (ske->start_payload &&
883 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
885 SILC_LOG_DEBUG(("We are doing mutual authentication"));
887 if (!recv_payload->pk_data && verify_key) {
888 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
889 "certificate), even though we require it"));
890 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
894 if (recv_payload->pk_data && verify_key) {
895 SILC_LOG_DEBUG(("Verifying public key"));
898 (*verify_key)(ske, recv_payload->pk_data, recv_payload->pk_len,
899 recv_payload->pk_type, verify_context,
900 silc_ske_responder_phase2_final, finish);
902 /* We will continue to the final state after the public key has
903 been verified by the caller. */
904 return SILC_SKE_STATUS_PENDING;
908 /* Continue to final state */
909 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, finish);
911 return SILC_SKE_STATUS_OK;
914 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
915 value to be signed and sent to the other end. This then encodes Key
916 Exchange Payload and sends it to the other end. */
918 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
919 SilcPublicKey public_key,
920 SilcPrivateKey private_key,
921 SilcSKEPKType pk_type,
922 SilcSKESendPacketCb send_packet,
925 SilcSKEStatus status = SILC_SKE_STATUS_OK;
926 SilcBuffer payload_buf;
928 unsigned char hash[32], sign[1024], *pk;
929 uint32 hash_len, sign_len, pk_len;
931 SILC_LOG_DEBUG(("Start"));
933 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
935 /* Compute the shared secret key */
936 KEY = silc_calloc(1, sizeof(*KEY));
938 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
939 &ske->prop->group->group);
942 if (public_key && private_key) {
943 SILC_LOG_DEBUG(("Getting public key"));
945 /* Get the public key */
946 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
948 status = SILC_SKE_STATUS_ERROR;
951 ske->ke2_payload->pk_data = pk;
952 ske->ke2_payload->pk_len = pk_len;
954 SILC_LOG_DEBUG(("Computing HASH value"));
956 /* Compute the hash value */
957 memset(hash, 0, sizeof(hash));
958 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
959 if (status != SILC_SKE_STATUS_OK)
962 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
963 memcpy(ske->hash, hash, hash_len);
964 ske->hash_len = hash_len;
966 SILC_LOG_DEBUG(("Signing HASH value"));
968 /* Sign the hash value */
969 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
970 private_key->prv_len);
971 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
972 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
973 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
974 memset(sign, 0, sizeof(sign));
975 ske->ke2_payload->sign_len = sign_len;
977 ske->ke2_payload->pk_type = pk_type;
979 /* Encode the Key Exchange Payload */
980 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
982 if (status != SILC_SKE_STATUS_OK)
985 /* Send the packet. */
987 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE_2, context);
989 silc_buffer_free(payload_buf);
994 silc_mp_uninit(ske->KEY);
997 silc_ske_payload_ke_free(ske->ke2_payload);
999 if (status == SILC_SKE_STATUS_OK)
1000 return SILC_SKE_STATUS_ERROR;
1002 ske->status = status;
1006 /* The Key Exchange protocol is ended by calling this function. This
1007 must not be called until the keys are processed like the protocol
1008 defines. This function is for both initiator and responder. */
1010 SilcSKEStatus silc_ske_end(SilcSKE ske,
1011 SilcSKESendPacketCb send_packet,
1016 SILC_LOG_DEBUG(("Start"));
1018 packet = silc_buffer_alloc(4);
1019 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1020 silc_buffer_format(packet,
1021 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
1025 (*send_packet)(ske, packet, SILC_PACKET_SUCCESS, context);
1027 silc_buffer_free(packet);
1029 return SILC_SKE_STATUS_OK;
1032 /* Aborts the Key Exchange protocol. This is called if error occurs
1033 while performing the protocol. The status argument is the error
1034 status and it is sent to the remote end. */
1036 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status,
1037 SilcSKESendPacketCb send_packet,
1042 SILC_LOG_DEBUG(("Start"));
1044 packet = silc_buffer_alloc(4);
1045 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1046 silc_buffer_format(packet,
1047 SILC_STR_UI_INT((uint32)status),
1051 (*send_packet)(ske, packet, SILC_PACKET_FAILURE, context);
1053 silc_buffer_free(packet);
1055 return SILC_SKE_STATUS_OK;
1058 /* Assembles security properties to Key Exchange Start Payload to be
1059 sent to the remote end. This checks system wide (SILC system, that is)
1060 settings and chooses from those. However, if other properties
1061 should be used this function is easy to replace by another function,
1062 as, this function is called by the caller of the protocol and not
1063 by the protocol itself. */
1066 silc_ske_assemble_security_properties(SilcSKE ske,
1067 unsigned char flags,
1069 SilcSKEStartPayload **return_payload)
1071 SilcSKEStartPayload *rp;
1074 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1076 rp = silc_calloc(1, sizeof(*rp));
1081 /* Set random cookie */
1082 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1083 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1084 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1085 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1088 rp->version = strdup(version);
1089 rp->version_len = strlen(version);
1091 /* Get supported Key Exhange groups */
1092 rp->ke_grp_list = silc_ske_get_supported_groups();
1093 rp->ke_grp_len = strlen(rp->ke_grp_list);
1095 /* Get supported PKCS algorithms */
1096 rp->pkcs_alg_list = silc_pkcs_get_supported();
1097 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1099 /* Get supported encryption algorithms */
1100 rp->enc_alg_list = silc_cipher_get_supported();
1101 rp->enc_alg_len = strlen(rp->enc_alg_list);
1103 /* Get supported hash algorithms */
1104 rp->hash_alg_list = silc_hash_get_supported();
1105 rp->hash_alg_len = strlen(rp->hash_alg_list);
1107 /* Get supported HMACs */
1108 rp->hmac_alg_list = silc_hmac_get_supported();
1109 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1112 /* Get supported compression algorithms */
1113 rp->comp_alg_list = "";
1114 rp->comp_alg_len = 0;
1116 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1117 2 + rp->version_len +
1118 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1119 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1120 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1122 *return_payload = rp;
1124 return SILC_SKE_STATUS_OK;
1127 /* Selects the supported security properties from the remote end's Key
1128 Exchange Start Payload. */
1131 silc_ske_select_security_properties(SilcSKE ske,
1133 SilcSKEStartPayload *payload,
1134 SilcSKEStartPayload *remote_payload)
1136 SilcSKEStatus status;
1137 SilcSKEStartPayload *rp;
1141 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1143 rp = remote_payload;
1145 /* Check version string */
1146 status = silc_ske_check_version(ske, rp->version, rp->version_len);
1147 if (status != SILC_SKE_STATUS_OK) {
1148 ske->status = status;
1152 /* Flags are returned unchanged. */
1153 payload->flags = rp->flags;
1156 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1157 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1158 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1160 /* Put our version to our reply */
1161 payload->version = strdup(version);
1162 payload->version_len = strlen(version);
1164 /* Get supported Key Exchange groups */
1165 cp = rp->ke_grp_list;
1166 if (cp && strchr(cp, ',')) {
1170 len = strcspn(cp, ",");
1171 item = silc_calloc(len + 1, sizeof(char));
1172 memcpy(item, cp, len);
1174 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1176 if (silc_ske_get_group_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1177 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1179 payload->ke_grp_len = len;
1180 payload->ke_grp_list = item;
1185 if (strlen(cp) == 0)
1194 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1195 SILC_LOG_DEBUG(("Could not find supported KE group"));
1197 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1201 if (!rp->ke_grp_len) {
1202 SILC_LOG_DEBUG(("KE group not defined in payload"));
1204 return SILC_SKE_STATUS_BAD_PAYLOAD;
1207 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1208 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1210 payload->ke_grp_len = rp->ke_grp_len;
1211 payload->ke_grp_list = strdup(rp->ke_grp_list);
1214 /* Get supported PKCS algorithms */
1215 cp = rp->pkcs_alg_list;
1216 if (cp && strchr(cp, ',')) {
1220 len = strcspn(cp, ",");
1221 item = silc_calloc(len + 1, sizeof(char));
1222 memcpy(item, cp, len);
1224 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1226 if (silc_pkcs_is_supported(item) == TRUE) {
1227 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1229 payload->pkcs_alg_len = len;
1230 payload->pkcs_alg_list = item;
1235 if (strlen(cp) == 0)
1244 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1245 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1246 silc_free(payload->ke_grp_list);
1248 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1252 if (!rp->pkcs_alg_len) {
1253 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1254 silc_free(payload->ke_grp_list);
1256 return SILC_SKE_STATUS_BAD_PAYLOAD;
1259 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1260 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1262 payload->pkcs_alg_len = rp->pkcs_alg_len;
1263 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1266 /* Get supported encryption algorithms */
1267 cp = rp->enc_alg_list;
1268 if (cp && strchr(cp, ',')) {
1272 len = strcspn(cp, ",");
1273 item = silc_calloc(len + 1, sizeof(char));
1274 memcpy(item, cp, len);
1276 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1278 if (silc_cipher_is_supported(item) == TRUE) {
1279 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1281 payload->enc_alg_len = len;
1282 payload->enc_alg_list = item;
1287 if (strlen(cp) == 0)
1296 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1297 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1298 silc_free(payload->ke_grp_list);
1299 silc_free(payload->pkcs_alg_list);
1301 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1305 if (!rp->enc_alg_len) {
1306 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1307 silc_free(payload->ke_grp_list);
1308 silc_free(payload->pkcs_alg_list);
1310 return SILC_SKE_STATUS_BAD_PAYLOAD;
1313 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1316 payload->enc_alg_len = rp->enc_alg_len;
1317 payload->enc_alg_list = strdup(rp->enc_alg_list);
1320 /* Get supported hash algorithms */
1321 cp = rp->hash_alg_list;
1322 if (cp && strchr(cp, ',')) {
1326 len = strcspn(cp, ",");
1327 item = silc_calloc(len + 1, sizeof(char));
1328 memcpy(item, cp, len);
1330 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1332 if (silc_hash_is_supported(item) == TRUE) {
1333 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1335 payload->hash_alg_len = len;
1336 payload->hash_alg_list = item;
1341 if (strlen(cp) == 0)
1350 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1351 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1352 silc_free(payload->ke_grp_list);
1353 silc_free(payload->pkcs_alg_list);
1354 silc_free(payload->enc_alg_list);
1356 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1360 if (!rp->hash_alg_len) {
1361 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1362 silc_free(payload->ke_grp_list);
1363 silc_free(payload->pkcs_alg_list);
1364 silc_free(payload->enc_alg_list);
1366 return SILC_SKE_STATUS_BAD_PAYLOAD;
1369 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1370 rp->hash_alg_list));
1372 payload->hash_alg_len = rp->hash_alg_len;
1373 payload->hash_alg_list = strdup(rp->hash_alg_list);
1376 /* Get supported HMACs */
1377 cp = rp->hmac_alg_list;
1378 if (cp && strchr(cp, ',')) {
1382 len = strcspn(cp, ",");
1383 item = silc_calloc(len + 1, sizeof(char));
1384 memcpy(item, cp, len);
1386 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1388 if (silc_hmac_is_supported(item) == TRUE) {
1389 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1391 payload->hmac_alg_len = len;
1392 payload->hmac_alg_list = item;
1397 if (strlen(cp) == 0)
1406 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1407 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1408 silc_free(payload->ke_grp_list);
1409 silc_free(payload->pkcs_alg_list);
1410 silc_free(payload->enc_alg_list);
1411 silc_free(payload->hash_alg_list);
1413 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1417 if (!rp->hmac_alg_len) {
1418 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1419 silc_free(payload->ke_grp_list);
1420 silc_free(payload->pkcs_alg_list);
1421 silc_free(payload->enc_alg_list);
1422 silc_free(payload->hash_alg_list);
1424 return SILC_SKE_STATUS_BAD_PAYLOAD;
1427 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1428 rp->hmac_alg_list));
1430 payload->hmac_alg_len = rp->hmac_alg_len;
1431 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1435 /* Get supported compression algorithms */
1436 cp = rp->hash_alg_list;
1437 if (cp && strchr(cp, ',')) {
1441 len = strcspn(cp, ",");
1442 item = silc_calloc(len + 1, sizeof(char));
1443 memcpy(item, cp, len);
1445 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1447 if (silc_hash_is_supported(item) == TRUE) {
1448 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1450 payload->hash_alg_len = len;
1451 payload->hash_alg_list = item;
1456 if (strlen(cp) == 0)
1465 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1466 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1467 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1468 silc_free(payload->ke_grp_list);
1469 silc_free(payload->pkcs_alg_list);
1470 silc_free(payload->enc_alg_list);
1479 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1480 2 + payload->version_len +
1481 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1482 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1483 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1485 return SILC_SKE_STATUS_OK;
1488 /* Creates random number such that 1 < rnd < n and at most length
1489 of len bits. The rnd sent as argument must be initialized. */
1491 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt n,
1495 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1496 unsigned char *string;
1498 SILC_LOG_DEBUG(("Creating random number"));
1500 /* Get the random number as string */
1501 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1503 return SILC_SKE_STATUS_ERROR;
1505 /* Decode the string into a MP integer */
1506 silc_mp_bin2mp(string, (len / 8), rnd);
1507 silc_mp_mod_2exp(rnd, rnd, len);
1510 if (silc_mp_cmp_ui(rnd, 1) < 0)
1511 status = SILC_SKE_STATUS_ERROR;
1513 if (silc_mp_cmp(rnd, &n) >= 0)
1514 status = SILC_SKE_STATUS_ERROR;
1516 memset(string, 'F', (len / 8));
1522 /* Creates a hash value HASH as defined in the SKE protocol. If the
1523 `initiator' is TRUE then this function is used to create the HASH_i
1524 hash value defined in the protocol. If it is FALSE then this is used
1525 to create the HASH value defined by the protocol. */
1527 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1528 unsigned char *return_hash,
1529 uint32 *return_hash_len,
1532 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1534 unsigned char *e, *f, *KEY;
1535 uint32 e_len, f_len, KEY_len;
1538 SILC_LOG_DEBUG(("Start"));
1540 if (initiator == FALSE) {
1541 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1542 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1543 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1545 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1546 ske->pk_len + e_len + f_len + KEY_len);
1547 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1549 /* Format the buffer used to compute the hash value */
1551 silc_buffer_format(buf,
1552 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1553 ske->start_payload_copy->len),
1554 SILC_STR_UI_XNSTRING(ske->pk, ske->pk_len),
1555 SILC_STR_UI_XNSTRING(e, e_len),
1556 SILC_STR_UI_XNSTRING(f, f_len),
1557 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1560 silc_buffer_free(buf);
1561 memset(e, 0, e_len);
1562 memset(f, 0, f_len);
1563 memset(KEY, 0, KEY_len);
1567 return SILC_SKE_STATUS_ERROR;
1570 memset(e, 0, e_len);
1571 memset(f, 0, f_len);
1572 memset(KEY, 0, KEY_len);
1577 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1579 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1580 ske->pk_len + e_len);
1581 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1583 /* Format the buffer used to compute the hash value */
1585 silc_buffer_format(buf,
1586 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1587 ske->start_payload_copy->len),
1588 SILC_STR_UI_XNSTRING(ske->pk, ske->pk_len),
1589 SILC_STR_UI_XNSTRING(e, e_len),
1592 silc_buffer_free(buf);
1593 memset(e, 0, e_len);
1595 return SILC_SKE_STATUS_ERROR;
1598 memset(e, 0, e_len);
1603 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1604 *return_hash_len = ske->prop->hash->hash->hash_len;
1606 if (initiator == FALSE) {
1607 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1609 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1612 silc_buffer_free(buf);
1617 /* Processes the provided key material `data' as the SILC protocol
1618 specification specifies. */
1621 silc_ske_process_key_material_data(unsigned char *data,
1624 uint32 req_enc_key_len,
1625 uint32 req_hmac_key_len,
1627 SilcSKEKeyMaterial *key)
1630 unsigned char hashd[32];
1631 uint32 hash_len = req_hmac_key_len;
1632 uint32 enc_key_len = req_enc_key_len / 8;
1634 SILC_LOG_DEBUG(("Start"));
1636 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1637 return SILC_SKE_STATUS_ERROR;
1639 buf = silc_buffer_alloc(1 + data_len);
1640 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1641 silc_buffer_format(buf,
1642 SILC_STR_UI_CHAR(0),
1643 SILC_STR_UI_XNSTRING(data, data_len),
1647 memset(hashd, 0, sizeof(hashd));
1649 silc_hash_make(hash, buf->data, buf->len, hashd);
1650 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1651 memcpy(key->send_iv, hashd, req_iv_len);
1652 memset(hashd, 0, sizeof(hashd));
1654 silc_hash_make(hash, buf->data, buf->len, hashd);
1655 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1656 memcpy(key->receive_iv, hashd, req_iv_len);
1657 key->iv_len = req_iv_len;
1659 /* Take the encryption keys. If requested key size is more than
1660 the size of hash length we will distribute more key material
1661 as protocol defines. */
1663 if (enc_key_len > hash_len) {
1665 unsigned char k1[32], k2[32], k3[32];
1666 unsigned char *dtmp;
1669 if (enc_key_len > (3 * hash_len))
1670 return SILC_SKE_STATUS_ERROR;
1672 /* Take first round */
1673 memset(k1, 0, sizeof(k1));
1674 silc_hash_make(hash, buf->data, buf->len, k1);
1676 /* Take second round */
1677 dist = silc_buffer_alloc(data_len + hash_len);
1678 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1679 silc_buffer_format(dist,
1680 SILC_STR_UI_XNSTRING(data, data_len),
1681 SILC_STR_UI_XNSTRING(k1, hash_len),
1683 memset(k2, 0, sizeof(k2));
1684 silc_hash_make(hash, dist->data, dist->len, k2);
1686 /* Take third round */
1687 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1688 silc_buffer_pull_tail(dist, hash_len);
1689 silc_buffer_pull(dist, data_len + hash_len);
1690 silc_buffer_format(dist,
1691 SILC_STR_UI_XNSTRING(k2, hash_len),
1693 silc_buffer_push(dist, data_len + hash_len);
1694 memset(k3, 0, sizeof(k3));
1695 silc_hash_make(hash, dist->data, dist->len, k3);
1697 /* Then, save the keys */
1698 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1699 memcpy(dtmp, k1, hash_len);
1700 memcpy(dtmp + hash_len, k2, hash_len);
1701 memcpy(dtmp + hash_len, k3, hash_len);
1703 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1704 memcpy(key->send_enc_key, dtmp, enc_key_len);
1705 key->enc_key_len = req_enc_key_len;
1707 memset(dtmp, 0, (3 * hash_len));
1708 memset(k1, 0, sizeof(k1));
1709 memset(k2, 0, sizeof(k2));
1710 memset(k3, 0, sizeof(k3));
1712 silc_buffer_free(dist);
1714 /* Take normal hash as key */
1715 memset(hashd, 0, sizeof(hashd));
1716 silc_hash_make(hash, buf->data, buf->len, hashd);
1717 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1718 memcpy(key->send_enc_key, hashd, enc_key_len);
1719 key->enc_key_len = req_enc_key_len;
1723 if (enc_key_len > hash_len) {
1725 unsigned char k1[32], k2[32], k3[32];
1726 unsigned char *dtmp;
1729 if (enc_key_len > (3 * hash_len))
1730 return SILC_SKE_STATUS_ERROR;
1732 /* Take first round */
1733 memset(k1, 0, sizeof(k1));
1734 silc_hash_make(hash, buf->data, buf->len, k1);
1736 /* Take second round */
1737 dist = silc_buffer_alloc(data_len + hash_len);
1738 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1739 silc_buffer_format(dist,
1740 SILC_STR_UI_XNSTRING(data, data_len),
1741 SILC_STR_UI_XNSTRING(k1, hash_len),
1743 memset(k2, 0, sizeof(k2));
1744 silc_hash_make(hash, dist->data, dist->len, k2);
1746 /* Take third round */
1747 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1748 silc_buffer_pull_tail(dist, hash_len);
1749 silc_buffer_pull(dist, data_len + hash_len);
1750 silc_buffer_format(dist,
1751 SILC_STR_UI_XNSTRING(k2, hash_len),
1753 silc_buffer_push(dist, data_len + hash_len);
1754 memset(k3, 0, sizeof(k3));
1755 silc_hash_make(hash, dist->data, dist->len, k3);
1757 /* Then, save the keys */
1758 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1759 memcpy(dtmp, k1, hash_len);
1760 memcpy(dtmp + hash_len, k2, hash_len);
1761 memcpy(dtmp + hash_len, k3, hash_len);
1763 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1764 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1765 key->enc_key_len = req_enc_key_len;
1767 memset(dtmp, 0, (3 * hash_len));
1768 memset(k1, 0, sizeof(k1));
1769 memset(k2, 0, sizeof(k2));
1770 memset(k3, 0, sizeof(k3));
1772 silc_buffer_free(dist);
1774 /* Take normal hash as key */
1775 memset(hashd, 0, sizeof(hashd));
1776 silc_hash_make(hash, buf->data, buf->len, hashd);
1777 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1778 memcpy(key->receive_enc_key, hashd, enc_key_len);
1779 key->enc_key_len = req_enc_key_len;
1783 memset(hashd, 0, sizeof(hashd));
1785 silc_hash_make(hash, buf->data, buf->len, hashd);
1786 key->hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1787 memcpy(key->hmac_key, hashd, req_hmac_key_len);
1788 key->hmac_key_len = req_hmac_key_len;
1790 silc_buffer_free(buf);
1792 return SILC_SKE_STATUS_OK;
1795 /* Processes negotiated key material as protocol specifies. This returns
1796 the actual keys to be used in the SILC. */
1798 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1800 uint32 req_enc_key_len,
1801 uint32 req_hmac_key_len,
1802 SilcSKEKeyMaterial *key)
1804 SilcSKEStatus status;
1806 unsigned char *tmpbuf;
1809 /* Encode KEY to binary data */
1810 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1812 buf = silc_buffer_alloc(klen + ske->hash_len);
1813 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1814 silc_buffer_format(buf,
1815 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1816 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1819 /* Process the key material */
1820 status = silc_ske_process_key_material_data(buf->data, buf->len,
1821 req_iv_len, req_enc_key_len,
1823 ske->prop->hash, key);
1825 memset(tmpbuf, 0, klen);
1827 silc_buffer_free(buf);
1832 /* Free key material structure */
1834 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1840 silc_free(key->send_iv);
1841 if (key->receive_iv)
1842 silc_free(key->receive_iv);
1843 if (key->send_enc_key) {
1844 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1845 silc_free(key->send_enc_key);
1847 if (key->receive_enc_key) {
1848 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1849 silc_free(key->receive_enc_key);
1851 if (key->hmac_key) {
1852 memset(key->hmac_key, 0, key->hmac_key_len);
1853 silc_free(key->hmac_key);