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;
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,
212 SILC_LOG_ERROR(("Could not compute signature"));
213 silc_buffer_clear(sign);
214 silc_buffer_free(sign);
219 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
221 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
223 silc_buffer_clear(sign);
224 silc_buffer_free(sign);
225 memset(auth_data, 0, sizeof(auth_data));
230 silc_buffer_format(buffer,
231 SILC_STR_UI_SHORT(pk_len),
232 SILC_STR_UI_SHORT(pk_type),
236 silc_buffer_pull(buffer, 4);
237 silc_buffer_format(buffer,
238 SILC_STR_UI_XNSTRING(pk, pk_len),
240 silc_buffer_push(buffer, 4);
243 silc_buffer_pull(buffer, 4 + pk_len);
244 silc_buffer_format(buffer,
245 SILC_STR_UI_SHORT(auth_len),
246 SILC_STR_UI_XNSTRING(auth_data, auth_len),
248 silc_buffer_push(buffer, 4 + pk_len);
250 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
252 memset(auth_data, 0, sizeof(auth_data));
253 silc_buffer_clear(sign);
254 silc_buffer_free(sign);
261 /***************************** Payload parsing ******************************/
263 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
265 SilcBool silc_message_payload_decrypt(unsigned char *data,
267 SilcBool private_message,
273 SilcUInt32 mac_len, iv_len = 0, block_len;
274 SilcUInt16 len, totlen;
275 unsigned char mac[32], *ivp;
277 mac_len = silc_hmac_len(hmac);
278 block_len = silc_cipher_get_block_len(cipher);
280 /* IV is present for all channel messages, and private messages when
281 static key (pre-shared key) is used. */
282 if (!private_message || (private_message && static_key))
285 if (silc_unlikely(data_len < (mac_len + iv_len + block_len)))
288 if (silc_likely(check_mac)) {
289 /* Check the MAC of the message */
290 SILC_LOG_DEBUG(("Checking message MAC"));
291 silc_hmac_init(hmac);
292 silc_hmac_update(hmac, data, data_len - mac_len);
293 silc_hmac_final(hmac, mac, &mac_len);
294 if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) {
295 SILC_LOG_DEBUG(("Message MAC does not match"));
298 SILC_LOG_DEBUG(("MAC is Ok"));
301 /* Decrypt first only one block to get the header and then rest of
302 the data. This is done because there might be unencrypted data at
303 the end and we don't know the encrypted length yet. */
305 /* Get pointer to the IV */
306 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
307 silc_cipher_get_iv(cipher));
310 if (silc_unlikely(!silc_cipher_decrypt(cipher, data, data, block_len,
316 /* Get the payload length and decrypt rest */
318 SILC_GET16_MSB(len, data + totlen);
320 if (silc_unlikely(totlen + iv_len + mac_len + 2 > data_len))
323 if (totlen >= block_len)
324 if (silc_unlikely(!silc_cipher_decrypt(cipher, data + block_len,
326 (totlen - block_len) +
327 SILC_MESSAGE_PAD(totlen), ivp))) {
335 /* Parses Message Payload returning new payload structure. This also
336 decrypts it and checks the MAC. */
339 silc_message_payload_parse(unsigned char *payload,
340 SilcUInt32 payload_len,
341 SilcBool private_message,
346 SilcBool no_allocation,
347 SilcMessagePayload message)
349 SilcBufferStruct buffer;
350 SilcMessagePayload newp = NULL;
352 SilcUInt32 mac_len = 0, iv_len = 0;
354 SILC_LOG_DEBUG(("Parsing Message Payload"));
356 silc_buffer_set(&buffer, payload, payload_len);
358 /* Decrypt the payload */
359 if (silc_likely(cipher)) {
360 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
361 private_message, static_key,
363 if (silc_unlikely(ret == FALSE))
367 if (silc_likely(hmac))
368 mac_len = silc_hmac_len(hmac);
370 /* IV is present for all channel messages, and private messages when
371 static key (pre-shared key) is used. */
372 if (cipher && (!private_message || (private_message && static_key)))
373 iv_len = silc_cipher_get_block_len(cipher);
376 newp = message = silc_calloc(1, sizeof(*newp));
377 if (silc_unlikely(!newp))
380 memset(message, 0, sizeof(*message));
381 message->allocated = (stack || no_allocation ? FALSE : TRUE);
383 /* Parse the Message Payload. */
385 ret = silc_buffer_sunformat(stack, &buffer,
386 SILC_STR_UI_SHORT(&message->flags),
387 SILC_STR_UI16_NSTRING_ALLOC(&message->data,
389 SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
393 ret = silc_buffer_unformat(&buffer,
394 SILC_STR_UI_SHORT(&message->flags),
395 SILC_STR_UI16_NSTRING(&message->data,
397 SILC_STR_UI16_NSTRING(&message->pad,
400 if (silc_unlikely(ret == -1))
403 if (silc_unlikely((message->data_len > silc_buffer_len(&buffer) -
404 6 - mac_len - iv_len) ||
405 (message->pad_len + message->data_len >
406 silc_buffer_len(&buffer) - 6 - mac_len - iv_len))) {
407 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
411 /* Parse Signed Message Payload if provided */
412 if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
413 message->data_len + message->pad_len + 6 + mac_len +
414 iv_len < silc_buffer_len(&buffer)) {
415 if (!silc_message_signed_payload_parse(buffer.data + 6 +
418 silc_buffer_len(&buffer) -
419 iv_len - mac_len - 6 -
426 /* Parse MAC from the payload */
428 message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
434 silc_message_payload_free(newp);
439 /***************************** Payload encoding *****************************/
441 /* This function is used to encrypt the Messsage Payload which is
442 the `data' and `data_len'. This is used internally by the Message
443 Payload encoding routines but application may call this too if needed.
444 The `true_len' is the data length which is used to create MAC out of. */
446 SilcBool silc_message_payload_encrypt(unsigned char *data,
453 /* Encrypt payload of the packet */
454 if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv)))
457 /* Compute the MAC of the encrypted message data */
458 silc_hmac_init(hmac);
459 silc_hmac_update(hmac, data, true_len);
460 silc_hmac_final(hmac, data + true_len, NULL);
465 /* Encrypt message payload */
467 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
468 void *value, void *context)
470 SilcMessageEncode *e = context;
473 if (!e->cipher || !e->hmac)
476 mac_len = silc_hmac_len(e->hmac);
477 if (silc_unlikely(!silc_buffer_enlarge(buffer, mac_len)))
480 if (silc_unlikely(!silc_message_payload_encrypt(buffer->head,
482 silc_buffer_headlen(buffer),
483 e->iv, e->cipher, e->hmac)))
489 /* Compute message signature */
491 static int silc_message_payload_encode_sig(SilcBuffer buffer,
492 void *value, void *context)
494 SilcMessageEncode *e = context;
498 if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
501 sig = silc_message_signed_payload_encode(buffer->head,
502 silc_buffer_headlen(buffer),
503 e->public_key, e->private_key,
505 if (silc_unlikely(!sig))
508 len = silc_buffer_format(buffer,
509 SILC_STR_DATA(silc_buffer_data(sig),
510 silc_buffer_len(sig)),
512 if (silc_unlikely(len < 0)) {
513 silc_buffer_free(sig);
517 silc_buffer_free(sig);
521 /* Encodes Message Payload into a buffer and returns it. */
523 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
524 const unsigned char *data,
526 SilcBool generate_iv,
527 SilcBool private_message,
531 SilcPublicKey public_key,
532 SilcPrivateKey private_key,
536 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
537 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
538 SilcBuffer buf = NULL;
542 SILC_LOG_DEBUG(("Encoding Message Payload"));
544 if (silc_unlikely(!data_len))
546 if (silc_unlikely(!private_message && (!cipher || !hmac)))
550 buf = buffer = silc_buffer_alloc(0);
551 if (silc_unlikely(!buf))
554 silc_buffer_reset(buffer);
556 /* For channel messages IV is always generated */
557 if (!private_message && !generate_iv)
561 if (cipher && generate_iv) {
562 iv_len = silc_cipher_get_block_len(cipher);
564 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
566 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
571 mac_len = silc_hmac_len(hmac);
572 data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
573 public_key, private_key);
575 /* Calculate length of padding. IV is not included into the calculation
576 since it is not encrypted. */
577 pad_len = SILC_MESSAGE_PAD(6 + data_len);
579 /* Generate padding */
582 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
584 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
589 e.public_key = public_key;
590 e.private_key = private_key;
594 e.iv = iv_len ? iv : NULL;
595 e.payload_len = 6 + data_len + pad_len;
597 /* Encode the Message Payload */
598 if (silc_buffer_format(buffer,
599 SILC_STR_UI_SHORT(flags),
600 SILC_STR_UI_SHORT(data_len),
601 SILC_STR_DATA(data, data_len),
602 SILC_STR_UI_SHORT(pad_len),
603 SILC_STR_DATA(pad, pad_len),
604 SILC_STR_FUNC(silc_message_payload_encode_sig,
606 SILC_STR_DATA(iv, iv_len),
607 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
610 silc_buffer_free(buf);
617 /* Free's Message Payload */
619 void silc_message_payload_free(SilcMessagePayload payload)
622 memset(payload->data, 0, payload->data_len);
623 if (payload->allocated)
624 silc_free(payload->data);
626 if (payload->allocated) {
627 silc_free(payload->pad);
630 silc_message_signed_payload_free(&payload->sig);
635 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
637 return payload->flags;
642 unsigned char *silc_message_get_data(SilcMessagePayload payload,
643 SilcUInt32 *data_len)
646 *data_len = payload->data_len;
647 return payload->data;
650 /* Return MAC. The caller knows the length of the MAC */
652 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
657 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
659 SilcAuthResult silc_message_signed_verify(SilcMessagePayload message,
660 SilcPublicKey remote_public_key,
663 int ret = SILC_AUTH_FAILED;
664 SilcBuffer sign, tmp;
665 SilcMessageSignedPayload sig = &message->sig;
667 if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
668 !sig->sign_len || !remote_public_key || !hash)
671 /* Generate the signature verification data, the Message Payload */
672 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
673 silc_buffer_format(tmp,
674 SILC_STR_UI_SHORT(message->flags),
675 SILC_STR_UI_SHORT(message->data_len),
676 SILC_STR_UI_XNSTRING(message->data, message->data_len),
677 SILC_STR_UI_SHORT(message->pad_len),
678 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
680 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
681 sig->pk_data, sig->pk_len,
683 silc_buffer_clear(tmp);
684 silc_buffer_free(tmp);
689 /* Verify the authentication data */
690 if (!silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len,
691 silc_buffer_data(sign), silc_buffer_len(sign), hash)) {
692 silc_buffer_clear(sign);
693 silc_buffer_free(sign);
694 SILC_LOG_DEBUG(("Signature verification failed"));
700 silc_buffer_clear(sign);
701 silc_buffer_free(sign);
703 SILC_LOG_DEBUG(("Signature verification successful"));
708 /* Return the public key from the payload */
711 silc_message_signed_get_public_key(SilcMessagePayload payload,
712 const unsigned char **pk_data,
713 SilcUInt32 *pk_data_len)
716 SilcMessageSignedPayload sig = &payload->sig;
721 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
726 *pk_data = sig->pk_data;
728 *pk_data_len = sig->pk_len;