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 /* 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;
50 /************************* Static utility functions *************************/
52 /* Returns the data length that fits to the packet. If data length is too
53 big it will be truncated to fit to the payload. */
56 SilcUInt32 silc_message_payload_datalen(SilcUInt32 data_len,
57 SilcUInt32 header_len,
59 SilcPublicKey public_key,
60 SilcPrivateKey private_key)
62 SilcUInt32 pklen = (flags & SILC_MESSAGE_FLAG_SIGNED && public_key ?
63 silc_pkcs_public_key_get_len(public_key) : 0);
64 SilcUInt32 prlen = (flags & SILC_MESSAGE_FLAG_SIGNED ?
65 silc_pkcs_private_key_get_len(private_key) / 8 : 0);
66 SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
68 if (silc_unlikely(dlen > SILC_MESSAGE_MAX_LEN))
69 data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
74 /* Free signed payload */
76 static void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
79 memset(sig->sign_data, 0, sig->sign_len);
80 silc_free(sig->sign_data);
82 silc_free(sig->pk_data);
85 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
88 silc_message_signed_payload_parse(const unsigned char *data,
90 SilcMessageSignedPayload sig)
92 SilcBufferStruct buffer;
95 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
97 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
99 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
101 /* Parse the payload */
102 ret = silc_buffer_unformat(&buffer,
103 SILC_STR_UI_SHORT(&sig->pk_len),
104 SILC_STR_UI_SHORT(&sig->pk_type),
106 if (ret == -1 || sig->pk_len > data_len - 4) {
107 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
112 silc_buffer_pull(&buffer, 4);
113 ret = silc_buffer_unformat(&buffer,
114 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
116 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
119 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
121 silc_message_signed_payload_free(sig);
122 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
125 silc_buffer_push(&buffer, 4);
127 /* Signature must be provided */
128 if (sig->sign_len < 1) {
129 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
131 silc_message_signed_payload_free(sig);
138 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
141 silc_message_signed_encode_data(const unsigned char *message_payload,
142 SilcUInt32 message_payload_len,
144 SilcUInt32 pk_len, SilcUInt32 pk_type)
148 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
152 silc_buffer_format(sign,
153 SILC_STR_UI_XNSTRING(message_payload,
154 message_payload_len),
155 SILC_STR_UI_SHORT(pk_len),
156 SILC_STR_UI_SHORT(pk_type),
160 silc_buffer_pull(sign, message_payload_len + 4);
161 silc_buffer_format(sign,
162 SILC_STR_UI_XNSTRING(pk, pk_len),
164 silc_buffer_push(sign, message_payload_len + 4);
170 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
174 silc_message_signed_payload_encode(const unsigned char *message_payload,
175 SilcUInt32 message_payload_len,
176 SilcPublicKey public_key,
177 SilcPrivateKey private_key,
180 SilcBuffer buffer, sign;
181 unsigned char auth_data[2048 + 1];
183 unsigned char *pk = NULL;
184 SilcUInt32 pk_len = 0;
187 if (!message_payload || !message_payload_len || !private_key || !hash)
191 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
195 pk_type = silc_pkcs_get_type(private_key);
197 /* Encode the data to be signed */
198 sign = silc_message_signed_encode_data(message_payload,
200 pk, pk_len, pk_type);
206 /* Sign the buffer */
208 /* Compute the hash and the signature. */
209 if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
210 auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
211 SILC_LOG_ERROR(("Could not compute signature"));
212 silc_buffer_clear(sign);
213 silc_buffer_free(sign);
218 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
220 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
222 silc_buffer_clear(sign);
223 silc_buffer_free(sign);
224 memset(auth_data, 0, sizeof(auth_data));
229 silc_buffer_format(buffer,
230 SILC_STR_UI_SHORT(pk_len),
231 SILC_STR_UI_SHORT(pk_type),
235 silc_buffer_pull(buffer, 4);
236 silc_buffer_format(buffer,
237 SILC_STR_UI_XNSTRING(pk, pk_len),
239 silc_buffer_push(buffer, 4);
242 silc_buffer_pull(buffer, 4 + pk_len);
243 silc_buffer_format(buffer,
244 SILC_STR_UI_SHORT(auth_len),
245 SILC_STR_UI_XNSTRING(auth_data, auth_len),
247 silc_buffer_push(buffer, 4 + pk_len);
249 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
251 memset(auth_data, 0, sizeof(auth_data));
252 silc_buffer_clear(sign);
253 silc_buffer_free(sign);
260 /***************************** Payload parsing ******************************/
262 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
264 SilcBool silc_message_payload_decrypt(unsigned char *data,
266 SilcBool private_message,
272 SilcUInt32 mac_len, iv_len = 0, block_len;
273 SilcUInt16 len, totlen;
274 unsigned char mac[32], *ivp;
276 mac_len = silc_hmac_len(hmac);
277 block_len = silc_cipher_get_block_len(cipher);
279 /* IV is present for all channel messages, and private messages when
280 static key (pre-shared key) is used. */
281 if (!private_message || (private_message && static_key))
284 if (silc_unlikely(data_len < (mac_len + iv_len + block_len)))
287 if (silc_likely(check_mac)) {
288 /* Check the MAC of the message */
289 SILC_LOG_DEBUG(("Checking message MAC"));
290 silc_hmac_init(hmac);
291 silc_hmac_update(hmac, data, data_len - mac_len);
292 silc_hmac_final(hmac, mac, &mac_len);
293 if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
294 SILC_LOG_DEBUG(("Message MAC does not match"));
297 SILC_LOG_DEBUG(("MAC is Ok"));
300 /* Decrypt first only one block to get the header and then rest of
301 the data. This is done because there might be unencrypted data at
302 the end and we don't know the encrypted length yet. */
304 /* Get pointer to the IV */
305 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
306 silc_cipher_get_iv(cipher));
309 if (silc_unlikely(!silc_cipher_decrypt(cipher, data, data, block_len,
315 /* Get the payload length and decrypt rest */
317 SILC_GET16_MSB(len, data + totlen);
319 if (silc_unlikely(totlen + iv_len + mac_len + 2 > data_len))
322 if (totlen >= block_len)
323 if (silc_unlikely(!silc_cipher_decrypt(cipher, data + block_len,
325 (totlen - block_len) +
326 SILC_MESSAGE_PAD(totlen), ivp))) {
334 /* Parses Message Payload returning new payload structure. This also
335 decrypts it and checks the MAC. */
338 silc_message_payload_parse(unsigned char *payload,
339 SilcUInt32 payload_len,
340 SilcBool private_message,
345 SilcBool no_allocation,
346 SilcMessagePayload message)
348 SilcBufferStruct buffer;
349 SilcMessagePayload newp = NULL;
351 SilcUInt32 mac_len = 0, iv_len = 0;
353 SILC_LOG_DEBUG(("Parsing Message Payload"));
355 silc_buffer_set(&buffer, payload, payload_len);
357 /* Decrypt the payload */
358 if (silc_likely(cipher)) {
359 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
360 private_message, static_key,
362 if (silc_unlikely(ret == FALSE))
366 if (silc_likely(hmac))
367 mac_len = silc_hmac_len(hmac);
369 /* IV is present for all channel messages, and private messages when
370 static key (pre-shared key) is used. */
371 if (cipher && (!private_message || (private_message && static_key)))
372 iv_len = silc_cipher_get_block_len(cipher);
375 newp = message = silc_calloc(1, sizeof(*newp));
376 if (silc_unlikely(!newp))
379 memset(message, 0, sizeof(*message));
380 message->allocated = (stack || no_allocation ? FALSE : TRUE);
382 /* Parse the Message Payload. */
384 ret = silc_buffer_sunformat(stack, &buffer,
385 SILC_STR_UI_SHORT(&message->flags),
386 SILC_STR_UI16_NSTRING_ALLOC(&message->data,
388 SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
392 ret = silc_buffer_unformat(&buffer,
393 SILC_STR_UI_SHORT(&message->flags),
394 SILC_STR_UI16_NSTRING(&message->data,
396 SILC_STR_UI16_NSTRING(&message->pad,
399 if (silc_unlikely(ret == -1))
402 if (silc_unlikely((message->data_len > silc_buffer_len(&buffer) -
403 6 - mac_len - iv_len) ||
404 (message->pad_len + message->data_len >
405 silc_buffer_len(&buffer) - 6 - mac_len - iv_len))) {
406 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
410 /* Parse Signed Message Payload if provided */
411 if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
412 message->data_len + message->pad_len + 6 + mac_len +
413 iv_len < silc_buffer_len(&buffer)) {
414 if (!silc_message_signed_payload_parse(buffer.data + 6 +
417 silc_buffer_len(&buffer) -
418 iv_len - mac_len - 6 -
425 /* Parse MAC from the payload */
427 message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
433 silc_message_payload_free(newp);
438 /***************************** Payload encoding *****************************/
440 /* This function is used to encrypt the Messsage Payload which is
441 the `data' and `data_len'. This is used internally by the Message
442 Payload encoding routines but application may call this too if needed.
443 The `true_len' is the data length which is used to create MAC out of. */
445 SilcBool silc_message_payload_encrypt(unsigned char *data,
452 /* Encrypt payload of the packet */
453 if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv)))
456 /* Compute the MAC of the encrypted message data */
457 silc_hmac_init(hmac);
458 silc_hmac_update(hmac, data, true_len);
459 silc_hmac_final(hmac, data + true_len, NULL);
464 /* Encrypt message payload */
466 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
467 void *value, void *context)
469 SilcMessageEncode *e = context;
472 if (!e->cipher || !e->hmac)
475 mac_len = silc_hmac_len(e->hmac);
476 if (silc_unlikely(!silc_buffer_enlarge(buffer, mac_len)))
479 if (silc_unlikely(!silc_message_payload_encrypt(buffer->head,
481 silc_buffer_headlen(buffer),
482 e->iv, e->cipher, e->hmac)))
488 /* Compute message signature */
490 static int silc_message_payload_encode_sig(SilcBuffer buffer,
491 void *value, void *context)
493 SilcMessageEncode *e = context;
497 if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
500 sig = silc_message_signed_payload_encode(buffer->head,
501 silc_buffer_headlen(buffer),
502 e->public_key, e->private_key,
504 if (silc_unlikely(!sig))
507 len = silc_buffer_format(buffer,
508 SILC_STR_DATA(silc_buffer_data(sig),
509 silc_buffer_len(sig)),
511 if (silc_unlikely(len < 0)) {
512 silc_buffer_free(sig);
516 silc_buffer_free(sig);
520 /* Encodes Message Payload into a buffer and returns it. */
522 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
523 const unsigned char *data,
525 SilcBool generate_iv,
526 SilcBool private_message,
530 SilcPublicKey public_key,
531 SilcPrivateKey private_key,
535 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
536 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
537 SilcBuffer buf = NULL;
541 SILC_LOG_DEBUG(("Encoding Message Payload"));
543 if (silc_unlikely(!data_len))
545 if (silc_unlikely(!private_message && (!cipher || !hmac)))
549 buf = buffer = silc_buffer_alloc(0);
550 if (silc_unlikely(!buf))
553 silc_buffer_reset(buffer);
555 /* For channel messages IV is always generated */
556 if (!private_message && !generate_iv)
560 if (cipher && generate_iv) {
561 iv_len = silc_cipher_get_block_len(cipher);
563 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
565 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
570 mac_len = silc_hmac_len(hmac);
571 data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
572 public_key, private_key);
574 /* Calculate length of padding. IV is not included into the calculation
575 since it is not encrypted. */
576 pad_len = SILC_MESSAGE_PAD(6 + data_len);
578 /* Generate padding */
581 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
583 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
588 e.public_key = public_key;
589 e.private_key = private_key;
593 e.iv = iv_len ? iv : NULL;
594 e.payload_len = 6 + data_len + pad_len;
596 /* Encode the Message Payload */
597 if (silc_buffer_format(buffer,
598 SILC_STR_UI_SHORT(flags),
599 SILC_STR_UI_SHORT(data_len),
600 SILC_STR_DATA(data, data_len),
601 SILC_STR_UI_SHORT(pad_len),
602 SILC_STR_DATA(pad, pad_len),
603 SILC_STR_FUNC(silc_message_payload_encode_sig,
605 SILC_STR_DATA(iv, iv_len),
606 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
609 silc_buffer_free(buf);
616 /* Free's Message Payload */
618 void silc_message_payload_free(SilcMessagePayload payload)
621 memset(payload->data, 0, payload->data_len);
622 if (payload->allocated)
623 silc_free(payload->data);
625 if (payload->allocated) {
626 silc_free(payload->pad);
629 silc_message_signed_payload_free(&payload->sig);
634 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
636 return payload->flags;
641 unsigned char *silc_message_get_data(SilcMessagePayload payload,
642 SilcUInt32 *data_len)
645 *data_len = payload->data_len;
646 return payload->data;
649 /* Return MAC. The caller knows the length of the MAC */
651 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
656 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
658 SilcAuthResult silc_message_signed_verify(SilcMessagePayload message,
659 SilcPublicKey remote_public_key,
662 int ret = SILC_AUTH_FAILED;
663 SilcBuffer sign, tmp;
664 SilcMessageSignedPayload sig = &message->sig;
666 if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
667 !sig->sign_len || !remote_public_key || !hash)
670 /* Generate the signature verification data, the Message Payload */
671 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
672 silc_buffer_format(tmp,
673 SILC_STR_UI_SHORT(message->flags),
674 SILC_STR_UI_SHORT(message->data_len),
675 SILC_STR_UI_XNSTRING(message->data, message->data_len),
676 SILC_STR_UI_SHORT(message->pad_len),
677 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
679 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
680 sig->pk_data, sig->pk_len,
682 silc_buffer_clear(tmp);
683 silc_buffer_free(tmp);
688 /* Verify the authentication data */
689 if (!silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len,
690 silc_buffer_data(sign), silc_buffer_len(sign), hash)) {
691 silc_buffer_clear(sign);
692 silc_buffer_free(sign);
693 SILC_LOG_DEBUG(("Signature verification failed"));
699 silc_buffer_clear(sign);
700 silc_buffer_free(sign);
702 SILC_LOG_DEBUG(("Signature verification successful"));
707 /* Return the public key from the payload */
710 silc_message_signed_get_public_key(SilcMessagePayload payload,
711 const unsigned char **pk_data,
712 SilcUInt32 *pk_data_len)
715 SilcMessageSignedPayload sig = &payload->sig;
720 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
725 *pk_data = sig->pk_data;
727 *pk_data_len = sig->pk_len;