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)
127 if (totlen >= block_len)
128 if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
129 (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
136 /* Parses Message Payload returning new payload structure. This also
137 decrypts it and checks the MAC. */
140 silc_message_payload_parse(unsigned char *payload,
141 SilcUInt32 payload_len,
142 SilcBool private_message,
147 SilcBufferStruct buffer;
148 SilcMessagePayload newp;
150 SilcUInt32 mac_len = 0, iv_len = 0;
152 SILC_LOG_DEBUG(("Parsing Message Payload"));
154 silc_buffer_set(&buffer, payload, payload_len);
156 /* Decrypt the payload */
158 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
159 private_message, static_key,
166 mac_len = silc_hmac_len(hmac);
168 /* IV is present for all channel messages, and private messages when
169 static key (pre-shared key) is used. */
170 if (cipher && (!private_message || (private_message && static_key)))
171 iv_len = silc_cipher_get_block_len(cipher);
173 newp = silc_calloc(1, sizeof(*newp));
177 /* Parse the Message Payload. */
178 ret = silc_buffer_unformat(&buffer,
179 SILC_STR_UI_SHORT(&newp->flags),
180 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
182 SILC_STR_UI16_NSTRING_ALLOC(&newp->pad,
188 if ((newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
189 (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) -
190 6 - mac_len - iv_len)) {
191 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
195 /* Parse Signed Message Payload if provided */
196 if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
197 newp->data_len + newp->pad_len + 6 + mac_len +
198 iv_len < silc_buffer_len(&buffer)) {
200 silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
202 silc_buffer_len(&buffer) -
203 iv_len - mac_len - 6 - newp->data_len -
207 /* Parse MAC from the payload */
209 newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
214 silc_message_payload_free(newp);
219 /***************************** Payload encoding *****************************/
221 /* This function is used to encrypt the Messsage Payload which is
222 the `data' and `data_len'. This is used internally by the Message
223 Payload encoding routines but application may call this too if needed.
224 The `true_len' is the data length which is used to create MAC out of. */
226 SilcBool silc_message_payload_encrypt(unsigned char *data,
233 /* Encrypt payload of the packet */
234 if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
237 /* Compute the MAC of the encrypted message data */
238 silc_hmac_init(hmac);
239 silc_hmac_update(hmac, data, true_len);
240 silc_hmac_final(hmac, data + true_len, NULL);
245 /* Encrypt message payload */
247 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
248 void *value, void *context)
250 SilcMessageEncode *e = context;
253 if (!e->cipher || !e->hmac)
256 mac_len = silc_hmac_len(e->hmac);
257 if (!silc_buffer_enlarge(buffer, mac_len))
260 if (!silc_message_payload_encrypt(buffer->head,
262 silc_buffer_headlen(buffer),
263 e->iv, e->cipher, e->hmac))
269 /* Compute message signature */
271 static int silc_message_payload_encode_sig(SilcBuffer buffer,
272 void *value, void *context)
274 SilcMessageEncode *e = context;
278 if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
281 sig = silc_message_signed_payload_encode(buffer->head,
282 silc_buffer_headlen(buffer),
283 e->public_key, e->private_key,
288 len = silc_buffer_format(buffer,
289 SILC_STR_DATA(silc_buffer_data(sig),
290 silc_buffer_len(sig)),
293 silc_buffer_free(sig);
297 silc_buffer_free(sig);
301 /* Encodes Message Payload into a buffer and returns it. */
303 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
304 const unsigned char *data,
306 SilcBool generate_iv,
307 SilcBool private_message,
311 SilcPublicKey public_key,
312 SilcPrivateKey private_key,
316 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
317 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
318 SilcBuffer buf = NULL;
322 SILC_LOG_DEBUG(("Encoding Message Payload"));
326 if (!private_message && (!cipher || !hmac))
330 buf = buffer = silc_buffer_alloc(0);
334 silc_buffer_reset(buffer);
336 /* For channel messages IV is always generated */
337 if (!private_message && !generate_iv)
341 if (cipher && generate_iv) {
342 iv_len = silc_cipher_get_block_len(cipher);
344 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
346 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
351 mac_len = silc_hmac_len(hmac);
352 data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
354 /* Calculate length of padding. IV is not included into the calculation
355 since it is not encrypted. */
356 pad_len = SILC_MESSAGE_PAD(6 + data_len);
358 /* Generate padding */
361 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
363 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
368 e.public_key = public_key;
369 e.private_key = private_key;
373 e.iv = iv_len ? iv : NULL;
374 e.payload_len = 6 + data_len + pad_len;
376 /* Encode the Message Payload */
377 if (silc_buffer_format(buffer,
378 SILC_STR_UI_SHORT(flags),
379 SILC_STR_UI_SHORT(data_len),
380 SILC_STR_DATA(data, data_len),
381 SILC_STR_UI_SHORT(pad_len),
382 SILC_STR_DATA(pad, pad_len),
383 SILC_STR_FUNC(silc_message_payload_encode_sig,
385 SILC_STR_DATA(iv, iv_len),
386 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
389 silc_buffer_free(buf);
396 /* Free's Message Payload */
398 void silc_message_payload_free(SilcMessagePayload payload)
401 memset(payload->data, 0, payload->data_len);
402 silc_free(payload->data);
405 silc_message_signed_payload_free(payload->sig);
406 silc_free(payload->pad);
412 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
414 return payload->flags;
419 unsigned char *silc_message_get_data(SilcMessagePayload payload,
420 SilcUInt32 *data_len)
423 *data_len = payload->data_len;
424 return payload->data;
427 /* Return MAC. The caller knows the length of the MAC */
429 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
434 /* Return signature of the message */
436 SilcMessageSignedPayload
437 silc_message_get_signature(SilcMessagePayload payload)
443 /************************ Message Signature Payload *************************/
445 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
446 struct SilcMessageSignedPayloadStruct {
450 unsigned char *pk_data;
451 unsigned char *sign_data;
454 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
457 silc_message_signed_encode_data(const unsigned char *message_payload,
458 SilcUInt32 message_payload_len,
460 SilcUInt32 pk_len, SilcUInt32 pk_type)
464 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
468 silc_buffer_format(sign,
469 SILC_STR_UI_XNSTRING(message_payload,
470 message_payload_len),
471 SILC_STR_UI_SHORT(pk_len),
472 SILC_STR_UI_SHORT(pk_type),
476 silc_buffer_pull(sign, message_payload_len + 4);
477 silc_buffer_format(sign,
478 SILC_STR_UI_XNSTRING(pk, pk_len),
480 silc_buffer_push(sign, message_payload_len + 4);
486 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
488 SilcMessageSignedPayload
489 silc_message_signed_payload_parse(const unsigned char *data,
492 SilcMessageSignedPayload sig;
493 SilcBufferStruct buffer;
496 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
498 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
500 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
501 sig = silc_calloc(1, sizeof(*sig));
505 /* Parse the payload */
506 ret = silc_buffer_unformat(&buffer,
507 SILC_STR_UI_SHORT(&sig->pk_len),
508 SILC_STR_UI_SHORT(&sig->pk_type),
510 if (ret == -1 || sig->pk_len > data_len - 4) {
511 silc_message_signed_payload_free(sig);
512 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
517 silc_buffer_pull(&buffer, 4);
518 ret = silc_buffer_unformat(&buffer,
519 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
521 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
524 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
526 silc_message_signed_payload_free(sig);
527 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
530 silc_buffer_push(&buffer, 4);
532 /* Signature must be provided */
533 if (sig->sign_len < 1) {
534 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
536 silc_message_signed_payload_free(sig);
543 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
547 silc_message_signed_payload_encode(const unsigned char *message_payload,
548 SilcUInt32 message_payload_len,
549 SilcPublicKey public_key,
550 SilcPrivateKey private_key,
553 SilcBuffer buffer, sign;
554 unsigned char auth_data[2048 + 1];
556 unsigned char *pk = NULL;
557 SilcUInt32 pk_len = 0;
560 if (!message_payload || !message_payload_len || !private_key || !hash)
564 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
568 pk_type = silc_pkcs_get_type(public_key);
570 /* Encode the data to be signed */
571 sign = silc_message_signed_encode_data(message_payload,
573 pk, pk_len, pk_type);
579 /* Sign the buffer */
581 /* Compute the hash and the signature. */
582 if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
583 auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
584 SILC_LOG_ERROR(("Could not compute signature"));
585 silc_buffer_clear(sign);
586 silc_buffer_free(sign);
591 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
593 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
595 silc_buffer_clear(sign);
596 silc_buffer_free(sign);
597 memset(auth_data, 0, sizeof(auth_data));
602 silc_buffer_format(buffer,
603 SILC_STR_UI_SHORT(pk_len),
604 SILC_STR_UI_SHORT(pk_type),
608 silc_buffer_pull(buffer, 4);
609 silc_buffer_format(buffer,
610 SILC_STR_UI_XNSTRING(pk, pk_len),
612 silc_buffer_push(buffer, 4);
615 silc_buffer_pull(buffer, 4 + pk_len);
616 silc_buffer_format(buffer,
617 SILC_STR_UI_SHORT(auth_len),
618 SILC_STR_UI_XNSTRING(auth_data, auth_len),
620 silc_buffer_push(buffer, 4 + pk_len);
622 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
624 memset(auth_data, 0, sizeof(auth_data));
625 silc_buffer_clear(sign);
626 silc_buffer_free(sign);
632 /* Free the payload */
634 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
636 memset(sig->sign_data, 0, sig->sign_len);
637 silc_free(sig->sign_data);
638 silc_free(sig->pk_data);
642 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
644 int silc_message_signed_verify(SilcMessageSignedPayload sig,
645 SilcMessagePayload message,
646 SilcPublicKey remote_public_key,
649 int ret = SILC_AUTH_FAILED;
650 SilcBuffer sign, tmp;
652 if (!sig || !remote_public_key || !hash)
655 /* Generate the signature verification data, the Message Payload */
656 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
657 silc_buffer_format(tmp,
658 SILC_STR_UI_SHORT(message->flags),
659 SILC_STR_UI_SHORT(message->data_len),
660 SILC_STR_UI_XNSTRING(message->data, message->data_len),
661 SILC_STR_UI_SHORT(message->pad_len),
662 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
664 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
665 sig->pk_data, sig->pk_len,
667 silc_buffer_clear(tmp);
668 silc_buffer_free(tmp);
673 /* Verify the authentication data */
674 if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
676 sign->data, silc_buffer_len(sign), hash)) {
678 silc_buffer_clear(sign);
679 silc_buffer_free(sign);
680 SILC_LOG_DEBUG(("Signature verification failed"));
686 silc_buffer_clear(sign);
687 silc_buffer_free(sign);
689 SILC_LOG_DEBUG(("Signature verification successful"));
694 /* Return the public key from the payload */
697 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
698 const unsigned char **pk_data,
699 SilcUInt32 *pk_data_len)
706 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
711 *pk_data = sig->pk_data;
713 *pk_data_len = sig->pk_len;