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 */
39 SilcMessageFlags flags;
40 SilcPublicKey public_key;
41 SilcPrivateKey private_key;
46 SilcUInt16 payload_len;
52 /************************* Static utility functions *************************/
54 /* Returns the data length that fits to the packet. If data length is too
55 big it will be truncated to fit to the payload. */
58 SilcUInt32 silc_message_payload_datalen(SilcUInt32 data_len,
59 SilcUInt32 header_len,
61 SilcPublicKey public_key,
62 SilcPrivateKey private_key)
64 SilcUInt32 pklen = (flags & SILC_MESSAGE_FLAG_SIGNED && public_key ?
65 silc_pkcs_public_key_get_len(public_key) : 0);
66 SilcUInt32 prlen = (flags & SILC_MESSAGE_FLAG_SIGNED ?
67 silc_pkcs_private_key_get_len(private_key) / 8 : 0);
68 SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
70 if (silc_unlikely(dlen > SILC_MESSAGE_MAX_LEN))
71 data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
76 /* Free signed payload */
78 static void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
81 memset(sig->sign_data, 0, sig->sign_len);
82 silc_free(sig->sign_data);
84 silc_free(sig->pk_data);
87 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
90 silc_message_signed_payload_parse(const unsigned char *data,
92 SilcMessageSignedPayload sig)
94 SilcBufferStruct buffer;
97 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
99 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
101 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
103 /* Parse the payload */
104 ret = silc_buffer_unformat(&buffer,
105 SILC_STR_UI_SHORT(&sig->pk_len),
106 SILC_STR_UI_SHORT(&sig->pk_type),
108 if (ret == -1 || sig->pk_len > data_len - 4) {
109 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
114 silc_buffer_pull(&buffer, 4);
115 ret = silc_buffer_unformat(&buffer,
116 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
118 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
121 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
123 silc_message_signed_payload_free(sig);
124 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
127 silc_buffer_push(&buffer, 4);
129 /* Signature must be provided */
130 if (sig->sign_len < 1) {
131 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
133 silc_message_signed_payload_free(sig);
140 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
143 silc_message_signed_encode_data(const unsigned char *message_payload,
144 SilcUInt32 message_payload_len,
146 SilcUInt32 pk_len, SilcUInt32 pk_type)
150 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
154 silc_buffer_format(sign,
155 SILC_STR_UI_XNSTRING(message_payload,
156 message_payload_len),
157 SILC_STR_UI_SHORT(pk_len),
158 SILC_STR_UI_SHORT(pk_type),
162 silc_buffer_pull(sign, message_payload_len + 4);
163 silc_buffer_format(sign,
164 SILC_STR_UI_XNSTRING(pk, pk_len),
166 silc_buffer_push(sign, message_payload_len + 4);
172 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
176 silc_message_signed_payload_encode(const unsigned char *message_payload,
177 SilcUInt32 message_payload_len,
178 SilcPublicKey public_key,
179 SilcPrivateKey private_key,
182 SilcBuffer buffer, sign;
183 unsigned char auth_data[2048 + 1];
185 unsigned char *pk = NULL;
186 SilcUInt32 pk_len = 0;
189 if (!message_payload || !message_payload_len || !private_key || !hash)
193 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
197 pk_type = silc_pkcs_get_type(private_key);
199 /* Encode the data to be signed */
200 sign = silc_message_signed_encode_data(message_payload,
202 pk, pk_len, pk_type);
208 /* Sign the buffer */
210 /* Compute the hash and the signature. */
211 if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
212 auth_data, sizeof(auth_data) - 1, &auth_len,
214 SILC_LOG_ERROR(("Could not compute signature"));
215 silc_buffer_clear(sign);
216 silc_buffer_free(sign);
221 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
223 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
225 silc_buffer_clear(sign);
226 silc_buffer_free(sign);
227 memset(auth_data, 0, sizeof(auth_data));
232 silc_buffer_format(buffer,
233 SILC_STR_UI_SHORT(pk_len),
234 SILC_STR_UI_SHORT(pk_type),
238 silc_buffer_pull(buffer, 4);
239 silc_buffer_format(buffer,
240 SILC_STR_UI_XNSTRING(pk, pk_len),
242 silc_buffer_push(buffer, 4);
245 silc_buffer_pull(buffer, 4 + pk_len);
246 silc_buffer_format(buffer,
247 SILC_STR_UI_SHORT(auth_len),
248 SILC_STR_UI_XNSTRING(auth_data, auth_len),
250 silc_buffer_push(buffer, 4 + pk_len);
252 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
254 memset(auth_data, 0, sizeof(auth_data));
255 silc_buffer_clear(sign);
256 silc_buffer_free(sign);
263 /***************************** Payload parsing ******************************/
265 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
267 SilcBool silc_message_payload_decrypt(unsigned char *data,
269 SilcBool private_message,
273 unsigned char *sender_id,
274 SilcUInt32 sender_id_len,
275 unsigned char *receiver_id,
276 SilcUInt32 receiver_id_len,
279 SilcUInt32 mac_len, iv_len = 0, block_len;
280 SilcUInt16 len, totlen;
281 unsigned char mac[32], *ivp;
283 mac_len = silc_hmac_len(hmac);
284 block_len = silc_cipher_get_block_len(cipher);
286 /* IV is present for all channel messages, and private messages when
287 static key (pre-shared key) is used. */
288 if (!private_message || (private_message && static_key))
291 if (silc_unlikely(data_len < (mac_len + iv_len + block_len)))
294 if (silc_likely(check_mac)) {
295 /* Check the MAC of the message */
296 SILC_LOG_DEBUG(("Checking message MAC"));
297 silc_hmac_init(hmac);
298 silc_hmac_update(hmac, data, data_len - mac_len);
299 silc_hmac_update(hmac, sender_id, sender_id_len);
300 silc_hmac_update(hmac, receiver_id, receiver_id_len);
301 silc_hmac_final(hmac, mac, &mac_len);
302 if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
304 SILC_LOG_DEBUG(("Message MAC does not match"));
307 /* Check for old style message MAC. Remove this check at some point. */
308 silc_hmac_init(hmac);
309 silc_hmac_update(hmac, data, data_len - mac_len);
310 silc_hmac_final(hmac, mac, &mac_len);
311 if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
312 SILC_LOG_DEBUG(("Message MAC does not match"));
317 SILC_LOG_DEBUG(("MAC is Ok"));
320 /* Decrypt first only one block to get the header and then rest of
321 the data. This is done because there might be unencrypted data at
322 the end and we don't know the encrypted length yet. */
324 /* Get pointer to the IV */
325 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
326 silc_cipher_get_iv(cipher));
329 if (silc_unlikely(!silc_cipher_decrypt(cipher, data, data, block_len,
335 /* Get the payload length and decrypt rest */
337 SILC_GET16_MSB(len, data + totlen);
339 if (silc_unlikely(totlen + iv_len + mac_len + 2 > data_len))
342 if (totlen >= block_len)
343 if (silc_unlikely(!silc_cipher_decrypt(cipher, data + block_len,
345 (totlen - block_len) +
346 SILC_MESSAGE_PAD(totlen), ivp))) {
354 /* Parses Message Payload returning new payload structure. This also
355 decrypts it and checks the MAC. */
358 silc_message_payload_parse(unsigned char *payload,
359 SilcUInt32 payload_len,
360 SilcBool private_message,
364 unsigned char *sender_id,
365 SilcUInt32 sender_id_len,
366 unsigned char *receiver_id,
367 SilcUInt32 receiver_id_len,
369 SilcBool no_allocation,
370 SilcMessagePayload message)
372 SilcBufferStruct buffer;
373 SilcMessagePayload newp = NULL;
375 SilcUInt32 mac_len = 0, iv_len = 0;
377 SILC_LOG_DEBUG(("Parsing Message Payload"));
379 silc_buffer_set(&buffer, payload, payload_len);
381 /* Decrypt the payload */
382 if (silc_likely(cipher)) {
383 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
384 private_message, static_key,
385 cipher, hmac, sender_id,
386 sender_id_len, receiver_id,
387 receiver_id_len, TRUE);
388 if (silc_unlikely(ret == FALSE))
392 if (silc_likely(hmac))
393 mac_len = silc_hmac_len(hmac);
395 /* IV is present for all channel messages, and private messages when
396 static key (pre-shared key) is used. */
397 if (cipher && (!private_message || (private_message && static_key)))
398 iv_len = silc_cipher_get_block_len(cipher);
401 newp = message = silc_calloc(1, sizeof(*newp));
402 if (silc_unlikely(!newp))
405 memset(message, 0, sizeof(*message));
406 message->allocated = (stack || no_allocation ? FALSE : TRUE);
408 /* Parse the Message Payload. */
410 ret = silc_buffer_sunformat(stack, &buffer,
411 SILC_STR_UI_SHORT(&message->flags),
412 SILC_STR_UI16_NSTRING_ALLOC(&message->data,
414 SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
418 ret = silc_buffer_unformat(&buffer,
419 SILC_STR_UI_SHORT(&message->flags),
420 SILC_STR_UI16_NSTRING(&message->data,
422 SILC_STR_UI16_NSTRING(&message->pad,
425 if (silc_unlikely(ret == -1))
428 if (silc_unlikely((message->data_len > silc_buffer_len(&buffer) -
429 6 - mac_len - iv_len) ||
430 (message->pad_len + message->data_len >
431 silc_buffer_len(&buffer) - 6 - mac_len - iv_len))) {
432 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
436 /* Parse Signed Message Payload if provided */
437 if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
438 message->data_len + message->pad_len + 6 + mac_len +
439 iv_len < silc_buffer_len(&buffer)) {
440 if (!silc_message_signed_payload_parse(buffer.data + 6 +
443 silc_buffer_len(&buffer) -
444 iv_len - mac_len - 6 -
451 /* Parse MAC from the payload */
453 message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
459 silc_message_payload_free(newp);
464 /***************************** Payload encoding *****************************/
466 /* This function is used to encrypt the Messsage Payload which is
467 the `data' and `data_len'. This is used internally by the Message
468 Payload encoding routines but application may call this too if needed.
469 The `true_len' is the data length which is used to create MAC out of. */
471 SilcBool silc_message_payload_encrypt(unsigned char *data,
481 unsigned char sid[32], rid[32];
482 SilcUInt32 sid_len = 0, rid_len = 0;
485 /* Encrypt payload of the packet */
486 if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv)))
489 #if 0 /* For now this is disabled. Enable at 1.1.x or 1.2 at the latest. */
491 silc_id_id2str(&sender_id->u.client_id, SILC_ID_CLIENT, sid, sizeof(sid),
493 if (receiver_id->type == SILC_ID_CLIENT)
494 silc_id_id2str(&receiver_id->u.client_id, SILC_ID_CLIENT, rid,
495 sizeof(rid), &rid_len);
496 else if (receiver_id->type == SILC_ID_CHANNEL)
497 silc_id_id2str(&receiver_id->u.channel_id, SILC_ID_CHANNEL, rid,
498 sizeof(rid), &rid_len);
501 /* Compute the MAC of the encrypted message data */
502 silc_hmac_init(hmac);
503 silc_hmac_update(hmac, data, true_len);
505 silc_hmac_update(hmac, sid, sid_len);
506 silc_hmac_update(hmac, rid, rid_len);
508 silc_hmac_final(hmac, data + true_len, NULL);
513 /* Encrypt message payload */
515 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
516 void *value, void *context)
518 SilcMessageEncode *e = context;
521 if (!e->cipher || !e->hmac)
524 mac_len = silc_hmac_len(e->hmac);
525 if (silc_unlikely(!silc_buffer_enlarge(buffer, mac_len)))
528 if (silc_unlikely(!silc_message_payload_encrypt(buffer->head,
530 silc_buffer_headlen(buffer),
531 e->iv, e->sid, e->rid,
532 e->cipher, e->hmac)))
538 /* Compute message signature */
540 static int silc_message_payload_encode_sig(SilcBuffer buffer,
541 void *value, void *context)
543 SilcMessageEncode *e = context;
547 if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
550 sig = silc_message_signed_payload_encode(buffer->head,
551 silc_buffer_headlen(buffer),
552 e->public_key, e->private_key,
554 if (silc_unlikely(!sig))
557 len = silc_buffer_format(buffer,
558 SILC_STR_DATA(silc_buffer_data(sig),
559 silc_buffer_len(sig)),
561 if (silc_unlikely(len < 0)) {
562 silc_buffer_free(sig);
566 silc_buffer_free(sig);
570 /* Encodes Message Payload into a buffer and returns it. */
572 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
573 const unsigned char *data,
575 SilcBool generate_iv,
576 SilcBool private_message,
580 SilcPublicKey public_key,
581 SilcPrivateKey private_key,
587 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
588 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
589 SilcBuffer buf = NULL;
593 SILC_LOG_DEBUG(("Encoding Message Payload"));
595 if (silc_unlikely(!data_len))
597 if (silc_unlikely(!private_message && (!cipher || !hmac)))
601 buf = buffer = silc_buffer_alloc(0);
602 if (silc_unlikely(!buf))
605 silc_buffer_reset(buffer);
607 /* For channel messages IV is always generated */
608 if (!private_message && !generate_iv)
612 if (cipher && generate_iv) {
613 iv_len = silc_cipher_get_block_len(cipher);
615 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
617 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
622 mac_len = silc_hmac_len(hmac);
623 data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
624 public_key, private_key);
626 /* Calculate length of padding. IV is not included into the calculation
627 since it is not encrypted. */
628 pad_len = SILC_MESSAGE_PAD(6 + data_len);
630 /* Generate padding */
633 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
635 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
640 e.public_key = public_key;
641 e.private_key = private_key;
647 e.iv = iv_len ? iv : NULL;
648 e.payload_len = 6 + data_len + pad_len;
650 /* Encode the Message Payload */
651 if (silc_buffer_format(buffer,
652 SILC_STR_UI_SHORT(flags),
653 SILC_STR_UI_SHORT(data_len),
654 SILC_STR_DATA(data, data_len),
655 SILC_STR_UI_SHORT(pad_len),
656 SILC_STR_DATA(pad, pad_len),
657 SILC_STR_FUNC(silc_message_payload_encode_sig,
659 SILC_STR_DATA(iv, iv_len),
660 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
663 silc_buffer_free(buf);
670 /* Free's Message Payload */
672 void silc_message_payload_free(SilcMessagePayload payload)
674 silc_message_signed_payload_free(&payload->sig);
676 memset(payload->data, 0, payload->data_len);
677 if (payload->allocated)
678 silc_free(payload->data);
680 if (payload->allocated) {
681 silc_free(payload->pad);
688 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
690 return payload->flags;
695 unsigned char *silc_message_get_data(SilcMessagePayload payload,
696 SilcUInt32 *data_len)
699 *data_len = payload->data_len;
700 return payload->data;
703 /* Return MAC. The caller knows the length of the MAC */
705 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
710 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
712 SilcAuthResult silc_message_signed_verify(SilcMessagePayload message,
713 SilcPublicKey remote_public_key,
716 int ret = SILC_AUTH_FAILED;
717 SilcBuffer sign, tmp;
718 SilcMessageSignedPayload sig = &message->sig;
720 if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
721 !sig->sign_len || !remote_public_key || !hash)
724 /* Generate the signature verification data, the Message Payload */
725 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
726 silc_buffer_format(tmp,
727 SILC_STR_UI_SHORT(message->flags),
728 SILC_STR_UI_SHORT(message->data_len),
729 SILC_STR_UI_XNSTRING(message->data, message->data_len),
730 SILC_STR_UI_SHORT(message->pad_len),
731 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
733 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
734 sig->pk_data, sig->pk_len,
736 silc_buffer_clear(tmp);
737 silc_buffer_free(tmp);
742 /* Verify the authentication data */
743 if (!silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len,
744 silc_buffer_data(sign), silc_buffer_len(sign), hash)) {
745 silc_buffer_clear(sign);
746 silc_buffer_free(sign);
747 SILC_LOG_DEBUG(("Signature verification failed"));
753 silc_buffer_clear(sign);
754 silc_buffer_free(sign);
756 SILC_LOG_DEBUG(("Signature verification successful"));
761 /* Return the public key from the payload */
764 silc_message_signed_get_public_key(SilcMessagePayload payload,
765 const unsigned char **pk_data,
766 SilcUInt32 *pk_data_len)
769 SilcMessageSignedPayload sig = &payload->sig;
774 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
779 *pk_data = sig->pk_data;
781 *pk_data_len = sig->pk_len;