5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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 /******************************************************************************
30 ******************************************************************************/
32 /* Calculates padding length for message payload */
33 #define SILC_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
35 /* Header length plus maximum padding length */
36 #define SILC_MESSAGE_HLEN 6 + 16
38 /* Returns the data length that fits to the packet. If data length is too
39 big it will be truncated to fit to the payload. */
40 #define SILC_MESSAGE_DATALEN(data_len, header_len) \
41 ((data_len + SILC_MESSAGE_HLEN + header_len) > \
42 SILC_PACKET_MAX_LEN ? \
43 data_len - ((data_len + SILC_MESSAGE_HLEN + header_len) - \
44 SILC_PACKET_MAX_LEN) : data_len)
46 /* Message Payload structure. Contents of this structure is parsed
48 struct SilcMessagePayloadStruct {
49 SilcMessageFlags flags;
57 SilcMessageSignedPayload sig;
60 /* Decrypts the Message Payload. The `data' is the actual Message Payload */
62 SilcBool silc_message_payload_decrypt(unsigned char *data,
64 SilcBool private_message,
70 SilcUInt32 mac_len, iv_len = 0, block_len;
71 SilcUInt16 len, totlen, dlen;
72 unsigned char mac[32], *ivp, *dec;
74 mac_len = silc_hmac_len(hmac);
76 /* IV is present for all channel messages, and private messages when
77 static key (pre-shared key) is used. */
78 if (!private_message || (private_message && static_key))
79 iv_len = silc_cipher_get_block_len(cipher);
81 if (data_len <= (mac_len + iv_len))
85 /* Check the MAC of the message */
86 SILC_LOG_DEBUG(("Checking message MAC"));
88 silc_hmac_update(hmac, data, data_len - mac_len);
89 silc_hmac_final(hmac, mac, &mac_len);
90 if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
91 SILC_LOG_DEBUG(("Message MAC does not match"));
94 SILC_LOG_DEBUG(("MAC is Ok"));
97 /* Decrypt the entire buffer into allocated decryption buffer, since we
98 do not reliably know its encrypted length (it may include unencrypted
101 /* Get pointer to the IV */
102 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
103 silc_cipher_get_iv(cipher));
105 /* Allocate buffer for decryption. Since there might be unencrypted
106 data at the end, it might not be multiple by block size, make it so. */
107 block_len = silc_cipher_get_block_len(cipher);
108 dlen = data_len - iv_len - mac_len;
109 if (dlen & (block_len - 1))
110 dlen += SILC_MESSAGE_PAD(dlen);
111 if (dlen > data_len - iv_len - mac_len)
113 dec = silc_malloc(dlen);
116 silc_cipher_decrypt(cipher, data, dec, dlen, ivp);
118 /* Now verify the true length of the payload and copy the decrypted
119 part over the original data. First get data length, and then padding
120 length from the decrypted data. Then, copy over the original data. */
123 SILC_GET16_MSB(len, dec + totlen);
125 if (totlen + iv_len + mac_len + 2 > data_len) {
126 memset(dec, 0, dlen);
130 SILC_GET16_MSB(len, dec + totlen);
132 if (totlen + iv_len + mac_len > data_len) {
133 memset(dec, 0, dlen);
138 memcpy(data, dec, totlen);
139 memset(dec, 0, dlen);
145 /* Parses Message Payload returning new payload structure. This also
146 decrypts it and checks the MAC. */
149 silc_message_payload_parse(unsigned char *payload,
150 SilcUInt32 payload_len,
151 SilcBool private_message,
156 SilcBufferStruct buffer;
157 SilcMessagePayload newp;
159 SilcUInt32 mac_len = 0, iv_len = 0;
161 SILC_LOG_DEBUG(("Parsing Message Payload"));
163 silc_buffer_set(&buffer, payload, payload_len);
165 /* Decrypt the payload */
167 ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
168 private_message, static_key,
175 mac_len = silc_hmac_len(hmac);
177 /* IV is present for all channel messages, and private messages when
178 static key (pre-shared key) is used. */
179 if (cipher && (!private_message || (private_message && static_key)))
180 iv_len = silc_cipher_get_block_len(cipher);
182 newp = silc_calloc(1, sizeof(*newp));
186 /* Parse the Message Payload. */
187 ret = silc_buffer_unformat(&buffer,
188 SILC_STR_UI_SHORT(&newp->flags),
189 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
191 SILC_STR_UI16_NSTRING_ALLOC(&newp->pad,
197 if ((newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
198 (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len)) {
199 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
203 /* Parse Signed Message Payload if provided */
204 if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
205 newp->data_len + newp->pad_len + 6 + mac_len + iv_len < silc_buffer_len(&buffer)) {
207 silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
209 silc_buffer_len(&buffer) - iv_len - mac_len);
212 /* Parse IV and MAC from the payload */
214 newp->iv = buffer.data + (silc_buffer_len(&buffer) - iv_len - mac_len);
215 newp->iv_len = iv_len;
218 newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
223 silc_message_payload_free(newp);
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,
240 unsigned char mac[32];
242 SilcBufferStruct buf;
244 /* Encrypt payload of the packet. If the IV is added to packet do
246 silc_cipher_encrypt(cipher, data, data, data_len, iv_len ? iv : NULL);
248 /* Compute the MAC of the encrypted message data */
249 silc_hmac_init(hmac);
250 silc_hmac_update(hmac, data, true_len);
251 silc_hmac_final(hmac, mac, &mac_len);
253 /* Put rest of the data to the payload */
254 silc_buffer_set(&buf, data, true_len + mac_len);
255 silc_buffer_pull(&buf, true_len);
256 silc_buffer_put(&buf, mac, mac_len);
261 /* Encodes Message Payload into a buffer and returns it. */
263 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
264 const unsigned char *data,
266 SilcBool generate_iv,
267 SilcBool private_message,
271 SilcPublicKey public_key,
272 SilcPrivateKey private_key,
277 SilcUInt32 len, pad_len = 0, mac_len = 0, iv_len = 0;
278 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
279 SilcBuffer sig = NULL;
281 SILC_LOG_DEBUG(("Encoding Message Payload"));
286 /* For channel messages IV is always generated */
287 if (!private_message && !generate_iv)
291 if (cipher && generate_iv) {
292 iv_len = silc_cipher_get_block_len(cipher);
294 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
296 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
301 mac_len = silc_hmac_len(hmac);
302 data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
304 /* Calculate length of padding. IV is not included into the calculation
305 since it is not encrypted. */
307 pad_len = SILC_MESSAGE_PAD(len);
309 /* Allocate payload buffer */
310 len += pad_len + iv_len + mac_len;
311 buffer = silc_buffer_alloc(len);
315 /* Generate padding */
318 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
320 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
324 /* Encode the Message Payload */
325 silc_buffer_pull_tail(buffer, 6 + data_len + pad_len);
326 silc_buffer_format(buffer,
327 SILC_STR_UI_SHORT(flags),
328 SILC_STR_UI_SHORT(data_len),
329 SILC_STR_UI_XNSTRING(data, data_len),
330 SILC_STR_UI_SHORT(pad_len),
331 SILC_STR_UI_XNSTRING(pad, pad_len),
334 memset(pad, 0, sizeof(pad));
336 /* Sign the message if wanted */
337 if (flags & SILC_MESSAGE_FLAG_SIGNED && private_key && hash) {
338 sig = silc_message_signed_payload_encode(buffer->data, silc_buffer_len(buffer),
339 public_key, private_key, hash);
341 buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) + silc_buffer_len(sig));
343 silc_buffer_pull(buffer, 6 + data_len + pad_len);
344 silc_buffer_pull_tail(buffer, silc_buffer_len(sig));
345 silc_buffer_put(buffer, sig->data, silc_buffer_len(sig));
346 silc_buffer_push(buffer, 6 + data_len + pad_len);
352 silc_buffer_pull(buffer, 6 + data_len + pad_len + (sig ? silc_buffer_len(sig) : 0));
353 silc_buffer_pull_tail(buffer, iv_len);
354 silc_buffer_format(buffer,
355 SILC_STR_UI_XNSTRING(iv, iv_len),
357 silc_buffer_push(buffer, 6 + data_len + pad_len + (sig ? silc_buffer_len(sig) : 0));
359 SILC_LOG_HEXDUMP(("foo"), buffer->data, silc_buffer_len(buffer));
361 /* Now encrypt the Message Payload and compute MAC */
363 if (!silc_message_payload_encrypt(buffer->data,
364 silc_buffer_len(buffer) - iv_len -
365 (sig ? silc_buffer_len(sig) : 0),
366 silc_buffer_len(buffer), iv, iv_len,
368 silc_buffer_free(buffer);
369 silc_buffer_free(sig);
373 silc_buffer_pull_tail(buffer, silc_buffer_truelen(buffer) - silc_buffer_len(buffer));
375 silc_buffer_free(sig);
379 /* Free's Message Payload */
381 void silc_message_payload_free(SilcMessagePayload payload)
384 memset(payload->data, 0, payload->data_len);
385 silc_free(payload->data);
388 silc_message_signed_payload_free(payload->sig);
389 silc_free(payload->pad);
395 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
397 return payload->flags;
402 unsigned char *silc_message_get_data(SilcMessagePayload payload,
403 SilcUInt32 *data_len)
406 *data_len = payload->data_len;
407 return payload->data;
410 /* Return MAC. The caller knows the length of the MAC */
412 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
417 /* Return IV. The caller knows the length of the IV */
419 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
424 /* Return signature of the message */
426 SilcMessageSignedPayload
427 silc_message_get_signature(SilcMessagePayload payload)
432 /******************************************************************************
434 SILC_MESSAGE_FLAG_SIGNED Payload
436 ******************************************************************************/
438 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
439 struct SilcMessageSignedPayloadStruct {
443 unsigned char *pk_data;
444 unsigned char *sign_data;
447 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
450 silc_message_signed_encode_data(const unsigned char *message_payload,
451 SilcUInt32 message_payload_len,
453 SilcUInt32 pk_len, SilcUInt32 pk_type)
457 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
461 silc_buffer_format(sign,
462 SILC_STR_UI_XNSTRING(message_payload,
463 message_payload_len),
464 SILC_STR_UI_SHORT(pk_len),
465 SILC_STR_UI_SHORT(pk_type),
469 silc_buffer_pull(sign, message_payload_len + 4);
470 silc_buffer_format(sign,
471 SILC_STR_UI_XNSTRING(pk, pk_len),
473 silc_buffer_push(sign, message_payload_len + 4);
479 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
481 SilcMessageSignedPayload
482 silc_message_signed_payload_parse(const unsigned char *data,
485 SilcMessageSignedPayload sig;
486 SilcBufferStruct buffer;
489 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
491 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
493 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
494 sig = silc_calloc(1, sizeof(*sig));
498 /* Parse the payload */
499 ret = silc_buffer_unformat(&buffer,
500 SILC_STR_UI_SHORT(&sig->pk_len),
501 SILC_STR_UI_SHORT(&sig->pk_type),
503 if (ret == -1 || sig->pk_len > data_len - 4) {
504 silc_message_signed_payload_free(sig);
505 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
510 silc_buffer_pull(&buffer, 4);
511 ret = silc_buffer_unformat(&buffer,
512 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
514 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
517 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) - sig->pk_len - 2) {
518 silc_message_signed_payload_free(sig);
519 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
522 silc_buffer_push(&buffer, 4);
524 /* Signature must be provided */
525 if (sig->sign_len < 1) {
526 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
528 silc_message_signed_payload_free(sig);
535 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
539 silc_message_signed_payload_encode(const unsigned char *message_payload,
540 SilcUInt32 message_payload_len,
541 SilcPublicKey public_key,
542 SilcPrivateKey private_key,
545 SilcBuffer buffer, sign;
547 unsigned char auth_data[2048 + 1];
549 unsigned char *pk = NULL;
550 SilcUInt32 pk_len = 0;
553 if (!message_payload || !message_payload_len || !private_key || !hash)
557 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
559 /* Now we support only SILC style public key */
560 pk_type = SILC_SKE_PK_TYPE_SILC;
562 /* Encode the data to be signed */
563 sign = silc_message_signed_encode_data(message_payload,
565 pk, pk_len, pk_type);
571 /* Sign the buffer */
573 /* Allocate PKCS object */
574 if (!silc_pkcs_alloc(private_key->name, SILC_PKCS_SILC, &pkcs)) {
575 SILC_LOG_ERROR(("Could not allocated PKCS"));
576 silc_buffer_clear(sign);
577 silc_buffer_free(sign);
581 silc_pkcs_private_key_set(pkcs, private_key);
583 /* Compute the hash and the signature. */
584 if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
585 !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, silc_buffer_len(sign), auth_data,
587 SILC_LOG_ERROR(("Could not compute signature"));
588 silc_buffer_clear(sign);
589 silc_buffer_free(sign);
590 silc_pkcs_free(pkcs);
595 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
597 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
599 silc_buffer_clear(sign);
600 silc_buffer_free(sign);
601 silc_pkcs_free(pkcs);
602 memset(auth_data, 0, sizeof(auth_data));
607 silc_buffer_format(buffer,
608 SILC_STR_UI_SHORT(pk_len),
609 SILC_STR_UI_SHORT(pk_type),
613 silc_buffer_pull(buffer, 4);
614 silc_buffer_format(buffer,
615 SILC_STR_UI_XNSTRING(pk, pk_len),
617 silc_buffer_push(buffer, 4);
620 silc_buffer_pull(buffer, 4 + pk_len);
621 silc_buffer_format(buffer,
622 SILC_STR_UI_SHORT(auth_len),
623 SILC_STR_UI_XNSTRING(auth_data, auth_len),
625 silc_buffer_push(buffer, 4 + pk_len);
627 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
629 memset(auth_data, 0, sizeof(auth_data));
630 silc_pkcs_free(pkcs);
631 silc_buffer_clear(sign);
632 silc_buffer_free(sign);
638 /* Free the payload */
640 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
642 memset(sig->sign_data, 0, sig->sign_len);
643 silc_free(sig->sign_data);
644 silc_free(sig->pk_data);
648 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
650 int silc_message_signed_verify(SilcMessageSignedPayload sig,
651 SilcMessagePayload message,
652 SilcPublicKey remote_public_key,
655 int ret = SILC_AUTH_FAILED;
660 if (!sig || !remote_public_key || !hash)
663 /* Generate the signature verification data, the Message Payload */
664 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
665 silc_buffer_format(tmp,
666 SILC_STR_UI_SHORT(message->flags),
667 SILC_STR_UI_SHORT(message->data_len),
668 SILC_STR_UI_XNSTRING(message->data, message->data_len),
669 SILC_STR_UI_SHORT(message->pad_len),
670 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
672 sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
673 sig->pk_data, sig->pk_len,
675 silc_buffer_clear(tmp);
676 silc_buffer_free(tmp);
681 /* Allocate PKCS object */
682 if (!silc_pkcs_alloc(remote_public_key->name, SILC_PKCS_SILC, &pkcs)) {
683 silc_buffer_clear(sign);
684 silc_buffer_free(sign);
687 silc_pkcs_public_key_set(pkcs, remote_public_key);
689 /* Verify the authentication data */
690 if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
692 sign->data, silc_buffer_len(sign))) {
694 silc_buffer_clear(sign);
695 silc_buffer_free(sign);
696 silc_pkcs_free(pkcs);
697 SILC_LOG_DEBUG(("Signature verification failed"));
703 silc_buffer_clear(sign);
704 silc_buffer_free(sign);
705 silc_pkcs_free(pkcs);
707 SILC_LOG_DEBUG(("Signature verification successful"));
712 /* Return the public key from the payload */
715 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
716 unsigned char **pk_data,
717 SilcUInt32 *pk_data_len)
721 if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
726 *pk_data = sig->pk_data;
728 *pk_data_len = sig->pk_len;