5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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
23 #include "silcincludes.h"
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 bool silc_message_payload_decrypt(unsigned char *data,
70 SilcUInt32 mac_len, iv_len = 0;
71 SilcUInt16 len, totlen;
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)
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 /* Get pointer to the IV */
98 ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
99 silc_cipher_get_iv(cipher));
101 /* Decrypt the entire buffer into allocated decryption buffer. Then
102 use only the Message Payload and don't touch data after that, since
103 it may not be even encrypted (it may include signature payload).
104 Since we do not reliably know how long the Message Payload is we
105 decrypt entire data buffer. */
106 dec = silc_malloc(data_len - iv_len - mac_len);
107 silc_cipher_decrypt(cipher, data, dec, data_len - iv_len - mac_len, ivp);
109 /* Now verify the true length of the payload and copy the decrypted
110 part over the original data. First get data length, and then padding
111 length from the decrypted data. Then, copy over the original data. */
114 SILC_GET16_MSB(len, dec + totlen);
116 if (totlen + iv_len + mac_len + 2 > data_len) {
117 memset(dec, 0, data_len);
121 SILC_GET16_MSB(len, dec + totlen);
123 if (totlen + iv_len + mac_len > data_len) {
124 memset(dec, 0, data_len);
129 memcpy(data, dec, totlen);
130 memset(dec, 0, data_len);
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 bool 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, buffer.len,
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 > buffer.len - 6 - mac_len - iv_len) ||
189 (newp->pad_len + newp->data_len > buffer.len - 6 - mac_len - iv_len)) {
190 SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
194 /* Parse Signed Message Payload if provided */
195 if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
196 newp->data_len + newp->pad_len + 6 + mac_len + iv_len < buffer.len) {
198 silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
200 buffer.len - iv_len - mac_len);
203 /* Parse IV and MAC from the payload */
205 newp->iv = buffer.data + (buffer.len - iv_len - mac_len);
206 newp->iv_len = iv_len;
209 newp->mac = buffer.data + (buffer.len - mac_len);
214 silc_message_payload_free(newp);
218 /* This function is used to encrypt the Messsage Payload which is
219 the `data' and `data_len'. This is used internally by the Message
220 Payload encoding routines but application may call this too if needed.
221 The `true_len' is the data length which is used to create MAC out of. */
223 bool silc_message_payload_encrypt(unsigned char *data,
231 unsigned char mac[32];
233 SilcBufferStruct buf;
235 /* Encrypt payload of the packet. If the IV is added to packet do
237 silc_cipher_encrypt(cipher, data, data, data_len, iv_len ? iv : NULL);
239 /* Compute the MAC of the encrypted message data */
240 silc_hmac_init(hmac);
241 silc_hmac_update(hmac, data, true_len);
242 silc_hmac_final(hmac, mac, &mac_len);
244 /* Put rest of the data to the payload */
245 silc_buffer_set(&buf, data, true_len + mac_len);
246 silc_buffer_pull(&buf, true_len);
247 silc_buffer_put(&buf, mac, mac_len);
252 /* Encodes Message Payload into a buffer and returns it. */
254 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
255 const unsigned char *data,
258 bool private_message,
262 SilcPublicKey public_key,
263 SilcPrivateKey private_key,
268 SilcUInt32 len, pad_len = 0, mac_len = 0, iv_len = 0;
269 unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
270 SilcBuffer sig = NULL;
272 SILC_LOG_DEBUG(("Encoding Message Payload"));
277 /* For channel messages IV is always generated */
278 if (!private_message && !generate_iv)
282 if (cipher && generate_iv) {
283 iv_len = silc_cipher_get_block_len(cipher);
285 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
287 for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
292 mac_len = silc_hmac_len(hmac);
293 data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
295 /* Calculate length of padding. IV is not included into the calculation
296 since it is not encrypted. */
298 pad_len = SILC_MESSAGE_PAD(len);
300 /* Allocate payload buffer */
301 len += pad_len + iv_len + mac_len;
302 buffer = silc_buffer_alloc(len);
306 /* Generate padding */
309 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
311 for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
315 /* Encode the Message Payload */
316 silc_buffer_pull_tail(buffer, 6 + data_len + pad_len);
317 silc_buffer_format(buffer,
318 SILC_STR_UI_SHORT(flags),
319 SILC_STR_UI_SHORT(data_len),
320 SILC_STR_UI_XNSTRING(data, data_len),
321 SILC_STR_UI_SHORT(pad_len),
322 SILC_STR_UI_XNSTRING(pad, pad_len),
325 memset(pad, 0, sizeof(pad));
327 /* Sign the message if wanted */
328 if (flags & SILC_MESSAGE_FLAG_SIGNED && private_key && hash) {
329 sig = silc_message_signed_payload_encode(buffer->data, buffer->len,
330 public_key, private_key, hash);
332 buffer = silc_buffer_realloc(buffer, buffer->truelen + sig->len);
334 silc_buffer_pull(buffer, 6 + data_len + pad_len);
335 silc_buffer_pull_tail(buffer, sig->len);
336 silc_buffer_put(buffer, sig->data, sig->len);
337 silc_buffer_push(buffer, 6 + data_len + pad_len);
343 silc_buffer_pull(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
344 silc_buffer_pull_tail(buffer, iv_len);
345 silc_buffer_format(buffer,
346 SILC_STR_UI_XNSTRING(iv, iv_len),
348 silc_buffer_push(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
350 SILC_LOG_HEXDUMP(("foo"), buffer->data, buffer->len);
352 /* Now encrypt the Message Payload and compute MAC */
354 if (!silc_message_payload_encrypt(buffer->data,
355 buffer->len - iv_len -
356 (sig ? sig->len : 0),
357 buffer->len, iv, iv_len,
359 silc_buffer_free(buffer);
360 silc_buffer_free(sig);
364 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len);
366 silc_buffer_free(sig);
370 /* Free's Message Payload */
372 void silc_message_payload_free(SilcMessagePayload payload)
375 memset(payload->data, 0, payload->data_len);
376 silc_free(payload->data);
379 silc_message_signed_payload_free(payload->sig);
380 silc_free(payload->pad);
386 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
388 return payload->flags;
393 unsigned char *silc_message_get_data(SilcMessagePayload payload,
394 SilcUInt32 *data_len)
397 *data_len = payload->data_len;
398 return payload->data;
401 /* Return MAC. The caller knows the length of the MAC */
403 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
408 /* Return IV. The caller knows the length of the IV */
410 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
415 /* Return signature of the message */
417 const SilcMessageSignedPayload
418 silc_message_get_signature(SilcMessagePayload payload)
420 return (const SilcMessageSignedPayload)payload->sig;
423 /******************************************************************************
425 SILC_MESSAGE_FLAG_SIGNED Payload
427 ******************************************************************************/
429 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
430 struct SilcMessageSignedPayloadStruct {
434 unsigned char *pk_data;
435 unsigned char *sign_data;
438 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
441 silc_message_signed_encode_data(const unsigned char *message_payload,
442 SilcUInt32 message_payload_len,
444 SilcUInt32 pk_len, SilcUInt32 pk_type)
448 sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
452 silc_buffer_format(sign,
453 SILC_STR_UI_XNSTRING(message_payload,
454 message_payload_len),
455 SILC_STR_UI_SHORT(pk_len),
456 SILC_STR_UI_SHORT(pk_type),
460 silc_buffer_pull(sign, message_payload_len + 4);
461 silc_buffer_format(sign,
462 SILC_STR_UI_XNSTRING(pk, pk_len),
464 silc_buffer_push(sign, message_payload_len + 4);
470 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
472 SilcMessageSignedPayload
473 silc_message_signed_payload_parse(const unsigned char *data,
476 SilcMessageSignedPayload sig;
477 SilcBufferStruct buffer;
480 SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
482 SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
484 silc_buffer_set(&buffer, (unsigned char *)data, data_len);
485 sig = silc_calloc(1, sizeof(*sig));
489 /* Parse the payload */
490 ret = silc_buffer_unformat(&buffer,
491 SILC_STR_UI_SHORT(&sig->pk_len),
492 SILC_STR_UI_SHORT(&sig->pk_type),
494 if (ret == -1 || sig->pk_len > data_len - 4) {
495 silc_message_signed_payload_free(sig);
496 SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
501 silc_buffer_pull(&buffer, 4);
502 ret = silc_buffer_unformat(&buffer,
503 SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
505 SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
509 silc_message_signed_payload_free(sig);
510 SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
513 silc_buffer_push(&buffer, 4);
515 /* Signature must be provided */
516 if (sig->sign_len < 1) {
517 SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
519 silc_message_signed_payload_free(sig);
526 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
530 silc_message_signed_payload_encode(const unsigned char *message_payload,
531 SilcUInt32 message_payload_len,
532 SilcPublicKey public_key,
533 SilcPrivateKey private_key,
536 SilcBuffer buffer, sign;
538 unsigned char auth_data[2048];
540 unsigned char *pk = NULL;
541 SilcUInt32 pk_len = 0;
544 if (!message_payload || !message_payload_len || !private_key || !hash)
548 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
550 /* Now we support only SILC style public key */
551 pk_type = SILC_SKE_PK_TYPE_SILC;
553 /* Encode the data to be signed */
554 sign = silc_message_signed_encode_data(message_payload,
556 pk, pk_len, pk_type);
562 /* Sign the buffer */
564 /* Allocate PKCS object */
565 if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
566 SILC_LOG_ERROR(("Could not allocated PKCS"));
567 silc_buffer_clear(sign);
568 silc_buffer_free(sign);
572 silc_pkcs_private_key_set(pkcs, private_key);
574 /* Compute the hash and the signature. */
575 if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
576 !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
578 SILC_LOG_ERROR(("Could not compute signature"));
579 silc_buffer_clear(sign);
580 silc_buffer_free(sign);
581 silc_pkcs_free(pkcs);
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 silc_pkcs_free(pkcs);
593 memset(auth_data, 0, sizeof(auth_data));
598 silc_buffer_format(buffer,
599 SILC_STR_UI_SHORT(pk_len),
600 SILC_STR_UI_SHORT(pk_type),
604 silc_buffer_pull(buffer, 4);
605 silc_buffer_format(buffer,
606 SILC_STR_UI_XNSTRING(pk, pk_len),
608 silc_buffer_push(buffer, 4);
611 silc_buffer_pull(buffer, 4 + pk_len);
612 silc_buffer_format(buffer,
613 SILC_STR_UI_SHORT(auth_len),
614 SILC_STR_UI_XNSTRING(auth_data, auth_len),
616 silc_buffer_push(buffer, 4 + pk_len);
618 SILC_LOG_HEXDUMP(("sig payload"), buffer->data, buffer->len);
620 memset(auth_data, 0, sizeof(auth_data));
621 silc_pkcs_free(pkcs);
622 silc_buffer_clear(sign);
623 silc_buffer_free(sign);
629 /* Free the payload */
631 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
633 memset(sig->sign_data, 0, sig->sign_len);
634 silc_free(sig->sign_data);
635 silc_free(sig->pk_data);
639 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
641 int silc_message_signed_verify(SilcMessageSignedPayload sig,
642 SilcMessagePayload message,
643 SilcPublicKey remote_public_key,
646 int ret = SILC_AUTH_FAILED;
651 if (!sig || !remote_public_key || !hash)
654 /* Generate the signature verification data, the Message Payload */
655 tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
656 silc_buffer_format(tmp,
657 SILC_STR_UI_SHORT(message->flags),
658 SILC_STR_UI_SHORT(message->data_len),
659 SILC_STR_UI_XNSTRING(message->data, message->data_len),
660 SILC_STR_UI_SHORT(message->pad_len),
661 SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
663 sign = silc_message_signed_encode_data(tmp->data, tmp->len,
664 sig->pk_data, sig->pk_len,
666 silc_buffer_clear(tmp);
667 silc_buffer_free(tmp);
672 /* Allocate PKCS object */
673 if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
674 silc_buffer_clear(sign);
675 silc_buffer_free(sign);
678 silc_pkcs_public_key_set(pkcs, remote_public_key);
680 /* Verify the authentication data */
681 if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
683 sign->data, sign->len)) {
685 silc_buffer_clear(sign);
686 silc_buffer_free(sign);
687 silc_pkcs_free(pkcs);
688 SILC_LOG_DEBUG(("Signature verification failed"));
694 silc_buffer_clear(sign);
695 silc_buffer_free(sign);
696 silc_pkcs_free(pkcs);
698 SILC_LOG_DEBUG(("Signature verification successful"));
703 /* Return the public key from the payload */
706 silc_message_signed_get_public_key(SilcMessageSignedPayload sig)
710 if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,