5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 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 /* Returns the data length that fits to the packet. If data length is too
35 big it will be truncated to fit to the payload. */
36 #define SILC_MESSAGE_DATALEN(data_len, header_len) \
37 ((data_len + SILC_MESSAGE_HLEN + header_len) > \
38 SILC_PACKET_MAX_LEN ? \
39 data_len - ((data_len + SILC_MESSAGE_HLEN + header_len) - \
40 SILC_PACKET_MAX_LEN) : data_len)
42 /* Message Payload structure. Contents of this structure is parsed
44 struct SilcMessagePayloadStruct {
45 SilcMessageFlags flags;
52 SilcMessageSignedPayload sig;
55 /* Payload encoding context */
57 SilcMessageFlags flags;
58 SilcPublicKey public_key;
59 SilcPrivateKey private_key;
64 SilcUInt16 payload_len;
68 /****************************** Payload parsing *****************************/
70 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
72 SilcBool silc_message_payload_decrypt(unsigned char *data,
74 SilcBool private_message,
80 SilcUInt32 mac_len, iv_len = 0, block_len;
81 SilcUInt16 len, totlen;
82 unsigned char mac[32], *ivp;
84 mac_len = silc_hmac_len(hmac);
85 block_len = silc_cipher_get_block_len(cipher);
87 /* IV is present for all channel messages, and private messages when
88 static key (pre-shared key) is used. */
89 if (!private_message || (private_message && static_key))
92 if (data_len <= (mac_len + iv_len))
96 /* Check the MAC of the message */
97 SILC_LOG_DEBUG(("Checking message MAC"));
99 silc_hmac_update(hmac, data, data_len - mac_len);
100 silc_hmac_final(hmac, mac, &mac_len);
101 if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
102 SILC_LOG_DEBUG(("Message MAC does not match"));
105 SILC_LOG_DEBUG(("MAC is Ok"));
108 /* Decrypt first only one block to get the header and then rest of
109 the data. This is done because there might be unencrypted data at
110 the end and we don't know the encrypted length yet. */
112 /* Get pointer to the IV */
113 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
114 silc_cipher_get_iv(cipher));
117 if (!silc_cipher_decrypt(cipher, data, data, block_len, ivp))
120 /* Get the payload length and decrypt rest */
122 SILC_GET16_MSB(len, data + totlen);
124 if (totlen + iv_len + mac_len + 2 > data_len)
126 if (totlen >= block_len)
127 if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
128 (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
135 /* Parses Message Payload returning new payload structure. This also
136 decrypts it and checks the MAC. */
139 silc_message_payload_parse(unsigned char *payload,
140 SilcUInt32 payload_len,
141 SilcBool private_message,
146 SilcBufferStruct buffer;
147 SilcMessagePayload newp;
149 SilcUInt32 mac_len = 0, iv_len = 0;
151 SILC_LOG_DEBUG(("Parsing Message Payload"));
153 silc_buffer_set(&buffer, payload, payload_len);
155 /* Decrypt the payload */
157 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
158 private_message, static_key,
165 mac_len = silc_hmac_len(hmac);
167 /* IV is present for all channel messages, and private messages when
168 static key (pre-shared key) is used. */
169 if (cipher && (!private_message || (private_message && static_key)))
170 iv_len = silc_cipher_get_block_len(cipher);
172 newp = silc_calloc(1, sizeof(*newp));
176 /* Parse the Message Payload. */
177 ret = silc_buffer_unformat(&buffer,
178 SILC_STR_UI_SHORT(&newp->flags),
179 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
181 SILC_STR_UI16_NSTRING_ALLOC(&newp->pad,
187 if ((newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
188 (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) -
189 6 - mac_len - iv_len)) {
190 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
194 /* Parse Signed Message Payload if provided */
195 if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
196 newp->data_len + newp->pad_len + 6 + mac_len +
197 iv_len < silc_buffer_len(&buffer)) {
199 silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
201 silc_buffer_len(&buffer) -
202 iv_len - mac_len - 6 - newp->data_len -
206 /* Parse MAC from the payload */
208 newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
213 silc_message_payload_free(newp);
218 /***************************** Payload encoding *****************************/
220 /* This function is used to encrypt the Messsage Payload which is
221 the `data' and `data_len'. This is used internally by the Message
222 Payload encoding routines but application may call this too if needed.
223 The `true_len' is the data length which is used to create MAC out of. */
225 SilcBool silc_message_payload_encrypt(unsigned char *data,
232 /* Encrypt payload of the packet */
233 if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
236 /* Compute the MAC of the encrypted message data */
237 silc_hmac_init(hmac);
238 silc_hmac_update(hmac, data, true_len);
239 silc_hmac_final(hmac, data + true_len, NULL);
244 /* Encrypt message payload */
246 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
247 void *value, void *context)
249 SilcMessageEncode *e = context;
252 if (!e->cipher || !e->hmac)
255 mac_len = silc_hmac_len(e->hmac);
256 if (!silc_buffer_enlarge(buffer, mac_len))
259 if (!silc_message_payload_encrypt(buffer->head,
261 silc_buffer_headlen(buffer),
262 e->iv, e->cipher, e->hmac))
268 /* Compute message signature */
270 static int silc_message_payload_encode_sig(SilcBuffer buffer,
271 void *value, void *context)
273 SilcMessageEncode *e = context;
277 if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
280 sig = silc_message_signed_payload_encode(buffer->head,
281 silc_buffer_headlen(buffer),
282 e->public_key, e->private_key,
287 len = silc_buffer_format(buffer,
288 SILC_STR_DATA(silc_buffer_data(sig),
289 silc_buffer_len(sig)),
292 silc_buffer_free(sig);
296 silc_buffer_free(sig);
300 /* Encodes Message Payload into a buffer and returns it. */
302 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
303 const unsigned char *data,
305 SilcBool generate_iv,
306 SilcBool private_message,
310 SilcPublicKey public_key,
311 SilcPrivateKey private_key,
315 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
316 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
317 SilcBuffer buf = NULL;
321 SILC_LOG_DEBUG(("Encoding Message Payload"));
325 if (!private_message && (!cipher || !hmac))
329 buf = buffer = silc_buffer_alloc(0);
333 silc_buffer_reset(buffer);
335 /* For channel messages IV is always generated */
336 if (!private_message && !generate_iv)
340 if (cipher && generate_iv) {
341 iv_len = silc_cipher_get_block_len(cipher);
343 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
345 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
350 mac_len = silc_hmac_len(hmac);
351 data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
353 /* Calculate length of padding. IV is not included into the calculation
354 since it is not encrypted. */
355 pad_len = SILC_MESSAGE_PAD(6 + data_len);
357 /* Generate padding */
360 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
362 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
367 e.public_key = public_key;
368 e.private_key = private_key;
372 e.iv = iv_len ? iv : NULL;
373 e.payload_len = 6 + data_len + pad_len;
375 /* Encode the Message Payload */
376 if (silc_buffer_format(buffer,
377 SILC_STR_UI_SHORT(flags),
378 SILC_STR_UI_SHORT(data_len),
379 SILC_STR_DATA(data, data_len),
380 SILC_STR_UI_SHORT(pad_len),
381 SILC_STR_DATA(pad, pad_len),
382 SILC_STR_FUNC(silc_message_payload_encode_sig,
384 SILC_STR_DATA(iv, iv_len),
385 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
388 silc_buffer_free(buf);
395 /* Free's Message Payload */
397 void silc_message_payload_free(SilcMessagePayload payload)
400 memset(payload->data, 0, payload->data_len);
401 silc_free(payload->data);
404 silc_message_signed_payload_free(payload->sig);
405 silc_free(payload->pad);
411 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
413 return payload->flags;
418 unsigned char *silc_message_get_data(SilcMessagePayload payload,
419 SilcUInt32 *data_len)
422 *data_len = payload->data_len;
423 return payload->data;
426 /* Return MAC. The caller knows the length of the MAC */
428 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
433 /* Return signature of the message */
435 SilcMessageSignedPayload
436 silc_message_get_signature(SilcMessagePayload payload)
442 /************************ Message Signature Payload *************************/
444 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
445 struct SilcMessageSignedPayloadStruct {
449 unsigned char *pk_data;
450 unsigned char *sign_data;
453 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
456 silc_message_signed_encode_data(const unsigned char *message_payload,
457 SilcUInt32 message_payload_len,
459 SilcUInt32 pk_len, SilcUInt32 pk_type)
463 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
467 silc_buffer_format(sign,
468 SILC_STR_UI_XNSTRING(message_payload,
469 message_payload_len),
470 SILC_STR_UI_SHORT(pk_len),
471 SILC_STR_UI_SHORT(pk_type),
475 silc_buffer_pull(sign, message_payload_len + 4);
476 silc_buffer_format(sign,
477 SILC_STR_UI_XNSTRING(pk, pk_len),
479 silc_buffer_push(sign, message_payload_len + 4);
485 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
487 SilcMessageSignedPayload
488 silc_message_signed_payload_parse(const unsigned char *data,
491 SilcMessageSignedPayload sig;
492 SilcBufferStruct buffer;
495 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
497 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
499 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
500 sig = silc_calloc(1, sizeof(*sig));
504 /* Parse the payload */
505 ret = silc_buffer_unformat(&buffer,
506 SILC_STR_UI_SHORT(&sig->pk_len),
507 SILC_STR_UI_SHORT(&sig->pk_type),
509 if (ret == -1 || sig->pk_len > data_len - 4) {
510 silc_message_signed_payload_free(sig);
511 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
516 silc_buffer_pull(&buffer, 4);
517 ret = silc_buffer_unformat(&buffer,
518 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
520 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
523 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
525 silc_message_signed_payload_free(sig);
526 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
529 silc_buffer_push(&buffer, 4);
531 /* Signature must be provided */
532 if (sig->sign_len < 1) {
533 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
535 silc_message_signed_payload_free(sig);
542 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
546 silc_message_signed_payload_encode(const unsigned char *message_payload,
547 SilcUInt32 message_payload_len,
548 SilcPublicKey public_key,
549 SilcPrivateKey private_key,
552 SilcBuffer buffer, sign;
553 unsigned char auth_data[2048 + 1];
555 unsigned char *pk = NULL;
556 SilcUInt32 pk_len = 0;
559 if (!message_payload || !message_payload_len || !private_key || !hash)
563 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
567 pk_type = silc_pkcs_get_type(public_key);
569 /* Encode the data to be signed */
570 sign = silc_message_signed_encode_data(message_payload,
572 pk, pk_len, pk_type);
578 /* Sign the buffer */
580 /* Compute the hash and the signature. */
581 if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
582 auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
583 SILC_LOG_ERROR(("Could not compute signature"));
584 silc_buffer_clear(sign);
585 silc_buffer_free(sign);
590 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
592 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
594 silc_buffer_clear(sign);
595 silc_buffer_free(sign);
596 memset(auth_data, 0, sizeof(auth_data));
601 silc_buffer_format(buffer,
602 SILC_STR_UI_SHORT(pk_len),
603 SILC_STR_UI_SHORT(pk_type),
607 silc_buffer_pull(buffer, 4);
608 silc_buffer_format(buffer,
609 SILC_STR_UI_XNSTRING(pk, pk_len),
611 silc_buffer_push(buffer, 4);
614 silc_buffer_pull(buffer, 4 + pk_len);
615 silc_buffer_format(buffer,
616 SILC_STR_UI_SHORT(auth_len),
617 SILC_STR_UI_XNSTRING(auth_data, auth_len),
619 silc_buffer_push(buffer, 4 + pk_len);
621 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
623 memset(auth_data, 0, sizeof(auth_data));
624 silc_buffer_clear(sign);
625 silc_buffer_free(sign);
631 /* Free the payload */
633 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
635 memset(sig->sign_data, 0, sig->sign_len);
636 silc_free(sig->sign_data);
637 silc_free(sig->pk_data);
641 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
643 int silc_message_signed_verify(SilcMessageSignedPayload sig,
644 SilcMessagePayload message,
645 SilcPublicKey remote_public_key,
648 int ret = SILC_AUTH_FAILED;
649 SilcBuffer sign, tmp;
651 if (!sig || !remote_public_key || !hash)
654 /* Generate the signature verification data, the Message Payload */
655 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
656 silc_buffer_format(tmp,
657 SILC_STR_UI_SHORT(message->flags),
658 SILC_STR_UI_SHORT(message->data_len),
659 SILC_STR_UI_XNSTRING(message->data, message->data_len),
660 SILC_STR_UI_SHORT(message->pad_len),
661 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
663 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
664 sig->pk_data, sig->pk_len,
666 silc_buffer_clear(tmp);
667 silc_buffer_free(tmp);
672 /* Verify the authentication data */
673 if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
675 sign->data, silc_buffer_len(sign), hash)) {
677 silc_buffer_clear(sign);
678 silc_buffer_free(sign);
679 SILC_LOG_DEBUG(("Signature verification failed"));
685 silc_buffer_clear(sign);
686 silc_buffer_free(sign);
688 SILC_LOG_DEBUG(("Signature verification successful"));
693 /* Return the public key from the payload */
696 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
697 const unsigned char **pk_data,
698 SilcUInt32 *pk_data_len)
705 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
710 *pk_data = sig->pk_data;
712 *pk_data_len = sig->pk_len;