5 Author: Pekka Riikonen <priikone@silcnet.org>
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"
24 #include "groups_internal.h"
26 /* Structure to hold all SKE callbacks. */
27 struct SilcSKECallbacksStruct {
28 SilcSKESendPacketCb send_packet;
29 SilcSKECb payload_receive;
30 SilcSKEVerifyCb verify_key;
31 SilcSKECb proto_continue;
32 SilcSKECheckVersion check_version;
36 /* Allocates new SKE object. */
38 SilcSKE silc_ske_alloc()
42 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
44 ske = silc_calloc(1, sizeof(*ske));
45 ske->status = SILC_SKE_STATUS_OK;
51 /* Free's SKE object. */
53 void silc_ske_free(SilcSKE ske)
57 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
58 ske->status = SILC_SKE_STATUS_FREED;
62 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
65 /* Free start payload */
66 if (ske->start_payload)
67 silc_ske_payload_start_free(ske->start_payload);
71 silc_ske_payload_ke_free(ske->ke1_payload);
75 silc_free(ske->prop->group);
77 silc_pkcs_free(ske->prop->pkcs);
78 if (ske->prop->cipher)
79 silc_cipher_free(ske->prop->cipher);
81 silc_hash_free(ske->prop->hash);
83 silc_hmac_free(ske->prop->hmac);
86 if (ske->start_payload_copy)
87 silc_buffer_free(ske->start_payload_copy);
89 silc_mp_uninit(ske->x);
93 silc_mp_uninit(ske->KEY);
97 silc_free(ske->callbacks);
102 /* Sets the callback functions for the SKE session.
104 The `send_packet' callback is a function that sends the packet to
105 network. The SKE library will call it at any time packet needs to
106 be sent to the remote host.
108 The `payload_receive' callback is called when the remote host's Key
109 Exchange Start Payload has been processed. The payload is saved
110 to ske->start_payload if the application would need it. The application
111 must also provide the payload to the next state of the SKE.
113 The `verify_key' callback is called to verify the received public key
114 or certificate. The verification process is most likely asynchronous.
115 That is why the application must call the completion callback when the
116 verification process has been completed. The library then calls the user
117 callback (`proto_continue'), if it is provided to indicate that the SKE
118 protocol may continue.
120 The `proto_continue' callback is called to indicate that it is
121 safe to continue the execution of the SKE protocol after executing
122 an asynchronous operation, such as calling the `verify_key' callback
123 function, which is asynchronous. The application should check the
124 ske->status in this function to check whether it is Ok to continue
125 the execution of the protocol.
127 The `check_version' callback is called to verify the remote host's
128 version. The application may check its own version against the remote
129 host's version and determine whether supporting the remote host
132 The `context' is passed as argument to all of the above callback
135 void silc_ske_set_callbacks(SilcSKE ske,
136 SilcSKESendPacketCb send_packet,
137 SilcSKECb payload_receive,
138 SilcSKEVerifyCb verify_key,
139 SilcSKECb proto_continue,
140 SilcSKECheckVersion check_version,
144 silc_free(ske->callbacks);
145 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
146 ske->callbacks->send_packet = send_packet;
147 ske->callbacks->payload_receive = payload_receive;
148 ske->callbacks->verify_key = verify_key;
149 ske->callbacks->proto_continue = proto_continue;
150 ske->callbacks->check_version = check_version;
151 ske->callbacks->context = context;
154 /* Starts the SILC Key Exchange protocol for initiator. The connection
155 to the remote end must be established before calling this function
156 and the connecting socket must be sent as argument. This function
157 creates the Key Exchange Start Payload which includes all our
158 configured security properties. This payload is then sent to the
159 remote end for further processing. This payload must be sent as
160 argument to the function, however, it must not be encoded
161 already, it is done by this function. The caller must not free
162 the `start_payload' since the SKE library will save it.
164 The packet sending is done by calling a callback function. Caller
165 must provide a routine to send the packet. */
167 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
168 SilcSocketConnection sock,
169 SilcSKEStartPayload *start_payload)
171 SilcSKEStatus status = SILC_SKE_STATUS_OK;
172 SilcBuffer payload_buf;
174 SILC_LOG_DEBUG(("Start"));
179 /* Encode the payload */
180 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
181 if (status != SILC_SKE_STATUS_OK)
184 /* Take a copy of the payload buffer for future use. It is used to
185 compute the HASH value. */
186 ske->start_payload_copy = silc_buffer_copy(payload_buf);
187 ske->start_payload = start_payload;
189 /* Send the packet. */
190 if (ske->callbacks->send_packet)
191 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
192 ske->callbacks->context);
194 silc_buffer_free(payload_buf);
199 /* Function called after ske_initiator_start fuction. This receives
200 the remote ends Key Exchange Start payload which includes the
201 security properties selected by the responder from our payload
202 sent in the silc_ske_initiator_start function. */
204 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
205 SilcBuffer start_payload)
207 SilcSKEStatus status = SILC_SKE_STATUS_OK;
208 SilcSKEStartPayload *payload;
209 SilcSKESecurityProperties prop;
210 SilcSKEDiffieHellmanGroup group;
212 SILC_LOG_DEBUG(("Start"));
214 /* Decode the payload */
215 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
216 if (status != SILC_SKE_STATUS_OK) {
217 ske->status = status;
218 silc_ske_payload_start_free(ske->start_payload);
222 /* Check that the cookie is returned unmodified */
223 if (memcmp(ske->start_payload->cookie, payload->cookie,
224 ske->start_payload->cookie_len)) {
225 SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
226 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
227 silc_ske_payload_start_free(ske->start_payload);
231 /* Check version string */
232 if (ske->callbacks->check_version) {
233 status = ske->callbacks->check_version(ske, payload->version,
234 payload->version_len,
235 ske->callbacks->context);
236 if (status != SILC_SKE_STATUS_OK) {
237 ske->status = status;
238 silc_ske_payload_start_free(ske->start_payload);
243 /* Free our KE Start Payload context, we don't need it anymore. */
244 silc_ske_payload_start_free(ske->start_payload);
246 /* Take the selected security properties into use while doing
247 the key exchange. This is used only while doing the key
248 exchange. The same data is returned to upper levels by calling
249 the callback function. */
250 ske->prop = prop = silc_calloc(1, sizeof(*prop));
251 prop->flags = payload->flags;
252 status = silc_ske_get_group_by_name(payload->ke_grp_list, &group);
253 if (status != SILC_SKE_STATUS_OK)
258 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
259 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
263 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
264 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
268 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
269 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
273 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
274 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
278 /* Save remote's KE Start Payload */
279 ske->start_payload = payload;
281 /* Return the received payload by calling the callback function. */
282 if (ske->callbacks->payload_receive)
283 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
289 silc_ske_payload_start_free(payload);
294 silc_pkcs_free(prop->pkcs);
296 silc_cipher_free(prop->cipher);
298 silc_hash_free(prop->hash);
300 silc_hmac_free(prop->hmac);
304 if (status == SILC_SKE_STATUS_OK)
305 return SILC_SKE_STATUS_ERROR;
307 ske->status = status;
311 /* This function creates random number x, such that 1 < x < q and
312 computes e = g ^ x mod p and sends the result to the remote end in
313 Key Exchange Payload. */
315 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
316 SilcPublicKey public_key,
317 SilcPrivateKey private_key)
319 SilcSKEStatus status = SILC_SKE_STATUS_OK;
320 SilcBuffer payload_buf;
322 SilcSKEKEPayload *payload;
325 SILC_LOG_DEBUG(("Start"));
327 /* Create the random number x, 1 < x < q. */
328 x = silc_calloc(1, sizeof(*x));
331 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
332 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
334 if (status != SILC_SKE_STATUS_OK) {
337 ske->status = status;
341 /* Encode the result to Key Exchange Payload. */
343 payload = silc_calloc(1, sizeof(*payload));
344 ske->ke1_payload = payload;
346 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
348 /* Do the Diffie Hellman computation, e = g ^ x mod p */
349 silc_mp_init(&payload->x);
350 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
351 &ske->prop->group->group);
355 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
356 if (!payload->pk_data) {
359 silc_mp_uninit(&payload->x);
361 ske->status = SILC_SKE_STATUS_OK;
364 payload->pk_len = pk_len;
366 payload->pk_type = SILC_SKE_PK_TYPE_SILC;
368 /* Compute signature data if we are doing mutual authentication */
369 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
370 unsigned char hash[32], sign[1024];
371 uint32 hash_len, sign_len;
373 SILC_LOG_DEBUG(("We are doing mutual authentication"));
374 SILC_LOG_DEBUG(("Computing HASH_i value"));
376 /* Compute the hash value */
377 memset(hash, 0, sizeof(hash));
378 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
380 SILC_LOG_DEBUG(("Signing HASH_i value"));
382 /* Sign the hash value */
383 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
384 private_key->prv_len);
385 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
386 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
387 memcpy(payload->sign_data, sign, sign_len);
388 memset(sign, 0, sizeof(sign));
389 payload->sign_len = sign_len;
392 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
393 if (status != SILC_SKE_STATUS_OK) {
396 silc_mp_uninit(&payload->x);
397 silc_free(payload->pk_data);
399 ske->status = status;
405 /* Send the packet. */
406 if (ske->callbacks->send_packet)
407 (*ske->callbacks->send_packet)(ske, payload_buf,
408 SILC_PACKET_KEY_EXCHANGE_1,
409 ske->callbacks->context);
411 silc_buffer_free(payload_buf);
416 /* An initiator finish final callback that is called to indicate that
417 the SKE protocol may continue. */
419 static void silc_ske_initiator_finish_final(SilcSKE ske,
420 SilcSKEStatus status,
423 SilcSKEKEPayload *payload;
424 unsigned char hash[32];
426 SilcPublicKey public_key = NULL;
428 /* If the SKE was freed during the async call then free it really now,
429 otherwise just decrement the reference counter. */
430 if (ske->status == SILC_SKE_STATUS_FREED) {
435 /* If the caller returns PENDING status SKE library will assume that
436 the caller will re-call this callback when it is not anymore in
438 if (status == SILC_SKE_STATUS_PENDING)
442 payload = ske->ke2_payload;
444 /* If the status is an error then the public key that was verified
445 by the caller is not authentic. */
446 if (status != SILC_SKE_STATUS_OK) {
447 ske->status = status;
448 if (ske->callbacks->proto_continue)
449 ske->callbacks->proto_continue(ske, ske->callbacks->context);
453 if (payload->pk_data) {
454 /* Decode the public key */
455 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
457 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
458 if (ske->callbacks->proto_continue)
459 ske->callbacks->proto_continue(ske, ske->callbacks->context);
463 SILC_LOG_DEBUG(("Public key is authentic"));
465 /* Compute the hash value */
466 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
467 if (status != SILC_SKE_STATUS_OK)
470 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
471 memcpy(ske->hash, hash, hash_len);
472 ske->hash_len = hash_len;
474 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
476 /* Verify signature */
477 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
478 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
479 payload->sign_len, hash, hash_len) == FALSE) {
481 SILC_LOG_DEBUG(("Signature don't match"));
483 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
487 SILC_LOG_DEBUG(("Signature is Ok"));
489 silc_pkcs_public_key_free(public_key);
490 memset(hash, 'F', hash_len);
493 ske->status = SILC_SKE_STATUS_OK;
495 /* Call the callback. The caller may now continue the SKE protocol. */
496 if (ske->callbacks->proto_continue)
497 ske->callbacks->proto_continue(ske, ske->callbacks->context);
502 memset(hash, 'F', sizeof(hash));
503 silc_ske_payload_ke_free(payload);
504 ske->ke2_payload = NULL;
506 silc_mp_uninit(ske->KEY);
511 silc_pkcs_public_key_free(public_key);
514 memset(ske->hash, 'F', hash_len);
515 silc_free(ske->hash);
519 if (status == SILC_SKE_STATUS_OK)
520 ske->status = SILC_SKE_STATUS_ERROR;
522 ske->status = status;
524 /* Call the callback. */
525 if (ske->callbacks->proto_continue)
526 ske->callbacks->proto_continue(ske, ske->callbacks->context);
529 /* Receives Key Exchange Payload from responder consisting responders
530 public key, f, and signature. This function verifies the public key,
531 computes the secret shared key and verifies the signature.
533 The `callback' will be called to indicate that the caller may
534 continue with the SKE protocol. The caller must not continue
535 before the SKE libary has called that callback. If this function
536 returns an error the callback will not be called. It is called
537 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
538 However, note that when the library calls the callback the ske->status
541 This calls the `verify_key' callback to verify the received public
542 key or certificate. If the `verify_key' is provided then the remote
543 must send public key and it is considered to be an error if remote
544 does not send its public key. If caller is performing a re-key with
545 SKE then the `verify_key' is usually not provided when it is not also
546 required for the remote to send its public key. */
548 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
549 SilcBuffer ke_payload)
551 SilcSKEStatus status = SILC_SKE_STATUS_OK;
552 SilcSKEKEPayload *payload;
555 SILC_LOG_DEBUG(("Start"));
557 /* Decode the payload */
558 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
559 if (status != SILC_SKE_STATUS_OK) {
560 ske->status = status;
563 ske->ke2_payload = payload;
565 if (!payload->pk_data && ske->callbacks->verify_key) {
566 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
567 "even though we require it"));
568 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
572 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
574 /* Compute the shared secret key */
575 KEY = silc_calloc(1, sizeof(*KEY));
577 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
580 if (payload->pk_data && ske->callbacks->verify_key) {
581 SILC_LOG_DEBUG(("Verifying public key"));
584 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
585 payload->pk_type, ske->callbacks->context,
586 silc_ske_initiator_finish_final, NULL);
588 /* We will continue to the final state after the public key has
589 been verified by the caller. */
590 return SILC_SKE_STATUS_PENDING;
593 /* Continue to final state */
595 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
597 return SILC_SKE_STATUS_OK;
600 silc_ske_payload_ke_free(payload);
601 ske->ke2_payload = NULL;
603 silc_mp_uninit(ske->KEY);
607 if (status == SILC_SKE_STATUS_OK)
608 return SILC_SKE_STATUS_ERROR;
610 ske->status = status;
614 /* Starts Key Exchange protocol for responder. Responder receives
615 Key Exchange Start Payload from initiator consisting of all the
616 security properties the initiator supports. This function decodes
617 the payload and parses the payload further and selects the right
618 security properties. */
620 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
621 SilcSocketConnection sock,
623 SilcBuffer start_payload,
626 SilcSKEStatus status = SILC_SKE_STATUS_OK;
627 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
629 SILC_LOG_DEBUG(("Start"));
634 /* Decode the payload */
635 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
636 if (status != SILC_SKE_STATUS_OK) {
637 ske->status = status;
641 /* Take a copy of the payload buffer for future use. It is used to
642 compute the HASH value. */
643 ske->start_payload_copy = silc_buffer_copy(start_payload);
645 /* Force the mutual authentication flag if we want to do it. */
647 SILC_LOG_DEBUG(("Force mutual authentication"));
648 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
651 /* Parse and select the security properties from the payload */
652 payload = silc_calloc(1, sizeof(*payload));
653 status = silc_ske_select_security_properties(ske, version,
654 payload, remote_payload);
655 if (status != SILC_SKE_STATUS_OK)
658 ske->start_payload = payload;
660 /* Call the callback function. */
661 if (ske->callbacks->payload_receive)
662 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
664 silc_ske_payload_start_free(remote_payload);
670 silc_ske_payload_start_free(remote_payload);
674 if (status == SILC_SKE_STATUS_OK)
675 return SILC_SKE_STATUS_ERROR;
677 ske->status = status;
681 /* The selected security properties from the initiator payload is now
682 encoded into Key Exchange Start Payload and sent to the initiator. */
684 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
685 SilcSKEStartPayload *start_payload)
687 SilcSKEStatus status = SILC_SKE_STATUS_OK;
688 SilcBuffer payload_buf;
689 SilcSKESecurityProperties prop;
690 SilcSKEDiffieHellmanGroup group = NULL;
692 SILC_LOG_DEBUG(("Start"));
694 /* Allocate security properties from the payload. These are allocated
695 only for this negotiation and will be free'd after KE is over. */
696 ske->prop = prop = silc_calloc(1, sizeof(*prop));
697 prop->flags = start_payload->flags;
698 status = silc_ske_get_group_by_name(start_payload->ke_grp_list, &group);
699 if (status != SILC_SKE_STATUS_OK)
704 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
705 &prop->pkcs) == FALSE) {
706 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
710 if (silc_cipher_alloc(start_payload->enc_alg_list,
711 &prop->cipher) == FALSE) {
712 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
716 if (silc_hash_alloc(start_payload->hash_alg_list,
717 &prop->hash) == FALSE) {
718 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
722 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
723 &prop->hmac) == FALSE) {
724 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
728 /* Encode the payload */
729 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
730 if (status != SILC_SKE_STATUS_OK)
733 /* Send the packet. */
734 if (ske->callbacks->send_packet)
735 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
736 ske->callbacks->context);
738 silc_buffer_free(payload_buf);
747 silc_pkcs_free(prop->pkcs);
749 silc_cipher_free(prop->cipher);
751 silc_hash_free(prop->hash);
753 silc_hmac_free(prop->hmac);
757 if (status == SILC_SKE_STATUS_OK)
758 return SILC_SKE_STATUS_ERROR;
760 ske->status = status;
764 /* An responder phase 2 final callback that is called to indicate that
765 the SKE protocol may continue. */
767 static void silc_ske_responder_phase2_final(SilcSKE ske,
768 SilcSKEStatus status,
771 SilcSKEKEPayload *recv_payload, *send_payload;
774 /* If the SKE was freed during the async call then free it really now,
775 otherwise just decrement the reference counter. */
776 if (ske->status == SILC_SKE_STATUS_FREED) {
781 /* If the caller returns PENDING status SKE library will assume that
782 the caller will re-call this callback when it is not anymore in
784 if (status == SILC_SKE_STATUS_PENDING)
788 recv_payload = ske->ke1_payload;
790 /* If the status is an error then the public key that was verified
791 by the caller is not authentic. */
792 if (status != SILC_SKE_STATUS_OK) {
793 ske->status = status;
794 if (ske->callbacks->proto_continue)
795 ske->callbacks->proto_continue(ske, ske->callbacks->context);
799 /* The public key verification was performed only if the Mutual
800 Authentication flag is set. */
801 if (ske->start_payload &&
802 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
803 SilcPublicKey public_key = NULL;
804 unsigned char hash[32];
807 /* Decode the public key */
808 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
809 recv_payload->pk_len,
811 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
812 if (ske->callbacks->proto_continue)
813 ske->callbacks->proto_continue(ske, ske->callbacks->context);
817 SILC_LOG_DEBUG(("Public key is authentic"));
819 /* Compute the hash value */
820 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
821 if (status != SILC_SKE_STATUS_OK) {
822 ske->status = status;
823 if (ske->callbacks->proto_continue)
824 ske->callbacks->proto_continue(ske, ske->callbacks->context);
828 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
830 /* Verify signature */
831 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
832 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
833 recv_payload->sign_len, hash, hash_len) == FALSE) {
835 SILC_LOG_DEBUG(("Signature don't match"));
837 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
838 if (ske->callbacks->proto_continue)
839 ske->callbacks->proto_continue(ske, ske->callbacks->context);
843 SILC_LOG_DEBUG(("Signature is Ok"));
845 silc_pkcs_public_key_free(public_key);
846 memset(hash, 'F', hash_len);
849 /* Create the random number x, 1 < x < q. */
850 x = silc_calloc(1, sizeof(*x));
853 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
854 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
856 if (status != SILC_SKE_STATUS_OK) {
859 ske->status = status;
860 if (ske->callbacks->proto_continue)
861 ske->callbacks->proto_continue(ske, ske->callbacks->context);
865 /* Save the results for later processing */
866 send_payload = silc_calloc(1, sizeof(*send_payload));
868 ske->ke2_payload = send_payload;
870 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
872 /* Do the Diffie Hellman computation, f = g ^ x mod p */
873 silc_mp_init(&send_payload->x);
874 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
875 &ske->prop->group->group);
877 /* Call the callback. The caller may now continue with the SKE protocol. */
878 ske->status = SILC_SKE_STATUS_OK;
879 if (ske->callbacks->proto_continue)
880 ske->callbacks->proto_continue(ske, ske->callbacks->context);
883 /* This function receives the Key Exchange Payload from the initiator.
884 This also performs the mutual authentication if required. Then, this
885 function first generated a random number x, such that 1 < x < q
886 and computes f = g ^ x mod p. This then puts the result f to a Key
889 The `callback' will be called to indicate that the caller may
890 continue with the SKE protocol. The caller must not continue
891 before the SKE libary has called that callback. If this function
892 returns an error the callback will not be called. It is called
893 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
894 However, note that when the library calls the callback the ske->status
897 This calls the `verify_key' callback to verify the received public
898 key or certificate if the Mutual Authentication flag is set. If the
899 `verify_key' is provided then the remote must send public key and it
900 is considered to be an error if remote does not send its public key. */
902 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
903 SilcBuffer ke_payload)
905 SilcSKEStatus status = SILC_SKE_STATUS_OK;
906 SilcSKEKEPayload *recv_payload;
908 SILC_LOG_DEBUG(("Start"));
910 /* Decode Key Exchange Payload */
911 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
912 if (status != SILC_SKE_STATUS_OK) {
913 ske->status = status;
917 ske->ke1_payload = recv_payload;
919 /* Verify the received public key and verify the signature if we are
920 doing mutual authentication. */
921 if (ske->start_payload &&
922 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
924 SILC_LOG_DEBUG(("We are doing mutual authentication"));
926 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
927 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
928 "certificate), even though we require it"));
929 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
933 if (recv_payload->pk_data && ske->callbacks->verify_key) {
934 SILC_LOG_DEBUG(("Verifying public key"));
937 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
938 recv_payload->pk_len,
939 recv_payload->pk_type,
940 ske->callbacks->context,
941 silc_ske_responder_phase2_final, NULL);
943 /* We will continue to the final state after the public key has
944 been verified by the caller. */
945 return SILC_SKE_STATUS_PENDING;
949 /* Continue to final state */
951 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
953 return SILC_SKE_STATUS_OK;
956 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
957 value to be signed and sent to the other end. This then encodes Key
958 Exchange Payload and sends it to the other end. */
960 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
961 SilcPublicKey public_key,
962 SilcPrivateKey private_key,
963 SilcSKEPKType pk_type)
965 SilcSKEStatus status = SILC_SKE_STATUS_OK;
966 SilcBuffer payload_buf;
968 unsigned char hash[32], sign[1024], *pk;
969 uint32 hash_len, sign_len, pk_len;
971 SILC_LOG_DEBUG(("Start"));
973 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
975 /* Compute the shared secret key */
976 KEY = silc_calloc(1, sizeof(*KEY));
978 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
979 &ske->prop->group->group);
982 if (public_key && private_key) {
983 SILC_LOG_DEBUG(("Getting public key"));
985 /* Get the public key */
986 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
988 status = SILC_SKE_STATUS_ERROR;
991 ske->ke2_payload->pk_data = pk;
992 ske->ke2_payload->pk_len = pk_len;
994 SILC_LOG_DEBUG(("Computing HASH value"));
996 /* Compute the hash value */
997 memset(hash, 0, sizeof(hash));
998 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
999 if (status != SILC_SKE_STATUS_OK)
1002 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1003 memcpy(ske->hash, hash, hash_len);
1004 ske->hash_len = hash_len;
1006 SILC_LOG_DEBUG(("Signing HASH value"));
1008 /* Sign the hash value */
1009 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1010 private_key->prv_len);
1011 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1012 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1013 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1014 memset(sign, 0, sizeof(sign));
1015 ske->ke2_payload->sign_len = sign_len;
1017 ske->ke2_payload->pk_type = pk_type;
1019 /* Encode the Key Exchange Payload */
1020 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1022 if (status != SILC_SKE_STATUS_OK)
1025 /* Send the packet. */
1026 if (ske->callbacks->send_packet)
1027 (*ske->callbacks->send_packet)(ske, payload_buf,
1028 SILC_PACKET_KEY_EXCHANGE_2,
1029 ske->callbacks->context);
1031 silc_buffer_free(payload_buf);
1036 silc_mp_uninit(ske->KEY);
1037 silc_free(ske->KEY);
1039 silc_ske_payload_ke_free(ske->ke2_payload);
1041 if (status == SILC_SKE_STATUS_OK)
1042 return SILC_SKE_STATUS_ERROR;
1044 ske->status = status;
1048 /* The Key Exchange protocol is ended by calling this function. This
1049 must not be called until the keys are processed like the protocol
1050 defines. This function is for both initiator and responder. */
1052 SilcSKEStatus silc_ske_end(SilcSKE ske)
1056 SILC_LOG_DEBUG(("Start"));
1058 packet = silc_buffer_alloc(4);
1059 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1060 silc_buffer_format(packet,
1061 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
1064 if (ske->callbacks->send_packet)
1065 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1066 ske->callbacks->context);
1068 silc_buffer_free(packet);
1070 return SILC_SKE_STATUS_OK;
1073 /* Aborts the Key Exchange protocol. This is called if error occurs
1074 while performing the protocol. The status argument is the error
1075 status and it is sent to the remote end. */
1077 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1081 SILC_LOG_DEBUG(("Start"));
1083 packet = silc_buffer_alloc(4);
1084 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1085 silc_buffer_format(packet,
1086 SILC_STR_UI_INT((uint32)status),
1089 if (ske->callbacks->send_packet)
1090 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1091 ske->callbacks->context);
1093 silc_buffer_free(packet);
1095 return SILC_SKE_STATUS_OK;
1098 /* Assembles security properties to Key Exchange Start Payload to be
1099 sent to the remote end. This checks system wide (SILC system, that is)
1100 settings and chooses from those. However, if other properties
1101 should be used this function is easy to replace by another function,
1102 as, this function is called by the caller of the protocol and not
1103 by the protocol itself. */
1106 silc_ske_assemble_security_properties(SilcSKE ske,
1107 unsigned char flags,
1109 SilcSKEStartPayload **return_payload)
1111 SilcSKEStartPayload *rp;
1114 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1116 rp = silc_calloc(1, sizeof(*rp));
1121 /* Set random cookie */
1122 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1123 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1124 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1125 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1128 rp->version = strdup(version);
1129 rp->version_len = strlen(version);
1131 /* Get supported Key Exhange groups */
1132 rp->ke_grp_list = silc_ske_get_supported_groups();
1133 rp->ke_grp_len = strlen(rp->ke_grp_list);
1135 /* Get supported PKCS algorithms */
1136 rp->pkcs_alg_list = silc_pkcs_get_supported();
1137 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1139 /* Get supported encryption algorithms */
1140 rp->enc_alg_list = silc_cipher_get_supported();
1141 rp->enc_alg_len = strlen(rp->enc_alg_list);
1143 /* Get supported hash algorithms */
1144 rp->hash_alg_list = silc_hash_get_supported();
1145 rp->hash_alg_len = strlen(rp->hash_alg_list);
1147 /* Get supported HMACs */
1148 rp->hmac_alg_list = silc_hmac_get_supported();
1149 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1152 /* Get supported compression algorithms */
1153 rp->comp_alg_list = strdup("");
1154 rp->comp_alg_len = 0;
1156 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1157 2 + rp->version_len +
1158 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1159 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1160 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1162 *return_payload = rp;
1164 return SILC_SKE_STATUS_OK;
1167 /* Selects the supported security properties from the remote end's Key
1168 Exchange Start Payload. */
1171 silc_ske_select_security_properties(SilcSKE ske,
1173 SilcSKEStartPayload *payload,
1174 SilcSKEStartPayload *remote_payload)
1176 SilcSKEStatus status;
1177 SilcSKEStartPayload *rp;
1181 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1183 rp = remote_payload;
1185 /* Check version string */
1186 if (ske->callbacks->check_version) {
1187 status = ske->callbacks->check_version(ske, rp->version,
1189 ske->callbacks->context);
1190 if (status != SILC_SKE_STATUS_OK) {
1191 ske->status = status;
1196 /* Flags are returned unchanged. */
1197 payload->flags = rp->flags;
1199 /* Take cookie, we must return it to sender unmodified. */
1200 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1201 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1202 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1204 /* Put our version to our reply */
1205 payload->version = strdup(version);
1206 payload->version_len = strlen(version);
1208 /* Get supported Key Exchange groups */
1209 cp = rp->ke_grp_list;
1210 if (cp && strchr(cp, ',')) {
1214 len = strcspn(cp, ",");
1215 item = silc_calloc(len + 1, sizeof(char));
1216 memcpy(item, cp, len);
1218 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1220 if (silc_ske_get_group_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1221 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1223 payload->ke_grp_len = len;
1224 payload->ke_grp_list = item;
1229 if (strlen(cp) == 0)
1238 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1239 SILC_LOG_DEBUG(("Could not find supported KE group"));
1241 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1245 if (!rp->ke_grp_len) {
1246 SILC_LOG_DEBUG(("KE group not defined in payload"));
1248 return SILC_SKE_STATUS_BAD_PAYLOAD;
1251 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1252 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1254 payload->ke_grp_len = rp->ke_grp_len;
1255 payload->ke_grp_list = strdup(rp->ke_grp_list);
1258 /* Get supported PKCS algorithms */
1259 cp = rp->pkcs_alg_list;
1260 if (cp && strchr(cp, ',')) {
1264 len = strcspn(cp, ",");
1265 item = silc_calloc(len + 1, sizeof(char));
1266 memcpy(item, cp, len);
1268 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1270 if (silc_pkcs_is_supported(item) == TRUE) {
1271 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1273 payload->pkcs_alg_len = len;
1274 payload->pkcs_alg_list = item;
1279 if (strlen(cp) == 0)
1288 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1289 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1290 silc_free(payload->ke_grp_list);
1292 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1296 if (!rp->pkcs_alg_len) {
1297 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1298 silc_free(payload->ke_grp_list);
1300 return SILC_SKE_STATUS_BAD_PAYLOAD;
1303 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1304 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1306 payload->pkcs_alg_len = rp->pkcs_alg_len;
1307 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1310 /* Get supported encryption algorithms */
1311 cp = rp->enc_alg_list;
1312 if (cp && strchr(cp, ',')) {
1316 len = strcspn(cp, ",");
1317 item = silc_calloc(len + 1, sizeof(char));
1318 memcpy(item, cp, len);
1320 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1322 if (silc_cipher_is_supported(item) == TRUE) {
1323 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1325 payload->enc_alg_len = len;
1326 payload->enc_alg_list = item;
1331 if (strlen(cp) == 0)
1340 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1341 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1342 silc_free(payload->ke_grp_list);
1343 silc_free(payload->pkcs_alg_list);
1345 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1349 if (!rp->enc_alg_len) {
1350 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1351 silc_free(payload->ke_grp_list);
1352 silc_free(payload->pkcs_alg_list);
1354 return SILC_SKE_STATUS_BAD_PAYLOAD;
1357 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1360 payload->enc_alg_len = rp->enc_alg_len;
1361 payload->enc_alg_list = strdup(rp->enc_alg_list);
1364 /* Get supported hash algorithms */
1365 cp = rp->hash_alg_list;
1366 if (cp && strchr(cp, ',')) {
1370 len = strcspn(cp, ",");
1371 item = silc_calloc(len + 1, sizeof(char));
1372 memcpy(item, cp, len);
1374 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1376 if (silc_hash_is_supported(item) == TRUE) {
1377 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1379 payload->hash_alg_len = len;
1380 payload->hash_alg_list = item;
1385 if (strlen(cp) == 0)
1394 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1395 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1396 silc_free(payload->ke_grp_list);
1397 silc_free(payload->pkcs_alg_list);
1398 silc_free(payload->enc_alg_list);
1400 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1404 if (!rp->hash_alg_len) {
1405 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1406 silc_free(payload->ke_grp_list);
1407 silc_free(payload->pkcs_alg_list);
1408 silc_free(payload->enc_alg_list);
1410 return SILC_SKE_STATUS_BAD_PAYLOAD;
1413 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1414 rp->hash_alg_list));
1416 payload->hash_alg_len = rp->hash_alg_len;
1417 payload->hash_alg_list = strdup(rp->hash_alg_list);
1420 /* Get supported HMACs */
1421 cp = rp->hmac_alg_list;
1422 if (cp && strchr(cp, ',')) {
1426 len = strcspn(cp, ",");
1427 item = silc_calloc(len + 1, sizeof(char));
1428 memcpy(item, cp, len);
1430 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1432 if (silc_hmac_is_supported(item) == TRUE) {
1433 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1435 payload->hmac_alg_len = len;
1436 payload->hmac_alg_list = item;
1441 if (strlen(cp) == 0)
1450 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1451 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1452 silc_free(payload->ke_grp_list);
1453 silc_free(payload->pkcs_alg_list);
1454 silc_free(payload->enc_alg_list);
1455 silc_free(payload->hash_alg_list);
1457 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1461 if (!rp->hmac_alg_len) {
1462 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1463 silc_free(payload->ke_grp_list);
1464 silc_free(payload->pkcs_alg_list);
1465 silc_free(payload->enc_alg_list);
1466 silc_free(payload->hash_alg_list);
1468 return SILC_SKE_STATUS_BAD_PAYLOAD;
1471 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1472 rp->hmac_alg_list));
1474 payload->hmac_alg_len = rp->hmac_alg_len;
1475 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1479 /* Get supported compression algorithms */
1480 cp = rp->hash_alg_list;
1481 if (cp && strchr(cp, ',')) {
1485 len = strcspn(cp, ",");
1486 item = silc_calloc(len + 1, sizeof(char));
1487 memcpy(item, cp, len);
1489 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1491 if (silc_hash_is_supported(item) == TRUE) {
1492 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1494 payload->hash_alg_len = len;
1495 payload->hash_alg_list = item;
1500 if (strlen(cp) == 0)
1509 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1510 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1511 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1512 silc_free(payload->ke_grp_list);
1513 silc_free(payload->pkcs_alg_list);
1514 silc_free(payload->enc_alg_list);
1523 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1524 2 + payload->version_len +
1525 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1526 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1527 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1529 return SILC_SKE_STATUS_OK;
1532 /* Creates random number such that 1 < rnd < n and at most length
1533 of len bits. The rnd sent as argument must be initialized. */
1535 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1539 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1540 unsigned char *string;
1542 SILC_LOG_DEBUG(("Creating random number"));
1544 /* Get the random number as string */
1545 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1547 return SILC_SKE_STATUS_ERROR;
1549 /* Decode the string into a MP integer */
1550 silc_mp_bin2mp(string, (len / 8), rnd);
1551 silc_mp_mod_2exp(rnd, rnd, len);
1554 if (silc_mp_cmp_ui(rnd, 1) < 0)
1555 status = SILC_SKE_STATUS_ERROR;
1557 if (silc_mp_cmp(rnd, n) >= 0)
1558 status = SILC_SKE_STATUS_ERROR;
1560 memset(string, 'F', (len / 8));
1566 /* Creates a hash value HASH as defined in the SKE protocol. If the
1567 `initiator' is TRUE then this function is used to create the HASH_i
1568 hash value defined in the protocol. If it is FALSE then this is used
1569 to create the HASH value defined by the protocol. */
1571 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1572 unsigned char *return_hash,
1573 uint32 *return_hash_len,
1576 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1578 unsigned char *e, *f, *KEY;
1579 uint32 e_len, f_len, KEY_len;
1582 SILC_LOG_DEBUG(("Start"));
1584 if (initiator == FALSE) {
1585 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1586 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1587 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1589 /* Format the buffer used to compute the hash value */
1590 /* XXX Backward support for 0.6.1 */
1591 if (ske->backward_version == 1) {
1592 SILC_LOG_DEBUG(("*********** Using old KE payload"));
1593 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1594 ske->ke2_payload->pk_len + e_len +
1596 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1599 silc_buffer_format(buf,
1600 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1601 ske->start_payload_copy->len),
1602 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1603 ske->ke2_payload->pk_len),
1604 SILC_STR_UI_XNSTRING(e, e_len),
1605 SILC_STR_UI_XNSTRING(f, f_len),
1606 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1609 /* Initiator is not required to send its public key */
1610 SILC_LOG_DEBUG(("*********** Using new KE payload"));
1611 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1612 ske->ke2_payload->pk_len +
1613 ske->ke1_payload->pk_len +
1614 e_len + f_len + KEY_len);
1615 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1617 if (!ske->ke1_payload->pk_data) {
1619 silc_buffer_format(buf,
1620 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1622 ske->start_payload_copy->
1624 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1625 ske->ke2_payload->pk_len),
1626 SILC_STR_UI_XNSTRING(e, e_len),
1627 SILC_STR_UI_XNSTRING(f, f_len),
1628 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1632 silc_buffer_format(buf,
1633 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1635 ske->start_payload_copy->
1637 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1638 ske->ke2_payload->pk_len),
1639 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1640 ske->ke1_payload->pk_len),
1641 SILC_STR_UI_XNSTRING(e, e_len),
1642 SILC_STR_UI_XNSTRING(f, f_len),
1643 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1648 silc_buffer_free(buf);
1649 memset(e, 0, e_len);
1650 memset(f, 0, f_len);
1651 memset(KEY, 0, KEY_len);
1655 return SILC_SKE_STATUS_ERROR;
1658 memset(e, 0, e_len);
1659 memset(f, 0, f_len);
1660 memset(KEY, 0, KEY_len);
1665 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1667 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1668 ske->ke1_payload->pk_len + e_len);
1669 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1671 /* Format the buffer used to compute the hash value */
1673 silc_buffer_format(buf,
1674 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1675 ske->start_payload_copy->len),
1676 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1677 ske->ke1_payload->pk_len),
1678 SILC_STR_UI_XNSTRING(e, e_len),
1681 silc_buffer_free(buf);
1682 memset(e, 0, e_len);
1684 return SILC_SKE_STATUS_ERROR;
1687 memset(e, 0, e_len);
1692 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1693 *return_hash_len = ske->prop->hash->hash->hash_len;
1695 if (initiator == FALSE) {
1696 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1698 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1701 silc_buffer_free(buf);
1706 /* Processes the provided key material `data' as the SILC protocol
1707 specification defines. */
1710 silc_ske_process_key_material_data(unsigned char *data,
1713 uint32 req_enc_key_len,
1714 uint32 req_hmac_key_len,
1716 SilcSKEKeyMaterial *key)
1719 unsigned char hashd[32];
1720 uint32 hash_len = req_hmac_key_len;
1721 uint32 enc_key_len = req_enc_key_len / 8;
1723 SILC_LOG_DEBUG(("Start"));
1725 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1726 return SILC_SKE_STATUS_ERROR;
1728 buf = silc_buffer_alloc(1 + data_len);
1729 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1730 silc_buffer_format(buf,
1731 SILC_STR_UI_CHAR(0),
1732 SILC_STR_UI_XNSTRING(data, data_len),
1736 memset(hashd, 0, sizeof(hashd));
1738 silc_hash_make(hash, buf->data, buf->len, hashd);
1739 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1740 memcpy(key->send_iv, hashd, req_iv_len);
1741 memset(hashd, 0, sizeof(hashd));
1743 silc_hash_make(hash, buf->data, buf->len, hashd);
1744 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1745 memcpy(key->receive_iv, hashd, req_iv_len);
1746 key->iv_len = req_iv_len;
1748 /* Take the encryption keys. If requested key size is more than
1749 the size of hash length we will distribute more key material
1750 as protocol defines. */
1752 if (enc_key_len > hash_len) {
1754 unsigned char k1[32], k2[32], k3[32];
1755 unsigned char *dtmp;
1758 if (enc_key_len > (3 * hash_len))
1759 return SILC_SKE_STATUS_ERROR;
1761 /* Take first round */
1762 memset(k1, 0, sizeof(k1));
1763 silc_hash_make(hash, buf->data, buf->len, k1);
1765 /* Take second round */
1766 dist = silc_buffer_alloc(data_len + hash_len);
1767 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1768 silc_buffer_format(dist,
1769 SILC_STR_UI_XNSTRING(data, data_len),
1770 SILC_STR_UI_XNSTRING(k1, hash_len),
1772 memset(k2, 0, sizeof(k2));
1773 silc_hash_make(hash, dist->data, dist->len, k2);
1775 /* Take third round */
1776 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1777 silc_buffer_pull_tail(dist, hash_len);
1778 silc_buffer_pull(dist, data_len + hash_len);
1779 silc_buffer_format(dist,
1780 SILC_STR_UI_XNSTRING(k2, hash_len),
1782 silc_buffer_push(dist, data_len + hash_len);
1783 memset(k3, 0, sizeof(k3));
1784 silc_hash_make(hash, dist->data, dist->len, k3);
1786 /* Then, save the keys */
1787 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1788 memcpy(dtmp, k1, hash_len);
1789 memcpy(dtmp + hash_len, k2, hash_len);
1790 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1792 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1793 memcpy(key->send_enc_key, dtmp, enc_key_len);
1794 key->enc_key_len = req_enc_key_len;
1796 memset(dtmp, 0, (3 * hash_len));
1797 memset(k1, 0, sizeof(k1));
1798 memset(k2, 0, sizeof(k2));
1799 memset(k3, 0, sizeof(k3));
1801 silc_buffer_free(dist);
1803 /* Take normal hash as key */
1804 memset(hashd, 0, sizeof(hashd));
1805 silc_hash_make(hash, buf->data, buf->len, hashd);
1806 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1807 memcpy(key->send_enc_key, hashd, enc_key_len);
1808 key->enc_key_len = req_enc_key_len;
1812 if (enc_key_len > hash_len) {
1814 unsigned char k1[32], k2[32], k3[32];
1815 unsigned char *dtmp;
1818 if (enc_key_len > (3 * hash_len))
1819 return SILC_SKE_STATUS_ERROR;
1821 /* Take first round */
1822 memset(k1, 0, sizeof(k1));
1823 silc_hash_make(hash, buf->data, buf->len, k1);
1825 /* Take second round */
1826 dist = silc_buffer_alloc(data_len + hash_len);
1827 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1828 silc_buffer_format(dist,
1829 SILC_STR_UI_XNSTRING(data, data_len),
1830 SILC_STR_UI_XNSTRING(k1, hash_len),
1832 memset(k2, 0, sizeof(k2));
1833 silc_hash_make(hash, dist->data, dist->len, k2);
1835 /* Take third round */
1836 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1837 silc_buffer_pull_tail(dist, hash_len);
1838 silc_buffer_pull(dist, data_len + hash_len);
1839 silc_buffer_format(dist,
1840 SILC_STR_UI_XNSTRING(k2, hash_len),
1842 silc_buffer_push(dist, data_len + hash_len);
1843 memset(k3, 0, sizeof(k3));
1844 silc_hash_make(hash, dist->data, dist->len, k3);
1846 /* Then, save the keys */
1847 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1848 memcpy(dtmp, k1, hash_len);
1849 memcpy(dtmp + hash_len, k2, hash_len);
1850 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1852 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1853 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1854 key->enc_key_len = req_enc_key_len;
1856 memset(dtmp, 0, (3 * hash_len));
1857 memset(k1, 0, sizeof(k1));
1858 memset(k2, 0, sizeof(k2));
1859 memset(k3, 0, sizeof(k3));
1861 silc_buffer_free(dist);
1863 /* Take normal hash as key */
1864 memset(hashd, 0, sizeof(hashd));
1865 silc_hash_make(hash, buf->data, buf->len, hashd);
1866 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1867 memcpy(key->receive_enc_key, hashd, enc_key_len);
1868 key->enc_key_len = req_enc_key_len;
1871 /* Take HMAC keys */
1872 memset(hashd, 0, sizeof(hashd));
1874 silc_hash_make(hash, buf->data, buf->len, hashd);
1875 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1876 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1877 memset(hashd, 0, sizeof(hashd));
1879 silc_hash_make(hash, buf->data, buf->len, hashd);
1880 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1881 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1882 key->hmac_key_len = req_hmac_key_len;
1883 memset(hashd, 0, sizeof(hashd));
1885 silc_buffer_free(buf);
1887 return SILC_SKE_STATUS_OK;
1890 /* Processes negotiated key material as protocol specifies. This returns
1891 the actual keys to be used in the SILC. */
1893 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1895 uint32 req_enc_key_len,
1896 uint32 req_hmac_key_len,
1897 SilcSKEKeyMaterial *key)
1899 SilcSKEStatus status;
1901 unsigned char *tmpbuf;
1904 /* Encode KEY to binary data */
1905 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1907 buf = silc_buffer_alloc(klen + ske->hash_len);
1908 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1909 silc_buffer_format(buf,
1910 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1911 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1914 /* Process the key material */
1915 status = silc_ske_process_key_material_data(buf->data, buf->len,
1916 req_iv_len, req_enc_key_len,
1918 ske->prop->hash, key);
1920 memset(tmpbuf, 0, klen);
1922 silc_buffer_free(buf);
1927 /* Free key material structure */
1929 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1935 silc_free(key->send_iv);
1936 if (key->receive_iv)
1937 silc_free(key->receive_iv);
1938 if (key->send_enc_key) {
1939 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1940 silc_free(key->send_enc_key);
1942 if (key->receive_enc_key) {
1943 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1944 silc_free(key->receive_enc_key);
1946 if (key->send_hmac_key) {
1947 memset(key->send_hmac_key, 0, key->hmac_key_len);
1948 silc_free(key->send_hmac_key);
1950 if (key->receive_hmac_key) {
1951 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1952 silc_free(key->receive_hmac_key);
1957 const char *silc_ske_status_string[] =
1961 "Unkown error occurred",
1962 "Bad payload in packet",
1963 "Unsupported group",
1964 "Unsupported cipher",
1966 "Unsupported hash function",
1968 "Unsupported public key (or certificate)",
1969 "Incorrect signature",
1970 "Bad or unsupported version",
1975 "Remote did not provide public key",
1976 "Key exchange protocol is not active",
1977 "Bad reserved field in packet",
1978 "Bad payload length in packet",
1984 /* Maps status to readable string and returns the string. If string is not
1985 found and empty character string ("") is returned. */
1987 const char *silc_ske_map_status(SilcSKEStatus status)
1991 for (i = 0; silc_ske_status_string[i]; i++)
1993 return silc_ske_status_string[i];