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 /******************************************************************************
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,
339 silc_buffer_len(buffer),
340 public_key, private_key, hash);
342 buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
343 silc_buffer_len(sig));
345 silc_buffer_pull(buffer, 6 + data_len + pad_len);
346 silc_buffer_pull_tail(buffer, silc_buffer_len(sig));
347 silc_buffer_put(buffer, sig->data, silc_buffer_len(sig));
348 silc_buffer_push(buffer, 6 + data_len + pad_len);
354 silc_buffer_pull(buffer, 6 + data_len + pad_len +
355 (sig ? silc_buffer_len(sig) : 0));
356 silc_buffer_pull_tail(buffer, iv_len);
357 silc_buffer_format(buffer,
358 SILC_STR_UI_XNSTRING(iv, iv_len),
360 silc_buffer_push(buffer, 6 + data_len + pad_len +
361 (sig ? silc_buffer_len(sig) : 0));
363 /* Now encrypt the Message Payload and compute MAC */
365 if (!silc_message_payload_encrypt(buffer->data,
366 silc_buffer_len(buffer) - iv_len -
367 (sig ? silc_buffer_len(sig) : 0),
368 silc_buffer_len(buffer), iv, iv_len,
370 silc_buffer_free(buffer);
371 silc_buffer_free(sig);
375 silc_buffer_pull_tail(buffer, silc_buffer_truelen(buffer) -
376 silc_buffer_len(buffer));
378 silc_buffer_free(sig);
382 /* Free's Message Payload */
384 void silc_message_payload_free(SilcMessagePayload payload)
387 memset(payload->data, 0, payload->data_len);
388 silc_free(payload->data);
391 silc_message_signed_payload_free(payload->sig);
392 silc_free(payload->pad);
398 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
400 return payload->flags;
405 unsigned char *silc_message_get_data(SilcMessagePayload payload,
406 SilcUInt32 *data_len)
409 *data_len = payload->data_len;
410 return payload->data;
413 /* Return MAC. The caller knows the length of the MAC */
415 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
420 /* Return IV. The caller knows the length of the IV */
422 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
427 /* Return signature of the message */
429 SilcMessageSignedPayload
430 silc_message_get_signature(SilcMessagePayload payload)
435 /******************************************************************************
437 SILC_MESSAGE_FLAG_SIGNED Payload
439 ******************************************************************************/
441 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
442 struct SilcMessageSignedPayloadStruct {
446 unsigned char *pk_data;
447 unsigned char *sign_data;
450 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
453 silc_message_signed_encode_data(const unsigned char *message_payload,
454 SilcUInt32 message_payload_len,
456 SilcUInt32 pk_len, SilcUInt32 pk_type)
460 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
464 silc_buffer_format(sign,
465 SILC_STR_UI_XNSTRING(message_payload,
466 message_payload_len),
467 SILC_STR_UI_SHORT(pk_len),
468 SILC_STR_UI_SHORT(pk_type),
472 silc_buffer_pull(sign, message_payload_len + 4);
473 silc_buffer_format(sign,
474 SILC_STR_UI_XNSTRING(pk, pk_len),
476 silc_buffer_push(sign, message_payload_len + 4);
482 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
484 SilcMessageSignedPayload
485 silc_message_signed_payload_parse(const unsigned char *data,
488 SilcMessageSignedPayload sig;
489 SilcBufferStruct buffer;
492 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
494 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
496 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
497 sig = silc_calloc(1, sizeof(*sig));
501 /* Parse the payload */
502 ret = silc_buffer_unformat(&buffer,
503 SILC_STR_UI_SHORT(&sig->pk_len),
504 SILC_STR_UI_SHORT(&sig->pk_type),
506 if (ret == -1 || sig->pk_len > data_len - 4) {
507 silc_message_signed_payload_free(sig);
508 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
513 silc_buffer_pull(&buffer, 4);
514 ret = silc_buffer_unformat(&buffer,
515 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
517 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
520 if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) - sig->pk_len - 2) {
521 silc_message_signed_payload_free(sig);
522 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
525 silc_buffer_push(&buffer, 4);
527 /* Signature must be provided */
528 if (sig->sign_len < 1) {
529 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
531 silc_message_signed_payload_free(sig);
538 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
542 silc_message_signed_payload_encode(const unsigned char *message_payload,
543 SilcUInt32 message_payload_len,
544 SilcPublicKey public_key,
545 SilcPrivateKey private_key,
548 SilcBuffer buffer, sign;
549 unsigned char auth_data[2048 + 1];
551 unsigned char *pk = NULL;
552 SilcUInt32 pk_len = 0;
555 if (!message_payload || !message_payload_len || !private_key || !hash)
559 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
563 pk_type = silc_pkcs_get_type(public_key);
565 /* Encode the data to be signed */
566 sign = silc_message_signed_encode_data(message_payload,
568 pk, pk_len, pk_type);
574 /* Sign the buffer */
576 /* Compute the hash and the signature. */
577 if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
578 auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
579 SILC_LOG_ERROR(("Could not compute signature"));
580 silc_buffer_clear(sign);
581 silc_buffer_free(sign);
586 /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
588 buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
590 silc_buffer_clear(sign);
591 silc_buffer_free(sign);
592 memset(auth_data, 0, sizeof(auth_data));
597 silc_buffer_format(buffer,
598 SILC_STR_UI_SHORT(pk_len),
599 SILC_STR_UI_SHORT(pk_type),
603 silc_buffer_pull(buffer, 4);
604 silc_buffer_format(buffer,
605 SILC_STR_UI_XNSTRING(pk, pk_len),
607 silc_buffer_push(buffer, 4);
610 silc_buffer_pull(buffer, 4 + pk_len);
611 silc_buffer_format(buffer,
612 SILC_STR_UI_SHORT(auth_len),
613 SILC_STR_UI_XNSTRING(auth_data, auth_len),
615 silc_buffer_push(buffer, 4 + pk_len);
617 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
619 memset(auth_data, 0, sizeof(auth_data));
620 silc_buffer_clear(sign);
621 silc_buffer_free(sign);
627 /* Free the payload */
629 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
631 memset(sig->sign_data, 0, sig->sign_len);
632 silc_free(sig->sign_data);
633 silc_free(sig->pk_data);
637 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
639 int silc_message_signed_verify(SilcMessageSignedPayload sig,
640 SilcMessagePayload message,
641 SilcPublicKey remote_public_key,
644 int ret = SILC_AUTH_FAILED;
646 SilcBufferStruct tmp;
648 if (!sig || !remote_public_key || !hash)
651 /* Generate the signature verification data, the Message Payload */
652 memset(&tmp, 0, sizeof(tmp));
653 silc_buffer_format(&tmp,
654 SILC_STR_UI_SHORT(message->flags),
655 SILC_STR_UI_SHORT(message->data_len),
656 SILC_STR_UI_XNSTRING(message->data, message->data_len),
657 SILC_STR_UI_SHORT(message->pad_len),
658 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
660 sign = silc_message_signed_encode_data(tmp.data, silc_buffer_len(&tmp),
661 sig->pk_data, sig->pk_len,
663 silc_buffer_clear(&tmp);
664 silc_free(silc_buffer_steal(&tmp, NULL));
669 /* Verify the authentication data */
670 if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
672 sign->data, silc_buffer_len(sign), hash)) {
674 silc_buffer_clear(sign);
675 silc_buffer_free(sign);
676 SILC_LOG_DEBUG(("Signature verification failed"));
682 silc_buffer_clear(sign);
683 silc_buffer_free(sign);
685 SILC_LOG_DEBUG(("Signature verification successful"));
690 /* Return the public key from the payload */
693 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
694 const unsigned char **pk_data,
695 SilcUInt32 *pk_data_len)
702 if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
707 *pk_data = sig->pk_data;
709 *pk_data_len = sig->pk_len;