5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 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.
19 /* Implementation of the Message Payload used as channel messages and
24 #include "silcmessage.h"
26 /*************************** Types and definitions **************************/
28 /* Calculates padding length for message payload */
29 #define SILC_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
31 /* Header length plus maximum padding length */
32 #define SILC_MESSAGE_HLEN 6 + 16
34 /* Maximum message length */
35 #define SILC_MESSAGE_MAX_LEN SILC_PACKET_MAX_LEN - SILC_MESSAGE_HLEN - 16
37 /* Payload encoding context */
42 SilcMessagePayloadEncoded encoded;
44 SilcMessageFlags flags;
45 SilcPublicKey public_key;
46 SilcPrivateKey private_key;
54 SilcUInt16 payload_len;
60 /************************* Static utility functions *************************/
63 silc_message_payload_encode_final(SilcBuffer buffer,
64 SilcMessageFlags flags,
69 SilcUInt32 payload_len,
74 SilcMessagePayloadEncoded encoded,
77 /* Returns the data length that fits to the packet. If data length is too
78 big it will be truncated to fit to the payload. */
81 SilcUInt32 silc_message_payload_datalen(SilcUInt32 data_len,
82 SilcUInt32 header_len,
84 SilcPublicKey public_key,
85 SilcPrivateKey private_key)
87 SilcUInt32 pklen = (flags & SILC_MESSAGE_FLAG_SIGNED && public_key ?
88 silc_pkcs_public_key_get_len(public_key) : 0);
89 SilcUInt32 prlen = (flags & SILC_MESSAGE_FLAG_SIGNED ?
90 silc_pkcs_private_key_get_len(private_key) / 8 : 0);
91 SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
93 if (silc_unlikely(dlen > SILC_MESSAGE_MAX_LEN))
94 data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
99 /* Free signed payload */
101 static void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
103 if (sig->sign_data) {
104 memset(sig->sign_data, 0, sig->sign_len);
105 silc_free(sig->sign_data);
107 silc_free(sig->pk_data);
110 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
113 silc_message_signed_payload_parse(const unsigned char *data,
115 SilcMessageSignedPayload sig)
117 SilcBufferStruct buffer;
120 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
122 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
124 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
126 /* Parse the payload */
127 ret = silc_buffer_unformat(&buffer,
128 SILC_STR_UI_SHORT(&sig->pk_len),
129 SILC_STR_UI_SHORT(&sig->pk_type),
131 if (ret == -1 || sig->pk_len > data_len - 4) {
132 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
137 silc_buffer_pull(&buffer, 4);
138 ret = silc_buffer_unformat(&buffer,
139 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
141 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
144 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
146 silc_message_signed_payload_free(sig);
147 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
150 silc_buffer_push(&buffer, 4);
152 /* Signature must be provided */
153 if (sig->sign_len < 1) {
154 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
156 silc_message_signed_payload_free(sig);
163 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
166 silc_message_signed_encode_data(SilcStack stack,
167 const unsigned char *message_payload,
168 SilcUInt32 message_payload_len,
170 SilcUInt32 pk_len, SilcUInt32 pk_type)
174 sign = silc_buffer_salloc_size(stack, message_payload_len + 4 + pk_len);
178 silc_buffer_sformat(stack, sign,
179 SILC_STR_DATA(message_payload, message_payload_len),
180 SILC_STR_UI_SHORT(pk_len),
181 SILC_STR_UI_SHORT(pk_type),
185 silc_buffer_pull(sign, message_payload_len + 4);
186 silc_buffer_sformat(stack, sign,
187 SILC_STR_UI_XNSTRING(pk, pk_len),
189 silc_buffer_push(sign, message_payload_len + 4);
195 /* Signature callback */
197 void silc_message_signed_payload_encode_cb(SilcBool success,
198 const unsigned char *signature,
199 SilcUInt32 signature_len,
202 SilcMessageEncode *e = context;
203 SilcPKCSType pk_type;
204 SilcStack stack = e->stack;
205 SilcBuffer buffer, payload;
206 SilcMessageFlags flags;
210 SilcUInt32 iv_len, payload_len;
212 SilcMessagePayloadEncoded encoded;
213 void *encoded_context;
216 e->encoded(NULL, e->context);
217 silc_buffer_sfree(stack, e->sign);
218 silc_sfree(stack, e->pk);
219 silc_sfree(stack, e);
220 silc_stack_free(stack);
224 pk_type = silc_pkcs_get_type(e->private_key);
226 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
227 buffer = silc_buffer_salloc_size(stack, 4 + e->pk_len + 2 + signature_len);
229 e->encoded(NULL, e->context);
230 silc_buffer_sfree(stack, e->sign);
231 silc_sfree(stack, e->pk);
232 silc_sfree(stack, e);
233 silc_stack_free(stack);
237 silc_buffer_sformat(stack, buffer,
238 SILC_STR_UI_SHORT(e->pk_len),
239 SILC_STR_UI_SHORT(pk_type),
242 if (e->pk_len && e->pk) {
243 silc_buffer_pull(buffer, 4);
244 silc_buffer_sformat(stack, buffer,
245 SILC_STR_DATA(e->pk, e->pk_len),
247 silc_buffer_push(buffer, 4);
250 silc_buffer_pull(buffer, 4 + e->pk_len);
251 silc_buffer_sformat(stack, buffer,
252 SILC_STR_UI_SHORT(signature_len),
253 SILC_STR_DATA(signature, signature_len),
255 silc_buffer_push(buffer, 4 + e->pk_len);
257 SILC_LOG_HEXDUMP(("SIG payload"), buffer->data, silc_buffer_len(buffer));
265 payload_len = e->payload_len;
268 encoded = e->encoded;
269 encoded_context = e->context;
271 silc_sfree(stack, e->pk);
272 silc_buffer_sfree(stack, e->sign);
273 silc_sfree(stack, e);
275 /* Finalize message payload encoding */
276 silc_message_payload_encode_final(payload, flags, cipher, hmac,
277 iv, iv_len, payload_len,
278 sid, rid, stack, buffer,
279 encoded, encoded_context);
282 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
285 static SilcAsyncOperation
286 silc_message_signed_payload_encode(SilcBuffer payload,
287 SilcMessageEncode *e)
289 SilcAsyncOperation op;
291 unsigned char *pk = NULL;
292 SilcUInt32 pk_len = 0;
294 SilcStack stack = e->stack;
295 SilcHash hash = e->hash;
296 SilcPublicKey public_key = e->public_key;
297 SilcPrivateKey private_key = e->private_key;
298 unsigned char *message_payload;
299 SilcUInt16 message_payload_len;
301 message_payload = payload->head;
302 message_payload_len = silc_buffer_headlen(payload);
304 if (!message_payload || !message_payload_len || !private_key || !hash) {
305 e->encoded(NULL, e->context);
306 silc_sfree(stack, e);
307 silc_stack_free(stack);
312 e->pk = pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len);
314 e->encoded(NULL, e->context);
315 silc_sfree(stack, e);
316 silc_stack_free(stack);
321 pk_type = silc_pkcs_get_type(private_key);
323 /* Encode the data to be signed */
324 e->sign = sign = silc_message_signed_encode_data(stack, message_payload,
326 pk, pk_len, pk_type);
328 e->encoded(NULL, e->context);
329 silc_sfree(stack, pk);
330 silc_sfree(stack, e);
331 silc_stack_free(stack);
335 /* Compute signature */
336 op = silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
337 TRUE, hash, silc_message_signed_payload_encode_cb, e);
342 /***************************** Payload parsing ******************************/
344 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
346 SilcBool silc_message_payload_decrypt(unsigned char *data,
348 SilcBool private_message,
352 unsigned char *sender_id,
353 SilcUInt32 sender_id_len,
354 unsigned char *receiver_id,
355 SilcUInt32 receiver_id_len,
358 SilcUInt32 mac_len, iv_len = 0, block_len;
359 SilcUInt16 len, totlen;
360 unsigned char mac[32], *ivp;
362 mac_len = silc_hmac_len(hmac);
363 block_len = silc_cipher_get_block_len(cipher);
365 /* IV is present for all channel messages, and private messages when
366 static key (pre-shared key) is used. */
367 if (!private_message || (private_message && static_key))
370 if (silc_unlikely(data_len < (mac_len + iv_len + block_len)))
373 if (silc_likely(check_mac)) {
374 /* Check the MAC of the message */
375 SILC_LOG_DEBUG(("Checking message MAC"));
376 silc_hmac_init(hmac);
377 silc_hmac_update(hmac, data, data_len - mac_len);
378 silc_hmac_update(hmac, sender_id, sender_id_len);
379 silc_hmac_update(hmac, receiver_id, receiver_id_len);
380 silc_hmac_final(hmac, mac, &mac_len);
381 if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
382 SILC_LOG_DEBUG(("Message MAC does not match"));
385 SILC_LOG_DEBUG(("MAC is Ok"));
388 /* Decrypt first only one block to get the header and then rest of
389 the data. This is done because there might be unencrypted data at
390 the end and we don't know the encrypted length yet. */
392 /* Get pointer to the IV */
393 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
394 silc_cipher_get_iv(cipher));
397 if (silc_unlikely(!silc_cipher_decrypt(cipher, data, data, block_len,
403 /* Get the payload length and decrypt rest */
405 SILC_GET16_MSB(len, data + totlen);
407 if (silc_unlikely(totlen + iv_len + mac_len + 2 > data_len))
410 if (totlen >= block_len)
411 if (silc_unlikely(!silc_cipher_decrypt(cipher, data + block_len,
413 (totlen - block_len) +
414 SILC_MESSAGE_PAD(totlen), ivp))) {
422 /* Parses Message Payload returning new payload structure. This also
423 decrypts it and checks the MAC. */
426 silc_message_payload_parse(unsigned char *payload,
427 SilcUInt32 payload_len,
428 SilcBool private_message,
432 unsigned char *sender_id,
433 SilcUInt32 sender_id_len,
434 unsigned char *receiver_id,
435 SilcUInt32 receiver_id_len,
437 SilcBool no_allocation,
438 SilcMessagePayload message)
440 SilcBufferStruct buffer;
441 SilcMessagePayload newp = NULL;
443 SilcUInt32 mac_len = 0, iv_len = 0;
445 SILC_LOG_DEBUG(("Parsing Message Payload"));
447 silc_buffer_set(&buffer, payload, payload_len);
449 /* Decrypt the payload */
450 if (silc_likely(cipher)) {
451 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
452 private_message, static_key,
453 cipher, hmac, sender_id,
454 sender_id_len, receiver_id,
455 receiver_id_len, TRUE);
456 if (silc_unlikely(ret == FALSE))
460 if (silc_likely(hmac))
461 mac_len = silc_hmac_len(hmac);
463 /* IV is present for all channel messages, and private messages when
464 static key (pre-shared key) is used. */
465 if (cipher && (!private_message || (private_message && static_key)))
466 iv_len = silc_cipher_get_block_len(cipher);
469 newp = message = silc_calloc(1, sizeof(*newp));
470 if (silc_unlikely(!newp))
473 memset(message, 0, sizeof(*message));
474 message->allocated = (stack || no_allocation ? FALSE : TRUE);
476 /* Parse the Message Payload. */
478 ret = silc_buffer_sunformat(stack, &buffer,
479 SILC_STR_UI_SHORT(&message->flags),
480 SILC_STR_UI16_NSTRING_ALLOC(&message->data,
482 SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
486 ret = silc_buffer_unformat(&buffer,
487 SILC_STR_UI_SHORT(&message->flags),
488 SILC_STR_UI16_NSTRING(&message->data,
490 SILC_STR_UI16_NSTRING(&message->pad,
493 if (silc_unlikely(ret == -1))
496 if (silc_unlikely((message->data_len > silc_buffer_len(&buffer) -
497 6 - mac_len - iv_len) ||
498 (message->pad_len + message->data_len >
499 silc_buffer_len(&buffer) - 6 - mac_len - iv_len))) {
500 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
504 /* Parse Signed Message Payload if provided */
505 if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
506 message->data_len + message->pad_len + 6 + mac_len +
507 iv_len < silc_buffer_len(&buffer)) {
508 if (!silc_message_signed_payload_parse(buffer.data + 6 +
511 silc_buffer_len(&buffer) -
512 iv_len - mac_len - 6 -
519 /* Parse MAC from the payload */
521 message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
527 silc_message_payload_free(newp);
532 /***************************** Payload encoding *****************************/
534 /* This function is used to encrypt the Messsage Payload which is
535 the `data' and `data_len'. This is used internally by the Message
536 Payload encoding routines but application may call this too if needed.
537 The `true_len' is the data length which is used to create MAC out of. */
539 SilcBool silc_message_payload_encrypt(unsigned char *data,
548 unsigned char sid[32], rid[32];
549 SilcUInt32 sid_len = 0, rid_len = 0;
551 /* Encrypt payload of the packet */
552 if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv)))
556 silc_id_id2str(&sender_id->u.client_id, SILC_ID_CLIENT, sid, sizeof(sid),
558 if (receiver_id->type == SILC_ID_CLIENT)
559 silc_id_id2str(&receiver_id->u.client_id, SILC_ID_CLIENT, rid,
560 sizeof(rid), &rid_len);
561 else if (receiver_id->type == SILC_ID_CHANNEL)
562 silc_id_id2str(&receiver_id->u.channel_id, SILC_ID_CHANNEL, rid,
563 sizeof(rid), &rid_len);
565 /* Compute the MAC of the encrypted message data */
566 silc_hmac_init(hmac);
567 silc_hmac_update(hmac, data, true_len);
568 silc_hmac_update(hmac, sid, sid_len);
569 silc_hmac_update(hmac, rid, rid_len);
570 silc_hmac_final(hmac, data + true_len, NULL);
575 /* Encrypt message payload */
577 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
578 void *value, void *context)
580 SilcMessageEncode *e = context;
583 if (!e->cipher || !e->hmac)
586 mac_len = silc_hmac_len(e->hmac);
587 if (silc_unlikely(!silc_buffer_enlarge(buffer, mac_len)))
590 if (silc_unlikely(!silc_message_payload_encrypt(buffer->head,
592 silc_buffer_headlen(buffer),
593 e->iv, &e->sid, &e->rid,
594 e->cipher, e->hmac)))
600 /* Finalize message payload encoding */
603 silc_message_payload_encode_final(SilcBuffer buffer,
604 SilcMessageFlags flags,
609 SilcUInt32 payload_len,
613 SilcBuffer signature,
614 SilcMessagePayloadEncoded encoded,
623 e.rid = *receiver_id;
625 e.payload_len = payload_len;
628 if (silc_buffer_format(buffer,
629 SILC_STR_DATA(silc_buffer_data(signature),
630 silc_buffer_len(signature)),
631 SILC_STR_DATA(iv, iv_len),
632 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
635 silc_buffer_sfree(stack, buffer);
636 encoded(NULL, context);
640 /* Deliver message payload */
641 silc_buffer_start(buffer);
642 encoded(buffer, context);
644 silc_buffer_sfree(stack, buffer);
645 silc_buffer_sfree(stack, signature);
646 silc_stack_free(stack);
649 /* Encodes Message Payload into a buffer and returns it. */
652 silc_message_payload_encode(SilcMessageFlags flags,
653 const unsigned char *data,
655 SilcBool generate_iv,
656 SilcBool private_message,
660 SilcPublicKey public_key,
661 SilcPrivateKey private_key,
666 SilcMessagePayloadEncoded encoded,
669 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
670 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
674 SILC_LOG_DEBUG(("Encoding Message Payload"));
676 if (silc_unlikely(!data_len)) {
677 encoded(NULL, context);
680 if (silc_unlikely(!private_message && (!cipher || !hmac))) {
681 encoded(NULL, context);
685 stack = silc_stack_alloc(0, stack ? stack : silc_crypto_stack());
687 buffer = silc_buffer_salloc(stack, 0);
688 if (silc_unlikely(!buffer)) {
689 encoded(NULL, context);
690 silc_stack_free(stack);
694 /* For channel messages IV is always generated */
695 if (!private_message && !generate_iv)
699 if (cipher && generate_iv) {
700 iv_len = silc_cipher_get_block_len(cipher);
702 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
704 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
709 mac_len = silc_hmac_len(hmac);
710 data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
711 public_key, private_key);
713 /* Calculate length of padding. IV is not included into the calculation
714 since it is not encrypted. */
715 pad_len = SILC_MESSAGE_PAD(6 + data_len);
717 /* Generate padding */
720 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
722 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
726 /* Encode the Message Payload */
727 if (silc_buffer_format(buffer,
729 SILC_STR_UI_SHORT(flags),
730 SILC_STR_UI_SHORT(data_len),
731 SILC_STR_DATA(data, data_len),
732 SILC_STR_UI_SHORT(pad_len),
733 SILC_STR_DATA(pad, pad_len),
735 silc_buffer_sfree(stack, buffer);
736 encoded(NULL, context);
737 silc_stack_free(stack);
741 if (flags & SILC_MESSAGE_FLAG_SIGNED) {
742 SilcMessageEncode *e = silc_scalloc(stack, 1, sizeof(*e));
744 silc_buffer_sfree(stack, buffer);
745 encoded(NULL, context);
746 silc_stack_free(stack);
753 e->public_key = public_key;
754 e->private_key = private_key;
759 e->rid = *receiver_id;
760 e->iv = iv_len ? iv : NULL;
762 e->payload_len = 6 + data_len + pad_len;
764 /* Compute signature */
765 return silc_message_signed_payload_encode(buffer, e);
769 silc_message_payload_encode_final(buffer, flags, cipher, hmac,
770 iv_len ? iv : NULL, iv_len,
771 6 + data_len + pad_len,
772 sender_id, receiver_id, stack, NULL,
777 /* Free's Message Payload */
779 void silc_message_payload_free(SilcMessagePayload payload)
781 silc_message_signed_payload_free(&payload->sig);
783 memset(payload->data, 0, payload->data_len);
784 if (payload->allocated)
785 silc_free(payload->data);
787 if (payload->allocated) {
788 silc_free(payload->pad);
795 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
797 return payload->flags;
802 unsigned char *silc_message_get_data(SilcMessagePayload payload,
803 SilcUInt32 *data_len)
806 *data_len = payload->data_len;
807 return payload->data;
810 /* Return MAC. The caller knows the length of the MAC */
812 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
817 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
820 silc_message_signed_verify(SilcMessagePayload message,
821 SilcPublicKey remote_public_key,
823 SilcAuthResultCb result,
826 SilcAsyncOperation op;
827 SilcBuffer sign, tmp;
828 SilcStack stack = NULL;
829 SilcMessageSignedPayload sig = &message->sig;
831 if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
832 !sig->sign_len || !remote_public_key || !hash) {
833 result(FALSE, context);
837 if (silc_crypto_stack())
838 stack = silc_stack_alloc(0, silc_crypto_stack());
840 /* Generate the signature verification data, the Message Payload */
841 tmp = silc_buffer_salloc_size(stack,
842 6 + message->data_len + message->pad_len);
843 silc_buffer_sformat(stack, tmp,
844 SILC_STR_UI_SHORT(message->flags),
845 SILC_STR_UI_SHORT(message->data_len),
846 SILC_STR_DATA(message->data, message->data_len),
847 SILC_STR_UI_SHORT(message->pad_len),
848 SILC_STR_DATA(message->pad, message->pad_len),
850 sign = silc_message_signed_encode_data(stack, tmp->data, silc_buffer_len(tmp),
851 sig->pk_data, sig->pk_len,
853 silc_buffer_clear(tmp);
854 silc_buffer_sfree(stack, tmp);
857 result(FALSE, context);
858 silc_stack_free(stack);
862 /* Verify the authentication data */
863 op = silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len,
864 silc_buffer_data(sign), silc_buffer_len(sign), hash,
867 silc_buffer_clear(sign);
868 silc_buffer_sfree(stack, sign);
869 silc_stack_free(stack);
874 /* Return the public key from the payload */
877 silc_message_signed_get_public_key(SilcMessagePayload payload,
878 const unsigned char **pk_data,
879 SilcUInt32 *pk_data_len)
882 SilcMessageSignedPayload sig = &payload->sig;
887 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
892 *pk_data = sig->pk_data;
894 *pk_data_len = sig->pk_len;