5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 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 "silcchannel_i.h"
24 #include "silcprivate_i.h"
26 /******************************************************************************
28 Authentication Payload
30 ******************************************************************************/
32 /* Authentication Payload structure */
33 struct SilcAuthPayloadStruct {
35 SilcUInt16 auth_method;
36 SilcUInt16 random_len;
37 unsigned char *random_data;
39 unsigned char *auth_data;
42 /* Parses and returns Authentication Payload */
44 SilcAuthPayload silc_auth_payload_parse(const unsigned char *data,
47 SilcBufferStruct buffer;
51 SILC_LOG_DEBUG(("Parsing Authentication Payload"));
53 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
54 newp = silc_calloc(1, sizeof(*newp));
58 /* Parse the payload */
59 ret = silc_buffer_unformat(&buffer,
60 SILC_STR_UI_SHORT(&newp->len),
61 SILC_STR_UI_SHORT(&newp->auth_method),
62 SILC_STR_UI16_NSTRING_ALLOC(&newp->random_data,
64 SILC_STR_UI16_NSTRING_ALLOC(&newp->auth_data,
72 if (newp->len != buffer.len ||
73 newp->random_len + newp->auth_len > buffer.len - 8) {
74 silc_auth_payload_free(newp);
78 /* Authentication data must be provided */
79 if (newp->auth_len < 1) {
80 silc_auth_payload_free(newp);
84 /* If password authentication, random data must not be set */
85 if (newp->auth_method == SILC_AUTH_PASSWORD && newp->random_len) {
86 silc_auth_payload_free(newp);
90 /* If public key authentication, random data must be at least 128 bytes */
91 if (newp->auth_method == SILC_AUTH_PUBLIC_KEY && newp->random_len < 128) {
92 silc_auth_payload_free(newp);
99 /* Encodes authentication payload into buffer and returns it */
101 SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
102 const unsigned char *random_data,
103 SilcUInt16 random_len,
104 const unsigned char *auth_data,
109 unsigned char *autf8 = NULL;
110 SilcUInt32 autf8_len;
112 SILC_LOG_DEBUG(("Encoding Authentication Payload"));
114 /* Passphrase MUST be UTF-8 encoded, encode if it is not */
115 if (method == SILC_AUTH_PASSWORD && !silc_utf8_valid(auth_data, auth_len)) {
116 autf8_len = silc_utf8_encoded_len(auth_data, auth_len, 0);
119 autf8 = silc_calloc(autf8_len, sizeof(*autf8));
120 auth_len = silc_utf8_encode(auth_data, auth_len, 0, autf8, autf8_len);
121 auth_data = (const unsigned char *)autf8;
124 len = 2 + 2 + 2 + random_len + 2 + auth_len;
125 buffer = silc_buffer_alloc_size(len);
131 silc_buffer_format(buffer,
132 SILC_STR_UI_SHORT(len),
133 SILC_STR_UI_SHORT(method),
134 SILC_STR_UI_SHORT(random_len),
135 SILC_STR_UI_XNSTRING(random_data, random_len),
136 SILC_STR_UI_SHORT(auth_len),
137 SILC_STR_UI_XNSTRING(auth_data, auth_len),
144 /* Frees authentication payload. */
146 void silc_auth_payload_free(SilcAuthPayload payload)
149 if (payload->random_data) {
150 memset(payload->random_data, 0, payload->random_len);
151 silc_free(payload->random_data);
153 if (payload->auth_data) {
154 memset(payload->auth_data, 0, payload->auth_len);
155 silc_free(payload->auth_data);
161 /* Get authentication method */
163 SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload)
165 return payload->auth_method;
168 /* Get the authentication data. If this is passphrase it is UTF-8 encoded. */
170 unsigned char *silc_auth_get_data(SilcAuthPayload payload,
171 SilcUInt32 *auth_len)
174 *auth_len = payload->auth_len;
176 return payload->auth_data;
179 /******************************************************************************
181 Authentication Routines
183 ******************************************************************************/
185 /* Encodes the authentication data for hashing and signing as the protocol
188 static unsigned char *
189 silc_auth_public_key_encode_data(SilcPublicKey public_key,
190 const unsigned char *randomdata,
191 SilcUInt32 random_len, const void *id,
192 SilcIdType type, SilcUInt32 *ret_len)
195 unsigned char *pk, *id_data, *ret;
196 SilcUInt32 pk_len, id_len;
198 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
202 id_data = silc_id_id2str(id, type);
207 id_len = silc_id_get_len(id, type);
209 buf = silc_buffer_alloc_size(random_len + id_len + pk_len);
215 silc_buffer_format(buf,
216 SILC_STR_UI_XNSTRING(randomdata, random_len),
217 SILC_STR_UI_XNSTRING(id_data, id_len),
218 SILC_STR_UI_XNSTRING(pk, pk_len),
221 ret = silc_memdup(buf->data, buf->len);
228 silc_buffer_clear(buf);
229 silc_buffer_free(buf);
236 /* Generates Authentication Payload with authentication data. This is used
237 to do public key based authentication. This generates the random data
238 and the actual authentication data. Returns NULL on error. */
240 SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key,
241 SilcPrivateKey private_key,
242 SilcRng rng, SilcHash hash,
243 const void *id, SilcIdType type)
245 unsigned char *randomdata;
246 unsigned char auth_data[2048];
253 SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
255 /* Get 256 bytes of random data */
257 randomdata = silc_rng_get_rn_data(rng, 256);
259 randomdata = silc_rng_global_get_rn_data(256);
263 /* Encode the auth data */
264 tmp = silc_auth_public_key_encode_data(public_key, randomdata, 256, id,
269 /* Allocate PKCS object */
270 if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
271 memset(tmp, 0, tmp_len);
275 silc_pkcs_public_key_set(pkcs, public_key);
276 silc_pkcs_private_key_set(pkcs, private_key);
278 /* Compute the hash and the signature. */
279 if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
280 !silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
282 memset(randomdata, 0, 256);
283 memset(tmp, 0, tmp_len);
285 silc_free(randomdata);
286 silc_pkcs_free(pkcs);
290 /* Encode Authentication Payload */
291 buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, randomdata, 256,
292 auth_data, auth_len);
294 memset(tmp, 0, tmp_len);
295 memset(auth_data, 0, sizeof(auth_data));
296 memset(randomdata, 0, 256);
298 silc_free(randomdata);
299 silc_pkcs_free(pkcs);
304 /* Verifies the authentication data. Returns TRUE if authentication was
307 bool silc_auth_public_key_auth_verify(SilcAuthPayload payload,
308 SilcPublicKey public_key, SilcHash hash,
309 const void *id, SilcIdType type)
315 SILC_LOG_DEBUG(("Verifying authentication data"));
317 /* Encode auth data */
318 tmp = silc_auth_public_key_encode_data(public_key, payload->random_data,
322 SILC_LOG_DEBUG(("Authentication failed"));
326 /* Allocate PKCS object */
327 if (!silc_pkcs_alloc(public_key->name, &pkcs)) {
328 memset(tmp, 0, tmp_len);
332 silc_pkcs_public_key_set(pkcs, public_key);
334 /* Verify the authentication data */
335 if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->auth_data,
336 payload->auth_len, tmp, tmp_len)) {
338 memset(tmp, 0, tmp_len);
340 silc_pkcs_free(pkcs);
341 SILC_LOG_DEBUG(("Authentication failed"));
345 memset(tmp, 0, tmp_len);
347 silc_pkcs_free(pkcs);
349 SILC_LOG_DEBUG(("Authentication successful"));
354 /* Same as above but the payload is not parsed yet. This will parse it. */
356 bool silc_auth_public_key_auth_verify_data(const unsigned char *payload,
357 SilcUInt32 payload_len,
358 SilcPublicKey public_key,
360 const void *id, SilcIdType type)
362 SilcAuthPayload auth_payload;
365 auth_payload = silc_auth_payload_parse(payload, payload_len);
367 SILC_LOG_DEBUG(("Authentication failed"));
371 ret = silc_auth_public_key_auth_verify(auth_payload, public_key, hash,
374 silc_auth_payload_free(auth_payload);
379 /* Verifies the authentication data directly from the Authentication
380 Payload. Supports all authentication methods. If the authentication
381 method is passphrase based then the `auth_data' and `auth_data_len'
382 are the passphrase and its length. If the method is public key
383 authentication then the `auth_data' is the SilcPublicKey and the
384 `auth_data_len' is ignored. */
386 bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method,
387 const void *auth_data, SilcUInt32 auth_data_len,
388 SilcHash hash, const void *id, SilcIdType type)
390 SILC_LOG_DEBUG(("Verifying authentication"));
392 if (!payload || auth_method != payload->auth_method)
395 switch (payload->auth_method) {
397 /* No authentication */
398 SILC_LOG_DEBUG(("No authentication required"));
401 case SILC_AUTH_PASSWORD:
402 /* Passphrase based authentication. The `pkcs', `hash', `id' and `type'
403 arguments are not needed. */
406 if ((payload->auth_len == 0) || !auth_data ||
407 payload->auth_len != auth_data_len)
410 if (!memcmp(payload->auth_data, auth_data, auth_data_len)) {
411 SILC_LOG_DEBUG(("Passphrase Authentication successful"));
416 case SILC_AUTH_PUBLIC_KEY:
417 /* Public key based authentication */
418 return silc_auth_public_key_auth_verify(payload, (SilcPublicKey)auth_data,
426 SILC_LOG_DEBUG(("Authentication failed"));
431 /* Same as above but parses the authentication payload before verify. */
433 bool silc_auth_verify_data(const unsigned char *payload,
434 SilcUInt32 payload_len,
435 SilcAuthMethod auth_method, const void *auth_data,
436 SilcUInt32 auth_data_len, SilcHash hash,
437 const void *id, SilcIdType type)
439 SilcAuthPayload auth_payload;
442 auth_payload = silc_auth_payload_parse(payload, payload_len);
443 if (!auth_payload || (auth_payload->auth_len == 0))
446 ret = silc_auth_verify(auth_payload, auth_method, auth_data, auth_data_len,
449 silc_auth_payload_free(auth_payload);
454 /******************************************************************************
456 Key Agreement Payload
458 ******************************************************************************/
460 /* The Key Agreement protocol structure */
461 struct SilcKeyAgreementPayloadStruct {
462 SilcUInt16 hostname_len;
463 unsigned char *hostname;
467 /* Parses and returns an allocated Key Agreement payload. */
469 SilcKeyAgreementPayload
470 silc_key_agreement_payload_parse(const unsigned char *payload,
471 SilcUInt32 payload_len)
473 SilcBufferStruct buffer;
474 SilcKeyAgreementPayload newp;
477 SILC_LOG_DEBUG(("Parsing Key Agreement Payload"));
479 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
480 newp = silc_calloc(1, sizeof(*newp));
484 /* Parse the payload */
485 ret = silc_buffer_unformat(&buffer,
486 SILC_STR_UI16_NSTRING_ALLOC(&newp->hostname,
487 &newp->hostname_len),
488 SILC_STR_UI_INT(&newp->port),
498 /* Encodes the Key Agreement protocol and returns the encoded buffer */
500 SilcBuffer silc_key_agreement_payload_encode(const char *hostname,
504 SilcUInt32 len = hostname ? strlen(hostname) : 0;
506 SILC_LOG_DEBUG(("Encoding Key Agreement Payload"));
508 buffer = silc_buffer_alloc_size(2 + len + 4);
511 silc_buffer_format(buffer,
512 SILC_STR_UI_SHORT(len),
513 SILC_STR_UI_XNSTRING(hostname, len),
514 SILC_STR_UI_INT(port),
520 /* Frees the Key Agreement protocol */
522 void silc_key_agreement_payload_free(SilcKeyAgreementPayload payload)
525 silc_free(payload->hostname);
530 /* Returns the hostname in the payload */
532 char *silc_key_agreement_get_hostname(SilcKeyAgreementPayload payload)
534 return payload->hostname;
537 /* Returns the port in the payload */
539 SilcUInt32 silc_key_agreement_get_port(SilcKeyAgreementPayload payload)
541 return payload->port;
544 /******************************************************************************
546 SILC_MESSAGE_FLAG_SIGNED Payload
548 ******************************************************************************/
550 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
551 struct SilcSignedPayloadStruct {
555 unsigned char *pk_data;
556 unsigned char *sign_data;
559 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
562 silc_signed_payload_encode_data(const unsigned char *message_payload,
563 SilcUInt32 message_payload_len,
565 SilcUInt32 pk_len, SilcUInt32 pk_type)
569 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
573 silc_buffer_format(sign,
574 SILC_STR_UI_XNSTRING(message_payload,
575 message_payload_len),
576 SILC_STR_UI_SHORT(pk_len),
577 SILC_STR_UI_SHORT(pk_type),
581 silc_buffer_pull(sign, message_payload_len + 4);
582 silc_buffer_format(sign,
583 SILC_STR_UI_XNSTRING(pk, pk_len),
585 silc_buffer_push(sign, message_payload_len + 4);
591 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
593 SilcSignedPayload silc_signed_payload_parse(const unsigned char *data,
596 SilcSignedPayload sig;
597 SilcBufferStruct buffer;
600 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
602 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
603 sig = silc_calloc(1, sizeof(*sig));
607 /* Parse the payload */
608 ret = silc_buffer_unformat(&buffer,
609 SILC_STR_UI_SHORT(&sig->pk_len),
610 SILC_STR_UI_SHORT(&sig->pk_type),
612 if (ret == -1 || sig->pk_len > data_len - 4) {
613 silc_signed_payload_free(sig);
617 silc_buffer_pull(&buffer, 4);
618 ret = silc_buffer_unformat(&buffer,
619 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
621 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
625 silc_signed_payload_free(sig);
628 silc_buffer_push(&buffer, 4);
630 /* Signature must be provided */
631 if (sig->sign_len < 1) {
632 silc_signed_payload_free(sig);
639 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
642 SilcBuffer silc_signed_payload_encode(const unsigned char *message_payload,
643 SilcUInt32 message_payload_len,
644 SilcPublicKey public_key,
645 SilcPrivateKey private_key,
647 bool include_public_key)
649 SilcBuffer buffer, sign;
651 unsigned char auth_data[2048];
653 unsigned char *pk = NULL;
654 SilcUInt32 pk_len = 0;
657 if (!message_payload || !message_payload_len || !private_key || !hash)
659 if (include_public_key && !public_key)
662 if (include_public_key)
663 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
665 /* Now we support only SILC style public key */
666 pk_type = SILC_SKE_PK_TYPE_SILC;
668 /* Encode the data to be signed */
669 sign = silc_signed_payload_encode_data(message_payload,
671 pk, pk_len, pk_type);
677 /* Sign the buffer */
679 /* Allocate PKCS object */
680 if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
681 silc_buffer_clear(sign);
682 silc_buffer_free(sign);
686 silc_pkcs_private_key_set(pkcs, private_key);
688 /* Compute the hash and the signature. */
689 if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
690 !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
692 silc_buffer_clear(sign);
693 silc_buffer_free(sign);
694 silc_pkcs_free(pkcs);
699 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
701 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
703 silc_buffer_clear(sign);
704 silc_buffer_free(sign);
705 silc_pkcs_free(pkcs);
706 memset(auth_data, 0, sizeof(auth_data));
711 silc_buffer_format(sign,
712 SILC_STR_UI_SHORT(pk_len),
713 SILC_STR_UI_SHORT(pk_type),
717 silc_buffer_pull(sign, 4);
718 silc_buffer_format(sign,
719 SILC_STR_UI_XNSTRING(pk, pk_len),
721 silc_buffer_push(sign, 4);
724 silc_buffer_pull(sign, 4 + pk_len);
725 silc_buffer_format(sign,
726 SILC_STR_UI_SHORT(auth_len),
727 SILC_STR_UI_XNSTRING(auth_data, auth_len),
729 silc_buffer_push(sign, 4 + pk_len);
731 memset(auth_data, 0, sizeof(auth_data));
732 silc_pkcs_free(pkcs);
733 silc_buffer_clear(sign);
734 silc_buffer_free(sign);
740 /* Free the payload */
742 void silc_signed_payload_free(SilcSignedPayload sig)
745 memset(sig->sign_data, 0, sig->sign_len);
746 silc_free(sig->sign_data);
747 silc_free(sig->pk_data);
752 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
754 int silc_signed_payload_verify(SilcSignedPayload sig,
755 bool channel_message,
756 void *message_payload,
757 SilcPublicKey remote_public_key,
760 int ret = SILC_AUTH_FAILED;
765 if (!sig || !remote_public_key || !hash)
768 /* Generate the signature verification data */
769 if (channel_message) {
770 SilcChannelMessagePayload chm =
771 (SilcChannelMessagePayload)message_payload;
774 /* Encode Channel Message Payload */
775 tmp = silc_buffer_alloc_size(6 + chm->data_len + chm->pad_len +
777 silc_buffer_format(tmp,
778 SILC_STR_UI_SHORT(chm->flags),
779 SILC_STR_UI_SHORT(chm->data_len),
780 SILC_STR_UI_XNSTRING(chm->data, chm->data_len),
781 SILC_STR_UI_SHORT(chm->pad_len),
782 SILC_STR_UI_XNSTRING(chm->pad, chm->pad_len),
783 SILC_STR_UI_XNSTRING(chm->iv, chm->iv_len),
786 sign = silc_signed_payload_encode_data(tmp->data, tmp->len,
787 sig->pk_data, sig->pk_len,
789 silc_buffer_clear(tmp);
790 silc_buffer_free(tmp);
792 SilcPrivateMessagePayload prm =
793 (SilcPrivateMessagePayload)message_payload;
796 /* Encode Private Message Payload */
797 tmp = silc_buffer_alloc_size(4 + prm->data_len +
798 SILC_PRIVATE_MESSAGE_PAD(4 + prm->data_len));
799 silc_buffer_format(tmp,
800 SILC_STR_UI_SHORT(prm->flags),
801 SILC_STR_UI_SHORT(prm->message_len),
802 SILC_STR_UI_XNSTRING(prm->message, prm->message_len),
805 sign = silc_signed_payload_encode_data(tmp->data, tmp->len,
806 sig->pk_data, sig->pk_len,
808 silc_buffer_clear(tmp);
809 silc_buffer_free(tmp);
815 /* Allocate PKCS object */
816 if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
817 silc_buffer_clear(sign);
818 silc_buffer_free(sign);
821 silc_pkcs_public_key_set(pkcs, remote_public_key);
823 /* Verify the authentication data */
824 if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->sign_data
826 sign->data, sign->len)) {
828 silc_buffer_clear(sign);
829 silc_buffer_free(sign);
830 silc_pkcs_free(pkcs);
831 SILC_LOG_DEBUG(("Signature verification failed"));
837 silc_buffer_clear(sign);
838 silc_buffer_free(sign);
839 silc_pkcs_free(pkcs);
841 SILC_LOG_DEBUG(("Signature verification successful"));
847 /* Return the public key from the payload */
849 SilcPublicKey silc_signed_payload_get_public_key(SilcSignedPayload sig)
853 if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,