5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 #include "groups_internal.h"
25 /* Static functions */
26 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
29 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
30 unsigned char *return_hash,
31 SilcUInt32 *return_hash_len,
34 /* Structure to hold all SKE callbacks. */
35 struct SilcSKECallbacksStruct {
36 SilcSKESendPacketCb send_packet;
37 SilcSKECb payload_receive;
38 SilcSKEVerifyCb verify_key;
39 SilcSKECb proto_continue;
40 SilcSKECheckVersion check_version;
44 /* Allocates new SKE object. */
46 SilcSKE silc_ske_alloc(SilcRng rng, void *context)
50 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
52 ske = silc_calloc(1, sizeof(*ske));
53 ske->status = SILC_SKE_STATUS_OK;
55 ske->user_data = context;
61 /* Free's SKE object. */
63 void silc_ske_free(SilcSKE ske)
67 SILC_LOG_DEBUG(("Key Exchange set to FREED status"));
68 ske->status = SILC_SKE_STATUS_FREED;
72 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
75 /* Free start payload */
76 if (ske->start_payload)
77 silc_ske_payload_start_free(ske->start_payload);
81 silc_ske_payload_ke_free(ske->ke1_payload);
83 silc_ske_payload_ke_free(ske->ke2_payload);
84 silc_free(ske->remote_version);
89 silc_ske_group_free(ske->prop->group);
91 silc_pkcs_free(ske->prop->pkcs);
92 if (ske->prop->cipher)
93 silc_cipher_free(ske->prop->cipher);
95 silc_hash_free(ske->prop->hash);
97 silc_hmac_free(ske->prop->hmac);
100 if (ske->start_payload_copy)
101 silc_buffer_free(ske->start_payload_copy);
103 silc_mp_uninit(ske->x);
107 silc_mp_uninit(ske->KEY);
110 silc_free(ske->hash);
111 silc_free(ske->callbacks);
116 /* Sets the callback functions for the SKE session.
118 The `send_packet' callback is a function that sends the packet to
119 network. The SKE library will call it at any time packet needs to
120 be sent to the remote host.
122 The `payload_receive' callback is called when the remote host's Key
123 Exchange Start Payload has been processed. The payload is saved
124 to ske->start_payload if the application would need it. The application
125 must also provide the payload to the next state of the SKE.
127 The `verify_key' callback is called to verify the received public key
128 or certificate. The verification process is most likely asynchronous.
129 That is why the application must call the completion callback when the
130 verification process has been completed. The library then calls the user
131 callback (`proto_continue'), if it is provided to indicate that the SKE
132 protocol may continue.
134 The `proto_continue' callback is called to indicate that it is
135 safe to continue the execution of the SKE protocol after executing
136 an asynchronous operation, such as calling the `verify_key' callback
137 function, which is asynchronous. The application should check the
138 ske->status in this function to check whether it is Ok to continue
139 the execution of the protocol.
141 The `check_version' callback is called to verify the remote host's
142 version. The application may check its own version against the remote
143 host's version and determine whether supporting the remote host
146 The `context' is passed as argument to all of the above callback
149 void silc_ske_set_callbacks(SilcSKE ske,
150 SilcSKESendPacketCb send_packet,
151 SilcSKECb payload_receive,
152 SilcSKEVerifyCb verify_key,
153 SilcSKECb proto_continue,
154 SilcSKECheckVersion check_version,
158 silc_free(ske->callbacks);
159 ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
160 ske->callbacks->send_packet = send_packet;
161 ske->callbacks->payload_receive = payload_receive;
162 ske->callbacks->verify_key = verify_key;
163 ske->callbacks->proto_continue = proto_continue;
164 ske->callbacks->check_version = check_version;
165 ske->callbacks->context = context;
168 /* Starts the SILC Key Exchange protocol for initiator. The connection
169 to the remote end must be established before calling this function
170 and the connecting socket must be sent as argument. This function
171 creates the Key Exchange Start Payload which includes all our
172 configured security properties. This payload is then sent to the
173 remote end for further processing. This payload must be sent as
174 argument to the function, however, it must not be encoded
175 already, it is done by this function. The caller must not free
176 the `start_payload' since the SKE library will save it.
178 The packet sending is done by calling a callback function. Caller
179 must provide a routine to send the packet. */
181 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
182 SilcSocketConnection sock,
183 SilcSKEStartPayload *start_payload)
185 SilcSKEStatus status = SILC_SKE_STATUS_OK;
186 SilcBuffer payload_buf;
188 SILC_LOG_DEBUG(("Start"));
193 /* Encode the payload */
194 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
195 if (status != SILC_SKE_STATUS_OK)
198 /* Take a copy of the payload buffer for future use. It is used to
199 compute the HASH value. */
200 ske->start_payload_copy = silc_buffer_copy(payload_buf);
201 ske->start_payload = start_payload;
203 /* Send the packet. */
204 if (ske->callbacks->send_packet)
205 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
206 ske->callbacks->context);
208 silc_buffer_free(payload_buf);
213 /* Function called after ske_initiator_start fuction. This receives
214 the remote ends Key Exchange Start payload which includes the
215 security properties selected by the responder from our payload
216 sent in the silc_ske_initiator_start function. */
218 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
219 SilcBuffer start_payload)
221 SilcSKEStatus status = SILC_SKE_STATUS_OK;
222 SilcSKEStartPayload *payload;
223 SilcSKESecurityProperties prop;
224 SilcSKEDiffieHellmanGroup group;
226 SILC_LOG_DEBUG(("Start"));
228 /* Decode the payload */
229 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
230 if (status != SILC_SKE_STATUS_OK) {
231 ske->status = status;
232 silc_ske_payload_start_free(ske->start_payload);
236 /* Check that the cookie is returned unmodified */
237 if (memcmp(ske->start_payload->cookie, payload->cookie,
238 ske->start_payload->cookie_len)) {
239 SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
240 ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
241 silc_ske_payload_start_free(ske->start_payload);
245 /* Check version string */
246 if (ske->callbacks->check_version) {
247 status = ske->callbacks->check_version(ske, payload->version,
248 payload->version_len,
249 ske->callbacks->context);
250 if (status != SILC_SKE_STATUS_OK) {
251 ske->status = status;
252 silc_ske_payload_start_free(ske->start_payload);
257 /* Free our KE Start Payload context, we don't need it anymore. */
258 silc_ske_payload_start_free(ske->start_payload);
260 /* Take the selected security properties into use while doing
261 the key exchange. This is used only while doing the key
262 exchange. The same data is returned to upper levels by calling
263 the callback function. */
264 ske->prop = prop = silc_calloc(1, sizeof(*prop));
265 prop->flags = payload->flags;
266 status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
267 if (status != SILC_SKE_STATUS_OK)
272 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
273 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
277 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
278 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
282 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
283 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
287 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
288 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
292 /* Save remote's KE Start Payload */
293 ske->start_payload = payload;
295 /* Return the received payload by calling the callback function. */
296 if (ske->callbacks->payload_receive)
297 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
303 silc_ske_payload_start_free(payload);
305 silc_ske_group_free(group);
308 silc_pkcs_free(prop->pkcs);
310 silc_cipher_free(prop->cipher);
312 silc_hash_free(prop->hash);
314 silc_hmac_free(prop->hmac);
318 if (status == SILC_SKE_STATUS_OK)
319 return SILC_SKE_STATUS_ERROR;
321 ske->status = status;
325 /* This function creates random number x, such that 1 < x < q and
326 computes e = g ^ x mod p and sends the result to the remote end in
327 Key Exchange Payload. */
329 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
330 SilcPublicKey public_key,
331 SilcPrivateKey private_key,
332 SilcSKEPKType pk_type)
334 SilcSKEStatus status = SILC_SKE_STATUS_OK;
335 SilcBuffer payload_buf;
337 SilcSKEKEPayload *payload;
340 SILC_LOG_DEBUG(("Start"));
342 /* Create the random number x, 1 < x < q. */
343 x = silc_calloc(1, sizeof(*x));
346 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
347 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
349 if (status != SILC_SKE_STATUS_OK) {
352 ske->status = status;
356 /* Encode the result to Key Exchange Payload. */
358 payload = silc_calloc(1, sizeof(*payload));
359 ske->ke1_payload = payload;
361 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
363 /* Do the Diffie Hellman computation, e = g ^ x mod p */
364 silc_mp_init(&payload->x);
365 silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
366 &ske->prop->group->group);
370 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
371 if (!payload->pk_data) {
374 silc_mp_uninit(&payload->x);
376 ske->status = SILC_SKE_STATUS_OK;
379 payload->pk_len = pk_len;
381 payload->pk_type = pk_type;
383 /* Compute signature data if we are doing mutual authentication */
384 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
385 unsigned char hash[32], sign[1024];
386 SilcUInt32 hash_len, sign_len;
388 SILC_LOG_DEBUG(("We are doing mutual authentication"));
389 SILC_LOG_DEBUG(("Computing HASH_i value"));
391 /* Compute the hash value */
392 memset(hash, 0, sizeof(hash));
393 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
395 SILC_LOG_DEBUG(("Signing HASH_i value"));
397 /* Sign the hash value */
398 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
399 private_key->prv_len);
400 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
401 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
402 memcpy(payload->sign_data, sign, sign_len);
403 memset(sign, 0, sizeof(sign));
404 payload->sign_len = sign_len;
407 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
408 if (status != SILC_SKE_STATUS_OK) {
411 silc_mp_uninit(&payload->x);
412 silc_free(payload->pk_data);
414 ske->status = status;
420 /* Send the packet. */
421 if (ske->callbacks->send_packet)
422 (*ske->callbacks->send_packet)(ske, payload_buf,
423 SILC_PACKET_KEY_EXCHANGE_1,
424 ske->callbacks->context);
426 silc_buffer_free(payload_buf);
431 /* An initiator finish final callback that is called to indicate that
432 the SKE protocol may continue. */
434 static void silc_ske_initiator_finish_final(SilcSKE ske,
435 SilcSKEStatus status,
438 SilcSKEKEPayload *payload;
439 unsigned char hash[32];
441 SilcPublicKey public_key = NULL;
443 /* If the SKE was freed during the async call then free it really now,
444 otherwise just decrement the reference counter. */
445 if (ske->status == SILC_SKE_STATUS_FREED) {
450 /* If the caller returns PENDING status SKE library will assume that
451 the caller will re-call this callback when it is not anymore in
453 if (status == SILC_SKE_STATUS_PENDING)
457 payload = ske->ke2_payload;
459 /* If the status is an error then the public key that was verified
460 by the caller is not authentic. */
461 if (status != SILC_SKE_STATUS_OK) {
462 ske->status = status;
463 if (ske->callbacks->proto_continue)
464 ske->callbacks->proto_continue(ske, ske->callbacks->context);
468 if (payload->pk_data) {
469 /* Decode the public key */
470 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
472 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
473 if (ske->callbacks->proto_continue)
474 ske->callbacks->proto_continue(ske, ske->callbacks->context);
478 SILC_LOG_DEBUG(("Public key is authentic"));
480 /* Compute the hash value */
481 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
482 if (status != SILC_SKE_STATUS_OK)
485 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
486 memcpy(ske->hash, hash, hash_len);
487 ske->hash_len = hash_len;
489 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
491 /* Verify signature */
492 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
493 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
494 payload->sign_len, hash, hash_len) == FALSE) {
496 SILC_LOG_DEBUG(("Signature don't match"));
498 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
502 SILC_LOG_DEBUG(("Signature is Ok"));
504 silc_pkcs_public_key_free(public_key);
505 memset(hash, 'F', hash_len);
508 ske->status = SILC_SKE_STATUS_OK;
510 /* Call the callback. The caller may now continue the SKE protocol. */
511 if (ske->callbacks->proto_continue)
512 ske->callbacks->proto_continue(ske, ske->callbacks->context);
517 memset(hash, 'F', sizeof(hash));
518 silc_ske_payload_ke_free(payload);
519 ske->ke2_payload = NULL;
521 silc_mp_uninit(ske->KEY);
526 silc_pkcs_public_key_free(public_key);
529 memset(ske->hash, 'F', hash_len);
530 silc_free(ske->hash);
534 if (status == SILC_SKE_STATUS_OK)
535 ske->status = SILC_SKE_STATUS_ERROR;
537 ske->status = status;
539 /* Call the callback. */
540 if (ske->callbacks->proto_continue)
541 ske->callbacks->proto_continue(ske, ske->callbacks->context);
544 /* Receives Key Exchange Payload from responder consisting responders
545 public key, f, and signature. This function verifies the public key,
546 computes the secret shared key and verifies the signature.
548 The `proto_continue' will be called to indicate that the caller may
549 continue with the SKE protocol. The caller must not continue
550 before the SKE libary has called that callback. If this function
551 returns an error the callback will not be called. It is called
552 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
553 However, note that when the library calls the callback the ske->status
556 This calls the `verify_key' callback to verify the received public
557 key or certificate. If the `verify_key' is provided then the remote
558 must send public key and it is considered to be an error if remote
559 does not send its public key. If caller is performing a re-key with
560 SKE then the `verify_key' is usually not provided when it is not also
561 required for the remote to send its public key. */
563 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
564 SilcBuffer ke_payload)
566 SilcSKEStatus status = SILC_SKE_STATUS_OK;
567 SilcSKEKEPayload *payload;
570 SILC_LOG_DEBUG(("Start"));
572 /* Decode the payload */
573 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
574 if (status != SILC_SKE_STATUS_OK) {
575 ske->status = status;
578 ske->ke2_payload = payload;
580 if (!payload->pk_data && ske->callbacks->verify_key) {
581 SILC_LOG_DEBUG(("Remote end did not send its public key (or certificate), "
582 "even though we require it"));
583 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
587 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
589 /* Compute the shared secret key */
590 KEY = silc_calloc(1, sizeof(*KEY));
592 silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
595 if (payload->pk_data && ske->callbacks->verify_key) {
596 SILC_LOG_DEBUG(("Verifying public key"));
599 (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
600 payload->pk_type, ske->callbacks->context,
601 silc_ske_initiator_finish_final, NULL);
603 /* We will continue to the final state after the public key has
604 been verified by the caller. */
605 return SILC_SKE_STATUS_PENDING;
608 /* Continue to final state */
610 silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
612 return SILC_SKE_STATUS_OK;
615 silc_ske_payload_ke_free(payload);
616 ske->ke2_payload = NULL;
618 silc_mp_uninit(ske->KEY);
622 if (status == SILC_SKE_STATUS_OK)
623 return SILC_SKE_STATUS_ERROR;
625 ske->status = status;
629 /* Starts Key Exchange protocol for responder. Responder receives
630 Key Exchange Start Payload from initiator consisting of all the
631 security properties the initiator supports. This function decodes
632 the payload and parses the payload further and selects the right
633 security properties. */
635 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
636 SilcSocketConnection sock,
638 SilcBuffer start_payload,
639 SilcSKESecurityPropertyFlag flags)
641 SilcSKEStatus status = SILC_SKE_STATUS_OK;
642 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
644 SILC_LOG_DEBUG(("Start"));
649 /* Decode the payload */
650 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
651 if (status != SILC_SKE_STATUS_OK) {
652 ske->status = status;
656 /* Take a copy of the payload buffer for future use. It is used to
657 compute the HASH value. */
658 ske->start_payload_copy = silc_buffer_copy(start_payload);
660 /* Force the mutual authentication flag if we want to do it. */
661 if (flags & SILC_SKE_SP_FLAG_MUTUAL) {
662 SILC_LOG_DEBUG(("Force mutual authentication"));
663 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
666 /* Force PFS flag if we require it */
667 if (flags & SILC_SKE_SP_FLAG_PFS) {
668 SILC_LOG_DEBUG(("Force PFS"));
669 remote_payload->flags |= SILC_SKE_SP_FLAG_PFS;
672 /* Parse and select the security properties from the payload */
673 payload = silc_calloc(1, sizeof(*payload));
674 status = silc_ske_select_security_properties(ske, version,
675 payload, remote_payload);
676 if (status != SILC_SKE_STATUS_OK)
679 ske->start_payload = payload;
681 /* Call the callback function. */
682 if (ske->callbacks->payload_receive)
683 (*ske->callbacks->payload_receive)(ske, ske->callbacks->context);
685 silc_ske_payload_start_free(remote_payload);
691 silc_ske_payload_start_free(remote_payload);
695 if (status == SILC_SKE_STATUS_OK)
696 return SILC_SKE_STATUS_ERROR;
698 ske->status = status;
702 /* The selected security properties from the initiator payload is now
703 encoded into Key Exchange Start Payload and sent to the initiator. */
705 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
707 SilcSKEStatus status = SILC_SKE_STATUS_OK;
708 SilcBuffer payload_buf;
709 SilcSKESecurityProperties prop;
710 SilcSKEDiffieHellmanGroup group = NULL;
712 SILC_LOG_DEBUG(("Start"));
714 /* Allocate security properties from the payload. These are allocated
715 only for this negotiation and will be free'd after KE is over. */
716 ske->prop = prop = silc_calloc(1, sizeof(*prop));
717 prop->flags = ske->start_payload->flags;
718 status = silc_ske_group_get_by_name(ske->start_payload->ke_grp_list, &group);
719 if (status != SILC_SKE_STATUS_OK)
724 if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
725 &prop->pkcs) == FALSE) {
726 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
730 if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
731 &prop->cipher) == FALSE) {
732 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
736 if (silc_hash_alloc(ske->start_payload->hash_alg_list,
737 &prop->hash) == FALSE) {
738 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
742 if (silc_hmac_alloc(ske->start_payload->hmac_alg_list, NULL,
743 &prop->hmac) == FALSE) {
744 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
748 /* Encode the payload */
749 status = silc_ske_payload_start_encode(ske, ske->start_payload,
751 if (status != SILC_SKE_STATUS_OK)
754 /* Send the packet. */
755 if (ske->callbacks->send_packet)
756 (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
757 ske->callbacks->context);
759 silc_buffer_free(payload_buf);
765 silc_ske_group_free(group);
768 silc_pkcs_free(prop->pkcs);
770 silc_cipher_free(prop->cipher);
772 silc_hash_free(prop->hash);
774 silc_hmac_free(prop->hmac);
778 if (status == SILC_SKE_STATUS_OK)
779 return SILC_SKE_STATUS_ERROR;
781 ske->status = status;
785 /* An responder phase 2 final callback that is called to indicate that
786 the SKE protocol may continue. */
788 static void silc_ske_responder_phase2_final(SilcSKE ske,
789 SilcSKEStatus status,
792 SilcSKEKEPayload *recv_payload, *send_payload;
795 /* If the SKE was freed during the async call then free it really now,
796 otherwise just decrement the reference counter. */
797 if (ske->status == SILC_SKE_STATUS_FREED) {
802 /* If the caller returns PENDING status SKE library will assume that
803 the caller will re-call this callback when it is not anymore in
805 if (status == SILC_SKE_STATUS_PENDING)
809 recv_payload = ske->ke1_payload;
811 /* If the status is an error then the public key that was verified
812 by the caller is not authentic. */
813 if (status != SILC_SKE_STATUS_OK) {
814 ske->status = status;
815 if (ske->callbacks->proto_continue)
816 ske->callbacks->proto_continue(ske, ske->callbacks->context);
820 /* The public key verification was performed only if the Mutual
821 Authentication flag is set. */
822 if (ske->start_payload &&
823 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
824 SilcPublicKey public_key = NULL;
825 unsigned char hash[32];
828 /* Decode the public key */
829 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
830 recv_payload->pk_len,
832 ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
833 if (ske->callbacks->proto_continue)
834 ske->callbacks->proto_continue(ske, ske->callbacks->context);
838 SILC_LOG_DEBUG(("Public key is authentic"));
840 /* Compute the hash value */
841 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
842 if (status != SILC_SKE_STATUS_OK) {
843 ske->status = status;
844 if (ske->callbacks->proto_continue)
845 ske->callbacks->proto_continue(ske, ske->callbacks->context);
849 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
851 /* Verify signature */
852 silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
853 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
854 recv_payload->sign_len, hash, hash_len) == FALSE) {
856 SILC_LOG_DEBUG(("Signature don't match"));
858 ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
859 if (ske->callbacks->proto_continue)
860 ske->callbacks->proto_continue(ske, ske->callbacks->context);
864 SILC_LOG_DEBUG(("Signature is Ok"));
866 silc_pkcs_public_key_free(public_key);
867 memset(hash, 'F', hash_len);
870 /* Create the random number x, 1 < x < q. */
871 x = silc_calloc(1, sizeof(*x));
874 silc_ske_create_rnd(ske, &ske->prop->group->group_order,
875 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
877 if (status != SILC_SKE_STATUS_OK) {
880 ske->status = status;
881 if (ske->callbacks->proto_continue)
882 ske->callbacks->proto_continue(ske, ske->callbacks->context);
886 /* Save the results for later processing */
887 send_payload = silc_calloc(1, sizeof(*send_payload));
889 ske->ke2_payload = send_payload;
891 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
893 /* Do the Diffie Hellman computation, f = g ^ x mod p */
894 silc_mp_init(&send_payload->x);
895 silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
896 &ske->prop->group->group);
898 /* Call the callback. The caller may now continue with the SKE protocol. */
899 ske->status = SILC_SKE_STATUS_OK;
900 if (ske->callbacks->proto_continue)
901 ske->callbacks->proto_continue(ske, ske->callbacks->context);
904 /* This function receives the Key Exchange Payload from the initiator.
905 This also performs the mutual authentication if required. Then, this
906 function first generated a random number x, such that 1 < x < q
907 and computes f = g ^ x mod p. This then puts the result f to a Key
910 The `proto_continue' will be called to indicate that the caller may
911 continue with the SKE protocol. The caller must not continue
912 before the SKE libary has called that callback. If this function
913 returns an error the callback will not be called. It is called
914 if this function return SILC_SKE_STATUS_OK or SILC_SKE_STATUS_PENDING.
915 However, note that when the library calls the callback the ske->status
918 This calls the `verify_key' callback to verify the received public
919 key or certificate if the Mutual Authentication flag is set. If the
920 `verify_key' is provided then the remote must send public key and it
921 is considered to be an error if remote does not send its public key. */
923 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
924 SilcBuffer ke_payload)
926 SilcSKEStatus status = SILC_SKE_STATUS_OK;
927 SilcSKEKEPayload *recv_payload;
929 SILC_LOG_DEBUG(("Start"));
931 /* Decode Key Exchange Payload */
932 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
933 if (status != SILC_SKE_STATUS_OK) {
934 ske->status = status;
938 ske->ke1_payload = recv_payload;
940 /* Verify the received public key and verify the signature if we are
941 doing mutual authentication. */
942 if (ske->start_payload &&
943 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
945 SILC_LOG_DEBUG(("We are doing mutual authentication"));
947 if (!recv_payload->pk_data && ske->callbacks->verify_key) {
948 SILC_LOG_DEBUG(("Remote end did not send its public key (or "
949 "certificate), even though we require it"));
950 ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
954 if (recv_payload->pk_data && ske->callbacks->verify_key) {
955 SILC_LOG_DEBUG(("Verifying public key"));
958 (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
959 recv_payload->pk_len,
960 recv_payload->pk_type,
961 ske->callbacks->context,
962 silc_ske_responder_phase2_final, NULL);
964 /* We will continue to the final state after the public key has
965 been verified by the caller. */
966 return SILC_SKE_STATUS_PENDING;
970 /* Continue to final state */
972 silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
974 return SILC_SKE_STATUS_OK;
977 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
978 value to be signed and sent to the other end. This then encodes Key
979 Exchange Payload and sends it to the other end. */
981 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
982 SilcPublicKey public_key,
983 SilcPrivateKey private_key,
984 SilcSKEPKType pk_type)
986 SilcSKEStatus status = SILC_SKE_STATUS_OK;
987 SilcBuffer payload_buf;
989 unsigned char hash[32], sign[1024], *pk;
990 SilcUInt32 hash_len, sign_len, pk_len;
992 SILC_LOG_DEBUG(("Start"));
994 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
996 /* Compute the shared secret key */
997 KEY = silc_calloc(1, sizeof(*KEY));
999 silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
1000 &ske->prop->group->group);
1003 if (public_key && private_key) {
1004 SILC_LOG_DEBUG(("Getting public key"));
1006 /* Get the public key */
1007 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1009 status = SILC_SKE_STATUS_ERROR;
1012 ske->ke2_payload->pk_data = pk;
1013 ske->ke2_payload->pk_len = pk_len;
1015 SILC_LOG_DEBUG(("Computing HASH value"));
1017 /* Compute the hash value */
1018 memset(hash, 0, sizeof(hash));
1019 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
1020 if (status != SILC_SKE_STATUS_OK)
1023 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
1024 memcpy(ske->hash, hash, hash_len);
1025 ske->hash_len = hash_len;
1027 SILC_LOG_DEBUG(("Signing HASH value"));
1029 /* Sign the hash value */
1030 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
1031 private_key->prv_len);
1032 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
1033 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
1034 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
1035 memset(sign, 0, sizeof(sign));
1036 ske->ke2_payload->sign_len = sign_len;
1038 ske->ke2_payload->pk_type = pk_type;
1040 /* Encode the Key Exchange Payload */
1041 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
1043 if (status != SILC_SKE_STATUS_OK)
1046 /* Send the packet. */
1047 if (ske->callbacks->send_packet)
1048 (*ske->callbacks->send_packet)(ske, payload_buf,
1049 SILC_PACKET_KEY_EXCHANGE_2,
1050 ske->callbacks->context);
1052 silc_buffer_free(payload_buf);
1057 silc_mp_uninit(ske->KEY);
1058 silc_free(ske->KEY);
1060 silc_ske_payload_ke_free(ske->ke2_payload);
1062 if (status == SILC_SKE_STATUS_OK)
1063 return SILC_SKE_STATUS_ERROR;
1065 ske->status = status;
1069 /* The Key Exchange protocol is ended by calling this function. This
1070 must not be called until the keys are processed like the protocol
1071 defines. This function is for both initiator and responder. */
1073 SilcSKEStatus silc_ske_end(SilcSKE ske)
1077 SILC_LOG_DEBUG(("Start"));
1079 packet = silc_buffer_alloc(4);
1080 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1081 silc_buffer_format(packet,
1082 SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
1085 if (ske->callbacks->send_packet)
1086 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS,
1087 ske->callbacks->context);
1089 silc_buffer_free(packet);
1091 return SILC_SKE_STATUS_OK;
1094 /* Aborts the Key Exchange protocol. This is called if error occurs
1095 while performing the protocol. The status argument is the error
1096 status and it is sent to the remote end. */
1098 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
1102 SILC_LOG_DEBUG(("Start"));
1104 if (status > SILC_SKE_STATUS_INVALID_COOKIE)
1105 status = SILC_SKE_STATUS_BAD_PAYLOAD;
1107 packet = silc_buffer_alloc(4);
1108 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1109 silc_buffer_format(packet,
1110 SILC_STR_UI_INT((SilcUInt32)status),
1113 if (ske->callbacks->send_packet)
1114 (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE,
1115 ske->callbacks->context);
1117 silc_buffer_free(packet);
1119 return SILC_SKE_STATUS_OK;
1122 /* Assembles security properties to Key Exchange Start Payload to be
1123 sent to the remote end. This checks system wide (SILC system, that is)
1124 settings and chooses from those. However, if other properties
1125 should be used this function is easy to replace by another function,
1126 as, this function is called by the caller of the protocol and not
1127 by the protocol itself. */
1130 silc_ske_assemble_security_properties(SilcSKE ske,
1131 SilcSKESecurityPropertyFlag flags,
1132 const char *version,
1133 SilcSKEStartPayload **return_payload)
1135 SilcSKEStartPayload *rp;
1138 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
1140 rp = silc_calloc(1, sizeof(*rp));
1143 rp->flags = (unsigned char)flags;
1145 /* Set random cookie */
1146 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
1147 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
1148 rp->cookie[i] = silc_rng_get_byte(ske->rng);
1149 rp->cookie_len = SILC_SKE_COOKIE_LEN;
1152 rp->version = strdup(version);
1153 rp->version_len = strlen(version);
1155 /* Get supported Key Exhange groups */
1156 rp->ke_grp_list = silc_ske_get_supported_groups();
1157 rp->ke_grp_len = strlen(rp->ke_grp_list);
1159 /* Get supported PKCS algorithms */
1160 rp->pkcs_alg_list = silc_pkcs_get_supported();
1161 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
1163 /* Get supported encryption algorithms */
1164 rp->enc_alg_list = silc_cipher_get_supported();
1165 rp->enc_alg_len = strlen(rp->enc_alg_list);
1167 /* Get supported hash algorithms */
1168 rp->hash_alg_list = silc_hash_get_supported();
1169 rp->hash_alg_len = strlen(rp->hash_alg_list);
1171 /* Get supported HMACs */
1172 rp->hmac_alg_list = silc_hmac_get_supported();
1173 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
1176 /* Get supported compression algorithms */
1177 rp->comp_alg_list = strdup("");
1178 rp->comp_alg_len = 0;
1180 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1181 2 + rp->version_len +
1182 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
1183 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
1184 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
1186 *return_payload = rp;
1188 return SILC_SKE_STATUS_OK;
1191 /* Selects the supported security properties from the remote end's Key
1192 Exchange Start Payload. */
1195 silc_ske_select_security_properties(SilcSKE ske,
1196 const char *version,
1197 SilcSKEStartPayload *payload,
1198 SilcSKEStartPayload *remote_payload)
1200 SilcSKEStatus status;
1201 SilcSKEStartPayload *rp;
1205 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
1207 rp = remote_payload;
1209 /* Check version string */
1210 if (ske->callbacks->check_version) {
1211 status = ske->callbacks->check_version(ske, rp->version,
1213 ske->callbacks->context);
1214 if (status != SILC_SKE_STATUS_OK) {
1215 ske->status = status;
1220 ske->remote_version = silc_memdup(rp->version, rp->version_len);
1222 /* Flags are returned unchanged. */
1223 payload->flags = rp->flags;
1225 /* Take cookie, we must return it to sender unmodified. */
1226 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
1227 payload->cookie_len = SILC_SKE_COOKIE_LEN;
1228 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
1230 /* Put our version to our reply */
1231 payload->version = strdup(version);
1232 payload->version_len = strlen(version);
1234 /* Get supported Key Exchange groups */
1235 cp = rp->ke_grp_list;
1236 if (cp && strchr(cp, ',')) {
1240 len = strcspn(cp, ",");
1241 item = silc_calloc(len + 1, sizeof(char));
1242 memcpy(item, cp, len);
1244 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
1246 if (silc_ske_group_get_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
1247 SILC_LOG_DEBUG(("Found KE group `%s'", item));
1249 payload->ke_grp_len = len;
1250 payload->ke_grp_list = item;
1255 if (strlen(cp) == 0)
1264 if (!payload->ke_grp_len && !payload->ke_grp_list) {
1265 SILC_LOG_DEBUG(("Could not find supported KE group"));
1267 return SILC_SKE_STATUS_UNKNOWN_GROUP;
1271 if (!rp->ke_grp_len) {
1272 SILC_LOG_DEBUG(("KE group not defined in payload"));
1274 return SILC_SKE_STATUS_BAD_PAYLOAD;
1277 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1278 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1280 payload->ke_grp_len = rp->ke_grp_len;
1281 payload->ke_grp_list = strdup(rp->ke_grp_list);
1284 /* Get supported PKCS algorithms */
1285 cp = rp->pkcs_alg_list;
1286 if (cp && strchr(cp, ',')) {
1290 len = strcspn(cp, ",");
1291 item = silc_calloc(len + 1, sizeof(char));
1292 memcpy(item, cp, len);
1294 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1296 if (silc_pkcs_is_supported(item) == TRUE) {
1297 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1299 payload->pkcs_alg_len = len;
1300 payload->pkcs_alg_list = item;
1305 if (strlen(cp) == 0)
1314 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1315 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1316 silc_free(payload->ke_grp_list);
1318 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1322 if (!rp->pkcs_alg_len) {
1323 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1324 silc_free(payload->ke_grp_list);
1326 return SILC_SKE_STATUS_BAD_PAYLOAD;
1329 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1330 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1332 payload->pkcs_alg_len = rp->pkcs_alg_len;
1333 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1336 /* Get supported encryption algorithms */
1337 cp = rp->enc_alg_list;
1338 if (cp && strchr(cp, ',')) {
1342 len = strcspn(cp, ",");
1343 item = silc_calloc(len + 1, sizeof(char));
1344 memcpy(item, cp, len);
1346 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1348 if (silc_cipher_is_supported(item) == TRUE) {
1349 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1351 payload->enc_alg_len = len;
1352 payload->enc_alg_list = item;
1357 if (strlen(cp) == 0)
1366 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1367 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1368 silc_free(payload->ke_grp_list);
1369 silc_free(payload->pkcs_alg_list);
1371 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1375 if (!rp->enc_alg_len) {
1376 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1377 silc_free(payload->ke_grp_list);
1378 silc_free(payload->pkcs_alg_list);
1380 return SILC_SKE_STATUS_BAD_PAYLOAD;
1383 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1386 payload->enc_alg_len = rp->enc_alg_len;
1387 payload->enc_alg_list = strdup(rp->enc_alg_list);
1390 /* Get supported hash algorithms */
1391 cp = rp->hash_alg_list;
1392 if (cp && strchr(cp, ',')) {
1396 len = strcspn(cp, ",");
1397 item = silc_calloc(len + 1, sizeof(char));
1398 memcpy(item, cp, len);
1400 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1402 if (silc_hash_is_supported(item) == TRUE) {
1403 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1405 payload->hash_alg_len = len;
1406 payload->hash_alg_list = item;
1411 if (strlen(cp) == 0)
1420 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1421 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1422 silc_free(payload->ke_grp_list);
1423 silc_free(payload->pkcs_alg_list);
1424 silc_free(payload->enc_alg_list);
1426 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1430 if (!rp->hash_alg_len) {
1431 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1432 silc_free(payload->ke_grp_list);
1433 silc_free(payload->pkcs_alg_list);
1434 silc_free(payload->enc_alg_list);
1436 return SILC_SKE_STATUS_BAD_PAYLOAD;
1439 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1440 rp->hash_alg_list));
1442 payload->hash_alg_len = rp->hash_alg_len;
1443 payload->hash_alg_list = strdup(rp->hash_alg_list);
1446 /* Get supported HMACs */
1447 cp = rp->hmac_alg_list;
1448 if (cp && strchr(cp, ',')) {
1452 len = strcspn(cp, ",");
1453 item = silc_calloc(len + 1, sizeof(char));
1454 memcpy(item, cp, len);
1456 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1458 if (silc_hmac_is_supported(item) == TRUE) {
1459 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1461 payload->hmac_alg_len = len;
1462 payload->hmac_alg_list = item;
1467 if (strlen(cp) == 0)
1476 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1477 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1478 silc_free(payload->ke_grp_list);
1479 silc_free(payload->pkcs_alg_list);
1480 silc_free(payload->enc_alg_list);
1481 silc_free(payload->hash_alg_list);
1483 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1487 if (!rp->hmac_alg_len) {
1488 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1489 silc_free(payload->ke_grp_list);
1490 silc_free(payload->pkcs_alg_list);
1491 silc_free(payload->enc_alg_list);
1492 silc_free(payload->hash_alg_list);
1494 return SILC_SKE_STATUS_BAD_PAYLOAD;
1497 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1498 rp->hmac_alg_list));
1500 payload->hmac_alg_len = rp->hmac_alg_len;
1501 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1505 /* Get supported compression algorithms */
1506 cp = rp->hash_alg_list;
1507 if (cp && strchr(cp, ',')) {
1511 len = strcspn(cp, ",");
1512 item = silc_calloc(len + 1, sizeof(char));
1513 memcpy(item, cp, len);
1515 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1517 if (silc_hash_is_supported(item) == TRUE) {
1518 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1520 payload->hash_alg_len = len;
1521 payload->hash_alg_list = item;
1526 if (strlen(cp) == 0)
1535 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1536 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1537 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1538 silc_free(payload->ke_grp_list);
1539 silc_free(payload->pkcs_alg_list);
1540 silc_free(payload->enc_alg_list);
1549 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1550 2 + payload->version_len +
1551 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1552 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1553 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1555 return SILC_SKE_STATUS_OK;
1558 /* Creates random number such that 1 < rnd < n and at most length
1559 of len bits. The rnd sent as argument must be initialized. */
1561 static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
1565 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1566 unsigned char *string;
1568 SILC_LOG_DEBUG(("Creating random number"));
1570 /* Get the random number as string */
1571 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1573 return SILC_SKE_STATUS_ERROR;
1575 /* Decode the string into a MP integer */
1576 silc_mp_bin2mp(string, (len / 8), rnd);
1577 silc_mp_mod_2exp(rnd, rnd, len);
1580 if (silc_mp_cmp_ui(rnd, 1) < 0)
1581 status = SILC_SKE_STATUS_ERROR;
1583 if (silc_mp_cmp(rnd, n) >= 0)
1584 status = SILC_SKE_STATUS_ERROR;
1586 memset(string, 'F', (len / 8));
1592 /* Creates a hash value HASH as defined in the SKE protocol. If the
1593 `initiator' is TRUE then this function is used to create the HASH_i
1594 hash value defined in the protocol. If it is FALSE then this is used
1595 to create the HASH value defined by the protocol. */
1597 static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1598 unsigned char *return_hash,
1599 SilcUInt32 *return_hash_len,
1602 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1604 unsigned char *e, *f, *KEY;
1605 SilcUInt32 e_len, f_len, KEY_len;
1608 SILC_LOG_DEBUG(("Start"));
1610 if (initiator == FALSE) {
1611 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1612 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1613 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1615 /* Format the buffer used to compute the hash value */
1616 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1617 ske->ke2_payload->pk_len +
1618 ske->ke1_payload->pk_len +
1619 e_len + f_len + KEY_len);
1620 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1622 /* Initiator is not required to send its public key */
1623 if (!ske->ke1_payload->pk_data) {
1625 silc_buffer_format(buf,
1626 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1628 ske->start_payload_copy->
1630 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1631 ske->ke2_payload->pk_len),
1632 SILC_STR_UI_XNSTRING(e, e_len),
1633 SILC_STR_UI_XNSTRING(f, f_len),
1634 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1638 silc_buffer_format(buf,
1639 SILC_STR_UI_XNSTRING(ske->start_payload_copy->
1641 ske->start_payload_copy->
1643 SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
1644 ske->ke2_payload->pk_len),
1645 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1646 ske->ke1_payload->pk_len),
1647 SILC_STR_UI_XNSTRING(e, e_len),
1648 SILC_STR_UI_XNSTRING(f, f_len),
1649 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1653 silc_buffer_free(buf);
1654 memset(e, 0, e_len);
1655 memset(f, 0, f_len);
1656 memset(KEY, 0, KEY_len);
1660 return SILC_SKE_STATUS_ERROR;
1663 memset(e, 0, e_len);
1664 memset(f, 0, f_len);
1665 memset(KEY, 0, KEY_len);
1670 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1672 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1673 ske->ke1_payload->pk_len + e_len);
1674 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1676 /* Format the buffer used to compute the hash value */
1678 silc_buffer_format(buf,
1679 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1680 ske->start_payload_copy->len),
1681 SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
1682 ske->ke1_payload->pk_len),
1683 SILC_STR_UI_XNSTRING(e, e_len),
1686 silc_buffer_free(buf);
1687 memset(e, 0, e_len);
1689 return SILC_SKE_STATUS_ERROR;
1692 memset(e, 0, e_len);
1697 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1698 *return_hash_len = silc_hash_len(ske->prop->hash);
1700 if (initiator == FALSE) {
1701 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1703 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1706 silc_buffer_free(buf);
1711 /* Processes the provided key material `data' as the SILC protocol
1712 specification defines. */
1715 silc_ske_process_key_material_data(unsigned char *data,
1716 SilcUInt32 data_len,
1717 SilcUInt32 req_iv_len,
1718 SilcUInt32 req_enc_key_len,
1719 SilcUInt32 req_hmac_key_len,
1721 SilcSKEKeyMaterial *key)
1724 unsigned char hashd[32];
1725 SilcUInt32 hash_len = req_hmac_key_len;
1726 SilcUInt32 enc_key_len = req_enc_key_len / 8;
1728 SILC_LOG_DEBUG(("Start"));
1730 if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
1731 return SILC_SKE_STATUS_ERROR;
1733 buf = silc_buffer_alloc(1 + data_len);
1734 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1735 silc_buffer_format(buf,
1736 SILC_STR_UI_CHAR(0),
1737 SILC_STR_UI_XNSTRING(data, data_len),
1741 memset(hashd, 0, sizeof(hashd));
1743 silc_hash_make(hash, buf->data, buf->len, hashd);
1744 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1745 memcpy(key->send_iv, hashd, req_iv_len);
1746 memset(hashd, 0, sizeof(hashd));
1748 silc_hash_make(hash, buf->data, buf->len, hashd);
1749 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1750 memcpy(key->receive_iv, hashd, req_iv_len);
1751 key->iv_len = req_iv_len;
1753 /* Take the encryption keys. If requested key size is more than
1754 the size of hash length we will distribute more key material
1755 as protocol defines. */
1757 if (enc_key_len > hash_len) {
1759 unsigned char k1[32], k2[32], k3[32];
1760 unsigned char *dtmp;
1763 if (enc_key_len > (3 * hash_len))
1764 return SILC_SKE_STATUS_ERROR;
1766 /* Take first round */
1767 memset(k1, 0, sizeof(k1));
1768 silc_hash_make(hash, buf->data, buf->len, k1);
1770 /* Take second round */
1771 dist = silc_buffer_alloc(data_len + hash_len);
1772 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1773 silc_buffer_format(dist,
1774 SILC_STR_UI_XNSTRING(data, data_len),
1775 SILC_STR_UI_XNSTRING(k1, hash_len),
1777 memset(k2, 0, sizeof(k2));
1778 silc_hash_make(hash, dist->data, dist->len, k2);
1780 /* Take third round */
1781 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1782 silc_buffer_pull_tail(dist, hash_len);
1783 silc_buffer_pull(dist, data_len + hash_len);
1784 silc_buffer_format(dist,
1785 SILC_STR_UI_XNSTRING(k2, hash_len),
1787 silc_buffer_push(dist, data_len + hash_len);
1788 memset(k3, 0, sizeof(k3));
1789 silc_hash_make(hash, dist->data, dist->len, k3);
1791 /* Then, save the keys */
1792 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1793 memcpy(dtmp, k1, hash_len);
1794 memcpy(dtmp + hash_len, k2, hash_len);
1795 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1797 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1798 memcpy(key->send_enc_key, dtmp, enc_key_len);
1799 key->enc_key_len = req_enc_key_len;
1801 memset(dtmp, 0, (3 * hash_len));
1802 memset(k1, 0, sizeof(k1));
1803 memset(k2, 0, sizeof(k2));
1804 memset(k3, 0, sizeof(k3));
1806 silc_buffer_free(dist);
1808 /* Take normal hash as key */
1809 memset(hashd, 0, sizeof(hashd));
1810 silc_hash_make(hash, buf->data, buf->len, hashd);
1811 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1812 memcpy(key->send_enc_key, hashd, enc_key_len);
1813 key->enc_key_len = req_enc_key_len;
1817 if (enc_key_len > hash_len) {
1819 unsigned char k1[32], k2[32], k3[32];
1820 unsigned char *dtmp;
1823 if (enc_key_len > (3 * hash_len))
1824 return SILC_SKE_STATUS_ERROR;
1826 /* Take first round */
1827 memset(k1, 0, sizeof(k1));
1828 silc_hash_make(hash, buf->data, buf->len, k1);
1830 /* Take second round */
1831 dist = silc_buffer_alloc(data_len + hash_len);
1832 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1833 silc_buffer_format(dist,
1834 SILC_STR_UI_XNSTRING(data, data_len),
1835 SILC_STR_UI_XNSTRING(k1, hash_len),
1837 memset(k2, 0, sizeof(k2));
1838 silc_hash_make(hash, dist->data, dist->len, k2);
1840 /* Take third round */
1841 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1842 silc_buffer_pull_tail(dist, hash_len);
1843 silc_buffer_pull(dist, data_len + hash_len);
1844 silc_buffer_format(dist,
1845 SILC_STR_UI_XNSTRING(k2, hash_len),
1847 silc_buffer_push(dist, data_len + hash_len);
1848 memset(k3, 0, sizeof(k3));
1849 silc_hash_make(hash, dist->data, dist->len, k3);
1851 /* Then, save the keys */
1852 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1853 memcpy(dtmp, k1, hash_len);
1854 memcpy(dtmp + hash_len, k2, hash_len);
1855 memcpy(dtmp + hash_len + hash_len, k3, hash_len);
1857 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1858 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1859 key->enc_key_len = req_enc_key_len;
1861 memset(dtmp, 0, (3 * hash_len));
1862 memset(k1, 0, sizeof(k1));
1863 memset(k2, 0, sizeof(k2));
1864 memset(k3, 0, sizeof(k3));
1866 silc_buffer_free(dist);
1868 /* Take normal hash as key */
1869 memset(hashd, 0, sizeof(hashd));
1870 silc_hash_make(hash, buf->data, buf->len, hashd);
1871 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1872 memcpy(key->receive_enc_key, hashd, enc_key_len);
1873 key->enc_key_len = req_enc_key_len;
1876 /* Take HMAC keys */
1877 memset(hashd, 0, sizeof(hashd));
1879 silc_hash_make(hash, buf->data, buf->len, hashd);
1880 key->send_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1881 memcpy(key->send_hmac_key, hashd, req_hmac_key_len);
1882 memset(hashd, 0, sizeof(hashd));
1884 silc_hash_make(hash, buf->data, buf->len, hashd);
1885 key->receive_hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1886 memcpy(key->receive_hmac_key, hashd, req_hmac_key_len);
1887 key->hmac_key_len = req_hmac_key_len;
1888 memset(hashd, 0, sizeof(hashd));
1890 silc_buffer_free(buf);
1892 return SILC_SKE_STATUS_OK;
1895 /* Processes negotiated key material as protocol specifies. This returns
1896 the actual keys to be used in the SILC. */
1898 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1899 SilcUInt32 req_iv_len,
1900 SilcUInt32 req_enc_key_len,
1901 SilcUInt32 req_hmac_key_len,
1902 SilcSKEKeyMaterial *key)
1904 SilcSKEStatus status;
1906 unsigned char *tmpbuf;
1909 /* Encode KEY to binary data */
1910 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1912 buf = silc_buffer_alloc(klen + ske->hash_len);
1913 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1914 silc_buffer_format(buf,
1915 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1916 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1919 /* Process the key material */
1920 status = silc_ske_process_key_material_data(buf->data, buf->len,
1921 req_iv_len, req_enc_key_len,
1923 ske->prop->hash, key);
1925 memset(tmpbuf, 0, klen);
1927 silc_buffer_free(buf);
1932 /* Free key material structure */
1934 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1940 silc_free(key->send_iv);
1941 if (key->receive_iv)
1942 silc_free(key->receive_iv);
1943 if (key->send_enc_key) {
1944 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1945 silc_free(key->send_enc_key);
1947 if (key->receive_enc_key) {
1948 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1949 silc_free(key->receive_enc_key);
1951 if (key->send_hmac_key) {
1952 memset(key->send_hmac_key, 0, key->hmac_key_len);
1953 silc_free(key->send_hmac_key);
1955 if (key->receive_hmac_key) {
1956 memset(key->receive_hmac_key, 0, key->hmac_key_len);
1957 silc_free(key->receive_hmac_key);
1962 const char *silc_ske_status_string[] =
1966 "Unkown error occurred",
1967 "Bad payload in packet",
1968 "Unsupported group",
1969 "Unsupported cipher",
1971 "Unsupported hash function",
1973 "Unsupported public key (or certificate)",
1974 "Incorrect signature",
1975 "Bad or unsupported version",
1980 "Remote did not provide public key",
1981 "Key exchange protocol is not active",
1982 "Bad reserved field in packet",
1983 "Bad payload length in packet",
1989 /* Maps status to readable string and returns the string. If string is not
1990 found and empty character string ("") is returned. */
1992 const char *silc_ske_map_status(SilcSKEStatus status)
1996 for (i = 0; silc_ske_status_string[i]; i++)
1998 return silc_ske_status_string[i];
2003 /* Parses remote host's version string. */
2005 bool silc_ske_parse_version(SilcSKE ske,
2006 SilcUInt32 *protocol_version,
2007 char **protocol_version_string,
2008 SilcUInt32 *software_version,
2009 char **software_version_string,
2010 char **vendor_version)
2012 return silc_parse_version_string(ske->remote_version,
2014 protocol_version_string,
2016 software_version_string,