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;
53 SilcMessageSignedPayload sig;
56 /* Payload encoding context */
58 SilcMessageFlags flags;
59 SilcPublicKey public_key;
60 SilcPrivateKey private_key;
65 SilcUInt16 payload_len;
69 /****************************** Payload parsing *****************************/
71 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
73 SilcBool silc_message_payload_decrypt(unsigned char *data,
75 SilcBool private_message,
81 SilcUInt32 mac_len, iv_len = 0, block_len;
82 SilcUInt16 len, totlen;
83 unsigned char mac[32], *ivp;
85 mac_len = silc_hmac_len(hmac);
86 block_len = silc_cipher_get_block_len(cipher);
88 /* IV is present for all channel messages, and private messages when
89 static key (pre-shared key) is used. */
90 if (!private_message || (private_message && static_key))
93 if (data_len <= (mac_len + iv_len))
97 /* Check the MAC of the message */
98 SILC_LOG_DEBUG(("Checking message MAC"));
100 silc_hmac_update(hmac, data, data_len - mac_len);
101 silc_hmac_final(hmac, mac, &mac_len);
102 if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
103 SILC_LOG_DEBUG(("Message MAC does not match"));
106 SILC_LOG_DEBUG(("MAC is Ok"));
109 /* Decrypt first only one block to get the header and then rest of
110 the data. This is done because there might be unencrypted data at
111 the end and we don't know the encrypted length yet. */
113 /* Get pointer to the IV */
114 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
115 silc_cipher_get_iv(cipher));
118 if (!silc_cipher_decrypt(cipher, data, data, block_len, ivp))
121 /* Get the payload length and decrypt rest */
123 SILC_GET16_MSB(len, data + totlen);
125 if (totlen + iv_len + mac_len + 2 > data_len)
127 SILC_GET16_MSB(len, data + totlen);
129 if (totlen + iv_len + mac_len > data_len)
131 if (totlen - block_len)
132 if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
133 totlen - block_len, ivp))
139 /* Parses Message Payload returning new payload structure. This also
140 decrypts it and checks the MAC. */
143 silc_message_payload_parse(unsigned char *payload,
144 SilcUInt32 payload_len,
145 SilcBool private_message,
150 SilcBufferStruct buffer;
151 SilcMessagePayload newp;
153 SilcUInt32 mac_len = 0, iv_len = 0;
155 SILC_LOG_DEBUG(("Parsing Message Payload"));
157 silc_buffer_set(&buffer, payload, payload_len);
159 /* Decrypt the payload */
161 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
162 private_message, static_key,
169 mac_len = silc_hmac_len(hmac);
171 /* IV is present for all channel messages, and private messages when
172 static key (pre-shared key) is used. */
173 if (cipher && (!private_message || (private_message && static_key)))
174 iv_len = silc_cipher_get_block_len(cipher);
176 newp = silc_calloc(1, sizeof(*newp));
180 /* Parse the Message Payload. */
181 ret = silc_buffer_unformat(&buffer,
182 SILC_STR_UI_SHORT(&newp->flags),
183 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
185 SILC_STR_UI16_NSTRING_ALLOC(&newp->pad,
191 if ((newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
192 (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) -
193 6 - mac_len - iv_len)) {
194 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
198 /* Parse Signed Message Payload if provided */
199 if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
200 newp->data_len + newp->pad_len + 6 + mac_len +
201 iv_len < silc_buffer_len(&buffer)) {
203 silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
205 silc_buffer_len(&buffer) -
209 /* Parse IV and MAC from the payload */
211 newp->iv = buffer.data + (silc_buffer_len(&buffer) - iv_len - mac_len);
212 newp->iv_len = iv_len;
215 newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
220 silc_message_payload_free(newp);
225 /***************************** Payload encoding *****************************/
227 /* This function is used to encrypt the Messsage Payload which is
228 the `data' and `data_len'. This is used internally by the Message
229 Payload encoding routines but application may call this too if needed.
230 The `true_len' is the data length which is used to create MAC out of. */
232 SilcBool silc_message_payload_encrypt(unsigned char *data,
239 /* Encrypt payload of the packet */
240 if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
243 /* Compute the MAC of the encrypted message data */
244 silc_hmac_init(hmac);
245 silc_hmac_update(hmac, data, true_len);
246 silc_hmac_final(hmac, data + true_len, NULL);
251 /* Encrypt message payload */
253 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
254 void *value, void *context)
256 SilcMessageEncode *e = context;
259 if (!e->cipher || !e->hmac)
262 mac_len = silc_hmac_len(e->hmac);
263 if (!silc_buffer_enlarge(buffer, mac_len))
266 if (!silc_message_payload_encrypt(buffer->head,
268 silc_buffer_headlen(buffer),
269 e->iv, e->cipher, e->hmac))
275 /* Compute message signature */
277 static int silc_message_payload_encode_sig(SilcBuffer buffer,
278 void *value, void *context)
280 SilcMessageEncode *e = context;
284 if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
287 sig = silc_message_signed_payload_encode(buffer->head,
288 silc_buffer_headlen(buffer),
289 e->public_key, e->private_key,
294 len = silc_buffer_format(buffer,
295 SILC_STR_DATA(silc_buffer_data(sig),
296 silc_buffer_len(sig)),
299 silc_buffer_free(sig);
303 silc_buffer_free(sig);
307 /* Encodes Message Payload into a buffer and returns it. */
309 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
310 const unsigned char *data,
312 SilcBool generate_iv,
313 SilcBool private_message,
317 SilcPublicKey public_key,
318 SilcPrivateKey private_key,
322 SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
323 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
324 SilcBuffer buf = NULL;
328 SILC_LOG_DEBUG(("Encoding Message Payload"));
334 buf = buffer = silc_buffer_alloc(0);
338 silc_buffer_reset(buffer);
340 /* For channel messages IV is always generated */
341 if (!private_message && !generate_iv)
345 if (cipher && generate_iv) {
346 iv_len = silc_cipher_get_block_len(cipher);
348 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
350 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
355 mac_len = silc_hmac_len(hmac);
356 data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
358 /* Calculate length of padding. IV is not included into the calculation
359 since it is not encrypted. */
360 pad_len = SILC_MESSAGE_PAD(6 + data_len);
362 /* Generate padding */
365 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
367 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
372 e.public_key = public_key;
373 e.private_key = private_key;
377 e.iv = iv_len ? iv : NULL;
378 e.payload_len = 6 + data_len + pad_len;
380 /* Encode the Message Payload */
381 if (silc_buffer_format(buffer,
382 SILC_STR_UI_SHORT(flags),
383 SILC_STR_UI_SHORT(data_len),
384 SILC_STR_DATA(data, data_len),
385 SILC_STR_UI_SHORT(pad_len),
386 SILC_STR_DATA(pad, pad_len),
387 SILC_STR_FUNC(silc_message_payload_encode_sig,
389 SILC_STR_DATA(iv, iv_len),
390 SILC_STR_FUNC(silc_message_payload_encode_encrypt,
393 silc_buffer_free(buf);
400 /* Free's Message Payload */
402 void silc_message_payload_free(SilcMessagePayload payload)
405 memset(payload->data, 0, payload->data_len);
406 silc_free(payload->data);
409 silc_message_signed_payload_free(payload->sig);
410 silc_free(payload->pad);
416 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
418 return payload->flags;
423 unsigned char *silc_message_get_data(SilcMessagePayload payload,
424 SilcUInt32 *data_len)
427 *data_len = payload->data_len;
428 return payload->data;
431 /* Return MAC. The caller knows the length of the MAC */
433 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
438 /* Return IV. The caller knows the length of the IV */
440 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
445 /* Return signature of the message */
447 SilcMessageSignedPayload
448 silc_message_get_signature(SilcMessagePayload payload)
454 /************************ Message Signature Payload *************************/
456 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
457 struct SilcMessageSignedPayloadStruct {
461 unsigned char *pk_data;
462 unsigned char *sign_data;
465 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
468 silc_message_signed_encode_data(const unsigned char *message_payload,
469 SilcUInt32 message_payload_len,
471 SilcUInt32 pk_len, SilcUInt32 pk_type)
475 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
479 silc_buffer_format(sign,
480 SILC_STR_UI_XNSTRING(message_payload,
481 message_payload_len),
482 SILC_STR_UI_SHORT(pk_len),
483 SILC_STR_UI_SHORT(pk_type),
487 silc_buffer_pull(sign, message_payload_len + 4);
488 silc_buffer_format(sign,
489 SILC_STR_UI_XNSTRING(pk, pk_len),
491 silc_buffer_push(sign, message_payload_len + 4);
497 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
499 SilcMessageSignedPayload
500 silc_message_signed_payload_parse(const unsigned char *data,
503 SilcMessageSignedPayload sig;
504 SilcBufferStruct buffer;
507 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
509 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
511 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
512 sig = silc_calloc(1, sizeof(*sig));
516 /* Parse the payload */
517 ret = silc_buffer_unformat(&buffer,
518 SILC_STR_UI_SHORT(&sig->pk_len),
519 SILC_STR_UI_SHORT(&sig->pk_type),
521 if (ret == -1 || sig->pk_len > data_len - 4) {
522 silc_message_signed_payload_free(sig);
523 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
528 silc_buffer_pull(&buffer, 4);
529 ret = silc_buffer_unformat(&buffer,
530 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
532 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
535 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
537 silc_message_signed_payload_free(sig);
538 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
541 silc_buffer_push(&buffer, 4);
543 /* Signature must be provided */
544 if (sig->sign_len < 1) {
545 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
547 silc_message_signed_payload_free(sig);
554 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
558 silc_message_signed_payload_encode(const unsigned char *message_payload,
559 SilcUInt32 message_payload_len,
560 SilcPublicKey public_key,
561 SilcPrivateKey private_key,
564 SilcBuffer buffer, sign;
565 unsigned char auth_data[2048 + 1];
567 unsigned char *pk = NULL;
568 SilcUInt32 pk_len = 0;
571 if (!message_payload || !message_payload_len || !private_key || !hash)
575 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
579 pk_type = silc_pkcs_get_type(public_key);
581 /* Encode the data to be signed */
582 sign = silc_message_signed_encode_data(message_payload,
584 pk, pk_len, pk_type);
590 /* Sign the buffer */
592 /* Compute the hash and the signature. */
593 if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
594 auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
595 SILC_LOG_ERROR(("Could not compute signature"));
596 silc_buffer_clear(sign);
597 silc_buffer_free(sign);
602 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
604 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
606 silc_buffer_clear(sign);
607 silc_buffer_free(sign);
608 memset(auth_data, 0, sizeof(auth_data));
613 silc_buffer_format(buffer,
614 SILC_STR_UI_SHORT(pk_len),
615 SILC_STR_UI_SHORT(pk_type),
619 silc_buffer_pull(buffer, 4);
620 silc_buffer_format(buffer,
621 SILC_STR_UI_XNSTRING(pk, pk_len),
623 silc_buffer_push(buffer, 4);
626 silc_buffer_pull(buffer, 4 + pk_len);
627 silc_buffer_format(buffer,
628 SILC_STR_UI_SHORT(auth_len),
629 SILC_STR_UI_XNSTRING(auth_data, auth_len),
631 silc_buffer_push(buffer, 4 + pk_len);
633 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
635 memset(auth_data, 0, sizeof(auth_data));
636 silc_buffer_clear(sign);
637 silc_buffer_free(sign);
643 /* Free the payload */
645 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
647 memset(sig->sign_data, 0, sig->sign_len);
648 silc_free(sig->sign_data);
649 silc_free(sig->pk_data);
653 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
655 int silc_message_signed_verify(SilcMessageSignedPayload sig,
656 SilcMessagePayload message,
657 SilcPublicKey remote_public_key,
660 int ret = SILC_AUTH_FAILED;
661 SilcBuffer sign, tmp;
663 if (!sig || !remote_public_key || !hash)
666 /* Generate the signature verification data, the Message Payload */
667 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
668 silc_buffer_format(tmp,
669 SILC_STR_UI_SHORT(message->flags),
670 SILC_STR_UI_SHORT(message->data_len),
671 SILC_STR_UI_XNSTRING(message->data, message->data_len),
672 SILC_STR_UI_SHORT(message->pad_len),
673 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
675 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
676 sig->pk_data, sig->pk_len,
678 silc_buffer_clear(tmp);
679 silc_buffer_free(tmp);
684 /* Verify the authentication data */
685 if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
687 sign->data, silc_buffer_len(sign), hash)) {
689 silc_buffer_clear(sign);
690 silc_buffer_free(sign);
691 SILC_LOG_DEBUG(("Signature verification failed"));
697 silc_buffer_clear(sign);
698 silc_buffer_free(sign);
700 SILC_LOG_DEBUG(("Signature verification successful"));
705 /* Return the public key from the payload */
708 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
709 const unsigned char **pk_data,
710 SilcUInt32 *pk_data_len)
717 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
722 *pk_data = sig->pk_data;
724 *pk_data_len = sig->pk_len;