5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2000 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
23 #include "payload_internal.h"
24 #include "groups_internal.h"
26 /* Allocates new SKE object. */
28 SilcSKE silc_ske_alloc()
32 SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
34 ske = silc_calloc(1, sizeof(*ske));
35 ske->status = SILC_SKE_STATUS_OK;
40 /* Free's SKE object. */
42 void silc_ske_free(SilcSKE ske)
44 SILC_LOG_DEBUG(("Freeing Key Exchange object"));
47 /* Free start payload */
48 if (ske->start_payload)
49 silc_ske_payload_start_free(ske->start_payload);
53 silc_ske_payload_ke_free(ske->ke1_payload);
58 silc_free(ske->prop->group);
60 silc_pkcs_free(ske->prop->pkcs);
61 if (ske->prop->cipher)
62 silc_cipher_free(ske->prop->cipher);
64 silc_hash_free(ske->prop->hash);
66 silc_hmac_free(ske->prop->hmac);
69 if (ske->start_payload_copy)
70 silc_buffer_free(ske->start_payload_copy);
74 silc_mp_clear(ske->x);
78 silc_mp_clear(ske->KEY);
87 /* Starts the SILC Key Exchange protocol for initiator. The connection
88 to the remote end must be established before calling this function
89 and the connecting socket must be sent as argument. This function
90 creates the Key Exchange Start Paload which includes all our
91 configured security properties. This payload is then sent to the
92 remote end for further processing. This payload must be sent as
93 argument to the function, however, it must not be encoded
94 already, it is done by this function.
96 The packet sending is done by calling a callback function. Caller
97 must provide a routine to send the packet. */
99 SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
100 SilcSocketConnection sock,
101 SilcSKEStartPayload *start_payload,
102 SilcSKESendPacketCb send_packet,
105 SilcSKEStatus status = SILC_SKE_STATUS_OK;
106 SilcBuffer payload_buf;
108 SILC_LOG_DEBUG(("Start"));
113 /* Encode the payload */
114 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
115 if (status != SILC_SKE_STATUS_OK)
118 /* Take a copy of the payload buffer for future use. It is used to
119 compute the HASH value. */
120 ske->start_payload_copy = silc_buffer_copy(payload_buf);
122 /* Send the packet. */
124 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, context);
126 silc_buffer_free(payload_buf);
131 /* Function called after ske_initiator_start fuction. This receives
132 the remote ends Key Exchange Start payload which includes the
133 security properties selected by the responder from our payload
134 sent in the silc_ske_initiator_start function. */
136 SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
137 SilcBuffer start_payload,
141 SilcSKEStatus status = SILC_SKE_STATUS_OK;
142 SilcSKEStartPayload *payload;
143 SilcSKESecurityProperties prop;
144 SilcSKEDiffieHellmanGroup group;
146 SILC_LOG_DEBUG(("Start"));
148 /* Decode the payload */
149 status = silc_ske_payload_start_decode(ske, start_payload, &payload);
150 if (status != SILC_SKE_STATUS_OK) {
151 ske->status = status;
155 /* Take the selected security properties into use while doing
156 the key exchange. This is used only while doing the key
157 exchange. The same data is returned to upper levels by calling
158 the callback function. */
159 ske->prop = prop = silc_calloc(1, sizeof(*prop));
160 prop->flags = payload->flags;
161 status = silc_ske_get_group_by_name(payload->ke_grp_list, &group);
162 if (status != SILC_SKE_STATUS_OK)
167 if (silc_pkcs_alloc(payload->pkcs_alg_list, &prop->pkcs) == FALSE) {
168 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
172 if (silc_cipher_alloc(payload->enc_alg_list, &prop->cipher) == FALSE) {
173 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
177 if (silc_hash_alloc(payload->hash_alg_list, &prop->hash) == FALSE) {
178 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
182 if (silc_hmac_alloc(payload->hmac_alg_list, NULL, &prop->hmac) == FALSE) {
183 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
187 ske->start_payload = payload;
189 /* Return the received payload by calling the callback function. */
191 (*callback)(ske, context);
197 silc_ske_payload_start_free(payload);
202 silc_pkcs_free(prop->pkcs);
204 silc_cipher_free(prop->cipher);
206 silc_hash_free(prop->hash);
208 silc_hmac_free(prop->hmac);
212 if (status == SILC_SKE_STATUS_OK)
213 return SILC_SKE_STATUS_ERROR;
215 ske->status = status;
219 /* This function creates random number x, such that 1 < x < q and
220 computes e = g ^ x mod p and sends the result to the remote end in
221 Key Exchange Payload. */
223 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
224 SilcPublicKey public_key,
225 SilcPrivateKey private_key,
226 SilcSKESendPacketCb send_packet,
229 SilcSKEStatus status = SILC_SKE_STATUS_OK;
230 SilcBuffer payload_buf;
232 SilcSKEKEPayload *payload;
235 SILC_LOG_DEBUG(("Start"));
237 /* Create the random number x, 1 < x < q. */
238 x = silc_calloc(1, sizeof(*x));
241 silc_ske_create_rnd(ske, ske->prop->group->group_order,
242 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
244 if (status != SILC_SKE_STATUS_OK) {
247 ske->status = status;
251 SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
253 /* Do the Diffie Hellman computation, e = g ^ x mod p */
255 silc_mp_powm(&e, &ske->prop->group->generator, x,
256 &ske->prop->group->group);
258 /* Encode the result to Key Exchange Payload. */
260 payload = silc_calloc(1, sizeof(*payload));
261 ske->ke1_payload = payload;
267 payload->pk_data = silc_pkcs_public_key_encode(public_key, &pk_len);
268 if (!payload->pk_data) {
273 ske->status = SILC_SKE_STATUS_OK;
276 payload->pk_len = pk_len;
278 payload->pk_type = SILC_SKE_PK_TYPE_SILC;
280 /* Compute signature data if we are doing mutual authentication */
281 if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
282 unsigned char hash[32], sign[1024];
283 uint32 hash_len, sign_len;
285 SILC_LOG_DEBUG(("We are doing mutual authentication"));
286 SILC_LOG_DEBUG(("Computing HASH_i value"));
288 /* Compute the hash value */
289 memset(hash, 0, sizeof(hash));
290 silc_ske_make_hash(ske, hash, &hash_len, TRUE);
292 SILC_LOG_DEBUG(("Signing HASH_i value"));
294 /* Sign the hash value */
295 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
296 private_key->prv_len);
297 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
298 payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
299 memcpy(payload->sign_data, sign, sign_len);
300 memset(sign, 0, sizeof(sign));
301 payload->sign_len = sign_len;
304 status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
305 if (status != SILC_SKE_STATUS_OK) {
309 silc_free(payload->pk_data);
311 ske->status = status;
317 /* Send the packet. */
319 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE_1, context);
321 silc_buffer_free(payload_buf);
326 /* Receives Key Exchange Payload from responder consisting responders
327 public key, f, and signature. This function verifies the public key,
328 computes the secret shared key and verifies the signature. */
330 SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
331 SilcBuffer ke_payload,
332 SilcSKEVerifyCb verify_key,
333 void *verify_context,
337 SilcSKEStatus status = SILC_SKE_STATUS_OK;
338 SilcSKEKEPayload *payload;
339 SilcPublicKey public_key = NULL;
341 unsigned char hash[32];
344 SILC_LOG_DEBUG(("Start"));
346 /* Decode the payload */
347 status = silc_ske_payload_ke_decode(ske, ke_payload, &payload);
348 if (status != SILC_SKE_STATUS_OK) {
349 ske->status = status;
352 ske->ke2_payload = payload;
354 SILC_LOG_DEBUG(("Computing KEY = f ^ x mod p"));
356 /* Compute the shared secret key */
357 KEY = silc_calloc(1, sizeof(*KEY));
359 silc_mp_powm(KEY, &payload->x, ske->x, &ske->prop->group->group);
362 if (payload->pk_data) {
363 SILC_LOG_DEBUG(("Verifying public key"));
365 if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
367 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
373 status = (*verify_key)(ske, payload->pk_data, payload->pk_len,
374 payload->pk_type, verify_context);
375 if (status != SILC_SKE_STATUS_OK)
378 SILC_LOG_DEBUG(("Public key is authentic"));
381 if (payload->pk_data) {
382 /* Compute the hash value */
383 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
384 if (status != SILC_SKE_STATUS_OK)
387 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
388 memcpy(ske->hash, hash, hash_len);
389 ske->hash_len = hash_len;
391 SILC_LOG_DEBUG(("Verifying signature (HASH)"));
393 /* Verify signature */
394 silc_pkcs_public_key_data_set(ske->prop->pkcs, public_key->pk,
396 if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
397 payload->sign_len, hash, hash_len) == FALSE) {
399 SILC_LOG_DEBUG(("Signature don't match"));
401 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
405 SILC_LOG_DEBUG(("Signature is Ok"));
407 silc_pkcs_public_key_free(public_key);
408 memset(hash, 'F', hash_len);
411 /* Call the callback. */
413 (*callback)(ske, context);
418 memset(hash, 'F', sizeof(hash));
419 silc_ske_payload_ke_free(payload);
420 ske->ke2_payload = NULL;
422 silc_mp_clear(ske->KEY);
427 silc_pkcs_public_key_free(public_key);
430 memset(ske->hash, 'F', hash_len);
431 silc_free(ske->hash);
435 if (status == SILC_SKE_STATUS_OK)
436 return SILC_SKE_STATUS_ERROR;
438 ske->status = status;
442 /* Starts Key Exchange protocol for responder. Responder receives
443 Key Exchange Start Payload from initiator consisting of all the
444 security properties the initiator supports. This function decodes
445 the payload and parses the payload further and selects the right
446 security properties. */
448 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
449 SilcSocketConnection sock,
451 SilcBuffer start_payload,
456 SilcSKEStatus status = SILC_SKE_STATUS_OK;
457 SilcSKEStartPayload *remote_payload = NULL, *payload = NULL;
459 SILC_LOG_DEBUG(("Start"));
464 /* Decode the payload */
465 status = silc_ske_payload_start_decode(ske, start_payload, &remote_payload);
466 if (status != SILC_SKE_STATUS_OK) {
467 ske->status = status;
471 /* Take a copy of the payload buffer for future use. It is used to
472 compute the HASH value. */
473 ske->start_payload_copy = silc_buffer_copy(start_payload);
475 /* Force the mutual authentication flag if we want to do it. */
477 SILC_LOG_DEBUG(("Force mutual authentication"));
478 remote_payload->flags |= SILC_SKE_SP_FLAG_MUTUAL;
481 /* Parse and select the security properties from the payload */
482 payload = silc_calloc(1, sizeof(*payload));
483 status = silc_ske_select_security_properties(ske, version,
484 payload, remote_payload);
485 if (status != SILC_SKE_STATUS_OK)
488 ske->start_payload = payload;
490 /* Call the callback function. */
492 (*callback)(ske, context);
498 silc_ske_payload_start_free(remote_payload);
502 if (status == SILC_SKE_STATUS_OK)
503 return SILC_SKE_STATUS_ERROR;
505 ske->status = status;
509 /* The selected security properties from the initiator payload is now
510 encoded into Key Exchange Start Payload and sent to the initiator. */
512 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske,
513 SilcSKEStartPayload *start_payload,
514 SilcSKESendPacketCb send_packet,
517 SilcSKEStatus status = SILC_SKE_STATUS_OK;
518 SilcBuffer payload_buf;
519 SilcSKESecurityProperties prop;
520 SilcSKEDiffieHellmanGroup group = NULL;
522 SILC_LOG_DEBUG(("Start"));
524 /* Allocate security properties from the payload. These are allocated
525 only for this negotiation and will be free'd after KE is over. */
526 ske->prop = prop = silc_calloc(1, sizeof(*prop));
527 prop->flags = start_payload->flags;
528 status = silc_ske_get_group_by_name(start_payload->ke_grp_list, &group);
529 if (status != SILC_SKE_STATUS_OK)
534 if (silc_pkcs_alloc(start_payload->pkcs_alg_list,
535 &prop->pkcs) == FALSE) {
536 status = SILC_SKE_STATUS_UNKNOWN_PKCS;
540 if (silc_cipher_alloc(start_payload->enc_alg_list,
541 &prop->cipher) == FALSE) {
542 status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
546 if (silc_hash_alloc(start_payload->hash_alg_list,
547 &prop->hash) == FALSE) {
548 status = SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
552 if (silc_hmac_alloc(start_payload->hmac_alg_list, NULL,
553 &prop->hmac) == FALSE) {
554 status = SILC_SKE_STATUS_UNKNOWN_HMAC;
558 /* Encode the payload */
559 status = silc_ske_payload_start_encode(ske, start_payload, &payload_buf);
560 if (status != SILC_SKE_STATUS_OK)
563 /* Send the packet. */
565 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, context);
567 silc_buffer_free(payload_buf);
576 silc_pkcs_free(prop->pkcs);
578 silc_cipher_free(prop->cipher);
580 silc_hash_free(prop->hash);
582 silc_hmac_free(prop->hmac);
586 if (status == SILC_SKE_STATUS_OK)
587 return SILC_SKE_STATUS_ERROR;
589 ske->status = status;
593 /* This function receives the Key Exchange Payload from the initiator.
594 This also performs the mutual authentication if required. Then, this
595 function first generated a random number x, such that 1 < x < q
596 and computes f = g ^ x mod p. This then puts the result f to a Key
599 SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
600 SilcBuffer ke_payload,
601 SilcSKEVerifyCb verify_key,
602 void *verify_context,
606 SilcSKEStatus status = SILC_SKE_STATUS_OK;
607 SilcSKEKEPayload *recv_payload, *send_payload;
610 SILC_LOG_DEBUG(("Start"));
612 /* Decode Key Exchange Payload */
613 status = silc_ske_payload_ke_decode(ske, ke_payload, &recv_payload);
614 if (status != SILC_SKE_STATUS_OK) {
615 ske->status = status;
619 ske->ke1_payload = recv_payload;
621 /* Verify the received public key and verify the signature if we are
622 doing mutual authentication. */
623 if (ske->start_payload &&
624 ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
625 SilcPublicKey public_key = NULL;
626 unsigned char hash[32];
629 SILC_LOG_DEBUG(("We are doing mutual authentication"));
630 SILC_LOG_DEBUG(("Verifying public key"));
632 if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
633 recv_payload->pk_len,
635 status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
640 status = (*verify_key)(ske, recv_payload->pk_data, recv_payload->pk_len,
641 recv_payload->pk_type, verify_context);
642 if (status != SILC_SKE_STATUS_OK)
646 SILC_LOG_DEBUG(("Public key is authentic"));
648 /* Compute the hash value */
649 status = silc_ske_make_hash(ske, hash, &hash_len, TRUE);
650 if (status != SILC_SKE_STATUS_OK)
653 SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
655 /* Verify signature */
656 silc_pkcs_public_key_data_set(ske->prop->pkcs, public_key->pk,
658 if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
659 recv_payload->sign_len, hash, hash_len) == FALSE) {
661 SILC_LOG_DEBUG(("Signature don't match"));
663 status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
667 SILC_LOG_DEBUG(("Signature is Ok"));
669 silc_pkcs_public_key_free(public_key);
670 memset(hash, 'F', hash_len);
673 /* Create the random number x, 1 < x < q. */
674 x = silc_calloc(1, sizeof(*x));
677 silc_ske_create_rnd(ske, ske->prop->group->group_order,
678 silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
680 if (status != SILC_SKE_STATUS_OK) {
686 SILC_LOG_DEBUG(("Computing f = g ^ x mod p"));
688 /* Do the Diffie Hellman computation, f = g ^ x mod p */
690 silc_mp_powm(&f, &ske->prop->group->generator, x,
691 &ske->prop->group->group);
693 /* Save the results for later processing */
694 send_payload = silc_calloc(1, sizeof(*send_payload));
697 ske->ke2_payload = send_payload;
699 /* Call the callback. */
701 (*callback)(ske, context);
706 /* This functions generates the secret key KEY = e ^ x mod p, and, a hash
707 value to be signed and sent to the other end. This then encodes Key
708 Exchange Payload and sends it to the other end. */
710 SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
711 SilcPublicKey public_key,
712 SilcPrivateKey private_key,
713 SilcSKEPKType pk_type,
714 SilcSKESendPacketCb send_packet,
717 SilcSKEStatus status = SILC_SKE_STATUS_OK;
718 SilcBuffer payload_buf;
720 unsigned char hash[32], sign[1024], *pk;
721 uint32 hash_len, sign_len, pk_len;
723 SILC_LOG_DEBUG(("Start"));
725 SILC_LOG_DEBUG(("Computing KEY = e ^ x mod p"));
727 /* Compute the shared secret key */
728 KEY = silc_calloc(1, sizeof(*KEY));
730 silc_mp_powm(KEY, &ske->ke1_payload->x, ske->x,
731 &ske->prop->group->group);
734 if (public_key && private_key) {
735 SILC_LOG_DEBUG(("Getting public key"));
737 /* Get the public key */
738 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
740 status = SILC_SKE_STATUS_ERROR;
743 ske->ke2_payload->pk_data = pk;
744 ske->ke2_payload->pk_len = pk_len;
746 SILC_LOG_DEBUG(("Computing HASH value"));
748 /* Compute the hash value */
749 memset(hash, 0, sizeof(hash));
750 status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
751 if (status != SILC_SKE_STATUS_OK)
754 ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
755 memcpy(ske->hash, hash, hash_len);
756 ske->hash_len = hash_len;
758 SILC_LOG_DEBUG(("Signing HASH value"));
760 /* Sign the hash value */
761 silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
762 private_key->prv_len);
763 silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len);
764 ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
765 memcpy(ske->ke2_payload->sign_data, sign, sign_len);
766 memset(sign, 0, sizeof(sign));
767 ske->ke2_payload->sign_len = sign_len;
769 ske->ke2_payload->pk_type = pk_type;
771 /* Encode the Key Exchange Payload */
772 status = silc_ske_payload_ke_encode(ske, ske->ke2_payload,
774 if (status != SILC_SKE_STATUS_OK)
777 /* Send the packet. */
779 (*send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE_2, context);
781 silc_buffer_free(payload_buf);
786 silc_mp_clear(ske->KEY);
789 silc_ske_payload_ke_free(ske->ke2_payload);
791 if (status == SILC_SKE_STATUS_OK)
792 return SILC_SKE_STATUS_ERROR;
794 ske->status = status;
798 /* The Key Exchange protocol is ended by calling this function. This
799 must not be called until the keys are processed like the protocol
800 defines. This function is for both initiator and responder. */
802 SilcSKEStatus silc_ske_end(SilcSKE ske,
803 SilcSKESendPacketCb send_packet,
808 SILC_LOG_DEBUG(("Start"));
810 packet = silc_buffer_alloc(4);
811 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
812 silc_buffer_format(packet,
813 SILC_STR_UI_INT((uint32)SILC_SKE_STATUS_OK),
817 (*send_packet)(ske, packet, SILC_PACKET_SUCCESS, context);
819 silc_buffer_free(packet);
821 return SILC_SKE_STATUS_OK;
824 /* Aborts the Key Exchange protocol. This is called if error occurs
825 while performing the protocol. The status argument is the error
826 status and it is sent to the remote end. */
828 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status,
829 SilcSKESendPacketCb send_packet,
834 SILC_LOG_DEBUG(("Start"));
836 packet = silc_buffer_alloc(4);
837 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
838 silc_buffer_format(packet,
839 SILC_STR_UI_INT((uint32)status),
843 (*send_packet)(ske, packet, SILC_PACKET_FAILURE, context);
845 silc_buffer_free(packet);
847 return SILC_SKE_STATUS_OK;
850 /* Assembles security properties to Key Exchange Start Payload to be
851 sent to the remote end. This checks system wide (SILC system, that is)
852 settings and chooses from those. However, if other properties
853 should be used this function is easy to replace by another function,
854 as, this function is called by the caller of the protocol and not
855 by the protocol itself. */
858 silc_ske_assemble_security_properties(SilcSKE ske,
861 SilcSKEStartPayload **return_payload)
863 SilcSKEStartPayload *rp;
866 SILC_LOG_DEBUG(("Assembling KE Start Payload"));
868 rp = silc_calloc(1, sizeof(*rp));
873 /* Set random cookie */
874 rp->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(*rp->cookie));
875 for (i = 0; i < SILC_SKE_COOKIE_LEN; i++)
876 rp->cookie[i] = silc_rng_get_byte(ske->rng);
877 rp->cookie_len = SILC_SKE_COOKIE_LEN;
880 rp->version = strdup(version);
881 rp->version_len = strlen(version);
883 /* Get supported Key Exhange groups */
884 rp->ke_grp_list = silc_ske_get_supported_groups();
885 rp->ke_grp_len = strlen(rp->ke_grp_list);
887 /* Get supported PKCS algorithms */
888 rp->pkcs_alg_list = silc_pkcs_get_supported();
889 rp->pkcs_alg_len = strlen(rp->pkcs_alg_list);
891 /* Get supported encryption algorithms */
892 rp->enc_alg_list = silc_cipher_get_supported();
893 rp->enc_alg_len = strlen(rp->enc_alg_list);
895 /* Get supported hash algorithms */
896 rp->hash_alg_list = silc_hash_get_supported();
897 rp->hash_alg_len = strlen(rp->hash_alg_list);
899 /* Get supported HMACs */
900 rp->hmac_alg_list = silc_hmac_get_supported();
901 rp->hmac_alg_len = strlen(rp->hmac_alg_list);
904 /* Get supported compression algorithms */
905 rp->comp_alg_list = "";
906 rp->comp_alg_len = 0;
908 rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
909 2 + rp->version_len +
910 2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
911 2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
912 2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
914 *return_payload = rp;
916 return SILC_SKE_STATUS_OK;
919 /* Selects the supported security properties from the remote end's Key
920 Exchange Start Payload. */
923 silc_ske_select_security_properties(SilcSKE ske,
925 SilcSKEStartPayload *payload,
926 SilcSKEStartPayload *remote_payload)
928 SilcSKEStatus status;
929 SilcSKEStartPayload *rp;
933 SILC_LOG_DEBUG(("Parsing KE Start Payload"));
937 /* Check version string */
938 status = silc_ske_check_version(ske, rp->version, rp->version_len);
939 if (status != SILC_SKE_STATUS_OK) {
940 ske->status = status;
944 /* Flags are returned unchanged. */
945 payload->flags = rp->flags;
948 payload->cookie = silc_calloc(SILC_SKE_COOKIE_LEN, sizeof(unsigned char));
949 payload->cookie_len = SILC_SKE_COOKIE_LEN;
950 memcpy(payload->cookie, rp->cookie, SILC_SKE_COOKIE_LEN);
952 /* Put our version to our reply */
953 payload->version = strdup(version);
954 payload->version_len = strlen(version);
956 /* Get supported Key Exchange groups */
957 cp = rp->ke_grp_list;
958 if (cp && strchr(cp, ',')) {
962 len = strcspn(cp, ",");
963 item = silc_calloc(len + 1, sizeof(char));
964 memcpy(item, cp, len);
966 SILC_LOG_DEBUG(("Proposed KE group `%s'", item));
968 if (silc_ske_get_group_by_name(item, NULL) == SILC_SKE_STATUS_OK) {
969 SILC_LOG_DEBUG(("Found KE group `%s'", item));
971 payload->ke_grp_len = len;
972 payload->ke_grp_list = item;
986 if (!payload->ke_grp_len && !payload->ke_grp_list) {
987 SILC_LOG_DEBUG(("Could not find supported KE group"));
989 return SILC_SKE_STATUS_UNKNOWN_GROUP;
993 if (!rp->ke_grp_len) {
994 SILC_LOG_DEBUG(("KE group not defined in payload"));
996 return SILC_SKE_STATUS_BAD_PAYLOAD;
999 SILC_LOG_DEBUG(("Proposed KE group `%s'", rp->ke_grp_list));
1000 SILC_LOG_DEBUG(("Found KE group `%s'", rp->ke_grp_list));
1002 payload->ke_grp_len = rp->ke_grp_len;
1003 payload->ke_grp_list = strdup(rp->ke_grp_list);
1006 /* Get supported PKCS algorithms */
1007 cp = rp->pkcs_alg_list;
1008 if (cp && strchr(cp, ',')) {
1012 len = strcspn(cp, ",");
1013 item = silc_calloc(len + 1, sizeof(char));
1014 memcpy(item, cp, len);
1016 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
1018 if (silc_pkcs_is_supported(item) == TRUE) {
1019 SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
1021 payload->pkcs_alg_len = len;
1022 payload->pkcs_alg_list = item;
1027 if (strlen(cp) == 0)
1036 if (!payload->pkcs_alg_len && !payload->pkcs_alg_list) {
1037 SILC_LOG_DEBUG(("Could not find supported PKCS alg"));
1038 silc_free(payload->ke_grp_list);
1040 return SILC_SKE_STATUS_UNKNOWN_PKCS;
1044 if (!rp->pkcs_alg_len) {
1045 SILC_LOG_DEBUG(("PKCS alg not defined in payload"));
1046 silc_free(payload->ke_grp_list);
1048 return SILC_SKE_STATUS_BAD_PAYLOAD;
1051 SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", rp->pkcs_alg_list));
1052 SILC_LOG_DEBUG(("Found PKCS alg `%s'", rp->pkcs_alg_list));
1054 payload->pkcs_alg_len = rp->pkcs_alg_len;
1055 payload->pkcs_alg_list = strdup(rp->pkcs_alg_list);
1058 /* Get supported encryption algorithms */
1059 cp = rp->enc_alg_list;
1060 if (cp && strchr(cp, ',')) {
1064 len = strcspn(cp, ",");
1065 item = silc_calloc(len + 1, sizeof(char));
1066 memcpy(item, cp, len);
1068 SILC_LOG_DEBUG(("Proposed encryption alg `%s'", item));
1070 if (silc_cipher_is_supported(item) == TRUE) {
1071 SILC_LOG_DEBUG(("Found encryption alg `%s'", item));
1073 payload->enc_alg_len = len;
1074 payload->enc_alg_list = item;
1079 if (strlen(cp) == 0)
1088 if (!payload->enc_alg_len && !payload->enc_alg_list) {
1089 SILC_LOG_DEBUG(("Could not find supported encryption alg"));
1090 silc_free(payload->ke_grp_list);
1091 silc_free(payload->pkcs_alg_list);
1093 return SILC_SKE_STATUS_UNKNOWN_CIPHER;
1097 if (!rp->enc_alg_len) {
1098 SILC_LOG_DEBUG(("Encryption alg not defined in payload"));
1099 silc_free(payload->ke_grp_list);
1100 silc_free(payload->pkcs_alg_list);
1102 return SILC_SKE_STATUS_BAD_PAYLOAD;
1105 SILC_LOG_DEBUG(("Proposed encryption alg `%s' and selected it",
1108 payload->enc_alg_len = rp->enc_alg_len;
1109 payload->enc_alg_list = strdup(rp->enc_alg_list);
1112 /* Get supported hash algorithms */
1113 cp = rp->hash_alg_list;
1114 if (cp && strchr(cp, ',')) {
1118 len = strcspn(cp, ",");
1119 item = silc_calloc(len + 1, sizeof(char));
1120 memcpy(item, cp, len);
1122 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1124 if (silc_hash_is_supported(item) == TRUE) {
1125 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1127 payload->hash_alg_len = len;
1128 payload->hash_alg_list = item;
1133 if (strlen(cp) == 0)
1142 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1143 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1144 silc_free(payload->ke_grp_list);
1145 silc_free(payload->pkcs_alg_list);
1146 silc_free(payload->enc_alg_list);
1148 return SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION;
1152 if (!rp->hash_alg_len) {
1153 SILC_LOG_DEBUG(("Hash alg not defined in payload"));
1154 silc_free(payload->ke_grp_list);
1155 silc_free(payload->pkcs_alg_list);
1156 silc_free(payload->enc_alg_list);
1158 return SILC_SKE_STATUS_BAD_PAYLOAD;
1161 SILC_LOG_DEBUG(("Proposed hash alg `%s' and selected it",
1162 rp->hash_alg_list));
1164 payload->hash_alg_len = rp->hash_alg_len;
1165 payload->hash_alg_list = strdup(rp->hash_alg_list);
1168 /* Get supported HMACs */
1169 cp = rp->hmac_alg_list;
1170 if (cp && strchr(cp, ',')) {
1174 len = strcspn(cp, ",");
1175 item = silc_calloc(len + 1, sizeof(char));
1176 memcpy(item, cp, len);
1178 SILC_LOG_DEBUG(("Proposed HMAC `%s'", item));
1180 if (silc_hmac_is_supported(item) == TRUE) {
1181 SILC_LOG_DEBUG(("Found HMAC `%s'", item));
1183 payload->hmac_alg_len = len;
1184 payload->hmac_alg_list = item;
1189 if (strlen(cp) == 0)
1198 if (!payload->hmac_alg_len && !payload->hmac_alg_list) {
1199 SILC_LOG_DEBUG(("Could not find supported HMAC"));
1200 silc_free(payload->ke_grp_list);
1201 silc_free(payload->pkcs_alg_list);
1202 silc_free(payload->enc_alg_list);
1203 silc_free(payload->hash_alg_list);
1205 return SILC_SKE_STATUS_UNKNOWN_HMAC;
1209 if (!rp->hmac_alg_len) {
1210 SILC_LOG_DEBUG(("HMAC not defined in payload"));
1211 silc_free(payload->ke_grp_list);
1212 silc_free(payload->pkcs_alg_list);
1213 silc_free(payload->enc_alg_list);
1214 silc_free(payload->hash_alg_list);
1216 return SILC_SKE_STATUS_BAD_PAYLOAD;
1219 SILC_LOG_DEBUG(("Proposed HMAC `%s' and selected it",
1220 rp->hmac_alg_list));
1222 payload->hmac_alg_len = rp->hmac_alg_len;
1223 payload->hmac_alg_list = strdup(rp->hmac_alg_list);
1227 /* Get supported compression algorithms */
1228 cp = rp->hash_alg_list;
1229 if (cp && strchr(cp, ',')) {
1233 len = strcspn(cp, ",");
1234 item = silc_calloc(len + 1, sizeof(char));
1235 memcpy(item, cp, len);
1237 SILC_LOG_DEBUG(("Proposed hash alg `%s'", item));
1239 if (silc_hash_is_supported(item) == TRUE) {
1240 SILC_LOG_DEBUG(("Found hash alg `%s'", item));
1242 payload->hash_alg_len = len;
1243 payload->hash_alg_list = item;
1248 if (strlen(cp) == 0)
1257 if (!payload->hash_alg_len && !payload->hash_alg_list) {
1258 SILC_LOG_DEBUG(("Could not find supported hash alg"));
1259 silc_ske_abort(ske, SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION);
1260 silc_free(payload->ke_grp_list);
1261 silc_free(payload->pkcs_alg_list);
1262 silc_free(payload->enc_alg_list);
1271 payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
1272 2 + payload->version_len +
1273 2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
1274 2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
1275 2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
1277 return SILC_SKE_STATUS_OK;
1280 /* Creates random number such that 1 < rnd < n and at most length
1281 of len bits. The rnd sent as argument must be initialized. */
1283 SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcInt n,
1287 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1288 unsigned char *string;
1290 SILC_LOG_DEBUG(("Creating random number"));
1292 /* Get the random number as string */
1293 string = silc_rng_get_rn_data(ske->rng, (len / 8));
1295 return SILC_SKE_STATUS_ERROR;
1297 /* Decode the string into a MP integer */
1298 silc_mp_bin2mp(string, (len / 8), rnd);
1299 silc_mp_mod_2exp(rnd, rnd, len);
1302 if (silc_mp_cmp_ui(rnd, 1) < 0)
1303 status = SILC_SKE_STATUS_ERROR;
1305 if (silc_mp_cmp(rnd, &n) >= 0)
1306 status = SILC_SKE_STATUS_ERROR;
1308 memset(string, 'F', (len / 8));
1314 /* Creates a hash value HASH as defined in the SKE protocol. If the
1315 `initiator' is TRUE then this function is used to create the HASH_i
1316 hash value defined in the protocol. If it is FALSE then this is used
1317 to create the HASH value defined by the protocol. */
1319 SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
1320 unsigned char *return_hash,
1321 uint32 *return_hash_len,
1324 SilcSKEStatus status = SILC_SKE_STATUS_OK;
1326 unsigned char *e, *f, *KEY;
1327 uint32 e_len, f_len, KEY_len;
1330 SILC_LOG_DEBUG(("Start"));
1332 if (initiator == FALSE) {
1333 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1334 f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
1335 KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
1337 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1338 ske->pk_len + e_len + f_len + KEY_len);
1339 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1341 /* Format the buffer used to compute the hash value */
1343 silc_buffer_format(buf,
1344 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1345 ske->start_payload_copy->len),
1346 SILC_STR_UI_XNSTRING(ske->pk, ske->pk_len),
1347 SILC_STR_UI_XNSTRING(e, e_len),
1348 SILC_STR_UI_XNSTRING(f, f_len),
1349 SILC_STR_UI_XNSTRING(KEY, KEY_len),
1352 silc_buffer_free(buf);
1353 memset(e, 0, e_len);
1354 memset(f, 0, f_len);
1355 memset(KEY, 0, KEY_len);
1359 return SILC_SKE_STATUS_ERROR;
1362 memset(e, 0, e_len);
1363 memset(f, 0, f_len);
1364 memset(KEY, 0, KEY_len);
1369 e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
1371 buf = silc_buffer_alloc(ske->start_payload_copy->len +
1372 ske->pk_len + e_len);
1373 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1375 /* Format the buffer used to compute the hash value */
1377 silc_buffer_format(buf,
1378 SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
1379 ske->start_payload_copy->len),
1380 SILC_STR_UI_XNSTRING(ske->pk, ske->pk_len),
1381 SILC_STR_UI_XNSTRING(e, e_len),
1384 silc_buffer_free(buf);
1385 memset(e, 0, e_len);
1387 return SILC_SKE_STATUS_ERROR;
1390 memset(e, 0, e_len);
1395 silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
1396 *return_hash_len = ske->prop->hash->hash->hash_len;
1398 if (initiator == FALSE) {
1399 SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
1401 SILC_LOG_HEXDUMP(("HASH_i"), return_hash, *return_hash_len);
1404 silc_buffer_free(buf);
1409 /* Processes the provided key material `data' as the SILC protocol
1410 specification specifies. */
1413 silc_ske_process_key_material_data(unsigned char *data,
1416 uint32 req_enc_key_len,
1417 uint32 req_hmac_key_len,
1419 SilcSKEKeyMaterial *key)
1422 unsigned char hashd[32];
1423 uint32 hash_len = req_hmac_key_len;
1424 uint32 enc_key_len = req_enc_key_len / 8;
1426 SILC_LOG_DEBUG(("Start"));
1428 buf = silc_buffer_alloc(1 + data_len);
1429 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1430 silc_buffer_format(buf,
1431 SILC_STR_UI_CHAR(0),
1432 SILC_STR_UI_XNSTRING(data, data_len),
1436 memset(hashd, 0, sizeof(hashd));
1438 silc_hash_make(hash, buf->data, buf->len, hashd);
1439 key->send_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1440 memcpy(key->send_iv, hashd, req_iv_len);
1441 memset(hashd, 0, sizeof(hashd));
1443 silc_hash_make(hash, buf->data, buf->len, hashd);
1444 key->receive_iv = silc_calloc(req_iv_len, sizeof(unsigned char));
1445 memcpy(key->receive_iv, hashd, req_iv_len);
1446 key->iv_len = req_iv_len;
1448 /* Take the encryption keys. If requested key size is more than
1449 the size of hash length we will distribute more key material
1450 as protocol defines. */
1452 if (enc_key_len > hash_len) {
1454 unsigned char k1[32], k2[32], k3[32];
1455 unsigned char *dtmp;
1458 if (enc_key_len > (3 * hash_len))
1459 return SILC_SKE_STATUS_ERROR;
1461 /* Take first round */
1462 memset(k1, 0, sizeof(k1));
1463 silc_hash_make(hash, buf->data, buf->len, k1);
1465 /* Take second round */
1466 dist = silc_buffer_alloc(data_len + hash_len);
1467 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1468 silc_buffer_format(dist,
1469 SILC_STR_UI_XNSTRING(data, data_len),
1470 SILC_STR_UI_XNSTRING(k1, hash_len),
1472 memset(k2, 0, sizeof(k2));
1473 silc_hash_make(hash, dist->data, dist->len, k2);
1475 /* Take third round */
1476 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1477 silc_buffer_pull_tail(dist, hash_len);
1478 silc_buffer_pull(dist, data_len + hash_len);
1479 silc_buffer_format(dist,
1480 SILC_STR_UI_XNSTRING(k2, hash_len),
1482 silc_buffer_push(dist, data_len + hash_len);
1483 memset(k3, 0, sizeof(k3));
1484 silc_hash_make(hash, dist->data, dist->len, k3);
1486 /* Then, save the keys */
1487 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1488 memcpy(dtmp, k1, hash_len);
1489 memcpy(dtmp + hash_len, k2, hash_len);
1490 memcpy(dtmp + hash_len, k3, hash_len);
1492 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1493 memcpy(key->send_enc_key, dtmp, enc_key_len);
1494 key->enc_key_len = req_enc_key_len;
1496 memset(dtmp, 0, (3 * hash_len));
1497 memset(k1, 0, sizeof(k1));
1498 memset(k2, 0, sizeof(k2));
1499 memset(k3, 0, sizeof(k3));
1501 silc_buffer_free(dist);
1503 /* Take normal hash as key */
1504 memset(hashd, 0, sizeof(hashd));
1505 silc_hash_make(hash, buf->data, buf->len, hashd);
1506 key->send_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1507 memcpy(key->send_enc_key, hashd, enc_key_len);
1508 key->enc_key_len = req_enc_key_len;
1512 if (enc_key_len > hash_len) {
1514 unsigned char k1[32], k2[32], k3[32];
1515 unsigned char *dtmp;
1518 if (enc_key_len > (3 * hash_len))
1519 return SILC_SKE_STATUS_ERROR;
1521 /* Take first round */
1522 memset(k1, 0, sizeof(k1));
1523 silc_hash_make(hash, buf->data, buf->len, k1);
1525 /* Take second round */
1526 dist = silc_buffer_alloc(data_len + hash_len);
1527 silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
1528 silc_buffer_format(dist,
1529 SILC_STR_UI_XNSTRING(data, data_len),
1530 SILC_STR_UI_XNSTRING(k1, hash_len),
1532 memset(k2, 0, sizeof(k2));
1533 silc_hash_make(hash, dist->data, dist->len, k2);
1535 /* Take third round */
1536 dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
1537 silc_buffer_pull_tail(dist, hash_len);
1538 silc_buffer_pull(dist, data_len + hash_len);
1539 silc_buffer_format(dist,
1540 SILC_STR_UI_XNSTRING(k2, hash_len),
1542 silc_buffer_push(dist, data_len + hash_len);
1543 memset(k3, 0, sizeof(k3));
1544 silc_hash_make(hash, dist->data, dist->len, k3);
1546 /* Then, save the keys */
1547 dtmp = silc_calloc((3 * hash_len), sizeof(unsigned char));
1548 memcpy(dtmp, k1, hash_len);
1549 memcpy(dtmp + hash_len, k2, hash_len);
1550 memcpy(dtmp + hash_len, k3, hash_len);
1552 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1553 memcpy(key->receive_enc_key, dtmp, enc_key_len);
1554 key->enc_key_len = req_enc_key_len;
1556 memset(dtmp, 0, (3 * hash_len));
1557 memset(k1, 0, sizeof(k1));
1558 memset(k2, 0, sizeof(k2));
1559 memset(k3, 0, sizeof(k3));
1561 silc_buffer_free(dist);
1563 /* Take normal hash as key */
1564 memset(hashd, 0, sizeof(hashd));
1565 silc_hash_make(hash, buf->data, buf->len, hashd);
1566 key->receive_enc_key = silc_calloc(enc_key_len, sizeof(unsigned char));
1567 memcpy(key->receive_enc_key, hashd, enc_key_len);
1568 key->enc_key_len = req_enc_key_len;
1572 memset(hashd, 0, sizeof(hashd));
1574 silc_hash_make(hash, buf->data, buf->len, hashd);
1575 key->hmac_key = silc_calloc(req_hmac_key_len, sizeof(unsigned char));
1576 memcpy(key->hmac_key, hashd, req_hmac_key_len);
1577 key->hmac_key_len = req_hmac_key_len;
1579 silc_buffer_free(buf);
1581 return SILC_SKE_STATUS_OK;
1584 /* Processes negotiated key material as protocol specifies. This returns
1585 the actual keys to be used in the SILC. */
1587 SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
1589 uint32 req_enc_key_len,
1590 uint32 req_hmac_key_len,
1591 SilcSKEKeyMaterial *key)
1593 SilcSKEStatus status;
1595 unsigned char *tmpbuf;
1598 /* Encode KEY to binary data */
1599 tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
1601 buf = silc_buffer_alloc(klen + ske->hash_len);
1602 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1603 silc_buffer_format(buf,
1604 SILC_STR_UI_XNSTRING(tmpbuf, klen),
1605 SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
1608 /* Process the key material */
1609 status = silc_ske_process_key_material_data(buf->data, buf->len,
1610 req_iv_len, req_enc_key_len,
1612 ske->prop->hash, key);
1614 memset(tmpbuf, 0, klen);
1616 silc_buffer_free(buf);
1621 /* Free key material structure */
1623 void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
1629 silc_free(key->send_iv);
1630 if (key->receive_iv)
1631 silc_free(key->receive_iv);
1632 if (key->send_enc_key) {
1633 memset(key->send_enc_key, 0, key->enc_key_len / 8);
1634 silc_free(key->send_enc_key);
1636 if (key->receive_enc_key) {
1637 memset(key->receive_enc_key, 0, key->enc_key_len / 8);
1638 silc_free(key->receive_enc_key);
1640 if (key->hmac_key) {
1641 memset(key->hmac_key, 0, key->hmac_key_len);
1642 silc_free(key->hmac_key);