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);
73 silc_ske_payload_ke_free(ske->ke2_payload);
78 silc_ske_group_free(ske->prop->group);
80 silc_pkcs_free(ske->prop->pkcs);
81 if (ske->prop->cipher)
82 silc_cipher_free(ske->prop->cipher);
84 silc_hash_free(ske->prop->hash);
86 silc_hmac_free(ske->prop->hmac);
89 if (ske->start_payload_copy)
90 silc_buffer_free(ske->start_payload_copy);
92 silc_mp_uninit(ske->x);
96 silc_mp_uninit(ske->KEY);
100 silc_free(ske->callbacks);
105 /* Sets the callback functions for the SKE session.
107 The `send_packet' callback is a function that sends the packet to
108 network. The SKE library will call it at any time packet needs to
109 be sent to the remote host.
111 The `payload_receive' callback is called when the remote host's Key
112 Exchange Start Payload has been processed. The payload is saved
113 to ske->start_payload if the application would need it. The application
114 must also provide the payload to the next state of the SKE.
116 The `verify_key' callback is called to verify the received public key
117 or certificate. The verification process is most likely asynchronous.
118 That is why the application must call the completion callback when the
119 verification process has been completed. The library then calls the user
120 callback (`proto_continue'), if it is provided to indicate that the SKE
121 protocol may continue.
123 The `proto_continue' callback is called to indicate that it is
124 safe to continue the execution of the SKE protocol after executing
125 an asynchronous operation, such as calling the `verify_key' callback
126 function, which is asynchronous. The application should check the
127 ske->status in this function to check whether it is Ok to continue
128 the execution of the protocol.
130 The `check_version' callback is called to verify the remote host's
131 version. The application may check its own version against the remote
132 host's version and determine whether supporting the remote host
135 The `context' is passed as argument to all of the above callback
138 void silc_ske_set_callbacks(SilcSKE ske,
139 SilcSKESendPacketCb send_packet,
140 SilcSKECb payload_receive,
141 SilcSKEVerifyCb verify_key,
142 SilcSKECb proto_continue,
143 SilcSKECheckVersion check_version,
147 silc_free(ske->callbacks);
148 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
149 ske->callbacks->send_packet = send_packet;
150 ske->callbacks->payload_receive = payload_receive;
151 ske->callbacks->verify_key = verify_key;
152 ske->callbacks->proto_continue = proto_continue;
153 ske->callbacks->check_version = check_version;
154 ske->callbacks->context = context;
157 /* Starts the SILC Key Exchange protocol for initiator. The connection
158 to the remote end must be established before calling this function
159 and the connecting socket must be sent as argument. This function
160 creates the Key Exchange Start Payload which includes all our
161 configured security properties. This payload is then sent to the
162 remote end for further processing. This payload must be sent as
163 argument to the function, however, it must not be encoded
164 already, it is done by this function. The caller must not free
165 the `start_payload' since the SKE library will save it.
167 The packet sending is done by calling a callback function. Caller
168 must provide a routine to send the packet. */
170 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
171 SilcSocketConnection sock,
172 SilcSKEStartPayload *start_payload)
174 SilcSKEStatus status = SILC_SKE_STATUS_OK;
175 SilcBuffer payload_buf;
177 SILC_LOG_DEBUG(("Start"));
182 /* Encode the payload */
183 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
184 if (status != SILC_SKE_STATUS_OK)
187 /* Take a copy of the payload buffer for future use. It is used to
188 compute the HASH value. */
189 ske->start_payload_copy = silc_buffer_copy(payload_buf);
190 ske->start_payload = start_payload;
192 /* Send the packet. */
193 if (ske->callbacks->send_packet)
194 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
195 ske->callbacks->context);
197 silc_buffer_free(payload_buf);
202 /* Function called after ske_initiator_start fuction. This receives
203 the remote ends Key Exchange Start payload which includes the
204 security properties selected by the responder from our payload
205 sent in the silc_ske_initiator_start function. */
207 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
208 SilcBuffer start_payload)
210 SilcSKEStatus status = SILC_SKE_STATUS_OK;
211 SilcSKEStartPayload *payload;
212 SilcSKESecurityProperties prop;
213 SilcSKEDiffieHellmanGroup group;
215 SILC_LOG_DEBUG(("Start"));
217 /* Decode the payload */
218 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
219 if (status != SILC_SKE_STATUS_OK) {
220 ske->status = status;
221 silc_ske_payload_start_free(ske->start_payload);
225 /* Check that the cookie is returned unmodified */
226 if (memcmp(ske->start_payload->cookie, payload->cookie,
227 ske->start_payload->cookie_len)) {
228 SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
229 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
230 silc_ske_payload_start_free(ske->start_payload);
234 /* Check version string */
235 if (ske->callbacks->check_version) {
236 status = ske->callbacks->check_version(ske, payload->version,
237 payload->version_len,
238 ske->callbacks->context);
239 if (status != SILC_SKE_STATUS_OK) {
240 ske->status = status;
241 silc_ske_payload_start_free(ske->start_payload);
246 /* Free our KE Start Payload context, we don't need it anymore. */
247 silc_ske_payload_start_free(ske->start_payload);
249 /* Take the selected security properties into use while doing
250 the key exchange. This is used only while doing the key
251 exchange. The same data is returned to upper levels by calling
252 the callback function. */
253 ske->prop = prop = silc_calloc(1, sizeof(*prop));
254 prop->flags = payload->flags;
255 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
256 if (status != SILC_SKE_STATUS_OK)
261 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
262 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
266 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
267 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
271 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
272 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
276 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
277 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
281 /* Save remote's KE Start Payload */
282 ske->start_payload = payload;
284 /* Return the received payload by calling the callback function. */
285 if (ske->callbacks->payload_receive)
286 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
292 silc_ske_payload_start_free(payload);
294 silc_ske_group_free(group);
297 silc_pkcs_free(prop->pkcs);
299 silc_cipher_free(prop->cipher);
301 silc_hash_free(prop->hash);
303 silc_hmac_free(prop->hmac);
307 if (status == SILC_SKE_STATUS_OK)
308 return SILC_SKE_STATUS_ERROR;
310 ske->status = status;
314 /* This function creates random number x, such that 1 < x < q and
315 computes e = g ^ x mod p and sends the result to the remote end in
316 Key Exchange Payload. */
318 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
319 SilcPublicKey public_key,
320 SilcPrivateKey private_key)
322 SilcSKEStatus status = SILC_SKE_STATUS_OK;
323 SilcBuffer payload_buf;
325 SilcSKEKEPayload *payload;
328 SILC_LOG_DEBUG(("Start"));
330 /* Create the random number x, 1 < x < q. */
331 x = silc_calloc(1, sizeof(*x));
334 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
335 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
337 if (status != SILC_SKE_STATUS_OK) {
340 ske->status = status;
344 /* Encode the result to Key Exchange Payload. */
346 payload = silc_calloc(1, sizeof(*payload));
347 ske->ke1_payload = payload;
349 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
351 /* Do the Diffie Hellman computation, e = g ^ x mod p */
352 silc_mp_init(&payload->x);
353 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
354 &ske->prop->group->group);
358 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
359 if (!payload->pk_data) {
362 silc_mp_uninit(&payload->x);
364 ske->status = SILC_SKE_STATUS_OK;
367 payload->pk_len = pk_len;
369 payload->pk_type = SILC_SKE_PK_TYPE_SILC;
371 /* Compute signature data if we are doing mutual authentication */
372 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
373 unsigned char hash[32], sign[1024];
374 uint32 hash_len, sign_len;
376 SILC_LOG_DEBUG(("We are doing mutual authentication"));
377 SILC_LOG_DEBUG(("Computing HASH_i value"));
379 /* Compute the hash value */
380 memset(hash, 0, sizeof(hash));
381 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
383 SILC_LOG_DEBUG(("Signing HASH_i value"));
385 /* Sign the hash value */
386 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
387 private_key->prv_len);
388 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
389 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
390 memcpy(payload->sign_data, sign, sign_len);
391 memset(sign, 0, sizeof(sign));
392 payload->sign_len = sign_len;
395 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
396 if (status != SILC_SKE_STATUS_OK) {
399 silc_mp_uninit(&payload->x);
400 silc_free(payload->pk_data);
402 ske->status = status;
408 /* Send the packet. */
409 if (ske->callbacks->send_packet)
410 (*ske->callbacks->send_packet)(ske, payload_buf,
411 SILC_PACKET_KEY_EXCHANGE_1,
412 ske->callbacks->context);
414 silc_buffer_free(payload_buf);
419 /* An initiator finish final callback that is called to indicate that
420 the SKE protocol may continue. */
422 static void silc_ske_initiator_finish_final(SilcSKE ske,
423 SilcSKEStatus status,
426 SilcSKEKEPayload *payload;
427 unsigned char hash[32];
429 SilcPublicKey public_key = NULL;
431 /* If the SKE was freed during the async call then free it really now,
432 otherwise just decrement the reference counter. */
433 if (ske->status == SILC_SKE_STATUS_FREED) {
438 /* If the caller returns PENDING status SKE library will assume that
439 the caller will re-call this callback when it is not anymore in
441 if (status == SILC_SKE_STATUS_PENDING)
445 payload = ske->ke2_payload;
447 /* If the status is an error then the public key that was verified
448 by the caller is not authentic. */
449 if (status != SILC_SKE_STATUS_OK) {
450 ske->status = status;
451 if (ske->callbacks->proto_continue)
452 ske->callbacks->proto_continue(ske, ske->callbacks->context);
456 if (payload->pk_data) {
457 /* Decode the public key */
458 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
460 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
461 if (ske->callbacks->proto_continue)
462 ske->callbacks->proto_continue(ske, ske->callbacks->context);
466 SILC_LOG_DEBUG(("Public key is authentic"));
468 /* Compute the hash value */
469 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
470 if (status != SILC_SKE_STATUS_OK)
473 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
474 memcpy(ske->hash, hash, hash_len);
475 ske->hash_len = hash_len;
477 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
479 /* Verify signature */
480 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
481 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
482 payload->sign_len, hash, hash_len) == FALSE) {
484 SILC_LOG_DEBUG(("Signature don't match"));
486 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
490 SILC_LOG_DEBUG(("Signature is Ok"));
492 silc_pkcs_public_key_free(public_key);
493 memset(hash, 'F', hash_len);
496 ske->status = SILC_SKE_STATUS_OK;
498 /* Call the callback. The caller may now continue the SKE protocol. */
499 if (ske->callbacks->proto_continue)
500 ske->callbacks->proto_continue(ske, ske->callbacks->context);
505 memset(hash, 'F', sizeof(hash));
506 silc_ske_payload_ke_free(payload);
507 ske->ke2_payload = NULL;
509 silc_mp_uninit(ske->KEY);
514 silc_pkcs_public_key_free(public_key);
517 memset(ske->hash, 'F', hash_len);
518 silc_free(ske->hash);
522 if (status == SILC_SKE_STATUS_OK)
523 ske->status = SILC_SKE_STATUS_ERROR;
525 ske->status = status;
527 /* Call the callback. */
528 if (ske->callbacks->proto_continue)
529 ske->callbacks->proto_continue(ske, ske->callbacks->context);
532 /* Receives Key Exchange Payload from responder consisting responders
533 public key, f, and signature. This function verifies the public key,
534 computes the secret shared key and verifies the signature.
536 The `callback' will be called to indicate that the caller may
537 continue with the SKE protocol. The caller must not continue
538 before the SKE libary has called that callback. If this function
539 returns an error the callback will not be called. It is called
540 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
541 However, note that when the library calls the callback the ske->status
544 This calls the `verify_key' callback to verify the received public
545 key or certificate. If the `verify_key' is provided then the remote
546 must send public key and it is considered to be an error if remote
547 does not send its public key. If caller is performing a re-key with
548 SKE then the `verify_key' is usually not provided when it is not also
549 required for the remote to send its public key. */
551 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
552 SilcBuffer ke_payload)
554 SilcSKEStatus status = SILC_SKE_STATUS_OK;
555 SilcSKEKEPayload *payload;
558 SILC_LOG_DEBUG(("Start"));
560 /* Decode the payload */
561 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
562 if (status != SILC_SKE_STATUS_OK) {
563 ske->status = status;
566 ske->ke2_payload = payload;
568 if (!payload->pk_data && ske->callbacks->verify_key) {
569 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
570 "even though we require it"));
571 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
575 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
577 /* Compute the shared secret key */
578 KEY = silc_calloc(1, sizeof(*KEY));
580 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
583 if (payload->pk_data && ske->callbacks->verify_key) {
584 SILC_LOG_DEBUG(("Verifying public key"));
587 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
588 payload->pk_type, ske->callbacks->context,
589 silc_ske_initiator_finish_final, NULL);
591 /* We will continue to the final state after the public key has
592 been verified by the caller. */
593 return SILC_SKE_STATUS_PENDING;
596 /* Continue to final state */
598 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
600 return SILC_SKE_STATUS_OK;
603 silc_ske_payload_ke_free(payload);
604 ske->ke2_payload = NULL;
606 silc_mp_uninit(ske->KEY);
610 if (status == SILC_SKE_STATUS_OK)
611 return SILC_SKE_STATUS_ERROR;
613 ske->status = status;
617 /* Starts Key Exchange protocol for responder. Responder receives
618 Key Exchange Start Payload from initiator consisting of all the
619 security properties the initiator supports. This function decodes
620 the payload and parses the payload further and selects the right
621 security properties. */
623 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
624 SilcSocketConnection sock,
626 SilcBuffer start_payload,
627 SilcSKESecurityPropertyFlag flags)
629 SilcSKEStatus status = SILC_SKE_STATUS_OK;
630 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
632 SILC_LOG_DEBUG(("Start"));
637 /* Decode the payload */
638 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
639 if (status != SILC_SKE_STATUS_OK) {
640 ske->status = status;
644 /* Take a copy of the payload buffer for future use. It is used to
645 compute the HASH value. */
646 ske->start_payload_copy = silc_buffer_copy(start_payload);
648 /* Force the mutual authentication flag if we want to do it. */
649 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
650 SILC_LOG_DEBUG(("Force mutual authentication"));
651 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
654 /* Force PFS flag if we require it */
655 if (flags & SILC_SKE_SP_FLAG_PFS) {
656 SILC_LOG_DEBUG(("Force PFS"));
657 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
660 /* Parse and select the security properties from the payload */
661 payload = silc_calloc(1, sizeof(*payload));
662 status = silc_ske_select_security_properties(ske, version,
663 payload, remote_payload);
664 if (status != SILC_SKE_STATUS_OK)
667 ske->start_payload = payload;
669 /* Call the callback function. */
670 if (ske->callbacks->payload_receive)
671 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
673 silc_ske_payload_start_free(remote_payload);
679 silc_ske_payload_start_free(remote_payload);
683 if (status == SILC_SKE_STATUS_OK)
684 return SILC_SKE_STATUS_ERROR;
686 ske->status = status;
690 /* The selected security properties from the initiator payload is now
691 encoded into Key Exchange Start Payload and sent to the initiator. */
693 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
694 SilcSKEStartPayload *start_payload)
696 SilcSKEStatus status = SILC_SKE_STATUS_OK;
697 SilcBuffer payload_buf;
698 SilcSKESecurityProperties prop;
699 SilcSKEDiffieHellmanGroup group = NULL;
701 SILC_LOG_DEBUG(("Start"));
703 /* Allocate security properties from the payload. These are allocated
704 only for this negotiation and will be free'd after KE is over. */
705 ske->prop = prop = silc_calloc(1, sizeof(*prop));
706 prop->flags = start_payload->flags;
707 status = silc_ske_group_get_by_name(start_payload->ke_grp_list, &group);
708 if (status != SILC_SKE_STATUS_OK)
713 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
714 &prop->pkcs) == FALSE) {
715 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
719 if (silc_cipher_alloc(start_payload->enc_alg_list,
720 &prop->cipher) == FALSE) {
721 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
725 if (silc_hash_alloc(start_payload->hash_alg_list,
726 &prop->hash) == FALSE) {
727 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
731 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
732 &prop->hmac) == FALSE) {
733 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
737 /* Encode the payload */
738 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
739 if (status != SILC_SKE_STATUS_OK)
742 /* Send the packet. */
743 if (ske->callbacks->send_packet)
744 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
745 ske->callbacks->context);
747 silc_buffer_free(payload_buf);
753 silc_ske_group_free(group);
756 silc_pkcs_free(prop->pkcs);
758 silc_cipher_free(prop->cipher);
760 silc_hash_free(prop->hash);
762 silc_hmac_free(prop->hmac);
766 if (status == SILC_SKE_STATUS_OK)
767 return SILC_SKE_STATUS_ERROR;
769 ske->status = status;
773 /* An responder phase 2 final callback that is called to indicate that
774 the SKE protocol may continue. */
776 static void silc_ske_responder_phase2_final(SilcSKE ske,
777 SilcSKEStatus status,
780 SilcSKEKEPayload *recv_payload, *send_payload;
783 /* If the SKE was freed during the async call then free it really now,
784 otherwise just decrement the reference counter. */
785 if (ske->status == SILC_SKE_STATUS_FREED) {
790 /* If the caller returns PENDING status SKE library will assume that
791 the caller will re-call this callback when it is not anymore in
793 if (status == SILC_SKE_STATUS_PENDING)
797 recv_payload = ske->ke1_payload;
799 /* If the status is an error then the public key that was verified
800 by the caller is not authentic. */
801 if (status != SILC_SKE_STATUS_OK) {
802 ske->status = status;
803 if (ske->callbacks->proto_continue)
804 ske->callbacks->proto_continue(ske, ske->callbacks->context);
808 /* The public key verification was performed only if the Mutual
809 Authentication flag is set. */
810 if (ske->start_payload &&
811 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
812 SilcPublicKey public_key = NULL;
813 unsigned char hash[32];
816 /* Decode the public key */
817 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
818 recv_payload->pk_len,
820 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
821 if (ske->callbacks->proto_continue)
822 ske->callbacks->proto_continue(ske, ske->callbacks->context);
826 SILC_LOG_DEBUG(("Public key is authentic"));
828 /* Compute the hash value */
829 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
830 if (status != SILC_SKE_STATUS_OK) {
831 ske->status = status;
832 if (ske->callbacks->proto_continue)
833 ske->callbacks->proto_continue(ske, ske->callbacks->context);
837 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
839 /* Verify signature */
840 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
841 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
842 recv_payload->sign_len, hash, hash_len) == FALSE) {
844 SILC_LOG_DEBUG(("Signature don't match"));
846 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
847 if (ske->callbacks->proto_continue)
848 ske->callbacks->proto_continue(ske, ske->callbacks->context);
852 SILC_LOG_DEBUG(("Signature is Ok"));
854 silc_pkcs_public_key_free(public_key);
855 memset(hash, 'F', hash_len);
858 /* Create the random number x, 1 < x < q. */
859 x = silc_calloc(1, sizeof(*x));
862 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
863 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
865 if (status != SILC_SKE_STATUS_OK) {
868 ske->status = status;
869 if (ske->callbacks->proto_continue)
870 ske->callbacks->proto_continue(ske, ske->callbacks->context);
874 /* Save the results for later processing */
875 send_payload = silc_calloc(1, sizeof(*send_payload));
877 ske->ke2_payload = send_payload;
879 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
881 /* Do the Diffie Hellman computation, f = g ^ x mod p */
882 silc_mp_init(&send_payload->x);
883 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
884 &ske->prop->group->group);
886 /* Call the callback. The caller may now continue with the SKE protocol. */
887 ske->status = SILC_SKE_STATUS_OK;
888 if (ske->callbacks->proto_continue)
889 ske->callbacks->proto_continue(ske, ske->callbacks->context);
892 /* This function receives the Key Exchange Payload from the initiator.
893 This also performs the mutual authentication if required. Then, this
894 function first generated a random number x, such that 1 < x < q
895 and computes f = g ^ x mod p. This then puts the result f to a Key
898 The `callback' will be called to indicate that the caller may
899 continue with the SKE protocol. The caller must not continue
900 before the SKE libary has called that callback. If this function
901 returns an error the callback will not be called. It is called
902 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
903 However, note that when the library calls the callback the ske->status
906 This calls the `verify_key' callback to verify the received public
907 key or certificate if the Mutual Authentication flag is set. If the
908 `verify_key' is provided then the remote must send public key and it
909 is considered to be an error if remote does not send its public key. */
911 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
912 SilcBuffer ke_payload)
914 SilcSKEStatus status = SILC_SKE_STATUS_OK;
915 SilcSKEKEPayload *recv_payload;
917 SILC_LOG_DEBUG(("Start"));
919 /* Decode Key Exchange Payload */
920 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
921 if (status != SILC_SKE_STATUS_OK) {
922 ske->status = status;
926 ske->ke1_payload = recv_payload;
928 /* Verify the received public key and verify the signature if we are
929 doing mutual authentication. */
930 if (ske->start_payload &&
931 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
933 SILC_LOG_DEBUG(("We are doing mutual authentication"));
935 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
936 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
937 "certificate), even though we require it"));
938 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
942 if (recv_payload->pk_data && ske->callbacks->verify_key) {
943 SILC_LOG_DEBUG(("Verifying public key"));
946 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
947 recv_payload->pk_len,
948 recv_payload->pk_type,
949 ske->callbacks->context,
950 silc_ske_responder_phase2_final, NULL);
952 /* We will continue to the final state after the public key has
953 been verified by the caller. */
954 return SILC_SKE_STATUS_PENDING;
958 /* Continue to final state */
960 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
962 return SILC_SKE_STATUS_OK;
965 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
966 value to be signed and sent to the other end. This then encodes Key
967 Exchange Payload and sends it to the other end. */
969 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
970 SilcPublicKey public_key,
971 SilcPrivateKey private_key,
972 SilcSKEPKType pk_type)
974 SilcSKEStatus status = SILC_SKE_STATUS_OK;
975 SilcBuffer payload_buf;
977 unsigned char hash[32], sign[1024], *pk;
978 uint32 hash_len, sign_len, pk_len;
980 SILC_LOG_DEBUG(("Start"));
982 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
984 /* Compute the shared secret key */
985 KEY = silc_calloc(1, sizeof(*KEY));
987 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
988 &ske->prop->group->group);
991 if (public_key && private_key) {
992 SILC_LOG_DEBUG(("Getting public key"));
994 /* Get the public key */
995 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
997 status = SILC_SKE_STATUS_ERROR;
1000 ske->ke2_payload->pk_data = pk;
1001 ske->ke2_payload->pk_len = pk_len;
1003 SILC_LOG_DEBUG(("Computing HASH value"));
1005 /* Compute the hash value */
1006 memset(hash, 0, sizeof(hash));
1007 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1008 if (status != SILC_SKE_STATUS_OK)
1011 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1012 memcpy(ske->hash, hash, hash_len);
1013 ske->hash_len = hash_len;
1015 SILC_LOG_DEBUG(("Signing HASH value"));
1017 /* Sign the hash value */
1018 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1019 private_key->prv_len);
1020 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1021 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1022 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1023 memset(sign, 0, sizeof(sign));
1024 ske->ke2_payload->sign_len = sign_len;
1026 ske->ke2_payload->pk_type = pk_type;
1028 /* Encode the Key Exchange Payload */
1029 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1031 if (status != SILC_SKE_STATUS_OK)
1034 /* Send the packet. */
1035 if (ske->callbacks->send_packet)
1036 (*ske->callbacks->send_packet)(ske, payload_buf,
1037 SILC_PACKET_KEY_EXCHANGE_2,
1038 ske->callbacks->context);
1040 silc_buffer_free(payload_buf);
1045 silc_mp_uninit(ske->KEY);
1046 silc_free(ske->KEY);
1048 silc_ske_payload_ke_free(ske->ke2_payload);
1050 if (status == SILC_SKE_STATUS_OK)
1051 return SILC_SKE_STATUS_ERROR;
1053 ske->status = status;
1057 /* The Key Exchange protocol is ended by calling this function. This
1058 must not be called until the keys are processed like the protocol
1059 defines. This function is for both initiator and responder. */
1061 SilcSKEStatus silc_ske_end(SilcSKE ske)
1065 SILC_LOG_DEBUG(("Start"));
1067 packet = silc_buffer_alloc(4);
1068 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1069 silc_buffer_format(packet,
1070 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
1073 if (ske->callbacks->send_packet)
1074 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1075 ske->callbacks->context);
1077 silc_buffer_free(packet);
1079 return SILC_SKE_STATUS_OK;
1082 /* Aborts the Key Exchange protocol. This is called if error occurs
1083 while performing the protocol. The status argument is the error
1084 status and it is sent to the remote end. */
1086 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1090 SILC_LOG_DEBUG(("Start"));
1092 packet = silc_buffer_alloc(4);
1093 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1094 silc_buffer_format(packet,
1095 SILC_STR_UI_INT((uint32)status),
1098 if (ske->callbacks->send_packet)
1099 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1100 ske->callbacks->context);
1102 silc_buffer_free(packet);
1104 return SILC_SKE_STATUS_OK;
1107 /* Assembles security properties to Key Exchange Start Payload to be
1108 sent to the remote end. This checks system wide (SILC system, that is)
1109 settings and chooses from those. However, if other properties
1110 should be used this function is easy to replace by another function,
1111 as, this function is called by the caller of the protocol and not
1112 by the protocol itself. */
1115 silc_ske_assemble_security_properties(SilcSKE ske,
1116 SilcSKESecurityPropertyFlag flags,
1118 SilcSKEStartPayload **return_payload)
1120 SilcSKEStartPayload *rp;
1123 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1125 rp = silc_calloc(1, sizeof(*rp));
1130 /* Set random cookie */
1131 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1132 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1133 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1134 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1137 rp->version = strdup(version);
1138 rp->version_len = strlen(version);
1140 /* Get supported Key Exhange groups */
1141 rp->ke_grp_list = silc_ske_get_supported_groups();
1142 rp->ke_grp_len = strlen(rp->ke_grp_list);
1144 /* Get supported PKCS algorithms */
1145 rp->pkcs_alg_list = silc_pkcs_get_supported();
1146 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1148 /* Get supported encryption algorithms */
1149 rp->enc_alg_list = silc_cipher_get_supported();
1150 rp->enc_alg_len = strlen(rp->enc_alg_list);
1152 /* Get supported hash algorithms */
1153 rp->hash_alg_list = silc_hash_get_supported();
1154 rp->hash_alg_len = strlen(rp->hash_alg_list);
1156 /* Get supported HMACs */
1157 rp->hmac_alg_list = silc_hmac_get_supported();
1158 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1161 /* Get supported compression algorithms */
1162 rp->comp_alg_list = strdup("");
1163 rp->comp_alg_len = 0;
1165 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1166 2 + rp->version_len +
1167 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1168 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1169 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1171 *return_payload = rp;
1173 return SILC_SKE_STATUS_OK;
1176 /* Selects the supported security properties from the remote end's Key
1177 Exchange Start Payload. */
1180 silc_ske_select_security_properties(SilcSKE ske,
1182 SilcSKEStartPayload *payload,
1183 SilcSKEStartPayload *remote_payload)
1185 SilcSKEStatus status;
1186 SilcSKEStartPayload *rp;
1190 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1192 rp = remote_payload;
1194 /* Check version string */
1195 if (ske->callbacks->check_version) {
1196 status = ske->callbacks->check_version(ske, rp->version,
1198 ske->callbacks->context);
1199 if (status != SILC_SKE_STATUS_OK) {
1200 ske->status = status;
1205 /* Flags are returned unchanged. */
1206 payload->flags = rp->flags;
1208 /* Take cookie, we must return it to sender unmodified. */
1209 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1210 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1211 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1213 /* Put our version to our reply */
1214 payload->version = strdup(version);
1215 payload->version_len = strlen(version);
1217 /* Get supported Key Exchange groups */
1218 cp = rp->ke_grp_list;
1219 if (cp && strchr(cp, ',')) {
1223 len = strcspn(cp, ",");
1224 item = silc_calloc(len + 1, sizeof(char));
1225 memcpy(item, cp, len);
1227 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1229 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1230 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1232 payload->ke_grp_len = len;
1233 payload->ke_grp_list = item;
1238 if (strlen(cp) == 0)
1247 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1248 SILC_LOG_DEBUG(("Could not find supported KE group"));
1250 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1254 if (!rp->ke_grp_len) {
1255 SILC_LOG_DEBUG(("KE group not defined in payload"));
1257 return SILC_SKE_STATUS_BAD_PAYLOAD;
1260 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1261 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1263 payload->ke_grp_len = rp->ke_grp_len;
1264 payload->ke_grp_list = strdup(rp->ke_grp_list);
1267 /* Get supported PKCS algorithms */
1268 cp = rp->pkcs_alg_list;
1269 if (cp && strchr(cp, ',')) {
1273 len = strcspn(cp, ",");
1274 item = silc_calloc(len + 1, sizeof(char));
1275 memcpy(item, cp, len);
1277 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1279 if (silc_pkcs_is_supported(item) == TRUE) {
1280 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1282 payload->pkcs_alg_len = len;
1283 payload->pkcs_alg_list = item;
1288 if (strlen(cp) == 0)
1297 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1298 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1299 silc_free(payload->ke_grp_list);
1301 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1305 if (!rp->pkcs_alg_len) {
1306 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1307 silc_free(payload->ke_grp_list);
1309 return SILC_SKE_STATUS_BAD_PAYLOAD;
1312 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1313 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1315 payload->pkcs_alg_len = rp->pkcs_alg_len;
1316 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1319 /* Get supported encryption algorithms */
1320 cp = rp->enc_alg_list;
1321 if (cp && strchr(cp, ',')) {
1325 len = strcspn(cp, ",");
1326 item = silc_calloc(len + 1, sizeof(char));
1327 memcpy(item, cp, len);
1329 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1331 if (silc_cipher_is_supported(item) == TRUE) {
1332 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1334 payload->enc_alg_len = len;
1335 payload->enc_alg_list = item;
1340 if (strlen(cp) == 0)
1349 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1350 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1351 silc_free(payload->ke_grp_list);
1352 silc_free(payload->pkcs_alg_list);
1354 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1358 if (!rp->enc_alg_len) {
1359 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1360 silc_free(payload->ke_grp_list);
1361 silc_free(payload->pkcs_alg_list);
1363 return SILC_SKE_STATUS_BAD_PAYLOAD;
1366 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1369 payload->enc_alg_len = rp->enc_alg_len;
1370 payload->enc_alg_list = strdup(rp->enc_alg_list);
1373 /* Get supported hash algorithms */
1374 cp = rp->hash_alg_list;
1375 if (cp && strchr(cp, ',')) {
1379 len = strcspn(cp, ",");
1380 item = silc_calloc(len + 1, sizeof(char));
1381 memcpy(item, cp, len);
1383 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1385 if (silc_hash_is_supported(item) == TRUE) {
1386 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1388 payload->hash_alg_len = len;
1389 payload->hash_alg_list = item;
1394 if (strlen(cp) == 0)
1403 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1404 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1405 silc_free(payload->ke_grp_list);
1406 silc_free(payload->pkcs_alg_list);
1407 silc_free(payload->enc_alg_list);
1409 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1413 if (!rp->hash_alg_len) {
1414 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1415 silc_free(payload->ke_grp_list);
1416 silc_free(payload->pkcs_alg_list);
1417 silc_free(payload->enc_alg_list);
1419 return SILC_SKE_STATUS_BAD_PAYLOAD;
1422 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1423 rp->hash_alg_list));
1425 payload->hash_alg_len = rp->hash_alg_len;
1426 payload->hash_alg_list = strdup(rp->hash_alg_list);
1429 /* Get supported HMACs */
1430 cp = rp->hmac_alg_list;
1431 if (cp && strchr(cp, ',')) {
1435 len = strcspn(cp, ",");
1436 item = silc_calloc(len + 1, sizeof(char));
1437 memcpy(item, cp, len);
1439 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1441 if (silc_hmac_is_supported(item) == TRUE) {
1442 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1444 payload->hmac_alg_len = len;
1445 payload->hmac_alg_list = item;
1450 if (strlen(cp) == 0)
1459 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1460 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1461 silc_free(payload->ke_grp_list);
1462 silc_free(payload->pkcs_alg_list);
1463 silc_free(payload->enc_alg_list);
1464 silc_free(payload->hash_alg_list);
1466 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1470 if (!rp->hmac_alg_len) {
1471 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1472 silc_free(payload->ke_grp_list);
1473 silc_free(payload->pkcs_alg_list);
1474 silc_free(payload->enc_alg_list);
1475 silc_free(payload->hash_alg_list);
1477 return SILC_SKE_STATUS_BAD_PAYLOAD;
1480 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1481 rp->hmac_alg_list));
1483 payload->hmac_alg_len = rp->hmac_alg_len;
1484 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1488 /* Get supported compression algorithms */
1489 cp = rp->hash_alg_list;
1490 if (cp && strchr(cp, ',')) {
1494 len = strcspn(cp, ",");
1495 item = silc_calloc(len + 1, sizeof(char));
1496 memcpy(item, cp, len);
1498 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1500 if (silc_hash_is_supported(item) == TRUE) {
1501 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1503 payload->hash_alg_len = len;
1504 payload->hash_alg_list = item;
1509 if (strlen(cp) == 0)
1518 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1519 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1520 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1521 silc_free(payload->ke_grp_list);
1522 silc_free(payload->pkcs_alg_list);
1523 silc_free(payload->enc_alg_list);
1532 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1533 2 + payload->version_len +
1534 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1535 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1536 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1538 return SILC_SKE_STATUS_OK;
1541 /* Creates random number such that 1 < rnd < n and at most length
1542 of len bits. The rnd sent as argument must be initialized. */
1544 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1548 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1549 unsigned char *string;
1551 SILC_LOG_DEBUG(("Creating random number"));
1553 /* Get the random number as string */
1554 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1556 return SILC_SKE_STATUS_ERROR;
1558 /* Decode the string into a MP integer */
1559 silc_mp_bin2mp(string, (len / 8), rnd);
1560 silc_mp_mod_2exp(rnd, rnd, len);
1563 if (silc_mp_cmp_ui(rnd, 1) < 0)
1564 status = SILC_SKE_STATUS_ERROR;
1566 if (silc_mp_cmp(rnd, n) >= 0)
1567 status = SILC_SKE_STATUS_ERROR;
1569 memset(string, 'F', (len / 8));
1575 /* Creates a hash value HASH as defined in the SKE protocol. If the
1576 `initiator' is TRUE then this function is used to create the HASH_i
1577 hash value defined in the protocol. If it is FALSE then this is used
1578 to create the HASH value defined by the protocol. */
1580 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1581 unsigned char *return_hash,
1582 uint32 *return_hash_len,
1585 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1587 unsigned char *e, *f, *KEY;
1588 uint32 e_len, f_len, KEY_len;
1591 SILC_LOG_DEBUG(("Start"));
1593 if (initiator == FALSE) {
1594 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1595 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1596 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1598 /* Format the buffer used to compute the hash value */
1599 /* XXX Backward support for 0.6.1 */
1600 if (ske->backward_version == 1) {
1601 SILC_LOG_DEBUG(("*********** Using old KE payload"));
1602 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1603 ske->ke2_payload->pk_len + e_len +
1605 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1608 silc_buffer_format(buf,
1609 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1610 ske->start_payload_copy->len),
1611 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1612 ske->ke2_payload->pk_len),
1613 SILC_STR_UI_XNSTRING(e, e_len),
1614 SILC_STR_UI_XNSTRING(f, f_len),
1615 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1618 /* Initiator is not required to send its public key */
1619 SILC_LOG_DEBUG(("*********** Using new KE payload"));
1620 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1621 ske->ke2_payload->pk_len +
1622 ske->ke1_payload->pk_len +
1623 e_len + f_len + KEY_len);
1624 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1626 if (!ske->ke1_payload->pk_data) {
1628 silc_buffer_format(buf,
1629 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1631 ske->start_payload_copy->
1633 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1634 ske->ke2_payload->pk_len),
1635 SILC_STR_UI_XNSTRING(e, e_len),
1636 SILC_STR_UI_XNSTRING(f, f_len),
1637 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1641 silc_buffer_format(buf,
1642 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1644 ske->start_payload_copy->
1646 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1647 ske->ke2_payload->pk_len),
1648 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1649 ske->ke1_payload->pk_len),
1650 SILC_STR_UI_XNSTRING(e, e_len),
1651 SILC_STR_UI_XNSTRING(f, f_len),
1652 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1657 silc_buffer_free(buf);
1658 memset(e, 0, e_len);
1659 memset(f, 0, f_len);
1660 memset(KEY, 0, KEY_len);
1664 return SILC_SKE_STATUS_ERROR;
1667 memset(e, 0, e_len);
1668 memset(f, 0, f_len);
1669 memset(KEY, 0, KEY_len);
1674 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1676 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1677 ske->ke1_payload->pk_len + e_len);
1678 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1680 /* Format the buffer used to compute the hash value */
1682 silc_buffer_format(buf,
1683 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1684 ske->start_payload_copy->len),
1685 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1686 ske->ke1_payload->pk_len),
1687 SILC_STR_UI_XNSTRING(e, e_len),
1690 silc_buffer_free(buf);
1691 memset(e, 0, e_len);
1693 return SILC_SKE_STATUS_ERROR;
1696 memset(e, 0, e_len);
1701 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1702 *return_hash_len = ske->prop->hash->hash->hash_len;
1704 if (initiator == FALSE) {
1705 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1707 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1710 silc_buffer_free(buf);
1715 /* Processes the provided key material `data' as the SILC protocol
1716 specification defines. */
1719 silc_ske_process_key_material_data(unsigned char *data,
1722 uint32 req_enc_key_len,
1723 uint32 req_hmac_key_len,
1725 SilcSKEKeyMaterial *key)
1728 unsigned char hashd[32];
1729 uint32 hash_len = req_hmac_key_len;
1730 uint32 enc_key_len = req_enc_key_len / 8;
1732 SILC_LOG_DEBUG(("Start"));
1734 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1735 return SILC_SKE_STATUS_ERROR;
1737 buf = silc_buffer_alloc(1 + data_len);
1738 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1739 silc_buffer_format(buf,
1740 SILC_STR_UI_CHAR(0),
1741 SILC_STR_UI_XNSTRING(data, data_len),
1745 memset(hashd, 0, sizeof(hashd));
1747 silc_hash_make(hash, buf->data, buf->len, hashd);
1748 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1749 memcpy(key->send_iv, hashd, req_iv_len);
1750 memset(hashd, 0, sizeof(hashd));
1752 silc_hash_make(hash, buf->data, buf->len, hashd);
1753 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1754 memcpy(key->receive_iv, hashd, req_iv_len);
1755 key->iv_len = req_iv_len;
1757 /* Take the encryption keys. If requested key size is more than
1758 the size of hash length we will distribute more key material
1759 as protocol defines. */
1761 if (enc_key_len > hash_len) {
1763 unsigned char k1[32], k2[32], k3[32];
1764 unsigned char *dtmp;
1767 if (enc_key_len > (3 * hash_len))
1768 return SILC_SKE_STATUS_ERROR;
1770 /* Take first round */
1771 memset(k1, 0, sizeof(k1));
1772 silc_hash_make(hash, buf->data, buf->len, k1);
1774 /* Take second round */
1775 dist = silc_buffer_alloc(data_len + hash_len);
1776 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1777 silc_buffer_format(dist,
1778 SILC_STR_UI_XNSTRING(data, data_len),
1779 SILC_STR_UI_XNSTRING(k1, hash_len),
1781 memset(k2, 0, sizeof(k2));
1782 silc_hash_make(hash, dist->data, dist->len, k2);
1784 /* Take third round */
1785 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1786 silc_buffer_pull_tail(dist, hash_len);
1787 silc_buffer_pull(dist, data_len + hash_len);
1788 silc_buffer_format(dist,
1789 SILC_STR_UI_XNSTRING(k2, hash_len),
1791 silc_buffer_push(dist, data_len + hash_len);
1792 memset(k3, 0, sizeof(k3));
1793 silc_hash_make(hash, dist->data, dist->len, k3);
1795 /* Then, save the keys */
1796 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1797 memcpy(dtmp, k1, hash_len);
1798 memcpy(dtmp + hash_len, k2, hash_len);
1799 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1801 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1802 memcpy(key->send_enc_key, dtmp, enc_key_len);
1803 key->enc_key_len = req_enc_key_len;
1805 memset(dtmp, 0, (3 * hash_len));
1806 memset(k1, 0, sizeof(k1));
1807 memset(k2, 0, sizeof(k2));
1808 memset(k3, 0, sizeof(k3));
1810 silc_buffer_free(dist);
1812 /* Take normal hash as key */
1813 memset(hashd, 0, sizeof(hashd));
1814 silc_hash_make(hash, buf->data, buf->len, hashd);
1815 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1816 memcpy(key->send_enc_key, hashd, enc_key_len);
1817 key->enc_key_len = req_enc_key_len;
1821 if (enc_key_len > hash_len) {
1823 unsigned char k1[32], k2[32], k3[32];
1824 unsigned char *dtmp;
1827 if (enc_key_len > (3 * hash_len))
1828 return SILC_SKE_STATUS_ERROR;
1830 /* Take first round */
1831 memset(k1, 0, sizeof(k1));
1832 silc_hash_make(hash, buf->data, buf->len, k1);
1834 /* Take second round */
1835 dist = silc_buffer_alloc(data_len + hash_len);
1836 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1837 silc_buffer_format(dist,
1838 SILC_STR_UI_XNSTRING(data, data_len),
1839 SILC_STR_UI_XNSTRING(k1, hash_len),
1841 memset(k2, 0, sizeof(k2));
1842 silc_hash_make(hash, dist->data, dist->len, k2);
1844 /* Take third round */
1845 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1846 silc_buffer_pull_tail(dist, hash_len);
1847 silc_buffer_pull(dist, data_len + hash_len);
1848 silc_buffer_format(dist,
1849 SILC_STR_UI_XNSTRING(k2, hash_len),
1851 silc_buffer_push(dist, data_len + hash_len);
1852 memset(k3, 0, sizeof(k3));
1853 silc_hash_make(hash, dist->data, dist->len, k3);
1855 /* Then, save the keys */
1856 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1857 memcpy(dtmp, k1, hash_len);
1858 memcpy(dtmp + hash_len, k2, hash_len);
1859 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1861 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1862 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1863 key->enc_key_len = req_enc_key_len;
1865 memset(dtmp, 0, (3 * hash_len));
1866 memset(k1, 0, sizeof(k1));
1867 memset(k2, 0, sizeof(k2));
1868 memset(k3, 0, sizeof(k3));
1870 silc_buffer_free(dist);
1872 /* Take normal hash as key */
1873 memset(hashd, 0, sizeof(hashd));
1874 silc_hash_make(hash, buf->data, buf->len, hashd);
1875 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1876 memcpy(key->receive_enc_key, hashd, enc_key_len);
1877 key->enc_key_len = req_enc_key_len;
1880 /* Take HMAC keys */
1881 memset(hashd, 0, sizeof(hashd));
1883 silc_hash_make(hash, buf->data, buf->len, hashd);
1884 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1885 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1886 memset(hashd, 0, sizeof(hashd));
1888 silc_hash_make(hash, buf->data, buf->len, hashd);
1889 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1890 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1891 key->hmac_key_len = req_hmac_key_len;
1892 memset(hashd, 0, sizeof(hashd));
1894 silc_buffer_free(buf);
1896 return SILC_SKE_STATUS_OK;
1899 /* Processes negotiated key material as protocol specifies. This returns
1900 the actual keys to be used in the SILC. */
1902 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1904 uint32 req_enc_key_len,
1905 uint32 req_hmac_key_len,
1906 SilcSKEKeyMaterial *key)
1908 SilcSKEStatus status;
1910 unsigned char *tmpbuf;
1913 /* Encode KEY to binary data */
1914 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1916 buf = silc_buffer_alloc(klen + ske->hash_len);
1917 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1918 silc_buffer_format(buf,
1919 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1920 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1923 /* Process the key material */
1924 status = silc_ske_process_key_material_data(buf->data, buf->len,
1925 req_iv_len, req_enc_key_len,
1927 ske->prop->hash, key);
1929 memset(tmpbuf, 0, klen);
1931 silc_buffer_free(buf);
1936 /* Free key material structure */
1938 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1944 silc_free(key->send_iv);
1945 if (key->receive_iv)
1946 silc_free(key->receive_iv);
1947 if (key->send_enc_key) {
1948 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1949 silc_free(key->send_enc_key);
1951 if (key->receive_enc_key) {
1952 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1953 silc_free(key->receive_enc_key);
1955 if (key->send_hmac_key) {
1956 memset(key->send_hmac_key, 0, key->hmac_key_len);
1957 silc_free(key->send_hmac_key);
1959 if (key->receive_hmac_key) {
1960 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1961 silc_free(key->receive_hmac_key);
1966 const char *silc_ske_status_string[] =
1970 "Unkown error occurred",
1971 "Bad payload in packet",
1972 "Unsupported group",
1973 "Unsupported cipher",
1975 "Unsupported hash function",
1977 "Unsupported public key (or certificate)",
1978 "Incorrect signature",
1979 "Bad or unsupported version",
1984 "Remote did not provide public key",
1985 "Key exchange protocol is not active",
1986 "Bad reserved field in packet",
1987 "Bad payload length in packet",
1993 /* Maps status to readable string and returns the string. If string is not
1994 found and empty character string ("") is returned. */
1996 const char *silc_ske_map_status(SilcSKEStatus status)
2000 for (i = 0; silc_ske_status_string[i]; i++)
2002 return silc_ske_status_string[i];